| 86 | argsSchema = TaskArgs; |
| 87 | |
| 88 | async execute(args: z.infer<typeof TaskArgs>, ctx: ToolContext): Promise<ToolResult> { |
| 89 | if (!subAgentRunner) { |
| 90 | return { |
| 91 | content: '[SUBAGENT_DISABLED] Sub-agents are not enabled in this QodeX configuration. ' + |
| 92 | 'Run `qx setup` and select sequential or parallel sub-agent mode, or set ' + |
| 93 | 'subagents.mode: sequential in ~/.qodex/config.yaml.', |
| 94 | isError: true, |
| 95 | }; |
| 96 | } |
| 97 | |
| 98 | const maxIterations = args.max_iterations ?? 8; |
| 99 | const role = args.role; // undefined => default 'subagent' behavior; the runner resolves it |
| 100 | logger.info('Dispatching sub-agent', { |
| 101 | description: args.description, |
| 102 | maxIterations, |
| 103 | promptChars: args.prompt.length, |
| 104 | modelOverride: args.model ?? '(default)', |
| 105 | role: role ?? '(subagent)', |
| 106 | }); |
| 107 | |
| 108 | const subSessionId = `${ctx.sessionId}/sub-${Date.now()}`; |
| 109 | ctx.emit({ type: 'progress', message: `Sub-agent dispatched: ${args.description}${role ? ` [role: ${role}]` : ''}${args.model ? ` (model: ${args.model})` : ''}` }); |
| 110 | |
| 111 | const start = Date.now(); |
| 112 | const result = await subAgentRunner(args.prompt, { |
| 113 | maxIterations, |
| 114 | signal: ctx.signal, |
| 115 | sessionId: subSessionId, |
| 116 | modelOverride: args.model, |
| 117 | role, |
| 118 | }); |
| 119 | const elapsedSec = Math.round((Date.now() - start) / 1000); |
| 120 | |
| 121 | if (!result.ok) { |
| 122 | return { |
| 123 | content: |
| 124 | `[SUBAGENT_FAILED] Sub-agent "${args.description}" failed after ${result.toolCallsRun} tool call(s) in ${elapsedSec}s.\n` + |
| 125 | `Model: ${result.modelUsed ?? 'unknown'}\n` + |
| 126 | `Error: ${result.error ?? 'unknown'}\n` + |
| 127 | `Partial output:\n${result.finalText || '(none)'}`, |
| 128 | isError: true, |
| 129 | metadata: { subSessionId, toolCallsRun: result.toolCallsRun, elapsedSec, modelUsed: result.modelUsed }, |
| 130 | }; |
| 131 | } |
| 132 | |
| 133 | return { |
| 134 | content: |
| 135 | `[SUBAGENT_DONE] "${args.description}" — completed in ${result.toolCallsRun} tool call(s), ${elapsedSec}s` + |
| 136 | `${result.modelUsed ? ` (model: ${result.modelUsed})` : ''}\n\n` + |
| 137 | `--- Sub-agent summary ---\n${result.finalText}`, |
| 138 | metadata: { subSessionId, toolCallsRun: result.toolCallsRun, elapsedSec, ok: true, modelUsed: result.modelUsed }, |
| 139 | }; |
| 140 | } |
| 141 | } |