Skip to content

fix: 修复 Windows 宿主适配、配置恢复和工具路由问题 - #43

Closed
youyv wants to merge 1 commit into
KannaKuron:mainfrom
youyv:alpha适配

Hidden character warning

The head ref may contain hidden characters: "alpha\u9002\u914d"
Closed

youyv wants to merge 1 commit into
KannaKuron:mainfrom
youyv:alpha适配

Conversation

@youyv

@youyv youyv commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

问题与结果

这次在 Windows 上对 v0.50.0(fa9382257f31c281156ba0be608d3f004b90778a)进行了源码审核与隔离宿主验证,确认 5 类运行时/配置问题,并发现现有宿主 preview 由于加载器及旧 Core 调用契约而不能有效运行。

本 PR 修复这些问题,保留原有私有 Git Bash executor / 官方 PowerShell provider 架构,不改变访问策略,不升级插件版本或发布 npm。依照仓库纪律,修复从最新上游 main 的 alpha适配 分支提交。

问题 修复后的行为
Python run_code 被注入 JavaScript prelude 只转换实际 TypeScript runtime;Python/未知语言源码保持原样
补全持久终端 shellPath 删除其它 config 字段 仅更新 shellPath,保留参数、注释,并使用 profile 文件锁
隐藏全局/祖先同名工具被重新注册覆盖 检查全部 scope 的所有权,动态 companion 和 eager slot 均让位
停用插件误删用户原有 dsh-ops bash:false 持久化记录实际修改字段及原值,只恢复插件拥有的值
工具路由文字只改 schema 副本,模型看不到 由自有 Bash definition 和 PTC prompt section 正式发布
preview loader 栈溢出、旧 tools.execute 接口失效 防重入 loader,使用真实 Native/Ptc executor 与 calls/results 批次接口

1. Python run_code 语法错误

触发条件:Windows,默认 posixPaths / virtualMounts / codePaths 开启,调用会话使用 Python PTC runtime。

原问题:translateDispatch() 仅根据工具名 run_code 就拼接 programPrelude(),生成 try{const e=process.env;...}catch{}。即使输入只有 print("AUDIT_PYTHON_OK"),也会变成 Python 无法解析的程序。审核时用真实 Python 解释器复现:原程序退出码 0,转换后退出码 1,SyntaxError: expected ':'。

修复方法:

  • 新增 programLanguageFor(ctx, agent),优先从调用 agent 自己的 context 读取 ptcRuntime.language,不根据全局 peer 开关猜测。
  • 只有确认 language === 'typescript' 时执行 JS/TS 字面量转换及 TEMP prelude;Python、未知或不可读取的 runtime 不改源码。
  • 普通工具的路径参数翻译保持独立;程序提示文字也使用同一语言门控。
  • PTC 的 run_code 是 executor 提供的 transport,改用选中 executor 的实际 schema 判断它是否存在,而非普通工具 registry 的 definitions 列表。

验证:便携语言矩阵覆盖 Python/未知/TypeScript及 agent 优先级;完整插件入口经真实 Core PTC transport 将 Python 程序交给真实解释器,断言源代码逐字节不变且执行成功。

2. 持久终端自动接管删除用户配置

触发条件:profile 中已有启用的 optional-terminal-bash 行,其中设置了 timeoutMs、scrollbackLines 或 shellArgs,但尚未设置 shellPath。

原问题:原实现将整个 config 替换为 { shellPath }。审核复现中,timeoutMs: 98765、scrollbackLines: 4321 和 shellArgs 全部丢失,函数仍返回 updated。

修复方法:

  • 直接设置 YAML 路径 [bashIndex, 'config', 'shellPath'],不重建整个 config map。
  • 使用宿主 withFileLock(profile/package.json) 包住整个读取、修改、原子写入和回读验证,锁目标与 configEditor 一致。
  • 使用当前基线必备的 writeFileAtomic,移除无锁的 tmp/rename 回退;宿主能力不可用时明确失败。
  • tests/terminal-bundle.mjs 加入 npm test;YAML 成为锁定的开发依赖,删除作者个人机器路径探测。

验证:真实 YAML parser/writer 保留其它字段、数组和用户注释;原有 plan、序列化、写入失败、回读及回滚测试也执行。

3. 隐藏工具的所有权被覆盖

触发条件:全局或祖先 scope 已注册 gitbash_native / gitbash_to_native_path,在当前 agent 被 restrict 隐藏。

原问题:schemas(agent) 只列可见工具,原代码误认为隐藏名称空闲,并假设注册会因重名失败。当前 Core 明确允许 agent 层覆盖全局/祖先层,而自有注册不受该继承工具 mask 过滤。审核时在真实 Core 上复现隐藏工具重新可见且调用到插件实现。

