Commit Graph
9 Commits
Author SHA1 Message Date
thzxx 5b9d4d19b3 feat: v0.8.0 流语义补全 · 会话可靠 · 恢复力 — finish_reason 全链路贯通根治"思考中停止" · 2445 用例全量回归
CI / 类型检查 + Lint + 单元测试 (push) Failing after 9m16s
CI / 全量测试 (Electron ABI) (push) Failing after 6m4s
CI / 产物编译验证 (push) Successful in 11m1s
P0 会话可靠性收口(根治"模型思考着会话就停止"):
- P0-1 finish_reason 全链路贯通:DONE 事件与 IterationStep 新增 finishReason,OpenAI 共享 SSE / Anthropic message_delta.stop_reason / Ollama done_reason 三路采集,TRACE 层弃用硬编码 'stop' 记录真值
- P0-2 空响应守卫 + 降级重试:零产出流→可重试错误走退避;思考耗尽输出预算(reasoning-only + length)→自动关闭思考降级重试一次;仍失败→OUTPUT_LENGTH_EXCEEDED 结构化错误 + 故障转移;附带根治 abort 恰逢零工具调用轮被 COMPLETED 抢占的真实缺陷
- P0-3 思考×能力×预算三对齐:DeepSeek/MiMo/Agnes/Ollama 四家 supportsThinking=false 强制不发思考参数;小输出预算告警;设置页联动提示
- P0-4 渲染层可见性:截断/空完成/友好错误三类提示,i18n 全部出层
- P0-5 回归四件套:reasoning-only 终止判定、集成级空闲超时、504 引擎重试归类、思考中 abort→USER_INTERRUPT、P4-2 强制收尾路径

FEAT-1:LLM 设置新增「最大输出上限」——Provider 支持矩阵显隐 + 模型上限钳制提示 + 超限保存警告 + llm.maxTokens 热生效

P1 修复面收口:
- 渲染层三缺陷根治:后台会话回放缓冲(2000 条/4MB 有界 + agent:getReplayState + 事件总线)+ abort 双层自愈 + sendMessage 收尾兜底 + 中断卡片清扫
- 工具 abort 信号全覆盖:web_search/web_fetch/http_request/code_search/git 系列/delegate_task 全部接入引擎中断;web_search 时间预算收敛(720s→≤240s);移除伪造 ToolExecutionContext 与死代码
- 安全:本地 Pinned CONNECT 代理根治浏览器通道 DNS rebinding(校验期 IP pinning,可注入 resolver 表测);配置 URL 域名解析深校验(DeepCheckSoftFailure 软失败);SSE 空 error 帧防御修复;Ollama generate/embed AbortSignal.any 合并
- 缺陷清单:UTF-16 BOM 读取、tmp 同毫秒碰撞(nanoid 后缀)、code_search JS 回退参数对称(case_sensitive/前后文独立)、list_directory include_node_modules、崩溃自愈退避(60s 窗 ≥3 次停 reload)、MemoryViewer/Sidebar i18n 收口

P2 能力演进:
- 会话回收站:SCHEMA_VERSION 3 + 迁移 10(deleted_at,存在性守卫),软删除/恢复/彻底删除/30 天自动清理(启动+24h),searchMessages 聚合剔除,Sidebar 回收站面板
- 会话回放播放器:sessions:listRecordings/readRecording(白名单+目录边界+20MB 上限),SessionReplayPlayer 时间轴/步进/变速,Trace 面板入口
- electron-updater 自动更新:双轨(手动 feed 比对保留),生产环境启动静默检查 + update:status 广播 + app:updateInstall + LogsSettings UpdatePanel + builder publish 配置
- @ 文件提及:workspace.listFiles/readFileClip(边界/512KB/NUL 拒绝/MEMORY.md 保护),ChatInput Fuse 联想+键盘导航+附件管线注入
- MCP Resources/Prompts 发现:可选能力 try/catch 降级,mcp:listServerContents,MCPSettings 展开视图
- 文档对齐:内部 API 标准 HTML(Adapter 清单补 MiMo/已实现注记/STREAM_RESET/DONE.finishReason/ repetition_truncation 映射);README v0.8.0 亮点表

