- AgentCapabilitiesSchema with supportsStreaming/Reasoning/Background flags - supportsStreaming and supportsReasoningStream fields in ProviderSnapshotEntry - new_task tool: background mode flag for non-blocking subtask dispatch
72 lines
2.9 KiB
TypeScript
72 lines
2.9 KiB
TypeScript
import { z } from 'zod';
|
|
import type { ToolDef, ToolContext } from './types.js';
|
|
import { getInferenceContext } from './inference_context.js';
|
|
|
|
const NewTaskInput = z.object({
|
|
input: z.string().min(1).describe('Task description for the child subtask'),
|
|
agent: z.string().optional().describe('Optional: dispatch to a specific agent'),
|
|
model: z.string().optional().describe('Optional: model override for the subtask'),
|
|
background: z.boolean().optional().describe('If true, return immediately without blocking on completion'),
|
|
});
|
|
|
|
type NewTaskInputT = z.infer<typeof NewTaskInput>;
|
|
|
|
export const newTaskTool: ToolDef<NewTaskInputT> = {
|
|
name: 'new_task',
|
|
description:
|
|
'Spawn a subtask that runs in isolation. The subtask gets its own session and ' +
|
|
'worktree. Use check_task_status to monitor progress. Only the output_summary is ' +
|
|
'accessible to the parent — full isolation (Boomerang pattern).',
|
|
inputSchema: NewTaskInput,
|
|
jsonSchema: {
|
|
type: 'function',
|
|
function: {
|
|
name: 'new_task',
|
|
description:
|
|
'Spawn a subtask that runs in isolation. The subtask gets its own session and ' +
|
|
'worktree. Use check_task_status to monitor progress.',
|
|
parameters: {
|
|
type: 'object',
|
|
properties: {
|
|
input: { type: 'string', description: 'Task description for the child subtask' },
|
|
agent: { type: 'string', description: 'Optional: dispatch to a specific agent' },
|
|
model: { type: 'string', description: 'Optional: model override for the subtask' },
|
|
background: { type: 'boolean', description: 'If true, returns immediately without waiting' },
|
|
},
|
|
required: ['input'],
|
|
},
|
|
},
|
|
},
|
|
|
|
async execute(input: NewTaskInputT, _projectRoot: string, context: ToolContext): Promise<unknown> {
|
|
const { sql } = context;
|
|
// Get the current task's project_id from the inference context
|
|
const ctx = getInferenceContext();
|
|
const currentTaskId = ctx.taskId;
|
|
|
|
// Look up the project_id from the current session
|
|
const [session] = await sql<{ project_id: string }[]>`
|
|
SELECT project_id FROM sessions WHERE id = ${ctx.sessionId}
|
|
`;
|
|
if (!session) {
|
|
return { error: 'Cannot determine project_id from current session' };
|
|
}
|
|
|
|
const isBg = input.background === true;
|
|
const [task] = await sql<{ id: string; state: string }[]>`
|
|
INSERT INTO tasks (project_id, parent_task_id, input, agent, model)
|
|
VALUES (${session.project_id}, ${currentTaskId}, ${input.input}, ${input.agent ?? null}, ${input.model ?? null})
|
|
RETURNING id, state
|
|
`;
|
|
|
|
return {
|
|
message: isBg
|
|
? `Background subtask created (id: ${task!.id}). It will continue independently.`
|
|
: `Subtask created (id: ${task!.id}). It will run in isolation. Use check_task_status to monitor.`,
|
|
task_id: task!.id,
|
|
state: task!.state,
|
|
background: isBg,
|
|
};
|
|
},
|
|
};
|