refactor: 全面清理死代码 — 删除 348 行无用代码
删除文件: - training-export.ts: 训练数据导出(零引用,UI 已移除) 删除函数: - workspace.ts: isProcessAlive, getActiveProcessCount, execWorkspaceCommand, terminateWorkspaceCommand - sqlite.ts: deleteMessagesBySession, getSkill, closeDatabase - tool-registry.ts: isToolEnabled - cron-manager.ts: clearAllTimers - workspace-panel.ts: setOnToolTerminated, setWorkspaceDirPath 删除 UI: - index.html: 训练数据导出按钮及说明 - settings-modal.ts: 训练数据导出事件绑定
This commit is contained in:
@@ -199,161 +199,3 @@ export function listWorkspaceDir(dirPath?: string): { success: boolean; entries?
|
||||
return { success: false, error: (err as Error).message };
|
||||
}
|
||||
}
|
||||
|
||||
/** 检查进程是否还活着 */
|
||||
export function isProcessAlive(id: string): boolean {
|
||||
return activeProcesses.has(id);
|
||||
}
|
||||
|
||||
/** 获取活跃进程数量 */
|
||||
export function getActiveProcessCount(): number {
|
||||
return activeProcesses.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行命令并收集完整输出(无超时限制)
|
||||
* 用于 AI Tool Calling 集成,通过 IPC invoke/handle 调用
|
||||
* 返回完整的 stdout + stderr + exitCode
|
||||
*/
|
||||
export function execWorkspaceCommand(
|
||||
command: string,
|
||||
cwd?: string,
|
||||
onOutput?: (type: 'stdout' | 'stderr', data: string) => void
|
||||
): Promise<{ success: boolean; stdout: string; stderr: string; exitCode: number | null; duration: number; userTerminated: boolean; truncated: boolean }> {
|
||||
return new Promise((resolve) => {
|
||||
const workDir = cwd ? path.resolve(cwd) : _workspaceDir;
|
||||
const cmdId = `_tool_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
||||
|
||||
// 安全检查
|
||||
const cmdCheck = checkCommandAllowed(command);
|
||||
if (!cmdCheck.ok) {
|
||||
sendLog('warn', `🔧 工具命令被拦截`, `${command.slice(0, 100)} | ${cmdCheck.reason}`);
|
||||
resolve({ success: false, stdout: '', stderr: cmdCheck.reason!, exitCode: 1, duration: 0, userTerminated: false, truncated: false });
|
||||
return;
|
||||
}
|
||||
|
||||
const dirCheck = checkPathAllowed(workDir, 'read');
|
||||
if (!dirCheck.ok) {
|
||||
sendLog('warn', `🔧 工具目录被拦截`, `${workDir} | ${dirCheck.reason}`);
|
||||
resolve({ success: false, stdout: '', stderr: dirCheck.reason!, exitCode: 1, duration: 0, userTerminated: false, truncated: false });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(workDir)) {
|
||||
resolve({ success: false, stdout: '', stderr: `工作目录不存在: ${workDir}`, exitCode: 1, duration: 0, userTerminated: false, truncated: false });
|
||||
return;
|
||||
}
|
||||
|
||||
sendLog('info', `🔧 execWorkspaceCommand`, `${command.slice(0, 200)} | cwd: ${workDir}`);
|
||||
|
||||
const startTime = Date.now();
|
||||
const MAX_OUTPUT = 5 * 1024 * 1024; // 5MB 输出上限
|
||||
let stdoutBuf = '';
|
||||
let stderrBuf = '';
|
||||
let truncated = false;
|
||||
|
||||
try {
|
||||
const isWin = process.platform === 'win32';
|
||||
const shell = isWin ? 'cmd.exe' : 'bash';
|
||||
const actualCmd = isWin ? `chcp 65001 >nul && ${command}` : command;
|
||||
const shellArgs = isWin ? ['/c', actualCmd] : ['-c', actualCmd];
|
||||
const proc = spawn(shell, shellArgs, {
|
||||
cwd: workDir,
|
||||
env: {
|
||||
...process.env,
|
||||
...(isWin ? {} : { TERM: 'xterm-256color' }),
|
||||
LANG: 'en_US.UTF-8',
|
||||
LC_ALL: 'en_US.UTF-8',
|
||||
PYTHONIOENCODING: 'utf-8'
|
||||
},
|
||||
stdio: ['pipe', 'pipe', 'pipe']
|
||||
});
|
||||
|
||||
activeProcesses.set(cmdId, proc);
|
||||
|
||||
proc.stdout.on('data', (data: Buffer) => {
|
||||
const str = data.toString('utf-8');
|
||||
if (stdoutBuf.length < MAX_OUTPUT) {
|
||||
stdoutBuf += str;
|
||||
if (stdoutBuf.length > MAX_OUTPUT) {
|
||||
stdoutBuf = stdoutBuf.slice(0, MAX_OUTPUT);
|
||||
truncated = true;
|
||||
}
|
||||
} else {
|
||||
truncated = true;
|
||||
}
|
||||
// 实时推送到渲染进程
|
||||
onOutput?.('stdout', str);
|
||||
});
|
||||
|
||||
proc.stderr.on('data', (data: Buffer) => {
|
||||
const str = data.toString('utf-8');
|
||||
if (stderrBuf.length < MAX_OUTPUT) {
|
||||
stderrBuf += str;
|
||||
if (stderrBuf.length > MAX_OUTPUT) {
|
||||
stderrBuf = stderrBuf.slice(0, MAX_OUTPUT);
|
||||
truncated = true;
|
||||
}
|
||||
} else {
|
||||
truncated = true;
|
||||
}
|
||||
// 实时推送到渲染进程
|
||||
onOutput?.('stderr', str);
|
||||
});
|
||||
|
||||
proc.on('close', (code) => {
|
||||
activeProcesses.delete(cmdId);
|
||||
const duration = Date.now() - startTime;
|
||||
sendLog(
|
||||
code === 0 ? 'success' : 'warn',
|
||||
`🔧 execWorkspaceCommand 完成`,
|
||||
`code: ${code} | ${duration}ms | stdout: ${stdoutBuf.length}B | stderr: ${stderrBuf.length}B`
|
||||
);
|
||||
resolve({
|
||||
success: code === 0,
|
||||
stdout: stdoutBuf,
|
||||
stderr: stderrBuf,
|
||||
exitCode: code,
|
||||
duration,
|
||||
userTerminated: false,
|
||||
truncated
|
||||
});
|
||||
});
|
||||
|
||||
proc.on('error', (err) => {
|
||||
activeProcesses.delete(cmdId);
|
||||
const duration = Date.now() - startTime;
|
||||
sendLog('error', `🔧 execWorkspaceCommand 失败`, `${cmdId} | ${err.message}`);
|
||||
resolve({
|
||||
success: false,
|
||||
stdout: stdoutBuf,
|
||||
stderr: stderrBuf + (stderrBuf ? '\n' : '') + `进程启动失败: ${err.message}`,
|
||||
exitCode: 1,
|
||||
duration,
|
||||
userTerminated: false,
|
||||
truncated
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
const duration = Date.now() - startTime;
|
||||
sendLog('error', `🔧 execWorkspaceCommand 异常`, (err as Error).message);
|
||||
resolve({
|
||||
success: false,
|
||||
stdout: stdoutBuf,
|
||||
stderr: (err as Error).message,
|
||||
exitCode: 1,
|
||||
duration,
|
||||
userTerminated: false,
|
||||
truncated: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 终止 execWorkspaceCommand 启动的进程
|
||||
* @returns 是否成功终止
|
||||
*/
|
||||
export function terminateWorkspaceCommand(commandId: string): boolean {
|
||||
return killProcess(commandId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user