14 KiB
14 KiB
沙箱 API 接口文档
版本: 1.0.0
更新: 2026-03-22
状态: 待实现
1. 概览
本文档定义 Qiming Agent 沙箱的 TypeScript/JavaScript API 接口。
2. 类型定义
2.1 核心类型
// src/shared/types/sandbox.ts
export type Platform = 'darwin' | 'win32' | 'linux';
export type SandboxType = 'docker' | 'wsl' | 'firejail' | 'none';
export type PermissionLevel = 0 | 1 | 2 | 3;
export interface SandboxConfig {
type: SandboxType;
platform: Platform;
enabled: boolean;
workspaceRoot: string;
memoryLimit?: string; // 如 "2g"
cpuLimit?: number; // 如 2
diskQuota?: string; // 如 "10g"
networkEnabled?: boolean;
mode?: SandboxMode; // "strict" | "compat" | "permissive"
}
export interface Workspace {
id: string;
rootPath: string;
projectsPath: string;
nodeModulesPath: string;
pythonEnvPath: string;
binPath: string;
cachePath: string;
sandboxConfig: SandboxConfig;
createdAt: Date;
lastAccessedAt: Date;
retentionPolicy: RetentionPolicy;
}
export interface ExecuteOptions {
cwd?: string;
env?: Record<string, string>;
timeout?: number;
maxMemory?: string;
stdio?: 'pipe' | 'inherit';
permissionLevel?: PermissionLevel;
}
export interface ExecuteResult {
stdout: string;
stderr: string;
exitCode: number;
timedOut: boolean;
duration: number;
}
export interface RetentionPolicy {
mode: 'always' | 'timeout' | 'manual';
maxAge?: number;
maxWorkspaces?: number;
maxSize?: string;
preserveOnError?: boolean;
}
export interface Permission {
type: PermissionType;
target: string;
sessionId: string;
approvedBy: 'system' | 'user' | 'policy' | 'denied';
timestamp: Date;
reason?: string;
}
export type PermissionType =
| 'file:read'
| 'file:write'
| 'file:delete'
| 'command:execute'
| 'network:access'
| 'network:download'
| 'package:install:npm'
| 'package:install:python'
| 'package:install:system';
3. SandboxManager 接口
3.1 类签名
// src/main/services/sandbox/SandboxManager.ts
export abstract class SandboxManager {
protected config: SandboxConfig;
protected workspaces: Map<string, Workspace>;
constructor(config: SandboxConfig);
// 初始化
abstract init(): Promise<void>;
// 检查沙箱是否可用
abstract isAvailable(): Promise<boolean>;
// 创建工作区
abstract createWorkspace(sessionId: string): Promise<Workspace>;
// 销毁工作区
abstract destroyWorkspace(sessionId: string): Promise<void>;
// 执行命令
abstract execute(
sessionId: string,
command: string,
args: string[],
options?: ExecuteOptions
): Promise<ExecuteResult>;
// 文件操作
abstract readFile(sessionId: string, path: string): Promise<string>;
abstract writeFile(sessionId: string, path: string, content: string): Promise<void>;
abstract readDir(sessionId: string, path: string): Promise<FileInfo[]>;
// 工作区信息
abstract getWorkspace(sessionId: string): Workspace | undefined;
abstract listWorkspaces(): Workspace[];
// 清理
abstract cleanup(): Promise<void>;
}
3.2 Docker 实现
// src/main/services/sandbox/DockerSandbox.ts
export class DockerSandbox extends SandboxManager {
private containerIds: Map<string, string>;
constructor(config: SandboxConfig & {
dockerImage: string;
dockerHost?: string;
});
async init(): Promise<void>;
async isAvailable(): Promise<boolean>;
async createWorkspace(sessionId: string): Promise<Workspace>;
async destroyWorkspace(sessionId: string): Promise<void>;
async execute(
sessionId: string,
command: string,
args: string[],
options?: ExecuteOptions
): Promise<ExecuteResult>;
async readFile(sessionId: string, path: string): Promise<string>;
async writeFile(sessionId: string, path: string, content: string): Promise<void>;
// Docker 特有
async listContainers(): Promise<ContainerInfo[]>;
async getContainerLogs(sessionId: string): Promise<string>;
}
3.3 WSL 实现(Windows)
// src/main/services/sandbox/WslSandbox.ts
export class WslSandbox extends SandboxManager {
private distribution: string;
private instanceId: string;
constructor(config: SandboxConfig & {
distribution: string;
});
async init(): Promise<void>;
async isAvailable(): Promise<boolean>;
async createWorkspace(sessionId: string): Promise<Workspace>;
async destroyWorkspace(sessionId: string): Promise<void>;
async execute(
sessionId: string,
command: string,
args: string[],
options?: ExecuteOptions
): Promise<ExecuteResult>;
}
3.4 Firejail 实现(Linux)
// src/main/services/sandbox/FirejailSandbox.ts
export class FirejailSandbox extends SandboxManager {
private profiles: Map<string, string>;
constructor(config: SandboxConfig & {
profileDir?: string;
});
async init(): Promise<void>;
async isAvailable(): Promise<boolean>;
async createWorkspace(sessionId: string): Promise<Workspace>;
async destroyWorkspace(sessionId: string): Promise<void>;
async execute(
sessionId: string,
command: string,
args: string[],
options?: ExecuteOptions
): Promise<ExecuteResult>;
}
4. PermissionManager 接口
4.1 类签名
// src/main/services/sandbox/PermissionManager.ts
export class PermissionManager {
private policy: PermissionPolicy;
private pendingRequests: Map<string, PermissionRequest>;
private approvedCache: Map<string, Permission>;
constructor(policy: PermissionPolicy);
// 检查权限
async checkPermission(
sessionId: string,
permission: PermissionType,
target: string
): Promise<PermissionResult>;
// 请求权限
async requestPermission(
sessionId: string,
permission: PermissionType,
target: string,
reason?: string
): Promise<Permission>;
// 批准权限
async approve(
requestId: string,
approvedBy: 'user' | 'system',
reason?: string
): Promise<void>;
// 拒绝权限
async deny(requestId: string, reason?: string): Promise<void>;
// 批量批准
async approveBatch(requestIds: string[]): Promise<void>;
// 获取待审批列表
getPendingRequests(sessionId?: string): PermissionRequest[];
// 清除缓存
clearCache(): void;
}
export interface PermissionPolicy {
autoApprove: PermissionType[]; // 自动批准的类型
requireConfirm: PermissionType[]; // 需要确认的类型
denyList: PermissionType[]; // 禁止的类型
workspaceOnly: boolean; // 是否只允许工作区操作
safeCommands: string[]; // 安全命令白名单
}
export interface PermissionResult {
allowed: boolean;
reason: string;
requestId?: string;
}
export interface PermissionRequest {
id: string;
sessionId: string;
type: PermissionType;
target: string;
reason?: string;
requestedAt: Date;
status: 'pending' | 'approved' | 'denied';
}
5. WorkspaceManager 接口
5.1 类签名
// src/main/services/sandbox/WorkspaceManager.ts
export class WorkspaceManager {
private sandboxManager: SandboxManager;
private permissionManager: PermissionManager;
private workspaceStore: WorkspaceStore;
constructor(
sandboxManager: SandboxManager,
permissionManager: PermissionManager
);
// 工作区生命周期
async create(sessionId: string, options?: CreateWorkspaceOptions): Promise<Workspace>;
async destroy(sessionId: string, force?: boolean): Promise<void>;
async get(sessionId: string): Promise<Workspace | undefined>;
async list(): Promise<Workspace[]>;
// 工作区操作(带权限检查)
async readFile(sessionId: string, path: string): Promise<string>;
async writeFile(sessionId: string, path: string, content: string): Promise<void>;
async execute(
sessionId: string,
command: string,
args: string[],
options?: ExecuteOptions
): Promise<ExecuteResult>;
// 清理
async cleanupExpired(): Promise<CleanupResult>;
async cleanupAll(): Promise<void>;
// 保留策略
async setRetentionPolicy(sessionId: string, policy: RetentionPolicy): Promise<void>;
async getRetentionPolicy(sessionId: string): Promise<RetentionPolicy>;
}
export interface CreateWorkspaceOptions {
retention?: Partial<RetentionPolicy>;
platform?: Platform;
sandboxType?: SandboxType;
}
export interface CleanupResult {
deletedCount: number;
freedSpace: number;
errors: string[];
}
6. IPC 接口
6.1 IPC 通道定义
// src/main/ipc/channels.ts
export const SANDBOX_CHANNELS = {
// 工作区管理
'sandbox:create': {
request: { sessionId: string },
response: Workspace
},
'sandbox:destroy': {
request: { sessionId: string, force?: boolean },
response: { success: boolean }
},
'sandbox:list': {
request: void,
response: Workspace[]
},
'sandbox:info': {
request: { sessionId: string },
response: Workspace | null
},
// 文件操作
'sandbox:readFile': {
request: { sessionId: string, path: string },
response: { content: string }
},
'sandbox:writeFile': {
request: { sessionId: string, path: string, content: string },
response: { success: boolean }
},
// 执行
'sandbox:execute': {
request: {
sessionId: string,
command: string,
args: string[],
options?: ExecuteOptions
},
response: ExecuteResult
},
// 权限
'sandbox:checkPermission': {
request: { sessionId: string, type: PermissionType, target: string },
response: PermissionResult
},
'sandbox:requestPermission': {
request: { sessionId: string, type: PermissionType, target: string, reason?: string },
response: Permission
},
'sandbox:getPendingPermissions': {
request: { sessionId?: string },
response: PermissionRequest[]
},
'sandbox:approvePermission': {
request: { requestId: string },
response: { success: boolean }
},
'sandbox:denyPermission': {
request: { requestId: string },
response: { success: boolean }
},
// 清理
'sandbox:cleanup': {
request: void,
response: CleanupResult
},
// 状态
'sandbox:status': {
request: void,
response: SandboxStatus
},
// 策略
'sandbox:policy:get': {
request: void,
response: SandboxPolicy
},
'sandbox:policy:set': {
request: Partial<SandboxPolicy>,
response: SandboxPolicy
},
'sandbox:capabilities': {
request: void,
response: SandboxCapabilities
},
// 后端初始化(Windows Codex setup)
'sandbox:setup': {
request: {
windows?: { codex?: { mode?: 'unelevated' | 'elevated' } }
},
response: { success: boolean; message?: string }
}
} as const;
export interface SandboxStatus {
available: boolean;
type: SandboxType;
backend?: SandboxBackend;
platform: Platform;
activeWorkspaces: number;
degraded?: boolean;
reason?: string;
capabilities?: SandboxCapabilities;
totalMemory?: string;
diskUsage?: string;
}
export interface SandboxPolicy {
enabled: boolean;
mode: SandboxMode; // "strict" | "compat" | "permissive"
backend: SandboxBackend; // "auto" | "docker" | "macos-seatbelt" | "linux-bwrap" | "windows-sandbox"
autoFallback: SandboxAutoFallback; // "startup-only" | "session" | "manual"
windowsMode: WindowsSandboxMode; // "read-only" | "workspace-write"
}
7. 事件
7.1 事件类型
// src/shared/events/sandbox.ts
export const SANDBOX_EVENTS = {
// 工作区事件
'workspace:created': { workspace: Workspace };
'workspace:destroyed': { workspaceId: string };
'workspace:accessed': { workspaceId: string; timestamp: Date };
// 权限事件
'permission:requested': { request: PermissionRequest };
'permission:approved': { permission: Permission };
'permission:denied': { requestId: string; reason?: string };
// 执行事件
'execute:start': { sessionId: string; command: string };
'execute:complete': { sessionId: string; result: ExecuteResult };
'execute:error': { sessionId: string; error: string };
// 清理事件
'cleanup:start': void;
'cleanup:complete': { result: CleanupResult };
// 沙箱事件
'sandbox:unavailable': { reason: string };
'sandbox:recovered': void;
} as const;
8. 错误类型
8.1 错误类
// src/shared/errors/sandbox.ts
export class SandboxError extends Error {
constructor(
message: string,
public code: SandboxErrorCode,
public sessionId?: string
);
}
export enum SandboxErrorCode {
SANDBOX_UNAVAILABLE = 'SANDBOX_UNAVAILABLE',
WORKSPACE_NOT_FOUND = 'WORKSPACE_NOT_FOUND',
WORKSPACE_EXISTS = 'WORKSPACE_EXISTS',
PERMISSION_DENIED = 'PERMISSION_DENIED',
EXECUTION_FAILED = 'EXECUTION_FAILED',
EXECUTION_TIMEOUT = 'EXECUTION_TIMEOUT',
FILE_NOT_FOUND = 'FILE_NOT_FOUND',
FILE_WRITE_FAILED = 'FILE_WRITE_FAILED',
CLEANUP_FAILED = 'CLEANUP_FAILED',
CONFIG_INVALID = 'CONFIG_INVALID'
}
9. 使用示例
9.1 创建工作区
import { WorkspaceManager } from './services/sandbox/WorkspaceManager';
const workspaceManager = new WorkspaceManager(
new DockerSandbox({ type: 'docker', platform: 'darwin', enabled: true }),
new PermissionManager({ /* policy */ })
);
// 创建工作区
const workspace = await workspaceManager.create('session-123', {
retention: { mode: 'timeout', maxAge: 7 * 24 * 60 * 60 * 1000 }
});
console.log(`Workspace created at: ${workspace.rootPath}`);
9.2 执行命令
// 检查权限
const result = await workspaceManager.execute(
'session-123',
'npm',
['install', 'lodash'],
{ cwd: workspace.projectsPath }
);
console.log(`Exit code: ${result.exitCode}`);
console.log(`Output: ${result.stdout}`);
9.3 权限请求
// 请求安装包权限
const permission = await workspaceManager.permissionManager.requestPermission(
'session-123',
'package:install:npm',
'lodash',
'Need lodash for utility functions'
);
// 等待用户批准
if (permission.approvedBy === 'user') {
// 执行安装
}
10. 变更记录
| 日期 | 版本 | 变更 |
|---|---|---|
| 2026-03-22 | 1.0.0 | 初始版本 |