Replies: 2 comments 1 reply
|
Your mechanism is right: two copies of What I can add is the trigger, because it is narrower than "tsx's $ git show 9ddef327a4 --stat --format='%h %ci %s'
9ddef327a4 2026-09-17 20:08:51 +0800 feat: resolution mode link to runtime
apps/cli/src/profile-boot.ts | 2 +-
apps/desktop-host/src/index.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
- const resolutionMode = packaged ? 'runtime' : options.resolutionMode ?? 'link'
+ const resolutionMode = packaged ? 'runtime' : options.resolutionMode ?? 'runtime'It carries exactly one tag: Why that line is what puts two copies in one process
// :210 — which generation the profile's plugin rows resolve through
const resolution = resolutionMode === 'runtime' || resolvedProfile !== undefined
? await createProfileResolutionGeneration(resolutionOptions)
: await healProfilesModuleFallback(resolutionOptions)
// :312 — and whether that generation is enforced on the loader
await hostCtx.plugin(PluginPackages, resolutionMode === 'link' ? {} : {
generation: composed.resolution,
behavior: resolutionMode === 'dual' ? 'verify' : 'enforce',
})Under The part I would weigh most: the author reverted the other half themselves$ git show d9a55c7c0d --stat --format='%h %ci %s'
d9a55c7c0d 2026-09-17 20:47:27 +0800 fix: revert desktop
apps/desktop-host/src/index.ts | 2 +-Thirty-nine minutes after There is no escape hatch from the CLI
On the fixReverting The narrow fix for this specific failure is to make the key itself cross-plane: export const TOOL_RUNTIME_SCHEDULER: unique symbol = Symbol.for('@deepseek-ai/dsh-tools.scheduler')I checked whether that is sufficient or merely cosmetic, and for this key it is sufficient: The honest cost: that removes your symptom without restoring the invariant those two planes exist to hold (one package identity per process). Two module instances would remain, holding different code, so a version skew between Both of these are upstream changes. This is not mountable as a plugin: the dereference throws before any Finally, for the record on duplicates: |
|
Independent cross-check on macOS, plus the fix that is running in this tree. Environment: macOS arm64, Node v22.22.0, dsh 0.1.6-alpha.2 ( Reproduced from one directory - The keyless gate reproduces the failure end to end in ~2.5 s: Fix applied here, in the direction #7048 documents (two commits):
Verification: gate red -> green; One detail worth folding into the fix: per #7048, a source launch with no |
Uh oh!
There was an error while loading. Please reload this page.
Summary
Booting the CLI through its source entry (
pnpm dsh web, i.e.node --import tsx/esm apps/cli/src/bin.ts web) while a profile's plugin rows resolve throughnode_modulesto builtlib/puts two copies of@deepseek-ai/dsh-toolsin one process.TOOL_RUNTIME_SCHEDULERis a module-scopedunique symbolused as a lookup key, so each copy produces its own symbol: the agent loop holds one, the mountedtoolsservice carries the other, the lookup yieldsundefined, and every tool call ends its turn withCannot read properties of undefined (reading 'prepare'). Booting the built entry (node apps/cli/lib/bin.js web) resolves both sides tolib/and the failure disappears.Environment
90d2af322e(merged from tagdsh-v0.1.6-alpha.2)web, with local.mjsplugins in the profile directory that register tools throughdefineToolfrom@deepseek-ai/dsh-toolspackages/*/*/lib/index.jsnewer than its source) — this is not build stalenessReproduction
Both commands run from one directory,
packages/core/agent-loop, which depends on@deepseek-ai/dsh-toolsexactly as a profile plugin row does:The same probe is saved at
~/.gena/gerados/ferramentas/dsh-scheduler-identity-probe.mts(run it asnode --import tsx/esm <file> tsx/node <file> node).Current behavior
Under the source entry, the first tool call of a turn fails:
Observed twice in a real session (2026-09-19 02:20:39 and 02:31:28 CAT); the tool call never executed. The dereference site is
packages/core/agent-loop/src/tool-calls.ts:170:Expected behavior
A tool call issued through the source launch executes normally, exactly as it does through the built entry.
Root cause
TOOL_RUNTIME_SCHEDULERis exported frompackages/core/tools/src/index.ts(line 463) as aunique symboland carried as a property of the registry, so the loop and the service must share one module instance for the key to match.@deepseek-ai/dsh-*specifiers resolve throughtsconfig.base.jsonpathstopackages/*/*/src/index.ts; profile plugin rows are imported by resolved path and loadpackages/*/*/lib/.ctx.tools[TOOL_RUNTIME_SCHEDULER]isundefined.Why the test suite does not catch it
Unit tests run under vitest, where every workspace specifier resolves to
src/— one copy, one symbol. The failure only appears in a real boot that mixes the source and artifact planes.Workaround
Launch the built entry instead of the source entry:
Note that
README.md:41states "pnpm run buildprepares the repository artifacts.pnpm dsh webuses those built artifacts without rebuilding" — a rebuild is required after updating the monorepo either way.Suggested directions (not prescriptive)
pathsmapping instead ofnode_modules→lib/.UNKNOWN.Notes
--profile headless; the same condition applies whenever the CLI boots through tsx while its plugin rows resolve throughnode_modules.lib/artifacts (the composer and other UI components did not activate), then this symbol split. Both are resolved bydps-down && pnpm run build && dps-up.All reactions