@aexhq/sdk 0.13.6

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 (112) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +160 -0
  3. package/dist/_contracts/connection-ticket.d.ts +21 -0
  4. package/dist/_contracts/connection-ticket.js +49 -0
  5. package/dist/_contracts/event-envelope.d.ts +276 -0
  6. package/dist/_contracts/event-envelope.js +324 -0
  7. package/dist/_contracts/event-stream-client.d.ts +47 -0
  8. package/dist/_contracts/event-stream-client.js +141 -0
  9. package/dist/_contracts/http.d.ts +35 -0
  10. package/dist/_contracts/http.js +114 -0
  11. package/dist/_contracts/index.d.ts +28 -0
  12. package/dist/_contracts/index.js +29 -0
  13. package/dist/_contracts/managed-key.d.ts +74 -0
  14. package/dist/_contracts/managed-key.js +110 -0
  15. package/dist/_contracts/operations.d.ts +237 -0
  16. package/dist/_contracts/operations.js +632 -0
  17. package/dist/_contracts/provider-support.d.ts +220 -0
  18. package/dist/_contracts/provider-support.js +90 -0
  19. package/dist/_contracts/proxy-protocol.d.ts +257 -0
  20. package/dist/_contracts/proxy-protocol.js +234 -0
  21. package/dist/_contracts/proxy-validation.d.ts +19 -0
  22. package/dist/_contracts/proxy-validation.js +51 -0
  23. package/dist/_contracts/run-artifacts.d.ts +47 -0
  24. package/dist/_contracts/run-artifacts.js +101 -0
  25. package/dist/_contracts/run-config.d.ts +304 -0
  26. package/dist/_contracts/run-config.js +659 -0
  27. package/dist/_contracts/run-cost.d.ts +125 -0
  28. package/dist/_contracts/run-cost.js +616 -0
  29. package/dist/_contracts/run-custody.d.ts +226 -0
  30. package/dist/_contracts/run-custody.js +465 -0
  31. package/dist/_contracts/run-record.d.ts +127 -0
  32. package/dist/_contracts/run-record.js +177 -0
  33. package/dist/_contracts/run-retention.d.ts +213 -0
  34. package/dist/_contracts/run-retention.js +484 -0
  35. package/dist/_contracts/run-unit.d.ts +194 -0
  36. package/dist/_contracts/run-unit.js +215 -0
  37. package/dist/_contracts/runner-event.d.ts +114 -0
  38. package/dist/_contracts/runner-event.js +187 -0
  39. package/dist/_contracts/runtime-manifest.d.ts +106 -0
  40. package/dist/_contracts/runtime-manifest.js +98 -0
  41. package/dist/_contracts/runtime-security-profile.d.ts +27 -0
  42. package/dist/_contracts/runtime-security-profile.js +82 -0
  43. package/dist/_contracts/runtime-sizes.d.ts +144 -0
  44. package/dist/_contracts/runtime-sizes.js +136 -0
  45. package/dist/_contracts/runtime-types.d.ts +212 -0
  46. package/dist/_contracts/runtime-types.js +2 -0
  47. package/dist/_contracts/sdk-errors.d.ts +34 -0
  48. package/dist/_contracts/sdk-errors.js +52 -0
  49. package/dist/_contracts/sdk-secrets.d.ts +31 -0
  50. package/dist/_contracts/sdk-secrets.js +220 -0
  51. package/dist/_contracts/side-effect-audit.d.ts +129 -0
  52. package/dist/_contracts/side-effect-audit.js +494 -0
  53. package/dist/_contracts/sse.d.ts +74 -0
  54. package/dist/_contracts/sse.js +0 -0
  55. package/dist/_contracts/stable.d.ts +26 -0
  56. package/dist/_contracts/stable.js +44 -0
  57. package/dist/_contracts/status.d.ts +19 -0
  58. package/dist/_contracts/status.js +61 -0
  59. package/dist/_contracts/submission.d.ts +383 -0
  60. package/dist/_contracts/submission.js +1380 -0
  61. package/dist/agents-md.d.ts +46 -0
  62. package/dist/agents-md.js +83 -0
  63. package/dist/agents-md.js.map +1 -0
  64. package/dist/asset-upload.d.ts +66 -0
  65. package/dist/asset-upload.js +168 -0
  66. package/dist/asset-upload.js.map +1 -0
  67. package/dist/bundle.d.ts +33 -0
  68. package/dist/bundle.js +89 -0
  69. package/dist/bundle.js.map +1 -0
  70. package/dist/cli.mjs +4140 -0
  71. package/dist/cli.mjs.sha256 +1 -0
  72. package/dist/client.d.ts +460 -0
  73. package/dist/client.js +857 -0
  74. package/dist/client.js.map +1 -0
  75. package/dist/fetch-archive.d.ts +16 -0
  76. package/dist/fetch-archive.js +170 -0
  77. package/dist/fetch-archive.js.map +1 -0
  78. package/dist/file.d.ts +57 -0
  79. package/dist/file.js +153 -0
  80. package/dist/file.js.map +1 -0
  81. package/dist/index.d.ts +30 -0
  82. package/dist/index.js +34 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/mcp-server.d.ts +84 -0
  85. package/dist/mcp-server.js +114 -0
  86. package/dist/mcp-server.js.map +1 -0
  87. package/dist/node-fs.d.ts +12 -0
  88. package/dist/node-fs.js +44 -0
  89. package/dist/node-fs.js.map +1 -0
  90. package/dist/proxy-endpoint.d.ts +131 -0
  91. package/dist/proxy-endpoint.js +147 -0
  92. package/dist/proxy-endpoint.js.map +1 -0
  93. package/dist/skill.d.ts +117 -0
  94. package/dist/skill.js +169 -0
  95. package/dist/skill.js.map +1 -0
  96. package/dist/version.d.ts +9 -0
  97. package/dist/version.js +10 -0
  98. package/dist/version.js.map +1 -0
  99. package/docs/cleanup.md +38 -0
  100. package/docs/credentials.md +153 -0
  101. package/docs/events.md +76 -0
  102. package/docs/mcp.md +47 -0
  103. package/docs/outputs.md +157 -0
  104. package/docs/product-boundaries.md +57 -0
  105. package/docs/provider-runtime-capabilities.md +103 -0
  106. package/docs/quickstart.md +110 -0
  107. package/docs/release.md +99 -0
  108. package/docs/run-config.md +53 -0
  109. package/docs/run-record.md +39 -0
  110. package/docs/skills.md +139 -0
  111. package/docs/testing.md +29 -0
  112. package/package.json +47 -0
