2026-06-11 02:03:00 +08:00

13 KiB
Raw Blame History

v0.5.8

新功能

  • 逆向工程插件 v0.4.2(plugins/reverse-engineering)。仓库自带的 marketplace 现在收录一个多平台 逆向工具箱,一键安装即可获得 7 个 MCP 服务器、1 个编排 agent、11 个 skill、2 个 slash 命令:

    • 静态分析:Ghidra(pyghidra-mcp)/ radare2 / JADX / apktool。覆盖 PE / ELF / Mach-O,以及 无 header 的固件 blob(路由器固件、Cortex-M flash dump、ECU dump 等)。多架构:x86/x64、ARM (含 Cortex-M Thumb-only)、AArch64、MIPS、PowerPC(含 VLE)、Motorola 68k / ColdFire、SuperH、 RISC-V,以及 AVR / MSP430 / 6502 / Z80 等小架构
    • 动态分析:Frida(Java/ObjC hook + Stalker trace)/ GDB(单步、硬件断点、watchpoint、跨架构 via gdb-multiarch + qemu)/ LLDB(Apple 平台单步 + ObjC method hook)。dynamic-debug-overview skill 让 agent 自动选车道
    • 编排:reverse-engineer agent 走 triage → static → 可选 dynamic → report 流程,产物落在 ${ARTIFACT_DIR}/<sample-id>/(默认 artifacts/re-runs)
    • slash 命令:/reverse-engineering:triage <path>/reverse-engineering:report <sample-id>
    • 配置:GHIDRA_INSTALL_DIR(可选,Ghidra 安装目录)、ARTIFACT_DIR(产物输出位置)
    • 规则:对样本只读,不向外推任何样本(无 VT / no malware-bazaar),不破解商业授权,Frida 只跑 用户授权过的目标,纯静态结论可信度上限封在 medium

    桌面端「设置 → 插件」添加本仓库 plugins/ 目录作为 marketplace 即可启用。详见 plugins/reverse-engineering/README.md

  • 零成本会话接力。新建会话欢迎页"最近活动"卡片新增"从这里继续"按钮。点击后服务端用 LLM 生成上一个会话的两层摘要(主线 + 最新进展)落盘缓存,通过 --append-system-prompt 注入到新 会话的 system prompt,再自动发一条短的 trigger message 让 AI 接续。前端展示生成进度阶段 ("读缓存 → 生成摘要 → 启动会话"),完成后会话头部出现 ↗ 已接续 (N tokens) 小芯片。摘要生成 失败时静默降级到原有的 zero-token textarea 预填路径。摘要 token 上限受 CLAUDE_CODE_HANDOFF_MAX_TOKENS (默认 1500)和 CLAUDE_CODE_HANDOFF_INPUT_CHARS(默认 80000)约束,WS handler 缓存命中后不重生成。

  • 欢迎任务卡片项目感知。原本写死的 4 个起始 prompt 现在按项目状态动态填充:

    • "PR 预合并审查"会替换成实际的 git.defaultBranch,develop 分支上不会再让 AI 对着 main 做审查
    • "排查失败的测试"和"补单元测试"会从最新的 dirty files 列表里挑一个真实文件路径(测试文件正则 + 源码文件正则,跳过锁文件 / 构建产物 / 二进制),自动填进 prompt
    • 每张卡片的 title= 属性都是完整解析后的 prompt,鼠标悬停就能预览要发送什么
    • 第 4 张卡 explainCode 重命名为 understandProject,prompt 改成读 CLAUDE.md / AGENTS.md / README + 列技术栈和顶层目录的项目全景介绍
    • 服务端 recent-activity 接口新增 dirtyFiles[] 字段(git status --porcelain=v1 -z 解析,按 mtime 倒序,最多 20 个),走原有 TTL 缓存
  • 伪 tool_use 检测与 provider 兼容追踪。某些第三方 Anthropic 兼容网关(mimo / lgfzer / 部分代理) 不转发原生 tool_use block,模型只能在 content_delta 里输出 XML 风格的 <tool_use ...>{...}</tool_use> 当文本流过来,渲染后变成 <tool_useid="..." 那样的乱码,而且模型自己以为调用成功还会写"Done."。 这次三层防御:

    • 桌面端 desktop/src/lib/fakeToolUseDetection.ts 用正则提取这种伪块(闭合 / 流式半开 / 多块连续 / 属性顺序互换 / 引号变体 / 自闭合 / 围栏代码块内的合法示例不误伤),AssistantMessage 在交给 MarkdownRenderer 前清掉,copyText 也走净化版本
    • 新组件 FakeToolUseNotice 在气泡上方渲染灰色提示卡:"模型尝试用 XML 文本块调用 Bash,但当前 provider 似乎不转发原生 tool_use,实际并未执行",让用户不会误信后续"Done."
    • 新 store providerCompatStore 按 provider id 计数(localStorage 持久化),累计 3 次伪 tool_use 弹一次 warning toast 建议切换 provider;Settings → Provider 列表上对应 provider 显示"工具调用异常"红色徽标, 编辑该 provider 配置后会自动清零(给新配置一次机会),阈值之后只增不弹,不打扰

