| 498 | } |
| 499 | |
| 500 | export function createCronApi({ gatewayManager }: { gatewayManager: GatewayManager }): CompleteHostServiceRegistry['cron'] { |
| 501 | return { |
| 502 | list: async () => listCronJobs(gatewayManager), |
| 503 | create: async (payload) => { |
| 504 | const input = payload; |
| 505 | const agentId = typeof input.agentId === 'string' && input.agentId.trim() ? input.agentId.trim() : 'main'; |
| 506 | const delivery = normalizeCronDelivery(input.delivery); |
| 507 | const unsupportedDeliveryError = getUnsupportedCronDeliveryError(delivery.channel); |
| 508 | if (delivery.mode === 'announce' && unsupportedDeliveryError) { |
| 509 | throw new Error(unsupportedDeliveryError); |
| 510 | } |
| 511 | const result = await gatewayManager.rpc('cron.add', { |
| 512 | name: input.name, |
| 513 | schedule: normalizeScheduleInput(input.schedule), |
| 514 | payload: { kind: 'agentTurn', message: input.message }, |
| 515 | enabled: typeof input.enabled === 'boolean' ? input.enabled : true, |
| 516 | wakeMode: 'next-heartbeat', |
| 517 | sessionTarget: 'isolated', |
| 518 | agentId, |
| 519 | delivery, |
| 520 | }); |
| 521 | if (!result || typeof result !== 'object') { |
| 522 | throw new Error('Cron create returned an invalid job'); |
| 523 | } |
| 524 | return transformCronJob(result as GatewayCronJob); |
| 525 | }, |
| 526 | update: async (payload) => { |
| 527 | const body = payload; |
| 528 | const id = getId(body); |
| 529 | const input = isRecord(body.input) ? body.input : {}; |
| 530 | const patch = buildCronUpdatePatch(input); |
| 531 | delete patch.id; |
| 532 | delete patch.input; |
| 533 | const deliveryPatch = patch.delivery && typeof patch.delivery === 'object' |
| 534 | ? patch.delivery as Record<string, unknown> |
| 535 | : undefined; |
| 536 | const deliveryChannel = typeof deliveryPatch?.channel === 'string' && deliveryPatch.channel.trim() |
| 537 | ? deliveryPatch.channel.trim() |
| 538 | : undefined; |
| 539 | const deliveryMode = typeof deliveryPatch?.mode === 'string' && deliveryPatch.mode.trim() |
| 540 | ? deliveryPatch.mode.trim() |
| 541 | : undefined; |
| 542 | const unsupportedDeliveryError = getUnsupportedCronDeliveryError(deliveryChannel); |
| 543 | if (unsupportedDeliveryError && deliveryMode !== 'none') { |
| 544 | throw new Error(unsupportedDeliveryError); |
| 545 | } |
| 546 | const result = await gatewayManager.rpc('cron.update', { id, patch }); |
| 547 | if (!result || typeof result !== 'object') { |
| 548 | throw new Error('Cron update returned an invalid job'); |
| 549 | } |
| 550 | return transformCronJob(result as GatewayCronJob); |
| 551 | }, |
| 552 | delete: async (payload) => gatewayManager.rpc('cron.remove', { id: getId(payload) }), |
| 553 | toggle: async (payload) => { |
| 554 | const body = payload; |
| 555 | return gatewayManager.rpc('cron.update', { |
| 556 | id: getId(body), |
| 557 | patch: { enabled: body.enabled === true }, |