/ tools / ScheduleCronTool / CronDeleteTool.ts
CronDeleteTool.ts
 1  import { z } from 'zod/v4'
 2  import type { ValidationResult } from '../../Tool.js'
 3  import { buildTool, type ToolDef } from '../../Tool.js'
 4  import {
 5    getCronFilePath,
 6    listAllCronTasks,
 7    removeCronTasks,
 8  } from '../../utils/cronTasks.js'
 9  import { lazySchema } from '../../utils/lazySchema.js'
10  import { getTeammateContext } from '../../utils/teammateContext.js'
11  import {
12    buildCronDeletePrompt,
13    CRON_DELETE_DESCRIPTION,
14    CRON_DELETE_TOOL_NAME,
15    isDurableCronEnabled,
16    isKairosCronEnabled,
17  } from './prompt.js'
18  import { renderDeleteResultMessage, renderDeleteToolUseMessage } from './UI.js'
19  
20  const inputSchema = lazySchema(() =>
21    z.strictObject({
22      id: z.string().describe('Job ID returned by CronCreate.'),
23    }),
24  )
25  type InputSchema = ReturnType<typeof inputSchema>
26  
27  const outputSchema = lazySchema(() =>
28    z.object({
29      id: z.string(),
30    }),
31  )
32  type OutputSchema = ReturnType<typeof outputSchema>
33  export type DeleteOutput = z.infer<OutputSchema>
34  
35  export const CronDeleteTool = buildTool({
36    name: CRON_DELETE_TOOL_NAME,
37    searchHint: 'cancel a scheduled cron job',
38    maxResultSizeChars: 100_000,
39    shouldDefer: true,
40    get inputSchema(): InputSchema {
41      return inputSchema()
42    },
43    get outputSchema(): OutputSchema {
44      return outputSchema()
45    },
46    isEnabled() {
47      return isKairosCronEnabled()
48    },
49    toAutoClassifierInput(input) {
50      return input.id
51    },
52    async description() {
53      return CRON_DELETE_DESCRIPTION
54    },
55    async prompt() {
56      return buildCronDeletePrompt(isDurableCronEnabled())
57    },
58    getPath() {
59      return getCronFilePath()
60    },
61    async validateInput(input): Promise<ValidationResult> {
62      const tasks = await listAllCronTasks()
63      const task = tasks.find(t => t.id === input.id)
64      if (!task) {
65        return {
66          result: false,
67          message: `No scheduled job with id '${input.id}'`,
68          errorCode: 1,
69        }
70      }
71      // Teammates may only delete their own crons.
72      const ctx = getTeammateContext()
73      if (ctx && task.agentId !== ctx.agentId) {
74        return {
75          result: false,
76          message: `Cannot delete cron job '${input.id}': owned by another agent`,
77          errorCode: 2,
78        }
79      }
80      return { result: true }
81    },
82    async call({ id }) {
83      await removeCronTasks([id])
84      return { data: { id } }
85    },
86    mapToolResultToToolResultBlockParam(output, toolUseID) {
87      return {
88        tool_use_id: toolUseID,
89        type: 'tool_result',
90        content: `Cancelled job ${output.id}.`,
91      }
92    },
93    renderToolUseMessage: renderDeleteToolUseMessage,
94    renderToolResultMessage: renderDeleteResultMessage,
95  } satisfies ToolDef<InputSchema, DeleteOutput>)