agents 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +1 -0
  2. package/dist/{agent-tool-types-CzGGB-20.d.ts → agent-routing-CnkaHb-v.d.ts} +2921 -3057
  3. package/dist/agent-routing.d.ts +14 -0
  4. package/dist/agent-routing.js +187 -0
  5. package/dist/agent-routing.js.map +1 -0
  6. package/dist/agent-tool-types.d.ts +26 -26
  7. package/dist/{agent-tools-zR2d5uij.d.ts → agent-tools-C0XJqWzB.d.ts} +7 -7
  8. package/dist/agent-tools.d.ts +21 -21
  9. package/dist/agent-tools.js +2 -1
  10. package/dist/agent-tools.js.map +1 -1
  11. package/dist/browser/ai.js +2 -1
  12. package/dist/browser/ai.js.map +1 -1
  13. package/dist/capability-BjSKYpzg.js +42 -0
  14. package/dist/capability-BjSKYpzg.js.map +1 -0
  15. package/dist/capability-runner-CvHGZqUu.d.ts +150 -0
  16. package/dist/chat/index.d.ts +22 -15
  17. package/dist/chat/index.js +4 -4
  18. package/dist/chat/index.js.map +1 -1
  19. package/dist/chat/react.d.ts +14 -1
  20. package/dist/chat/react.js +82 -52
  21. package/dist/chat/react.js.map +1 -1
  22. package/dist/chat/transport.js +1 -1
  23. package/dist/chat-sdk/index.d.ts +4 -4
  24. package/dist/chat-sdk/index.js +1 -1
  25. package/dist/{client-zqKcsyFa.js → client-jagG8a9_.js} +129 -37
  26. package/dist/client-jagG8a9_.js.map +1 -0
  27. package/dist/client.d.ts +1 -1
  28. package/dist/client.js +1 -1
  29. package/dist/{cloudflare-BduZwmYK.js → cloudflare-Dzvc7V2N.js} +10 -3
  30. package/dist/{cloudflare-BduZwmYK.js.map → cloudflare-Dzvc7V2N.js.map} +1 -1
  31. package/dist/current-agent-CuMErtly.d.ts +283 -0
  32. package/dist/current-agent-DhoDkSnH.js +51 -0
  33. package/dist/current-agent-DhoDkSnH.js.map +1 -0
  34. package/dist/diagnostics-CaBjfz4J.js +41 -0
  35. package/dist/diagnostics-CaBjfz4J.js.map +1 -0
  36. package/dist/{do-oauth-client-provider-VTZj2VtM.d.ts → do-oauth-client-provider-Tmf1vgKz.d.ts} +2 -2
  37. package/dist/durable-object-lifecycle-D6nNQJJd.js +862 -0
  38. package/dist/durable-object-lifecycle-D6nNQJJd.js.map +1 -0
  39. package/dist/{email-CL27preh.d.ts → email-7TatiTnl.d.ts} +38 -9
  40. package/dist/email-send.d.ts +15 -0
  41. package/dist/email-send.js +32 -0
  42. package/dist/email-send.js.map +1 -0
  43. package/dist/email.d.ts +14 -10
  44. package/dist/email.js.map +1 -1
  45. package/dist/experimental/memory/session/index.d.ts +3 -2
  46. package/dist/experimental/memory/session/index.js +15 -10
  47. package/dist/experimental/memory/session/index.js.map +1 -1
  48. package/dist/{handler-stateless-C_bo-Ytq.d.ts → handler-stateless-DxYpJ_XF.d.ts} +3 -3
  49. package/dist/{handler-stateless-CIkKPETH.js → handler-stateless-VvrWSAVA.js} +5 -5
  50. package/dist/handler-stateless-VvrWSAVA.js.map +1 -0
  51. package/dist/{index-BRnybD6X.d.ts → index-DcSAZKsB.d.ts} +19 -31
  52. package/dist/index.d.ts +98 -95
  53. package/dist/index.js +10 -7234
  54. package/dist/internal_context-BlxFEWfn.d.ts +19 -0
  55. package/dist/internal_context.d.ts +10 -4
  56. package/dist/internal_context.js +1 -10
  57. package/dist/{client-invoker-BNSZxAkv.d.ts → invoker-CG0_p_Wq.d.ts} +2 -2
  58. package/dist/{client-invoker-VNZ7X0nn.js → invoker-CHMnoxIA.js} +2 -2
  59. package/dist/invoker-CHMnoxIA.js.map +1 -0
  60. package/dist/lifecycle/index.d.ts +48 -0
  61. package/dist/lifecycle/index.js +4 -0
  62. package/dist/mcp/{do-oauth-client-provider.d.ts → client/do-oauth-client-provider.d.ts} +1 -1
  63. package/dist/mcp/{do-oauth-client-provider.js → client/do-oauth-client-provider.js} +1 -1
  64. package/dist/mcp/client/do-oauth-client-provider.js.map +1 -0
  65. package/dist/mcp/client/index.d.ts +42 -0
  66. package/dist/mcp/{client.js → client/index.js} +1 -1
  67. package/dist/mcp/{x402.d.ts → client/x402.d.ts} +2 -2
  68. package/dist/mcp/{x402.js → client/x402.js} +2 -2
  69. package/dist/mcp/client/x402.js.map +1 -0
  70. package/dist/mcp/index.d.ts +36 -36
  71. package/dist/mcp/index.js +14 -16
  72. package/dist/mcp/index.js.map +1 -1
  73. package/dist/mcp/{server.d.ts → server/index.d.ts} +1 -1
  74. package/dist/mcp/{server.js → server/index.js} +1 -1
  75. package/dist/observability/ai/index.js +50 -35
  76. package/dist/observability/ai/index.js.map +1 -1
  77. package/dist/observability/index.d.ts +4 -4
  78. package/dist/observability/index.js +3 -50
  79. package/dist/observability/index.js.map +1 -1
  80. package/dist/{protocol-Dqc2MQxo.js → protocol-B0nh6KNf.js} +19 -21
  81. package/dist/protocol-B0nh6KNf.js.map +1 -0
  82. package/dist/react.d.ts +4 -4
  83. package/dist/react.js +1 -1
  84. package/dist/schedule.d.ts +25 -94
  85. package/dist/schedule.js +1 -98
  86. package/dist/schedule.js.map +1 -1
  87. package/dist/scheduler-CR9RHGos.js +857 -0
  88. package/dist/scheduler-CR9RHGos.js.map +1 -0
  89. package/dist/scheduler-DQoTGoAW.d.ts +224 -0
  90. package/dist/schedules/index.d.ts +22 -0
  91. package/dist/schedules/index.js +2 -0
  92. package/dist/schedules/parser.d.ts +79 -0
  93. package/dist/schedules/parser.js +103 -0
  94. package/dist/schedules/parser.js.map +1 -0
  95. package/dist/serializable.d.ts +1 -1
  96. package/dist/sql-error-CPY-GXyI.d.ts +12 -0
  97. package/dist/sql-error.d.ts +2 -0
  98. package/dist/sql-error.js +16 -0
  99. package/dist/sql-error.js.map +1 -0
  100. package/dist/src-5W6JNKVb.js +6613 -0
  101. package/dist/src-5W6JNKVb.js.map +1 -0
  102. package/dist/sub-routing.d.ts +12 -12
  103. package/dist/workflow-types.d.ts +25 -25
  104. package/dist/workflows.d.ts +22 -22
  105. package/dist/workflows.js +2 -1
  106. package/dist/workflows.js.map +1 -1
  107. package/dist/{ws-chat-transport-CIoOBbO7.js → ws-chat-transport-rWwta645.js} +152 -15
  108. package/dist/ws-chat-transport-rWwta645.js.map +1 -0
  109. package/docs/agent-class.md +28 -86
  110. package/docs/chat-agents.md +13 -12
  111. package/docs/durable-execution.md +1 -1
  112. package/docs/http-websockets.md +1 -11
  113. package/docs/human-in-the-loop.md +1 -1
  114. package/docs/index.md +1 -0
  115. package/docs/lifecycle.md +323 -0
  116. package/docs/long-running-agents.md +2 -4
  117. package/docs/mcp-client.md +55 -0
  118. package/docs/observability.md +11 -11
  119. package/docs/resumable-streaming.md +1 -1
  120. package/docs/scheduling.md +175 -15
  121. package/docs/server-driven-messages.md +1 -1
  122. package/docs/sub-agents.md +1 -1
  123. package/package.json +30 -21
  124. package/dist/cli/index.d.ts +0 -1
  125. package/dist/cli/index.js +0 -26
  126. package/dist/cli/index.js.map +0 -1
  127. package/dist/client-invoker-VNZ7X0nn.js.map +0 -1
  128. package/dist/client-zqKcsyFa.js.map +0 -1
  129. package/dist/handler-stateless-CIkKPETH.js.map +0 -1
  130. package/dist/index.js.map +0 -1
  131. package/dist/internal_context-Dg4Cgjcu.d.ts +0 -37
  132. package/dist/internal_context.js.map +0 -1
  133. package/dist/mcp/client.d.ts +0 -42
  134. package/dist/mcp/do-oauth-client-provider.js.map +0 -1
  135. package/dist/mcp/x402.js.map +0 -1
  136. package/dist/protocol-Dqc2MQxo.js.map +0 -1
  137. package/dist/ws-chat-transport-CIoOBbO7.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-CR9RHGos.js","names":[],"sources":["../src/schedules/schedule-timing.ts","../src/schedules/scheduler.ts"],"sourcesContent":["/**\n * Pure timing rules for persistent schedules.\n *\n * A `ScheduleTiming` is the parsed \"when and how it runs\" half of a\n * `Schedule` — everything except identity, callback, and payload. Parsing\n * user-facing inputs here keeps Scheduler's storage code to one insert path.\n */\n\nimport { parseCronExpression } from \"cron-schedule\";\n\n/** Longest allowed gap between interval executions: 30 days. */\nexport const MAX_INTERVAL_SECONDS = 30 * 24 * 60 * 60;\n\n/** When and how one schedule runs; a `Schedule` minus identity and payload. */\nexport type ScheduleTiming =\n | {\n /** One-time execution at a specific date. */\n readonly type: \"scheduled\";\n /** Unix timestamp in seconds. */\n readonly time: number;\n }\n | {\n /** One-time execution after a relative delay. */\n readonly type: \"delayed\";\n /** Unix timestamp in seconds. */\n readonly time: number;\n /** Delay from creation in seconds. */\n readonly delayInSeconds: number;\n }\n | {\n /** Recurring execution from a cron expression. */\n readonly type: \"cron\";\n /** Unix timestamp in seconds for the next execution. */\n readonly time: number;\n /** Cron expression defining the recurrence. */\n readonly cron: string;\n }\n | {\n /** Recurring execution at a fixed interval. */\n readonly type: \"interval\";\n /** Unix timestamp in seconds for the next execution. */\n readonly time: number;\n /** Number of seconds between executions. */\n readonly intervalSeconds: number;\n };\n\n/** True when this timing repeats and therefore deduplicates by default. */\nexport function isRecurring(timing: ScheduleTiming): boolean {\n return timing.type === \"cron\" || timing.type === \"interval\";\n}\n\n/**\n * Next wall-clock execution time for a cron expression.\n *\n * @param cron - A standard cron expression.\n * @param nowMs - Current epoch time in milliseconds.\n * @returns The next execution epoch time in milliseconds.\n * @throws For an unparseable cron expression.\n */\nexport function nextCronTimeMs(cron: string, nowMs: number): number {\n return parseCronExpression(cron).getNextDate(new Date(nowMs)).getTime();\n}\n\n/**\n * Parse a user-facing `when` into schedule timing.\n *\n * A `Date` runs once at that date, a number runs once after that many\n * seconds, and a string is a recurring cron expression.\n *\n * @param when - The requested execution time or recurrence.\n * @param nowMs - Current epoch time in milliseconds.\n * @param callback - Callback name, used only in error messages.\n * @returns The parsed timing.\n * @throws For a `when` value that is not a `Date`, number, or string.\n */\nexport function parseWhen(\n when: Date | string | number,\n nowMs: number,\n callback: string\n): ScheduleTiming {\n if (when instanceof Date) {\n return { type: \"scheduled\", time: Math.floor(when.getTime() / 1000) };\n }\n if (typeof when === \"number\") {\n return {\n type: \"delayed\",\n time: Math.floor((nowMs + when * 1000) / 1000),\n delayInSeconds: when\n };\n }\n if (typeof when === \"string\") {\n return {\n type: \"cron\",\n time: Math.floor(nextCronTimeMs(when, nowMs) / 1000),\n cron: when\n };\n }\n throw new Error(\n `Invalid schedule type: ${JSON.stringify(when)}(${typeof when}) trying to schedule ${callback}`\n );\n}\n\n/**\n * Reject an interval outside the supported range.\n *\n * @param intervalSeconds - The requested gap between executions.\n * @throws For a non-positive interval or one longer than 30 days.\n */\nexport function validateIntervalSeconds(intervalSeconds: number): void {\n if (typeof intervalSeconds !== \"number\" || intervalSeconds <= 0) {\n throw new Error(\"intervalSeconds must be a positive number\");\n }\n if (intervalSeconds > MAX_INTERVAL_SECONDS) {\n throw new Error(\n `intervalSeconds cannot exceed ${MAX_INTERVAL_SECONDS} seconds (30 days)`\n );\n }\n}\n\n/**\n * Parse a fixed interval into schedule timing.\n *\n * @param intervalSeconds - Seconds between executions.\n * @param nowMs - Current epoch time in milliseconds.\n * @returns The parsed timing with the first execution one interval from now.\n * @throws For an interval outside the supported range.\n */\nexport function parseInterval(\n intervalSeconds: number,\n nowMs: number\n): ScheduleTiming {\n validateIntervalSeconds(intervalSeconds);\n return {\n type: \"interval\",\n time: Math.floor((nowMs + intervalSeconds * 1000) / 1000),\n intervalSeconds\n };\n}\n","/**\n * Lifecycle scheduling primitive. Owns the `cf_agents_schedules` table,\n * callback retry policy, and due-row processing.\n *\n * Scheduler consumes only the standard capability services: storage, alarm\n * coordination, the host invocation boundary, events, and routing. Lifecycle combines\n * Scheduler's next wake-up candidate with contributions from other\n * capabilities and the host before arming the Durable Object.\n */\n\nimport { nanoid } from \"nanoid\";\nimport {\n LifecycleCapability,\n type LifecycleRouteAddress,\n type LifecycleRouteContext\n} from \"../lifecycle/capability\";\nimport {\n isDurableObjectCodeUpdateReset,\n isDurableObjectMemoryLimitReset,\n isPlatformTransientError,\n tryN,\n validateRetryOptions\n} from \"../retries\";\nimport type { RetryOptions } from \"../retries\";\nimport { SqlError } from \"../sql-error\";\nimport type { SchedulerEventType, SchedulerOptions } from \"./options\";\nimport {\n isRecurring,\n nextCronTimeMs,\n parseInterval,\n parseWhen,\n validateIntervalSeconds,\n type ScheduleTiming\n} from \"./schedule-timing\";\nimport type {\n Schedule,\n ScheduleCriteria,\n ScheduleOptions,\n ScheduleStorageRow,\n SchedulerCallbacks,\n SchedulerHandlers,\n SchedulerPayload\n} from \"./types\";\n\n/**\n * A resolved fallback handler for a callback name outside the registered map.\n */\ntype ResolvedSchedulerCallback = (\n payload: unknown,\n schedule: Schedule<unknown>\n) => unknown;\n\nconst schedulerCallbackResolvers = new WeakMap<\n object,\n (name: string) => ResolvedSchedulerCallback | undefined\n>();\n\n/**\n * @internal Supply a composition-root fallback for callback names outside the\n * registered map. Agent uses this to keep its historical name-based\n * scheduling API (`this.schedule(60, \"methodName\")`) working: the resolver\n * looks the method up on the Agent, and the resolved handler still runs\n * inside the Lifecycle host boundary.\n */\nexport function setSchedulerCallbackResolver(\n scheduler: Scheduler<never>,\n resolver: (name: string) => ResolvedSchedulerCallback | undefined\n): void {\n schedulerCallbackResolvers.set(scheduler, resolver);\n}\n\nconst SCHEDULE_SCHEMA_VERSION_KEY = \"cf_agents:schedules_schema_version\";\nconst CURRENT_SCHEDULE_SCHEMA_VERSION = 1;\n\nconst DEFAULT_RETRY: Required<RetryOptions> = {\n maxAttempts: 3,\n baseDelayMs: 100,\n maxDelayMs: 3000\n};\n\ntype SchedulerRouteMessage =\n | {\n readonly type: \"schedule\";\n readonly when: Date | string | number;\n readonly callback: string;\n readonly payload?: unknown;\n readonly options?: ScheduleOptions;\n }\n | {\n readonly type: \"every\";\n readonly intervalSeconds: number;\n readonly callback: string;\n readonly payload?: unknown;\n readonly options?: ScheduleOptions;\n }\n | { readonly type: \"get\" | \"cancel\"; readonly id: string }\n | { readonly type: \"list\"; readonly criteria?: ScheduleCriteria }\n | { readonly type: \"dispatch\"; readonly row: ScheduleStorageRow };\n\ntype InsertResult<T> = {\n readonly schedule: Schedule<T>;\n readonly created: boolean;\n};\n\nfunction parseRetryOptions(row: ScheduleStorageRow): RetryOptions | undefined {\n return typeof row.retry_options === \"string\"\n ? (JSON.parse(row.retry_options) as RetryOptions)\n : undefined;\n}\n\nfunction resolveRetryConfig(\n retry: RetryOptions | undefined,\n defaults: Required<RetryOptions>\n): Required<RetryOptions> {\n return {\n maxAttempts: retry?.maxAttempts ?? defaults.maxAttempts,\n baseDelayMs: retry?.baseDelayMs ?? defaults.baseDelayMs,\n maxDelayMs: retry?.maxDelayMs ?? defaults.maxDelayMs\n };\n}\n\n/**\n * @internal Create or migrate the schedule table. Idempotent. Shared with\n * Agent's constructor-time schema initialization so a brand-new Agent\n * exposes the table before Lifecycle startup completes, exactly as it did\n * before Scheduler was extracted; {@link Scheduler.onStart} applies the\n * same migration for plain Lifecycle Objects.\n */\nexport function ensureScheduleTable(storage: DurableObjectStorage): void {\n const rawSql = (query: string, ...params: (string | number | null)[]) =>\n storage.sql.exec(query, ...params);\n\n // The literal whitespace below is load-bearing: sqlite_master stores the\n // statement text verbatim, and the schema DDL snapshot test pins it, so the\n // stored DDL must stay byte-identical to what Agent created historically.\n rawSql(`\n CREATE TABLE IF NOT EXISTS cf_agents_schedules (\n id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),\n callback TEXT,\n payload TEXT,\n type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron', 'interval')),\n time INTEGER,\n delayInSeconds INTEGER,\n cron TEXT,\n intervalSeconds INTEGER,\n running INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (unixepoch()),\n execution_started_at INTEGER,\n retry_options TEXT,\n owner_path TEXT,\n owner_path_key TEXT\n )\n `);\n\n const addColumnIfMissing = (statement: string): void => {\n try {\n rawSql(statement);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!message.toLowerCase().includes(\"duplicate column\")) throw error;\n }\n };\n addColumnIfMissing(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN intervalSeconds INTEGER\"\n );\n addColumnIfMissing(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN running INTEGER DEFAULT 0\"\n );\n addColumnIfMissing(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN execution_started_at INTEGER\"\n );\n addColumnIfMissing(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN retry_options TEXT\"\n );\n addColumnIfMissing(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN owner_path TEXT\"\n );\n addColumnIfMissing(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN owner_path_key TEXT\"\n );\n\n const rows = rawSql(\n \"SELECT sql FROM sqlite_master WHERE type='table' AND name='cf_agents_schedules'\"\n ).toArray();\n const ddl = typeof rows[0]?.sql === \"string\" ? rows[0].sql : \"\";\n if (ddl && !ddl.includes(\"'interval'\")) {\n rawSql(\"DROP TABLE IF EXISTS cf_agents_schedules_new\");\n rawSql(`\n CREATE TABLE cf_agents_schedules_new (\n id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),\n callback TEXT,\n payload TEXT,\n type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron', 'interval')),\n time INTEGER,\n delayInSeconds INTEGER,\n cron TEXT,\n intervalSeconds INTEGER,\n running INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (unixepoch()),\n execution_started_at INTEGER,\n retry_options TEXT,\n owner_path TEXT,\n owner_path_key TEXT\n )\n `);\n rawSql(`\n INSERT INTO cf_agents_schedules_new\n (id, callback, payload, type, time, delayInSeconds, cron,\n intervalSeconds, running, created_at, execution_started_at,\n retry_options, owner_path, owner_path_key)\n SELECT id, callback, payload, type, time, delayInSeconds, cron,\n intervalSeconds, running, created_at, execution_started_at,\n retry_options, owner_path, owner_path_key\n FROM cf_agents_schedules\n `);\n rawSql(\"DROP TABLE cf_agents_schedules\");\n rawSql(\"ALTER TABLE cf_agents_schedules_new RENAME TO cf_agents_schedules\");\n }\n\n // Keep-alive no longer uses schedule rows. Remove orphaned heartbeat rows\n // left by older Scheduler versions.\n rawSql(\n \"DELETE FROM cf_agents_schedules WHERE callback = '_cf_keepAliveHeartbeat'\"\n );\n}\n\n/**\n * Persistent task scheduling for a Lifecycle Object.\n *\n * Register callbacks in the constructor and install the instance with\n * `Lifecycle.use()`. Scheduler owns its SQL schema, task CRUD, callback\n * retries, and due-row processing. It contributes its next wake time while\n * Lifecycle owns the physical alarm, and it runs registered callbacks\n * through Lifecycle's host invocation boundary.\n *\n * @experimental The API surface may change before stabilizing.\n */\nexport class Scheduler<\n Handlers extends SchedulerHandlers = SchedulerCallbacks\n> extends LifecycleCapability {\n readonly #handlers: SchedulerHandlers;\n readonly #retryDefaults: Required<RetryOptions>;\n readonly #hungScheduleTimeoutSeconds: number;\n readonly #onError: ((error: unknown) => void | Promise<void>) | undefined;\n readonly #warnedStartupCallbacks = new Set<string>();\n #executingRowId: string | undefined;\n\n /**\n * Create a persistent Scheduler.\n *\n * @param options - Registered callbacks plus optional retry,\n * hung-interval, and error policy. Registering `callbacks` types\n * {@link set} and {@link every} against the map — names and\n * payloads are checked where the handlers are declared and where they are\n * scheduled. Names outside the map are rejected unless a composition-root\n * resolver supplies them — the internal aperture behind `Agent`'s\n * name-based scheduling API.\n */\n constructor(options: SchedulerOptions<Handlers> = {}) {\n super(\"scheduler\");\n this.#handlers = options.callbacks ?? {};\n // Retry defaults are resolved, not validated, here: a host whose\n // historically tolerated invalid retry config throws at construction\n // would brick every entry point of its Durable Object. Invalid defaults\n // surface per execution as schedule:error instead, and per-schedule\n // retry overrides are still validated when each schedule is created.\n this.#retryDefaults = resolveRetryConfig(options.retry, DEFAULT_RETRY);\n this.#hungScheduleTimeoutSeconds = options.hungScheduleTimeoutSeconds ?? 30;\n this.#onError = options.onError;\n }\n\n // ── Lifecycle capability hooks ───────────────────────────────────────────\n\n /** Initialize and migrate schedule storage during Lifecycle startup. */\n async onStart(): Promise<void> {\n this.#warnedStartupCallbacks.clear();\n const storage = this.lifecycle.storage;\n const version =\n (await storage.get<number>(SCHEDULE_SCHEMA_VERSION_KEY)) ?? 0;\n if (version >= CURRENT_SCHEDULE_SCHEMA_VERSION) return;\n\n ensureScheduleTable(this.lifecycle.storage);\n await storage.put(\n SCHEDULE_SCHEMA_VERSION_KEY,\n CURRENT_SCHEDULE_SCHEMA_VERSION\n );\n }\n\n /** Execute due schedule rows during the Lifecycle alarm phase. */\n async onAlarm(): Promise<void> {\n await this.#fireDueSchedules();\n }\n\n /** Handle Scheduler protocol messages routed by another Lifecycle. */\n async onRoute(context: LifecycleRouteContext): Promise<unknown> {\n const message = context.payload as SchedulerRouteMessage;\n const owner = context.source ?? null;\n switch (message.type) {\n case \"schedule\":\n return this.#insert(\n owner,\n parseWhen(message.when, Date.now(), message.callback),\n message.callback,\n message.payload,\n message.options\n );\n case \"every\":\n return this.#insert(\n owner,\n parseInterval(message.intervalSeconds, Date.now()),\n message.callback,\n message.payload,\n message.options\n );\n case \"get\":\n return this.#getForOwner(owner, message.id);\n case \"list\":\n return this.#listForOwner(owner, message.criteria);\n case \"cancel\":\n return this.#cancelForOwner(owner, message.id);\n case \"dispatch\":\n await this.#executeCallback(message.row);\n return true;\n default:\n throw new Error(\"Unknown routed Scheduler message\");\n }\n }\n\n /** Contribute the earliest pending schedule to Lifecycle alarm selection. */\n getNextAlarm(): number | null {\n const nowMs = Date.now();\n const hungCutoffSeconds =\n Math.floor(nowMs / 1000) - this.#hungScheduleTimeoutSeconds;\n const nextSchedule = this.#nextScheduleTimeMs(nowMs, hungCutoffSeconds);\n const hungIntervalRecheck =\n this.#nextHungIntervalRecheckMs(hungCutoffSeconds);\n if (nextSchedule === null) return hungIntervalRecheck;\n if (hungIntervalRecheck === null) return nextSchedule;\n return Math.min(nextSchedule, hungIntervalRecheck);\n }\n\n // ── Scheduling API ───────────────────────────────────────────────────────\n\n /** Set a delayed, dated, or cron schedule for a registered callback. */\n async set<Name extends keyof Handlers & string>(\n when: Date | string | number,\n callback: Name,\n payload?: SchedulerPayload<Handlers[Name]>,\n options?: ScheduleOptions\n ): Promise<Schedule<SchedulerPayload<Handlers[Name]>>> {\n await this.lifecycle.ready();\n this.#validateSchedule(when, callback, options);\n const result = this.lifecycle.routes.source\n ? ((await this.lifecycle.routes.toRoot({\n type: \"schedule\",\n when,\n callback,\n payload,\n options\n } satisfies SchedulerRouteMessage)) as InsertResult<\n SchedulerPayload<Handlers[Name]>\n >)\n : await this.#insert<SchedulerPayload<Handlers[Name]>>(\n null,\n parseWhen(when, Date.now(), callback),\n callback,\n payload,\n options\n );\n this.#emitCreated(result);\n return result.schedule;\n }\n\n /** Set a fixed-interval schedule for a registered callback. */\n async every<Name extends keyof Handlers & string>(\n intervalSeconds: number,\n callback: Name,\n payload?: SchedulerPayload<Handlers[Name]>,\n options?: ScheduleOptions\n ): Promise<Schedule<SchedulerPayload<Handlers[Name]>>> {\n await this.lifecycle.ready();\n this.#validateInterval(intervalSeconds, callback, options?.retry);\n const result = this.lifecycle.routes.source\n ? ((await this.lifecycle.routes.toRoot({\n type: \"every\",\n intervalSeconds,\n callback,\n payload,\n options\n } satisfies SchedulerRouteMessage)) as InsertResult<\n SchedulerPayload<Handlers[Name]>\n >)\n : await this.#insert<SchedulerPayload<Handlers[Name]>>(\n null,\n parseInterval(intervalSeconds, Date.now()),\n callback,\n payload,\n options\n );\n this.#emitCreated(result);\n return result.schedule;\n }\n\n /** Get a schedule by ID. Works inside routed sub-agents. */\n async get(id: string): Promise<Schedule<unknown> | undefined> {\n await this.lifecycle.ready();\n return this.lifecycle.routes.source\n ? ((await this.lifecycle.routes.toRoot({\n type: \"get\",\n id\n } satisfies SchedulerRouteMessage)) as Schedule<unknown> | undefined)\n : this.#getForOwner(null, id);\n }\n\n /** List schedules matching criteria. Works inside routed sub-agents. */\n async list(criteria: ScheduleCriteria = {}): Promise<Schedule<unknown>[]> {\n await this.lifecycle.ready();\n return this.lifecycle.routes.source\n ? ((await this.lifecycle.routes.toRoot({\n type: \"list\",\n criteria\n } satisfies SchedulerRouteMessage)) as Schedule<unknown>[])\n : this.#listForOwner(null, criteria);\n }\n\n /**\n * Cancel one schedule owned by this Scheduler.\n *\n * @param id - ID of the schedule to cancel.\n * @returns True when a schedule was cancelled, false when none matched.\n */\n async cancel(id: string): Promise<boolean> {\n await this.lifecycle.ready();\n const result = this.lifecycle.routes.source\n ? ((await this.lifecycle.routes.toRoot({\n type: \"cancel\",\n id\n } satisfies SchedulerRouteMessage)) as {\n ok: boolean;\n callback?: string;\n })\n : await this.#cancelForOwner(null, id);\n if (result.ok && result.callback) {\n this.#emit(\"schedule:cancel\", { callback: result.callback, id });\n }\n return result.ok;\n }\n\n // ── Host-owned policy apertures ──────────────────────────────────────────\n\n /**\n * @internal Synchronous read backing Agent's deprecated `getSchedule()`.\n * Not part of the primitive's contract — use {@link get}. Cannot cross\n * Durable Object boundaries and throws inside routed sub-agents.\n */\n __DO_NOT_USE_WILL_REMOVE__getSchedule<T = string>(\n id: string\n ): Schedule<T> | undefined {\n if (this.lifecycle.routes.source) {\n throw new Error(\n \"getSchedule() is synchronous and cannot read routed schedule storage. \" +\n \"Use await getScheduleById(id) on Agent, or await scheduler.get(id) \" +\n \"on a standalone Scheduler.\"\n );\n }\n return this.#getForOwner(null, id);\n }\n\n /**\n * @internal Synchronous read backing Agent's deprecated `getSchedules()`.\n * Not part of the primitive's contract — use {@link list}. Cannot cross\n * Durable Object boundaries and throws inside routed sub-agents.\n */\n __DO_NOT_USE_WILL_REMOVE__getSchedules<T = string>(\n criteria: ScheduleCriteria = {}\n ): Schedule<T>[] {\n if (this.lifecycle.routes.source) {\n throw new Error(\n \"getSchedules() is synchronous and cannot read routed schedule storage. \" +\n \"Use await listSchedules(criteria) on Agent, or await \" +\n \"scheduler.list(criteria) on a standalone Scheduler.\"\n );\n }\n return this.#listForOwner(null, criteria);\n }\n\n /** @internal Remove rows owned by one routed Lifecycle subtree. */\n __DO_NOT_USE_WILL_BREAK__cleanupRoutePrefix(prefix: string): void {\n this.#cancelOwners(\n (owner) => owner.key === prefix || owner.key.startsWith(`${prefix}/`)\n );\n }\n\n /** @internal Apply Agent's outer alarm memory-limit policy to Scheduler rows. */\n __DO_NOT_USE_WILL_BREAK__handleAlarmMemoryLimit(options: {\n readonly callbacks: ReadonlyArray<string>;\n readonly sealed: boolean;\n readonly nextTime?: number;\n }): void {\n const executingRowId = this.#executingRowId;\n this.#executingRowId = undefined;\n if (options.sealed) {\n this.#deleteRows(options.callbacks, executingRowId);\n return;\n }\n if (options.nextTime === undefined) {\n throw new Error(\"Scheduler memory-limit backoff requires nextTime\");\n }\n this.#moveRows(options.callbacks, executingRowId, options.nextTime);\n }\n\n // ── Validation ───────────────────────────────────────────────────────────\n\n #validateSchedule(\n when: Date | string | number,\n callback: string,\n options?: ScheduleOptions\n ): void {\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n if (!this.#hasCallback(callback)) {\n throw new Error(\n `Unknown scheduled callback \"${callback}\": not registered on this Scheduler`\n );\n }\n if (options?.retry) {\n validateRetryOptions(options.retry, this.#retryDefaults);\n }\n if (\n !(when instanceof Date) &&\n typeof when !== \"number\" &&\n typeof when !== \"string\"\n ) {\n throw new Error(\n `Invalid schedule type: ${JSON.stringify(when)}(${typeof when}) trying to schedule ${callback}`\n );\n }\n this.#warnWhenScheduledDuringStartup(when, callback, options);\n }\n\n #validateInterval(\n intervalSeconds: number,\n callback: string,\n retry?: RetryOptions\n ): void {\n validateIntervalSeconds(intervalSeconds);\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n if (!this.#hasCallback(callback)) {\n throw new Error(\n `Unknown scheduled callback \"${callback}\": not registered on this Scheduler`\n );\n }\n if (retry) validateRetryOptions(retry, this.#retryDefaults);\n }\n\n /**\n * A non-idempotent one-shot created during startup accumulates one row per\n * Durable Object wake, whether it came from the host's onStart or another\n * startup hook. Warn once per callback; an explicit `idempotent` choice\n * (either value) opts out.\n */\n #warnWhenScheduledDuringStartup(\n when: Date | string | number,\n callback: string,\n options?: ScheduleOptions\n ): void {\n if (!this.lifecycle.starting()) return;\n if (options?.idempotent !== undefined) return;\n if (typeof when === \"string\") return;\n if (this.#warnedStartupCallbacks.has(callback)) return;\n this.#warnedStartupCallbacks.add(callback);\n console.warn(\n `Scheduling \"${callback}\" during startup (e.g. onStart()) without ` +\n `{ idempotent: true } creates a new row on every Durable Object ` +\n `restart, which can cause duplicate executions. Pass ` +\n `{ idempotent: true } to deduplicate, or use an interval schedule ` +\n `for recurring tasks.`\n );\n }\n\n /** Resolve a name to its registered or composition-root-supplied handler. */\n #resolveCallback(name: string): ResolvedSchedulerCallback | undefined {\n const handler = this.#handlers[name];\n if (handler) {\n // SAFETY: registered handlers are constrained with `never` parameters\n // so concrete handler types satisfy the map under contravariance; the\n // payload passed at dispatch was parsed from the row this handler's\n // name was persisted with.\n return handler as ResolvedSchedulerCallback;\n }\n return schedulerCallbackResolvers.get(this)?.(name);\n }\n\n /** True when a name resolves to a runnable callback. */\n #hasCallback(name: string): boolean {\n return this.#resolveCallback(name) !== undefined;\n }\n\n /** Run one resolved callback inside the host invocation boundary. */\n async #invokeCallback(\n name: string,\n payload: unknown,\n schedule: Schedule<unknown>\n ): Promise<void> {\n const handler = this.#resolveCallback(name);\n if (!handler) {\n throw new Error(`Unknown scheduled callback \"${name}\"`);\n }\n await this.lifecycle.runInHostContext(() => handler(payload, schedule));\n }\n\n // ── Storage ──────────────────────────────────────────────────────────────\n\n #sql<T = Record<string, string | number | boolean | null>>(\n strings: TemplateStringsArray,\n ...values: (string | number | boolean | null)[]\n ): T[] {\n const query = strings.reduce(\n (result, part, index) =>\n result + part + (index < values.length ? \"?\" : \"\"),\n \"\"\n );\n try {\n // SAFETY: Scheduler queries select from its own schema; T describes the\n // projected columns of the accompanying query text.\n return [...this.lifecycle.storage.sql.exec(query, ...values)] as T[];\n } catch (cause) {\n throw new SqlError(query, cause);\n }\n }\n\n /**\n * Insert a schedule row for the given owner, or return the existing row\n * when an idempotent request matches one. One-shot timings deduplicate only\n * when `idempotent: true` is passed; recurring timings deduplicate unless\n * `idempotent: false` opts out. `created: false` marks a dedup hit so\n * callers suppress the `schedule:create` event.\n */\n async #insert<T = string>(\n owner: LifecycleRouteAddress | null,\n timing: ScheduleTiming,\n callback: string,\n payload: unknown,\n options?: ScheduleOptions\n ): Promise<InsertResult<T>> {\n const payloadJson = JSON.stringify(payload);\n // Recurring timings deduplicate unless explicitly opted out; one-shot\n // timings deduplicate on any truthy value (historic Agent behavior).\n const idempotent = isRecurring(timing)\n ? options?.idempotent !== false\n : Boolean(options?.idempotent);\n\n if (idempotent) {\n const existing = this.#findMatchingRow(\n owner?.key ?? null,\n timing,\n callback,\n payloadJson\n );\n if (existing) {\n await this.lifecycle.alarms.rearm();\n return { schedule: this.#rowToSchedule<T>(existing), created: false };\n }\n }\n\n const id = nanoid(9);\n this.#sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, time, delayInSeconds, cron,\n intervalSeconds, running, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, ${timing.type}, ${timing.time},\n ${timing.type === \"delayed\" ? timing.delayInSeconds : null},\n ${timing.type === \"cron\" ? timing.cron : null},\n ${timing.type === \"interval\" ? timing.intervalSeconds : null},\n 0,\n ${options?.retry ? JSON.stringify(options.retry) : null},\n ${owner?.data ?? null}, ${owner?.key ?? null})\n `;\n await this.lifecycle.alarms.rearm();\n\n return {\n schedule: {\n id,\n callback,\n // SAFETY: payload is optional at the call site; historical API shape\n // types an omitted payload as the schedule's payload type.\n payload: payload as T,\n retry: options?.retry,\n ...timing\n },\n created: true\n };\n }\n\n /** Find the row an idempotent insert deduplicates onto, if any. */\n #findMatchingRow(\n ownerKey: string | null,\n timing: ScheduleTiming,\n callback: string,\n payloadJson: string\n ): ScheduleStorageRow | undefined {\n let query =\n \"SELECT * FROM cf_agents_schedules \" +\n \"WHERE type = ? AND callback = ? AND payload IS ? AND owner_path_key IS ?\";\n const params: (string | number | null)[] = [\n timing.type,\n callback,\n payloadJson,\n ownerKey\n ];\n if (timing.type === \"cron\") {\n query += \" AND cron = ?\";\n params.push(timing.cron);\n }\n if (timing.type === \"interval\") {\n query += \" AND intervalSeconds = ?\";\n params.push(timing.intervalSeconds);\n }\n let rows: unknown[];\n try {\n rows = this.lifecycle.storage.sql.exec(query, ...params).toArray();\n } catch (cause) {\n throw new SqlError(query, cause);\n }\n // SAFETY: the query selects * from Scheduler's own schema.\n return rows[0] as ScheduleStorageRow | undefined;\n }\n\n #rowToSchedule<T>(row: ScheduleStorageRow): Schedule<T> {\n const base = {\n callback: row.callback,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(row)\n };\n\n switch (row.type) {\n case \"scheduled\":\n return { ...base, time: row.time, type: \"scheduled\" };\n case \"delayed\":\n return {\n ...base,\n delayInSeconds: row.delayInSeconds ?? 0,\n time: row.time,\n type: \"delayed\"\n };\n case \"cron\":\n return { ...base, cron: row.cron ?? \"\", time: row.time, type: \"cron\" };\n case \"interval\":\n return {\n ...base,\n intervalSeconds: row.intervalSeconds ?? 0,\n time: row.time,\n type: \"interval\"\n };\n }\n }\n\n #getForOwner<T = string>(\n owner: LifecycleRouteAddress | null,\n id: string\n ): Schedule<T> | undefined {\n const ownerPathKey = owner?.key ?? null;\n const result = this.#sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n if (result.length === 0) return undefined;\n return this.#rowToSchedule<T>(result[0]);\n }\n\n #listForOwner<T = string>(\n owner: LifecycleRouteAddress | null,\n criteria: ScheduleCriteria = {}\n ): Schedule<T>[] {\n let query = \"SELECT * FROM cf_agents_schedules WHERE owner_path_key IS ?\";\n const params: Array<string | number | null> = [owner?.key ?? null];\n\n if (criteria.id) {\n query += \" AND id = ?\";\n params.push(criteria.id);\n }\n if (criteria.type) {\n query += \" AND type = ?\";\n params.push(criteria.type);\n }\n if (criteria.timeRange) {\n query += \" AND time >= ? AND time <= ?\";\n const start = criteria.timeRange.start || new Date(0);\n const end = criteria.timeRange.end || new Date(999999999999999);\n params.push(\n Math.floor(start.getTime() / 1000),\n Math.floor(end.getTime() / 1000)\n );\n }\n\n return this.lifecycle.storage.sql\n .exec(query, ...params)\n .toArray()\n .map((row) =>\n // SAFETY: the query selects * from Scheduler's own schema.\n this.#rowToSchedule<T>(row as unknown as ScheduleStorageRow)\n );\n }\n\n async #cancelForOwner(\n owner: LifecycleRouteAddress | null,\n id: string\n ): Promise<{ ok: boolean; callback?: string }> {\n const ownerPathKey = owner?.key ?? null;\n const result = this.#sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n if (result.length === 0) return { ok: false };\n\n const callback = result[0].callback;\n this.#sql`\n DELETE FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n await this.lifecycle.alarms.rearm();\n return { ok: true, callback };\n }\n\n /** Cancel every owned row matched by a route-address predicate. */\n #cancelOwners(matches: (owner: LifecycleRouteAddress) => boolean): void {\n const rows = this.#sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE owner_path IS NOT NULL\n `;\n for (const row of rows) {\n if (\n !row.owner_path ||\n !matches({\n key: row.owner_path_key ?? row.owner_path,\n data: row.owner_path\n })\n )\n continue;\n this.#emit(\"schedule:cancel\", { callback: row.callback, id: row.id });\n this.#sql`DELETE FROM cf_agents_schedules WHERE id = ${row.id}`;\n }\n }\n\n /** Delete rows selected by a host-owned failure policy. Best-effort. */\n #deleteRows(callbacks: ReadonlyArray<string>, executingRowId?: string): void {\n for (const callback of callbacks) {\n try {\n this.#sql`\n DELETE FROM cf_agents_schedules WHERE callback = ${callback}\n `;\n } catch {\n // best-effort at a host failure boundary\n }\n }\n if (executingRowId) {\n try {\n this.#sql`\n DELETE FROM cf_agents_schedules WHERE id = ${executingRowId}\n `;\n } catch {\n // best-effort at a host failure boundary\n }\n }\n }\n\n /** Delay rows selected by a host-owned failure policy. Best-effort. */\n #moveRows(\n callbacks: ReadonlyArray<string>,\n executingRowId: string | undefined,\n nextTime: number\n ): void {\n for (const callback of callbacks) {\n try {\n this.#sql`\n UPDATE cf_agents_schedules\n SET time = ${nextTime}\n WHERE callback = ${callback} AND time <= ${nextTime}\n `;\n } catch {\n // best-effort at a host failure boundary\n }\n }\n if (executingRowId) {\n try {\n this.#sql`\n UPDATE cf_agents_schedules\n SET time = ${nextTime}\n WHERE id = ${executingRowId} AND time <= ${nextTime}\n `;\n } catch {\n // best-effort at a host failure boundary\n }\n }\n }\n\n // ── Execution ────────────────────────────────────────────────────────────\n\n #emit(type: SchedulerEventType, payload: Record<string, unknown>): void {\n this.lifecycle.events.emit(type, payload);\n }\n\n #emitCreated(result: InsertResult<unknown>): void {\n if (!result.created) return;\n this.#emit(\"schedule:create\", {\n callback: result.schedule.callback,\n id: result.schedule.id\n });\n }\n\n /**\n * Execute a local schedule row with retry handling.\n *\n * The capability remains outside ambient context. Lifecycle's host\n * invocation boundary establishes host context only around the user\n * callback itself.\n */\n async #executeCallback(row: ScheduleStorageRow): Promise<void> {\n if (!this.#hasCallback(row.callback)) {\n console.error(`callback ${row.callback} not found`);\n return;\n }\n\n const { maxAttempts, baseDelayMs, maxDelayMs } = resolveRetryConfig(\n parseRetryOptions(row),\n this.#retryDefaults\n );\n\n let parsedPayload: unknown;\n try {\n parsedPayload = JSON.parse(row.payload);\n } catch (error) {\n console.error(\n `Failed to parse payload for schedule \"${row.id}\" (callback \"${row.callback}\")`,\n error\n );\n this.#emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: error instanceof Error ? error.message : String(error),\n attempts: 0\n });\n return;\n }\n\n // A one-shot row is deleted by the alarm phase once this returns\n // normally. If it fails with a superseded-isolate error (a deploy / code\n // update replaced the isolate — \"reset because its code was updated\" or\n // \"this script has been upgraded\"), burning in-process retries is futile\n // (code never reloads mid-invocation) and swallowing the error would let\n // the alarm phase delete the row. Re-throw platform transients so the\n // durable alarm can retry the preserved row on a fresh invocation.\n const isOneShotSchedule =\n row.type === \"delayed\" || row.type === \"scheduled\";\n const shouldDeferReset = (error: unknown): boolean =>\n isOneShotSchedule && isDurableObjectCodeUpdateReset(error);\n const shouldDeferOnExhaustion = (error: unknown): boolean =>\n isOneShotSchedule && isPlatformTransientError(error);\n const shouldDeferMemoryLimit = (error: unknown): boolean =>\n isOneShotSchedule && isDurableObjectMemoryLimitReset(error);\n\n const schedule = this.#rowToSchedule<unknown>(row);\n\n try {\n this.#emit(\"schedule:execute\", { callback: row.callback, id: row.id });\n\n await tryN(\n maxAttempts,\n async (attempt) => {\n if (attempt > 1) {\n this.#emit(\"schedule:retry\", {\n callback: row.callback,\n id: row.id,\n attempt,\n maxAttempts\n });\n }\n await this.#invokeCallback(row.callback, parsedPayload, schedule);\n },\n {\n baseDelayMs,\n maxDelayMs,\n shouldRetry: (error) => !shouldDeferReset(error)\n }\n );\n } catch (error) {\n if (shouldDeferReset(error)) {\n console.warn(\n `Deferring scheduled callback \"${row.callback}\" to a fresh invocation after a Durable Object code-update reset; the one-shot row is preserved and the alarm will re-run on new code.`\n );\n throw error;\n }\n if (shouldDeferOnExhaustion(error)) {\n console.warn(\n `Deferring scheduled callback \"${row.callback}\" after exhausting in-process retries on a transient platform error; the one-shot row is preserved and the alarm will re-run once the platform recovers.`\n );\n throw error;\n }\n if (shouldDeferMemoryLimit(error)) {\n console.warn(\n `Deferring scheduled callback \"${row.callback}\" to the alarm memory-limit circuit breaker after a Durable Object memory-limit reset; the one-shot row is preserved so the breaker can bound the retry loop and seal it (#1825).`\n );\n throw error;\n }\n console.error(\n `error executing callback \"${row.callback}\" after ${maxAttempts} attempts`,\n error\n );\n this.#emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: error instanceof Error ? error.message : String(error),\n attempts: maxAttempts\n });\n try {\n await this.#onError?.(error);\n } catch {\n // swallow onError errors\n }\n }\n }\n\n /** Execute every schedule row due in the current alarm phase. */\n async #fireDueSchedules(): Promise<void> {\n const now = Math.floor(Date.now() / 1000);\n const dueRows = this.#sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules WHERE time <= ${now}\n `;\n this.#warnStaleOneShots(dueRows);\n\n for (const row of dueRows) {\n const outcome = await this.#runDueRow(row, now);\n if (outcome === \"stop\") return;\n if (outcome === \"executed\") this.#advanceRow(row);\n }\n }\n\n /**\n * Warn when many stale one-shot rows share the same callback — this\n * usually means one-shot schedules were created repeatedly (e.g. in\n * onStart) without idempotent:true and rows accumulated across restarts.\n */\n #warnStaleOneShots(dueRows: ReadonlyArray<ScheduleStorageRow>): void {\n const DUPLICATE_SCHEDULE_THRESHOLD = 10;\n const oneShotCounts = new Map<string, number>();\n for (const row of dueRows) {\n if (row.type === \"delayed\" || row.type === \"scheduled\") {\n oneShotCounts.set(\n row.callback,\n (oneShotCounts.get(row.callback) ?? 0) + 1\n );\n }\n }\n for (const [callback, count] of oneShotCounts) {\n if (count < DUPLICATE_SCHEDULE_THRESHOLD) continue;\n try {\n console.warn(\n `Processing ${count} stale \"${callback}\" schedules in a single alarm cycle. ` +\n `This usually means one-shot schedules are created repeatedly without ` +\n `the idempotent option. Consider an interval schedule for recurring ` +\n `tasks, or pass { idempotent: true } when creating one-shot schedules.`\n );\n this.#emit(\"schedule:duplicate_warning\", {\n callback,\n count,\n type: \"one-shot\"\n });\n } catch {\n // Warning emission is non-critical — never block row processing.\n }\n }\n }\n\n /**\n * Run one due row.\n *\n * @returns \"executed\" when the row ran and should advance, \"skipped\" when\n * it should be left for a later alarm cycle, and \"stop\" when host teardown\n * disabled further durable work mid-phase.\n */\n async #runDueRow(\n row: ScheduleStorageRow,\n now: number\n ): Promise<\"executed\" | \"skipped\" | \"stop\"> {\n // Overlap prevention for interval schedules with hung callback detection.\n if (row.type === \"interval\" && row.running === 1) {\n const elapsedSeconds = now - (row.execution_started_at ?? 0);\n if (elapsedSeconds < this.#hungScheduleTimeoutSeconds) {\n console.warn(\n `Skipping interval schedule ${row.id}: previous execution still running`\n );\n return \"skipped\";\n }\n // Previous execution appears hung; force reset and re-execute.\n console.warn(\n `Forcing reset of hung interval schedule ${row.id} (started ${elapsedSeconds}s ago)`\n );\n }\n\n if (row.type === \"interval\") {\n this.#sql`\n UPDATE cf_agents_schedules\n SET running = 1, execution_started_at = ${now}\n WHERE id = ${row.id}\n `;\n }\n\n let executed = false;\n if (row.owner_path) {\n try {\n executed = (await this.lifecycle.routes.to(\n { key: row.owner_path_key ?? row.owner_path, data: row.owner_path },\n { type: \"dispatch\", row } satisfies SchedulerRouteMessage\n )) as boolean;\n } catch (error) {\n console.error(\n `error dispatching scheduled callback \"${row.callback}\"`,\n error\n );\n this.#emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: error instanceof Error ? error.message : String(error),\n attempts: 0\n });\n try {\n await this.#onError?.(error);\n } catch {\n // swallow onError errors\n }\n // Reset the in-flight flag for interval rows so the row doesn't stay\n // stuck in `running=1` when dispatch fails (for example, a transport\n // can no longer resolve its owner). The next alarm cycle will retry.\n if (row.type === \"interval\") {\n this.#sql`\n UPDATE cf_agents_schedules SET running = 0 WHERE id = ${row.id}\n `;\n }\n return \"skipped\";\n }\n } else {\n // Retain the row ID while callback execution can escape so a host\n // failure policy can target the exact looping row without owning\n // storage.\n this.#executingRowId = row.id;\n await this.#executeCallback(row);\n this.#executingRowId = undefined;\n executed = true;\n }\n\n // A callback may have destroyed the host; its storage is gone.\n if (this.lifecycle.alarms.disabled()) return \"stop\";\n return executed ? \"executed\" : \"skipped\";\n }\n\n /** Reschedule a recurring row or delete an executed one-shot row. */\n #advanceRow(row: ScheduleStorageRow): void {\n if (row.type === \"cron\") {\n const nextTimestamp = Math.floor(\n nextCronTimeMs(row.cron ?? \"\", Date.now()) / 1000\n );\n this.#sql`\n UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}\n `;\n } else if (row.type === \"interval\") {\n const nextTimestamp =\n Math.floor(Date.now() / 1000) + (row.intervalSeconds ?? 0);\n this.#sql`\n UPDATE cf_agents_schedules\n SET running = 0, time = ${nextTimestamp}\n WHERE id = ${row.id}\n `;\n } else {\n this.#sql`\n DELETE FROM cf_agents_schedules WHERE id = ${row.id}\n `;\n }\n }\n\n // ── Alarm contribution ───────────────────────────────────────────────────\n\n /**\n * Earliest wall-clock time (ms) a schedule row is ready to execute,\n * clamped to the future, or `null` when no row qualifies.\n */\n #nextScheduleTimeMs(nowMs: number, hungCutoffSeconds: number): number | null {\n // Find the earliest schedule row that is safe to execute now, even if it\n // is already overdue. Overdue schedules can happen after a DO restart\n // because the SQLite row survives but the in-memory alarm does not.\n const readySchedules = this.#sql<{ time: number }>`\n SELECT time FROM cf_agents_schedules\n WHERE type != 'interval'\n OR running = 0\n OR coalesce(execution_started_at, 0) <= ${hungCutoffSeconds}\n ORDER BY time ASC\n LIMIT 1\n `;\n\n if (readySchedules.length > 0 && \"time\" in readySchedules[0]) {\n return Math.max(readySchedules[0].time * 1000, nowMs + 1);\n }\n return null;\n }\n\n /**\n * Wall-clock time (ms) at which the earliest still-running (not yet hung)\n * interval schedule crosses the hung timeout and must be re-checked, or\n * `null` when none is running.\n */\n #nextHungIntervalRecheckMs(hungCutoffSeconds: number): number | null {\n // Running interval schedules that are not hung yet still need a future\n // alarm so the runtime can re-check them once they cross the hung timeout.\n const recoveringIntervals = this.#sql<{\n execution_started_at: number | null;\n }>`\n SELECT execution_started_at FROM cf_agents_schedules\n WHERE type = 'interval'\n AND running = 1\n AND coalesce(execution_started_at, 0) > ${hungCutoffSeconds}\n ORDER BY execution_started_at ASC\n LIMIT 1\n `;\n\n const startedAt = recoveringIntervals[0]?.execution_started_at;\n if (startedAt !== null && startedAt !== undefined) {\n return (startedAt + this.#hungScheduleTimeoutSeconds) * 1000;\n }\n return null;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,224 @@
