theokit 0.12.0 → 0.13.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.
- package/dist/{actions-virtual-module-SQDY3V5X.js → actions-virtual-module-3CDQTWOC.js} +6 -6
- package/dist/{actions-virtual-module-PNPRCEOS.js → actions-virtual-module-EIPXX4ZB.js} +3 -3
- package/dist/adapters/web-shim.d.ts +67 -0
- package/dist/adapters/ws-shim.d.ts +55 -0
- package/dist/agent-events-DosDXkSV.d.ts +94 -0
- package/dist/agents-typed-client-SAWAAH7K.js +142 -0
- package/dist/agents-typed-client-SAWAAH7K.js.map +1 -0
- package/dist/agents-typed-client-UTEQUA63.js +143 -0
- package/dist/agents-typed-client-UTEQUA63.js.map +1 -0
- package/dist/{app-typed-client-5GYEOYP3.js → app-typed-client-7PBFWZUE.js} +3 -3
- package/dist/{app-typed-client-QG7BVZYW.js → app-typed-client-CSOK7NPC.js} +6 -6
- package/dist/audit-log-BQWM5YLG.d.ts +60 -0
- package/dist/body-parser-web-FV5HWCY3.js +71 -0
- package/dist/body-parser-web-FV5HWCY3.js.map +1 -0
- package/dist/boot/index.d.ts +39 -0
- package/dist/{build-QFRLSEZ4.js → build-HXND27XG.js} +11 -11
- package/dist/{chunk-223EFY5X.js → chunk-2J7XU3PW.js} +68 -27
- package/dist/chunk-2J7XU3PW.js.map +1 -0
- package/dist/{chunk-RESN62GB.js → chunk-2KZQPDYR.js} +5 -48
- package/dist/chunk-2KZQPDYR.js.map +1 -0
- package/dist/chunk-3S3BNW5K.js +445 -0
- package/dist/chunk-3S3BNW5K.js.map +1 -0
- package/dist/{chunk-6FYD34NX.js → chunk-BQDGES7C.js} +28 -28
- package/dist/{chunk-6FYD34NX.js.map → chunk-BQDGES7C.js.map} +1 -1
- package/dist/chunk-EXP56GFQ.js +52 -0
- package/dist/chunk-EXP56GFQ.js.map +1 -0
- package/dist/chunk-F4YUPDJ2.js +115 -0
- package/dist/chunk-F4YUPDJ2.js.map +1 -0
- package/dist/{chunk-NAZ4E2GT.js → chunk-KXA37ONC.js} +2 -2
- package/dist/chunk-NHJMZCAS.js +32 -0
- package/dist/chunk-NHJMZCAS.js.map +1 -0
- package/dist/{chunk-43D6XNDR.js → chunk-O62MW4MT.js} +91 -18
- package/dist/chunk-O62MW4MT.js.map +1 -0
- package/dist/chunk-RSVN727G.js +1 -0
- package/dist/{chunk-7CBRKNQA.js → chunk-RYTZYFSD.js} +198 -6
- package/dist/chunk-RYTZYFSD.js.map +1 -0
- package/dist/chunk-UNLA45FY.js +235 -0
- package/dist/chunk-UNLA45FY.js.map +1 -0
- package/dist/{chunk-GFMQJHXX.js → chunk-WR4F4EEZ.js} +1082 -1074
- package/dist/chunk-WR4F4EEZ.js.map +1 -0
- package/dist/{chunk-AD74EAK3.js → chunk-ZSTZXR2D.js} +1 -30
- package/dist/chunk-ZSTZXR2D.js.map +1 -0
- package/dist/cli/index.js +5 -5
- package/dist/client/index.d.ts +418 -0
- package/dist/client/index.js +84 -3
- package/dist/client/index.js.map +1 -1
- package/dist/csrf-BBrEZSBW.d.ts +107 -0
- package/dist/csrf-readiness-store-CjIoub3U.d.ts +43 -0
- package/dist/define-websocket-CdK94O-D.d.ts +64 -0
- package/dist/{dev-GBXOTXUP.js → dev-OWW4XVIH.js} +10 -10
- package/dist/{dev-emit-FEFEDLZF.js → dev-emit-5MDSBP5D.js} +3 -3
- package/dist/{dev-emit-O4EGOSNV.js → dev-emit-QH2YGZXN.js} +2 -2
- package/dist/devtools/entry.d.ts +5 -0
- package/dist/error-envelope-BsNzzAV5.d.ts +62 -0
- package/dist/health-route-C0hk64_U.d.ts +57 -0
- package/dist/index-B40qUSrQ.d.ts +575 -0
- package/dist/index.d.ts +361 -0
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/internal-api-4YTJDITC.js +83 -0
- package/dist/internal-api-EFKZWIYZ.js +66 -0
- package/dist/internal-api-EFKZWIYZ.js.map +1 -0
- package/dist/job-backend-CgC8Xf33.d.ts +68 -0
- package/dist/match-CfbEFRG4.d.ts +26 -0
- package/dist/{openapi-VR6AFBLJ.js → openapi-FHY6HC6I.js} +7 -7
- package/dist/plugin-runner-BGBkzgi0.d.ts +95 -0
- package/dist/plugin-types-DNJGxr4Z.d.ts +79 -0
- package/dist/rate-limit-BdNDZ3vt.d.ts +58 -0
- package/dist/rate-limit-store-BEJnhWdw.d.ts +72 -0
- package/dist/react-query/index.d.ts +33 -0
- package/dist/{registry-Q2TZQLUH.js → registry-34LL7NF4.js} +1 -1
- package/dist/{routes-LRYOIIAI.js → routes-EW7TP7NJ.js} +2 -2
- package/dist/schema-BpH6ivDY.d.ts +74 -0
- package/dist/server/agent/index.d.ts +229 -0
- package/dist/server/agent/index.js +2 -1
- package/dist/server/auth/index.d.ts +419 -0
- package/dist/server/cost/index.d.ts +177 -0
- package/dist/server/cron/index.d.ts +208 -0
- package/dist/server/define/index.d.ts +313 -0
- package/dist/server/define/index.js +4 -2
- package/dist/server/http/index.d.ts +11 -0
- package/dist/server/index.d.ts +848 -0
- package/dist/server/index.js +9 -294
- package/dist/server/index.js.map +1 -1
- package/dist/server/jobs/index.d.ts +348 -0
- package/dist/server/observability/index.d.ts +324 -0
- package/dist/server/plugins/index.d.ts +17 -0
- package/dist/server/rate-limit/index.d.ts +105 -0
- package/dist/server/realtime/index.d.ts +15 -0
- package/dist/server/scan/index.d.ts +126 -0
- package/dist/server/scan/index.js +1 -1
- package/dist/server/security/index.d.ts +193 -0
- package/dist/server/storage/index.d.ts +22 -0
- package/dist/server/webhook/index.d.ts +148 -0
- package/dist/{start-3ZHAXSJE.js → start-KIQ5TTLR.js} +76 -13
- package/dist/start-KIQ5TTLR.js.map +1 -0
- package/dist/storage-manager-C4jsO0Tp.d.ts +89 -0
- package/dist/storage-types-DsDTCPbp.d.ts +96 -0
- package/dist/vite-plugin/index.d.ts +115 -0
- package/dist/vite-plugin/index.js +6 -4
- package/dist/{vite-plugin-WO72VLYR.js → vite-plugin-RK66K26Z.js} +7 -7
- package/dist/vite-plugin-RK66K26Z.js.map +1 -0
- package/package.json +4 -4
- package/dist/chunk-223EFY5X.js.map +0 -1
- package/dist/chunk-3LVRAGAZ.js +0 -73
- package/dist/chunk-3LVRAGAZ.js.map +0 -1
- package/dist/chunk-43D6XNDR.js.map +0 -1
- package/dist/chunk-7CBRKNQA.js.map +0 -1
- package/dist/chunk-AD74EAK3.js.map +0 -1
- package/dist/chunk-GFMQJHXX.js.map +0 -1
- package/dist/chunk-PBEH6NXR.js +0 -44
- package/dist/chunk-PBEH6NXR.js.map +0 -1
- package/dist/chunk-PIVX3DYW.js +0 -142
- package/dist/chunk-PIVX3DYW.js.map +0 -1
- package/dist/chunk-PPPR5DGR.js +0 -1
- package/dist/chunk-RESN62GB.js.map +0 -1
- package/dist/start-3ZHAXSJE.js.map +0 -1
- /package/dist/{actions-virtual-module-SQDY3V5X.js.map → actions-virtual-module-3CDQTWOC.js.map} +0 -0
- /package/dist/{actions-virtual-module-PNPRCEOS.js.map → actions-virtual-module-EIPXX4ZB.js.map} +0 -0
- /package/dist/{app-typed-client-5GYEOYP3.js.map → app-typed-client-7PBFWZUE.js.map} +0 -0
- /package/dist/{app-typed-client-QG7BVZYW.js.map → app-typed-client-CSOK7NPC.js.map} +0 -0
- /package/dist/{build-QFRLSEZ4.js.map → build-HXND27XG.js.map} +0 -0
- /package/dist/{chunk-NAZ4E2GT.js.map → chunk-KXA37ONC.js.map} +0 -0
- /package/dist/{chunk-PPPR5DGR.js.map → chunk-RSVN727G.js.map} +0 -0
- /package/dist/{dev-GBXOTXUP.js.map → dev-OWW4XVIH.js.map} +0 -0
- /package/dist/{dev-emit-FEFEDLZF.js.map → dev-emit-5MDSBP5D.js.map} +0 -0
- /package/dist/{dev-emit-O4EGOSNV.js.map → dev-emit-QH2YGZXN.js.map} +0 -0
- /package/dist/{vite-plugin-WO72VLYR.js.map → internal-api-4YTJDITC.js.map} +0 -0
- /package/dist/{openapi-VR6AFBLJ.js.map → openapi-FHY6HC6I.js.map} +0 -0
- /package/dist/{registry-Q2TZQLUH.js.map → registry-34LL7NF4.js.map} +0 -0
- /package/dist/{routes-LRYOIIAI.js.map → routes-EW7TP7NJ.js.map} +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { d as StorageAdapter } from '../../storage-types-DsDTCPbp.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Cost tracking types (R0.5.11).
|
|
5
|
+
*
|
|
6
|
+
* @see docs/adr/0002-job-backend-interface-neutral-contract.md (mirror pattern)
|
|
7
|
+
*
|
|
8
|
+
* Phase 5 — Production-Readiness #4: adds `ToolUsageRecord` for per-tool
|
|
9
|
+
* latency / error tracking via SDK's onToolStart/onToolEnd/onToolError hooks.
|
|
10
|
+
* Same UsageStorageAdapter handles both via discriminated union.
|
|
11
|
+
*
|
|
12
|
+
* EC-9 (SHOULD TEST): backward compat — record() input without `kind` is
|
|
13
|
+
* normalized to 'llm' by the framework so external adapters from older
|
|
14
|
+
* versions keep working.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Per-LLM-call cost record (existing — gains optional `kind` discriminator).
|
|
18
|
+
*/
|
|
19
|
+
interface UsageRecord {
|
|
20
|
+
/** Discriminator. Optional for backward-compat; defaults to 'llm'. */
|
|
21
|
+
kind?: 'llm';
|
|
22
|
+
/** User identifier (e.g., session userId, tenantId, apiKey hash). */
|
|
23
|
+
userId: string;
|
|
24
|
+
/** Model id (e.g., 'claude-sonnet-4-5-20250929'). */
|
|
25
|
+
model: string;
|
|
26
|
+
/** Token counts per direction. */
|
|
27
|
+
tokens: {
|
|
28
|
+
input: number;
|
|
29
|
+
output: number;
|
|
30
|
+
};
|
|
31
|
+
/** USD cost in fractional dollars. */
|
|
32
|
+
costUsd: number;
|
|
33
|
+
/** When the run happened. */
|
|
34
|
+
timestamp: Date;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Per-tool-invocation record (Phase 5 — Production-Readiness #4).
|
|
38
|
+
*
|
|
39
|
+
* Emitted by `trackAgentTools` on every `onToolEnd` / `onToolError`. The same
|
|
40
|
+
* `UsageStorageAdapter.record` accepts both record kinds via union.
|
|
41
|
+
*/
|
|
42
|
+
interface ToolUsageRecord {
|
|
43
|
+
kind: 'tool';
|
|
44
|
+
userId: string;
|
|
45
|
+
conversationId: string;
|
|
46
|
+
toolName: string;
|
|
47
|
+
/**
|
|
48
|
+
* Unique per invocation; correlates onToolStart with onToolEnd / onToolError.
|
|
49
|
+
* EC-16 (DOCUMENT): callId uniqueness is SDK contract — if SDK ever reuses
|
|
50
|
+
* a callId, `trackAgentTools`'s Map uses last-write-wins (defensive).
|
|
51
|
+
*/
|
|
52
|
+
callId: string;
|
|
53
|
+
/** True when the tool handler returned; false when it threw. */
|
|
54
|
+
success: boolean;
|
|
55
|
+
/** Milliseconds from onToolStart to onToolEnd / onToolError. */
|
|
56
|
+
durationMs: number;
|
|
57
|
+
/** Populated only when success === false. */
|
|
58
|
+
errorMessage?: string;
|
|
59
|
+
timestamp: Date;
|
|
60
|
+
}
|
|
61
|
+
interface UsageQuery {
|
|
62
|
+
userId: string;
|
|
63
|
+
period: {
|
|
64
|
+
from: Date;
|
|
65
|
+
to: Date;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
interface UsageResult {
|
|
69
|
+
totalTokens: number;
|
|
70
|
+
totalCostUsd: number;
|
|
71
|
+
runs: number;
|
|
72
|
+
}
|
|
73
|
+
interface UsageStorageAdapter {
|
|
74
|
+
readonly name: string;
|
|
75
|
+
/**
|
|
76
|
+
* Record a usage event. Accepts both kinds; framework normalizes input
|
|
77
|
+
* without `kind` to 'llm' before calling adapter (EC-9 backward compat).
|
|
78
|
+
*/
|
|
79
|
+
record(input: UsageRecord | ToolUsageRecord): Promise<void>;
|
|
80
|
+
getUsage(query: UsageQuery): Promise<UsageResult>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface TrackAgentRunInput {
|
|
84
|
+
userId: string;
|
|
85
|
+
model: string;
|
|
86
|
+
tokens: {
|
|
87
|
+
input: number;
|
|
88
|
+
output: number;
|
|
89
|
+
};
|
|
90
|
+
costUsd: number;
|
|
91
|
+
/** Defaults to `new Date()`. */
|
|
92
|
+
timestamp?: Date;
|
|
93
|
+
/** Optional execution status surfaced to devtools (default 'finished'). */
|
|
94
|
+
status?: 'finished' | 'error' | 'aborted';
|
|
95
|
+
}
|
|
96
|
+
interface TrackAgentRunOptions {
|
|
97
|
+
/** Adapter resolved from `theo.config.ts > cost.storage`. */
|
|
98
|
+
storage: UsageStorageAdapter | undefined;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Record a single agent run's usage + cost. Companion to the client-side
|
|
102
|
+
* `<CostMeter>` from `@theokit/ui`.
|
|
103
|
+
*
|
|
104
|
+
* EC-14: this function NEVER bubbles errors back to the caller. Adapter
|
|
105
|
+
* failures (network outage, DB down, etc.) are logged via `console.warn`
|
|
106
|
+
* and swallowed. The agent response MUST NOT fail because cost tracking
|
|
107
|
+
* is degraded.
|
|
108
|
+
*
|
|
109
|
+
* No-op when `storage` is undefined (cost tracking unconfigured).
|
|
110
|
+
*
|
|
111
|
+
* In dev mode (Vite OR tsup-built with NODE_ENV != 'production'), fires a
|
|
112
|
+
* `theokit-evolution-ci-and-dx` Phase 3 dispatcher event so the devtools
|
|
113
|
+
* Agents tab can render the run. Prod tree-shakes the entire dispatcher
|
|
114
|
+
* import via the `__IS_DEV` IIFE guard.
|
|
115
|
+
*
|
|
116
|
+
* @see docs/concepts/cost-tracking.md (when implemented in T6.3)
|
|
117
|
+
*/
|
|
118
|
+
declare function trackAgentRun(input: TrackAgentRunInput, opts: TrackAgentRunOptions): Promise<void>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* In-memory usage storage for dev/tests. Unbounded — production
|
|
122
|
+
* deployments MUST plug in a durable adapter (Postgres/Redis recipes
|
|
123
|
+
* land with R0.6.7; documented in EC-114).
|
|
124
|
+
*
|
|
125
|
+
* Phase 5 — Production-Readiness #4: accepts both `UsageRecord` (LLM call,
|
|
126
|
+
* kind='llm' or omitted) AND `ToolUsageRecord` (tool call, kind='tool').
|
|
127
|
+
* `getUsage` only sums LLM records (tools have no token/cost dimension).
|
|
128
|
+
*
|
|
129
|
+
* EC-9 (backward compat): input without `kind` is normalized to `kind:'llm'`
|
|
130
|
+
* — adapters from older versions stay working.
|
|
131
|
+
*
|
|
132
|
+
* Concurrency: Node's single-threaded event loop guarantees that
|
|
133
|
+
* `Array.push` is atomic, so concurrent record() calls cannot lose data.
|
|
134
|
+
*/
|
|
135
|
+
declare class InMemoryUsageStorage implements UsageStorageAdapter, StorageAdapter {
|
|
136
|
+
#private;
|
|
137
|
+
readonly name = "memory";
|
|
138
|
+
/**
|
|
139
|
+
* T2.3 — `StorageAdapter` lifecycle hook (ADR-0007 D6). In-memory storage
|
|
140
|
+
* has no real cleanup to perform — this is intentionally a noop so the
|
|
141
|
+
* adapter can be registered with `StorageManager.register()` and
|
|
142
|
+
* participate in graceful shutdown without changing behavior.
|
|
143
|
+
*
|
|
144
|
+
* Does NOT clear stored records (dispose ≠ reset). For test reset use
|
|
145
|
+
* a fresh instance.
|
|
146
|
+
*/
|
|
147
|
+
dispose(): Promise<void>;
|
|
148
|
+
record(input: UsageRecord | ToolUsageRecord): Promise<void>;
|
|
149
|
+
getUsage(query: UsageQuery): Promise<UsageResult>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
interface TrackAgentToolsOptions {
|
|
153
|
+
storage: UsageStorageAdapter;
|
|
154
|
+
/** Defaults to () => new Date() — overridable for deterministic testing. */
|
|
155
|
+
now?: () => Date;
|
|
156
|
+
/** Identifier for the user — passed through to ToolUsageRecord.userId. */
|
|
157
|
+
userId?: string;
|
|
158
|
+
/** Identifier for the conversation — passed through to ToolUsageRecord.conversationId. */
|
|
159
|
+
conversationId?: string;
|
|
160
|
+
}
|
|
161
|
+
interface ToolHookEvent {
|
|
162
|
+
callId: string;
|
|
163
|
+
name: string;
|
|
164
|
+
[key: string]: unknown;
|
|
165
|
+
}
|
|
166
|
+
interface TrackAgentToolsHooks {
|
|
167
|
+
onToolStart: (event: ToolHookEvent) => void;
|
|
168
|
+
onToolEnd: (event: ToolHookEvent) => void;
|
|
169
|
+
onToolError: (event: ToolHookEvent) => void;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Create the three tool-lifecycle callbacks. Hand the returned object's
|
|
173
|
+
* methods to `Agent.create({ tools, onToolStart, onToolEnd, onToolError })`.
|
|
174
|
+
*/
|
|
175
|
+
declare function trackAgentTools(opts: TrackAgentToolsOptions): TrackAgentToolsHooks;
|
|
176
|
+
|
|
177
|
+
export { InMemoryUsageStorage, type ToolHookEvent, type ToolUsageRecord, type TrackAgentRunInput, type TrackAgentRunOptions, type TrackAgentToolsHooks, type TrackAgentToolsOptions, type UsageQuery, type UsageRecord, type UsageResult, type UsageStorageAdapter, trackAgentRun, trackAgentTools };
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron primitive types (R0.5.4).
|
|
3
|
+
*
|
|
4
|
+
* @see docs/adr/0004-cron-schedule-5-field-utc-strict.md
|
|
5
|
+
*/
|
|
6
|
+
type CronConcurrencyPolicy = 'forbid' | 'allow';
|
|
7
|
+
interface CronContext {
|
|
8
|
+
/** W3C trace_id propagated from the scheduler invocation. */
|
|
9
|
+
readonly traceId: string;
|
|
10
|
+
/** UTC instant the cron was scheduled to fire. */
|
|
11
|
+
readonly scheduledAt: Date;
|
|
12
|
+
/** Abort signal triggered when the scheduler stops or shuts down. */
|
|
13
|
+
readonly signal: AbortSignal;
|
|
14
|
+
}
|
|
15
|
+
interface CronOptions {
|
|
16
|
+
/** 5-field UTC cron expression (ADR-0004). */
|
|
17
|
+
schedule: string;
|
|
18
|
+
/** Handler invoked on each fire. May return Promise. */
|
|
19
|
+
handler: (ctx: CronContext) => unknown;
|
|
20
|
+
/**
|
|
21
|
+
* Concurrency policy when previous handler is still running:
|
|
22
|
+
* - 'forbid' (default) — skip the next fire + log a warning
|
|
23
|
+
* - 'allow' — run concurrently
|
|
24
|
+
*/
|
|
25
|
+
concurrency?: CronConcurrencyPolicy;
|
|
26
|
+
}
|
|
27
|
+
interface CronDefinition {
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly schedule: string;
|
|
30
|
+
readonly handler: (ctx: CronContext) => unknown;
|
|
31
|
+
readonly concurrency: CronConcurrencyPolicy;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Declare a time-triggered handler. Pure identity helper — no
|
|
36
|
+
* registration side effect; the build-time scanner (T1.3) discovers
|
|
37
|
+
* definitions by walking `server/crons/` and emits a manifest the
|
|
38
|
+
* adapters translate at deploy.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* // server/crons/morning-summary.ts
|
|
43
|
+
* export default defineCron('morning-summary', {
|
|
44
|
+
* schedule: '0 9 * * *', // 09:00 UTC
|
|
45
|
+
* async handler({ traceId, scheduledAt, signal }) {
|
|
46
|
+
* // ...
|
|
47
|
+
* },
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
declare function defineCron(name: string, options: CronOptions): CronDefinition;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validate a cron schedule string per ADR-0004 — 5-field UTC strict.
|
|
55
|
+
*
|
|
56
|
+
* Accepts:
|
|
57
|
+
* - Standard 5-field expressions: `minute hour dayOfMonth month dayOfWeek`
|
|
58
|
+
* - Step (`*\/15`), range (`1-5`), list (`MON,TUE,FRI`), wildcards
|
|
59
|
+
*
|
|
60
|
+
* Rejects:
|
|
61
|
+
* - 6-field with seconds (`* * * * * *`)
|
|
62
|
+
* - 7-field with year
|
|
63
|
+
* - Shorthand (`@daily`, `@hourly`, `@yearly`, `@reboot`)
|
|
64
|
+
* - Timezone suffix
|
|
65
|
+
* - Empty / whitespace-only
|
|
66
|
+
* - Malformed grammar
|
|
67
|
+
*
|
|
68
|
+
* Throws on every invalid input. Every error message includes the
|
|
69
|
+
* original input and the fix.
|
|
70
|
+
*
|
|
71
|
+
* @see docs/adr/0004-cron-schedule-5-field-utc-strict.md
|
|
72
|
+
*/
|
|
73
|
+
declare function validateCronSchedule(schedule: string): void;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* One discovered cron from build-time scan. The handler is intentionally
|
|
77
|
+
* NOT included — manifest is platform-neutral and consumed by adapters
|
|
78
|
+
* that emit static config. Runtime dispatch loads the handler at fire time.
|
|
79
|
+
*/
|
|
80
|
+
interface CronNode {
|
|
81
|
+
readonly name: string;
|
|
82
|
+
readonly filePath: string;
|
|
83
|
+
readonly schedule: string;
|
|
84
|
+
readonly concurrency: CronConcurrencyPolicy;
|
|
85
|
+
}
|
|
86
|
+
declare class DuplicateCronNameError extends Error {
|
|
87
|
+
readonly cronName: string;
|
|
88
|
+
readonly filePaths: readonly string[];
|
|
89
|
+
readonly code = "DUPLICATE_CRON_NAME";
|
|
90
|
+
constructor(cronName: string, filePaths: readonly string[]);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Scan a directory for cron definition files and return the discovered
|
|
94
|
+
* `CronNode[]` sorted by name. Throws `DuplicateCronNameError` on name
|
|
95
|
+
* collision and `Error` on missing default export.
|
|
96
|
+
*
|
|
97
|
+
* Sequential by design — module imports are awaited one-by-one to keep
|
|
98
|
+
* error messages anchored to the file that failed.
|
|
99
|
+
*/
|
|
100
|
+
declare function scanCrons(cronsDir: string): Promise<CronNode[]>;
|
|
101
|
+
|
|
102
|
+
declare const CRON_MANIFEST_SCHEMA_VERSION: 1;
|
|
103
|
+
interface CronManifestEntry {
|
|
104
|
+
readonly name: string;
|
|
105
|
+
readonly filePath: string;
|
|
106
|
+
readonly schedule: string;
|
|
107
|
+
readonly concurrency: 'forbid' | 'allow';
|
|
108
|
+
}
|
|
109
|
+
interface CronManifest {
|
|
110
|
+
readonly schemaVersion: typeof CRON_MANIFEST_SCHEMA_VERSION;
|
|
111
|
+
readonly generatedAt: string;
|
|
112
|
+
readonly crons: readonly CronManifestEntry[];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Build a `CronManifest` from scanned `CronNode[]`. Filepaths are kept
|
|
116
|
+
* relative to the caller's project root for portability.
|
|
117
|
+
*/
|
|
118
|
+
declare function buildCronManifest(nodes: readonly CronNode[], projectRoot?: string): CronManifest;
|
|
119
|
+
/**
|
|
120
|
+
* Write the cron manifest to `path` atomically (EC-106).
|
|
121
|
+
*
|
|
122
|
+
* Accepts either a pre-built `CronManifest` OR an array of `CronNode[]`
|
|
123
|
+
* (which gets converted via `buildCronManifest`). The atomic-write
|
|
124
|
+
* helper guarantees `path` always contains valid JSON, even under
|
|
125
|
+
* concurrent writes (e.g., dev-server rescan + build).
|
|
126
|
+
*/
|
|
127
|
+
declare function writeCronManifest(path: string, input: readonly CronNode[] | CronManifest, projectRoot?: string): void;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Thrown when an existing platform-config file (vercel.json, wrangler.toml,
|
|
131
|
+
* serverless.yml) cannot be parsed. Caller must fix the file before
|
|
132
|
+
* re-running `theokit build`. We NEVER silently overwrite a user's config.
|
|
133
|
+
*/
|
|
134
|
+
declare class ExistingConfigUnparseableError extends Error {
|
|
135
|
+
readonly filePath: string;
|
|
136
|
+
readonly parseError: string;
|
|
137
|
+
readonly code = "EXISTING_CONFIG_UNPARSEABLE";
|
|
138
|
+
constructor(filePath: string, parseError: string);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Translate a TheoKit cron manifest into `vercel.json crons[]`.
|
|
142
|
+
*
|
|
143
|
+
* EC-105: existing fields (functions, headers, redirects, rewrites, env,
|
|
144
|
+
* etc.) are preserved verbatim — ONLY the `crons[]` slice is replaced.
|
|
145
|
+
*/
|
|
146
|
+
declare function translateCronToVercel(vercelJsonPath: string, crons: readonly CronManifestEntry[]): void;
|
|
147
|
+
/**
|
|
148
|
+
* Translate a TheoKit cron manifest into `wrangler.toml [triggers] crons`.
|
|
149
|
+
*
|
|
150
|
+
* EC-105: regex-based mutation that preserves comments + other sections
|
|
151
|
+
* verbatim. Replaces only the `[triggers]` block (or appends if absent).
|
|
152
|
+
*/
|
|
153
|
+
declare function translateCronToCloudflare(wranglerTomlPath: string, crons: readonly CronManifestEntry[]): void;
|
|
154
|
+
/**
|
|
155
|
+
* Convert TheoKit's 5-field UTC cron to AWS EventBridge's 6-field format.
|
|
156
|
+
* EventBridge requires `?` in EITHER day-of-month OR day-of-week (not both `*`).
|
|
157
|
+
*
|
|
158
|
+
* Algorithm:
|
|
159
|
+
* - If DOM is "*" and DOW is "*" → insert ? in DOW (default)
|
|
160
|
+
* - If DOM is "*" and DOW is specific → insert ? in DOM
|
|
161
|
+
* - If DOM is specific and DOW is "*" → insert ? in DOW
|
|
162
|
+
* - Append "*" year field at end.
|
|
163
|
+
*/
|
|
164
|
+
declare function convertToAwsCron(schedule: string): string;
|
|
165
|
+
/**
|
|
166
|
+
* Translate a TheoKit cron manifest into a `serverless.yml` functions
|
|
167
|
+
* map with `events: - schedule: cron(...)` entries.
|
|
168
|
+
*
|
|
169
|
+
* EC-105: appends to `functions:` block, preserving all existing
|
|
170
|
+
* functions/sections. Cron functions are named `cron_<name>` to avoid
|
|
171
|
+
* collision with user-declared functions.
|
|
172
|
+
*/
|
|
173
|
+
declare function translateCronToAws(serverlessYmlPath: string, crons: readonly CronManifestEntry[]): void;
|
|
174
|
+
/**
|
|
175
|
+
* Emit a Deno entry file that registers each cron via `Deno.cron`.
|
|
176
|
+
*
|
|
177
|
+
* Unlike Vercel/CF/AWS, Deno.cron is an in-process runtime API — the
|
|
178
|
+
* entry file is a managed artifact (overwritten each build), not a user
|
|
179
|
+
* config (so EC-105 doesn't apply here).
|
|
180
|
+
*/
|
|
181
|
+
declare function translateCronToDeno(entryPath: string, crons: readonly CronManifestEntry[]): void;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* In-memory cron scheduler for `theokit dev` (T1.4).
|
|
185
|
+
*
|
|
186
|
+
* Algorithm:
|
|
187
|
+
* - For each cron, compute `nextFireAt = cron-parser.next()`.
|
|
188
|
+
* - Schedule a `setTimeout(handler, nextFireAt - now)`.
|
|
189
|
+
* - After handler invocation (sync return or Promise scheduled), recompute
|
|
190
|
+
* next fire from CURRENT time (drift-free vs scheduled time).
|
|
191
|
+
*
|
|
192
|
+
* Per-cron isolation (EC-109):
|
|
193
|
+
* - Each cron's handler invocation is fire-and-forget (`void` scheduled).
|
|
194
|
+
* A hanging handler does NOT block the scheduler loop nor other crons.
|
|
195
|
+
* - `concurrency: 'forbid'` (default) tracks an in-flight flag per-cron;
|
|
196
|
+
* subsequent ticks skip + warn while the in-flight flag is set.
|
|
197
|
+
* - `concurrency: 'allow'` runs handlers concurrently — caller's responsibility.
|
|
198
|
+
*
|
|
199
|
+
* Production deploys use platform-native triggers (T1.5 adapter translators);
|
|
200
|
+
* this scheduler exists only for local dev iteration.
|
|
201
|
+
*/
|
|
202
|
+
interface CronScheduler {
|
|
203
|
+
start(): void;
|
|
204
|
+
stop(): void;
|
|
205
|
+
}
|
|
206
|
+
declare function createCronScheduler(definitions: readonly CronDefinition[]): CronScheduler;
|
|
207
|
+
|
|
208
|
+
export { CRON_MANIFEST_SCHEMA_VERSION, type CronConcurrencyPolicy, type CronContext, type CronDefinition, type CronManifest, type CronManifestEntry, type CronNode, type CronOptions, type CronScheduler, DuplicateCronNameError, ExistingConfigUnparseableError, buildCronManifest, convertToAwsCron, createCronScheduler, defineCron, scanCrons, translateCronToAws, translateCronToCloudflare, translateCronToDeno, translateCronToVercel, validateCronSchedule, writeCronManifest };
|