tools.ts 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // 定时任务工具(docs/design/14-schedules.md §4):由 MCP Gateway 提供给所有会话(普通会话与工作组中的机器人)
  2. import { z } from 'zod'
  3. import { fail, ok, type BuiltinTool, type ToolResult } from '../mcp-gateway/builtin'
  4. import type { GatewayRunContext } from '../mcp-gateway/tokens'
  5. const scheduleArg = z.object({
  6. kind: z.enum(['once', 'daily', 'weekdays', 'weekly', 'monthly', 'interval'])
  7. .describe('once:只执行一次;daily:每天;weekdays:周一到周五;weekly:每周的某几天;monthly:每月某天;interval:每 N 小时'),
  8. time: z.string().optional().describe('daily / weekdays / weekly / monthly 的执行时间,HH:mm(24 小时制)'),
  9. days: z.array(z.number().int()).optional().describe('weekly 的星期几,1=周一 … 7=周日'),
  10. day: z.number().int().optional().describe('monthly 的日期 1–31,超过当月天数时取最后一天'),
  11. at: z.string().optional().describe('once 的执行时间,YYYY-MM-DD HH:mm'),
  12. after_minutes: z.number().optional().describe('once 的另一种写法:多少分钟后执行(用户说"两小时后"等相对时间时使用)'),
  13. hours: z.number().optional().describe('interval 的间隔小时数'),
  14. })
  15. const schemasFor = (timezone: string) => ({
  16. schedule_create: z.object({
  17. title: z.string().min(1).max(60).describe('简短的名称,如"销售日报"'),
  18. prompt: z.string().min(1).max(20_000).describe('到点时发给你的完整指令:要能独立执行,写清楚做什么、数据从哪里来、产出放在哪里'),
  19. schedule: scheduleArg.describe(`时间表,时间按 ${timezone} 时区`),
  20. }),
  21. schedule_list: z.object({}),
  22. schedule_update: z.object({
  23. schedule_id: z.string().describe('定时任务 id(见 schedule_list)'),
  24. title: z.string().max(60).optional(),
  25. prompt: z.string().max(20_000).optional(),
  26. schedule: scheduleArg.describe(`时间表,时间按 ${timezone} 时区`).optional(),
  27. status: z.enum(['active', 'paused']).optional().describe('暂停或恢复'),
  28. }),
  29. schedule_delete: z.object({ schedule_id: z.string() }),
  30. })
  31. type ToolName = keyof ReturnType<typeof schemasFor>
  32. const DESCRIPTIONS: Record<ToolName, string> = {
  33. schedule_create: '用户要求定期执行或在将来某个时间执行某项工作时,创建定时任务。会显示确认卡片,用户确认后生效;到点时系统把 prompt 作为一条新消息发到当前会话(工作组中发到工作组),由你执行。',
  34. schedule_list: '列出当前会话(或工作组)的定时任务。',
  35. schedule_update: '修改定时任务的名称、指令或时间表(需要用户确认),或者暂停、恢复(不需要确认)。',
  36. schedule_delete: '删除定时任务。',
  37. }
  38. export function scheduleTools(timezone: string, handle: (name: ToolName, args: Record<string, unknown>, ctx: GatewayRunContext) => Promise<string>): BuiltinTool[] {
  39. const schemas = schemasFor(timezone)
  40. return (Object.keys(schemas) as ToolName[]).map(name => ({
  41. name,
  42. description: DESCRIPTIONS[name],
  43. schema: schemas[name],
  44. readOnly: name === 'schedule_list',
  45. async handler(args, ctx): Promise<ToolResult> {
  46. try {
  47. return ok(await handle(name, args as Record<string, unknown>, ctx))
  48. } catch (err) {
  49. return fail((err as Error).message)
  50. }
  51. },
  52. }))
  53. }