From bdf5e39986717ccee3fa195eff22f09d65f2fa32 Mon Sep 17 00:00:00 2001 From: Yichen Jiang Date: Fri, 7 Aug 2026 14:25:35 +0800 Subject: [PATCH 1/2] fix(cli): give the shipped preset's todo tool its required config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit master made `allowParallelInProgress` a required field on dsh-tool-todo, so every composition must choose it. The base patch was updated with the field, but the Web surface takes `tool-todo` from the mounted preset instead, and that row carried no config — so the `standard` preset failed to mount and every session on the Web surface died at setup. Also make the preset tree's write test reach the override. Tearing the agent down stops in the loader's own "tree is being disposed" case before any write; a live row reconfiguring itself is the trigger that actually gets there. --- .../agent-presets/standard/agent.cordis.yml | 2 ++ .../tests/fixtures/plugins/contribute.js | 5 +++++ .../preset/agent-presets/tests/mount.spec.ts | 17 ++++++++++------- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/cli/config/agent-presets/standard/agent.cordis.yml b/apps/cli/config/agent-presets/standard/agent.cordis.yml index ec4f71a849..41d1d81a90 100644 --- a/apps/cli/config/agent-presets/standard/agent.cordis.yml +++ b/apps/cli/config/agent-presets/standard/agent.cordis.yml @@ -227,6 +227,8 @@ - id: tool-todo name: '@deepseek-ai/dsh-tool-todo' + config: + allowParallelInProgress: true # The `web` service and its search provider stay in the host composition; only # the model-facing tool is per-session. diff --git a/packages/preset/agent-presets/tests/fixtures/plugins/contribute.js b/packages/preset/agent-presets/tests/fixtures/plugins/contribute.js index b7b67be5d6..0d03277605 100644 --- a/packages/preset/agent-presets/tests/fixtures/plugins/contribute.js +++ b/packages/preset/agent-presets/tests/fixtures/plugins/contribute.js @@ -17,4 +17,9 @@ export function apply(ctx, config) { order: 10, text: `section for ${config.tool}`, })) + // Reconfiguring a live row runs the Loader's `internal/update` waterfall, + // which persists the owning tree. That is the trigger reaching the preset + // tree's `write` while the subtree is still mounted; tearing the agent down + // instead stops earlier, in the loader's own "tree is being disposed" case. + globalThis.__RECONFIGURE__ = tool => ctx.fiber.update({ ...config, tool }) } diff --git a/packages/preset/agent-presets/tests/mount.spec.ts b/packages/preset/agent-presets/tests/mount.spec.ts index 93b77d0047..fb3bfb6d8a 100644 --- a/packages/preset/agent-presets/tests/mount.spec.ts +++ b/packages/preset/agent-presets/tests/mount.spec.ts @@ -219,22 +219,25 @@ describe('a roster with nothing in it', () => { describe('attributing a service to a subtree', () => { it('never writes the preset file back, however the subtree changes', async () => { + delete (globalThis as { __RECONFIGURE__?: unknown }).__RECONFIGURE__ const handle = await ctx.agents.create({ sessionId: SessionId('sess-write'), setup: async (agentCtx: Context) => void await ctx.agentPresets.mount(agentCtx, 'standard'), }) - const [mount] = livePresetMounts().filter(entry => entry.presetId === 'standard') - expect(mount).toBeDefined() const file = join(FIXTURES, 'system', 'standard', 'agent.cordis.yml') const before = await readFile(file, 'utf8') - // The inherited `write()` persists the tree whenever the Loader thinks the - // config moved, and disposing an agent disposes its whole subtree — which - // is enough to trigger it. Inheriting that truncates the shipped preset to - // `[]` the first time a session ends. - await handle.dispose() + // The inherited `write()` persists the whole tree whenever the Loader + // decides a row's config moved, so one row reconfiguring itself would + // rewrite the shipped composition — here, with the row's new tool name. + const reconfigure = (globalThis as { __RECONFIGURE__?: (tool: string) => Promise }).__RECONFIGURE__ + expect(reconfigure).toBeTypeOf('function') + await reconfigure!('rewritten') + expect(toolNames(ctx, handle.agent)).toContain('rewritten') expect(await readFile(file, 'utf8')).toBe(before) + + await handle.dispose() }) it('attributes nothing to a subtree that is already torn down', async () => { From f1ac260a70ef2a1b7f997574a4d9a25474f8d460 Mon Sep 17 00:00:00 2001 From: Yichen Jiang Date: Fri, 7 Aug 2026 14:26:27 +0800 Subject: [PATCH 2/2] fix(cli): give the cordis preset's todo tool its required config Same required field as the standard preset: master made `allowParallelInProgress` mandatory on dsh-tool-todo, and a preset that names the row owns the choice. --- apps/cli/config/agent-presets/cordis/agent.cordis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/cli/config/agent-presets/cordis/agent.cordis.yml b/apps/cli/config/agent-presets/cordis/agent.cordis.yml index bf681dd0a8..d71e813905 100644 --- a/apps/cli/config/agent-presets/cordis/agent.cordis.yml +++ b/apps/cli/config/agent-presets/cordis/agent.cordis.yml @@ -221,6 +221,8 @@ - id: tool-todo name: '@deepseek-ai/dsh-tool-todo' + config: + allowParallelInProgress: true # The `web` service and its search provider stay in the host composition; only # the model-facing tool is per-session.