/ tools / TaskGetTool / TaskGetTool.ts
TaskGetTool.ts
  1  import { z } from 'zod/v4'
  2  import { buildTool, type ToolDef } from '../../Tool.js'
  3  import { lazySchema } from '../../utils/lazySchema.js'
  4  import {
  5    getTask,
  6    getTaskListId,
  7    isTodoV2Enabled,
  8    TaskStatusSchema,
  9  } from '../../utils/tasks.js'
 10  import { TASK_GET_TOOL_NAME } from './constants.js'
 11  import { DESCRIPTION, PROMPT } from './prompt.js'
 12  
 13  const inputSchema = lazySchema(() =>
 14    z.strictObject({
 15      taskId: z.string().describe('The ID of the task to retrieve'),
 16    }),
 17  )
 18  type InputSchema = ReturnType<typeof inputSchema>
 19  
 20  const outputSchema = lazySchema(() =>
 21    z.object({
 22      task: z
 23        .object({
 24          id: z.string(),
 25          subject: z.string(),
 26          description: z.string(),
 27          status: TaskStatusSchema(),
 28          blocks: z.array(z.string()),
 29          blockedBy: z.array(z.string()),
 30        })
 31        .nullable(),
 32    }),
 33  )
 34  type OutputSchema = ReturnType<typeof outputSchema>
 35  
 36  export type Output = z.infer<OutputSchema>
 37  
 38  export const TaskGetTool = buildTool({
 39    name: TASK_GET_TOOL_NAME,
 40    searchHint: 'retrieve a task by ID',
 41    maxResultSizeChars: 100_000,
 42    async description() {
 43      return DESCRIPTION
 44    },
 45    async prompt() {
 46      return PROMPT
 47    },
 48    get inputSchema(): InputSchema {
 49      return inputSchema()
 50    },
 51    get outputSchema(): OutputSchema {
 52      return outputSchema()
 53    },
 54    userFacingName() {
 55      return 'TaskGet'
 56    },
 57    shouldDefer: true,
 58    isEnabled() {
 59      return isTodoV2Enabled()
 60    },
 61    isConcurrencySafe() {
 62      return true
 63    },
 64    isReadOnly() {
 65      return true
 66    },
 67    toAutoClassifierInput(input) {
 68      return input.taskId
 69    },
 70    renderToolUseMessage() {
 71      return null
 72    },
 73    async call({ taskId }) {
 74      const taskListId = getTaskListId()
 75  
 76      const task = await getTask(taskListId, taskId)
 77  
 78      if (!task) {
 79        return {
 80          data: {
 81            task: null,
 82          },
 83        }
 84      }
 85  
 86      return {
 87        data: {
 88          task: {
 89            id: task.id,
 90            subject: task.subject,
 91            description: task.description,
 92            status: task.status,
 93            blocks: task.blocks,
 94            blockedBy: task.blockedBy,
 95          },
 96        },
 97      }
 98    },
 99    mapToolResultToToolResultBlockParam(content, toolUseID) {
100      const { task } = content as Output
101      if (!task) {
102        return {
103          tool_use_id: toolUseID,
104          type: 'tool_result',
105          content: 'Task not found',
106        }
107      }
108  
109      const lines = [
110        `Task #${task.id}: ${task.subject}`,
111        `Status: ${task.status}`,
112        `Description: ${task.description}`,
113      ]
114  
115      if (task.blockedBy.length > 0) {
116        lines.push(`Blocked by: ${task.blockedBy.map(id => `#${id}`).join(', ')}`)
117      }
118      if (task.blocks.length > 0) {
119        lines.push(`Blocks: ${task.blocks.map(id => `#${id}`).join(', ')}`)
120      }
121  
122      return {
123        tool_use_id: toolUseID,
124        type: 'tool_result',
125        content: lines.join('\n'),
126      }
127    },
128  } satisfies ToolDef<InputSchema, Output>)