Skip to content

fix: 工具面开关改为「重启生效」——不再在存活会话上重建工具面 - #41

Merged
KannaKuron merged 2 commits into
KannaKuron:mainfrom
MYCF711:fix/tool-face-switch-restart
Nov 1, 2026
Merged

KannaKuron merged 2 commits into
KannaKuron:mainfrom
MYCF711:fix/tool-face-switch-restart

Conversation

@MYCF711

@MYCF711 MYCF711 commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

症状

在设置卡把 pwshTool 关掉之后,存活会话的工具面被清空:request/header.tools 从 59 个掉到 31 个,丢掉的 29 个正是官方 preset 的工具,只剩 profile 级插件工具。重启 DSH 才恢复。

真机环境:Windows、dsh 0.2.1-rc.5、本插件 0.47.2。

证据

同一会话(session.v4.jsonl.zstd)里 request/header 的工具数时间线:

12:51:13  59     ← 正常
13:23:30  31     ← 关掉 pwshTool 之后
13:25:54  31
13:34:14  31
13:37:09  59     ← 重启后恢复

丢失的 29 个工具(对比 59 与 31 两份工具表):

ask_user_question, bash, create_goal, edit, exit_plan_mode, get_goal,
gitbash_native, gitbash_to_native_path, glob, grep, job_kill, job_list,
job_output, present, pwsh, read, read_image, schedule_create, schedule_delete,
schedule_list, schedule_update, skill, subagent_fork, todo_write, update_goal,
web_fetch, web_search, workflow, write

保留的 31 个全部来自 profile 级插件(hindsight / team / github / watch / unlag / subagent / working_directory 等)——即 preset 的工具整批消失,不是单个工具被隐藏。

插件侧成因

pwshTool / experimentalNative 是 volatile 字段,宿主把设置卡上的编辑实时交给运行中的行。插件在 loader/volatile-update 上的处理是:

ctx.on('loader/volatile-update', (paths) => {
  if (... ['pwshTool', 'experimentalNative'].includes(path[0])) return
  for (const agent of tracked.keys()) reconcile(agent)   // ← 每个存活 agent 重算工具面
})

