Replies: 1 comment
|
after deleting the dependencies and placing them into peerdependencies, this happened Error: dsh: plugin tree failed to load: failed to apply loader entry include (cordis:include): failed to import loader entry ui-deepseek-pet (@deepseek-ai/dsh-client-ui-deepseek-pet): Cannot find package '@deepseek-ai/dsh-client-ui-deepseek-pet' imported from C:\Users\chent.dsh\profiles\web Node.js v24.11.1 |
Uh oh!
There was an error while loading. Please reload this page.
Follow-up to #2078. After the version-skew reply and a full root-cause pass, we've revised our position:
Symbol.foris a defensive stopgap with side effects, not the fix. The crash isn't a bug in the code or a mistake by the author — it's two reasonable defaults colliding (private-identitySymbol()vs the npm-defaultdependencies), with nothing documenting, checking, or diagnosing the collision. The gap is three feedback loops that were never closed.Root-cause map and the three unclosed loops
The crash, restated
Two physical
@deepseek-ai/dsh-toolscopies → two module-localSymbol()keys →ctx.tools[TOOL_RUNTIME_SCHEDULER]isundefined→Cannot read properties of undefined (reading 'prepare').Two trade-offs colliding — not a bug in either place
Symbol()is a deliberate trade-off: private identity (safe and hidden) in exchange for failing hard when a duplicate exists. The crash is that trade-off's cost, delivered with a useless message.dependenciesis the author's reasonable default: "import X → dependencies" is the npm norm;peeris the exception, and that exception is never surfaced to third-party authors — the "never plain dependencies" rule lives only in aprofile.tssource comment, not inpublish.md.Neither choice is unreasonable. Two sensible defaults collide, and the collision was never documented, checked, or diagnosed — so each new author re-derives it the hard way (for us, ~a dozen isolated instances and five rounds of instrumentation).
Three feedback loops that were never closed
publish.mdshows a zero-dependency plugin; it never says "host packages must bepeerDependencies"dsh pluginis a bare pnpm forwarder; it silently accepts a plain@deepseek-ai/*dependencyundefined, not "two physical copies: one from the host, one from plugin X"The five ways a duplicate appears (and which loop catches each)
dependenciespnpm installin the profile* estimates from discussion frequency, not measurements.
Our revised position on
Symbol.for(self-correction)Symbol.formakes the key global so duplicates no longer crash. It's a stopgap with four side effects — semi-public key (breaks@internal), the key string frozen forever, cross-version copies silently cross-wire (the version-skew reply was right), and it removes the only signal (undefinedbecomes silent success / silent cross-wire). In a single-instance world preserved by relink + a check,Symbol()is strictly better. We still carry the change on our fork (fix/tool-runtime-scheduler-symbol), but now treat it as a local unblocker, not a proposal.Open for discussion — weighing the trade-offs, not requesting a patch
@deepseek-ai/*? Where's the line — and is it ever legitimate for a third-party plugin to pin a different host version?The community already covered the pieces
relinkHostPackages(relink profile copies to host)This post just assembles them into one map and opens the trade-off discussion.
All reactions