Skip to content

🔥 chore(sdk): 移除 commands fs-loader stub 与九个无触发点 hook 事件 - #465

Merged
CavinHuang merged 2 commits into
mainfrom
worktree-agent-a111d51065abe1db8
Aug 23, 2026
Merged

🔥 chore(sdk): 移除 commands fs-loader stub 与九个无触发点 hook 事件#465
CavinHuang merged 2 commits into
mainfrom
worktree-agent-a111d51065abe1db8

Conversation

@CavinHuang

Copy link
Copy Markdown
Owner

概要

清理两处投机性接口面(#295):

  1. commands fs-loader stubloadCommandDefinitions 硬编码返回 [],却接入了 agent.loadedCommands、initialization 流程与 index 导出面。整体删除:

    • commands/fs-loader.tscommands/types.ts
    • agent.ts:移除 loadedCommands 字段、两处装配(refreshCwdDependentState / reloadPlugins)、getPluginCommands()、初始化命令合并逻辑
    • plugins/loader.ts:移除 LoadedPlugin.commands 死字段与 manifest 装配
    • index.ts:移除对应导出面
  2. HOOK_EVENTS 收敛 27 → 18:移除全仓无任何 emit 路径的 9 个事件:WorktreeCreate / WorktreeRemove / CwdChanged / FileChanged / Notification / TeammateIdle / Elicitation / ElicitationResult / InstructionsLoaded。保留的 18 个事件逐一核实触发点存在(engine.ts 16 处 + agent-tool.ts SubagentStart/SubagentStop)。

逐项 grep 结论

  • loadCommandDefinitions/commandDefinitionsToSlashCommands/CommandDefinition/loadedCommands:消费方全部在 SDK 内部死链上,apps/ 无引用;sidecar 已不走 SDK 的 loadPlugins 路径
  • 9 个移除的 hook 事件:全仓仅存于 HOOK_EVENTS 声明与 README,零 emit 点;Notification/Elicitation 其余匹配均为无关的 SDK 消息类型(SDKTaskNotificationMessage 等)
  • sidecar plugin-hooks-bridge 仅 import HookConfig/HookDefinition/HookInput/HookOutput,不含 HookEvent,收敛后编译通过

验证

  • 全仓 grep 无残留引用
  • bun run typecheck 六包全绿
  • packages/sdk 测试 696 pass / 0 fail
  • sidecar plugin-hooks-bridge 定向测试:7 pass / 1 fail 为本机 PowerShell spawn 环境性失败,stash 基线对照确认与本改动无关

Fixes #295

🤖 Generated with Claude Code

TaTaLiao and others added 2 commits August 23, 2026 01:04
loadCommandDefinitions 硬编码返回空数组,属投机性扩展点残留:
- 删 commands/fs-loader.ts 与 commands/types.ts
- agent.ts 移除 loadedCommands 装配、getPluginCommands、初始化命令合并
- plugins/loader.ts 移除 LoadedPlugin.commands 死字段
- index.ts 移除对应导出面

sidecar 的 plugin-registry/commands 走自有实现,不受影响。

Fixes #295

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
移除全仓无任何 emit 路径的 9 个死事件:
WorktreeCreate/WorktreeRemove/CwdChanged/FileChanged/Notification/
TeammateIdle/Elicitation/ElicitationResult/InstructionsLoaded

保留的 18 个事件逐一核实 emit 路径存在(engine.ts 16 处 +
agent-tool.ts SubagentStart/SubagentStop)。sidecar 桥接层仅消费
HookConfig/HookDefinition/HookInput/HookOutput,不受影响。

Fixes #295

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@CavinHuang

Copy link
Copy Markdown
Owner Author

Review

结论

通过,可合。两块删除均逐条实证为零风险死代码清理:全仓 grep 确认被删符号与事件在 sdk 之外零消费方,18 个保留事件逐一核对 emit 路径存在,README 已同步修正。无阻塞发现。

发现

[P3] agent.test.ts:687 负向断言保护力弱化(无需改动)
expect(init.commands.find(c => c.name === "/code-review")).toBeUndefined() 在改动后成为恒真断言——插件/文件命令注入路径已整体消失,skill 泄漏的载体不复存在。作为防回归绊线仍有效(若未来重新引入 commands 装配会再次有意义),保留合理,仅备注。

[P3] @lume/agent-sdk 是发包面,外部宿主若有带 commands 的插件 manifest 会静默失效(可接受)
InitializationResult.commands 与 slash 合并逻辑此前理论上可接收 manifest.commands / 模块导出 commands 的插件贡献。仓内零此类插件、desktop/web 不消费该字段、sidecar 有自有实现,故本仓行为惰性;但若存在仓库外的第三方宿主依赖此扩展点,其命令会无声消失。#295 的裁定本就是删除投机扩展点,此处仅留痕。

已核实

1. LoadedPlugin.commands 删除安全性

  • 全仓 LoadedPlugin 消费方仅在 packages/sdk/src/agent.tsplugins/loader.ts 内部;docs/codex-plugin-*.md 中的 LoadedPlugin 是 Codex 上游 Rust 结构体分析,无关。
  • sidecar 不走 SDK loadPlugins:自有 capability-resolver 构造的 HookConfig = Record<string, HookDefinition[]> 键为裸 string,与 HOOK_EVENTS 收敛完全解耦。
  • manifest 无独立 schema(JSON.parse(...) as LoadedPlugin & { entry?: string }),删除字段后多余的 commands JSON 键静默忽略;仓内 grep 无任何 *.json"commands" 键。
  • loader.ts 同步删掉的 hasCommands 仅存在于 console.debug 日志对象;commandOnly/CommandToolManifest 是「kind === 'command' 命令即工具」的另一条活链路,PR 正确地未触碰。

2. InitializationResult.commands 契约

  • types.ts:1130 接口未动,commands: SlashCommand[] 保留,现恒返回五个内置命令(/clear /compact /resume /mcp /reload-plugins)。
  • main 上该值本就恒等于五内置:loadCommandDefinitions 硬编码返回 [],且无任何 manifest/module 提供过 commands。
  • 消费方核查:desktop/web 零调用 getInitializationResult;sidecar run.ts:1208 仅 await 不读字段;run.test.ts 十处调用无一断言 .commands;派生字段 slash_commands 由同一数组 map 而来,值不变。

3. 九个死事件判定复核

  • 派发机制穷举:executeHooks('<Event>') 在 engine.ts 恰好覆盖 16 个不同事件(Setup/SessionStart/SessionEnd/UserPromptSubmit/PreCompact/PostCompact/Stop/StopFailure/PreToolUse/PostToolUse/PostToolUseFailure/PermissionRequest/PermissionDenied/TaskCreated/TaskCompleted/ConfigChange),agent-tool.ts 另有两处 executeDetailed(SubagentStart:289、SubagentStop:400)——保留的 18 个全部各有 emit 点。
  • 被删 9 个在声明点外全仓零命中。重点排雷:Notification 的命中均为 desktop Electron new Notification 系统通知;Elicitation 的命中均为 node-repl 的 MCP form elicitation 与 SDK 消息类型 SDKElicitationCompleteMessage——都是同名撞车而非 hook 触发点。
  • codex-adapter.ts 的 CODEX_EVENT_MAP 仅映射 10 个保留事件,收敛后编译无损。
  • registerFromConfig 对不在 HOOK_EVENTS 内的事件名本就静默 continue,用户旧 manifest 若声明已删事件的 hook,行为等价(注册即死 vs 注册前跳过),无新增报错路径。

4. 文档同步

  • packages/sdk/README.md 已改 28→18 且事件列表精确对应;全仓 *.md 中这是唯一提及被删事件名处。hooks.ts 文件头 docblock 原本只列到 ConfigChange + CwdChanged/FileChanged/Notification 三行,PR 删的正是这三行,无残留。

5. 测试同步

  • 被删符号(fs-loader/types/loadCommandDefinitions/CommandDefinition/getPluginCommands/loadedCommands/HOOK_EVENTS 内容)在全部 *.test.* 中零引用——不存在需删除或跳过的钉死测试,PR 不动测试文件是正确形态。
  • agent.test.ts:687 负向断言语义仍成立且继续通过(见 P3 备注)。

6. CI / 提交划分 / 文案

  • CI 4/4 绿:Core verification (Ubuntu)、PR gate、Windows reliability、macOS desktop reliability。
  • 两个 commit 按关注点干净切分(commands 死链 / hook 事件收敛);emoji 前缀 conventional 格式合规;diff 为纯删除 + README 计数修正,零 scope creep。

@CavinHuang
CavinHuang merged commit 0acd1d3 into main Aug 23, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🔥 sdk: 死扩展点残留——commands fs-loader stub + 9 个无触发点 hook 事件

2 participants