bug: 源码启动(pnpm dsh / pnpm dsh web)首次工具调用必崩 — Cannot read properties of undefined (reading 'prepare') #6994
usniumowang-ctrl
started this conversation in
General
Replies: 2 comments
|
后续:本地按启动平面修好并验证(macOS 27.0 arm64 / Node v26.7.0 / dsh 0.1.6-alpha.2, master 按 #6967 的方向,把非打包启动的默认 resolution mode 按启动平面区分: // apps/cli/src/profile-boot.ts
const SOURCE_LAUNCH = import.meta.url.endsWith('.ts')
const defaultResolutionMode: ProfileResolutionMode = SOURCE_LAUNCH ? 'link' : 'runtime'
const resolutionMode = packaged ? 'runtime' : options.resolutionMode ?? defaultResolutionMode隔离验证(保留这处修法、把本贴原先建议的
另:崩溃过的会话确实会被卡死(assistant 消息里的 tool calls 无结果 → 之后每轮 |
0 replies
|
已把这批 本帖属于其中的
本地 CLI 聚焦测试 16/16、tools scheduler key 测试和 CLI/tools/agent-loop TypeScript build 已通过。详细补丁、用户恢复步骤、会话处理和回归门禁见上面的集中回复。 |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
源码启动的 dsh 每次工具调用都失败:
Cannot read properties of undefined (reading 'prepare')TL;DR (English)
A source launch (
pnpm dsh,pnpm dsh web) fails on the first tool call of every turn:One process loads two module copies of
@deepseek-ai/dsh-tools—packages/core/tools/src/index.tsandpackages/core/tools/lib/index.js. Each copy evaluates its ownSymbol('@deepseek-ai/dsh-tools.scheduler'), so thetoolsservice instance anddsh-agent-loopdisagree about the scheduler property key.ctx.tools[TOOL_RUNTIME_SCHEDULER]isundefinedand.prepare(...)throws. Registering the key (Symbol.for) fixes it locally; the underlying "source plane vs artifact plane" mix that produces the duplicate is untouched.Summary
从源码 checkout 启动 dsh 后,任何调用工具的轮次都会立刻失败,模型看不到工具结果,会话直接结束:
失败发生在「本轮第一个 tool call 之后、tool result 之前」,与工具种类无关(
bash、grep、skill、ask_user_question都复现),且完全确定为 100% 复现(源码启动必崩)。用户侧表现为 Web UI 里一条This turn failed+ 上面那行错误。在本地会话日志(
$DSH_HOME/sessions/**/session.v3.jsonl.zstd)中可以观察到同一天有 14 个 session 死于同一条错误,事件序列固定为:Reproduction
环境:macOS 27.0 (arm64)、Node v26.7.0、pnpm 11.7.0、dsh 0.1.6-alpha.2(master
ddefc45fbc)。实际结果:
对照实验(同一棵树、同一条启动链路的产物平面,正常):
pnpm dsh web(Web profile,用户日常用法)产生完全相同的错误。Root cause
崩溃点是工具调度器的取属性,不是任何 SQLite/
db.prepare:packages/core/agent-loop/src/tool-calls.ts:170(运行的是产物副本packages/core/agent-loop/lib/index.js:586)ctx.tools(ToolRuntime实例)上确实存在一个名为@deepseek-ai/dsh-tools.scheduler的 symbol 属性,但不是 agent-loop 导入的那个 symbol —— 两者描述相同、身份不同。插桩输出:同一个进程里,两份副本都被加载(模块加载标记各打印一次):
原因是一个进程里同一个包同时以源码副本和产物副本存在:
package.json的exports,把插件行解析到lib/index.js(packages/boot/app-boot/src/profile-resolution/、packages/boot/app-boot/src/profile.ts)。解析钩子实测:@deepseek-ai/dsh-tools被解析到file:///.../packages/core/tools/lib/index.js。paths投影(tsconfig.base.json中"@deepseek-ai/dsh-tools": ["./packages/core/tools/src"])把仓库内任何文件的 workspace import 映射到src/index.ts。因此packages/core/agent-loop/lib/index.js拿到的是源码副本的TOOL_RUNTIME_SCHEDULER,而注册tools服务的实例来自产物副本。这违反了仓库自己的规则 “Source plane vs artifact plane, never mixed”(AGENTS.md)。
补充观察(同一根因的另一面):把
packages/*/*/lib全部临时移走后启动源码链路,所有插件行都无法激活(Full diagnostics: $DSH_HOME/logs/startup-...log)。也就是说当前源码启动实际上依赖已构建的lib/;实测修改packages/core/agent-loop/src/**对pnpm dsh不生效,改lib/**才生效 —— “run one task from source” 目前并不成立。Expected behavior
pnpm dsh(源码启动)应当在单一平面里加载同一个包的一份实例:要么插件行与 workspace import 都落在src/,要么都落在lib/;任何跨包共享的模块级身份(Symbol、WeakMap标记、instanceof)都不应因平面混用而分裂。风险面不止这一个 symbol,同类键还有
packages/core/scope/src/index.ts:18的kScope(createScope写、scopeOf/scopeTarget读,跨包使用)、packages/api/gateway/src/client/remote-events.ts的REMOTE_EVENT_NEXT等;只要两个副本各持一份,就可能出现“写了读不到”的不一致。cordis 自身正是用注册表 symbol 做这类 brand(vendor/cordis/src/context.ts:66→Symbol.for('cordis.is')),可作为先例。本地修复与验证(供参考,未提交 PR)
packages/core/tools/src/index.ts:回归测试(
packages/core/tools/tests/tools.spec.ts):验证:
pnpm run build后,复现命令正常返回FIXED-OK(修复前同一命令必崩)。npx vitest run packages/core/tools packages/core/agent-loop→ 36 files / 844 tests 全绿。pnpm run build退出码 0。注意这是把症状挡住的最小改动:源码/产物两份副本仍然共存,跨包模块级身份的分裂风险仍在。
Ask
src/;如果目标是“插件一律跑产物”,那么 tsx 的paths投影不应再作用于lib/下的文件。Symbol.for)?在pnpm dsh这种同进程双副本可出现的运行时里,本地 symbol 天然不安全。dsh-source-launch-smoke(apps/cli/tests/source-launch.compat.spec.ts)只断言 TTY 拒绝,没有跑过任何一次带工具调用的 turn,因此这类崩溃不会被 CI 捕获(pnpm test走 tsconfig paths,全图单一平面,也不会覆盖)。Environment
ddefc45fbcpnpm dsh(headless)、pnpm dsh web$DSH_HOME/profiles/{web,headless}(默认 runtime resolution mode)pnpm run build,packages/*/*/lib存在All reactions