fix: address codex review round 2

- Wire the control service and send_message tool into every shipped
  composition with a resumable provider and background enabled
  (headless-agent, tui-agent, and the SDK helper's subagent feature
  base resources); jsonrpc-agent disables background and is unchanged.
- Resolve the send_message availability check in the CALLER's tool
  scope so a restriction that removes the follow-up tool from one
  agent also blocks that agent's continuable start.
- Control-service disposal now cancels live activations and awaits
  producer settlement instead of stranding them: TaskService keeps
  producer Tasks across a reload, so the disposing service aborts each
  activation-owned controller, resolves its terminal gate (the
  effect-scoped onTaskDone listener is already gone), and awaits done.
  A new test kills a mid-start activation through HMR disposal.
This commit is contained in:
Dudu-0223
2026-07-23 18:14:37 +08:00
committed by imccyu
parent 71570d7bec
commit 4eda48d002
12 changed files with 136 additions and 9 deletions

View File

@@ -903,6 +903,22 @@ describe('dsh-tool-subagent continuable background mode', () => {
// Nothing was started: no Task exists for the parent.
expect(ctx.tasks.list(parent)).toEqual([])
})
it('resolves send_message availability in the CALLER scope, not the global registry', async () => {
// A scoped restriction that keeps this delegation tool but removes
// send_message means this agent cannot execute the promised follow-up;
// the availability check must see the caller's surface.
const { ctx, parent } = await continuableSetup()
parent.ctx.tools.restrict({ deny: ['send_message'] })
const result = await callSubagent(
ctx,
{ description: 'd', prompt: 'p', run_in_background: true },
{ agent: parent },
)
expect(result.isError).toBe(true)
expect(text(result)).toContain('load @deepseek-ai/dsh-tool-subagent-control')
expect(ctx.tasks.list(parent)).toEqual([])
})
})
describe('background preflight failure (no orphaned child, by construction)', () => {