feat: 添加工作空间面板 - 右侧终端/文件浏览器
- 新增主进程 workspace.ts:spawn 进程管理,流式输出,安全检查 - IPC 双向通信:workspace:exec(on/send 模式,无超时限制) - preload 暴露 workspace API - 渲染进程 workspace-panel.ts:多终端 Tab、ANSI 颜色渲染、文件浏览器 - 设置面板添加工作空间目录配置 - 启动时自动创建 workspace 目录 - 窗口关闭时自动清理所有子进程 - 帮助文档更新
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
handleRunCommand
|
||||
} from './tool-handlers.js';
|
||||
import { getAllowedDirs, getBlockedDirs, setAllowedDirs } from './tool-security.js';
|
||||
import { startProcess, killProcess, getWorkspaceDir, setWorkspaceDir, listWorkspaceDir } from './workspace.js';
|
||||
|
||||
export function setupIPC(): void {
|
||||
ipcMain.handle('dialog:openFile', async (_, options?: { filters?: Array<{ name: string; extensions: string[] }> }) => {
|
||||
@@ -108,4 +109,61 @@ export function setupIPC(): void {
|
||||
ipcMain.handle('tool:setAllowedDirs', (_, dirs: string[]) => {
|
||||
setAllowedDirs(dirs);
|
||||
});
|
||||
|
||||
// ── Workspace IPC ──
|
||||
|
||||
// 获取工作空间目录
|
||||
ipcMain.handle('workspace:getDir', () => {
|
||||
return { dir: getWorkspaceDir(), defaultDir: getWorkspaceDir() };
|
||||
});
|
||||
|
||||
// 设置工作空间目录
|
||||
ipcMain.handle('workspace:setDir', (_, dir: string) => {
|
||||
try {
|
||||
setWorkspaceDir(dir);
|
||||
return { success: true, dir: getWorkspaceDir() };
|
||||
} catch (err) {
|
||||
return { success: false, error: (err as Error).message };
|
||||
}
|
||||
});
|
||||
|
||||
// 列出工作空间目录
|
||||
ipcMain.handle('workspace:listDir', (_, dirPath?: string) => {
|
||||
return listWorkspaceDir(dirPath);
|
||||
});
|
||||
|
||||
// 读取工作空间文件(复用 tool-handlers)
|
||||
ipcMain.handle('workspace:readFile', async (_, filePath: string) => {
|
||||
return handleReadFile({ path: filePath });
|
||||
});
|
||||
|
||||
// 启动命令(流式输出,通过 workspace:output 事件推送)
|
||||
ipcMain.on('workspace:exec', (event, { id, command, cwd }: { id: string; command: string; cwd?: string }) => {
|
||||
console.log('[IPC] workspace:exec', id, command.slice(0, 200));
|
||||
|
||||
const result = startProcess(
|
||||
id,
|
||||
command,
|
||||
cwd,
|
||||
(type, data) => {
|
||||
// 流式推送输出到渲染进程
|
||||
event.sender.send('workspace:output', { id, type, data });
|
||||
},
|
||||
(code) => {
|
||||
// 通知进程结束
|
||||
event.sender.send('workspace:exit', { id, code });
|
||||
}
|
||||
);
|
||||
|
||||
if (!result.success) {
|
||||
event.sender.send('workspace:output', { id, type: 'stderr', data: result.error + '\n' });
|
||||
event.sender.send('workspace:exit', { id, code: 1 });
|
||||
}
|
||||
});
|
||||
|
||||
// 停止命令
|
||||
ipcMain.on('workspace:kill', (_, id: string) => {
|
||||
console.log('[IPC] workspace:kill', id);
|
||||
killProcess(id);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user