而 reconcile() 的第一步是解开自己的 pwsh 掩码再读工具面(这是 PR #36 为「开方向翻转」引入的)。这次读取与宿主重组工具面的时序不保证稳定:读到「面里没有 pwsh」时,stand down 分支会把它当成「preset 掩码接管了工具集」,撤掉自己注册的 bash——两种失败方向都发生在一次纯展示开关的改动上。

插件不该在这条路径上重建任何存活会话的工具面;而且 UI 从未提示这个开关会动工具面。

改动

文件 改动
src/inline-tools.js ① newState() 增加 toolFace;reconcile() 在该 agent 首次观测时快照 { pwshVisible, experimental },此后一律按快照判定;② loader/volatile-update 命中这两个开关时只写一行日志,不再逐个 agent 重算;③ tools/pre-execute 的 pwsh 拒绝判定跟随快照(保留 deps.pwshEnabled?.() !== true 字面量,现有 smoke 断言锁它)
src/client.js 四个工具面开关(variant / experimental / pwsh / fctx)的中英 hint 增加「⚠ 改动需重启 DSH 后生效;运行中会话的工具面会被冻结在原值」
README.md / README_EN.md 把「切换 pwshTool 会改 bash description、一次性作废缓存」改为「只影响新会话/重启后的会话」
CHANGELOG.md [Unreleased] 条目(症状、根因、修法、真机证据)
tests/runtime-regressions.mjs 「活体跟随两次翻转」改为「冻结 + 只记日志」;新增「翻转只对 NEW agent 生效」(fixture 的 mask 改为 per-agent)

日志新增一行,便于用户对照:

[gitbash-shell] tool-face switch changed (pwshTool): running agents keep their
tool face; a new session or a DSH restart applies the new value

行为契约变化

开关不再对已存在的会话生效:新会话或重启后生效。这是有意的偏离——上游当前设计是活体跟随,而活体跟随在这台机器上直接导致了事故。

验证

  • npm test:346 项,346 pass,0 fail(本机 Windows,Node 24)。
  • 事故复现路径整理自上面那份会话日志(59→31→59 三段工具数)。
  • 本机已用同一补丁跑了一轮真实会话(设置卡切开关不再动现有工具面,日志出现上面那行)。

想请维护者判断的两点

  1. 插件侧该不该完全放弃活体跟随?如果你认为「开关应当立即生效」是必须保留的契约,我可以把它改成「只冻结 bash 的撤除(stand-down)判定」这一半,其余保持活体。
  2. 宿主侧那 29 个 preset 工具为什么整批消失——它超出本插件可影响的范围(本插件只注册 bash / gitbash_native / gitbash_to_native_path / pwsh / gb_* / terminal_*)。我能提供的只有上面的工具表时间线与宿主日志线索;如果这属于宿主的重组时序问题,这一条或许该转成 DSH 的 issue,本 PR 只作为插件侧止血。

MYCF711 and others added 2 commits November 1, 2026 21:57
`pwshTool` / `experimentalNative` 是 volatile 字段,宿主把设置卡上的编辑实时交给
运行中的行。插件在 `loader/volatile-update` 上对**每个存活 agent** 重跑 `reconcile()`,
而 `reconcile()` 会先解开自己的 pwsh 掩码再读工具面——这次读取与宿主重组的时序不保证
稳定:既可能把「面里没有 pwsh」误判成「preset 掩码接管」而撤掉自己注册的 bash,也让
一次纯展示开关的改动触发工具面重建。

真机事故(dsh 0.2.1-rc.5 + 插件 0.47.2,win32):把 `pwshTool` 关掉之后,存活会话的
`request/header.tools` 从 59 掉到 31,丢掉的 29 个正是官方 preset 的工具
(`read`/`write`/`edit`/`glob`/`grep`/`bash`/`gitbash_native`/`pwsh`/`web_search`/
`web_fetch`/`todo_write`/`exit_plan_mode`/`schedule_*`/`skill`/`present` 等),只剩
profile 级插件工具;重启 DSH 后恢复。

改动:

- 每个 agent 在**首次观测**时快照 `{ pwshVisible, experimental }`,此后一律按快照判定,
  不再读 live 开关;
- `loader/volatile-update` 命中这两个开关时只写一行日志
  (`tool-face switch changed (...)`),不再重建任何存活 agent 的工具面;
- `tools/pre-execute` 的 pwsh 拒绝判定跟随该 agent 的快照(保留
  `deps.pwshEnabled?.() !== true` 字面量,上游 smoke 断言锁它);
- 设置卡四个工具面开关(variant / experimental / pwsh / fctx)的中英 hint 增加
  「改动需重启 DSH 后生效」提示。

行为契约变化:开关只对**新会话**或重启后的会话生效,运行中的会话保持它创建时的工具面。

测试:`runtime-regressions` 的「活体跟随两次翻转」改为「冻结 + 只记日志」,并新增
「翻转只对 NEW agent 生效」用例(fixture 的 mask 改为 per-agent)。全量 346 项全通过。

未覆盖:丢掉的 29 个工具超出本插件可影响的范围,宿主侧「preset 工具整批消失」的完整
链路仍需宿主日志确认;本改动消除插件侧触发点,并让 UI 说明真实生效时机。
@KannaKuron

Copy link
Copy Markdown
Owner

按维护者评审,我已在这个 PR 上补了一版并推到 fix/tool-face-switch-restart(当前 head 4a3b934):

  • 补全 experimentalNative 的冻结:ensureNativeSlot / nativeWanted 改为按 agent 首次观测的快照创建/保留 native 槽,不再被 live 开关中途撤掉;toolFace.experimental 现在真正参与判定。
  • 设置卡只给 pwshTool / experimentalNative 两个开关加提示,并区分两件事:工具面可见性/注册保存后需重启才在运行中会话更新;原生工具的执行门禁仍按当前开关立即生效。variantPresets / fastctxTools 的提示恢复原语义(它们没有被这个 PR 冻结)。
  • 版本升到 v0.48.0,CHANGELOG 测试数修正为 346(345 pass + 1 平台 skip),并补了 native 源码断言。
  • macOS 全量测试通过;Windows 侧仍请按 gitbash_native is absent from the first step of every turn, invalidating the whole prompt-prefix cache #38 的 request/header 方法再复验一次,重点看保存开关后 step 1/step 2 工具数不再变化。

如果这个方向没问题,我就按 v0.48.0 合入并发布。

@KannaKuron
KannaKuron merged commit 4a3b934 into KannaKuron:main Nov 1, 2026
@KannaKuron

Copy link
Copy Markdown
Owner

已按 v0.48.0 合入 main 并发布:

合入后的 head 是 4a3b934(你的提交 + 维护者补全)。Windows 侧如果方便,升级到 0.48.0 后按 #38 的 request/header 方法再抓一轮:保存 pwshTool 后 step 1 / step 2 的工具数应保持不变,日志里应出现 tool-face switch changed ... 那一行。若还有问题随时开新 issue,感谢这份定位很扎实的 PR。

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.

2 participants