🐛 fix(sdk): MCP/LSP 域十项修复——孤儿进程回收、连接退避、spawn 环境白名单与写超时 - #440
Conversation
Code Review十项逐项核对:七项(#325/#326/#327/#328/#374/#375/#384)真实落地、方向正确、测试钉死有效;但三项与 main 已合入实现重复,且分支 CONFLICTING——须 rebase 去重后才能合。 重复冲突项(阻塞)
rebase 后需人工核对 workspace-mcp-manager 探测点同时保留 main 的 mapPublicError 包装与本分支 真增量七项核验(rebase 后原样保留)
非阻塞 P3
另注意合并顺序协调:PR#444(dead-code)同样触碰 mcp/client.ts / sdk-mcp-server.ts / README.md,先合者会制造新冲突。 |
Code Review七项新修复(#384 listChanged 订阅/#325 takenWrapperNames/#327 stdin 写超时/#374 lspmux 键控/#375 callTool 守卫/#328 SwiftLint win32/#405 seam 化测试)全部实证正确,但基线落后 main 三个已合 PR(#437 关掉 #311/#312,#443 关掉 #380),需 rebase 解冲突后再合。 [P1·合并操作风险] 原样合入将回退 main 已有修复merge-tree 实测 4 文件冲突,其中两处若按分支版本解决会静默丢弃:
[P2] disconnect() 不清自身负缓存与 PR 描述"显式 disconnect 清零"矛盾(靠 force 兜底);main 版行为是清零的。rebase 时建议顺手对齐。 [P3] 死代码上的重复投资client.ts/sdk-mcp-server.ts 属 #388 判定的死代码路径,#311/#326 hunk 是对死代码的重复修复;真实承接面是存活的 manager.ts 栈(#444 将删除死路径,故 #440 先合、#444 后 rebase)。 测试seam 化(setDefaultMcpSdkClientConstructor/setLspmuxProbeSpawn)替代 mock.module,符合 CI bun 1.3.13 严格导出约束 ✓;seam 未泄漏进公共导出 ✓ 结论修复合并基线后可合——rebase 弃重复 hunk,按上述方案解四处冲突。 |
8a09eec to
fffed0d
Compare
- ensureConnected 失败负缓存:指数退避(5s 起步倍增封顶 60s), 挂死 server 不再每个 run 阻塞整个连接超时;connect/testServer 支持 force 绕过,sidecar 手动探测走 force。 - wrapper 工具名去重提升为 manager 实例级集合:server id 大小写 折叠后跨 server 碰撞不再静默互相覆盖,断开/重建时回收旧名。 - callTool 结果为 undefined 时抛 protocol_error:在途 disconnect 不再把空结果伪装成成功喂给模型(合法空结果是对象)。 - 默认 client factory 订阅 tools/list_changed:带 generation 校验 地重拉 listTools 原地刷新工具表,动态增删工具不再陈旧到重连。 - 新增 mcp/naming 共享 util:normalizeMcpServerId/ToolName + buildMcpToolName(64 字符截断 + hash 消歧),client.ts 与 sdk-mcp-server 两处拼装点统一收口,engine 用量报告前缀同步。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
win32 无条件加 PowerShell "& " 调用符,但 Bash 工具在 win32 优先 走 Git Bash,行首 & 是语法错误,SwiftLint 诊断全量静默丢失。 shellKind 判定从 bash.ts 提升到 utils/shell-invocation 共享导出, 适配器改用与 Bash 工具一致的 resolveShellInvocation+shellKind 判定:仅 PowerShell 方言加 "&",Git Bash 不加。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
探测缓存原为模块级单例:不分 cwd 导致跨工作区误判,且 5 分钟 TTL 内 running 不复检,守护进程启/停双向滞后。改为 Map 按 resolve(cwd) 键控,正向 TTL 压到 30s、负向保 5min;新增 invalidateLspmuxCache,LspClient 启动 mux'd server 失败时主动 失效缓存,下次解析回退直连。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
send() 对 stdin.write 回调无限期等待且全通知链路无超时,LSP 僵死 即 Write/Edit 永久挂起。所有通知路径都汇聚于 send(),在此处统一 加 Promise.race 写超时(默认 10s)并在超时时 fail() 标记客户端 死亡,一处改动覆盖全部通知路径,调用方经 onDead 进入既有重启链。 新增 setLspWriteTimeout 供运行时与测试调整。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LspClient.start 原样 {...process.env} 全量继承宿主环境,而 lsp.json
由项目侧可控,任意 command 可读取宿主 API key/token(MCP 两路径
早已收口 getDefaultEnvironment,LSP 未同步)。spawn env 改为官方
SDK 最小默认环境 + server.env 显式白名单合并;normalizeServerConfig
补 record.env 透传入口(过滤非字符串值),resolveAvailableServer 对
lspmux 包装 env 改覆盖为合并避免丢失用户配置。测试以注入宿主变量
钉死不泄漏、白名单变量透传、PATH 可用。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lspmux 探测 spawn 与 MCP 默认 client 构造器原经 mock.module 整模块 替换,bun test 单进程套件内全局生效且 factory 缺失具名导出,组合跑 时污染后续文件(CI bun 1.3.13 更严必炸)。生产代码零行为变化: lspmux 新增 setLspmuxProbeSpawn、manager 新增 setDefaultMcpSdkClientConstructor 两个模块级可覆盖 seam,测试改注 入 fake。reviewer 五文件组合复跑零串扰。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
#312 退避已由 main 以 failureRetryBaseMs/MaxMs + nextRetryAt 实现, 本分支原退避时序断言与之重复,收敛为单个 force 旁路测试并换用 main 的选项名。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
collectLspAdapterDiagnostics 依赖 resolveLspExecutable 找到 swiftlint:POSIX 下探针要求 X_OK,测试只 writeFile 未 chmod,CI Linux 上解析失败静默返回 undefined;且裸名解析会兜底扫宿主 PATH, 结果不确定。改为显式 toolConfig 注入绝对路径 + POSIX 补 chmod。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
9517a29 to
cde1210
Compare
概述
修复 sdk 全量 review 提出的 10 个 issue(MCP + LSP 域),每个 commit 独立可跑绿。
验证
tsc --noEmit干净;src/mcp/ 31 pass / 0 fail;lsp+bash 组合 46 pass / 0 failCloses #311, closes #312, closes #325, closes #326, closes #327, closes #328, closes #374, closes #375, closes #380, closes #384
🤖 Generated with Claude Code