@keystrokehq/scheduler 0.0.66

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dallin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # @keystrokehq/scheduler
2
+
3
+ **Layer:** `platform`
4
+
5
+ Job queue and cron/poll schedule sync for [keystroke](../../README.md). Enqueues workflow, agent, and trigger work; ticks due schedules into the queue. No HTTP, no attachment execution, no trigger source definitions.
6
+
7
+ ## What it does
8
+
9
+ - **`createScheduler`** — queue backend from `SchedulerPlugin` (default: pg-boss on Postgres, Drizzle job table on SQLite), then expose `enqueue`, `startWorker`, `syncTriggerSchedules`, `startScheduleTicker`, and `fireDueSchedules`.
10
+ - **`SchedulerPlugin`** — swap backends (`defaultSchedulerPlugin()`, or cloud `@cloud/bull-mq-plugin` BullMQ).
11
+ - **`createMemoryJobQueue`** — in-process queue for tests (optional `sync: true` drain).
12
+ - **Job types** — `JobQueue`, `Scheduler`, `JobHandler`, `EnqueueInput`, `JobTrigger`, `StopFn` for server handlers and enqueue helpers.
13
+ - **Schedule sync** — `syncTriggerSchedules` (on `Scheduler`) upserts rows in `trigger_schedules` via `@keystrokehq/database`, resolving cron strings with **`resolveCronSchedule`** and next run times with **`nextTriggerRunAt`** from `@keystrokehq/trigger`.
14
+ - **Schedule ticker** — background loop claims due schedules and enqueues `kind: "trigger"` jobs.
15
+
16
+ Queue implementations (`database-queue`, `pg-boss-queue`) and standalone `syncTriggerSchedules` / `resolveTriggerSchedule` stay internal unless a consumer needs them in a follow-up.
17
+
18
+ ## What belongs somewhere else
19
+
20
+ - Trigger source defs (`defineCronSource`, poll cadence) → `@keystrokehq/trigger`
21
+ - Running attachments, webhooks, poll HTTP → `@keystrokehq/server`
22
+ - `trigger_schedules` / `jobs` schema and queries → `@keystrokehq/database`
23
+ - Workflow/agent run logic → `@keystrokehq/workflow` / `@keystrokehq/agent` (server wires handlers)
24
+
25
+ ## Where it sits
26
+
27
+ ```mermaid
28
+ flowchart TB
29
+ scheduler["@keystrokehq/scheduler"]
30
+
31
+ database["@keystrokehq/database"]
32
+ trigger["@keystrokehq/trigger"]
33
+
34
+ scheduler --> database
35
+ scheduler --> trigger
36
+ ```
37
+
38
+ **Allowed runtime deps:** `database`, `trigger`, `pg-boss`, `cron-schedule` (via trigger).
39
+
40
+ **Forbidden:** `server`, `workflow`, `agent`, `action`, `config`, `build`, `cli`, integrations, HTTP frameworks. Scheduler must stay callable from server without circular imports.
41
+
42
+ **Depends on:** `database`, `trigger`, `pg-boss`, `cron-schedule`.
43
+
44
+ **Used by:** `server` (embedded worker + schedule ticker), re-exports `createScheduler` / `Scheduler` from `@keystrokehq/server` for apps.
45
+
46
+ ## Exports
47
+
48
+ Import from the package root (`@keystrokehq/scheduler`), not from `src/…`.
49
+
50
+ | Export | What it's for |
51
+ | ------------------------ | --------------------------------------------------------- |
52
+ | `createScheduler` | Production queue + schedule APIs |
53
+ | `SchedulerPlugin` | Pluggable queue backend contract |
54
+ | `defaultSchedulerPlugin` | pg-boss (Postgres) / DB polling (SQLite) |
55
+ | `createSharedScheduler` | Platform shared queue (honors `configureSharedScheduler`) |
56
+ | `createMemoryJobQueue` | Test / dev in-process queue |
57
+ | `Scheduler` | Full surface (`JobQueue` + schedule sync/ticker) |
58
+ | `JobQueue` | Enqueue + worker only (typing server overrides) |
59
+ | `JobHandler` | Process one claimed job payload |
60
+ | `EnqueueInput` | Build enqueue calls from server |
61
+ | `JobTrigger` | `"api"` \| `"cron"` \| `"webhook"` \| `"poll"` \| … |
62
+ | `StopFn` | Stop worker or schedule ticker |
63
+ | `MemoryJobQueueOptions` | `{ sync?: boolean }` for memory queue |
64
+
65
+ ## Source layout
66
+
67
+ | File | What's in it |
68
+ | --------------------------- | ----------------------------------------------------------------- |
69
+ | `types.ts` | Job + scheduler types, retry backoff helper |
70
+ | `create-scheduler.ts` | `createScheduler`, `createJobQueue`, `wrapJobQueueAsScheduler` |
71
+ | `database-queue.ts` | SQLite / generic Postgres job table worker |
72
+ | `pg-boss-queue.ts` | Postgres pg-boss backend |
73
+ | `memory.ts` | In-memory `JobQueue` |
74
+ | `sync-trigger-schedules.ts` | DB upsert for discovered cron/poll attachments |
75
+ | `resolve-schedule.ts` | Override-aware cron string (uses trigger's `resolveCronSchedule`) |
76
+ | `schedule-ticker.ts` | Claim due schedules → enqueue trigger jobs |
77
+
78
+ ## Adding a feature?
79
+
80
+ 1. New queue backend or retry/concurrency behavior? → this package (keep types in `types.ts`).
81
+ 2. New trigger schedule expression rules? → `@keystrokehq/trigger` (`nextTriggerRunAt`, `resolveCronSchedule`).
82
+ 3. New table or claim query? → `@keystrokehq/database`.
83
+ 4. Who runs the job (workflow step, agent prompt, attachment)? → `@keystrokehq/server` job handlers.
84
+
85
+ ## Example
86
+
87
+ ```typescript
88
+ import { createScheduler } from "@keystrokehq/scheduler";
89
+ import { initDatabase } from "@keystrokehq/database";
90
+
91
+ await initDatabase({ url: process.env.DATABASE_URL });
92
+
93
+ const scheduler = await createScheduler({ url: process.env.DATABASE_URL });
94
+
95
+ await scheduler.syncTriggerSchedules({
96
+ schedules: [{ attachmentKey: "daily-report:run", kind: "cron", schedule: "0 9 * * *" }],
97
+ });
98
+
99
+ const stopWorker = await scheduler.startWorker(async (job) => {
100
+ console.log(job.kind, job.targetId, job.trigger);
101
+ });
102
+
103
+ const stopTicker = await scheduler.startScheduleTicker();
104
+
105
+ // … later
106
+ await stopTicker();
107
+ await stopWorker();
108
+ ```
109
+
110
+ ## Tests
111
+
112
+ ```bash
113
+ pnpm --filter @keystrokehq/scheduler test
114
+ pnpm --filter @keystrokehq/scheduler typecheck
115
+ ```
116
+
117
+ Unit: `*.test.ts`. Integration (`queue.int.test.ts`): Postgres pg-boss via `describePostgres`; SQLite DB queue uses in-memory DB.
118
+
119
+ ## See also
120
+
121
+ - [README.md](../../README.md) — platform layer map
122
+ - [packages/server/src/server.ts](../server/src/server.ts) — wires scheduler at listen
123
+ - [packages/trigger/](../trigger/) — cron parsing and `nextTriggerRunAt`
124
+ - [packages/database/src/scheduler/](../database/src/scheduler/) — jobs + `trigger_schedules` queries
@@ -0,0 +1,31 @@
1
+ //#region src/types.ts
2
+ const DEFAULT_RETRY_DELAY_MS = 5e3;
3
+ function retryDelayMs(attempt) {
4
+ return DEFAULT_RETRY_DELAY_MS * 2 ** Math.max(0, attempt - 1);
5
+ }
6
+ //#endregion
7
+ //#region src/contract.ts
8
+ function defineSchedulerPlugin(plugin) {
9
+ return plugin;
10
+ }
11
+ //#endregion
12
+ Object.defineProperty(exports, "DEFAULT_RETRY_DELAY_MS", {
13
+ enumerable: true,
14
+ get: function() {
15
+ return DEFAULT_RETRY_DELAY_MS;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "defineSchedulerPlugin", {
19
+ enumerable: true,
20
+ get: function() {
21
+ return defineSchedulerPlugin;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "retryDelayMs", {
25
+ enumerable: true,
26
+ get: function() {
27
+ return retryDelayMs;
28
+ }
29
+ });
30
+
31
+ //# sourceMappingURL=contract-C5JvbyQ-.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-C5JvbyQ-.cjs","names":[],"sources":["../src/types.ts","../src/contract.ts"],"sourcesContent":["export type JobKind = \"workflow\" | \"agent\" | \"trigger\";\n\nexport type JobTrigger = \"api\" | \"cron\" | \"webhook\" | \"poll\" | \"retry\" | \"prompt\";\n\nexport type JobPayload = {\n kind: JobKind;\n targetId: string;\n runId: string;\n trigger: JobTrigger;\n payload: unknown;\n attempt: number;\n maxAttempts: number;\n scheduledAt: Date;\n jobId: string;\n};\n\nexport type EnqueueInput = {\n kind: JobKind;\n targetId: string;\n runId: string;\n trigger: JobTrigger;\n payload?: unknown;\n scheduledAt?: Date;\n attempt?: number;\n maxAttempts?: number;\n};\n\nexport type JobHandler = (job: JobPayload) => Promise<void>;\n\nexport type StopFn = () => Promise<void> | void;\n\nexport type WorkerOptions = {\n workerId?: string;\n pollIntervalMs?: number;\n leaseSweepIntervalMs?: number;\n};\n\nexport type JobQueue = {\n enqueue(input: EnqueueInput): Promise<string>;\n startWorker(handler: JobHandler, options?: WorkerOptions): Promise<StopFn>;\n};\n\nimport type { SchedulerPlugin, SchedulerScope } from \"./contract\";\n\nexport type CreateJobQueueOptions = {\n url?: string;\n dialect?: \"postgres\" | \"sqlite\";\n adapter?: JobQueue;\n plugin?: SchedulerPlugin;\n scope?: SchedulerScope;\n projectId?: string;\n organizationId?: string;\n};\n\nexport type TriggerScheduleSpec = {\n attachmentKey: string;\n kind: \"cron\" | \"poll\";\n schedule: string;\n};\n\nexport type ScheduleSyncOptions = {\n schedules: TriggerScheduleSpec[];\n scheduleOverrides?: {\n global?: string;\n byAttachment?: Record<string, string>;\n };\n};\n\nexport type ScheduleTickerOptions = {\n pollIntervalMs?: number;\n batchSize?: number;\n};\n\nexport type Scheduler = JobQueue & {\n syncTriggerSchedules(options: ScheduleSyncOptions): Promise<void>;\n startScheduleTicker(options?: ScheduleTickerOptions): Promise<StopFn>;\n fireDueSchedules(asOf?: Date): Promise<number>;\n};\n\nexport type CreateSchedulerOptions = CreateJobQueueOptions;\n\nexport const DEFAULT_RETRY_DELAY_MS = 5_000;\n\nexport function retryDelayMs(attempt: number): number {\n return DEFAULT_RETRY_DELAY_MS * 2 ** Math.max(0, attempt - 1);\n}\n","export type {\n JobKind,\n JobTrigger,\n JobPayload,\n EnqueueInput,\n JobHandler,\n StopFn,\n WorkerOptions,\n JobQueue,\n} from \"./types\";\nexport { retryDelayMs, DEFAULT_RETRY_DELAY_MS } from \"./types\";\n\nimport type { JobQueue } from \"./types\";\n\n/**\n * Inlined to keep the contract database-free — structurally identical to\n * `@keystrokehq/database`'s `DatabaseDialect`. Importing it from the database\n * package would re-introduce the dependency `./contract` exists to avoid.\n */\nexport type DatabaseDialect = \"postgres\" | \"sqlite\";\n\nexport type SchedulerScope = \"platform\" | \"project\";\n\nexport type SchedulerPluginContext = {\n scope: SchedulerScope;\n url?: string;\n dialect?: DatabaseDialect;\n projectId?: string;\n organizationId?: string;\n};\n\nexport type SchedulerPlugin = {\n name: string;\n createJobQueue(ctx: SchedulerPluginContext): Promise<JobQueue>;\n};\n\nexport function defineSchedulerPlugin(plugin: SchedulerPlugin): SchedulerPlugin {\n return plugin;\n}\n"],"mappings":";AAiFA,MAAa,yBAAyB;AAEtC,SAAgB,aAAa,SAAyB;CACpD,OAAO,yBAAyB,KAAK,KAAK,IAAI,GAAG,UAAU,CAAC;AAC9D;;;ACjDA,SAAgB,sBAAsB,QAA0C;CAC9E,OAAO;AACT"}
@@ -0,0 +1,92 @@
1
+ //#region src/types.d.ts
2
+ type JobKind = "workflow" | "agent" | "trigger";
3
+ type JobTrigger = "api" | "cron" | "webhook" | "poll" | "retry" | "prompt";
4
+ type JobPayload = {
5
+ kind: JobKind;
6
+ targetId: string;
7
+ runId: string;
8
+ trigger: JobTrigger;
9
+ payload: unknown;
10
+ attempt: number;
11
+ maxAttempts: number;
12
+ scheduledAt: Date;
13
+ jobId: string;
14
+ };
15
+ type EnqueueInput = {
16
+ kind: JobKind;
17
+ targetId: string;
18
+ runId: string;
19
+ trigger: JobTrigger;
20
+ payload?: unknown;
21
+ scheduledAt?: Date;
22
+ attempt?: number;
23
+ maxAttempts?: number;
24
+ };
25
+ type JobHandler = (job: JobPayload) => Promise<void>;
26
+ type StopFn = () => Promise<void> | void;
27
+ type WorkerOptions = {
28
+ workerId?: string;
29
+ pollIntervalMs?: number;
30
+ leaseSweepIntervalMs?: number;
31
+ };
32
+ type JobQueue = {
33
+ enqueue(input: EnqueueInput): Promise<string>;
34
+ startWorker(handler: JobHandler, options?: WorkerOptions): Promise<StopFn>;
35
+ };
36
+ type CreateJobQueueOptions = {
37
+ url?: string;
38
+ dialect?: "postgres" | "sqlite";
39
+ adapter?: JobQueue;
40
+ plugin?: SchedulerPlugin;
41
+ scope?: SchedulerScope;
42
+ projectId?: string;
43
+ organizationId?: string;
44
+ };
45
+ type TriggerScheduleSpec = {
46
+ attachmentKey: string;
47
+ kind: "cron" | "poll";
48
+ schedule: string;
49
+ };
50
+ type ScheduleSyncOptions = {
51
+ schedules: TriggerScheduleSpec[];
52
+ scheduleOverrides?: {
53
+ global?: string;
54
+ byAttachment?: Record<string, string>;
55
+ };
56
+ };
57
+ type ScheduleTickerOptions = {
58
+ pollIntervalMs?: number;
59
+ batchSize?: number;
60
+ };
61
+ type Scheduler = JobQueue & {
62
+ syncTriggerSchedules(options: ScheduleSyncOptions): Promise<void>;
63
+ startScheduleTicker(options?: ScheduleTickerOptions): Promise<StopFn>;
64
+ fireDueSchedules(asOf?: Date): Promise<number>;
65
+ };
66
+ type CreateSchedulerOptions = CreateJobQueueOptions;
67
+ declare const DEFAULT_RETRY_DELAY_MS = 5000;
68
+ declare function retryDelayMs(attempt: number): number;
69
+ //#endregion
70
+ //#region src/contract.d.ts
71
+ /**
72
+ * Inlined to keep the contract database-free — structurally identical to
73
+ * `@keystrokehq/database`'s `DatabaseDialect`. Importing it from the database
74
+ * package would re-introduce the dependency `./contract` exists to avoid.
75
+ */
76
+ type DatabaseDialect = "postgres" | "sqlite";
77
+ type SchedulerScope = "platform" | "project";
78
+ type SchedulerPluginContext = {
79
+ scope: SchedulerScope;
80
+ url?: string;
81
+ dialect?: DatabaseDialect;
82
+ projectId?: string;
83
+ organizationId?: string;
84
+ };
85
+ type SchedulerPlugin = {
86
+ name: string;
87
+ createJobQueue(ctx: SchedulerPluginContext): Promise<JobQueue>;
88
+ };
89
+ declare function defineSchedulerPlugin(plugin: SchedulerPlugin): SchedulerPlugin;
90
+ //#endregion
91
+ export { Scheduler as _, defineSchedulerPlugin as a, retryDelayMs as b, DEFAULT_RETRY_DELAY_MS as c, JobKind as d, JobPayload as f, ScheduleTickerOptions as g, ScheduleSyncOptions as h, SchedulerScope as i, EnqueueInput as l, JobTrigger as m, SchedulerPlugin as n, CreateJobQueueOptions as o, JobQueue as p, SchedulerPluginContext as r, CreateSchedulerOptions as s, DatabaseDialect as t, JobHandler as u, StopFn as v, WorkerOptions as y };
92
+ //# sourceMappingURL=contract-CYKkRmnH.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-CYKkRmnH.d.cts","names":[],"sources":["../src/types.ts","../src/contract.ts"],"mappings":";KAAY,OAAA;AAAA,KAEA,UAAA;AAAA,KAEA,UAAA;EACV,IAAA,EAAM,OAAA;EACN,QAAA;EACA,KAAA;EACA,OAAA,EAAS,UAAA;EACT,OAAA;EACA,OAAA;EACA,WAAA;EACA,WAAA,EAAa,IAAA;EACb,KAAA;AAAA;AAAA,KAGU,YAAA;EACV,IAAA,EAAM,OAAA;EACN,QAAA;EACA,KAAA;EACA,OAAA,EAAS,UAAA;EACT,OAAA;EACA,WAAA,GAAc,IAAA;EACd,OAAA;EACA,WAAA;AAAA;AAAA,KAGU,UAAA,IAAc,GAAA,EAAK,UAAA,KAAe,OAAO;AAAA,KAEzC,MAAA,SAAe,OAAO;AAAA,KAEtB,aAAA;EACV,QAAA;EACA,cAAA;EACA,oBAAA;AAAA;AAAA,KAGU,QAAA;EACV,OAAA,CAAQ,KAAA,EAAO,YAAA,GAAe,OAAA;EAC9B,WAAA,CAAY,OAAA,EAAS,UAAA,EAAY,OAAA,GAAU,aAAA,GAAgB,OAAA,CAAQ,MAAA;AAAA;AAAA,KAKzD,qBAAA;EACV,GAAA;EACA,OAAA;EACA,OAAA,GAAU,QAAA;EACV,MAAA,GAAS,eAAA;EACT,KAAA,GAAQ,cAAA;EACR,SAAA;EACA,cAAA;AAAA;AAAA,KAGU,mBAAA;EACV,aAAA;EACA,IAAA;EACA,QAAA;AAAA;AAAA,KAGU,mBAAA;EACV,SAAA,EAAW,mBAAA;EACX,iBAAA;IACE,MAAA;IACA,YAAA,GAAe,MAAM;EAAA;AAAA;AAAA,KAIb,qBAAA;EACV,cAAA;EACA,SAAS;AAAA;AAAA,KAGC,SAAA,GAAY,QAAA;EACtB,oBAAA,CAAqB,OAAA,EAAS,mBAAA,GAAsB,OAAA;EACpD,mBAAA,CAAoB,OAAA,GAAU,qBAAA,GAAwB,OAAA,CAAQ,MAAA;EAC9D,gBAAA,CAAiB,IAAA,GAAO,IAAA,GAAO,OAAA;AAAA;AAAA,KAGrB,sBAAA,GAAyB,qBAAqB;AAAA,cAE7C,sBAAA;AAAA,iBAEG,YAAA,CAAa,OAAe;;;;;AAnFzB;AAEnB;;KCiBY,eAAA;AAAA,KAEA,cAAA;AAAA,KAEA,sBAAA;EACV,KAAA,EAAO,cAAA;EACP,GAAA;EACA,OAAA,GAAU,eAAe;EACzB,SAAA;EACA,cAAA;AAAA;AAAA,KAGU,eAAA;EACV,IAAA;EACA,cAAA,CAAe,GAAA,EAAK,sBAAA,GAAyB,OAAA,CAAQ,QAAA;AAAA;AAAA,iBAGvC,qBAAA,CAAsB,MAAA,EAAQ,eAAA,GAAkB,eAAe"}
@@ -0,0 +1,92 @@
1
+ //#region src/types.d.ts
2
+ type JobKind = "workflow" | "agent" | "trigger";
3
+ type JobTrigger = "api" | "cron" | "webhook" | "poll" | "retry" | "prompt";
4
+ type JobPayload = {
5
+ kind: JobKind;
6
+ targetId: string;
7
+ runId: string;
8
+ trigger: JobTrigger;
9
+ payload: unknown;
10
+ attempt: number;
11
+ maxAttempts: number;
12
+ scheduledAt: Date;
13
+ jobId: string;
14
+ };
15
+ type EnqueueInput = {
16
+ kind: JobKind;
17
+ targetId: string;
18
+ runId: string;
19
+ trigger: JobTrigger;
20
+ payload?: unknown;
21
+ scheduledAt?: Date;
22
+ attempt?: number;
23
+ maxAttempts?: number;
24
+ };
25
+ type JobHandler = (job: JobPayload) => Promise<void>;
26
+ type StopFn = () => Promise<void> | void;
27
+ type WorkerOptions = {
28
+ workerId?: string;
29
+ pollIntervalMs?: number;
30
+ leaseSweepIntervalMs?: number;
31
+ };
32
+ type JobQueue = {
33
+ enqueue(input: EnqueueInput): Promise<string>;
34
+ startWorker(handler: JobHandler, options?: WorkerOptions): Promise<StopFn>;
35
+ };
36
+ type CreateJobQueueOptions = {
37
+ url?: string;
38
+ dialect?: "postgres" | "sqlite";
39
+ adapter?: JobQueue;
40
+ plugin?: SchedulerPlugin;
41
+ scope?: SchedulerScope;
42
+ projectId?: string;
43
+ organizationId?: string;
44
+ };
45
+ type TriggerScheduleSpec = {
46
+ attachmentKey: string;
47
+ kind: "cron" | "poll";
48
+ schedule: string;
49
+ };
50
+ type ScheduleSyncOptions = {
51
+ schedules: TriggerScheduleSpec[];
52
+ scheduleOverrides?: {
53
+ global?: string;
54
+ byAttachment?: Record<string, string>;
55
+ };
56
+ };
57
+ type ScheduleTickerOptions = {
58
+ pollIntervalMs?: number;
59
+ batchSize?: number;
60
+ };
61
+ type Scheduler = JobQueue & {
62
+ syncTriggerSchedules(options: ScheduleSyncOptions): Promise<void>;
63
+ startScheduleTicker(options?: ScheduleTickerOptions): Promise<StopFn>;
64
+ fireDueSchedules(asOf?: Date): Promise<number>;
65
+ };
66
+ type CreateSchedulerOptions = CreateJobQueueOptions;
67
+ declare const DEFAULT_RETRY_DELAY_MS = 5000;
68
+ declare function retryDelayMs(attempt: number): number;
69
+ //#endregion
70
+ //#region src/contract.d.ts
71
+ /**
72
+ * Inlined to keep the contract database-free — structurally identical to
73
+ * `@keystrokehq/database`'s `DatabaseDialect`. Importing it from the database
74
+ * package would re-introduce the dependency `./contract` exists to avoid.
75
+ */
76
+ type DatabaseDialect = "postgres" | "sqlite";
77
+ type SchedulerScope = "platform" | "project";
78
+ type SchedulerPluginContext = {
79
+ scope: SchedulerScope;
80
+ url?: string;
81
+ dialect?: DatabaseDialect;
82
+ projectId?: string;
83
+ organizationId?: string;
84
+ };
85
+ type SchedulerPlugin = {
86
+ name: string;
87
+ createJobQueue(ctx: SchedulerPluginContext): Promise<JobQueue>;
88
+ };
89
+ declare function defineSchedulerPlugin(plugin: SchedulerPlugin): SchedulerPlugin;
90
+ //#endregion
91
+ export { Scheduler as _, defineSchedulerPlugin as a, retryDelayMs as b, DEFAULT_RETRY_DELAY_MS as c, JobKind as d, JobPayload as f, ScheduleTickerOptions as g, ScheduleSyncOptions as h, SchedulerScope as i, EnqueueInput as l, JobTrigger as m, SchedulerPlugin as n, CreateJobQueueOptions as o, JobQueue as p, SchedulerPluginContext as r, CreateSchedulerOptions as s, DatabaseDialect as t, JobHandler as u, StopFn as v, WorkerOptions as y };
92
+ //# sourceMappingURL=contract-CYKkRmnH.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-CYKkRmnH.d.mts","names":[],"sources":["../src/types.ts","../src/contract.ts"],"mappings":";KAAY,OAAA;AAAA,KAEA,UAAA;AAAA,KAEA,UAAA;EACV,IAAA,EAAM,OAAA;EACN,QAAA;EACA,KAAA;EACA,OAAA,EAAS,UAAA;EACT,OAAA;EACA,OAAA;EACA,WAAA;EACA,WAAA,EAAa,IAAA;EACb,KAAA;AAAA;AAAA,KAGU,YAAA;EACV,IAAA,EAAM,OAAA;EACN,QAAA;EACA,KAAA;EACA,OAAA,EAAS,UAAA;EACT,OAAA;EACA,WAAA,GAAc,IAAA;EACd,OAAA;EACA,WAAA;AAAA;AAAA,KAGU,UAAA,IAAc,GAAA,EAAK,UAAA,KAAe,OAAO;AAAA,KAEzC,MAAA,SAAe,OAAO;AAAA,KAEtB,aAAA;EACV,QAAA;EACA,cAAA;EACA,oBAAA;AAAA;AAAA,KAGU,QAAA;EACV,OAAA,CAAQ,KAAA,EAAO,YAAA,GAAe,OAAA;EAC9B,WAAA,CAAY,OAAA,EAAS,UAAA,EAAY,OAAA,GAAU,aAAA,GAAgB,OAAA,CAAQ,MAAA;AAAA;AAAA,KAKzD,qBAAA;EACV,GAAA;EACA,OAAA;EACA,OAAA,GAAU,QAAA;EACV,MAAA,GAAS,eAAA;EACT,KAAA,GAAQ,cAAA;EACR,SAAA;EACA,cAAA;AAAA;AAAA,KAGU,mBAAA;EACV,aAAA;EACA,IAAA;EACA,QAAA;AAAA;AAAA,KAGU,mBAAA;EACV,SAAA,EAAW,mBAAA;EACX,iBAAA;IACE,MAAA;IACA,YAAA,GAAe,MAAM;EAAA;AAAA;AAAA,KAIb,qBAAA;EACV,cAAA;EACA,SAAS;AAAA;AAAA,KAGC,SAAA,GAAY,QAAA;EACtB,oBAAA,CAAqB,OAAA,EAAS,mBAAA,GAAsB,OAAA;EACpD,mBAAA,CAAoB,OAAA,GAAU,qBAAA,GAAwB,OAAA,CAAQ,MAAA;EAC9D,gBAAA,CAAiB,IAAA,GAAO,IAAA,GAAO,OAAA;AAAA;AAAA,KAGrB,sBAAA,GAAyB,qBAAqB;AAAA,cAE7C,sBAAA;AAAA,iBAEG,YAAA,CAAa,OAAe;;;;;AAnFzB;AAEnB;;KCiBY,eAAA;AAAA,KAEA,cAAA;AAAA,KAEA,sBAAA;EACV,KAAA,EAAO,cAAA;EACP,GAAA;EACA,OAAA,GAAU,eAAe;EACzB,SAAA;EACA,cAAA;AAAA;AAAA,KAGU,eAAA;EACV,IAAA;EACA,cAAA,CAAe,GAAA,EAAK,sBAAA,GAAyB,OAAA,CAAQ,QAAA;AAAA;AAAA,iBAGvC,qBAAA,CAAsB,MAAA,EAAQ,eAAA,GAAkB,eAAe"}
@@ -0,0 +1,14 @@
1
+ //#region src/types.ts
2
+ const DEFAULT_RETRY_DELAY_MS = 5e3;
3
+ function retryDelayMs(attempt) {
4
+ return DEFAULT_RETRY_DELAY_MS * 2 ** Math.max(0, attempt - 1);
5
+ }
6
+ //#endregion
7
+ //#region src/contract.ts
8
+ function defineSchedulerPlugin(plugin) {
9
+ return plugin;
10
+ }
11
+ //#endregion
12
+ export { DEFAULT_RETRY_DELAY_MS as n, retryDelayMs as r, defineSchedulerPlugin as t };
13
+
14
+ //# sourceMappingURL=contract-E1QJBH6_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-E1QJBH6_.mjs","names":[],"sources":["../src/types.ts","../src/contract.ts"],"sourcesContent":["export type JobKind = \"workflow\" | \"agent\" | \"trigger\";\n\nexport type JobTrigger = \"api\" | \"cron\" | \"webhook\" | \"poll\" | \"retry\" | \"prompt\";\n\nexport type JobPayload = {\n kind: JobKind;\n targetId: string;\n runId: string;\n trigger: JobTrigger;\n payload: unknown;\n attempt: number;\n maxAttempts: number;\n scheduledAt: Date;\n jobId: string;\n};\n\nexport type EnqueueInput = {\n kind: JobKind;\n targetId: string;\n runId: string;\n trigger: JobTrigger;\n payload?: unknown;\n scheduledAt?: Date;\n attempt?: number;\n maxAttempts?: number;\n};\n\nexport type JobHandler = (job: JobPayload) => Promise<void>;\n\nexport type StopFn = () => Promise<void> | void;\n\nexport type WorkerOptions = {\n workerId?: string;\n pollIntervalMs?: number;\n leaseSweepIntervalMs?: number;\n};\n\nexport type JobQueue = {\n enqueue(input: EnqueueInput): Promise<string>;\n startWorker(handler: JobHandler, options?: WorkerOptions): Promise<StopFn>;\n};\n\nimport type { SchedulerPlugin, SchedulerScope } from \"./contract\";\n\nexport type CreateJobQueueOptions = {\n url?: string;\n dialect?: \"postgres\" | \"sqlite\";\n adapter?: JobQueue;\n plugin?: SchedulerPlugin;\n scope?: SchedulerScope;\n projectId?: string;\n organizationId?: string;\n};\n\nexport type TriggerScheduleSpec = {\n attachmentKey: string;\n kind: \"cron\" | \"poll\";\n schedule: string;\n};\n\nexport type ScheduleSyncOptions = {\n schedules: TriggerScheduleSpec[];\n scheduleOverrides?: {\n global?: string;\n byAttachment?: Record<string, string>;\n };\n};\n\nexport type ScheduleTickerOptions = {\n pollIntervalMs?: number;\n batchSize?: number;\n};\n\nexport type Scheduler = JobQueue & {\n syncTriggerSchedules(options: ScheduleSyncOptions): Promise<void>;\n startScheduleTicker(options?: ScheduleTickerOptions): Promise<StopFn>;\n fireDueSchedules(asOf?: Date): Promise<number>;\n};\n\nexport type CreateSchedulerOptions = CreateJobQueueOptions;\n\nexport const DEFAULT_RETRY_DELAY_MS = 5_000;\n\nexport function retryDelayMs(attempt: number): number {\n return DEFAULT_RETRY_DELAY_MS * 2 ** Math.max(0, attempt - 1);\n}\n","export type {\n JobKind,\n JobTrigger,\n JobPayload,\n EnqueueInput,\n JobHandler,\n StopFn,\n WorkerOptions,\n JobQueue,\n} from \"./types\";\nexport { retryDelayMs, DEFAULT_RETRY_DELAY_MS } from \"./types\";\n\nimport type { JobQueue } from \"./types\";\n\n/**\n * Inlined to keep the contract database-free — structurally identical to\n * `@keystrokehq/database`'s `DatabaseDialect`. Importing it from the database\n * package would re-introduce the dependency `./contract` exists to avoid.\n */\nexport type DatabaseDialect = \"postgres\" | \"sqlite\";\n\nexport type SchedulerScope = \"platform\" | \"project\";\n\nexport type SchedulerPluginContext = {\n scope: SchedulerScope;\n url?: string;\n dialect?: DatabaseDialect;\n projectId?: string;\n organizationId?: string;\n};\n\nexport type SchedulerPlugin = {\n name: string;\n createJobQueue(ctx: SchedulerPluginContext): Promise<JobQueue>;\n};\n\nexport function defineSchedulerPlugin(plugin: SchedulerPlugin): SchedulerPlugin {\n return plugin;\n}\n"],"mappings":";AAiFA,MAAa,yBAAyB;AAEtC,SAAgB,aAAa,SAAyB;CACpD,OAAO,yBAAyB,KAAK,KAAK,IAAI,GAAG,UAAU,CAAC;AAC9D;;;ACjDA,SAAgB,sBAAsB,QAA0C;CAC9E,OAAO;AACT"}
@@ -0,0 +1,5 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_contract = require("./contract-C5JvbyQ-.cjs");
3
+ exports.DEFAULT_RETRY_DELAY_MS = require_contract.DEFAULT_RETRY_DELAY_MS;
4
+ exports.defineSchedulerPlugin = require_contract.defineSchedulerPlugin;
5
+ exports.retryDelayMs = require_contract.retryDelayMs;
@@ -0,0 +1,2 @@
1
+ import { a as defineSchedulerPlugin, b as retryDelayMs, c as DEFAULT_RETRY_DELAY_MS, d as JobKind, f as JobPayload, i as SchedulerScope, l as EnqueueInput, m as JobTrigger, n as SchedulerPlugin, p as JobQueue, r as SchedulerPluginContext, t as DatabaseDialect, u as JobHandler, v as StopFn, y as WorkerOptions } from "./contract-CYKkRmnH.cjs";
2
+ export { DEFAULT_RETRY_DELAY_MS, DatabaseDialect, type EnqueueInput, type JobHandler, type JobKind, type JobPayload, type JobQueue, type JobTrigger, SchedulerPlugin, SchedulerPluginContext, SchedulerScope, type StopFn, type WorkerOptions, defineSchedulerPlugin, retryDelayMs };
@@ -0,0 +1,2 @@
1
+ import { a as defineSchedulerPlugin, b as retryDelayMs, c as DEFAULT_RETRY_DELAY_MS, d as JobKind, f as JobPayload, i as SchedulerScope, l as EnqueueInput, m as JobTrigger, n as SchedulerPlugin, p as JobQueue, r as SchedulerPluginContext, t as DatabaseDialect, u as JobHandler, v as StopFn, y as WorkerOptions } from "./contract-CYKkRmnH.mjs";
2
+ export { DEFAULT_RETRY_DELAY_MS, DatabaseDialect, type EnqueueInput, type JobHandler, type JobKind, type JobPayload, type JobQueue, type JobTrigger, SchedulerPlugin, SchedulerPluginContext, SchedulerScope, type StopFn, type WorkerOptions, defineSchedulerPlugin, retryDelayMs };
@@ -0,0 +1,2 @@
1
+ import { n as DEFAULT_RETRY_DELAY_MS, r as retryDelayMs, t as defineSchedulerPlugin } from "./contract-E1QJBH6_.mjs";
2
+ export { DEFAULT_RETRY_DELAY_MS, defineSchedulerPlugin, retryDelayMs };