@@ -0,0 +1,276 @@
1
+ /**
2
+ * The unified aex event envelope.
3
+ *
4
+ * One versioned, self-describing record that every subscriber sees, derived
5
+ * from the unified {@link RunnerEvent}. Managed runtime adapters emit
6
+ * byte-identical envelopes for the same logical event by construction. This is
7
+ * the shape the coordinator (Phase 2) appends, broadcasts, and archives.
8
+ *
9
+ * - **CloudEvents-shaped** self-describing envelope: a stable `id`, the
10
+ * coarse `source`, the AG-UI-aligned `type`, the `subject` (run), a
11
+ * `time`, the `sequence` cursor, and the typed `data`.
12
+ * - **AG-UI vocabulary** for `type` where it maps; aex-specific events
13
+ * ride AG-UI's reserved `CUSTOM` carrier under an `aex.*` name, so an
14
+ * off-the-shelf AG-UI client reads an aex run with no glue.
15
+ * - Two aex extensions: a coarse `source` (filter first by origin) and
16
+ * an optional human `message` (log / CLI / dashboard rendering).
17
+ *
18
+ * Unified observability spine:
19
+ * the envelope additionally carries four ordering attributes so BOTH the typed
20
+ * event stream and the high-volume hosted runtime log stream ride one per-run
21
+ * coordinator:
22
+ * - `channel` — "event" (the typed AG-UI stream) or "log" (a verbose log
23
+ * line). The single axis a consumer splits the unified stream
24
+ * on. Absent ⇒ "event" (back-compat for existing producers).
25
+ * - `sourceSeq` — a per-SOURCE monotonic counter assigned AT the source. The
26
+ * DO's hard guarantee is that records of the same source are
27
+ * never reordered relative to their `sourceSeq`.
28
+ * - `emittedAt` — source wall-clock ms at emit. Carried, never trusted for
29
+ * cross-source ordering (clocks are independent; the coordinator gives
30
+ * no synchronized clock). A client may re-sort by it for a
31
+ * best-effort time view.
32
+ * The coordinator remains the single serial ordering authority: it assigns the global
33
+ * `sequence` on arrival, which is the canonical stream order. `sourceSeq` /
34
+ * `emittedAt` are CARRIED through broadcast + archive, not used to reorder.
35
+ *
36
+ * This module is **additive**: it does not change {@link RunnerEvent} or any
37
+ * existing wire shape. It is a pure projection plus honest guards and a strict
38
+ * AG-UI projection for consumers.
39
+ */
40
+ import type { JsonValue } from "./submission.js";
41
+ import type { RunnerEvent } from "./runner-event.js";
42
+ /** CloudEvents `specversion` the envelope conforms to. */
43
+ export declare const AEX_EVENT_SPECVERSION: "1.0";
44
+ /**
45
+ * Mapping version. Bump when the RunnerEvent → envelope projection changes
46
+ * shape (new `source`/`type`, renamed data field). Independent of
47
+ * {@link AEX_EVENT_SPECVERSION} (the CloudEvents version) and of
48
+ * `RUNNER_EVENT_VERSION` (the upstream wire version).
49
+ */
50
+ export declare const AEX_EVENT_MAP_VERSION: 1;
51
+ /**
52
+ * Coarse origin classifier — the first axis a consumer filters on.
53
+ * - `agent` — the model: text, reasoning, builtin tool calls/results.
54
+ * - `worker` — the hosted aex edge itself.
55
+ * - `runtime` — the execution runtime (Goose container / Anthropic session):
56
+ * lifecycle, diagnostics, non-fatal stream errors.
57
+ * - `mcp` — an MCP server (a tool call/result routed through MCP).
58
+ * - `aex` — the platform: skills, files, and other aex-native events.
59
+ * - `workflow`— the orchestration layer (Cloudflare Workflows trace).
60
+ * - `machine` — the managed host the runtime executes on (machine-level host
61
+ * logs). A forthcoming source; `runtime` stays the
62
+ * Goose-container / Anthropic-session source, distinct from the
63
+ * host machine that carries it.
64
+ */
65
+ export declare const AEX_EVENT_SOURCES: readonly ["agent", "worker", "runtime", "mcp", "aex", "workflow", "machine"];
66
+ export type AexEventSource = (typeof AEX_EVENT_SOURCES)[number];
67
+ /**
68
+ * The channel a record rides on the unified per-run stream:
69
+ * - `event` — the typed, low-volume, fully-replayed AG-UI event stream.
70
+ * - `log` — a high-volume verbose log line (level + message + fields). The
71
+ * coordinator prunes flushed log rows after R2 archival (logs are
72
+ * append-only, events are kept). Absent on the wire ⇒ `event`.
73
+ */
74
+ export declare const AEX_EVENT_CHANNELS: readonly ["event", "log"];
75
+ export type AexEventChannel = (typeof AEX_EVENT_CHANNELS)[number];
76
+ /**
77
+ * Log severity carried by a `channel: "log"` record (the `LOG` event type).
78
+ * NOTE: the platform owner's canonical term for the middle level is "warning";
79
+ * we keep "warn" for consistency with the existing in-code vocabulary — the
80
+ * mapping is `warning ≡ warn`.
81
+ */
82
+ export declare const AEX_LOG_LEVELS: readonly ["info", "warn", "error"];
83
+ export type AexLogLevel = (typeof AEX_LOG_LEVELS)[number];
84
+ /**
85
+ * The AG-UI-aligned `type` vocabulary the envelope emits. A subset of the
86
+ * full AG-UI protocol — the events aex actually produces today — plus
87
+ * `CUSTOM`, AG-UI's reserved carrier for aex-native events.
88
+ */
89
+ export declare const AEX_EVENT_TYPES: readonly ["RUN_STARTED", "RUN_FINISHED", "RUN_ERROR", "TEXT_MESSAGE_CONTENT", "TOOL_CALL_START", "TOOL_CALL_RESULT", "CUSTOM", "LOG"];
90
+ export type AexEventType = (typeof AEX_EVENT_TYPES)[number];
91
+ /**
92
+ * One event on the unified log. CloudEvents core attributes (`specversion`,
93
+ * `id`, `source`, `type`, `subject`, `time`) plus the `sequence` extension
94
+ * (the ordering cursor) and the typed `data`.
95
+ */
96
+ export interface AexEvent {
97
+ /** CloudEvents specversion. Always {@link AEX_EVENT_SPECVERSION}. */
98
+ readonly specversion: typeof AEX_EVENT_SPECVERSION;
99
+ /** Stable, globally-unique event id: `${runId}:${sequence}`. Dedupe key. */
100
+ readonly id: string;
101
+ /** Coarse origin classifier. */
102
+ readonly source: AexEventSource;
103
+ /** AG-UI-aligned event type. */
104
+ readonly type: AexEventType;
105
+ /** The run this event belongs to (CloudEvents `subject`). */
106
+ readonly subject: string;
107
+ /** ISO-8601 event time (run base + the RunnerEvent's relative `tMs`). */
108
+ readonly time: string;
109
+ /**
110
+ * Monotonic ordering cursor within the run — the GLOBAL `seq` the coordinator
111
+ * assigns on arrival. This is the canonical stream order and the dedupe key.
112
+ */
113
+ readonly sequence: number;
114
+ /**
115
+ * Which sub-stream this record rides. Absent ⇒ `"event"` (existing typed
116
+ * producers don't set it; the coordinator defaults it on ingest).
117
+ */
118
+ readonly channel?: AexEventChannel;
119
+ /**
120
+ * Per-SOURCE monotonic counter assigned at the source. The coordinator
121
+ * preserves the order of same-source records by `sourceSeq` and never
122
+ * reorders them; cross-source order is by arrival (`sequence`) only.
123
+ */
124
+ readonly sourceSeq?: number;
125
+ /** Source wall-clock ms at emit. Carried for a best-effort client time view. */
126
+ readonly emittedAt?: number;
127
+ /**
128
+ * The DO's authoritative receive time (wall-clock ms), stamped at ingest
129
+ * alongside the global {@link sequence}. This is the authoritative wall-clock
130
+ * companion to `sequence` — distinct from `emittedAt` (the SOURCE's clock) and
131
+ * `time` (the LOGICAL time = run base + relative tMs).
132
+ *
133
+ * NOTE: a Workers clock is coarsened/frozen-at-I/O (a side-channel
134
+ * mitigation), so `receivedAt` is precisely "the DO's last-I/O wall-clock at
135
+ * ingest" — that is fine as the authoritative receive marker. It does NOT need
136
+ * to exceed `emittedAt`: the source runs on a different machine with an
137
+ * independent clock, so cross-machine drift can leave `receivedAt < emittedAt`
138
+ * and that is expected, not an error. Absent on records produced before this
139
+ * field existed (back-compat with archived records).
140
+ */
141
+ readonly receivedAt?: number;
142
+ /**
143
+ * Log severity, first-class on a `channel: "log"` record (mirrors
144
+ * `data.level`). Optional: only `log`-channel records carry it; typed `event`
145
+ * records omit it. ("warn" ≡ the owner's "warning" — see {@link AEX_LOG_LEVELS}.)
146
+ */
147
+ readonly level?: AexLogLevel;
148
+ /** Optional human-readable summary for log / CLI / dashboard rendering. */
149
+ readonly message?: string;
150
+ /**
151
+ * Typed payload. For `CUSTOM` events this is `{ name, value }` (AG-UI's
152
+ * custom carrier, `name` = `aex.<kind>`); for typed events it is the
153
+ * RunnerEvent's own data, projected to AG-UI fields by {@link toAGUI}.
154
+ */
155
+ readonly data: Readonly<Record<string, JsonValue>>;
156
+ }
157
+ /** Context the mapper needs to stamp absolute identity/time onto an event. */
158
+ export interface AexEventContext {
159
+ readonly runId: string;
160
+ /**
161
+ * Run-start epoch ms. The RunnerEvent's `tMs` is relative to this, so
162
+ * `time = new Date(baseMs + tMs)`. Pass the run's `createdAtMs`.
163
+ */
164
+ readonly baseMs: number;
165
+ }
166
+ /**
167
+ * Project a {@link RunnerEvent} onto the unified envelope. Pure and total:
168
+ * every RunnerEvent kind maps to exactly one envelope. Both runtimes feed
169
+ * RunnerEvents through this same function, so identical logical events
170
+ * produce identical envelopes.
171
+ */
172
+ export declare function runnerEventToAexEvent(evt: RunnerEvent, ctx: AexEventContext): AexEvent;
173
+ /** A log line as a producer hands it to {@link logToInbound} (pre-coordinator). */
174
+ export interface AexLogLine {
175
+ readonly level: AexLogLevel;
176
+ readonly message: string;
177
+ readonly fields?: Readonly<Record<string, JsonValue>>;
178
+ /** Source wall-clock ms at emit. */
179
+ readonly emittedAt: number;
180
+ /** Per-source monotonic counter assigned at the source. */
181
+ readonly sourceSeq: number;
182
+ }
183
+ /**
184
+ * The inbound (pre-seq) envelope a producer POSTs for a `channel: "log"` line.
185
+ * The coordinator stamps `specversion`/`id`/`subject`/`sequence` (the ordering
186
+ * authority) AND `receivedAt` (its authoritative receive time) on ingest, so a
187
+ * producer never supplies any of them.
188
+ */
189
+ export type AexInboundLog = Omit<AexEvent, "specversion" | "id" | "subject" | "sequence" | "receivedAt">;
190
+ /**
191
+ * Project a log line onto an inbound coordinator envelope. The coordinator
192
+ * stamps `specversion`/`id`/`subject`/`sequence` on ingest (it is the ordering
193
+ * authority); everything else — `channel`, `source`, `sourceSeq`, `emittedAt`,
194
+ * and the `LOG` payload — is supplied here.
195
+ */
196
+ export declare function logToInbound(source: AexEventSource, line: AexLogLine): AexInboundLog;
197
+ export declare function isRunStarted(e: AexEvent): boolean;
198
+ export declare function isRunFinished(e: AexEvent): boolean;
199
+ export declare function isRunError(e: AexEvent): boolean;
200
+ /** A terminal event of either flavour (finished or error). */
201
+ export declare function isRunTerminal(e: AexEvent): boolean;
202
+ export declare function isTextMessage(e: AexEvent): boolean;
203
+ export declare function isToolCallStart(e: AexEvent): boolean;
204
+ export declare function isToolCallResult(e: AexEvent): boolean;
205
+ export declare function isCustom(e: AexEvent): boolean;
206
+ /** The `aex.*` name of a CUSTOM event, or null for typed events. */
207
+ export declare function customName(e: AexEvent): string | null;
208
+ export declare function isFromSource(e: AexEvent, source: AexEventSource): boolean;
209
+ /** The channel a record rides, defaulting an absent value to `"event"`. */
210
+ export declare function channelOf(e: AexEvent): AexEventChannel;
211
+ /** True when a record is a log line (the `log` channel / `LOG` type). */
212
+ export declare function isLog(e: AexEvent): boolean;
213
+ /** True when a record is a typed AG-UI event (the `event` channel). */
214
+ export declare function isEventChannel(e: AexEvent): boolean;
215
+ /**
216
+ * The coordinator's embedded store caps a
217
+ * single row at 2 MB. Events whose serialized form exceeds the budget must be
218
+ * split before insert (the coordinator's responsibility); the archive uses the
219
+ * same bound. A conservative margin under the hard 2 MiB leaves room for row
220
+ * overhead and column framing.
221
+ */
222
+ export declare const MAX_SQLITE_ROW_BYTES: 2000000;
223
+ /** Serialized UTF-8 byte length of an event (the size the row must hold). */
224
+ export declare function serializedEventBytes(e: AexEvent): number;
225
+ /** True when an event's serialized form exceeds the row budget and must be split. */
226
+ export declare function exceedsRowBudget(e: AexEvent, max?: number): boolean;
227
+ /**
228
+ * AG-UI events aex projects to. Each carries the AG-UI `type` discriminant
229
+ * and a numeric `timestamp` (ms), plus the type-specific fields an off-the-shelf
230
+ * AG-UI client expects. Aex's envelope extensions (`source`, `message`, the
231
+ * CloudEvents framing) are dropped — `rawEvent` carries the original for clients
232
+ * that want it.
233
+ */
234
+ export type AguiEvent = {
235
+ type: "RUN_STARTED";
236
+ timestamp: number;
237
+ threadId: string;
238
+ runId: string;
239
+ } | {
240
+ type: "RUN_FINISHED";
241
+ timestamp: number;
242
+ threadId: string;
243
+ runId: string;
244
+ } | {
245
+ type: "RUN_ERROR";
246
+ timestamp: number;
247
+ message: string;
248
+ code?: string;
249
+ } | {
250
+ type: "TEXT_MESSAGE_CONTENT";
251
+ timestamp: number;
252
+ messageId: string;
253
+ delta: string;
254
+ } | {
255
+ type: "TOOL_CALL_START";
256
+ timestamp: number;
257
+ toolCallId: string;
258
+ toolCallName: string;
259
+ } | {
260
+ type: "TOOL_CALL_RESULT";
261
+ timestamp: number;
262
+ messageId: string;
263
+ toolCallId: string;
264
+ content: JsonValue;
265
+ } | {
266
+ type: "CUSTOM";
267
+ timestamp: number;
268
+ name: string;
269
+ value: JsonValue;
270
+ };
271
+ /**
272
+ * Project an aex envelope to a strict AG-UI event so an off-the-shelf
273
+ * AG-UI client can consume an aex run with no glue. This is the
274
+ * client-side projection the SDK exposes.
275
+ */
276
+ export declare function toAGUI(e: AexEvent): AguiEvent;
@@ -0,0 +1,324 @@
1
+ /**
2
+ * The unified aex event envelope.
3
+ *
4
+ * One versioned, self-describing record that every subscriber sees, derived
5
+ * from the unified {@link RunnerEvent}. Managed runtime adapters emit
6
+ * byte-identical envelopes for the same logical event by construction. This is
7
+ * the shape the coordinator (Phase 2) appends, broadcasts, and archives.
8
+ *
9
+ * - **CloudEvents-shaped** self-describing envelope: a stable `id`, the
10
+ * coarse `source`, the AG-UI-aligned `type`, the `subject` (run), a
11
+ * `time`, the `sequence` cursor, and the typed `data`.
12
+ * - **AG-UI vocabulary** for `type` where it maps; aex-specific events
13
+ * ride AG-UI's reserved `CUSTOM` carrier under an `aex.*` name, so an
14
+ * off-the-shelf AG-UI client reads an aex run with no glue.
15
+ * - Two aex extensions: a coarse `source` (filter first by origin) and
16
+ * an optional human `message` (log / CLI / dashboard rendering).
17
+ *
18
+ * Unified observability spine:
19
+ * the envelope additionally carries four ordering attributes so BOTH the typed
20
+ * event stream and the high-volume hosted runtime log stream ride one per-run
21
+ * coordinator:
22
+ * - `channel` — "event" (the typed AG-UI stream) or "log" (a verbose log
23
+ * line). The single axis a consumer splits the unified stream
24
+ * on. Absent ⇒ "event" (back-compat for existing producers).
25
+ * - `sourceSeq` — a per-SOURCE monotonic counter assigned AT the source. The
26
+ * DO's hard guarantee is that records of the same source are
27
+ * never reordered relative to their `sourceSeq`.
28
+ * - `emittedAt` — source wall-clock ms at emit. Carried, never trusted for
29
+ * cross-source ordering (clocks are independent; the coordinator gives
30
+ * no synchronized clock). A client may re-sort by it for a
31
+ * best-effort time view.
32
+ * The coordinator remains the single serial ordering authority: it assigns the global
33
+ * `sequence` on arrival, which is the canonical stream order. `sourceSeq` /
34
+ * `emittedAt` are CARRIED through broadcast + archive, not used to reorder.
35
+ *
36
+ * This module is **additive**: it does not change {@link RunnerEvent} or any
37
+ * existing wire shape. It is a pure projection plus honest guards and a strict
38
+ * AG-UI projection for consumers.
39
+ */
40
+ /** CloudEvents `specversion` the envelope conforms to. */
41
+ export const AEX_EVENT_SPECVERSION = "1.0";
42
+ /**
43
+ * Mapping version. Bump when the RunnerEvent → envelope projection changes
44
+ * shape (new `source`/`type`, renamed data field). Independent of
45
+ * {@link AEX_EVENT_SPECVERSION} (the CloudEvents version) and of
46
+ * `RUNNER_EVENT_VERSION` (the upstream wire version).
47
+ */
48
+ export const AEX_EVENT_MAP_VERSION = 1;
49
+ /**
50
+ * Coarse origin classifier — the first axis a consumer filters on.
51
+ * - `agent` — the model: text, reasoning, builtin tool calls/results.
52
+ * - `worker` — the hosted aex edge itself.
53
+ * - `runtime` — the execution runtime (Goose container / Anthropic session):
54
+ * lifecycle, diagnostics, non-fatal stream errors.
55
+ * - `mcp` — an MCP server (a tool call/result routed through MCP).
56
+ * - `aex` — the platform: skills, files, and other aex-native events.
57
+ * - `workflow`— the orchestration layer (Cloudflare Workflows trace).
58
+ * - `machine` — the managed host the runtime executes on (machine-level host
59
+ * logs). A forthcoming source; `runtime` stays the
60
+ * Goose-container / Anthropic-session source, distinct from the
61
+ * host machine that carries it.
62
+ */
63
+ export const AEX_EVENT_SOURCES = ["agent", "worker", "runtime", "mcp", "aex", "workflow", "machine"];
64
+ /**
65
+ * The channel a record rides on the unified per-run stream:
66
+ * - `event` — the typed, low-volume, fully-replayed AG-UI event stream.
67
+ * - `log` — a high-volume verbose log line (level + message + fields). The
68
+ * coordinator prunes flushed log rows after R2 archival (logs are
69
+ * append-only, events are kept). Absent on the wire ⇒ `event`.
70
+ */
71
+ export const AEX_EVENT_CHANNELS = ["event", "log"];
72
+ /**
73
+ * Log severity carried by a `channel: "log"` record (the `LOG` event type).
74
+ * NOTE: the platform owner's canonical term for the middle level is "warning";
75
+ * we keep "warn" for consistency with the existing in-code vocabulary — the
76
+ * mapping is `warning ≡ warn`.
77
+ */
78
+ export const AEX_LOG_LEVELS = ["info", "warn", "error"];
79
+ /**
80
+ * The AG-UI-aligned `type` vocabulary the envelope emits. A subset of the
81
+ * full AG-UI protocol — the events aex actually produces today — plus
82
+ * `CUSTOM`, AG-UI's reserved carrier for aex-native events.
83
+ */
84
+ export const AEX_EVENT_TYPES = [
85
+ "RUN_STARTED",
86
+ "RUN_FINISHED",
87
+ "RUN_ERROR",
88
+ "TEXT_MESSAGE_CONTENT",
89
+ "TOOL_CALL_START",
90
+ "TOOL_CALL_RESULT",
91
+ "CUSTOM",
92
+ // The carrier type for a `channel: "log"` record. Kept out of the AG-UI
93
+ // typed-event vocabulary on purpose: a `LOG` is never a run-lifecycle signal,
94
+ // so terminal detection (RUN_FINISHED/RUN_ERROR) is unaffected and an
95
+ // off-the-shelf AG-UI client filters logs out by `channel`.
96
+ "LOG"
97
+ ];
98
+ /**
99
+ * Project a {@link RunnerEvent} onto the unified envelope. Pure and total:
100
+ * every RunnerEvent kind maps to exactly one envelope. Both runtimes feed
101
+ * RunnerEvents through this same function, so identical logical events
102
+ * produce identical envelopes.
103
+ */
104
+ export function runnerEventToAexEvent(evt, ctx) {
105
+ const projection = project(evt);
106
+ return {
107
+ specversion: AEX_EVENT_SPECVERSION,
108
+ id: `${ctx.runId}:${evt.seq}`,
109
+ source: projection.source,
110
+ type: projection.type,
111
+ subject: ctx.runId,
112
+ time: new Date(ctx.baseMs + evt.tMs).toISOString(),
113
+ sequence: evt.seq,
114
+ ...(projection.message !== undefined ? { message: projection.message } : {}),
115
+ data: Object.freeze(projection.data)
116
+ };
117
+ }
118
+ function project(evt) {
119
+ const data = evt.data;
120
+ switch (evt.kind) {
121
+ case "runtime_started":
122
+ return { type: "RUN_STARTED", source: "runtime", message: "run started", data: { ...data } };
123
+ case "assistant_text": {
124
+ const text = str(data.text);
125
+ return {
126
+ type: "TEXT_MESSAGE_CONTENT",
127
+ source: "agent",
128
+ ...(text ? { message: clip(text) } : {}),
129
+ data: { ...data }
130
+ };
131
+ }
132
+ case "tool_request": {
133
+ const name = str(data.name);
134
+ return {
135
+ type: "TOOL_CALL_START",
136
+ source: data.extension ? "mcp" : "agent",
137
+ ...(name ? { message: `tool ${name}` } : {}),
138
+ data: { ...data }
139
+ };
140
+ }
141
+ case "tool_response":
142
+ return {
143
+ type: "TOOL_CALL_RESULT",
144
+ source: data.extension ? "mcp" : "agent",
145
+ data: { ...data }
146
+ };
147
+ case "skill_loaded":
148
+ return custom("aex.skill_loaded", "aex", data, "skill loaded");
149
+ case "file_uploaded":
150
+ return custom("aex.file_uploaded", "aex", data, "file uploaded");
151
+ case "notification":
152
+ return custom("aex.notification", "runtime", data, str(data.reason) || undefined);
153
+ case "stream_error":
154
+ return custom("aex.stream_error", "runtime", data, str(data.message) || "stream error");
155
+ case "runtime_terminal": {
156
+ const reason = str(data.reason);
157
+ return {
158
+ // The event's own reason types it (error vs finished); the
159
+ // authoritative run *status* is still owned by the orchestrator and
160
+ // is never re-derived from this event.
161
+ type: reason === "error" ? "RUN_ERROR" : "RUN_FINISHED",
162
+ source: "runtime",
163
+ message: reason ? `run ${reason}` : "run finished",
164
+ data: { ...data }
165
+ };
166
+ }
167
+ }
168
+ }
169
+ /**
170
+ * Project a log line onto an inbound coordinator envelope. The coordinator
171
+ * stamps `specversion`/`id`/`subject`/`sequence` on ingest (it is the ordering
172
+ * authority); everything else — `channel`, `source`, `sourceSeq`, `emittedAt`,
173
+ * and the `LOG` payload — is supplied here.
174
+ */
175
+ export function logToInbound(source, line) {
176
+ return {
177
+ source,
178
+ type: "LOG",
179
+ channel: "log",
180
+ sourceSeq: line.sourceSeq,
181
+ emittedAt: line.emittedAt,
182
+ // First-class severity on the envelope (not only inside `data`). `data.level`
183
+ // is kept too so an existing `data`-reading consumer still works.
184
+ level: line.level,
185
+ time: new Date(line.emittedAt).toISOString(),
186
+ message: line.message,
187
+ data: {
188
+ level: line.level,
189
+ message: line.message,
190
+ ...(line.fields ? { fields: { ...line.fields } } : {})
191
+ }
192
+ };
193
+ }
194
+ function custom(name, source, value, message) {
195
+ return {
196
+ type: "CUSTOM",
197
+ source,
198
+ ...(message !== undefined ? { message } : {}),
199
+ data: { name, value: { ...value } }
200
+ };
201
+ }
202
+ // --- Honest guards over the emitted vocabulary --------------------------------
203
+ // These match the vocabulary a consumer of the unified stream actually receives.
204
+ export function isRunStarted(e) {
205
+ return e.type === "RUN_STARTED";
206
+ }
207
+ export function isRunFinished(e) {
208
+ return e.type === "RUN_FINISHED";
209
+ }
210
+ export function isRunError(e) {
211
+ return e.type === "RUN_ERROR";
212
+ }
213
+ /** A terminal event of either flavour (finished or error). */
214
+ export function isRunTerminal(e) {
215
+ return e.type === "RUN_FINISHED" || e.type === "RUN_ERROR";
216
+ }
217
+ export function isTextMessage(e) {
218
+ return e.type === "TEXT_MESSAGE_CONTENT";
219
+ }
220
+ export function isToolCallStart(e) {
221
+ return e.type === "TOOL_CALL_START";
222
+ }
223
+ export function isToolCallResult(e) {
224
+ return e.type === "TOOL_CALL_RESULT";
225
+ }
226
+ export function isCustom(e) {
227
+ return e.type === "CUSTOM";
228
+ }
229
+ /** The `aex.*` name of a CUSTOM event, or null for typed events. */
230
+ export function customName(e) {
231
+ return e.type === "CUSTOM" ? str(e.data.name) || null : null;
232
+ }
233
+ export function isFromSource(e, source) {
234
+ return e.source === source;
235
+ }
236
+ /** The channel a record rides, defaulting an absent value to `"event"`. */
237
+ export function channelOf(e) {
238
+ return e.channel ?? "event";
239
+ }
240
+ /** True when a record is a log line (the `log` channel / `LOG` type). */
241
+ export function isLog(e) {
242
+ return channelOf(e) === "log";
243
+ }
244
+ /** True when a record is a typed AG-UI event (the `event` channel). */
245
+ export function isEventChannel(e) {
246
+ return channelOf(e) === "event";
247
+ }
248
+ // --- Oversized-payload rule (2 MB SQLite row cap) -----------------------------
249
+ /**
250
+ * The coordinator's embedded store caps a
251
+ * single row at 2 MB. Events whose serialized form exceeds the budget must be
252
+ * split before insert (the coordinator's responsibility); the archive uses the
253
+ * same bound. A conservative margin under the hard 2 MiB leaves room for row
254
+ * overhead and column framing.
255
+ */
256
+ export const MAX_SQLITE_ROW_BYTES = 2_000_000;
257
+ /** Serialized UTF-8 byte length of an event (the size the row must hold). */
258
+ export function serializedEventBytes(e) {
259
+ return new TextEncoder().encode(JSON.stringify(e)).byteLength;
260
+ }
261
+ /** True when an event's serialized form exceeds the row budget and must be split. */
262
+ export function exceedsRowBudget(e, max = MAX_SQLITE_ROW_BYTES) {
263
+ return serializedEventBytes(e) > max;
264
+ }
265
+ /**
266
+ * Project an aex envelope to a strict AG-UI event so an off-the-shelf
267
+ * AG-UI client can consume an aex run with no glue. This is the
268
+ * client-side projection the SDK exposes.
269
+ */
270
+ export function toAGUI(e) {
271
+ const timestamp = Date.parse(e.time);
272
+ const d = e.data;
273
+ switch (e.type) {
274
+ case "RUN_STARTED":
275
+ return { type: "RUN_STARTED", timestamp, threadId: e.subject, runId: e.subject };
276
+ case "RUN_FINISHED":
277
+ return { type: "RUN_FINISHED", timestamp, threadId: e.subject, runId: e.subject };
278
+ case "RUN_ERROR": {
279
+ const code = str(d.failureClass);
280
+ return {
281
+ type: "RUN_ERROR",
282
+ timestamp,
283
+ message: str(d.failureMessage) || e.message || "run error",
284
+ ...(code ? { code } : {})
285
+ };
286
+ }
287
+ case "TEXT_MESSAGE_CONTENT":
288
+ return {
289
+ type: "TEXT_MESSAGE_CONTENT",
290
+ timestamp,
291
+ messageId: str(d.messageId) || str(d.eventId) || e.id,
292
+ delta: str(d.text)
293
+ };
294
+ case "TOOL_CALL_START":
295
+ return {
296
+ type: "TOOL_CALL_START",
297
+ timestamp,
298
+ toolCallId: str(d.id) || e.id,
299
+ toolCallName: str(d.name)
300
+ };
301
+ case "TOOL_CALL_RESULT":
302
+ return {
303
+ type: "TOOL_CALL_RESULT",
304
+ timestamp,
305
+ messageId: str(d.messageId) || e.id,
306
+ toolCallId: str(d.id) || e.id,
307
+ content: d.content ?? null
308
+ };
309
+ case "CUSTOM":
310
+ return { type: "CUSTOM", timestamp, name: str(d.name), value: d.value ?? null };
311
+ case "LOG":
312
+ // Logs ride the `log` channel and are normally filtered out before
313
+ // projection. If a consumer projects one anyway, carry it under AG-UI's
314
+ // reserved CUSTOM so the client still receives a valid record.
315
+ return { type: "CUSTOM", timestamp, name: "aex.log", value: { ...d } };
316
+ }
317
+ }
318
+ function str(v) {
319
+ return typeof v === "string" ? v : "";
320
+ }
321
+ function clip(s, max = 200) {
322
+ return s.length <= max ? s : `${s.slice(0, max - 1)}…`;
323
+ }
324
+ //# sourceMappingURL=event-envelope.js.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Client-side consumer of the event coordinator's WebSocket stream.
3
+ *
4
+ * One mechanism for catch-up + resume + live: subscribe = read-from-cursor +
5
+ * tail. The consumer opens a WS to the coordinator with a connection ticket,
6
+ * replays from its cursor, and yields {@link AexEvent}s as they arrive.
7
+ * On a transport drop it reconnects with backoff and resumes from the last
8
+ * sequence it saw — `from = lastSeq + 1` — so delivery is exactly-once across
9
+ * reconnects (no gap, no duplicate). It stops on a terminal event, on abort,
10
+ * or when the caller breaks the iterator.
11
+ *
12
+ * Filtering and projection are the client's concern (the wire carries the
13
+ * whole run): compose {@link filterStream} with the envelope guards, and
14
+ * {@link mapStream} with {@link toAGUI}, on top of this stream.
15
+ *
16
+ * The WebSocket is injectable so the SDK/CLI use the Node/global `WebSocket`
17
+ * (Node 22+ ships it; no dependency) and tests drive a fake.
18
+ */
19
+ import type { AexEvent } from "./event-envelope.js";
20
+ /** The slice of the WHATWG WebSocket this client depends on. */
21
+ export interface WebSocketLike {
22
+ close(code?: number, reason?: string): void;
23
+ addEventListener(type: "open" | "message" | "close" | "error", listener: (ev: {
24
+ data?: unknown;
25
+ }) => void): void;
26
+ }
27
+ export type WebSocketFactory = (url: string) => WebSocketLike;
28
+ export interface CoordinatorStreamOptions {
29
+ /** Base subscribe URL, e.g. `wss://coordinator/runs/<id>/subscribe`. */
30
+ readonly wsUrl: string;
31
+ /** Starting cursor: events with `sequence >= from` are delivered. Default 0 (from start). */
32
+ readonly from?: number;
33
+ /** Mint/refresh a short-lived connection ticket (called before each connect). */
34
+ readonly fetchTicket: () => Promise<string>;
35
+ readonly signal?: AbortSignal;
36
+ /** Injected WebSocket constructor; defaults to the global `WebSocket`. */
37
+ readonly webSocketFactory?: WebSocketFactory;
38
+ /** Reconnect ceiling (default: unlimited until terminal/abort). */
39
+ readonly maxReconnects?: number;
40
+ /** Backoff between reconnect attempts (default 500 ms). */
41
+ readonly reconnectDelayMs?: number;
42
+ }
43
+ export declare function streamCoordinatorEvents(opts: CoordinatorStreamOptions): AsyncGenerator<AexEvent, void, void>;
44
+ /** Async-iterable filter — keep only events matching the predicate. */
45
+ export declare function filterStream<T>(stream: AsyncIterable<T>, predicate: (event: T) => boolean): AsyncGenerator<T, void, void>;
46
+ /** Async-iterable map — project each event (e.g. with `toAGUI`). */
47
+ export declare function mapStream<T, U>(stream: AsyncIterable<T>, project: (event: T) => U): AsyncGenerator<U, void, void>;