Repository navigation
Replies: 4 comments
|
The remove-then-install window is real; HMR triggers it.
Workaround: run the update with HMR out of the picture. Without HMR, The structural part remains: a bundle patch that relies on a |
|
Thanks — that matches what we measured, and we ran the three-way test you suggested with the Setup: fresh isolated
So to answer your framing: this is not "this patch cannot survive any update". Both Two follow-ups:
If it helps, the concrete detector for case 2 is cheap: during the install, a duplicate-service |
|
These are roadmap questions; I can only give the code path.
Whether a delta apply, a documented "cold-update only" note, or returning What would make the report stronger: the Hand this to an AI assistant to draft the issue with that code included. |
|
Thanks for checking the code path. The error code in our recorded DSH The original The target installation reached the enable stage after the package operation succeeded. Reinstalling the previous version also reported the collision. The profile returned to The later I also need to correct my earlier “cheap detector” suggestion. I have consolidated the tested package, recorded results and source references into an issue-style draft, with those limits stated explicitly. Happy to test a candidate fix. |
Uh oh!
There was an error while loading. Please reload this page.
Environment
@deepseek-ai/dsh0.2.2-rc.1(npm-installed), Node24.22.1, pnpm12.8.1DSH_HOME, web profile created with--from-default-profile web(so
dsh-base+dsh-web-app; HMR enabled by default through thehmrrow)dsh-deeppilot@0.9.15dsh-deeppilot@0.9.16(published, declaresdsh.bundle,engines.dshcompatible)Reproduction
Install the plugin into the profile with
dsh plugin --profile <p> add dsh-deeppilot@0.9.15.The resulting
package.jsonholds a registry spec anddsh.profile.bundlesincludes the name,so
listBundles()marks itupdatable.The plugin's bundle patch (
cordis.patch.yml) does the following, because a phone client cannotinteract with a native OS picker rendered on the host:
Start
dsh <profile>. Confirm the plugin is active andhost.listDirectoryworks.Trigger an update through the public service:
pluginManager.updateBundle('dsh-deeppilot', '0.9.16', { registry, requestId }).(In our case the call is driven by a phone client over an authenticated WebSocket, but the
failure is entirely inside the host's plugin manager.)
Observed
pnpm add dsh-deeppilot@0.9.16succeeds.installBundlethen returns:{ "step": "install", "result": { "application": "failed", "stage": "enable", "error": { "code": "operation-error", "diagnostic": "dsh: warning: 1 entry did not activate\ndeeppilot-directory-picker-browse (@deepseek-ai/dsh-host-directory-picker-browse): Error: service \"directoryPicker\" has been registered at <NativeDirectoryPicker>" } }, "restore": { "application": "failed", "error": { "code": "operation-error", "diagnostic": "… same duplicate-service error …" } } }Net effect: the target version is installed, then removed; the previous version is re-installed;
the update is reported as a failure. Reproduced twice in two independent
DSH_HOMEs (differentvolumes, different
requestIds), so it is deterministic, not an environment artifact.Root cause (as far as we can tell from the shipped code)
dsh-web-appcomposes thedirectory-pickerrow as@deepseek-ai/dsh-host-directory-picker-auto. That plugin samples the host once at boot and mountsthe matching backend and client surface via
ctx.loader.create()into the in-memory root tree;its disposer removes both and awaits their fibers. On a local macOS host with a loopback bind it
chooses
native, soNativeDirectoryPickerregistersctx.directoryPicker.With HMR enabled,
updateBundleperformsremoveBundle(name)→installBundle(name@version).During the intermediate composition the bundle layer is gone, so the
disabled: truepatch ondirectory-pickerdisappears and-autore-activates, mounting the native backend. When thebundle layer is re-added, the inserted
-browserow tries to registerdirectoryPickerwhile thenative instance is still registered. Cordis rejects duplicate services, the host turns
"1 entry did not activate" into
application: 'failed', and the restore path hits the samecollision.
This matches the
-autopackage README ("Fixing an interaction is not a config field: compose-nativeor-browsedirectly in place of this row … mounting the selector together with abackend row explicitly errors, duplicate
directoryPickerservice"). The problem is that theupdate's two-step replace exposes a composition state that is never reachable on a cold boot.
Why it is not the package or the network
dsh plugin --profile <p> add dsh-deeppilot@0.9.16followed by a host restart starts cleanly(
serverVersion 0.9.16, all rows active,host.listDirectoryworks).listVersions('dsh-deeppilot')returnslistedwith the target compatible.checkphase ofupdateBundlepasses; only the online enable step fails.Suggested fix
Make the remove→install transition atomic with respect to composition: do not let lower-layer rows
re-activate in the intermediate state. For example, hold the outgoing bundle's patch layer until the
incoming one is installed, then compose the final tree once and hand it to HMR; or compute the final
composition first and only apply the delta. If an online replace is inherently unsupported for
bundles that replace a service row, it would help to detect that case and return
restart-requiredinstead offailed+ rollback.Verified workaround
Disabling the
hmrrow in the profile'scordis.patch.ymlmakesupdateBundletake the no-HMRbranch (install over the running version,
restart-required). With that change:host.listDirectorykeeps working (the browse backend stays mounted),applyreportsrestart-required, the profile ends up on0.9.16,0.9.16and the durable update journal resolves todone.So the whole self-update flow is functional; only the HMR online-replace path is affected.
Evidence available on request
plugin-managerpnpm logs for the remove/install/restore runs, the fullupdateBundlereturnobject, the composed config dump (
--dump-config), and the phone-side wire frames. Happy to attachredacted copies.
All reactions