P3 测试基建:
- 新增 4 个测试文件:engine-stream-contract(6)、engine-stream-reliability(4:集成空闲超时/504 重试/思考中 abort/P4-2 强制收尾)、thinking-capability-gate(7)、pinned-proxy(9,含深校验 5)、session-trash(5,DB 域)、use-agent-stream hook 级(5)、agent.test 回放缓冲(2)
- 契约更新:orchestrator 被中断 SubAgent success=false(abort 优先级修复语义)、SSE 空 error 帧、UTF-16 正常读取、DeepSeek 未配置思考显式 disabled、迁移矩阵 v2→3
- 弱断言根治:registry WEBP 单向断言、hooks-contracts 自比恒真、memory 空 token 补强

全量验证:typecheck 0 错误 / lint 0 问题 / 系统 Node 2144 通过(301 DB 用例按 ABI 跳过)/ Electron ABI 2445/2445 全量通过 0 跳过
2026-09-05 20:06:26 +08:00
thzxx 99d0c54129 feat: v0.7.4 时序语义修正 · 防线实效补漏 · 全量测试翻倍 — 2406 用例 + jsdom 组件测试全量回归
CI / 类型检查 + Lint + 单元测试 (push) Failing after 6m27s
CI / 产物编译验证 (push) Successful in 9m57s
CI / 全量测试 (Electron ABI) (push) Failing after 5m19s
P1 修复面收口:
- 超时三态区分(aborted→USER_INTERRUPT / ETIMEDOUT→TIMEOUT / 其余→ERROR),
  根治"真实网络超时被误报为用户中断"
- 流空闲超时统一(SSE/Ollama/Anthropic 读循环 60s 无数据抛 504 进重试通道)
- 同会话并发 sendMessage 防重入(isRunning 守卫)+ 会话存在性预检 +
  前置调用移入 try(ERROR+DONE 双事件保证,根治 isStreaming 假死)
- 清空审计后 resetChainCache(根治 verifyChain 误报 TAMPERED)
- DONE 不再提前清理 TRACE(TERMINATED 统一收尾,补全最终迭代录制)
- IME 合成回车不发送(普通 Enter + Cmd/Ctrl+Enter 双分支)+ handleSend 闭包修复

P2 安全纵深:
- preload 移除原始 electronAPI 暴露(渲染层零使用,关掉 XSS invoke 任意通道单点风险)
- CORS 同源回显根治(仅当前浏览页面 Origin,did-navigate 同步)
- MEMORY.md 命令保护正则扩展(括号/$/反引号/< 重定向边界 + 前导路径)
- write_file append TOCTOU 统一(open 后 realpath 校验,新文件分支补漏)
- 敏感键归一化(authKey 驼峰/连字符命中)+ MCP headers 鉴权值加密落库
- ReDoS 检测共享化(search_files/file_editor 统一拦截)
- run_tests/lint_code 升风险 + 需确认 + npx --no-install(执行边界对齐 run_command)
- MCP/SearXNG/llm.baseURL/updateFeedUrl 配置类 URL 高危目标校验(IPv6 去括号 +
  十六进制映射解析 + 尾点剥离)

P3 架构还债:
- temperature/maxTokens 热生效(引擎/编排器/SubAgent 三处接线)+ setBatch 单事务落盘
- SessionRecorder flush 竞态根治(flushPromise 等待 + 超限内联落盘 + stopRecording async)
- 内存收口(lastConsolidationBySession LRU / subTraces 清理 / 会话删除 disposeEngine)
- i18n 全量收口(28 组件 + 353 key 双字典,状态标签改渲染时函数)
- 死代码清理(updateTraceStep/HEADER_HEIGHT/void preA/失实注释)
- 斜杠菜单 MUI 化 + 删除逻辑收敛 resetSessionState + Blob URL 统一释放 +
  用户消息"仅保存"落库(saveMessage 透传前端 id 修复 id 错位)

P4 能力演进:
- 死循环检测拆分(驻留前置 + 乒乓后置带进度信号,合法交替不误报)
- run-lock 30s 超时强制 abort(旧 run 卡死不无限排队)
- RETRY 双通道 stream_reset(前端按 run 归属精确清空,根治重试文本重复)
- FTS5 trigram 中文子串搜索(迁移 9 版本化 SCHEMA_VERSION=2,≤2 字符 LIKE 回退)
- getContextWindow 兜底 1M→128K(未知模型防 413)

