diff --git a/src/browser/components/tools/TaskToolCall.tsx b/src/browser/components/tools/TaskToolCall.tsx index 2955dba71..0519a8171 100644 --- a/src/browser/components/tools/TaskToolCall.tsx +++ b/src/browser/components/tools/TaskToolCall.tsx @@ -143,7 +143,7 @@ export const TaskToolCall: React.FC = ({ args, result, status const isBackground = args.run_in_background ?? false; const agentType = args.subagent_type; const prompt = args.prompt; - const description = args.description; + const title = args.title; // Derive task state from result const taskId = result?.taskId; @@ -174,7 +174,7 @@ export const TaskToolCall: React.FC = ({ args, result, status
- {reportTitle ?? description ?? "Sub-agent Task"} + {reportTitle ?? title} {taskId && } {taskStatus && } diff --git a/src/browser/stories/App.task.stories.tsx b/src/browser/stories/App.task.stories.tsx index d73de7fb7..33070feee 100644 --- a/src/browser/stories/App.task.stories.tsx +++ b/src/browser/stories/App.task.stories.tsx @@ -40,7 +40,7 @@ export const TaskWorkflow: AppStory = { createTaskTool("tc1", { subagent_type: "explore", prompt: "Analyze the frontend React components in src/browser/", - description: "Frontend analysis", + title: "Frontend analysis", run_in_background: true, taskId: "task-fe-001", status: "running", @@ -48,7 +48,7 @@ export const TaskWorkflow: AppStory = { createTaskTool("tc2", { subagent_type: "exec", prompt: "Run linting on the backend code in src/node/", - description: "Backend linting", + title: "Backend linting", run_in_background: true, taskId: "task-be-002", status: "queued", @@ -138,7 +138,7 @@ export const TaskWithReport: AppStory = { 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", + title: "Exploring test file structure", taskId: "task-abc123", reportMarkdown: `# Test File Analysis @@ -156,7 +156,7 @@ Found **47 test files** across the project: - Test files are co-located with implementation - Uses \`bun test\` for unit tests - Uses \`bun x jest\` for integration tests`, - title: "Test File Analysis", + reportTitle: "Test File Analysis", }), ], }), diff --git a/src/browser/stories/mockFactory.ts b/src/browser/stories/mockFactory.ts index d7f0a12d5..97499d371 100644 --- a/src/browser/stories/mockFactory.ts +++ b/src/browser/stories/mockFactory.ts @@ -704,7 +704,7 @@ export function createTaskTool( opts: { subagent_type: "explore" | "exec"; prompt: string; - description?: string; + title: string; run_in_background?: boolean; taskId: string; status: "queued" | "running"; @@ -718,7 +718,7 @@ export function createTaskTool( input: { subagent_type: opts.subagent_type, prompt: opts.prompt, - description: opts.description, + title: opts.title, run_in_background: opts.run_in_background ?? false, }, output: { @@ -734,10 +734,10 @@ export function createCompletedTaskTool( opts: { subagent_type: "explore" | "exec"; prompt: string; - description?: string; + title: string; taskId?: string; reportMarkdown: string; - title?: string; + reportTitle?: string; } ): MuxPart { return { @@ -748,14 +748,14 @@ export function createCompletedTaskTool( input: { subagent_type: opts.subagent_type, prompt: opts.prompt, - description: opts.description, + title: opts.title, run_in_background: false, }, output: { status: "completed", taskId: opts.taskId, reportMarkdown: opts.reportMarkdown, - title: opts.title, + title: opts.reportTitle, }, }; } @@ -766,7 +766,7 @@ export function createPendingTaskTool( opts: { subagent_type: "explore" | "exec"; prompt: string; - description?: string; + title: string; run_in_background?: boolean; } ): MuxPart { @@ -778,7 +778,7 @@ export function createPendingTaskTool( input: { subagent_type: opts.subagent_type, prompt: opts.prompt, - description: opts.description, + title: opts.title, run_in_background: opts.run_in_background ?? false, }, }; diff --git a/src/common/orpc/schemas/api.ts b/src/common/orpc/schemas/api.ts index 3ddf5aeef..dfef9cb11 100644 --- a/src/common/orpc/schemas/api.ts +++ b/src/common/orpc/schemas/api.ts @@ -488,7 +488,7 @@ export const tasks = { kind: z.literal("agent"), agentType: z.string(), prompt: z.string(), - description: z.string().optional(), + title: z.string().min(1), modelString: z.string().optional(), thinkingLevel: z.string().optional(), }), diff --git a/src/common/utils/tools/toolDefinitions.ts b/src/common/utils/tools/toolDefinitions.ts index 09d3b89d9..c52ddeaa9 100644 --- a/src/common/utils/tools/toolDefinitions.ts +++ b/src/common/utils/tools/toolDefinitions.ts @@ -97,7 +97,7 @@ export const TaskToolArgsSchema = z .object({ subagent_type: SubagentTypeSchema, prompt: z.string().min(1), - description: z.string().optional(), + title: z.string().min(1), run_in_background: z.boolean().default(false), }) .strict(); diff --git a/src/node/orpc/router.ts b/src/node/orpc/router.ts index 6ee8bcb35..d4b59d043 100644 --- a/src/node/orpc/router.ts +++ b/src/node/orpc/router.ts @@ -1122,7 +1122,7 @@ export const router = (authToken?: string) => { kind: input.kind, agentType: input.agentType, prompt: input.prompt, - description: input.description, + title: input.title, modelString: input.modelString, thinkingLevel, }); diff --git a/src/node/services/taskService.test.ts b/src/node/services/taskService.test.ts index b0fdb1491..c34370e86 100644 --- a/src/node/services/taskService.test.ts +++ b/src/node/services/taskService.test.ts @@ -253,6 +253,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "explore this repo", + title: "Test task", }); expect(first.success).toBe(true); if (!first.success) return; @@ -262,6 +263,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "nested explore", + title: "Test task", }); expect(second.success).toBe(false); if (!second.success) { @@ -334,6 +336,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "task 1", + title: "Test task", }); expect(running.success).toBe(true); if (!running.success) return; @@ -343,6 +346,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "task 2", + title: "Test task", }); expect(queued.success).toBe(true); if (!queued.success) return; @@ -428,6 +432,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "parent task", + title: "Test task", }); expect(parentTask.success).toBe(true); if (!parentTask.success) return; @@ -439,6 +444,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "child task", + title: "Test task", }); expect(childTask.success).toBe(true); if (!childTask.success) return; @@ -528,6 +534,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "task 1", + title: "Test task", }); expect(running.success).toBe(true); if (!running.success) return; @@ -540,6 +547,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "task 2", + title: "Test task", }); expect(queued.success).toBe(true); if (!queued.success) return; @@ -706,6 +714,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "task 1", + title: "Test task", }); expect(first.success).toBe(true); if (!first.success) return; @@ -716,6 +725,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "task 2", + title: "Test task", }); expect(second.success).toBe(true); if (!second.success) return; @@ -726,6 +736,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "task 3", + title: "Test task", }); expect(third.success).toBe(true); if (!third.success) return; @@ -766,6 +777,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "run task from local workspace", + title: "Test task", }); expect(created.success).toBe(true); if (!created.success) return; @@ -820,6 +832,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "run task with overrides", + title: "Test task", }); expect(created.success).toBe(true); if (!created.success) return; @@ -1368,6 +1381,7 @@ describe("TaskService", () => { kind: "agent", agentType: "explore", prompt: "do the thing", + title: "Test task", }); expect(created.success).toBe(false); @@ -1435,7 +1449,7 @@ describe("TaskService", () => { type: "dynamic-tool", toolCallId: "task-call-1", toolName: "task", - input: { subagent_type: "explore", prompt: "do the thing" }, + input: { subagent_type: "explore", prompt: "do the thing", title: "Test task" }, state: "input-available", }, ] @@ -1709,7 +1723,7 @@ describe("TaskService", () => { type: "dynamic-tool", toolCallId: "task-call-1", toolName: "task", - input: { subagent_type: "explore", prompt: "do the thing" }, + input: { subagent_type: "explore", prompt: "do the thing", title: "Test task" }, state: "input-available", }, ] diff --git a/src/node/services/taskService.ts b/src/node/services/taskService.ts index 07f5b3b89..58082a0e1 100644 --- a/src/node/services/taskService.ts +++ b/src/node/services/taskService.ts @@ -39,7 +39,8 @@ export interface TaskCreateArgs { kind: TaskKind; agentType: string; prompt: string; - description?: string; + /** Human-readable title for the task (displayed in sidebar) */ + title: string; modelString?: string; thinkingLevel?: ThinkingLevel; } @@ -439,7 +440,7 @@ export class TaskService { path: workspacePath, id: taskId, name: workspaceName, - title: args.description, + title: args.title, createdAt, runtimeConfig: taskRuntimeConfig, aiSettings: { model: canonicalModel, thinkingLevel: effectiveThinkingLevel }, @@ -524,7 +525,7 @@ export class TaskService { path: workspacePath, id: taskId, name: workspaceName, - title: args.description, + title: args.title, createdAt, runtimeConfig: taskRuntimeConfig, aiSettings: { model: canonicalModel, thinkingLevel: effectiveThinkingLevel }, diff --git a/src/node/services/tools/task.ts b/src/node/services/tools/task.ts index fdc699a91..68500fb70 100644 --- a/src/node/services/tools/task.ts +++ b/src/node/services/tools/task.ts @@ -34,7 +34,7 @@ export const createTaskTool: ToolFactory = (config: ToolConfiguration) => { kind: "agent", agentType: args.subagent_type, prompt: args.prompt, - description: args.description, + title: args.title, modelString, thinkingLevel, });