init claude-code
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
import { z } from 'zod/v4'
|
||||
import { buildTool, type ToolDef } from '../../Tool.js'
|
||||
import {
|
||||
executeTaskCreatedHooks,
|
||||
getTaskCreatedHookMessage,
|
||||
} from '../../utils/hooks.js'
|
||||
import { lazySchema } from '../../utils/lazySchema.js'
|
||||
import {
|
||||
createTask,
|
||||
deleteTask,
|
||||
getTaskListId,
|
||||
isTodoV2Enabled,
|
||||
} from '../../utils/tasks.js'
|
||||
import { getAgentName, getTeamName } from '../../utils/teammate.js'
|
||||
import { TASK_CREATE_TOOL_NAME } from './constants.js'
|
||||
import { DESCRIPTION, getPrompt } from './prompt.js'
|
||||
|
||||
const inputSchema = lazySchema(() =>
|
||||
z.strictObject({
|
||||
subject: z.string().describe('A brief title for the task'),
|
||||
description: z.string().describe('What needs to be done'),
|
||||
activeForm: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'Present continuous form shown in spinner when in_progress (e.g., "Running tests")',
|
||||
),
|
||||
metadata: z
|
||||
.record(z.string(), z.unknown())
|
||||
.optional()
|
||||
.describe('Arbitrary metadata to attach to the task'),
|
||||
}),
|
||||
)
|
||||
type InputSchema = ReturnType<typeof inputSchema>
|
||||
|
||||
const outputSchema = lazySchema(() =>
|
||||
z.object({
|
||||
task: z.object({
|
||||
id: z.string(),
|
||||
subject: z.string(),
|
||||
}),
|
||||
}),
|
||||
)
|
||||
type OutputSchema = ReturnType<typeof outputSchema>
|
||||
|
||||
export type Output = z.infer<OutputSchema>
|
||||
|
||||
export const TaskCreateTool = buildTool({
|
||||
name: TASK_CREATE_TOOL_NAME,
|
||||
searchHint: 'create a task in the task list',
|
||||
maxResultSizeChars: 100_000,
|
||||
async description() {
|
||||
return DESCRIPTION
|
||||
},
|
||||
async prompt() {
|
||||
return getPrompt()
|
||||
},
|
||||
get inputSchema(): InputSchema {
|
||||
return inputSchema()
|
||||
},
|
||||
get outputSchema(): OutputSchema {
|
||||
return outputSchema()
|
||||
},
|
||||
userFacingName() {
|
||||
return 'TaskCreate'
|
||||
},
|
||||
shouldDefer: true,
|
||||
isEnabled() {
|
||||
return isTodoV2Enabled()
|
||||
},
|
||||
isConcurrencySafe() {
|
||||
return true
|
||||
},
|
||||
toAutoClassifierInput(input) {
|
||||
return input.subject
|
||||
},
|
||||
renderToolUseMessage() {
|
||||
return null
|
||||
},
|
||||
async call({ subject, description, activeForm, metadata }, context) {
|
||||
const taskId = await createTask(getTaskListId(), {
|
||||
subject,
|
||||
description,
|
||||
activeForm,
|
||||
status: 'pending',
|
||||
owner: undefined,
|
||||
blocks: [],
|
||||
blockedBy: [],
|
||||
metadata,
|
||||
})
|
||||
|
||||
const blockingErrors: string[] = []
|
||||
const generator = executeTaskCreatedHooks(
|
||||
taskId,
|
||||
subject,
|
||||
description,
|
||||
getAgentName(),
|
||||
getTeamName(),
|
||||
undefined,
|
||||
context?.abortController?.signal,
|
||||
undefined,
|
||||
context,
|
||||
)
|
||||
for await (const result of generator) {
|
||||
if (result.blockingError) {
|
||||
blockingErrors.push(getTaskCreatedHookMessage(result.blockingError))
|
||||
}
|
||||
}
|
||||
|
||||
if (blockingErrors.length > 0) {
|
||||
await deleteTask(getTaskListId(), taskId)
|
||||
throw new Error(blockingErrors.join('\n'))
|
||||
}
|
||||
|
||||
// Auto-expand task list when creating tasks
|
||||
context.setAppState(prev => {
|
||||
if (prev.expandedView === 'tasks') return prev
|
||||
return { ...prev, expandedView: 'tasks' as const }
|
||||
})
|
||||
|
||||
return {
|
||||
data: {
|
||||
task: {
|
||||
id: taskId,
|
||||
subject,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
mapToolResultToToolResultBlockParam(content, toolUseID) {
|
||||
const { task } = content as Output
|
||||
return {
|
||||
tool_use_id: toolUseID,
|
||||
type: 'tool_result',
|
||||
content: `Task #${task.id} created successfully: ${task.subject}`,
|
||||
}
|
||||
},
|
||||
} satisfies ToolDef<InputSchema, Output>)
|
||||
@@ -0,0 +1 @@
|
||||
export const TASK_CREATE_TOOL_NAME = 'TaskCreate'
|
||||
@@ -0,0 +1,56 @@
|
||||
import { isAgentSwarmsEnabled } from '../../utils/agentSwarmsEnabled.js'
|
||||
|
||||
export const DESCRIPTION = 'Create a new task in the task list'
|
||||
|
||||
export function getPrompt(): string {
|
||||
const teammateContext = isAgentSwarmsEnabled()
|
||||
? ' and potentially assigned to teammates'
|
||||
: ''
|
||||
|
||||
const teammateTips = isAgentSwarmsEnabled()
|
||||
? `- Include enough detail in the description for another agent to understand and complete the task
|
||||
- New tasks are created with status 'pending' and no owner - use TaskUpdate with the \`owner\` parameter to assign them
|
||||
`
|
||||
: ''
|
||||
|
||||
return `Use this tool to create a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
|
||||
It also helps the user understand the progress of the task and overall progress of their requests.
|
||||
|
||||
## When to Use This Tool
|
||||
|
||||
Use this tool proactively in these scenarios:
|
||||
|
||||
- Complex multi-step tasks - When a task requires 3 or more distinct steps or actions
|
||||
- Non-trivial and complex tasks - Tasks that require careful planning or multiple operations${teammateContext}
|
||||
- Plan mode - When using plan mode, create a task list to track the work
|
||||
- User explicitly requests todo list - When the user directly asks you to use the todo list
|
||||
- User provides multiple tasks - When users provide a list of things to be done (numbered or comma-separated)
|
||||
- After receiving new instructions - Immediately capture user requirements as tasks
|
||||
- When you start working on a task - Mark it as in_progress BEFORE beginning work
|
||||
- After completing a task - Mark it as completed and add any new follow-up tasks discovered during implementation
|
||||
|
||||
## When NOT to Use This Tool
|
||||
|
||||
Skip using this tool when:
|
||||
- There is only a single, straightforward task
|
||||
- The task is trivial and tracking it provides no organizational benefit
|
||||
- The task can be completed in less than 3 trivial steps
|
||||
- The task is purely conversational or informational
|
||||
|
||||
NOTE that you should not use this tool if there is only one trivial task to do. In this case you are better off just doing the task directly.
|
||||
|
||||
## Task Fields
|
||||
|
||||
- **subject**: A brief, actionable title in imperative form (e.g., "Fix authentication bug in login flow")
|
||||
- **description**: What needs to be done
|
||||
- **activeForm** (optional): Present continuous form shown in the spinner when the task is in_progress (e.g., "Fixing authentication bug"). If omitted, the spinner shows the subject instead.
|
||||
|
||||
All tasks are created with status \`pending\`.
|
||||
|
||||
## Tips
|
||||
|
||||
- Create tasks with clear, specific subjects that describe the outcome
|
||||
- After creating tasks, use TaskUpdate to set up dependencies (blocks/blockedBy) if needed
|
||||
${teammateTips}- Check TaskList first to avoid creating duplicate tasks
|
||||
`
|
||||
}
|
||||
Reference in New Issue
Block a user