测试:
- 855 → 2406 用例(+1551,2.8 倍):服务层 +325(含 MemoryManager 51 新用例)、
  工具实体 +483、IPC/适配器 +390(含 OpenAI/Anthropic/Ollama 独立套件)、
  纯函数表格化 +330;引入 jsdom + @testing-library(14 组件测试文件 249 用例)
- 修复 R1(saveMessage id 透传)/ R2(stream_reset 精确归属)两个回归缺陷
- 遗留低危项清零:git-tools 顺序耦合 / web-fetch 真实时间退避 / slo 内存断言 /
  mcp-security 多余 skipIf / deepseek-balance 命名误导 / 组件 mock 注入脆弱性

版本: 0.7.4; README 同步(工具风险表/版本徽章); 依赖: 移除 @electron-toolkit/preload,
新增 jsdom/@testing-library(devDependencies 不打包)

回归: typecheck 双端 0 错误; ESLint 0/0; Electron ABI 全量 2406/2406 零跳过;
系统 Node 2110 通过 296 跳过(better-sqlite3 ABI)
2026-08-30 19:19:07 +08:00
thzxx ebe45482b0 feat: v0.7.3 成本收口 · 状态一致 · 死账清理 — Prompt Cache 根治 + SSRF DNS Pinning + 87 用例扩充全量回归
CI / 类型检查 + Lint + 单元测试 (push) Failing after 5m47s
CI / 全量测试 (Electron ABI) (push) Failing after 5m19s
CI / 产物编译验证 (push) Successful in 9m55s
P1 修复面收口: Prompt Cache 根治(日期/记忆/附件三类易变内容出 system 入用户消息
  前置块 user-context.ts, system 跨 run 字节级稳定; Anthropic system 块数组化 +
  cache_control ephemeral 断言, DeepSeek 自动缓存前缀命中 — 多轮对话输入 token
  成本降数量级); 编辑重发/重新生成幽灵 Trace 双侧根治(DB truncateMessagesAfter
  同步过滤 metadata.traceSteps + 前端 trimTraceStepsByAnchor 镜像, 严格小于锚点
  时间戳, 同毫秒等值判废); sessions:deleteMessage 死通道全链路删除(渲染层零调用
  + message_count 漂移面); Ollama vision 能力门控全链路(MetonaModelInfo
  .supportsVision 贯穿 adapter/IPC/store/UI, model-capabilities.ts 三道判定纯函数,
  未知保守放行); 记忆固化节流(consolidation-policy 纯函数: 总开关 + 内容门控
  [回答>=200字符或存在成功工具调用] + 会话级 10 分钟频率窗口, 三 memory.* 配置键)

P2 安全纵深: SSRF DNS Pinning 关闭 rebinding 窗口(ssrf-guard 重构
  resolvePublicAddresses 单源; ssrf-dispatcher 以 undici Agent.connect.lookup
  钉死校验 IP, TLS SNI 保持原域名, 一次性 dispatcher 用后即毁; 代理激活显式
  退化为仅入口校验); web_fetch 重写手动逐跳重定向循环(每跳先校验后连接,
  替代 redirect:follow 内核跟跳的中间跳裸奔, 上限 5 跳); http_request 换用
  pinned fetch; web_search 可达性预检加固(私有 URL 零请求 + 不跟跳, 3xx 视为
  可达); Agent 浏览器 CORS 通配收紧为 Origin 回显 + Vary: Origin;
  ConfirmationHook.forgetSession 会话终态清理(会话删除/abort 联动/SubAgent
  终结三处接线, 根治 rememberedDecisions 泄漏)

P3 架构还债: agent.enableReflection 死配置全链路接线(main→shared→引擎→
  Orchestrator→设置开关, REFLECTING 状态真实可达); AgentLoopConfig.timeoutMs
  死字段删除; MemoryManager.cleanupExpired 挂入健康检查周期(expires_at 回收
  管道真实化); buildSafeEnv 收敛 utils/safe-env.ts 单源(run_command 与 MCP
  stdio 共用, 终结双实现漂移); Trace 生命周期治理(metadata 只保留最近 20 个
  run — keepRecentRuns 纯函数; JSONL 录制启动自动清理保留 200 个 + 设置页
  手动清理); SLO/健康快照可视化(app:healthSnapshot IPC + 设置页只读卡片 +
  审计链一键校验)

