Repository navigation
Replies: 1 comment
SummaryIn a host plugin, calling Environment
Observed behaviorAfter a plugin-driven prompt, the session's tool panel reports: Added (host-level tools registered by the plugin): Removed (core tools previously available in the same session): After this event the model cannot call Minimal reproduction (our steps)
Notes on scope:
Workaround we are shippingStop calling await ctx.sessionController.prompt({ sessionId, requestId, mode: "queue", content }, signal)Set the model once, only for sessions the plugin itself creates. Consequence: a session with no stored model selection fails its first prompt with: so sessions must be created with a model default present (UI-created sessions are). After removing Questions
Related
Happy to provide the plugin source or a minimal Cordis bundle that reproduces step 2 if that helps. Cross-reference: same symptom as the original report, but triggered by sessionController.selectModel() re-composition rather than resume alone. |
Uh oh!
There was an error while loading. Please reload this page.
On session resume, the tool registry silently drops every core tool (48→19)
Same family as #9998. That report describes a 40→13 degradation after a mid-turn crash + model continuation; this is an independent reproduction on a different trigger (host restart → session resume) at
0.2.1-rc.2, with thetool-registrydiff itself captured in the event log.Environment
@deepseek-ai/dsh0.2.1-rc.2 (installed 10-19, never upgraded)dsh webunder systemd (ExecStart=dsh web --host 127.0.0.1 --port 7362)dsh-base,dsh-web-app,@xmanrui/dsh-im,meow-memory,billion-context@0.1.201,dsh-bili-whale,dsh-draw-toolbili-whale, 66 turns, 3700+ events)Symptom
After a
systemctl restart dsh-web, the first model request of the resumed session carries 19 tools instead of 48. The 30 missing ones are exactly the host's built-in tool family:The 19 that survive are every tool contributed by a plugin, plus
working_directory:acp_cache,acp_read_original_image,acp_status,compress,decompress,search_contextdsh_im_group_file,dsh_im_group_history,dsh_im_return_filememory_dream,memory_find_similar,memory_home,memory_project,memory_read,memory_remember,memory_search,memory_updatedraw_pictureworking_directoryThe model then calls
bashand getsunknown tool "bash"; the session is blinded for the rest of its life. Removing the third-party plugin and restarting recovers 43 tools (the 30 built-ins come back, the plugin's 6 leave).Direct evidence: the registry diff is in the session log
At the exact second of the bad request, the event stream (
session.v4.jsonl.zstd, 2074 zstd frames) contains:The
developer/messageat seq 2790 is the harness itself declaring the change:{ "source": { "kind": "tool-registry" }, "content": [ { "type": "tool-addition", "toolName": "draw_picture" }, { "type": "tool-removal", "toolName": "ask_user_question" }, { "type": "tool-removal", "toolName": "bash" }, { "type": "tool-removal", "toolName": "create_goal" }, ... 27 more tool-removals ... { "type": "tool-removal", "toolName": "write" } ] }add = 1(a plugin tool),remove = 30(every built-in). On the recovery restart (17:22:47, after removing the third-party plugin) the same mechanism runs in reverse:So the registry knows exactly which tools belong to which contributor — it just computed an "expected set" that did not include the host's built-ins.
The system prompt shrinks consistently with the tool list
system/messageat 12:08 is 6261 chars / 128 lines; at 17:22 (healthy, 43 tools) it is 9123 chars / 154 lines. Line-by-line, the degraded prompt is a strict subset of the healthy one — zero lines exist only in the degraded version. The 13 missing lines are exclusively built-in tool usage guidance:The persona / memory / role sections are byte-identical.
request/headercarries the sameconfigin all 10 captured requests:provider=deepseek-account, model=deepseek-flash, reasoningEffort=low, maxTokens=256000.⇒ This is not a model switch, not an agent-preset switch, and not a different profile.
Relation to #9998
0.2.1-alpha.40.2.1-rc.2systemctl restart+ session resumebash/read/write/edit/glob/grep/web_*/goal/job/schedule/present/skill/todo/workflowrequest/header.toolsonlyrequest/header+session/end-seed+ thetool-registrydiffThe hypothesis in #9998 — "the tool registry is assembled from several contributors; on the crash-recovery / resume path only a subset of contributors re-registers" — is consistent with everything observed here, and the
developer/messageabove makes the partial-rebuild step directly visible. The one difference worth noting: in #9998 the survivors were the agent-team layer; here they are third-party plugin contributors. In both cases the survivor set is "everything that re-registers through its own mount", and the casualty set is "everything contributed by the preset/base layer".Related reports — the same wiring area
All of these are about the registry being mutated or re-mounted outside a clean full rebuild:
"already registered"when a profile bundle and the session preset mount the same plugins. Resume-path re-mounting, different failure mode (throws instead of silently dropping).tool_additionblocks in a non-system message → permanent400 INVALID_REQUEST.400(tool_additionblocks can only be insystemmessages).400:tool_additionblocks serialized into a system-role message insidemessages[].deferLoading: a session whose baseline tool is replaced ends up with an all-deferred tool array and a permanent400.deferLoadinghides tools that have no activation channel.#10553 / #10547 / #10760 use the very same
tool_addition/tool_removalmechanism that produced thedeveloper/messageabove. Taken together with #9998 and #10545, the resume / mid-session registry-rebuild path looks like a known-shape weak spot: partial contributor rebuild (this report, #9998), duplicate mount on resume (#10545), and block-placement corruption when the registry changes mid-conversation (#10553/#10547/#10760/#8683).Not caused by the third-party plugin
The plugin in the mix (
billion-context@0.1.201) was audited at source level and only calls the additive API:ctx.tools.register(def)(src/agent/dsh-native.ts:874), purely incremental;unregister/remove/clear/rebuild/replacecalls anywhere in the package;0.1.201for the whole window (all 20acp-proxy v…startup lines in its log), and its self-update is correctly skipped because the install dir is managed by dsh;The producer is identified by the harness's own
developer/message: the registry decided the 30 built-ins were gone.Reproduction
plugins:list contributes the built-in tool family.systemctl restart dsh-web(or any path that re-seeds the session — the log showssession/end-seed).reason = "resume".request/header.tools— built-ins missing, only plugin-contributed tools +working_directoryremain.developer/messagewithsource.kind = "tool-registry"lists the removals.Trigger appears racy — it did not happen on every restart (7 restarts over 3 days were clean; the 8th was not). A fast double
stop/start(03:08:16→03:08:44, 28s apart) is present in the history and may widen the window.Suggested fix direction
resume/end-seed, force a full registry rebuild across all contributors, or reuse the same full-rebuild path used for a normal turn.UNKNOWN_TOOL.request/header.toolsequals the pre-restart set.Attachments
Redacted raw JSON (the two
developer/messageevents,session/end-seed, and bothrequest/headerpayloads with tool descriptions stripped): https://gist.github.com/GOOGLE-GD/9367b873461b717c1432a0ad46baf53cHappy to provide further log excerpts.
Originally triaged at ranxianglei/billion-context#4286 (ranxianglei/billion-context#4286) — a third-party plugin was in the profile and is the trigger, but the tool-registry evidence above points at the harness side.
All reactions