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:
@@ -288,8 +288,10 @@ export function apply(ctx: Context, config: Config): void {
|
||||
// The schema above tells the model to follow up with
|
||||
// `send_message`; starting a durable child the model cannot
|
||||
// continue would make that advertisement false. Sibling load order
|
||||
// is undetermined at mount, so the check lives at the operation.
|
||||
if (ctx.tools.get('send_message') === undefined) {
|
||||
// is undetermined at mount, so the check lives at the operation,
|
||||
// and it resolves in the CALLER's scope so a restriction that
|
||||
// removes send_message from this agent also blocks the start.
|
||||
if (ctx.tools.get('send_message', parent) === undefined) {
|
||||
throw new Error('continuable background subagents unavailable: load @deepseek-ai/dsh-tool-subagent-control (the advertised send_message tool is not registered)')
|
||||
}
|
||||
// The control service owns the durable child id, descriptor
|
||||
|
||||
@@ -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)', () => {
|
||||
|
||||
Reference in New Issue
Block a user