P4 能力演进: 会话标题 LLM 自动生成(TitleGenerator — 每会话幂等/并发重入复用
  同一 Promise/自定义标题不覆盖/失败静默回退, Sidebar 经 config:changed 实时
  刷新); MCP 自动重连(5s/15s/60s 退避最多 3 次, reconnecting 状态机,
  teardownConnection 内部拆除保留簿记 — 用户断开/开关关闭即时取消, 设置页
  显示第 N/3 次); 死循环检测 ABAB 乒乓模式(最近4轮 A→B→A→B 交替判定, 补齐
  docs 第五章"两状态反复切换"检测契约); i18n 第三阶段(ChatInput/LLMSettings/
  OnboardingWizard/MemoryViewer 主链路文案出层, zh-CN + en-US 双字典补齐)

测试: 737 → 824 用例(+87, 新增 8 个测试文件 + 扩展 3 个)。新覆盖: user-context
  分组/空值收缩/拼接契约、context-builder 字节级稳定性、Anthropic cache_control
  四态、consolidation-policy 九路判定矩阵、ssrf-dispatcher(pinned lookup/重定向
  解析/IP 校验)、forget-session 会话隔离、trace-lifecycle run 淘汰、
  trace-trim 严格小于边界、safe-env 净化矩阵、mcp-reconnect 退避状态机
  (fake timers)、title-generator 并发重入、SQLite 侧 truncate×TRACE 联动
  (Electron ABI)。测试驱动修复: GIT_*/ 注释终止块注释、重连计数被自身重试
  前置断开重置(拆 teardownConnection 保留簿记)、TitleGenerator 幂等占位与
  并发去重的检查顺序竞态(去重先于幂等)

版本: 0.7.3; README 同步(配置表新增 agent.enableReflection/memory.*/mcp.autoReconnect)

回归: typecheck 双端 0 错误; ESLint 0/0; 系统 Node 771 通过 53 跳过
  (better-sqlite3 ABI); Electron ABI 全量 824/824 零跳过
2026-08-30 09:44:43 +08:00
thzxx 80cf5b482c fix: v0.6.1 修复回复/推理期间偶发崩溃 — 浏览器回退窗口竞态 + 崩溃可观测性
CI / 类型检查 + Lint + 单元测试 (push) Failing after 5m41s
CI / 全量测试 (Electron ABI) (push) Failing after 5m21s
CI / 产物编译验证 (push) Successful in 10m1s
【根因(实证归因,非猜测)】
分析 userData/logs/main.log 全部 33 次启动会话,定位 3 处异常终止点
(07-25 ×2 / 08-22 ×1,启动标记前无 Database closed)。三处 100% 共享
同一模式:web_search 并行抓取 → 多个 web_fetch 同时进入浏览器回退 →
共享单例 BrowserWindowManager 中后到 open() 销毁前一个正在加载/执行
JS 的窗口。关键统计:56 次浏览器回退中 ERR_ABORTED(并发互毁的直接
证据)仅 3 次,而这 3 次恰好全部对应 3 个崩溃点;无并发销毁的 53 次
回退从未崩溃 —— 触发条件完全收敛。

缺陷链(三层叠加):
1. browserFetch 直接 open/evaluate 共享单例,无跨调用序列化 — 并发
   回退互相销毁窗口(ERR_ABORTED / "Object has been destroyed")
2. destroy() 对仍在使用中的 partition fire-and-forget
   clearStorageData/clearCache,与紧随其后的新窗口创建并发 —
   原生存储层竞态(崩溃引爆点)
3. ensureReady 检查与实际 executeJavaScript/loadURL 之间存在竞态窗口;
   loadURLWithTimeout 的 Race 落败方 rejection 无人处理

【修复(browser-window-manager.ts + web-fetch.ts + browser.ts)】
- 新增 fetchPageText:排队版页面抓取,串行化完整 open→等待→evaluate
  序列(与 open 共用单一操作链,destroy 只会在链上发生,跨链互毁彻底
  消除);web_fetch 浏览器回退改走此入口
- open() 拆分 openInternal(链内直调);open 与 fetchPageText 共用
  单一串行链,排队不分死锁