修复方法:

  • 新增共享 toolNameOccupied(),使用公开 scopeChainOf(),分别检查全局、祖先各自视图以及当前 scope;子 scope 的 mask 不再抹掉上层所有权。
  • registerExperimentalTool() 与 eager native slot 共用该判断。
  • 通过实际宿主 loader 预加载 scope 能力,避免混用不同包副本的 scope parent 表;能力不可用时记录原因并跳过注册。
  • 不读取私有 tools.view,不依赖跨 scope 的 register 冲突来保护所有权。

验证:真实 Core 覆盖全局/当前 agent 同名所有权、隐藏全局工具、隐藏祖先工具、foreign dispose 后恢复注册、Jobs reload,以及 eager-slot 生命周期。

这项是工具可见性和所有权修复;不宣称原问题能够绕过 OS sandbox。

4. dsh-ops 恢复误删原有 bash:false

触发条件:用户在安装本插件之前已经将某个模式设为 bash:false,随后插件接管其它模式并被停用/卸载。

原问题:恢复逻辑把所有四个模式的 false 都视为插件写入,甚至只读到 present 就安装恢复钩子。没有原值和来源记录,因此恢复会删除用户原先的 false,可能重新启用 ops bash。

修复方法:

  • 在 profile 旁新增 .gitbash-ops-ownership.json,只存本插件实际修改的模式、是否存在原 override 和原布尔值;不存凭证,不修改 dsh-ops 的 schema。
  • 写配置之前原子持久化收据;真正 profile 修改仍只经官方 configEditor.edit()。
  • 恢复仅处理收据拥有、且当前仍为插件写入 false 的字段;原有 false、用户后改 true/删除、非目标配置保留。
  • 记录跨进程可用;没有收据的历史 false 不猜测来源、不自动清理。
  • editor 拒绝写入时撤销新增认领;恢复失败保留收据供重试。编辑 callback 重验最新值,避免覆盖并发用户修改。
  • 注入 scope 在启动前登记清理:取消待执行 retry,等待正在进行的 adoption,然后执行恢复,避免卸载后的延迟重新写入。

验证:子 Node 进程完成 adoption、父进程读取落盘收据恢复;覆盖原有 false、原有 true、继承值、其它设置、后续用户修改、失败/不落盘写入、恢复重试以及并发值变化。没有对真实用户 profile 写入。

迁移说明:升级前留下的无收据 false 可能属于用户,也可能属于旧版本。本 PR 选择保留,用户可通过 dsh-ops 设置自行恢复;不能安全自动判定来源。

5. 路由提示未到达模型

原问题:system-prompt/assemble 中调用 tools.schemas() 后修改返回的数组。该数组是副本,当前宿主在 waterfall 前已收集 provider 工具声明,并在结束后附回原 tools;所以字符串单测虽然通过,最终模型 schema 没有任何新路由文字。

修复方法:

  • 路由纯函数拆到 src/tool-routing.js,避免 Bash module 与 inline wiring 互相循环导入。
  • 只对插件自有 Bash definition 增加 description getter,让宿主 native schema/PTC SDK 正常投影它。
  • 从对应 agent 可执行工具名称生成路由文字,不推荐隐藏或未获得 step admission 的条件工具,不读取 schema getter 造成递归。
  • 使用固定的运行中 agent pwsh tool-face 快照及实时路径方言设置;保留 complete persona 下仍可见的工具描述。
  • PTC 程序调用规则使用独立 prompt section;不修改官方 run_code transport,也不依赖无效的 schema 数组修改。

验证:直接检查真实 SystemPrompt.assemble() 最终产物,覆盖 native/PTC SDK、隐藏 pwsh、委托方言关闭与完整 persona。complete persona 按宿主语义保留唯一 section,不强行插入被明确抑制的 section。

6. 修复宿主预览与测试可信度

审核基线:原 npm test 为 342/342,通过并未暴露上述问题。原 test:preview 的 9 个文件在初始化阶段栈溢出;只临时修正 loader 后为 33/82,通过/失败不能直接解释为 49 个插件 bug,大量属于旧夹具。

修复方法:

  • registerHooks.resolve 内部的 require.resolve 会再次进入同步 hook,增加 try/finally 重入保护。
  • 新增测试公共 host-runtime.mjs,真正注册 Native/Ptc executor,传入 calls,从 results 读取单调用结果;不 monkey-patch ToolRuntime。
  • 更新 SDK 检查、preset registry 的 agents 依赖、移除已退役 fallback 期望,以及运行中 agent 工具面固定的断言。
  • 便携 Cordis 锁定到已验证宿主版本 4.1.0;CI 测 Node 24.9.0 声明下限和当前 Node 24,Windows/Linux 双平台,并包含 alpha适配 推送。
  • 更新中英文 README、AGENTS 当前契约、tests/README 和 CHANGELOG。

验证与边界

本机 Windows,从用户安装目录的 Desktop ASAR 只读提取完整 Core 到隔离目录;没有修改安装目录、生产 profile 或重启 Desktop。