修复

  • 服务端检测 + 自动回退 thinking 不兼容 provider。某些第三方 Anthropic 兼容网关(典型:基于 AWS Bedrock 的代理)会把 cc-haha 发的 thinking 字段塞进 Bedrock 的 additionalModelRequestFields, 目标模型不认识就返回 400 拒收(报错信息含 additionalModelRequestFields not supported / thinking is not supported 等)。这次:
    • 服务端 WS handler 在转发 sidecar 的 api_error 消息时新增 detectThinkingIncompatMessage 模式 匹配,命中后:
      1. providerService.markThinkingIncompatible(id, reason)thinkingIncompatible: true 和 reason 写进 ~/.claude/cc-haha/providers.json(单条 reason 最长 500 字)
      2. 通过 enqueueRuntimeTransition 调度一次 sidecar 重启(走的是和 set_runtime_config 同一条 优雅重启路径,不会打断进行中的流式响应)
      3. 推一条新的 WS 消息 provider_compat_event { providerId, kind: 'thinking_incompatible', reason } 给前端
    • buildProviderManagedEnv 看到 provider.thinkingIncompatible === true 时自动注入 CLAUDE_CODE_DISABLE_THINKING=1,sidecar 重启后所有后续请求都不再发 thinking 字段
    • 前端 providerCompatStore 新增 thinkingIncompatibleProviderIds: Set<string> 维度 (localStorage 持久化),收到 provider_compat_event 后弹一次 toast 告知用户已自动回退; Settings → Provider 列表对应行渲染"思考不兼容"红色徽标(独立于"工具调用异常"徽标,可同时 出现)
    • 用户编辑该 provider 任何字段并保存 → updateProvider 服务端清掉 thinkingIncompatible
      • reason,前端 clearProvider(id) 同步清两个维度的 store。给改完配置的 provider 一次新机会, 再次出错会重新触发流程
    • 检测的正则故意收得很紧(只匹配 additionalModelRequestFields / 明确的 thinking 拒绝短语), 避免误伤无关 4xx 把 thinking 永久关掉
  • 会话接力不再留下空白会话。当用户从 sidebar 顶部点过"新建会话"创建了一个空白 sessionA(然后 关掉 tab 留在 sidebar),回到欢迎屏点"从这里继续"时,之前的实现会再 createSession 一个新会话 sessionB,sessionA 变成孤儿空白会话。现在 EmptySession.onAutoHandoff 在 createSession 前先用 pickReusableEmptySession 找同 workDir 下消息数=0 且不是 previousSessionId 的最新空白会话,有 就 openTab 复用它,没有才创建新的。新增 desktop/src/lib/sessionReuse.ts + 7 个单测覆盖 workDir 过滤、消息数过滤、excludeSessionId、null workDir 防御等边界。
  • 会话接力摘要现在带最后 12 轮原文(可调)。原本的两层摘要 main + recent 是 LLM 抽象出来的, 容易丢失"用户上一句具体问什么"、"AI 上一次回复到哪了"的真实措辞。现在 sessionSummaryService 生成摘要时额外保留原会话最后 12 轮(默认)的 USER:/ASSISTANT: 原文,每条截到 400 字、整体 cap 8000 字,新字段 recentRaw 落进缓存,formatHandoffSystemPrompt 在 main+recent 之后追加这段 到接续 system prompt 里。可通过环境变量 CLAUDE_CODE_HANDOFF_RAW_TURNS(050,默认 12)和 CLAUDE_CODE_HANDOFF_RAW_CHARS(50030000,默认 8000)调节。0.5.7 旧缓存没有 recentRaw 字段, formatter 自动跳过原文段,完全向后兼容。
  • 服务端模型上下文不再示范错误格式specialistRouter.ts 早就警告过 key="value" 属性式片段 会让网关模型把 tool_use 退化成 XML 文本,但还有 3 处反复给模型喂 subagent_type="verification": verification_gate_reminder(messages.ts)、TodoWriteTool 的 verification 提醒、TaskUpdateTool 的 verification 提醒。改成散文形式("set the subagent_type parameter to verification"),从源头降低 伪 tool_use 概率。新增 noKeyValueNudges.test.ts 锁住这 3 处,以后改回属性形式立即挂 CI。

