agents 0.22.0 → 0.23.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 (186) hide show
  1. package/README.md +20 -1
  2. package/dist/{agent-routing-CnkaHb-v.d.ts → agent-routing-DE5zmCQ8.d.ts} +1038 -394
  3. package/dist/agent-routing.d.ts +1 -1
  4. package/dist/agent-tool-types.d.ts +26 -26
  5. package/dist/{agent-tools-C0XJqWzB.d.ts → agent-tools-DtXMTDGM.d.ts} +7 -7
  6. package/dist/agent-tools.d.ts +21 -21
  7. package/dist/browser/ai.js +4 -1
  8. package/dist/browser/ai.js.map +1 -1
  9. package/dist/browser/tanstack-ai.js.map +1 -1
  10. package/dist/callable-decorator-DP__HhBA.d.ts +72 -0
  11. package/dist/callable-decorator.d.ts +18 -0
  12. package/dist/callable-decorator.js +71 -0
  13. package/dist/callable-decorator.js.map +1 -0
  14. package/dist/capability-BjSKYpzg.js.map +1 -1
  15. package/dist/capability-runner-Be_-PLR1.d.ts +459 -0
  16. package/dist/channel-Bnm4S7T2.d.ts +491 -0
  17. package/dist/channels/ai-sdk.d.ts +46 -0
  18. package/dist/channels/ai-sdk.js +120 -0
  19. package/dist/channels/ai-sdk.js.map +1 -0
  20. package/dist/channels/email.d.ts +95 -0
  21. package/dist/channels/email.js +323 -0
  22. package/dist/channels/email.js.map +1 -0
  23. package/dist/channels/index.d.ts +233 -0
  24. package/dist/channels/index.js +608 -0
  25. package/dist/channels/index.js.map +1 -0
  26. package/dist/channels/slack.d.ts +140 -0
  27. package/dist/channels/slack.js +614 -0
  28. package/dist/channels/slack.js.map +1 -0
  29. package/dist/channels/tanstack-ai.d.ts +39 -0
  30. package/dist/channels/tanstack-ai.js +17 -0
  31. package/dist/channels/tanstack-ai.js.map +1 -0
  32. package/dist/channels/telegram.d.ts +106 -0
  33. package/dist/channels/telegram.js +427 -0
  34. package/dist/channels/telegram.js.map +1 -0
  35. package/dist/channels/voice.d.ts +45 -0
  36. package/dist/channels/voice.js +122 -0
  37. package/dist/channels/voice.js.map +1 -0
  38. package/dist/chat/index.d.ts +2325 -2019
  39. package/dist/chat/index.js +888 -518
  40. package/dist/chat/index.js.map +1 -1
  41. package/dist/chat-sdk/index.d.ts +7 -7
  42. package/dist/chat-sdk/index.js +1 -1
  43. package/dist/client.d.ts +1 -1
  44. package/dist/context/index.d.ts +216 -0
  45. package/dist/context/index.js +454 -0
  46. package/dist/context/index.js.map +1 -0
  47. package/dist/{current-agent-CuMErtly.d.ts → current-agent-Da_C9a3b.d.ts} +90 -107
  48. package/dist/current-agent-DhoDkSnH.js.map +1 -1
  49. package/dist/{diagnostics-CaBjfz4J.js → diagnostics-BzvaX2UT.js} +5 -1
  50. package/dist/diagnostics-BzvaX2UT.js.map +1 -0
  51. package/dist/diagnostics-C4jcz3VK.js +360 -0
  52. package/dist/diagnostics-C4jcz3VK.js.map +1 -0
  53. package/dist/index-BB0kqhIz.d.ts +101 -0
  54. package/dist/index-BVVgDSdq.d.ts +1 -0
  55. package/dist/index-XDkuQ7zm.d.ts +89 -0
  56. package/dist/{index-DcSAZKsB.d.ts → index-YSKgfgg9.d.ts} +3 -1
  57. package/dist/index.d.ts +91 -82
  58. package/dist/index.js +3 -2
  59. package/dist/ingress-BfetZbMO.js +83 -0
  60. package/dist/ingress-BfetZbMO.js.map +1 -0
  61. package/dist/internal-CYlgHl1l.js +59 -0
  62. package/dist/internal-CYlgHl1l.js.map +1 -0
  63. package/dist/internal_context.d.ts +1 -1
  64. package/dist/lifecycle/index.d.ts +35 -17
  65. package/dist/lifecycle/index.js +1 -1
  66. package/dist/lifecycle-CMRGjZdw.js +1299 -0
  67. package/dist/lifecycle-CMRGjZdw.js.map +1 -0
  68. package/dist/mcp/client/index.d.ts +20 -20
  69. package/dist/mcp/index.d.ts +35 -35
  70. package/dist/mcp/index.js +1 -1
  71. package/dist/observability/index.d.ts +1 -1
  72. package/dist/observability/index.js +1 -1
  73. package/dist/react.d.ts +4 -4
  74. package/dist/{retries-CAvxtG9d.d.ts → retries-D9Ds-1lz.d.ts} +17 -6
  75. package/dist/retries.d.ts +8 -6
  76. package/dist/retries.js +13 -1
  77. package/dist/retries.js.map +1 -1
  78. package/dist/routing/index.d.ts +137 -0
  79. package/dist/routing/index.js +244 -0
  80. package/dist/routing/index.js.map +1 -0
  81. package/dist/sanitize-D9TujEK8.js +79 -0
  82. package/dist/sanitize-D9TujEK8.js.map +1 -0
  83. package/dist/scheduler-DD9NdYbF.js +665 -0
  84. package/dist/scheduler-DD9NdYbF.js.map +1 -0
  85. package/dist/{scheduler-DQoTGoAW.d.ts → scheduler-Dwh85ZGl.d.ts} +21 -22
  86. package/dist/schedules/index.d.ts +1 -1
  87. package/dist/schedules/index.js +1 -1
  88. package/dist/sentence-chunker-BAidJ4DA.d.ts +68 -0
  89. package/dist/serializable.d.ts +1 -1
  90. package/dist/sessions/index.d.ts +441 -0
  91. package/dist/sessions/index.js +2063 -0
  92. package/dist/sessions/index.js.map +1 -0
  93. package/dist/skills/index.d.ts +99 -0
  94. package/dist/skills/index.js +254 -5
  95. package/dist/skills/index.js.map +1 -1
  96. package/dist/{src-5W6JNKVb.js → src-DlSHshb2.js} +1460 -1110
  97. package/dist/src-DlSHshb2.js.map +1 -0
  98. package/dist/streams/index.d.ts +120 -0
  99. package/dist/streams/index.js +107 -0
  100. package/dist/streams/index.js.map +1 -0
  101. package/dist/streams-D6tJ0NN9.d.ts +370 -0
  102. package/dist/streams-DZKgAj9b.js +709 -0
  103. package/dist/streams-DZKgAj9b.js.map +1 -0
  104. package/dist/sub-routing.d.ts +12 -12
  105. package/dist/surface-bZZJqBka.js +17 -0
  106. package/dist/surface-bZZJqBka.js.map +1 -0
  107. package/dist/tasks/index.d.ts +64 -0
  108. package/dist/tasks/index.js +2 -0
  109. package/dist/tasks-BRJ5zgya.d.ts +517 -0
  110. package/dist/tasks-ylZgBjhj.js +1656 -0
  111. package/dist/tasks-ylZgBjhj.js.map +1 -0
  112. package/dist/text-segment-joiner-BtAFQSA_.js +57 -0
  113. package/dist/text-segment-joiner-BtAFQSA_.js.map +1 -0
  114. package/dist/text-stream-CpdiKrJB.js +272 -0
  115. package/dist/text-stream-CpdiKrJB.js.map +1 -0
  116. package/dist/tokens-nHAKcN6M.js +52 -0
  117. package/dist/tokens-nHAKcN6M.js.map +1 -0
  118. package/dist/tool-schema-CBjGPrsQ.js +31 -0
  119. package/dist/tool-schema-CBjGPrsQ.js.map +1 -0
  120. package/dist/types-B7LojTe4.d.ts +202 -0
  121. package/dist/types-_Faxb570.d.ts +439 -0
  122. package/dist/voice/client.d.ts +226 -0
  123. package/dist/voice/client.js +932 -0
  124. package/dist/voice/client.js.map +1 -0
  125. package/dist/voice/errors.d.ts +43 -0
  126. package/dist/voice/errors.js +41 -0
  127. package/dist/voice/errors.js.map +1 -0
  128. package/dist/voice/index.d.ts +271 -0
  129. package/dist/voice/index.js +1812 -0
  130. package/dist/voice/index.js.map +1 -0
  131. package/dist/voice/react.d.ts +167 -0
  132. package/dist/voice/react.js +234 -0
  133. package/dist/voice/react.js.map +1 -0
  134. package/dist/voice/sfu.d.ts +71 -0
  135. package/dist/voice/sfu.js +157 -0
  136. package/dist/voice/sfu.js.map +1 -0
  137. package/dist/voice/text.d.ts +6 -0
  138. package/dist/voice/text.js +2 -0
  139. package/dist/voice/types.d.ts +58 -0
  140. package/dist/voice/types.js +18 -0
  141. package/dist/voice/types.js.map +1 -0
  142. package/dist/voice/workers-ai.d.ts +136 -0
  143. package/dist/voice/workers-ai.js +568 -0
  144. package/dist/voice/workers-ai.js.map +1 -0
  145. package/dist/websockets/index.d.ts +192 -0
  146. package/dist/websockets/index.js +2 -0
  147. package/dist/websockets-DUfRHPRq.js +502 -0
  148. package/dist/websockets-DUfRHPRq.js.map +1 -0
  149. package/dist/workflow-types.d.ts +25 -25
  150. package/dist/workflows.d.ts +21 -21
  151. package/dist/workflows.js +1 -1
  152. package/docs/agent-class.md +2 -2
  153. package/docs/agent-tools.md +2 -1
  154. package/docs/channels.md +323 -0
  155. package/docs/chat-agents.md +6 -13
  156. package/docs/context.md +131 -0
  157. package/docs/index.md +15 -12
  158. package/docs/lifecycle.md +102 -55
  159. package/docs/long-running-agents.md +2 -2
  160. package/docs/mcp-servers.md +5 -1
  161. package/docs/resumable-streaming.md +1 -1
  162. package/docs/routing.md +105 -0
  163. package/docs/sessions.md +237 -871
  164. package/docs/streams.md +213 -0
  165. package/docs/sub-agents.md +184 -124
  166. package/docs/tasks.md +246 -0
  167. package/docs/voice.md +745 -0
  168. package/package.json +115 -13
  169. package/dist/capability-runner-CvHGZqUu.d.ts +0 -150
  170. package/dist/compaction-helpers-iiKMr2TQ.js +0 -340
  171. package/dist/compaction-helpers-iiKMr2TQ.js.map +0 -1
  172. package/dist/compaction-helpers-wUz6M3us.d.ts +0 -621
  173. package/dist/diagnostics-CaBjfz4J.js.map +0 -1
  174. package/dist/durable-object-lifecycle-D6nNQJJd.js +0 -862
  175. package/dist/durable-object-lifecycle-D6nNQJJd.js.map +0 -1
  176. package/dist/experimental/memory/session/index.d.ts +0 -671
  177. package/dist/experimental/memory/session/index.js +0 -2379
  178. package/dist/experimental/memory/session/index.js.map +0 -1
  179. package/dist/experimental/memory/utils/index.d.ts +0 -96
  180. package/dist/experimental/memory/utils/index.js +0 -79
  181. package/dist/experimental/memory/utils/index.js.map +0 -1
  182. package/dist/scheduler-CR9RHGos.js +0 -857
  183. package/dist/scheduler-CR9RHGos.js.map +0 -1
  184. package/dist/src-5W6JNKVb.js.map +0 -1
  185. package/dist/tool-output-truncation-CNnnGZQ3.js +0 -98
  186. package/dist/tool-output-truncation-CNnnGZQ3.js.map +0 -1
