chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,559 @@
/**
* 沙箱 IPC 通道
*
* 提供沙箱工作区管理的 IPC 接口
*
* @version 1.0.0
* @updated 2026-03-22
*/
import { ipcMain } from "electron";
import log from "electron-log";
import type {
Workspace,
CreateWorkspaceOptions,
ExecuteOptions,
ExecuteResult,
FileInfo,
PermissionType,
PermissionResult,
PermissionRequest,
CleanupResult,
SandboxStatus,
SandboxPolicy,
SandboxCapabilities,
} from "@shared/types/sandbox";
import {
SandboxError,
SandboxErrorCode,
isSandboxError,
} from "@shared/errors/sandbox";
import { t } from "../services/i18n";
// 服务单例(在服务实现完成后注入)
let sandboxService: {
createWorkspace(
sessionId: string,
options?: CreateWorkspaceOptions,
): Promise<Workspace>;
destroyWorkspace(sessionId: string): Promise<void>;
listWorkspaces(): Workspace[];
getWorkspace(sessionId: string): Workspace | undefined;
execute(
sessionId: string,
command: string,
args: string[],
options?: ExecuteOptions,
): Promise<ExecuteResult>;
readFile(sessionId: string, path: string): Promise<string>;
writeFile(sessionId: string, path: string, content: string): Promise<void>;
isAvailable(): Promise<boolean>;
getStatus(): Promise<SandboxStatus>;
cleanup(): Promise<CleanupResult>;
} | null = null;
let permissionService: {
checkPermission(
sessionId: string,
type: PermissionType,
target: string,
): Promise<PermissionResult>;
requestPermission(
sessionId: string,
type: PermissionType,
target: string,
reason?: string,
): Promise<unknown>;
getPendingRequests(sessionId?: string): PermissionRequest[];
approve(
requestId: string,
approvedBy?: "user" | "system",
reason?: string,
): Promise<void>;
deny(requestId: string, reason?: string): Promise<void>;
} | null = null;
let sandboxControlService: {
getPolicy(): Promise<SandboxPolicy>;
setPolicy(patch: Partial<SandboxPolicy>): Promise<SandboxPolicy>;
getCapabilities(): Promise<SandboxCapabilities>;
setup(params?: {
windows?: { sandbox?: { mode?: "read-only" | "workspace-write" } };
}): Promise<{ success: boolean; message?: string }>;
} | null = null;
/**
* 设置沙箱服务实例
*/
export function setSandboxService(service: typeof sandboxService): void {
sandboxService = service;
log.info("[IPC] Sandbox service injected");
}
/**
* 设置权限服务实例
*/
export function setPermissionService(service: typeof permissionService): void {
permissionService = service;
log.info("[IPC] Permission service injected");
}
/**
* 设置沙箱控制服务(策略/能力/setup
*/
export function setSandboxControlService(
service: typeof sandboxControlService,
): void {
sandboxControlService = service;
log.info("[IPC] Sandbox control service injected");
}
/**
* 获取沙箱服务(带检查)
*/
function getSandboxService(): NonNullable<typeof sandboxService> {
if (!sandboxService) {
throw new SandboxError(
"Sandbox service not initialized",
SandboxErrorCode.SANDBOX_UNAVAILABLE,
);
}
return sandboxService;
}
/**
* 获取权限服务(带检查)
*/
function getPermissionService(): NonNullable<typeof permissionService> {
if (!permissionService) {
throw new SandboxError(
"Permission service not initialized",
SandboxErrorCode.INTERNAL_ERROR,
);
}
return permissionService;
}
function getSandboxControlService(): NonNullable<typeof sandboxControlService> {
if (!sandboxControlService) {
throw new SandboxError(
"Sandbox control service not initialized",
SandboxErrorCode.SANDBOX_UNAVAILABLE,
);
}
return sandboxControlService;
}
/**
* 错误处理包装器
*/
function handleError(
error: unknown,
operation: string,
): { success: false; error: string; code?: string } {
log.error(`[IPC] sandbox:${operation} failed:`, error);
if (isSandboxError(error)) {
return {
success: false,
error: error.getUserMessage(),
code: error.code,
};
}
return {
success: false,
error: error instanceof Error ? error.message : String(error),
};
}
/**
* 注册沙箱 IPC 通道
*/
export function registerSandboxHandlers(): void {
// ============================================================================
// 工作区管理
// ============================================================================
/**
* 创建工作区
* @channel sandbox:create
* @param sessionId 会话 ID
* @param options 创建选项
*/
ipcMain.handle(
"sandbox:create",
async (_, sessionId: string, options?: CreateWorkspaceOptions) => {
log.info("[IPC] sandbox:create:", { sessionId, options });
try {
const service = getSandboxService();
const workspace = await service.createWorkspace(sessionId, options);
return { success: true, data: workspace };
} catch (error) {
return handleError(error, "create");
}
},
);
/**
* 销毁工作区
* @channel sandbox:destroy
* @param sessionId 会话 ID
*/
ipcMain.handle("sandbox:destroy", async (_, sessionId: string) => {
log.info("[IPC] sandbox:destroy:", { sessionId });
try {
const service = getSandboxService();
await service.destroyWorkspace(sessionId);
return { success: true };
} catch (error) {
return handleError(error, "destroy");
}
});
/**
* 列出所有工作区
* @channel sandbox:list
*/
ipcMain.handle("sandbox:list", async () => {
log.info("[IPC] sandbox:list");
try {
const service = getSandboxService();
const workspaces = service.listWorkspaces();
return { success: true, data: workspaces };
} catch (error) {
return handleError(error, "list");
}
});
/**
* 获取工作区信息
* @channel sandbox:info
* @param sessionId 会话 ID
*/
ipcMain.handle("sandbox:info", async (_, sessionId: string) => {
log.info("[IPC] sandbox:info:", { sessionId });
try {
const service = getSandboxService();
const workspace = service.getWorkspace(sessionId);
if (!workspace) {
return {
success: false,
error: t("Claw.Sandbox.workspaceNotFound", sessionId),
code: SandboxErrorCode.WORKSPACE_NOT_FOUND,
};
}
return { success: true, data: workspace };
} catch (error) {
return handleError(error, "info");
}
});
// ============================================================================
// 命令执行
// ============================================================================
/**
* 执行命令
* @channel sandbox:execute
* @param sessionId 会话 ID
* @param command 命令
* @param args 参数
* @param options 执行选项
*/
ipcMain.handle(
"sandbox:execute",
async (
_,
sessionId: string,
command: string,
args: string[],
options?: ExecuteOptions,
) => {
log.info("[IPC] sandbox:execute:", { sessionId, command, args, options });
try {
const service = getSandboxService();
const result = await service.execute(sessionId, command, args, options);
return { success: true, data: result };
} catch (error) {
return handleError(error, "execute");
}
},
);
// ============================================================================
// 文件操作
// ============================================================================
/**
* 读取文件
* @channel sandbox:readFile
* @param sessionId 会话 ID
* @param path 文件路径
*/
ipcMain.handle(
"sandbox:readFile",
async (_, sessionId: string, path: string) => {
log.info("[IPC] sandbox:readFile:", { sessionId, path });
try {
const service = getSandboxService();
const content = await service.readFile(sessionId, path);
return { success: true, data: content };
} catch (error) {
return handleError(error, "readFile");
}
},
);
/**
* 写入文件
* @channel sandbox:writeFile
* @param sessionId 会话 ID
* @param path 文件路径
* @param content 文件内容
*/
ipcMain.handle(
"sandbox:writeFile",
async (_, sessionId: string, path: string, content: string) => {
log.info("[IPC] sandbox:writeFile:", { sessionId, path });
try {
const service = getSandboxService();
await service.writeFile(sessionId, path, content);
return { success: true };
} catch (error) {
return handleError(error, "writeFile");
}
},
);
// ============================================================================
// 权限管理
// ============================================================================
/**
* 检查权限
* @channel sandbox:checkPermission
* @param sessionId 会话 ID
* @param type 权限类型
* @param target 目标资源
*/
ipcMain.handle(
"sandbox:checkPermission",
async (_, sessionId: string, type: PermissionType, target: string) => {
log.info("[IPC] sandbox:checkPermission:", { sessionId, type, target });
try {
const service = getPermissionService();
const result = await service.checkPermission(sessionId, type, target);
return { success: true, data: result };
} catch (error) {
return handleError(error, "checkPermission");
}
},
);
/**
* 请求权限
* @channel sandbox:requestPermission
* @param sessionId 会话 ID
* @param type 权限类型
* @param target 目标资源
* @param reason 请求原因
*/
ipcMain.handle(
"sandbox:requestPermission",
async (
_,
sessionId: string,
type: PermissionType,
target: string,
reason?: string,
) => {
log.info("[IPC] sandbox:requestPermission:", {
sessionId,
type,
target,
reason,
});
try {
const service = getPermissionService();
const permission = await service.requestPermission(
sessionId,
type,
target,
reason,
);
return { success: true, data: permission };
} catch (error) {
return handleError(error, "requestPermission");
}
},
);
/**
* 获取待审批权限列表
* @channel sandbox:getPendingPermissions
* @param sessionId 可选的会话 ID 过滤
*/
ipcMain.handle(
"sandbox:getPendingPermissions",
async (_, sessionId?: string) => {
log.info("[IPC] sandbox:getPendingPermissions:", { sessionId });
try {
const service = getPermissionService();
const requests = service.getPendingRequests(sessionId);
return { success: true, data: requests };
} catch (error) {
return handleError(error, "getPendingPermissions");
}
},
);
/**
* 批准权限请求
* @channel sandbox:approvePermission
* @param requestId 请求 ID
* @param reason 原因
*/
ipcMain.handle(
"sandbox:approvePermission",
async (_, requestId: string, reason?: string) => {
log.info("[IPC] sandbox:approvePermission:", { requestId, reason });
try {
const service = getPermissionService();
await service.approve(requestId, "user", reason);
return { success: true };
} catch (error) {
return handleError(error, "approvePermission");
}
},
);
/**
* 拒绝权限请求
* @channel sandbox:denyPermission
* @param requestId 请求 ID
* @param reason 原因
*/
ipcMain.handle(
"sandbox:denyPermission",
async (_, requestId: string, reason?: string) => {
log.info("[IPC] sandbox:denyPermission:", { requestId, reason });
try {
const service = getPermissionService();
await service.deny(requestId, reason);
return { success: true };
} catch (error) {
return handleError(error, "denyPermission");
}
},
);
// ============================================================================
// 清理与状态
// ============================================================================
/**
* 清理资源
* @channel sandbox:cleanup
*/
ipcMain.handle("sandbox:cleanup", async () => {
log.info("[IPC] sandbox:cleanup");
try {
const service = getSandboxService();
const result = await service.cleanup();
return { success: true, data: result };
} catch (error) {
return handleError(error, "cleanup");
}
});
/**
* 获取沙箱状态
* @channel sandbox:status
*/
ipcMain.handle("sandbox:status", async () => {
log.info("[IPC] sandbox:status");
try {
const service = getSandboxService();
const status = await service.getStatus();
return { success: true, data: status };
} catch (error) {
return handleError(error, "status");
}
});
/**
* 获取沙箱策略
* @channel sandbox:policy:get
*/
ipcMain.handle("sandbox:policy:get", async () => {
log.info("[IPC] sandbox:policy:get");
try {
const control = getSandboxControlService();
const policy = await control.getPolicy();
return { success: true, data: policy };
} catch (error) {
return handleError(error, "policy:get");
}
});
/**
* 更新沙箱策略
* @channel sandbox:policy:set
*/
ipcMain.handle(
"sandbox:policy:set",
async (_, patch: Partial<SandboxPolicy>) => {
log.info("[IPC] sandbox:policy:set:", { patch });
try {
const control = getSandboxControlService();
const policy = await control.setPolicy(patch);
return { success: true, data: policy };
} catch (error) {
return handleError(error, "policy:set");
}
},
);
/**
* 获取后端能力
* @channel sandbox:capabilities
*/
ipcMain.handle("sandbox:capabilities", async () => {
log.info("[IPC] sandbox:capabilities");
try {
const control = getSandboxControlService();
const capabilities = await control.getCapabilities();
return { success: true, data: capabilities };
} catch (error) {
return handleError(error, "capabilities");
}
});
/**
* 执行后端 setup当前主要用于 Windows Sandbox
* @channel sandbox:setup
*/
ipcMain.handle(
"sandbox:setup",
async (
_,
params?: {
windows?: { sandbox?: { mode?: "read-only" | "workspace-write" } };
},
) => {
log.info("[IPC] sandbox:setup:", { params });
try {
const control = getSandboxControlService();
const result = await control.setup(params);
return { success: true, data: result };
} catch (error) {
return handleError(error, "setup");
}
},
);
log.info("[IPC] Sandbox handlers registered");
}