| import { z } from 'zod/v4' |
| import { buildTool, type ToolDef } from '../../Tool.js' |
| import { cronToHuman } from '../../utils/cron.js' |
| import { listAllCronTasks } from '../../utils/cronTasks.js' |
| import { truncate } from '../../utils/format.js' |
| import { lazySchema } from '../../utils/lazySchema.js' |
| import { getTeammateContext } from '../../utils/teammateContext.js' |
| import { |
| buildCronListPrompt, |
| CRON_LIST_DESCRIPTION, |
| CRON_LIST_TOOL_NAME, |
| isDurableCronEnabled, |
| isKairosCronEnabled, |
| } from './prompt.js' |
| import { renderListResultMessage, renderListToolUseMessage } from './UI.js' |
|
|
| const inputSchema = lazySchema(() => z.strictObject({})) |
| type InputSchema = ReturnType<typeof inputSchema> |
|
|
| const outputSchema = lazySchema(() => |
| z.object({ |
| jobs: z.array( |
| z.object({ |
| id: z.string(), |
| cron: z.string(), |
| humanSchedule: z.string(), |
| prompt: z.string(), |
| recurring: z.boolean().optional(), |
| durable: z.boolean().optional(), |
| }), |
| ), |
| }), |
| ) |
| type OutputSchema = ReturnType<typeof outputSchema> |
| export type ListOutput = z.infer<OutputSchema> |
|
|
| export const CronListTool = buildTool({ |
| name: CRON_LIST_TOOL_NAME, |
| searchHint: 'list active cron jobs', |
| maxResultSizeChars: 100_000, |
| shouldDefer: true, |
| get inputSchema(): InputSchema { |
| return inputSchema() |
| }, |
| get outputSchema(): OutputSchema { |
| return outputSchema() |
| }, |
| isEnabled() { |
| return isKairosCronEnabled() |
| }, |
| isConcurrencySafe() { |
| return true |
| }, |
| isReadOnly() { |
| return true |
| }, |
| async description() { |
| return CRON_LIST_DESCRIPTION |
| }, |
| async prompt() { |
| return buildCronListPrompt(isDurableCronEnabled()) |
| }, |
| async call() { |
| const allTasks = await listAllCronTasks() |
| |
| const ctx = getTeammateContext() |
| const tasks = ctx |
| ? allTasks.filter(t => t.agentId === ctx.agentId) |
| : allTasks |
| const jobs = tasks.map(t => ({ |
| id: t.id, |
| cron: t.cron, |
| humanSchedule: cronToHuman(t.cron), |
| prompt: t.prompt, |
| ...(t.recurring ? { recurring: true } : {}), |
| ...(t.durable === false ? { durable: false } : {}), |
| })) |
| return { data: { jobs } } |
| }, |
| mapToolResultToToolResultBlockParam(output, toolUseID) { |
| return { |
| tool_use_id: toolUseID, |
| type: 'tool_result', |
| content: |
| output.jobs.length > 0 |
| ? output.jobs |
| .map( |
| j => |
| `${j.id} — ${j.humanSchedule}${j.recurring ? ' (recurring)' : ' (one-shot)'}${j.durable === false ? ' [session-only]' : ''}: ${truncate(j.prompt, 80, true)}`, |
| ) |
| .join('\n') |
| : 'No scheduled jobs.', |
| } |
| }, |
| renderToolUseMessage: renderListToolUseMessage, |
| renderToolResultMessage: renderListResultMessage, |
| } satisfies ToolDef<InputSchema, ListOutput>) |
|
|