v0.12.3: 全面审计修复 + 稳定性加固 + 文档更新
P0 安全/稳定性修复 (6项):
- sqlite persist 改用临时文件+rename,I/O错误日志
- IPC fs 处理器加入 checkPathAllowed 路径验证
- handleCompress 命令注入修复 + 跨平台 (powershell/tar/zip/unzip)
- browser 全页截图简化,使用 capturePage full rect
- workspace 竞态条件修复
- editFile 5MB 大小限制
P1 安全/稳定性修复 (7项):
- 大小写不敏感搜索: query 同步转换小写
- web_fetch 无 content-length 时流式读取+10MB限制防OOM
- Windows SIGTERM 改用 taskkill /PID /T /F 强制终止
- startsWith 路径检查 Windows 大小写不敏感
- 安全黑名单扩展: 33个目录路径 + 30条危险命令 (Linux+Windows)
- plan_track stepIndex 改用 typeof === 'number' 精确检查
- MCP 前缀改用双下划线分隔 mcp_{server}__{tool} 防歧义
P2 代码质量修复 (8项):
- 修复 EXECUTING→THINKING 死循环Bug (转换表缺失)
- COMPRESSING 硬上限绕过时同步 _loopState 全局状态
- Abort 路径补齐 onDone 回调, 防止UI状态残留
- 幻觉检测从4条扩展到16条规则, 覆盖全部工具类别
- 移除 getTokenEfficiency 死代码
- 跨平台路径清理 (replace(/[\/]+$/, ''))
- 动态 import 加 try/catch, 失败自动批准不阻断
- #modelSelect 加 null 守卫, 防止运行时崩溃
文档 & UI 更新:
- README.md: 版本号/特性表/架构图/安全机制/工具清单全面刷新
- 帮助面板: 新增 Plan Mode、抗幻觉&稳定性章节, Agent Loop补8状态机
- 工具面板: plan_track卡片 + plan-mode徽章样式, 标题更新为42+1
- 工作空间面板宽度: 480px → 400px
- 源码注释移除所有版本标签, 仅保留4处必要位置
- 版本号 0.12.2 → 0.12.3
This commit is contained in:
+15
-6
@@ -87,8 +87,14 @@ function persist(): void {
|
||||
try {
|
||||
const data = db.export();
|
||||
const buf = Buffer.from(data);
|
||||
fs.writeFileSync(dbPath, buf);
|
||||
} catch { /* 静默失败,不阻断主流程 */ }
|
||||
// 先写临时文件再 rename,避免写一半崩溃导致数据库损坏
|
||||
const tmpPath = dbPath + '.tmp';
|
||||
fs.writeFileSync(tmpPath, buf);
|
||||
fs.renameSync(tmpPath, dbPath);
|
||||
} catch (err) {
|
||||
// 记录到启动日志文件(console.error 会被 main.ts 的 uncaughtException 捕获)
|
||||
console.error(`[SQLite persist] 写入失败: ${(err as Error).message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化数据库(异步,需加载 WASM) */
|
||||
@@ -200,6 +206,7 @@ export async function initDatabase(): Promise<SQL.Database> {
|
||||
action_input TEXT,
|
||||
observation TEXT,
|
||||
loop_count INTEGER,
|
||||
error_pattern TEXT,
|
||||
created_at INTEGER NOT NULL,
|
||||
FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE
|
||||
);
|
||||
@@ -210,7 +217,8 @@ export async function initDatabase(): Promise<SQL.Database> {
|
||||
// 兼容迁移:为已有 messages 表补充 attachments 列(文件/视频等附件 JSON)
|
||||
try { db.run('ALTER TABLE messages ADD COLUMN attachments TEXT'); } catch { /* 列已存在,忽略 */ }
|
||||
|
||||
// 兼容迁移:为已有 messages 表补充 prompt_eval_count 列
|
||||
// 兼容迁移:v0.12.0 — 为已有 traces 表补充 error_pattern 列
|
||||
try { db.run('ALTER TABLE traces ADD COLUMN error_pattern TEXT'); } catch { /* 列已存在,忽略 */ }
|
||||
|
||||
|
||||
// 尝试创建 FTS5 全文搜索(可选,sql.js 默认 WASM 可能不包含 FTS5)
|
||||
@@ -305,6 +313,7 @@ export interface TraceRow {
|
||||
action_input: string | null;
|
||||
observation: string | null;
|
||||
loop_count: number | null;
|
||||
error_pattern: string | null;
|
||||
created_at: number;
|
||||
}
|
||||
|
||||
@@ -481,9 +490,9 @@ export function getToolCallsBySession(sessionId: string): ToolCallRow[] {
|
||||
// ─── Traces CRUD ───
|
||||
|
||||
export function saveTrace(trace: TraceRow): string {
|
||||
runExec(getDb(), `INSERT OR REPLACE INTO traces (id, session_id, step_index, thought, action, action_input, observation, loop_count, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[trace.id, trace.session_id, trace.step_index, trace.thought, trace.action, trace.action_input, trace.observation, trace.loop_count, trace.created_at]
|
||||
runExec(getDb(), `INSERT OR REPLACE INTO traces (id, session_id, step_index, thought, action, action_input, observation, loop_count, error_pattern, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[trace.id, trace.session_id, trace.step_index, trace.thought, trace.action, trace.action_input, trace.observation, trace.loop_count, trace.error_pattern, trace.created_at]
|
||||
);
|
||||
persist();
|
||||
return trace.id;
|
||||
|
||||
Reference in New Issue
Block a user