refactor(core): rename TaskTool to AgentTool

Rename the Task tool to Agent tool for clearer semantics and better
alignment with industry terminology. This change includes:

- Rename TaskTool -> AgentTool, TaskParams -> AgentParams
- Rename TaskResultDisplay -> AgentResultDisplay
- Add 'Explore' built-in agent for read-only codebase exploration
- Add backward compatibility mappings for legacy tool names
- Improve Agent tool description with clearer usage guidelines
- Add case-insensitive agent name matching
- Fallback to built-in agents when subagent loading fails

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
tanzhenxin 2026-03-19 14:55:14 +08:00
parent 27356c1bac
commit 8891f4219d
37 changed files with 433 additions and 323 deletions

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import type { ChatRecord, TaskResultDisplay } from '@qwen-code/qwen-code-core';
import type { ChatRecord, AgentResultDisplay } from '@qwen-code/qwen-code-core';
import type {
Content,
GenerateContentResponseUsageMetadata,
@ -165,16 +165,16 @@ export class HistoryReplayer {
(resultDisplay as { type?: unknown }).type === 'task_execution'
) {
await this.emitTaskUsageFromResultDisplay(
resultDisplay as TaskResultDisplay,
resultDisplay as AgentResultDisplay,
);
}
}
/**
* Emits token usage from a TaskResultDisplay execution summary, if present.
* Emits token usage from a AgentResultDisplay execution summary, if present.
*/
private async emitTaskUsageFromResultDisplay(
resultDisplay: TaskResultDisplay,
resultDisplay: AgentResultDisplay,
): Promise<void> {
const summary = resultDisplay.executionSummary;
if (!summary) {

View file

@ -29,7 +29,7 @@ import {
logToolCall,
logUserPrompt,
getErrorStatus,
TaskTool,
AgentTool,
UserPromptEvent,
TodoWriteTool,
ExitPlanModeTool,
@ -517,7 +517,7 @@ export class Session implements SessionContext {
// Detect TodoWriteTool early - route to plan updates instead of tool_call events
const isTodoWriteTool = tool.name === TodoWriteTool.Name;
const isTaskTool = tool.name === TaskTool.Name;
const isAgentTool = tool.name === AgentTool.Name;
const isExitPlanModeTool = tool.name === ExitPlanModeTool.Name;
// Track cleanup functions for sub-agent event listeners
@ -526,15 +526,15 @@ export class Session implements SessionContext {
try {
const invocation = tool.build(args);
if (isTaskTool && 'eventEmitter' in invocation) {
// Access eventEmitter from TaskTool invocation
if (isAgentTool && 'eventEmitter' in invocation) {
// Access eventEmitter from AgentTool invocation
const taskEventEmitter = (
invocation as {
eventEmitter: AgentEventEmitter;
}
).eventEmitter;
// Extract subagent metadata from TaskTool call
// Extract subagent metadata from AgentTool call
const parentToolCallId = callId;
const subagentType = (args['subagent_type'] as string) ?? '';

View file

@ -65,7 +65,7 @@ const basicPermissionOptions: readonly PermissionOptionConfig[] = [
] as const;
/**
* Tracks and emits events for sub-agent tool calls within TaskTool execution.
* Tracks and emits events for sub-agent tool calls within AgentTool execution.
*
* Uses the unified ToolCallEmitter for consistency with normal flow
* and history replay. Also handles permission requests for tools that
@ -106,7 +106,7 @@ export class SubAgentTracker {
/**
* Sets up event listeners for a sub-agent's tool events.
*
* @param eventEmitter - The AgentEventEmitter from TaskTool
* @param eventEmitter - The AgentEventEmitter from AgentTool
* @param abortSignal - Signal to abort tracking if parent is cancelled
* @returns Array of cleanup functions to remove listeners
*/

View file

@ -225,7 +225,13 @@ export class ToolCallEmitter extends BaseEmitter {
// Pass tool name to handle special cases like exit_plan_mode -> switch_mode
kind = this.mapToolKind(tool.kind, toolName);
} catch {
// Use defaults on build failure
// Fallback: use the description arg directly if available
if (typeof args['description'] === 'string') {
title = `${title}: ${args['description']}`;
}
if (tool.kind) {
kind = this.mapToolKind(tool.kind, toolName);
}
}
}

View file

@ -35,9 +35,9 @@ export interface SessionContext extends SessionUpdateSender {
* Subagent metadata for tracking parent tool call context.
*/
export interface SubagentMeta {
/** ID of the parent TaskTool call that created this subagent */
/** ID of the parent AgentTool call that created this subagent */
parentToolCallId?: string;
/** Type of subagent (from TaskParams.subagent_type) */
/** Type of subagent (from AgentParams.subagent_type) */
subagentType?: string;
}

View file

@ -10,7 +10,7 @@ import {
type Config,
type ServerGeminiStreamEvent,
type ToolCallRequestInfo,
type TaskResultDisplay,
type AgentResultDisplay,
} from '@qwen-code/qwen-code-core';
import type { Part, GenerateContentResponseUsageMetadata } from '@google/genai';
import type {
@ -144,7 +144,7 @@ class TestJsonOutputAdapter extends BaseJsonOutputAdapter {
exposeCreateSubagentToolUseBlock(
state: MessageState,
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
parentToolUseId: string,
) {
return this.createSubagentToolUseBlock(state, toolCall, parentToolUseId);
@ -1314,7 +1314,7 @@ describe('BaseJsonOutputAdapter', () => {
it('should process subagent tool call', () => {
const parentToolUseId = 'parent-tool-1';
adapter.startSubagentAssistantMessage(parentToolUseId);
const toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number] = {
const toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number] = {
callId: 'tool-1',
name: 'test_tool',
args: { param: 'value' },
@ -1346,7 +1346,7 @@ describe('BaseJsonOutputAdapter', () => {
const state = adapter.exposeGetMessageState(parentToolUseId);
adapter.exposeAppendText(state, 'Text', parentToolUseId);
const toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number] = {
const toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number] = {
callId: 'tool-1',
name: 'test_tool',
args: {},
@ -1367,7 +1367,7 @@ describe('BaseJsonOutputAdapter', () => {
it('should create tool_use block for subagent', () => {
const state = adapter.exposeCreateMessageState();
adapter.startAssistantMessage();
const toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number] = {
const toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number] = {
callId: 'tool-1',
name: 'test_tool',
args: { param: 'value' },

View file

@ -11,7 +11,7 @@ import type {
ToolCallResponseInfo,
SessionMetrics,
ServerGeminiStreamEvent,
TaskResultDisplay,
AgentResultDisplay,
McpToolProgressData,
} from '@qwen-code/qwen-code-core';
import {
@ -110,7 +110,7 @@ export interface JsonOutputAdapterInterface extends MessageEmitter {
startSubagentAssistantMessage?(parentToolUseId: string): void;
processSubagentToolCall?(
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
parentToolUseId: string,
): void;
finalizeSubagentAssistantMessage?(
@ -693,7 +693,7 @@ export abstract class BaseJsonOutputAdapter {
* @param parentToolUseId - Parent tool use ID
*/
processSubagentToolCall(
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
parentToolUseId: string,
): void {
const state = this.getMessageState(parentToolUseId);
@ -744,7 +744,7 @@ export abstract class BaseJsonOutputAdapter {
protected processSubagentToolUseBlock(
state: MessageState,
index: number,
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
parentToolUseId: string,
): void {
// Emit tool_use block creation event (with empty input)
@ -937,7 +937,7 @@ export abstract class BaseJsonOutputAdapter {
*/
protected createSubagentToolUseBlock(
state: MessageState,
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
_parentToolUseId: string,
): { block: ToolUseBlock; index: number } {
const index = state.blocks.length;

View file

@ -43,7 +43,7 @@ import {
extractPartsFromUserMessage,
buildSystemMessage,
createToolProgressHandler,
createTaskToolProgressHandler,
createAgentToolProgressHandler,
computeUsageFromMetrics,
} from './utils/nonInteractiveHelpers.js';
@ -320,12 +320,12 @@ export async function runNonInteractive(
: undefined;
// Build outputUpdateHandler for this tool call.
// Task tool has its own complex handler (subagent messages).
// Agent tool has its own complex handler (subagent messages).
// All other tools with canUpdateOutput=true (e.g., MCP tools)
// get a generic handler that emits progress via the adapter.
const isTaskTool = finalRequestInfo.name === 'task';
const { handler: outputUpdateHandler } = isTaskTool
? createTaskToolProgressHandler(
const isAgentTool = finalRequestInfo.name === 'agent';
const { handler: outputUpdateHandler } = isAgentTool
? createAgentToolProgressHandler(
config,
finalRequestInfo.callId,
adapter,

View file

@ -268,7 +268,7 @@ describe('AppContainer State Management', () => {
// Mock config's getTargetDir to return consistent workspace directory
vi.spyOn(mockConfig, 'getTargetDir').mockReturnValue('/test/workspace');
// Mock GeminiClient to prevent unhandled errors from TaskTool.refreshSubagents
// Mock GeminiClient to prevent unhandled errors from AgentTool.refreshSubagents
const mockGeminiClient: Partial<GeminiClient> = {
initialize: vi.fn().mockResolvedValue(undefined),
setTools: vi.fn().mockResolvedValue(undefined),
@ -278,7 +278,7 @@ describe('AppContainer State Management', () => {
mockGeminiClient as GeminiClient,
);
// Mock SubagentManager to prevent errors during TaskTool initialization
// Mock SubagentManager to prevent errors during AgentTool initialization
const mockSubagentManager: Partial<SubagentManager> = {
listSubagents: vi.fn().mockResolvedValue([]),
addChangeListener: vi.fn(),

View file

@ -16,7 +16,7 @@ import { MaxSizedBox } from '../shared/MaxSizedBox.js';
import { TodoDisplay } from '../TodoDisplay.js';
import type {
TodoResultDisplay,
TaskResultDisplay,
AgentResultDisplay,
PlanResultDisplay,
AnsiOutput,
Config,
@ -50,7 +50,7 @@ type DisplayRendererResult =
| { type: 'plan'; data: PlanResultDisplay }
| { type: 'string'; data: string }
| { type: 'diff'; data: { fileDiff: string; fileName: string } }
| { type: 'task'; data: TaskResultDisplay }
| { type: 'task'; data: AgentResultDisplay }
| { type: 'ansi'; data: AnsiOutput };
/**
@ -98,7 +98,7 @@ const useResultDisplayRenderer = (
) {
return {
type: 'task',
data: resultDisplay as TaskResultDisplay,
data: resultDisplay as AgentResultDisplay,
};
}
@ -169,7 +169,7 @@ const PlanResultRenderer: React.FC<{
* Component to render subagent execution results
*/
const SubagentExecutionRenderer: React.FC<{
data: TaskResultDisplay;
data: AgentResultDisplay;
availableHeight?: number;
childWidth: number;
config: Config;

View file

@ -7,7 +7,7 @@
import React, { useMemo } from 'react';
import { Box, Text } from 'ink';
import type {
TaskResultDisplay,
AgentResultDisplay,
AgentStatsSummary,
Config,
} from '@qwen-code/qwen-code-core';
@ -20,7 +20,7 @@ import { ToolConfirmationMessage } from '../../messages/ToolConfirmationMessage.
export type DisplayMode = 'compact' | 'default' | 'verbose';
export interface AgentExecutionDisplayProps {
data: TaskResultDisplay;
data: AgentResultDisplay;
availableHeight?: number;
childWidth: number;
config: Config;
@ -28,7 +28,7 @@ export interface AgentExecutionDisplayProps {
const getStatusColor = (
status:
| TaskResultDisplay['status']
| AgentResultDisplay['status']
| 'executing'
| 'success'
| 'awaiting_approval',
@ -50,7 +50,7 @@ const getStatusColor = (
}
};
const getStatusText = (status: TaskResultDisplay['status']) => {
const getStatusText = (status: AgentResultDisplay['status']) => {
switch (status) {
case 'running':
return 'Running';
@ -301,7 +301,7 @@ const TaskPromptSection: React.FC<{
* Status dot component with similar height as text
*/
const StatusDot: React.FC<{
status: TaskResultDisplay['status'];
status: AgentResultDisplay['status'];
}> = ({ status }) => (
<Box marginLeft={1} marginRight={1}>
<Text color={getStatusColor(status)}></Text>
@ -312,7 +312,7 @@ const StatusDot: React.FC<{
* Status indicator component
*/
const StatusIndicator: React.FC<{
status: TaskResultDisplay['status'];
status: AgentResultDisplay['status'];
}> = ({ status }) => {
const color = getStatusColor(status);
const text = getStatusText(status);
@ -323,7 +323,7 @@ const StatusIndicator: React.FC<{
* Tool calls list - format consistent with ToolInfo in ToolMessage.tsx
*/
const ToolCallsList: React.FC<{
toolCalls: TaskResultDisplay['toolCalls'];
toolCalls: AgentResultDisplay['toolCalls'];
displayMode: DisplayMode;
}> = ({ toolCalls, displayMode }) => {
const calls = toolCalls || [];
@ -435,7 +435,7 @@ const ToolCallItem: React.FC<{
* Execution summary details component
*/
const ExecutionSummaryDetails: React.FC<{
data: TaskResultDisplay;
data: AgentResultDisplay;
displayMode: DisplayMode;
}> = ({ data, displayMode: _displayMode }) => {
const stats = data.executionSummary;
@ -505,7 +505,7 @@ const ToolUsageStats: React.FC<{
* Results section for completed executions - matches the clean layout from the image
*/
const ResultsSection: React.FC<{
data: TaskResultDisplay;
data: AgentResultDisplay;
displayMode: DisplayMode;
}> = ({ data, displayMode }) => (
<Box flexDirection="column" gap={1}>

View file

@ -100,6 +100,10 @@ function formatToolDescription(
const invocation = tool.build(args);
return invocation.getDescription();
} catch {
// Fallback: use the description arg directly if available
if (typeof args['description'] === 'string') {
return args['description'];
}
return '';
}
}

View file

@ -8,7 +8,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest';
import type {
Config,
SessionMetrics,
TaskResultDisplay,
AgentResultDisplay,
ToolCallResponseInfo,
} from '@qwen-code/qwen-code-core';
import {
@ -30,7 +30,7 @@ import {
computeUsageFromMetrics,
buildSystemMessage,
createToolProgressHandler,
createTaskToolProgressHandler,
createAgentToolProgressHandler,
functionResponsePartsToString,
toolResultContent,
} from './nonInteractiveHelpers.js';
@ -731,7 +731,7 @@ describe('createToolProgressHandler', () => {
});
});
describe('createTaskToolProgressHandler', () => {
describe('createAgentToolProgressHandler', () => {
let mockAdapter: JsonOutputAdapterInterface;
let mockConfig: Config;
@ -751,13 +751,13 @@ describe('createTaskToolProgressHandler', () => {
});
it('should create handler that processes task tool calls', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
const taskDisplay: TaskResultDisplay = {
const taskDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -786,13 +786,13 @@ describe('createTaskToolProgressHandler', () => {
});
it('should emit tool_result when tool call completes', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
const taskDisplay: TaskResultDisplay = {
const taskDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -825,13 +825,13 @@ describe('createTaskToolProgressHandler', () => {
});
it('should not duplicate tool_use emissions', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
const taskDisplay: TaskResultDisplay = {
const taskDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -855,13 +855,13 @@ describe('createTaskToolProgressHandler', () => {
});
it('should not duplicate tool_result emissions', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
const taskDisplay: TaskResultDisplay = {
const taskDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -886,14 +886,14 @@ describe('createTaskToolProgressHandler', () => {
});
it('should handle status transitions from executing to completed', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
// First: executing state
const executingDisplay: TaskResultDisplay = {
const executingDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -910,7 +910,7 @@ describe('createTaskToolProgressHandler', () => {
};
// Second: completed state
const completedDisplay: TaskResultDisplay = {
const completedDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -935,13 +935,13 @@ describe('createTaskToolProgressHandler', () => {
});
it('should emit error result for failed task status', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
const runningDisplay: TaskResultDisplay = {
const runningDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -950,7 +950,7 @@ describe('createTaskToolProgressHandler', () => {
toolCalls: [],
};
const failedDisplay: TaskResultDisplay = {
const failedDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -971,13 +971,13 @@ describe('createTaskToolProgressHandler', () => {
});
it('should emit error result for cancelled task status', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
const runningDisplay: TaskResultDisplay = {
const runningDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -986,7 +986,7 @@ describe('createTaskToolProgressHandler', () => {
toolCalls: [],
};
const cancelledDisplay: TaskResultDisplay = {
const cancelledDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -1006,7 +1006,7 @@ describe('createTaskToolProgressHandler', () => {
});
it('should not process non-task-execution displays', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
@ -1017,20 +1017,20 @@ describe('createTaskToolProgressHandler', () => {
content: 'some content',
};
handler('call-id', nonTaskDisplay as unknown as TaskResultDisplay);
handler('call-id', nonTaskDisplay as unknown as AgentResultDisplay);
expect(mockAdapter.processSubagentToolCall).not.toHaveBeenCalled();
expect(mockAdapter.emitToolResult).not.toHaveBeenCalled();
});
it('should handle tool calls with failed status', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
const taskDisplay: TaskResultDisplay = {
const taskDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -1061,13 +1061,13 @@ describe('createTaskToolProgressHandler', () => {
});
it('should handle tool calls without result content', () => {
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
mockAdapter,
);
const taskDisplay: TaskResultDisplay = {
const taskDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',
@ -1096,13 +1096,13 @@ describe('createTaskToolProgressHandler', () => {
emitToolResult: vi.fn(),
} as unknown as JsonOutputAdapterInterface;
const { handler } = createTaskToolProgressHandler(
const { handler } = createAgentToolProgressHandler(
mockConfig,
'parent-tool-id',
limitedAdapter,
);
const taskDisplay: TaskResultDisplay = {
const taskDisplay: AgentResultDisplay = {
type: 'task_execution',
subagentName: 'test-agent',
taskDescription: 'Test task',

View file

@ -7,7 +7,7 @@
import type {
Config,
ToolResultDisplay,
TaskResultDisplay,
AgentResultDisplay,
OutputUpdateHandler,
ToolCallRequestInfo,
ToolCallResponseInfo,
@ -335,25 +335,25 @@ export function createToolProgressHandler(
}
/**
* Creates an output update handler specifically for Task tool subagent execution.
* This handler monitors TaskResultDisplay updates and converts them to protocol messages
* Creates an output update handler specifically for Agent tool subagent execution.
* This handler monitors AgentResultDisplay updates and converts them to protocol messages
* using the unified adapter's subagent APIs. All emitted messages will have parent_tool_use_id set to
* the task tool's callId.
* the agent tool's callId.
*
* @param config - Config instance for getting output format
* @param taskToolCallId - The task tool's callId to use as parent_tool_use_id for all subagent messages
* @param agentToolCallId - The agent tool's callId to use as parent_tool_use_id for all subagent messages
* @param adapter - The unified adapter instance (JsonOutputAdapter or StreamJsonOutputAdapter)
* @returns An object containing the output update handler
*/
export function createTaskToolProgressHandler(
export function createAgentToolProgressHandler(
config: Config,
taskToolCallId: string,
agentToolCallId: string,
adapter: JsonOutputAdapterInterface,
): {
handler: OutputUpdateHandler;
} {
// Track previous TaskResultDisplay states per tool call to detect changes
const previousTaskStates = new Map<string, TaskResultDisplay>();
// Track previous AgentResultDisplay states per tool call to detect changes
const previousTaskStates = new Map<string, AgentResultDisplay>();
// Track which tool call IDs have already emitted tool_use to prevent duplicates
const emittedToolUseIds = new Set<string>();
// Track which tool call IDs have already emitted tool_result to prevent duplicates
@ -366,7 +366,7 @@ export function createTaskToolProgressHandler(
* @returns ToolCallRequestInfo object
*/
const buildRequest = (
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
): ToolCallRequestInfo => ({
callId: toolCall.callId,
name: toolCall.name,
@ -383,7 +383,7 @@ export function createTaskToolProgressHandler(
* @returns ToolCallResponseInfo object
*/
const buildResponse = (
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
): ToolCallResponseInfo => ({
callId: toolCall.callId,
error:
@ -403,7 +403,7 @@ export function createTaskToolProgressHandler(
* @returns True if the tool call has result content to emit
*/
const hasResultContent = (
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
): boolean => {
// Check resultDisplay string
if (
@ -429,14 +429,14 @@ export function createTaskToolProgressHandler(
* @param fallbackStatus - Optional fallback status if toolCall.status should be overridden
*/
const emitToolUseIfNeeded = (
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
fallbackStatus?: 'executing' | 'awaiting_approval',
): void => {
if (emittedToolUseIds.has(toolCall.callId)) {
return;
}
const toolCallToEmit: NonNullable<TaskResultDisplay['toolCalls']>[number] =
const toolCallToEmit: NonNullable<AgentResultDisplay['toolCalls']>[number] =
fallbackStatus
? {
...toolCall,
@ -449,7 +449,7 @@ export function createTaskToolProgressHandler(
toolCallToEmit.status === 'awaiting_approval'
) {
if (adapter.processSubagentToolCall) {
adapter.processSubagentToolCall(toolCallToEmit, taskToolCallId);
adapter.processSubagentToolCall(toolCallToEmit, agentToolCallId);
emittedToolUseIds.add(toolCall.callId);
}
}
@ -461,7 +461,7 @@ export function createTaskToolProgressHandler(
* @param toolCall - The tool call information
*/
const emitToolResultIfNeeded = (
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
): void => {
if (emittedToolResultIds.has(toolCall.callId)) {
return;
@ -482,7 +482,7 @@ export function createTaskToolProgressHandler(
'emitToolResult' in adapter &&
typeof adapter.emitToolResult === 'function'
) {
adapter.emitToolResult(request, response, taskToolCallId);
adapter.emitToolResult(request, response, agentToolCallId);
} else {
adapter.emitToolResult(request, response);
}
@ -495,8 +495,8 @@ export function createTaskToolProgressHandler(
* @param previousCall - The previous state of the tool call (if any)
*/
const processToolCall = (
toolCall: NonNullable<TaskResultDisplay['toolCalls']>[number],
previousCall?: NonNullable<TaskResultDisplay['toolCalls']>[number],
toolCall: NonNullable<AgentResultDisplay['toolCalls']>[number],
previousCall?: NonNullable<AgentResultDisplay['toolCalls']>[number],
): void => {
const isCompleted =
toolCall.status === 'success' || toolCall.status === 'failed';
@ -531,14 +531,14 @@ export function createTaskToolProgressHandler(
callId: string,
outputChunk: ToolResultDisplay,
) => {
// Only process TaskResultDisplay (Task tool updates)
// Only process AgentResultDisplay (Task tool updates)
if (
typeof outputChunk === 'object' &&
outputChunk !== null &&
'type' in outputChunk &&
outputChunk.type === 'task_execution'
) {
const taskDisplay = outputChunk as TaskResultDisplay;
const taskDisplay = outputChunk as AgentResultDisplay;
const previous = previousTaskStates.get(callId);
// Only process if adapter supports subagent APIs
@ -585,7 +585,7 @@ export function createTaskToolProgressHandler(
? 'Task was cancelled'
: 'Task execution failed');
// Use subagent adapter's emitSubagentErrorResult method
adapter.emitSubagentErrorResult(errorMessage, 0, taskToolCallId);
adapter.emitSubagentErrorResult(errorMessage, 0, agentToolCallId);
}
}
@ -601,7 +601,7 @@ export function createTaskToolProgressHandler(
// Emit the user message with the correct parent_tool_use_id
adapter.emitUserMessage(
[{ text: taskDisplay.taskPrompt }],
taskToolCallId,
agentToolCallId,
);
}
@ -610,7 +610,7 @@ export function createTaskToolProgressHandler(
}
};
// No longer need to attach adapter to handler - task.ts uses TaskResultDisplay.message instead
// No longer need to attach adapter to handler - task.ts uses AgentResultDisplay.message instead
return {
handler: outputUpdateHandler,