diff --git a/src/browser/components/Messages/ToolMessage.tsx b/src/browser/components/Messages/ToolMessage.tsx index 5f4089312..44039a328 100644 --- a/src/browser/components/Messages/ToolMessage.tsx +++ b/src/browser/components/Messages/ToolMessage.tsx @@ -14,6 +14,12 @@ import { BashBackgroundListToolCall } from "../tools/BashBackgroundListToolCall" import { BashBackgroundTerminateToolCall } from "../tools/BashBackgroundTerminateToolCall"; import { BashOutputToolCall } from "../tools/BashOutputToolCall"; import { CodeExecutionToolCall } from "../tools/CodeExecutionToolCall"; +import { + TaskToolCall, + TaskAwaitToolCall, + TaskListToolCall, + TaskTerminateToolCall, +} from "../tools/TaskToolCall"; import type { BashToolArgs, BashToolResult, @@ -41,6 +47,14 @@ import type { StatusSetToolResult, WebFetchToolArgs, WebFetchToolResult, + TaskToolArgs, + TaskToolSuccessResult, + TaskAwaitToolArgs, + TaskAwaitToolSuccessResult, + TaskListToolArgs, + TaskListToolSuccessResult, + TaskTerminateToolArgs, + TaskTerminateToolSuccessResult, } from "@/common/types/tools"; import type { ReviewNoteData } from "@/common/types/review"; import type { BashOutputGroupInfo } from "@/browser/utils/messages/messageUtils"; @@ -146,6 +160,26 @@ function isCodeExecutionTool(toolName: string, args: unknown): args is CodeExecu return TOOL_DEFINITIONS.code_execution.schema.safeParse(args).success; } +function isTaskTool(toolName: string, args: unknown): args is TaskToolArgs { + if (toolName !== "task") return false; + return TOOL_DEFINITIONS.task.schema.safeParse(args).success; +} + +function isTaskAwaitTool(toolName: string, args: unknown): args is TaskAwaitToolArgs { + if (toolName !== "task_await") return false; + return TOOL_DEFINITIONS.task_await.schema.safeParse(args).success; +} + +function isTaskListTool(toolName: string, args: unknown): args is TaskListToolArgs { + if (toolName !== "task_list") return false; + return TOOL_DEFINITIONS.task_list.schema.safeParse(args).success; +} + +function isTaskTerminateTool(toolName: string, args: unknown): args is TaskTerminateToolArgs { + if (toolName !== "task_terminate") return false; + return TOOL_DEFINITIONS.task_terminate.schema.safeParse(args).success; +} + export const ToolMessage: React.FC = ({ message, className, @@ -354,6 +388,54 @@ export const ToolMessage: React.FC = ({ ); } + if (isTaskTool(message.toolName, message.args)) { + return ( +
+ +
+ ); + } + + if (isTaskAwaitTool(message.toolName, message.args)) { + return ( +
+ +
+ ); + } + + if (isTaskListTool(message.toolName, message.args)) { + return ( +
+ +
+ ); + } + + if (isTaskTerminateTool(message.toolName, message.args)) { + return ( +
+ +
+ ); + } + // Fallback to generic tool call return (
diff --git a/src/browser/components/tools/TaskToolCall.tsx b/src/browser/components/tools/TaskToolCall.tsx new file mode 100644 index 000000000..2955dba71 --- /dev/null +++ b/src/browser/components/tools/TaskToolCall.tsx @@ -0,0 +1,466 @@ +import React from "react"; +import { + ToolContainer, + ToolHeader, + ExpandIcon, + ToolName, + StatusIndicator, + ToolDetails, + LoadingDots, +} from "./shared/ToolPrimitives"; +import { useToolExpansion, getStatusDisplay, type ToolStatus } from "./shared/toolUtils"; +import { MarkdownRenderer } from "../Messages/MarkdownRenderer"; +import { cn } from "@/common/lib/utils"; +import { Tooltip, TooltipTrigger, TooltipContent } from "../ui/tooltip"; +import type { + TaskToolArgs, + TaskToolSuccessResult, + TaskAwaitToolArgs, + TaskAwaitToolSuccessResult, + TaskListToolArgs, + TaskListToolSuccessResult, + TaskTerminateToolArgs, + TaskTerminateToolSuccessResult, +} from "@/common/types/tools"; + +/** + * Clean SVG icon for task tools - represents spawning/branching work + */ +const TaskIcon: React.FC<{ className?: string; toolName: string }> = ({ className, toolName }) => ( + + + + {/* Main vertical line */} + + {/* Branch to right */} + + {/* Arrow head */} + + {/* Dot at origin */} + + + + {toolName} + +); + +// Status badge component for task statuses +const TaskStatusBadge: React.FC<{ + status: string; + className?: string; +}> = ({ status, className }) => { + const getStatusStyle = () => { + switch (status) { + case "completed": + case "reported": + return "bg-success/20 text-success"; + case "running": + case "awaiting_report": + return "bg-pending/20 text-pending"; + case "queued": + return "bg-muted/20 text-muted"; + case "terminated": + return "bg-interrupted/20 text-interrupted"; + case "not_found": + case "invalid_scope": + case "error": + return "bg-danger/20 text-danger"; + default: + return "bg-muted/20 text-muted"; + } + }; + + return ( + + {status} + + ); +}; + +// Agent type badge +const AgentTypeBadge: React.FC<{ + type: string; + className?: string; +}> = ({ type, className }) => { + const getTypeStyle = () => { + switch (type) { + case "explore": + return "border-plan-mode/50 text-plan-mode"; + case "exec": + return "border-exec-mode/50 text-exec-mode"; + default: + return "border-muted/50 text-muted"; + } + }; + + return ( + + {type} + + ); +}; + +// Task ID display with monospace styling +const TaskId: React.FC<{ id: string; className?: string }> = ({ id, className }) => ( + {id} +); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TASK TOOL CALL (spawn sub-agent) +// ═══════════════════════════════════════════════════════════════════════════════ + +interface TaskToolCallProps { + args: TaskToolArgs; + result?: TaskToolSuccessResult; + status?: ToolStatus; +} + +export const TaskToolCall: React.FC = ({ args, result, status = "pending" }) => { + // Default expand for completed tasks with reports + const hasReport = result?.status === "completed" && !!result.reportMarkdown; + const { expanded, toggleExpanded } = useToolExpansion(hasReport); + + const isBackground = args.run_in_background ?? false; + const agentType = args.subagent_type; + const prompt = args.prompt; + const description = args.description; + + // Derive task state from result + const taskId = result?.taskId; + const taskStatus = result?.status; + const reportMarkdown = result?.status === "completed" ? result.reportMarkdown : undefined; + const reportTitle = result?.status === "completed" ? result.title : undefined; + + // Show preview of prompt (first line or truncated) + const promptPreview = + prompt.length > 60 ? prompt.slice(0, 60).trim() + "…" : prompt.split("\n")[0]; + + return ( + + + + + task + + {isBackground && ( + background + )} + {getStatusDisplay(status)} + + + {expanded && ( + + {/* Task info surface */} +
+
+ + {reportTitle ?? description ?? "Sub-agent Task"} + + {taskId && } + {taskStatus && } +
+ + {/* Prompt section */} +
+
Prompt
+
+ {prompt} +
+
+ + {/* Report section */} + {reportMarkdown && ( +
+
Report
+
+ +
+
+ )} + + {/* Pending state */} + {status === "executing" && !reportMarkdown && ( +
+ Task {isBackground ? "running in background" : "executing"} + +
+ )} +
+
+ )} + + {/* Collapsed preview */} + {!expanded &&
{promptPreview}
} +
+ ); +}; + +// ═══════════════════════════════════════════════════════════════════════════════ +// TASK AWAIT TOOL CALL +// ═══════════════════════════════════════════════════════════════════════════════ + +interface TaskAwaitToolCallProps { + args: TaskAwaitToolArgs; + result?: TaskAwaitToolSuccessResult; + status?: ToolStatus; +} + +export const TaskAwaitToolCall: React.FC = ({ + args, + result, + status = "pending", +}) => { + const hasResults = result?.results && result.results.length > 0; + const { expanded, toggleExpanded } = useToolExpansion(hasResults); + + const taskIds = args.task_ids; + const timeoutSecs = args.timeout_secs; + const results = result?.results ?? []; + + // Summary for header + const completedCount = results.filter((r) => r.status === "completed").length; + const totalCount = results.length; + + return ( + + + + + task_await + {totalCount > 0 && ( + + {completedCount}/{totalCount} completed + + )} + {getStatusDisplay(status)} + + + {expanded && ( + +
+ {/* Config info */} + {(taskIds ?? timeoutSecs) && ( +
+ {taskIds && Waiting for: {taskIds.length} task(s)} + {timeoutSecs && Timeout: {timeoutSecs}s} +
+ )} + + {/* Results */} + {results.length > 0 ? ( +
+ {results.map((r, idx) => ( + + ))} +
+ ) : status === "executing" ? ( +
+ Waiting for tasks to complete + +
+ ) : ( +
No tasks specified
+ )} +
+
+ )} +
+ ); +}; + +// Individual task_await result display +const TaskAwaitResult: React.FC<{ + result: TaskAwaitToolSuccessResult["results"][number]; +}> = ({ result }) => { + const isCompleted = result.status === "completed"; + const reportMarkdown = isCompleted ? result.reportMarkdown : undefined; + const title = isCompleted ? result.title : undefined; + + return ( +
+
+ + + {title && {title}} +
+ + {reportMarkdown && ( +
+ +
+ )} + + {"error" in result && result.error && ( +
{result.error}
+ )} +
+ ); +}; + +// ═══════════════════════════════════════════════════════════════════════════════ +// TASK LIST TOOL CALL +// ═══════════════════════════════════════════════════════════════════════════════ + +interface TaskListToolCallProps { + args: TaskListToolArgs; + result?: TaskListToolSuccessResult; + status?: ToolStatus; +} + +export const TaskListToolCall: React.FC = ({ + args, + result, + status = "pending", +}) => { + const tasks = result?.tasks ?? []; + const hasTasks = tasks.length > 0; + const { expanded, toggleExpanded } = useToolExpansion(hasTasks); + + const statusFilter = args.statuses; + + return ( + + + + + task_list + {tasks.length} task(s) + {getStatusDisplay(status)} + + + {expanded && ( + +
+ {statusFilter && statusFilter.length > 0 && ( +
+ Filter: {statusFilter.join(", ")} +
+ )} + + {tasks.length > 0 ? ( +
+ {tasks.map((task) => ( + + ))} +
+ ) : status === "executing" ? ( +
+ Fetching tasks + +
+ ) : ( +
No tasks found
+ )} +
+
+ )} +
+ ); +}; + +// Individual task in list display +const TaskListItem: React.FC<{ + task: TaskListToolSuccessResult["tasks"][number]; +}> = ({ task }) => ( +
+ + + {task.agentType && } + {task.title && ( + {task.title} + )} + {task.depth > 0 && depth: {task.depth}} +
+); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TASK TERMINATE TOOL CALL +// ═══════════════════════════════════════════════════════════════════════════════ + +interface TaskTerminateToolCallProps { + args: TaskTerminateToolArgs; + result?: TaskTerminateToolSuccessResult; + status?: ToolStatus; +} + +export const TaskTerminateToolCall: React.FC = ({ + args, + result, + status = "pending", +}) => { + const { expanded, toggleExpanded } = useToolExpansion(false); + + const taskIds = args.task_ids; + const results = result?.results ?? []; + + const terminatedCount = results.filter((r) => r.status === "terminated").length; + + return ( + + + + + task_terminate + + {terminatedCount > 0 ? `${terminatedCount} terminated` : `${taskIds.length} to terminate`} + + {getStatusDisplay(status)} + + + {expanded && ( + +
+ {results.length > 0 ? ( +
+ {results.map((r, idx) => ( +
+
+ + +
+ {"terminatedTaskIds" in r && r.terminatedTaskIds.length > 1 && ( +
+ Also terminated:{" "} + {r.terminatedTaskIds.filter((id) => id !== r.taskId).join(", ")} +
+ )} + {"error" in r && r.error && ( +
{r.error}
+ )} +
+ ))} +
+ ) : status === "executing" ? ( +
+ Terminating tasks + +
+ ) : ( +
Tasks to terminate: {taskIds.join(", ")}
+ )} +
+
+ )} +
+ ); +}; diff --git a/src/browser/stories/App.task.stories.tsx b/src/browser/stories/App.task.stories.tsx new file mode 100644 index 000000000..d73de7fb7 --- /dev/null +++ b/src/browser/stories/App.task.stories.tsx @@ -0,0 +1,242 @@ +/** + * Storybook stories for task tool components (task, task_await, task_list, task_terminate). + * Consolidated to capture all visual states in minimal stories. + */ + +import { appMeta, AppWithMocks, type AppStory } from "./meta.js"; +import { setupSimpleChatStory } from "./storyHelpers"; +import { + createUserMessage, + createAssistantMessage, + createTaskTool, + createCompletedTaskTool, + createTaskAwaitTool, + createTaskListTool, + createTaskTerminateTool, +} from "./mockFactory"; + +export default { + ...appMeta, + title: "App/Task Tools", +}; + +/** + * Full task workflow: spawn parallel tasks, list them, await results. + * Shows task, task_list, and task_await in a realistic sequence. + */ +export const TaskWorkflow: AppStory = { + render: () => ( + + setupSimpleChatStory({ + messages: [ + // User kicks off parallel analysis + createUserMessage("u1", "Analyze the frontend and backend code", { + historySequence: 1, + }), + createAssistantMessage("a1", "I'll spawn parallel tasks for analysis.", { + historySequence: 2, + toolCalls: [ + createTaskTool("tc1", { + subagent_type: "explore", + prompt: "Analyze the frontend React components in src/browser/", + description: "Frontend analysis", + run_in_background: true, + taskId: "task-fe-001", + status: "running", + }), + createTaskTool("tc2", { + subagent_type: "exec", + prompt: "Run linting on the backend code in src/node/", + description: "Backend linting", + run_in_background: true, + taskId: "task-be-002", + status: "queued", + }), + ], + }), + // User checks task status + createUserMessage("u2", "What tasks are running?", { historySequence: 3 }), + createAssistantMessage("a2", "Here are the active tasks:", { + historySequence: 4, + toolCalls: [ + createTaskListTool("tc3", { + statuses: ["running", "queued"], + tasks: [ + { + taskId: "task-fe-001", + status: "running", + parentWorkspaceId: "ws-main", + agentType: "explore", + title: "Frontend analysis", + depth: 0, + }, + { + taskId: "task-be-002", + status: "queued", + parentWorkspaceId: "ws-main", + agentType: "exec", + title: "Backend linting", + depth: 0, + }, + ], + }), + ], + }), + // User waits for results + createUserMessage("u3", "Wait for all tasks to complete", { historySequence: 5 }), + createAssistantMessage("a3", "Both tasks have completed.", { + historySequence: 6, + toolCalls: [ + createTaskAwaitTool("tc4", { + task_ids: ["task-fe-001", "task-be-002"], + results: [ + { + taskId: "task-fe-001", + status: "completed", + title: "Frontend Analysis", + reportMarkdown: `Found **23 React components** using hooks and TypeScript. + +Key patterns: +- Context providers for state management +- Custom hooks for reusable logic`, + }, + { + taskId: "task-be-002", + status: "completed", + title: "Backend Linting", + reportMarkdown: `Linting passed with **0 errors** and 3 warnings.`, + }, + ], + }), + ], + }), + ], + }) + } + /> + ), +}; + +/** + * Completed task with full markdown report. + * Shows the expanded report view with rich content. + */ +export const TaskWithReport: AppStory = { + render: () => ( + + setupSimpleChatStory({ + messages: [ + createUserMessage("u1", "Find all the test files in this project", { + historySequence: 1, + }), + createAssistantMessage("a1", "I'll spawn a sub-agent to explore the test files.", { + historySequence: 2, + toolCalls: [ + createCompletedTaskTool("tc1", { + subagent_type: "explore", + prompt: + "Find all test files in this project. Look for patterns like *.test.ts, *.spec.ts, and test directories.", + description: "Exploring test file structure", + taskId: "task-abc123", + reportMarkdown: `# Test File Analysis + +Found **47 test files** across the project: + +## Unit Tests (\`src/**/*.test.ts\`) +- 32 files covering components, hooks, and utilities +- Located in \`src/browser/\` and \`src/common/\` + +## Integration Tests (\`tests/integration/\`) +- 15 files for end-to-end scenarios +- Uses \`TEST_INTEGRATION=1\` environment variable + +### Key Patterns +- Test files are co-located with implementation +- Uses \`bun test\` for unit tests +- Uses \`bun x jest\` for integration tests`, + title: "Test File Analysis", + }), + ], + }), + ], + }) + } + /> + ), +}; + +/** + * Task termination and error states. + * Shows task_terminate with mixed success/error results and task_await errors. + */ +export const TaskErrorStates: AppStory = { + render: () => ( + + setupSimpleChatStory({ + messages: [ + // Check tasks with various error states + createUserMessage("u1", "Check on my background tasks", { historySequence: 1 }), + createAssistantMessage("a1", "Here's the status of your tasks:", { + historySequence: 2, + toolCalls: [ + createTaskAwaitTool("tc1", { + timeout_secs: 30, + results: [ + { + taskId: "task-001", + status: "completed", + title: "Quick Analysis", + reportMarkdown: "Analysis complete. Found 5 issues.", + }, + { + taskId: "task-002", + status: "running", + }, + { + taskId: "task-404", + status: "not_found", + }, + { + taskId: "task-err", + status: "error", + error: "Task crashed due to memory limit", + }, + ], + }), + ], + }), + // Terminate tasks with mixed results + createUserMessage("u2", "Stop all tasks", { historySequence: 3 }), + createAssistantMessage("a2", "Some tasks could not be terminated:", { + historySequence: 4, + toolCalls: [ + createTaskTerminateTool("tc2", { + task_ids: ["task-001", "task-002", "task-invalid"], + results: [ + { + taskId: "task-001", + status: "terminated", + terminatedTaskIds: ["task-001", "task-001-sub-a"], + }, + { + taskId: "task-002", + status: "terminated", + terminatedTaskIds: ["task-002"], + }, + { + taskId: "task-invalid", + status: "invalid_scope", + }, + ], + }), + ], + }), + ], + }) + } + /> + ), +}; diff --git a/src/browser/stories/mockFactory.ts b/src/browser/stories/mockFactory.ts index 328940a4b..d7f0a12d5 100644 --- a/src/browser/stories/mockFactory.ts +++ b/src/browser/stories/mockFactory.ts @@ -693,3 +693,212 @@ export function createStreamingChatHandler(opts: { return () => clearInterval(intervalId); }; } + +// ═══════════════════════════════════════════════════════════════════════════════ +// TASK TOOL FACTORIES +// ═══════════════════════════════════════════════════════════════════════════════ + +/** Create a task tool call (spawn sub-agent) - background/queued */ +export function createTaskTool( + toolCallId: string, + opts: { + subagent_type: "explore" | "exec"; + prompt: string; + description?: string; + run_in_background?: boolean; + taskId: string; + status: "queued" | "running"; + } +): MuxPart { + return { + type: "dynamic-tool", + toolCallId, + toolName: "task", + state: "output-available", + input: { + subagent_type: opts.subagent_type, + prompt: opts.prompt, + description: opts.description, + run_in_background: opts.run_in_background ?? false, + }, + output: { + status: opts.status, + taskId: opts.taskId, + }, + }; +} + +/** Create a completed task tool call with report */ +export function createCompletedTaskTool( + toolCallId: string, + opts: { + subagent_type: "explore" | "exec"; + prompt: string; + description?: string; + taskId?: string; + reportMarkdown: string; + title?: string; + } +): MuxPart { + return { + type: "dynamic-tool", + toolCallId, + toolName: "task", + state: "output-available", + input: { + subagent_type: opts.subagent_type, + prompt: opts.prompt, + description: opts.description, + run_in_background: false, + }, + output: { + status: "completed", + taskId: opts.taskId, + reportMarkdown: opts.reportMarkdown, + title: opts.title, + }, + }; +} + +/** Create a pending task tool call (executing) */ +export function createPendingTaskTool( + toolCallId: string, + opts: { + subagent_type: "explore" | "exec"; + prompt: string; + description?: string; + run_in_background?: boolean; + } +): MuxPart { + return { + type: "dynamic-tool", + toolCallId, + toolName: "task", + state: "input-available", + input: { + subagent_type: opts.subagent_type, + prompt: opts.prompt, + description: opts.description, + run_in_background: opts.run_in_background ?? false, + }, + }; +} + +/** Create a task_await tool call */ +export function createTaskAwaitTool( + toolCallId: string, + opts: { + task_ids?: string[]; + timeout_secs?: number; + results: Array<{ + taskId: string; + status: "completed" | "queued" | "running" | "awaiting_report" | "not_found" | "error"; + reportMarkdown?: string; + title?: string; + error?: string; + }>; + } +): MuxPart { + return { + type: "dynamic-tool", + toolCallId, + toolName: "task_await", + state: "output-available", + input: { + task_ids: opts.task_ids, + timeout_secs: opts.timeout_secs, + }, + output: { + results: opts.results.map((r) => { + if (r.status === "completed") { + return { + status: "completed" as const, + taskId: r.taskId, + reportMarkdown: r.reportMarkdown ?? "", + title: r.title, + }; + } + if (r.status === "error") { + return { + status: "error" as const, + taskId: r.taskId, + error: r.error ?? "Unknown error", + }; + } + return { + status: r.status, + taskId: r.taskId, + }; + }), + }, + }; +} + +/** Create a task_list tool call */ +export function createTaskListTool( + toolCallId: string, + opts: { + statuses?: Array<"queued" | "running" | "awaiting_report" | "reported">; + tasks: Array<{ + taskId: string; + status: "queued" | "running" | "awaiting_report" | "reported"; + parentWorkspaceId: string; + agentType?: string; + title?: string; + depth: number; + }>; + } +): MuxPart { + return { + type: "dynamic-tool", + toolCallId, + toolName: "task_list", + state: "output-available", + input: { statuses: opts.statuses }, + output: { tasks: opts.tasks }, + }; +} + +/** Create a task_terminate tool call */ +export function createTaskTerminateTool( + toolCallId: string, + opts: { + task_ids: string[]; + results: Array<{ + taskId: string; + status: "terminated" | "not_found" | "invalid_scope" | "error"; + terminatedTaskIds?: string[]; + error?: string; + }>; + } +): MuxPart { + return { + type: "dynamic-tool", + toolCallId, + toolName: "task_terminate", + state: "output-available", + input: { task_ids: opts.task_ids }, + output: { + results: opts.results.map((r) => { + if (r.status === "terminated") { + return { + status: "terminated" as const, + taskId: r.taskId, + terminatedTaskIds: r.terminatedTaskIds ?? [r.taskId], + }; + } + if (r.status === "error") { + return { + status: "error" as const, + taskId: r.taskId, + error: r.error ?? "Unknown error", + }; + } + return { + status: r.status, + taskId: r.taskId, + }; + }), + }, + }; +} diff --git a/src/browser/styles/globals.css b/src/browser/styles/globals.css index fb482a5a0..72cdd834f 100644 --- a/src/browser/styles/globals.css +++ b/src/browser/styles/globals.css @@ -133,6 +133,18 @@ --color-token-cached: hsl(0 0% 50%); --color-token-cache-create: hsl(140 20% 55%); + /* Task/subagent surfaces - teal/cyan theme for parallel work */ + --color-task-mode: hsl(175 60% 42%); + --color-task-mode-light: hsl(175 60% 55%); + --surface-task-gradient: linear-gradient( + 135deg, + color-mix(in srgb, var(--color-task-mode), transparent 92%) 0%, + color-mix(in srgb, var(--color-task-mode), transparent 95%) 100% + ); + --surface-task-border: color-mix(in srgb, var(--color-task-mode), transparent 70%); + --surface-task-border-strong: color-mix(in srgb, var(--color-task-mode), transparent 55%); + --surface-task-divider: color-mix(in srgb, var(--color-task-mode), transparent 80%); + /* Plan surfaces */ --surface-plan-gradient: linear-gradient( 135deg, @@ -1200,6 +1212,15 @@ body, border-style: dashed; border-color: var(--border-warning-dashed); } + +@utility task-surface { + background: var(--surface-task-gradient); + border: 1px solid var(--surface-task-border); +} + +@utility task-divider { + border-color: var(--surface-task-divider); +} code { font-family: var(--font-monospace); } diff --git a/src/common/types/tools.ts b/src/common/types/tools.ts index 333ce5220..e89c230b1 100644 --- a/src/common/types/tools.ts +++ b/src/common/types/tools.ts @@ -17,6 +17,9 @@ import type { FileEditReplaceStringToolResultSchema, FileReadToolResultSchema, TaskToolResultSchema, + TaskAwaitToolResultSchema, + TaskListToolResultSchema, + TaskTerminateToolResultSchema, TOOL_DEFINITIONS, WebFetchToolResultSchema, } from "@/common/utils/tools/toolDefinitions"; @@ -159,6 +162,27 @@ export type TaskToolSuccessResult = z.infer; export type TaskToolResult = TaskToolSuccessResult | ToolErrorResult; +// Task Await Tool Types +export type TaskAwaitToolArgs = z.infer; + +export type TaskAwaitToolSuccessResult = z.infer; + +export type TaskAwaitToolResult = TaskAwaitToolSuccessResult | ToolErrorResult; + +// Task List Tool Types +export type TaskListToolArgs = z.infer; + +export type TaskListToolSuccessResult = z.infer; + +export type TaskListToolResult = TaskListToolSuccessResult | ToolErrorResult; + +// Task Terminate Tool Types +export type TaskTerminateToolArgs = z.infer; + +export type TaskTerminateToolSuccessResult = z.infer; + +export type TaskTerminateToolResult = TaskTerminateToolSuccessResult | ToolErrorResult; + // Agent Report Tool Types export type AgentReportToolArgs = z.infer;