@@ -0,0 +1,709 @@
1
+ import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
2
+ import { t as LifecycleCapability } from "./capability-BjSKYpzg.js";
3
+ import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
4
+ import { SqlError } from "./sql-error.js";
5
+ //#region src/streams/errors.ts
6
+ /**
7
+ * Error classes for the Streams capability. Each carries a stable `name` so
8
+ * hosts and tests can classify failures without depending on message text.
9
+ */
10
+ /**
11
+ * Thrown when `open()` targets a terminal stream, or an append reaches a
12
+ * stream that settled (or was deleted) after the writer was created.
13
+ *
14
+ * @experimental The API surface may change before stabilizing.
15
+ */
16
+ var StreamClosedError = class extends Error {
17
+ constructor(streamId, detail) {
18
+ super(`Stream "${streamId}" is closed: ${detail}`);
19
+ this.name = "StreamClosedError";
20
+ this.streamId = streamId;
21
+ }
22
+ };
23
+ /**
24
+ * Thrown when `read()` targets a stream that was never opened (or was
25
+ * deleted). `status()` returns `null` instead, for existence probes.
26
+ *
27
+ * @experimental The API surface may change before stabilizing.
28
+ */
29
+ var StreamNotFoundError = class extends Error {
30
+ constructor(streamId) {
31
+ super(`Stream "${streamId}" does not exist. Open it before reading, or use status() to probe for existence.`);
32
+ this.name = "StreamNotFoundError";
33
+ this.streamId = streamId;
34
+ }
35
+ };
36
+ /**
37
+ * Thrown when a chunk or metadata value is not JSON-serializable or exceeds
38
+ * the configured size limit.
39
+ *
40
+ * @experimental The API surface may change before stabilizing.
41
+ */
42
+ var StreamSerializationError = class extends Error {
43
+ constructor(context, detail) {
44
+ super(`Cannot serialize ${context}: ${detail}`);
45
+ this.name = "StreamSerializationError";
46
+ }
47
+ };
48
+ //#endregion
49
+ //#region src/streams/streams.ts
50
+ /**
51
+ * Durable incremental output for Lifecycle Objects. `Streams` owns the
52
+ * `cf_agents_streams` and `cf_agents_stream_blocks` tables: an ordered,
53
+ * durable chunk log per stream with a monotonic cursor, replay-then-tail
54
+ * reads, and terminal status that doubles as recovery evidence for the
55
+ * Tasks capability (which composes through checkpointed cursors, never
56
+ * imports).
57
+ *
58
+ * Streams consumes only the standard capability services — storage and
59
+ * events. It needs no alarm, so it also works on facets. Live fanout is
60
+ * in-isolate: a Durable Object executes in one isolate at a time, so every
61
+ * concurrent reader shares the producer's isolate; readers that outlive an
62
+ * isolate replay from their cursor on reconnect.
63
+ */
64
+ const STREAM_SCHEMA_VERSION_KEY = "cf_agents:streams_schema_version";
65
+ const CURRENT_STREAM_SCHEMA_VERSION = 2;
66
+ /**
67
+ * A block row grows by UPDATE until its body reaches this many characters,
68
+ * then the next append opens a new block. Sized well under the 2 MiB row
69
+ * limit so a 1 MiB chunk always fits in a fresh block, and small enough
70
+ * that a replay page parses one block at a time.
71
+ */
72
+ const BLOCK_MAX_CHARS = 256 * 1024;
73
+ /** Rows read per page while folding one stream's v1 chunk rows into blocks. */
74
+ const LEGACY_FOLD_PAGE_ROWS = 500;
75
+ /** Default ceiling for one serialized chunk (1 MiB). */
76
+ const DEFAULT_MAX_CHUNK_BYTES = 1048576;
77
+ const MAX_STREAM_ID_LENGTH = 256;
78
+ const READ_BATCH_SIZE = 100;
79
+ const DEFAULT_LIST_LIMIT = 100;
80
+ const utf8 = new TextEncoder();
81
+ var _maxChunkBytes = /* @__PURE__ */ new WeakMap();
82
+ var _wakeups = /* @__PURE__ */ new WeakMap();
83
+ var _legacyChunkTable = /* @__PURE__ */ new WeakMap();
84
+ var _Streams_brand = /* @__PURE__ */ new WeakSet();
85
+ var _deleteHooks = /* @__PURE__ */ new WeakMap();
86
+ /**
87
+ * Durable incremental output for a Lifecycle Object.
88
+ *
89
+ * `open()` a stream, `append()` chunks (synchronous durable writes that wake
90
+ * live readers), and settle it with `close()` or `error()`. `read()` replays
91
+ * persisted chunks from a cursor and then tails live appends; `status()`
92
+ * reports the state and cursor — the recovery evidence a Task's `recover`
93
+ * callback consults after its producer was interrupted.
94
+ *
95
+ * @experimental The API surface may change before stabilizing.
96
+ */
97
+ var Streams = class extends LifecycleCapability {
98
+ constructor(options = {}) {
99
+ super("streams");
100
+ _classPrivateMethodInitSpec(this, _Streams_brand);
101
+ _classPrivateFieldInitSpec(this, _maxChunkBytes, void 0);
102
+ _classPrivateFieldInitSpec(this, _wakeups, /* @__PURE__ */ new Map());
103
+ _classPrivateFieldInitSpec(this, _legacyChunkTable, false);
104
+ _classPrivateFieldInitSpec(this, _deleteHooks, []);
105
+ _classPrivateFieldSet2(_maxChunkBytes, this, options.maxChunkBytes ?? 1048576);
106
+ }
107
+ /** Migrate stream storage during Lifecycle startup. */
108
+ async onStart() {
109
+ const storage = this.lifecycle.storage;
110
+ const version = await storage.get(STREAM_SCHEMA_VERSION_KEY) ?? 0;
111
+ if (version < CURRENT_STREAM_SCHEMA_VERSION) {
112
+ _assertClassBrand(_Streams_brand, this, _ensureTables).call(this);
113
+ await storage.put(STREAM_SCHEMA_VERSION_KEY, CURRENT_STREAM_SCHEMA_VERSION);
114
+ }
115
+ if (version >= 1) _classPrivateFieldSet2(_legacyChunkTable, this, _assertClassBrand(_Streams_brand, this, _hasLegacyChunkTable).call(this));
116
+ }
117
+ /**
118
+ * Open a stream for writing. Idempotent on the id: reopening a live stream
119
+ * returns a writer positioned at its current cursor; reopening a terminal
120
+ * stream throws {@link StreamClosedError}.
121
+ */
122
+ async open(streamId, options = {}) {
123
+ await this.lifecycle.ready();
124
+ _assertClassBrand(_Streams_brand, this, _validateStreamId).call(this, streamId);
125
+ const existing = _assertClassBrand(_Streams_brand, this, _getStream).call(this, streamId);
126
+ if (existing) {
127
+ if (existing.state !== "streaming") throw new StreamClosedError(streamId, `already settled as ${existing.state}`);
128
+ if (options.tag !== void 0 && options.tag !== (existing.tag ?? void 0)) throw new Error(`Stream "${streamId}" is already open with tag ${JSON.stringify(existing.tag)}; refusing reopen with tag ${JSON.stringify(options.tag)}`);
129
+ return _assertClassBrand(_Streams_brand, this, _writer).call(this, streamId);
130
+ }
131
+ const metadataJson = _assertClassBrand(_Streams_brand, this, _serialize).call(this, options.metadata, `metadata for stream "${streamId}"`);
132
+ const now = Date.now();
133
+ _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
134
+ INSERT INTO cf_agents_streams
135
+ (stream_id, state, tag, metadata, chunk_count, created_at, updated_at)
136
+ VALUES
137
+ (${streamId}, 'streaming', ${options.tag ?? null}, ${metadataJson}, 0, ${now}, ${now})
138
+ `;
139
+ _assertClassBrand(_Streams_brand, this, _emit).call(this, "stream:opened", { streamId });
140
+ return _assertClassBrand(_Streams_brand, this, _writer).call(this, streamId);
141
+ }
142
+ /**
143
+ * Replay persisted chunks from `from` (inclusive), then tail live appends
144
+ * until the stream settles. Ends when the stream reaches a terminal state
145
+ * and every durable chunk has been yielded; a read of an `errored` stream
146
+ * still yields its chunks and then simply ends — consult {@link status}
147
+ * for the terminal outcome. Aborting `options.signal` throws its reason.
148
+ */
149
+ async *read(streamId, options = {}) {
150
+ const signal = options.signal;
151
+ for await (const batch of this.readBatches(streamId, options)) for (const item of batch) {
152
+ if (signal?.aborted) throw signal.reason ?? /* @__PURE__ */ new Error("Read aborted");
153
+ yield item;
154
+ }
155
+ }
156
+ /**
157
+ * Batched form of {@link read}: yields non-empty arrays of consecutive
158
+ * chunks instead of one chunk at a time. Replay yields up to
159
+ * `options.batchSize` chunks per array; a live tail yields everything
160
+ * that accumulated since the last wakeup as one array — so a consumer
161
+ * paying per write (an SSE flush, an RPC hop, a history append) pays
162
+ * once per backlog, not once per chunk. Same lifecycle as {@link read}:
163
+ * ends when the stream settles and every durable chunk has been
164
+ * yielded; aborting `options.signal` throws its reason.
165
+ */
166
+ async *readBatches(streamId, options = {}) {
167
+ await this.lifecycle.ready();
168
+ const signal = options.signal;
169
+ const batchSize = Math.max(1, Math.floor(options.batchSize ?? READ_BATCH_SIZE));
170
+ let next = Math.max(0, options.from ?? 0);
171
+ let signaledUpToDate = false;
172
+ if (_assertClassBrand(_Streams_brand, this, _state).call(this, streamId) === void 0) throw new StreamNotFoundError(streamId);
173
+ for (;;) {
174
+ if (signal?.aborted) throw signal.reason ?? /* @__PURE__ */ new Error("Read aborted");
175
+ const rows = _assertClassBrand(_Streams_brand, this, _readChunks).call(this, streamId, next, batchSize);
176
+ if (rows.length > 0) {
177
+ next = rows[rows.length - 1].seq + 1;
178
+ yield rows.map((row) => ({
179
+ seq: row.seq,
180
+ chunk: JSON.parse(row.chunk)
181
+ }));
182
+ }
183
+ if (rows.length === batchSize) continue;
184
+ if (!signaledUpToDate) {
185
+ signaledUpToDate = true;
186
+ options.onUpToDate?.();
187
+ continue;
188
+ }
189
+ const state = _assertClassBrand(_Streams_brand, this, _state).call(this, streamId);
190
+ if (state === void 0) return;
191
+ if (state !== "streaming") {
192
+ if (rows.length === 0) return;
193
+ continue;
194
+ }
195
+ await _assertClassBrand(_Streams_brand, this, _waitForWakeup).call(this, streamId, signal);
196
+ }
197
+ }
198
+ /** Read one stream's state and cursor, or null when it does not exist. */
199
+ async status(streamId) {
200
+ await this.lifecycle.ready();
201
+ const row = _assertClassBrand(_Streams_brand, this, _getStream).call(this, streamId);
202
+ return row ? _assertClassBrand(_Streams_brand, this, _rowToStatus).call(this, row) : null;
203
+ }
204
+ /** List streams, newest first. */
205
+ async list(options = {}) {
206
+ await this.lifecycle.ready();
207
+ const states = Array.isArray(options.state) ? options.state : options.state !== void 0 ? [options.state] : [];
208
+ let query = "SELECT * FROM cf_agents_streams WHERE 1 = 1";
209
+ const params = [];
210
+ if (states.length > 0) {
211
+ query += ` AND state IN (${states.map(() => "?").join(", ")})`;
212
+ params.push(...states);
213
+ }
214
+ if (options.tag !== void 0) {
215
+ query += " AND tag = ?";
216
+ params.push(options.tag);
217
+ }
218
+ query += " ORDER BY created_at DESC, stream_id DESC LIMIT ?";
219
+ params.push(options.limit ?? DEFAULT_LIST_LIMIT);
220
+ let rows;
221
+ try {
222
+ rows = this.lifecycle.storage.sql.exec(query, ...params).toArray();
223
+ } catch (cause) {
224
+ throw new SqlError(query, cause);
225
+ }
226
+ return rows.map((row) => _assertClassBrand(_Streams_brand, this, _rowToStatus).call(this, row));
227
+ }
228
+ /**
229
+ * Delete one terminal stream and its chunk log.
230
+ *
231
+ * @returns True when a terminal stream was deleted; false when none
232
+ * exists. Throws on a live stream — settle it first.
233
+ */
234
+ async delete(streamId) {
235
+ await this.lifecycle.ready();
236
+ const row = _assertClassBrand(_Streams_brand, this, _getStream).call(this, streamId);
237
+ if (!row) return false;
238
+ if (row.state === "streaming") throw new Error(`Cannot delete live stream "${streamId}"; close() or error() it first`);
239
+ _assertClassBrand(_Streams_brand, this, _deleteRows).call(this, streamId);
240
+ _assertClassBrand(_Streams_brand, this, _emit).call(this, "stream:deleted", { streamId });
241
+ return true;
242
+ }
243
+ /**
244
+ * @internal Synchronous storage operations for same-isolate first-party
245
+ * machinery — today the chat `ResumableStream` adapter, whose whole public
246
+ * surface is synchronous and constructed before the Lifecycle starts.
247
+ * Bypasses `lifecycle.ready()`: the caller owns startup ordering. The
248
+ * invariant-bearing writes (append fence, settlement, wakeups, events) go
249
+ * through the same private methods as the public API, so live readers and
250
+ * diagnostics observe aperture writes exactly like capability writes. Will
251
+ * break without notice; never use from application code.
252
+ */
253
+ __DO_NOT_USE_WILL_BREAK__sync() {
254
+ return {
255
+ ensureTables: () => _assertClassBrand(_Streams_brand, this, _ensureTables).call(this),
256
+ getStream: (streamId) => _assertClassBrand(_Streams_brand, this, _getStream).call(this, streamId),
257
+ insertStream: (streamId, tag, metadata) => {
258
+ _assertClassBrand(_Streams_brand, this, _validateStreamId).call(this, streamId);
259
+ const metadataJson = _assertClassBrand(_Streams_brand, this, _serialize).call(this, metadata, `metadata for stream "${streamId}"`);
260
+ const now = Date.now();
261
+ _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
262
+ INSERT INTO cf_agents_streams
263
+ (stream_id, state, tag, metadata, chunk_count, created_at, updated_at)
264
+ VALUES
265
+ (${streamId}, 'streaming', ${tag}, ${metadataJson}, 0, ${now}, ${now})
266
+ `;
267
+ _assertClassBrand(_Streams_brand, this, _emit).call(this, "stream:opened", { streamId });
268
+ },
269
+ append: (streamId, chunk) => _assertClassBrand(_Streams_brand, this, _append).call(this, streamId, chunk),
270
+ lastChunkAt: (streamId) => _assertClassBrand(_Streams_brand, this, _tail).call(this, streamId).lastChunkAt,
271
+ cursor: (streamId) => _assertClassBrand(_Streams_brand, this, _tail).call(this, streamId).nextSeq,
272
+ onDelete: (hook) => {
273
+ _classPrivateFieldGet2(_deleteHooks, this).push(hook);
274
+ return () => {
275
+ const index = _classPrivateFieldGet2(_deleteHooks, this).indexOf(hook);
276
+ if (index !== -1) _classPrivateFieldGet2(_deleteHooks, this).splice(index, 1);
277
+ };
278
+ },
279
+ settle: (streamId, state, reason, options) => _assertClassBrand(_Streams_brand, this, _settle).call(this, streamId, state, reason, options),
280
+ deleteUnchecked: (streamId) => {
281
+ if (_assertClassBrand(_Streams_brand, this, _deleteRows).call(this, streamId) > 0) _assertClassBrand(_Streams_brand, this, _emit).call(this, "stream:deleted", { streamId });
282
+ _assertClassBrand(_Streams_brand, this, _wake).call(this, streamId);
283
+ },
284
+ deleteMany: (streamIds) => {
285
+ for (const streamId of streamIds) {
286
+ _assertClassBrand(_Streams_brand, this, _deleteRows).call(this, streamId);
287
+ _assertClassBrand(_Streams_brand, this, _wake).call(this, streamId);
288
+ }
289
+ },
290
+ readChunks: (streamId, fromSeq, limit) => _assertClassBrand(_Streams_brand, this, _readChunks).call(this, streamId, fromSeq, limit),
291
+ listRows: () => _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
292
+ SELECT * FROM cf_agents_streams ORDER BY created_at DESC, rowid DESC
293
+ `,
294
+ rowsByTag: (tag, state) => state ? _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
295
+ SELECT * FROM cf_agents_streams
296
+ WHERE tag = ${tag} AND state = ${state}
297
+ ORDER BY created_at DESC, rowid DESC
298
+ ` : _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
299
+ SELECT * FROM cf_agents_streams
300
+ WHERE tag = ${tag}
301
+ ORDER BY created_at DESC, rowid DESC
302
+ `,
303
+ importStream: (row) => {
304
+ _assertClassBrand(_Streams_brand, this, _validateStreamId).call(this, row.streamId);
305
+ const metadataJson = _assertClassBrand(_Streams_brand, this, _serialize).call(this, row.metadata, `metadata for stream "${row.streamId}"`);
306
+ _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
307
+ INSERT INTO cf_agents_streams
308
+ (stream_id, state, tag, metadata, chunk_count,
309
+ created_at, updated_at, closed_at)
310
+ VALUES
311
+ (${row.streamId}, ${row.state}, ${row.tag}, ${metadataJson},
312
+ ${row.chunkCount}, ${row.createdAt}, ${row.updatedAt},
313
+ ${row.closedAt})
314
+ `;
315
+ },
316
+ importChunk: (streamId, chunk, createdAt) => {
317
+ const chunkJson = _assertClassBrand(_Streams_brand, this, _serialize).call(this, chunk, `chunk for stream "${streamId}"`);
318
+ if (chunkJson === null) return;
319
+ _assertClassBrand(_Streams_brand, this, _writeChunk).call(this, streamId, chunkJson, createdAt);
320
+ }
321
+ };
322
+ }
323
+ };
324
+ function _writer(streamId) {
325
+ const capability = this;
326
+ return {
327
+ streamId,
328
+ get cursor() {
329
+ return _assertClassBrand(_Streams_brand, capability, _tail).call(capability, streamId).nextSeq;
330
+ },
331
+ append: (chunk) => _assertClassBrand(_Streams_brand, this, _append).call(this, streamId, chunk),
332
+ close: (options) => _assertClassBrand(_Streams_brand, this, _settle).call(this, streamId, "completed", null, options),
333
+ error: (reason, options) => _assertClassBrand(_Streams_brand, this, _settle).call(this, streamId, "errored", reason ?? null, options)
334
+ };
335
+ }
336
+ function _append(streamId, chunk) {
337
+ const chunkJson = _assertClassBrand(_Streams_brand, this, _serialize).call(this, chunk, `chunk for stream "${streamId}"`);
338
+ if (chunkJson === null) throw new StreamSerializationError(`chunk for stream "${streamId}"`, "chunks must not be undefined");
339
+ const state = _assertClassBrand(_Streams_brand, this, _state).call(this, streamId);
340
+ if (state !== "streaming") throw new StreamClosedError(streamId, state !== void 0 ? `already settled as ${state}` : "it was deleted");
341
+ const seq = _assertClassBrand(_Streams_brand, this, _writeChunk).call(this, streamId, chunkJson, Date.now());
342
+ _assertClassBrand(_Streams_brand, this, _wake).call(this, streamId);
343
+ return seq;
344
+ }
345
+ /**
346
+ * Append one serialized chunk to the stream's open block, or open a new
347
+ * block when the current one is full. Either way it is one billed row:
348
+ * an UPDATE that grows the block body, or the INSERT of the next block.
349
+ * Blocks are what make cleanup cheap — a stream of thousands of chunks
350
+ * is a handful of rows to delete at cutover, not thousands.
351
+ */
352
+ function _writeChunk(streamId, chunkJson, at) {
353
+ const tail = _assertClassBrand(_Streams_brand, this, _blockTail).call(this, streamId);
354
+ const seq = tail?.seq_to ?? 0;
355
+ if (tail && tail.len + chunkJson.length + 1 <= BLOCK_MAX_CHARS) _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
356
+ UPDATE cf_agents_stream_blocks
357
+ SET body = body || ',' || ${chunkJson}, seq_to = ${seq + 1}, updated_at = ${at}
358
+ WHERE stream_id = ${streamId} AND block = ${tail.block}
359
+ `;
360
+ else _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
361
+ INSERT INTO cf_agents_stream_blocks
362
+ (stream_id, block, seq_from, seq_to, body, created_at, updated_at)
363
+ VALUES
364
+ (${streamId}, ${(tail?.block ?? -1) + 1}, ${seq}, ${seq + 1}, ${chunkJson}, ${at}, ${at})
365
+ `;
366
+ return seq;
367
+ }
368
+ /**
369
+ * One page of chunks from `fromSeq`, in seq order, parsing one block at
370
+ * a time. A block body is the chunks' JSON texts joined by commas, so
371
+ * `[${body}]` parses straight back into the chunk values.
372
+ */
373
+ function _readChunks(streamId, fromSeq, limit) {
374
+ _assertClassBrand(_Streams_brand, this, _foldLegacyChunks).call(this, streamId);
375
+ const rows = [];
376
+ let block = -1;
377
+ while (rows.length < limit) {
378
+ const next = _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
379
+ SELECT block, seq_from, seq_to, body, updated_at
380
+ FROM cf_agents_stream_blocks
381
+ WHERE stream_id = ${streamId} AND block > ${block} AND seq_to > ${fromSeq}
382
+ ORDER BY block ASC
383
+ LIMIT 1
384
+ `[0];
385
+ if (!next) break;
386
+ block = next.block;
387
+ const chunks = JSON.parse(`[${next.body}]`);
388
+ for (let seq = Math.max(fromSeq, next.seq_from); seq < next.seq_to && rows.length < limit; seq++) rows.push({
389
+ stream_id: streamId,
390
+ seq,
391
+ chunk: JSON.stringify(chunks[seq - next.seq_from]),
392
+ created_at: next.updated_at
393
+ });
394
+ }
395
+ return rows;
396
+ }
397
+ /**
398
+ * Remove a stream's row and log. Deletion hooks see the row and its
399
+ * cursor first, so an owner can account for the segments before they are
400
+ * gone; this is the single point every delete path passes through.
401
+ */
402
+ function _deleteRows(streamId) {
403
+ if (_classPrivateFieldGet2(_deleteHooks, this).length > 0) {
404
+ const row = _assertClassBrand(_Streams_brand, this, _getStream).call(this, streamId);
405
+ if (row) {
406
+ const cursor = _assertClassBrand(_Streams_brand, this, _tail).call(this, streamId).nextSeq;
407
+ for (const hook of _classPrivateFieldGet2(_deleteHooks, this)) hook(row, cursor);
408
+ }
409
+ }
410
+ if (_classPrivateFieldGet2(_legacyChunkTable, this)) {
411
+ _assertClassBrand(_Streams_brand, this, _sql).bind(this)`DELETE FROM cf_agents_stream_chunks WHERE stream_id = ${streamId}`;
412
+ _assertClassBrand(_Streams_brand, this, _dropLegacyChunkTableIfEmpty).call(this);
413
+ }
414
+ _assertClassBrand(_Streams_brand, this, _sql).bind(this)`DELETE FROM cf_agents_stream_blocks WHERE stream_id = ${streamId}`;
415
+ return _assertClassBrand(_Streams_brand, this, _sqlWrite).call(this, "DELETE FROM cf_agents_streams WHERE stream_id = ?", [streamId]);
416
+ }
417
+ /**
418
+ * @returns Whether this call transitioned the stream (a repeat, or a
419
+ * deleted stream, is a no-op and returns false: the caller's `commit`
420
+ * does not run and nothing is discarded).
421
+ */
422
+ function _settle(streamId, state, reason, options) {
423
+ if (!options?.commit && !options?.discard) {
424
+ const settled = _assertClassBrand(_Streams_brand, this, _settleRow).call(this, streamId, state, reason);
425
+ if (settled) _assertClassBrand(_Streams_brand, this, _emitSettled).call(this, streamId, state, reason);
426
+ _assertClassBrand(_Streams_brand, this, _wake).call(this, streamId);
427
+ return settled;
428
+ }
429
+ let settled = false;
430
+ let deleted = false;
431
+ const hadLegacy = _classPrivateFieldGet2(_legacyChunkTable, this);
432
+ try {
433
+ this.lifecycle.storage.transactionSync(() => {
434
+ settled = _assertClassBrand(_Streams_brand, this, _settleRow).call(this, streamId, state, reason);
435
+ if (!settled) return;
436
+ options.commit?.();
437
+ if (options.discard) deleted = _assertClassBrand(_Streams_brand, this, _deleteRows).call(this, streamId) > 0;
438
+ });
439
+ } finally {
440
+ if (hadLegacy && !_classPrivateFieldGet2(_legacyChunkTable, this)) _classPrivateFieldSet2(_legacyChunkTable, this, _assertClassBrand(_Streams_brand, this, _hasLegacyChunkTable).call(this));
441
+ }
442
+ if (settled) _assertClassBrand(_Streams_brand, this, _emitSettled).call(this, streamId, state, reason);
443
+ if (deleted) _assertClassBrand(_Streams_brand, this, _emit).call(this, "stream:deleted", { streamId });
444
+ _assertClassBrand(_Streams_brand, this, _wake).call(this, streamId);
445
+ return settled;
446
+ }
447
+ /**
448
+ * The one guarded UPDATE that ends a stream. Settlement is the moment
449
+ * the stream row becomes exact at rest: the same write stamps the final
450
+ * cursor, read from the chunk log's tail in the same synchronous block.
451
+ * While the stream was live, appends wrote only the chunk log — the
452
+ * row's chunk_count and updated_at were not maintained per append.
453
+ * @returns Whether the row transitioned from `streaming`.
454
+ */
455
+ function _settleRow(streamId, state, reason) {
456
+ const finalCursor = _assertClassBrand(_Streams_brand, this, _tail).call(this, streamId).nextSeq;
457
+ return _assertClassBrand(_Streams_brand, this, _sqlWrite).call(this, `UPDATE cf_agents_streams
458
+ SET state = ?, error_message = ?, closed_at = ?, updated_at = ?,
459
+ chunk_count = ?
460
+ WHERE stream_id = ? AND state = 'streaming'`, [
461
+ state,
462
+ reason,
463
+ Date.now(),
464
+ Date.now(),
465
+ finalCursor,
466
+ streamId
467
+ ]) > 0;
468
+ }
469
+ function _emitSettled(streamId, state, reason) {
470
+ _assertClassBrand(_Streams_brand, this, _emit).call(this, state === "completed" ? "stream:closed" : "stream:errored", {
471
+ streamId,
472
+ ...reason !== null ? { reason } : {}
473
+ });
474
+ }
475
+ function _wake(streamId) {
476
+ const waiters = _classPrivateFieldGet2(_wakeups, this).get(streamId);
477
+ if (!waiters) return;
478
+ _classPrivateFieldGet2(_wakeups, this).delete(streamId);
479
+ for (const wake of waiters) wake();
480
+ }
481
+ function _waitForWakeup(streamId, signal) {
482
+ return new Promise((resolve) => {
483
+ const waiters = _classPrivateFieldGet2(_wakeups, this).get(streamId) ?? /* @__PURE__ */ new Set();
484
+ _classPrivateFieldGet2(_wakeups, this).set(streamId, waiters);
485
+ const wake = () => {
486
+ signal?.removeEventListener("abort", onAbort);
487
+ resolve();
488
+ };
489
+ const onAbort = () => {
490
+ waiters.delete(wake);
491
+ if (waiters.size === 0 && _classPrivateFieldGet2(_wakeups, this).get(streamId) === waiters) _classPrivateFieldGet2(_wakeups, this).delete(streamId);
492
+ resolve();
493
+ };
494
+ waiters.add(wake);
495
+ signal?.addEventListener("abort", onAbort, { once: true });
496
+ });
497
+ }
498
+ function _validateStreamId(streamId) {
499
+ if (typeof streamId !== "string" || streamId.length === 0) throw new Error("Stream ids must be non-empty strings");
500
+ if (streamId.length > MAX_STREAM_ID_LENGTH) throw new Error(`Stream id exceeds ${MAX_STREAM_ID_LENGTH} characters`);
501
+ }
502
+ function _serialize(value, context) {
503
+ if (value === void 0) return null;
504
+ let json;
505
+ try {
506
+ json = JSON.stringify(value);
507
+ } catch (error) {
508
+ throw new StreamSerializationError(context, error instanceof Error ? error.message : String(error));
509
+ }
510
+ if (json === void 0) throw new StreamSerializationError(context, `value of type ${typeof value} has no JSON representation`);
511
+ const bytes = utf8.encode(json).byteLength;
512
+ if (bytes > _classPrivateFieldGet2(_maxChunkBytes, this)) throw new StreamSerializationError(context, `serialized size ${bytes} bytes exceeds the ${_classPrivateFieldGet2(_maxChunkBytes, this)}-byte limit`);
513
+ return json;
514
+ }
515
+ function _sql(strings, ...values) {
516
+ const query = strings.reduce((result, part, index) => result + part + (index < values.length ? "?" : ""), "");
517
+ try {
518
+ return [...this.lifecycle.storage.sql.exec(query, ...values)];
519
+ } catch (cause) {
520
+ throw new SqlError(query, cause);
521
+ }
522
+ }
523
+ function _sqlWrite(query, params) {
524
+ try {
525
+ return this.lifecycle.storage.sql.exec(query, ...params).rowsWritten;
526
+ } catch (cause) {
527
+ throw new SqlError(query, cause);
528
+ }
529
+ }
530
+ function _getStream(streamId) {
531
+ return _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
532
+ SELECT * FROM cf_agents_streams WHERE stream_id = ${streamId}
533
+ `[0];
534
+ }
535
+ /**
536
+ * One stream's state alone — the narrow read for the append fence and the
537
+ * reader loop's liveness checks, which need neither the metadata column
538
+ * nor the (live-stale) counters of the full row.
539
+ */
540
+ function _state(streamId) {
541
+ return _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
542
+ SELECT state FROM cf_agents_streams WHERE stream_id = ${streamId}
543
+ `[0]?.state;
544
+ }
545
+ /**
546
+ * The chunk log's tail: the next append sequence and the newest chunk's
547
+ * timestamp. One PK-served read (`ORDER BY seq DESC LIMIT 1`), and the
548
+ * single derivation point for every cursor and per-append-liveness
549
+ * consumer — while a stream is live, the chunk log is authoritative and
550
+ * the stream row's `chunk_count`/`updated_at` are not maintained.
551
+ */
552
+ function _tail(streamId) {
553
+ const tail = _assertClassBrand(_Streams_brand, this, _blockTail).call(this, streamId);
554
+ return tail ? {
555
+ nextSeq: tail.seq_to,
556
+ lastChunkAt: tail.updated_at
557
+ } : {
558
+ nextSeq: 0,
559
+ lastChunkAt: null
560
+ };
561
+ }
562
+ /** The open block: one PK-served read (`ORDER BY block DESC LIMIT 1`). */
563
+ function _blockTail(streamId) {
564
+ _assertClassBrand(_Streams_brand, this, _foldLegacyChunks).call(this, streamId);
565
+ return _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
566
+ SELECT block, seq_to, updated_at, length(body) AS len
567
+ FROM cf_agents_stream_blocks
568
+ WHERE stream_id = ${streamId}
569
+ ORDER BY block DESC
570
+ LIMIT 1
571
+ `[0];
572
+ }
573
+ /**
574
+ * Schema v1 → v2 is lazy: the per-chunk `cf_agents_stream_chunks` rows of
575
+ * ONE stream are folded into blocks the first time that stream is
576
+ * touched (a tail read before an append or settle, a replay, a delete).
577
+ * Startup never pays for the whole legacy log, so an object that let a
578
+ * large log accumulate still boots within its memory budget; each fold
579
+ * pages through its stream's rows and writes whole blocks, not one row
580
+ * per chunk. The table is dropped once the last stream's rows are gone.
581
+ */
582
+ function _foldLegacyChunks(streamId) {
583
+ if (!_classPrivateFieldGet2(_legacyChunkTable, this)) return;
584
+ this.lifecycle.storage.transactionSync(() => {
585
+ const tail = _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
586
+ SELECT block, seq_to FROM cf_agents_stream_blocks
587
+ WHERE stream_id = ${streamId}
588
+ ORDER BY block DESC
589
+ LIMIT 1
590
+ `[0];
591
+ let block = (tail?.block ?? -1) + 1;
592
+ let seq = tail?.seq_to ?? 0;
593
+ let body = "";
594
+ let seqFrom = seq;
595
+ let createdAt = 0;
596
+ let updatedAt = 0;
597
+ const flush = () => {
598
+ if (body === "") return;
599
+ _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
600
+ INSERT INTO cf_agents_stream_blocks
601
+ (stream_id, block, seq_from, seq_to, body, created_at, updated_at)
602
+ VALUES
603
+ (${streamId}, ${block}, ${seqFrom}, ${seq}, ${body}, ${createdAt}, ${updatedAt})
604
+ `;
605
+ block += 1;
606
+ body = "";
607
+ seqFrom = seq;
608
+ };
609
+ let after = -1;
610
+ for (;;) {
611
+ const rows = _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
612
+ SELECT seq, chunk, created_at FROM cf_agents_stream_chunks
613
+ WHERE stream_id = ${streamId} AND seq > ${after}
614
+ ORDER BY seq ASC
615
+ LIMIT ${LEGACY_FOLD_PAGE_ROWS}
616
+ `;
617
+ for (const row of rows) {
618
+ if (body !== "" && body.length + row.chunk.length + 1 > BLOCK_MAX_CHARS) flush();
619
+ if (body === "") createdAt = row.created_at;
620
+ body = body === "" ? row.chunk : `${body},${row.chunk}`;
621
+ updatedAt = row.created_at;
622
+ seq += 1;
623
+ after = row.seq;
624
+ }
625
+ if (rows.length < LEGACY_FOLD_PAGE_ROWS) break;
626
+ }
627
+ flush();
628
+ if (after >= 0) _assertClassBrand(_Streams_brand, this, _sql).bind(this)`DELETE FROM cf_agents_stream_chunks WHERE stream_id = ${streamId}`;
629
+ _assertClassBrand(_Streams_brand, this, _dropLegacyChunkTableIfEmpty).call(this);
630
+ });
631
+ }
632
+ function _hasLegacyChunkTable() {
633
+ return _assertClassBrand(_Streams_brand, this, _sql).bind(this)`
634
+ SELECT name FROM sqlite_master
635
+ WHERE type = 'table' AND name = 'cf_agents_stream_chunks'
636
+ `.length > 0;
637
+ }
638
+ function _dropLegacyChunkTableIfEmpty() {
639
+ if (_assertClassBrand(_Streams_brand, this, _sql).bind(this)`
640
+ SELECT COUNT(*) AS n FROM (SELECT 1 FROM cf_agents_stream_chunks LIMIT 1)
641
+ `[0].n > 0) return;
642
+ _assertClassBrand(_Streams_brand, this, _sqlWrite).call(this, "DROP TABLE cf_agents_stream_chunks", []);
643
+ _classPrivateFieldSet2(_legacyChunkTable, this, false);
644
+ }
645
+ function _rowToStatus(row) {
646
+ let cursor = row.chunk_count;
647
+ let updatedAt = row.updated_at;
648
+ if (row.state === "streaming") {
649
+ const tail = _assertClassBrand(_Streams_brand, this, _tail).call(this, row.stream_id);
650
+ cursor = tail.nextSeq;
651
+ if (tail.lastChunkAt !== null && tail.lastChunkAt > updatedAt) updatedAt = tail.lastChunkAt;
652
+ }
653
+ return {
654
+ streamId: row.stream_id,
655
+ state: row.state,
656
+ cursor,
657
+ ...row.tag !== null ? { tag: row.tag } : {},
658
+ ...row.metadata !== null ? { metadata: JSON.parse(row.metadata) } : {},
659
+ ...row.error_message !== null ? { error: row.error_message } : {},
660
+ createdAt: row.created_at,
661
+ updatedAt,
662
+ ...row.closed_at !== null ? { closedAt: row.closed_at } : {}
663
+ };
664
+ }
665
+ function _ensureTables() {
666
+ const rawSql = (query) => {
667
+ try {
668
+ this.lifecycle.storage.sql.exec(query);
669
+ } catch (cause) {
670
+ throw new SqlError(query, cause);
671
+ }
672
+ };
673
+ rawSql(`
674
+ CREATE TABLE IF NOT EXISTS cf_agents_streams (
675
+ stream_id TEXT PRIMARY KEY,
676
+ state TEXT NOT NULL CHECK (state IN (
677
+ 'streaming', 'completed', 'errored'
678
+ )),
679
+ tag TEXT,
680
+ metadata TEXT,
681
+ error_message TEXT,
682
+ chunk_count INTEGER NOT NULL DEFAULT 0,
683
+ created_at INTEGER NOT NULL,
684
+ updated_at INTEGER NOT NULL,
685
+ closed_at INTEGER
686
+ )`);
687
+ rawSql(`
688
+ CREATE INDEX IF NOT EXISTS idx_cf_agents_streams_tag
689
+ ON cf_agents_streams(tag, created_at)
690
+ `);
691
+ rawSql(`
692
+ CREATE TABLE IF NOT EXISTS cf_agents_stream_blocks (
693
+ stream_id TEXT NOT NULL,
694
+ block INTEGER NOT NULL,
695
+ seq_from INTEGER NOT NULL,
696
+ seq_to INTEGER NOT NULL,
697
+ body TEXT NOT NULL,
698
+ created_at INTEGER NOT NULL,
699
+ updated_at INTEGER NOT NULL,
700
+ PRIMARY KEY (stream_id, block)
701
+ ) WITHOUT ROWID`);
702
+ }
703
+ function _emit(type, payload) {
704
+ this.lifecycle.events.emit(type, payload);
705
+ }
706
+ //#endregion
707
+ export { StreamSerializationError as a, StreamNotFoundError as i, Streams as n, StreamClosedError as r, DEFAULT_MAX_CHUNK_BYTES as t };
708
+
709
+ //# sourceMappingURL=streams-DZKgAj9b.js.map