检查 结果
npm test 372 passed / 0 failed / 0 skipped
完整 test:preview 文件清单,Desktop 自带 Node 24.21.0、Core 0.2.2-rc.1、Cordis 4.1.0 93 passed / 0 failed / 0 skipped
最终路由/所有权细化后的 audit + runtime preview 28 passed / 0 failed / 0 skipped
npm pack --dry-run --ignore-scripts 通过,37 个发布文件,新增 runtime modules 均包含
node --check 新增/修改入口与 git diff --check 通过

宿主预览同时覆盖实际 Git Bash / PowerShell、native exact argv、中文和空格路径、GBK/UTF-16/raw 输出、取消/owner disposal、Jobs promotion、前台超时、文件输出完整性与重复 policy gate。

npm ci --ignore-scripts --omit=optional
npm test
$env:DSH_PREVIEW_HOST_DIR = '<Desktop Core 完整目录,含 package.json 和 node_modules>'
$env:DSH_PREVIEW_PYTHON = '<需要验证的 Python 可执行文件>'
npm run test:preview
npm pack --dry-run --ignore-scripts

普通 Node 不能直接读 Electron ASAR:需用 Desktop 的完整只读提取副本,不能只用 app.asar.unpacked/dsh,更不能用不相干的全局 CLI 代替。

未声称完成真实 GUI/preset picker、真实 dsh-ops 0.5.0 整套插件生命周期、可选 Python PTC 插件整套部署、winget 安装或所有 FastCtx payload 的验证。Python 测试使用真实 Core transport + fixture runtime adapter 调用真实解释器。整个验证没有模型/API 调用。

远端检查补充:本提交 ad86e4c 在复刻仓库与上游 PR 的 GitHub Actions 均 4/4 通过:Windows / Ubuntu × Node 24.9.0 / 24;上游 workflow run 为 42221666847,复刻仓库 run 为 42221407656。

@KannaKuron

Copy link
Copy Markdown
Owner

感谢这份补丁,方向和覆盖面都很扎实。我按维护者流程把这套改动整理成了可评审分支,而不是直接合并原始 head:

相对原 head 的主要整理:

  1. Python run_code 语言门控:只对调用 agent 实际的 ptcRuntime.language === 'typescript' 做程序字面量转换和 JS TEMP prelude;Python/未知运行时源码保持原样。
  2. 路由投影:不再修改 system-prompt/assemble 返回的 assembly.tools 副本。Bash 自有 definition 的 description 由宿主 native/PTC provider 投影,PTC 指引走真实 prompt section。tools.selectExecutor 仍是私有入口,已加 typeof 守卫 + try/catch;缺失时省略 PTC 段,不让 prompt 组装失败。
  3. 终端接管:只改 config.shellPath,保留 shellArgs、超时、回滚行数等配置与注释;disabled/shellPath 若是 !!js 等非字面量,保持原样并返回 kept-user-choice。
  4. 工具所有权:经公开 scopeChainOf 逐层检查 global/祖先/当前 scope 的 schemas(),隐藏的祖先工具也不会被重新注册;动态 companion 与 eager native slot 共用同一判据。
  5. dsh-ops 恢复形状:收据只记录插件实际认领的字段;原本没有 override 的模式恢复为“无 override”,不再写成显式 bash: true。
  6. 提示词减重:PTC_ROUTING 删除与各 binding description 重复的逐工具选择说明,保留 call-only、权限拒绝即停止、不猜/不发明名字与安全句。

验证边界:本机 macOS npm test 375 项(374 pass + 1 平台 skip,0 fail),node --check、git diff --check、npm pack --dry-run 通过;CI 已在 Windows 跑通单测。Windows 专属的 test:preview/native companion、真实 dsh-ops 0.5 生命周期与 GUI/preset picker 我这边没有复验,不声称通过;作者报告的 Windows test:preview 93/93 本轮也未独立复现。

分支已推送供评审;暂未合并 main,也未发版。

@KannaKuron

Copy link
Copy Markdown
Owner

整理版已合并 main 并发布 v0.51.0。

合并的是在本仓库 alpha适配 上整理后的版本,没有直接合并原 head:除了 PR 的修复,还补了终端 !!js 条件字段保护、dsh-ops「恢复原形状」(原本无 override 不再写成显式 bash: true)、selectExecutor 缺失时的静默降级,以及 PTC_ROUTING 的重复内容收敛。

本机 macOS 只能验证非 Windows 面:npm test 375 项(374 pass + 1 平台 skip,0 fail);Windows 专属的 test:preview / native companion、真实 dsh-ops 0.5 生命周期与 GUI 仍未独立复验,CHANGELOG 与 Release notes 已如实标注。感谢提交。

@KannaKuron KannaKuron closed this Nov 7, 2026
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