1
+ import {
2
+ s as LifecycleCapability,
3
+ u as LifecycleRouteContext
4
+ } from "./capability-runner-CvHGZqUu.js";
5
+ import { t as RetryOptions } from "./retries-CAvxtG9d.js";
6
+
7
+ //#region src/schedules/types.d.ts
8
+ /**
9
+ * A persisted task scheduled by an Agent.
10
+ *
11
+ * @template T Type of the callback payload.
12
+ */
13
+ type Schedule<T = string> = {
14
+ /** Unique schedule identifier. */ id: string /** Name of the Agent method invoked by the schedule. */;
15
+ callback: string /** Data passed to the callback. */;
16
+ payload: T /** Retry policy for callback execution. */;
17
+ retry?: RetryOptions;
18
+ } & (
19
+ | {
20
+ /** One-time execution at a specific date. */ type: "scheduled" /** Unix timestamp in seconds. */;
21
+ time: number;
22
+ }
23
+ | {
24
+ /** One-time execution after a relative delay. */ type: "delayed" /** Unix timestamp in seconds. */;
25
+ time: number /** Delay from creation in seconds. */;
26
+ delayInSeconds: number;
27
+ }
28
+ | {
29
+ /** Recurring execution from a cron expression. */ type: "cron" /** Unix timestamp in seconds for the next execution. */;
30
+ time: number /** Cron expression defining the recurrence. */;
31
+ cron: string;
32
+ }
33
+ | {
34
+ /** Recurring execution at a fixed interval. */ type: "interval" /** Unix timestamp in seconds for the next execution. */;
35
+ time: number /** Number of seconds between executions. */;
36
+ intervalSeconds: number;
37
+ }
38
+ );
39
+ /**
40
+ * Constraint for a Scheduler's registered callback map: named handlers
41
+ * receiving the parsed payload and the schedule that fired.
42
+ *
43
+ * @experimental The API surface may change before stabilizing.
44
+ */
45
+ type SchedulerHandlers = Record<
46
+ string,
47
+ (payload: never, schedule: never) => unknown
48
+ >;
49
+ /**
50
+ * Default callback surface for a Scheduler constructed without registered
51
+ * callbacks: any name compiles with an untyped payload. At runtime a name
52
+ * must be registered or supplied by a composition-root resolver (the
53
+ * aperture behind Agent's name-based scheduling API); a bare Scheduler
54
+ * rejects it otherwise.
55
+ *
56
+ * @experimental The API surface may change before stabilizing.
57
+ */
58
+ type SchedulerCallbacks = Record<
59
+ string,
60
+ (payload: unknown, schedule: Schedule<unknown>) => unknown
61
+ >;
62
+ /**
63
+ * The payload type a registered scheduler callback accepts.
64
+ *
65
+ * @experimental The API surface may change before stabilizing.
66
+ */
67
+ type SchedulerPayload<Handler> = Handler extends (
68
+ payload: infer Payload,
69
+ ...rest: never[]
70
+ ) => unknown
71
+ ? Payload
72
+ : never;
73
+ /** Options accepted when creating one schedule. */
74
+ type ScheduleOptions = {
75
+ /** Retry policy for callback execution, overriding the Scheduler default. */ retry?: RetryOptions;
76
+ /**
77
+ * Deduplicate onto an existing matching schedule instead of creating a new
78
+ * row. Defaults to `true` for cron and interval schedules, `false` for
79
+ * one-shot schedules.
80
+ */
81
+ idempotent?: boolean;
82
+ };
83
+ /** Filters accepted by `getSchedules()` and `listSchedules()`. */
84
+ type ScheduleCriteria = {
85
+ id?: string;
86
+ type?: "scheduled" | "delayed" | "cron" | "interval";
87
+ timeRange?: {
88
+ start?: Date;
89
+ end?: Date;
90
+ };
91
+ };
92
+ //#endregion
93
+ //#region src/schedules/options.d.ts
94
+ /** Events emitted while a Scheduler creates, executes, retries, or cancels work. */
95
+ type SchedulerEventType =
96
+ | "schedule:create"
97
+ | "schedule:cancel"
98
+ | "schedule:execute"
99
+ | "schedule:retry"
100
+ | "schedule:error"
101
+ | "schedule:duplicate_warning";
102
+ /**
103
+ * Optional callbacks and policy for a Scheduler capability.
104
+ *
105
+ * @experimental The API surface may change before stabilizing.
106
+ */
107
+ interface SchedulerOptions<
108
+ Handlers extends SchedulerHandlers = SchedulerCallbacks
109
+ > {
110
+ /**
111
+ * Named callbacks this Scheduler can run. Each schedule row persists a
112
+ * callback name; registration in a field initializer re-binds the names on
113
+ * every Durable Object wake, so register unconditionally. Names outside
114
+ * this map are rejected unless a composition-root resolver supplies them
115
+ * — the internal aperture behind `Agent`'s name-based scheduling API.
116
+ */
117
+ readonly callbacks?: Handlers;
118
+ /** Default callback retry policy. */
119
+ readonly retry?: RetryOptions;
120
+ /** Seconds before an in-flight interval is treated as abandoned. Default: 30. */
121
+ readonly hungScheduleTimeoutSeconds?: number;
122
+ /** Observe terminal callback errors. Runs as capability code without host context. */
123
+ readonly onError?: (error: unknown) => void | Promise<void>;
124
+ }
125
+ //#endregion
126
+ //#region src/schedules/scheduler.d.ts
127
+ /**
128
+ * Persistent task scheduling for a Lifecycle Object.
129
+ *
130
+ * Register callbacks in the constructor and install the instance with
131
+ * `Lifecycle.use()`. Scheduler owns its SQL schema, task CRUD, callback
132
+ * retries, and due-row processing. It contributes its next wake time while
133
+ * Lifecycle owns the physical alarm, and it runs registered callbacks
134
+ * through Lifecycle's host invocation boundary.
135
+ *
136
+ * @experimental The API surface may change before stabilizing.
137
+ */
138
+ declare class Scheduler<
139
+ Handlers extends SchedulerHandlers = SchedulerCallbacks
140
+ > extends LifecycleCapability {
141
+ #private;
142
+ /**
143
+ * Create a persistent Scheduler.
144
+ *
145
+ * @param options - Registered callbacks plus optional retry,
146
+ * hung-interval, and error policy. Registering `callbacks` types
147
+ * {@link set} and {@link every} against the map — names and
148
+ * payloads are checked where the handlers are declared and where they are
149
+ * scheduled. Names outside the map are rejected unless a composition-root
150
+ * resolver supplies them — the internal aperture behind `Agent`'s
151
+ * name-based scheduling API.
152
+ */
153
+ constructor(options?: SchedulerOptions<Handlers>);
154
+ /** Initialize and migrate schedule storage during Lifecycle startup. */
155
+ onStart(): Promise<void>;
156
+ /** Execute due schedule rows during the Lifecycle alarm phase. */
157
+ onAlarm(): Promise<void>;
158
+ /** Handle Scheduler protocol messages routed by another Lifecycle. */
159
+ onRoute(context: LifecycleRouteContext): Promise<unknown>;
160
+ /** Contribute the earliest pending schedule to Lifecycle alarm selection. */
161
+ getNextAlarm(): number | null;
162
+ /** Set a delayed, dated, or cron schedule for a registered callback. */
163
+ set<Name extends keyof Handlers & string>(
164
+ when: Date | string | number,
165
+ callback: Name,
166
+ payload?: SchedulerPayload<Handlers[Name]>,
167
+ options?: ScheduleOptions
168
+ ): Promise<Schedule<SchedulerPayload<Handlers[Name]>>>;
169
+ /** Set a fixed-interval schedule for a registered callback. */
170
+ every<Name extends keyof Handlers & string>(
171
+ intervalSeconds: number,
172
+ callback: Name,
173
+ payload?: SchedulerPayload<Handlers[Name]>,
174
+ options?: ScheduleOptions
175
+ ): Promise<Schedule<SchedulerPayload<Handlers[Name]>>>;
176
+ /** Get a schedule by ID. Works inside routed sub-agents. */
177
+ get(id: string): Promise<Schedule<unknown> | undefined>;
178
+ /** List schedules matching criteria. Works inside routed sub-agents. */
179
+ list(criteria?: ScheduleCriteria): Promise<Schedule<unknown>[]>;
180
+ /**
181
+ * Cancel one schedule owned by this Scheduler.
182
+ *
183
+ * @param id - ID of the schedule to cancel.
184
+ * @returns True when a schedule was cancelled, false when none matched.
185
+ */
186
+ cancel(id: string): Promise<boolean>;
187
+ /**
188
+ * @internal Synchronous read backing Agent's deprecated `getSchedule()`.
189
+ * Not part of the primitive's contract — use {@link get}. Cannot cross
190
+ * Durable Object boundaries and throws inside routed sub-agents.
191
+ */
192
+ __DO_NOT_USE_WILL_REMOVE__getSchedule<T = string>(
193
+ id: string
194
+ ): Schedule<T> | undefined;
195
+ /**
196
+ * @internal Synchronous read backing Agent's deprecated `getSchedules()`.
197
+ * Not part of the primitive's contract — use {@link list}. Cannot cross
198
+ * Durable Object boundaries and throws inside routed sub-agents.
199
+ */
200
+ __DO_NOT_USE_WILL_REMOVE__getSchedules<T = string>(
201
+ criteria?: ScheduleCriteria
202
+ ): Schedule<T>[];
203
+ /** @internal Remove rows owned by one routed Lifecycle subtree. */
204
+ __DO_NOT_USE_WILL_BREAK__cleanupRoutePrefix(prefix: string): void;
205
+ /** @internal Apply Agent's outer alarm memory-limit policy to Scheduler rows. */
206
+ __DO_NOT_USE_WILL_BREAK__handleAlarmMemoryLimit(options: {
207
+ readonly callbacks: ReadonlyArray<string>;
208
+ readonly sealed: boolean;
209
+ readonly nextTime?: number;
210
+ }): void;
211
+ }
212
+ //#endregion
213
+ export {
214
+ ScheduleCriteria as a,
215
+ SchedulerHandlers as c,
216
+ Schedule as i,
217
+ SchedulerPayload as l,
218
+ SchedulerEventType as n,
219
+ ScheduleOptions as o,
220
+ SchedulerOptions as r,
221
+ SchedulerCallbacks as s,
222
+ Scheduler as t
223
+ };
224
+ //# sourceMappingURL=scheduler-DQoTGoAW.d.ts.map
@@ -0,0 +1,22 @@
1
+ import {
2
+ a as ScheduleCriteria,
3
+ c as SchedulerHandlers,
4
+ i as Schedule,
5
+ l as SchedulerPayload,
6
+ n as SchedulerEventType,
7
+ o as ScheduleOptions,
8
+ r as SchedulerOptions,
9
+ s as SchedulerCallbacks,
10
+ t as Scheduler
11
+ } from "../scheduler-DQoTGoAW.js";
12
+ export {
13
+ type Schedule,
14
+ type ScheduleCriteria,
15
+ type ScheduleOptions,
16
+ Scheduler,
17
+ type SchedulerCallbacks,
18
+ type SchedulerEventType,
19
+ type SchedulerHandlers,
20
+ type SchedulerOptions,
21
+ type SchedulerPayload
22
+ };
@@ -0,0 +1,2 @@
1
+ import { t as Scheduler } from "../scheduler-CR9RHGos.js";
2
+ export { Scheduler };
@@ -0,0 +1,79 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/schedules/parser.d.ts
4
+ /**
5
+ * Get the schedule prompt for a given event
6
+ * @param event - The event to get the schedule prompt for
7
+ * @returns The schedule prompt
8
+ */
9
+ declare function getSchedulePrompt(event: { date: Date }): string;
10
+ /**
11
+ * The schema for parsing natural language scheduling requests.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { generateObject } from "ai";
16
+ * import { scheduleSchema, getSchedulePrompt } from "agents/schedules/parser";
17
+ *
18
+ * const result = await generateObject({
19
+ * model,
20
+ * prompt: `${getSchedulePrompt({ date: new Date() })} Input: "${userInput}"`,
21
+ * schema: scheduleSchema,
22
+ * // Required for OpenAI to avoid strict JSON schema validation errors
23
+ * providerOptions: {
24
+ * openai: { strictJsonSchema: false }
25
+ * }
26
+ * });
27
+ * ```
28
+ *
29
+ * @remarks
30
+ * When using this schema with OpenAI models via the AI SDK, you must pass
31
+ * `providerOptions: { openai: { strictJsonSchema: false } }` to `generateObject`.
32
+ * This is because the schema uses a discriminated union which is not compatible
33
+ * with OpenAI's strict structured outputs mode.
34
+ */
35
+ declare const scheduleSchema: z.ZodObject<
36
+ {
37
+ description: z.ZodString;
38
+ when: z.ZodDiscriminatedUnion<
39
+ [
40
+ z.ZodObject<
41
+ {
42
+ type: z.ZodLiteral<"scheduled">;
43
+ date: z.ZodString;
44
+ },
45
+ z.core.$strip
46
+ >,
47
+ z.ZodObject<
48
+ {
49
+ type: z.ZodLiteral<"delayed">;
50
+ delayInSeconds: z.ZodNumber;
51
+ },
52
+ z.core.$strip
53
+ >,
54
+ z.ZodObject<
55
+ {
56
+ type: z.ZodLiteral<"cron">;
57
+ cron: z.ZodString;
58
+ },
59
+ z.core.$strip
60
+ >,
61
+ z.ZodObject<
62
+ {
63
+ type: z.ZodLiteral<"no-schedule">;
64
+ },
65
+ z.core.$strip
66
+ >
67
+ ],
68
+ "type"
69
+ >;
70
+ },
71
+ z.core.$strip
72
+ >;
73
+ /**
74
+ * The type for the schedule prompt
75
+ */
76
+ type ParsedSchedule = z.infer<typeof scheduleSchema>;
77
+ //#endregion
78
+ export { ParsedSchedule, getSchedulePrompt, scheduleSchema };
79
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1,103 @@
1
+ import { z } from "zod";
2
+ //#region src/schedules/parser.ts
3
+ /**
4
+ * Get the schedule prompt for a given event
5
+ * @param event - The event to get the schedule prompt for
6
+ * @returns The schedule prompt
7
+ */
8
+ function getSchedulePrompt(event) {
9
+ return `
10
+ [Schedule Parser Component]
11
+
12
+ Current time: ${event.date.toUTCString()}
13
+
14
+ This component parses natural language scheduling requests into a structured format. It extracts:
15
+ 1. A clean task description (without timing information)
16
+ 2. Scheduling details in one of these formats:
17
+ - scheduled: Specific date/time events
18
+ - delayed: Relative time delays (in seconds)
19
+ - cron: Recurring patterns
20
+ - no-schedule: Tasks without timing
21
+
22
+ Rules:
23
+ - Task descriptions should be clean and focused on the action
24
+ - Use numbers (0-6) for days in cron patterns (0=Sunday)
25
+ - For recurring tasks, use standard cron syntax
26
+ - For relative times, convert to seconds
27
+ - For specific dates, use the current time as reference
28
+
29
+ Example outputs:
30
+ {
31
+ "description": "meeting with team",
32
+ "when": {
33
+ "type": "scheduled",
34
+ "date": "tomorrow at 14:00"
35
+ }
36
+ }
37
+
38
+ {
39
+ "description": "backup database",
40
+ "when": {
41
+ "type": "cron",
42
+ "cron": "0 0 * * *"
43
+ }
44
+ }
45
+
46
+ {
47
+ "description": "send report",
48
+ "when": {
49
+ "type": "delayed",
50
+ "delayInSeconds": 1800
51
+ }
52
+ }
53
+
54
+ [End Schedule Parser Component]
55
+ `;
56
+ }
57
+ /**
58
+ * The schema for parsing natural language scheduling requests.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { generateObject } from "ai";
63
+ * import { scheduleSchema, getSchedulePrompt } from "agents/schedules/parser";
64
+ *
65
+ * const result = await generateObject({
66
+ * model,
67
+ * prompt: `${getSchedulePrompt({ date: new Date() })} Input: "${userInput}"`,
68
+ * schema: scheduleSchema,
69
+ * // Required for OpenAI to avoid strict JSON schema validation errors
70
+ * providerOptions: {
71
+ * openai: { strictJsonSchema: false }
72
+ * }
73
+ * });
74
+ * ```
75
+ *
76
+ * @remarks
77
+ * When using this schema with OpenAI models via the AI SDK, you must pass
78
+ * `providerOptions: { openai: { strictJsonSchema: false } }` to `generateObject`.
79
+ * This is because the schema uses a discriminated union which is not compatible
80
+ * with OpenAI's strict structured outputs mode.
81
+ */
82
+ const scheduleSchema = z.object({
83
+ description: z.string().describe("A description of the task"),
84
+ when: z.discriminatedUnion("type", [
85
+ z.object({
86
+ type: z.literal("scheduled"),
87
+ date: z.string().describe("Execute task at the specified date and time in ISO 8601 format")
88
+ }),
89
+ z.object({
90
+ type: z.literal("delayed"),
91
+ delayInSeconds: z.number().describe("Execute task after a delay in seconds")
92
+ }),
93
+ z.object({
94
+ type: z.literal("cron"),
95
+ cron: z.string().describe("Execute task on a recurring interval specified as cron syntax")
96
+ }),
97
+ z.object({ type: z.literal("no-schedule") })
98
+ ])
99
+ });
100
+ //#endregion
101
+ export { getSchedulePrompt, scheduleSchema };
102
+
103
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","names":[],"sources":["../../src/schedules/parser.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Get the schedule prompt for a given event\n * @param event - The event to get the schedule prompt for\n * @returns The schedule prompt\n */\nexport function getSchedulePrompt(event: { date: Date }) {\n return `\n[Schedule Parser Component]\n\nCurrent time: ${event.date.toUTCString()}\n\nThis component parses natural language scheduling requests into a structured format. It extracts:\n1. A clean task description (without timing information)\n2. Scheduling details in one of these formats:\n - scheduled: Specific date/time events\n - delayed: Relative time delays (in seconds)\n - cron: Recurring patterns\n - no-schedule: Tasks without timing\n\nRules:\n- Task descriptions should be clean and focused on the action\n- Use numbers (0-6) for days in cron patterns (0=Sunday)\n- For recurring tasks, use standard cron syntax\n- For relative times, convert to seconds\n- For specific dates, use the current time as reference\n\nExample outputs:\n{\n \"description\": \"meeting with team\",\n \"when\": {\n \"type\": \"scheduled\",\n \"date\": \"tomorrow at 14:00\"\n }\n}\n\n{\n \"description\": \"backup database\",\n \"when\": {\n \"type\": \"cron\",\n \"cron\": \"0 0 * * *\"\n }\n}\n\n{\n \"description\": \"send report\",\n \"when\": {\n \"type\": \"delayed\",\n \"delayInSeconds\": 1800\n }\n}\n\n[End Schedule Parser Component]\n`;\n}\n\n/**\n * The schema for parsing natural language scheduling requests.\n *\n * @example\n * ```typescript\n * import { generateObject } from \"ai\";\n * import { scheduleSchema, getSchedulePrompt } from \"agents/schedules/parser\";\n *\n * const result = await generateObject({\n * model,\n * prompt: `${getSchedulePrompt({ date: new Date() })} Input: \"${userInput}\"`,\n * schema: scheduleSchema,\n * // Required for OpenAI to avoid strict JSON schema validation errors\n * providerOptions: {\n * openai: { strictJsonSchema: false }\n * }\n * });\n * ```\n *\n * @remarks\n * When using this schema with OpenAI models via the AI SDK, you must pass\n * `providerOptions: { openai: { strictJsonSchema: false } }` to `generateObject`.\n * This is because the schema uses a discriminated union which is not compatible\n * with OpenAI's strict structured outputs mode.\n */\nexport const scheduleSchema = z.object({\n description: z.string().describe(\"A description of the task\"),\n when: z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"scheduled\"),\n date: z\n .string()\n .describe(\n \"Execute task at the specified date and time in ISO 8601 format\"\n )\n }),\n z.object({\n type: z.literal(\"delayed\"),\n delayInSeconds: z\n .number()\n .describe(\"Execute task after a delay in seconds\")\n }),\n z.object({\n type: z.literal(\"cron\"),\n cron: z\n .string()\n .describe(\n \"Execute task on a recurring interval specified as cron syntax\"\n )\n }),\n z.object({\n type: z.literal(\"no-schedule\")\n })\n ])\n});\n\n/**\n * The type for the schedule prompt\n */\nexport type ParsedSchedule = z.infer<typeof scheduleSchema>;\n"],"mappings":";;;;;;;AAOA,SAAgB,kBAAkB,OAAuB;CACvD,OAAO;;;gBAGO,MAAM,KAAK,YAAY,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CzC;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BA,MAAa,iBAAiB,EAAE,OAAO;CACrC,aAAa,EAAE,OAAO,CAAC,CAAC,SAAS,2BAA2B;CAC5D,MAAM,EAAE,mBAAmB,QAAQ;EACjC,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,WAAW;GAC3B,MAAM,EACH,OAAO,CAAC,CACR,SACC,gEACF;EACJ,CAAC;EACD,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,SAAS;GACzB,gBAAgB,EACb,OAAO,CAAC,CACR,SAAS,uCAAuC;EACrD,CAAC;EACD,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,MAAM;GACtB,MAAM,EACH,OAAO,CAAC,CACR,SACC,+DACF;EACJ,CAAC;EACD,EAAE,OAAO,EACP,MAAM,EAAE,QAAQ,aAAa,EAC/B,CAAC;CACH,CAAC;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- import { st as StreamingResponse } from "./agent-tool-types-CzGGB-20.js";
1
+ import { j as StreamingResponse } from "./agent-routing-CnkaHb-v.js";
2
2
 
3
3
  //#region src/serializable.d.ts
4
4
  type SerializablePrimitive = undefined | null | string | number | boolean;
@@ -0,0 +1,12 @@
1
+ //#region src/sql-error.d.ts
2
+ /**
3
+ * Error class for SQL execution failures, containing the query that failed.
4
+ */
5
+ declare class SqlError extends Error {
6
+ /** The SQL query that failed */
7
+ readonly query: string;
8
+ constructor(query: string, cause: unknown);
9
+ }
10
+ //#endregion
11
+ export { SqlError as t };
12
+ //# sourceMappingURL=sql-error-CPY-GXyI.d.ts.map
@@ -0,0 +1,2 @@
1
+ import { t as SqlError } from "./sql-error-CPY-GXyI.js";
2
+ export { SqlError };
@@ -0,0 +1,16 @@
1
+ //#region src/sql-error.ts
2
+ /**
3
+ * Error class for SQL execution failures, containing the query that failed.
4
+ */
5
+ var SqlError = class extends Error {
6
+ constructor(query, cause) {
7
+ const message = cause instanceof Error ? cause.message : String(cause);
8
+ super(`SQL query failed: ${message}`, { cause });
9
+ this.name = "SqlError";
10
+ this.query = query;
11
+ }
12
+ };
13
+ //#endregion
14
+ export { SqlError };
15
+
16
+ //# sourceMappingURL=sql-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-error.js","names":[],"sources":["../src/sql-error.ts"],"sourcesContent":["/**\n * Error class for SQL execution failures, containing the query that failed.\n */\nexport class SqlError extends Error {\n /** The SQL query that failed */\n readonly query: string;\n\n constructor(query: string, cause: unknown) {\n const message = cause instanceof Error ? cause.message : String(cause);\n super(`SQL query failed: ${message}`, { cause });\n this.name = \"SqlError\";\n this.query = query;\n }\n}\n"],"mappings":";;;;AAGA,IAAa,WAAb,cAA8B,MAAM;CAIlC,YAAY,OAAe,OAAgB;EACzC,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,MAAM,qBAAqB,WAAW,EAAE,MAAM,CAAC;EAC/C,KAAK,OAAO;EACZ,KAAK,QAAQ;CACf;AACF"}