- destroy() 移除 session 存储清理(终态清理迁移至 close(),await 执行,
  不再与窗口创建并发)
- safeWebContents() 即时校验替代 racy 的 ensureReady;evaluate/extract/
  screenshot/click/type/scroll/waitForSelector 全部加固,消除对已销毁
  webContents 的调用
- loadURLWithTimeout 落败方 rejection 兜底(防 unhandledRejection)
- cleanupBrowser/cleanup/close 异步化适配(main.ts 退出链路 await)

【崩溃可观测性(此前崩溃无迹可查 — 日志无声截断)】
- process.on(uncaughtException/unhandledRejection) → [FATAL] 落盘
- app.on(render-process-gone/child-process-gone) → [FATAL] 落盘
- WindowManager: 每窗口 render-process-gone 日志 + 自动 reload 自愈
  (渲染进程 OOM/崩溃不再白屏卡死,可自动恢复)

【验证】
- lint 0/0;typecheck 双工程 0 错误;test:electron 252/252;build 通过
2026-08-22 19:16:41 +08:00
thzxx 2230bcec3f feat: v0.4.0 四阶段迭代 — 安全加固 + 工程基线 + 架构重构 + 双 Provider 扩展
P0 安全修复:
- API Key 加密存储(safeStorage 密钥链,版本化前缀,历史明文平滑兼容)
- 间接提示注入防护(SecurityScanHook 工具结果深扫描,网络工具脱敏/本地工具警示分级)
- error:report IPC 断链修复(渲染进程错误上报落 electron-log + 审计)
- abort 信号贯通工具层(run_command/dev-tools 子进程随会话中断终止)
- run_command 沙箱加固(cd 系统目录/敏感文件读取拦截 + chcp 前缀剥离防解析退化)
- .env 真实生效(dotenv 回退加载,应用内配置优先)

P1 工程基础:
- ESLint 9 flat config + 全部 34 条存量 warnings 清零(零容忍基线)
- 测试基线 118 用例 11 文件(token/文件防护/权限/沙箱/注入/命令/引擎/注册表/审计链/摘要分层)
- test:electron 双模式(ELECTRON_RUN_AS_NODE 跑 Electron ABI,SQLite 套件全执行)
- SessionRecorder 多会话隔离 + 9 种 TRACE 事件补全(含最终轮 iteration_end)
- Provider 故障转移(重试耗尽/不可重试一次性切换 fallback + 前端通知)
- MCP 真就绪(等待全部连接完成再广播 tools:ready)
- SLO/HealthChecker 真实接入(60s 巡检 + 托盘状态)
- CONFIG_DEFAULTS 单一来源(消除 SEED 双源漂移)

P2 架构升级:
- handlers.ts 1940 行拆分为 13 个 IPC 域模块(防重入注册 + 多窗口广播)
- AgentEngineManager 每会话独立引擎(LRU 30 + adapter 工厂隔离 abort 信号)
- TaskOrchestrator EngineProvider 改造 + abortByParent 联动中断 SubAgent
- 会话摘要分层上下文(session_summaries 滚动摘要 + 截断游标清理防因果污染)
- 消息编辑重发/重新生成(truncateAfter IPC + store 动作 + UI)
- Markdown 导出 / WebSearch 并行抓取(并发 3)/ 记忆 TF 缓存 / 版本构建期注入

P3 能力扩展:
- OpenAI Adapter(o 系列推理模型 reasoning_effort/max_completion_tokens)
- Anthropic Adapter(原生 Messages API:tool_use 块/角色合并/thinking budget/图片 base64/SSE 事件机)
- 设置页/Onboarding 六 Provider 全链路接入
2026-08-20 23:17:02 +08:00
thzxx 2c2ca4a692 feat: 升级至 v0.3.16 — 工单修复 51 项 + 审查修复 30 项(安全加固/适配器/工具系统/数据层/前端) 2026-07-22 10:31:13 +08:00
thzxx 4f5f570ac8 fix: 修复多轮对话400/Provider通知反复弹出/浏览器环境隔离三大缺陷
1. 多轮对话第二次发消息 AI 不响应 (CRITICAL)

handlers.ts: 保存 tool 结果消息到数据库,DeepSeek API 要求 assistant 有 tool_calls 时后续必须有对应 tool 结果消息