范围

  • 思考不兼容自动回退:src/server/types/provider.ts(SavedProvider schema + thinkingIncompatible / thinkingIncompatibleReason 字段)、 src/server/services/providerService.ts(markThinkingIncompatible 方法 + updateProvider 自动 re-arm)、src/server/services/providerRuntimeEnv.ts(buildProviderManagedEnv 注入 CLAUDE_CODE_DISABLE_THINKING=1)、src/server/ws/{events,handler}.ts(新 ServerMessage provider_compat_event + detectThinkingIncompatMessage + notifyThinkingIncompatIfMatches)、 src/server/__tests__/{providers,provider-runtime-env}.test.ts(7 + 2 新单测)、 src/server/ws/thinkingIncompat.test.ts(6 新单测);桌面端 desktop/src/types/{provider,chat}.tsdesktop/src/stores/providerCompatStore.ts(新增 thinkingIncompatibleProviderIds 维度 + recordThinkingIncompatible action + hasProviderThinkingIncompatible helper)、desktop/src/stores/chatStore.ts(消息分发新增 case)、desktop/src/pages/Settings.tsx(新"思考不兼容"徽标)、5 语种 i18n 新增 3 条 key、 desktop/src/stores/providerCompatStore.test.ts(新增 6 单测)。
  • 会话接力修复:desktop/src/lib/sessionReuse.ts(空白会话复用 picker)、 desktop/src/lib/sessionReuse.test.ts(7 单测)、desktop/src/pages/EmptySession.tsx (onAutoHandoff 接入 picker)、src/server/services/sessionSummaryService.ts(recentRaw 字段 + buildRecentRawSlice + formatHandoffSystemPrompt 注入)、 src/server/services/sessionSummaryService.test.ts(8 单测)。
  • 逆向插件:plugins/.claude-plugin/marketplace.jsonplugins/reverse-engineering/(plugin.json / mcp/servers.json / agents/reverse-engineer.md / 11 个 SKILL.md / 2 个 slash 命令 / scripts/{dev-link,smoke,validate}.ts / README.md)。
  • 会话接力:src/server/services/sessionSummaryService.ts(LLM 双层摘要 + 磁盘缓存)、 src/server/api/sessions.tssrc/server/ws/handler.ts(set_handoff_summary 路径)、 desktop/src/components/welcome/RecentActivityCard.tsxdesktop/src/api/projects.tsdesktop/src/stores/sessionRuntimeStore.ts(handoffInfo)。
  • 欢迎卡片:desktop/src/components/welcome/WelcomeTaskCards.tsx(resolver 模式 + 内部 fetch)、 desktop/src/api/projects.tsdesktop/src/pages/{EmptySession,ActiveSession}.tsxsrc/server/services/projectActivityService.ts(dirtyFiles 派生)、5 个语言的 i18n 模板参数化。
  • 伪 tool_use 检测:desktop/src/lib/fakeToolUseDetection.tsdesktop/src/stores/providerCompatStore.tsdesktop/src/components/chat/{FakeToolUseNotice.tsx,AssistantMessage.tsx}desktop/src/pages/Settings.tsx(badge + clear-on-edit)、 src/utils/messages.tssrc/tools/{TodoWriteTool,TaskUpdateTool}/src/utils/noKeyValueNudges.test.ts
  • i18n:5 个语言新增会话接力、欢迎卡片参数化 prompt、providerCompat 共 10+ 条 key。

验证

  • 单元测试:fakeToolUseDetection.test.ts 14 / providerCompatStore.test.ts 14(原 8 + 6 新增 thinking-incompat) / AssistantMessage.faketooluse.test.tsx 6 / EmptySession.test.tsx 22 / sessionRuntimeStore.test.ts(含 handoffInfo)/ noKeyValueNudges.test.ts 3 / sessionReuse.test.ts 7 / sessionSummaryService.test.ts 8 全部通过
  • 服务端 bun test src/server/{ws/thinkingIncompat,__tests__/providers,__tests__/provider-runtime-env, utils/verificationGate,utils/noKeyValueNudges}.test.ts src/tools/AgentTool/specialistRouter.test.ts: 6 + 87 + (provider-runtime-env 新 2 单测) + 31 全部通过
  • cd desktop && bun run lint:tsc --noEmit 通过
  • 服务端 bun test src/utils/{verificationGate,noKeyValueNudges} src/tools/AgentTool/specialistRouter: 31 个测试通过
  • 浏览器 MCP 端到端:在 feat/welcome-cards-polish worktree 下,4 张卡片正确替换为 feat/welcome-cards-polish 分支名,脏文件 desktop/src/pages/EmptySession.test.tsx / desktop/src/pages/ActiveSession.tsx 自动填进 testPath / filePath 槽位,点击后撰写框正确预填
  • 会话接力 MCP 端到端:feat/session-handoff-summary 分支生成两层摘要,新会话头部出现 ↗ 已接续 (N tokens) 芯片,AI 首条响应直接基于摘要继续,不再要求用户重新解释上下文
  • 逆向插件:本次发布未运行端到端 smoke。校验入口在 plugins/reverse-engineering/scripts/smoke.ts (注册 marketplace → enable → /api/plugins/update + /reload → 断言版本号、组件计数与磁盘源 一致),需服务端 + vite 起来后手动跑 ⚠️ pending