Fix: profile resolution loads dsh-tools twice under tsx dev mode, breaking every tool call #7201
Replies: 1 comment
|
Your diagnosis holds, and I can confirm the mechanism from a different direction — from the resolver's own data model rather than from the tsx interaction. Four additions: where the symlinked parent comes from, why the default (not just the symlink) is implicated, what the fix touches beyond the parent URL, and the thread cluster this belongs to. Verified against 1. The symlinked parent is recorded by contract, and one builder already canonicalizes the anchor it doesn't record
links.set(dep, dir)
declarers.set(dep, next.anchor) // profile.ts:504 — the parent's manifest path
...
queue.push({ anchor: manifestPath, manifest }) // :508Under pnpm that parent is exactly the anchor you instrumented ( What makes this look like an oversight rather than a design choice: the other builder in the same file does canonicalize the anchor, immediately before walking it — const canonicalAnchor = join(realModuleDirectory(dirname(anchor)), basename(anchor)) // profile.ts:683
2. The default is implicated, and the author already reverted half of itThe line that made this reachable is one character:
Two consequences worth having on the record. First, there is no way to select 3. Blast radius:
|
Uh oh!
There was an error while loading. Please reload this page.
Bug report with fix:
pnpm dsh webbreaks every tool call ("Cannot read properties of undefined (reading 'prepare')")Symptoms: Since 0.1.6-alpha.2 (PR #4471), running the CLI in dev mode (
pnpm dsh web, i.e.node --import tsx/esm apps/cli/src/bin.ts) makes every tool call fail withTypeError: Cannot read properties of undefined (reading 'prepare')atpackages/core/agent-loop/src/tool-calls.ts:170, regardless of model or tool. Built mode (node apps/cli/lib/bin.js web) works.Root cause (confirmed by an instrumented boot of the web profile): The new runtime profile resolution routes profile-scoped requests to the declaring package's anchor as the native resolution parent. That anchor is found by walking pnpm's
node_modulessymlinks (packageDirFromAnchor), so it contains symlink segments (e.g.apps/cli/node_modules/@deepseek-ai/dsh-acp-app/package.json). tsx's resolver (resolveTsPathsSync) keys its tsconfig-paths rewriting off the parent URL and treats parents undernode_modulesas external packages, skipping the rewrite. The routed request therefore resolves@deepseek-ai/dsh-toolsto the builtpackages/core/tools/lib/index.js, while in-tree imports (agent-loop etc.) resolve topackages/core/tools/src/index.ts. The package loads twice,TOOL_RUNTIME_SCHEDULER(aunique symbol) splits, andctx.tools[TOOL_RUNTIME_SCHEDULER]isundefined— hence the crash on every tool call.Fix (3-line change): canonicalize the fallback declarer (realpath) before using it as the native resolution parent, in the ESM and CJS fallback paths of
packages/boot/app-boot/src/profile-resolution/resolver.ts. Node realpaths parents internally, so default resolution results are unchanged; only the parent URL visible to loader hooks changes.Verification:
srcmodule's symbol wasundefined; after the fix all probed parents resolve tosrc/index.tsand the slot is populated.packages/boot/app-boot/tests/profile-resolution.spec.ts(spies the native resolver and asserts the canonical declarer parent; verified it fails without the fix).PRs are disabled on this repository, so the fix is available at:
https://github.com/jimmyfreecoding/deepseek-harness/commits/fix/profile-resolution-canonical-declarer
(commit
e522d99e47, cherry-pickable onto master)All reactions