openai-format.ts: assistant 有 tool_calls 时 content 设为 null (API 规范,空字符串会导致 400)

agent-store.ts: 前端加载历史时过滤 tool 消息,避免冗余卡片

2. Provider 切换通知每次发消息都弹出

main.ts: reloadAdapter 添加配置签名比较 (lastConfigSig),配置未变化时幂等返回 true,不再重建 adapter 或发 toast

3. 浏览器工具无环境隔离

browser-window-manager.ts: 独立 partition 隔离 Cookie/存储; 恢复 webSecurity,CORS 通过 webRequest 处理; setWindowOpenHandler 拦截 window.open; 并发互斥锁串行化 open 调用; destroy() 改用 win.destroy() + clearStorageData 清理残留
2026-07-12 21:21:55 +08:00
thzxx 025f00171b feat: 升级至 v0.3.0 — 安全增强、死循环检测、六轮全面审计修复
大版本迭代,新增安全增强、Agent Loop 增强、UI/UX 增强,经六轮全面审计修复所有问题。

新增功能:
- OutputValidator 事实一致性检查 + 幻觉检测
- PromptInjectionDefender 语义级检测(指令性动词密度、角色边界、分隔符嵌套)
- DeadLoopError 死循环检测(连续3轮相同工具调用自动终止)
- PolicyEngine maxFrequency 滑动窗口频率限制
- MemoryManager TF-IDF 语义检索 + IDF 缓存原子替换
- 斜杠命令(/tool /memory /clear /export)+ 快捷键(Ctrl+B/J/Shift+F/N/[/])
- 专注模式(Ctrl+Shift+F)带面板状态快照保存/恢复

六轮审计修复(共修复 3 CRITICAL + 8 HIGH + 13 MEDIUM + 11 LOW):

CRITICAL:
- main.ts 传入 createAdapter 而非 reloadAdapter,导致 Provider 切换完全失效
- Ctrl+N/Ctrl+[/Ctrl+] 不同步 agent-store,导致消息发到错误会话
- engine.ts emit('error') 无监听器导致 DONE 事件丢失、前端卡死

HIGH:
- 死循环检测在工具执行之后(移入 PARSING 后 EXECUTING 前)
- deadLoop 事件前端未处理
- ConfirmationHook.clearPending 从未调用导致定时器泄漏
- engine.ts retry abort listener 未移除导致监听器堆积
- MCPManager JSON.parse 无 try-catch 导致初始化崩溃
- sendMessage 自动创建会话不同步 session-store
- setCurrentSession 竞态导致旧请求覆盖新会话数据

MEDIUM:
- toggleFocusMode 覆盖用户原有面板状态
- 正则检测可被常见词绕过
- 频率限制内存泄漏 + customPolicies 覆盖
- LIKE 回退转义未包含反斜杠
- OutputValidator 新功能未传入 toolResults/context
- MemoryConsolidator LLM 调用无超时保护
- AuditService 每次 log 都查询数据库
- browser-window-manager 超时后未停止页面加载
- output-validator URL 比较大小写敏感
- FileReader 无 onerror 导致 Promise 永久挂起
- /clear /export 不关闭斜杠菜单
- 专注模式下 toggleSidebar/toggleDetail 未恢复另一面板快照

LOW:
- abortPromise 事件监听器堆积
- RateLimitHook Map 内存泄漏
- memory.ts await 同步方法
- PolicyEngine 死代码清理
- Orchestrator sessionDepth 会话结束不清理
- workspace.service.ts 元数据插入边界问题
2026-07-12 19:46:47 +08:00
thzxx 8cdb93f8bf feat: MEMORY.md 访问保护、格式简化及预存问题修复
MEMORY.md 保护: 新建 file-guard.ts 共享守卫模块; read_file/write_file/search_files/run_command 禁止访问根目录 MEMORY.md; permissions.ts 增加 deniedPatterns 深度防御。格式简化: 元数据从 # 注释改为 > 引用语法; 校验规则从 6 条简化为 3 条; context-builder extractContent 适配。预存问题: 修复路径遍历前缀碰撞漏洞; 移除 browser_extract 内容截断; SearXNG 配置实时读取; web_search/web_fetch 移除截断; 侧边栏动态获取工具列表; 版本号 0.1.1
2026-07-05 21:24:22 +08:00