@demlik/tea 0.1.2 → 0.3.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 (212) hide show
  1. package/README.md +49 -0
  2. package/dist/agent/index.d.ts +16 -770
  3. package/dist/agent/index.js +18 -16
  4. package/dist/authed-call/index.d.ts +3 -3
  5. package/dist/authed-call/index.js +22 -36
  6. package/dist/authed-call/index.js.map +1 -1
  7. package/dist/await-terminal/index.d.ts +2 -2
  8. package/dist/await-terminal/index.js +2 -2
  9. package/dist/batch-window/index.d.ts +3 -3
  10. package/dist/batch-window/index.js +3 -3
  11. package/dist/cache/index.d.ts +2 -2
  12. package/dist/cache/index.js +5 -2
  13. package/dist/{chunk-3545BOYL.js → chunk-25LBDCBC.js} +6 -5
  14. package/dist/chunk-25LBDCBC.js.map +1 -0
  15. package/dist/{chunk-IN33Q4VJ.js → chunk-2KNLKQVN.js} +3 -3
  16. package/dist/{chunk-IN33Q4VJ.js.map → chunk-2KNLKQVN.js.map} +1 -1
  17. package/dist/{chunk-MMH7CW5K.js → chunk-BP2R7TPP.js} +216 -157
  18. package/dist/chunk-BP2R7TPP.js.map +1 -0
  19. package/dist/chunk-C6QC273X.js +71 -0
  20. package/dist/chunk-C6QC273X.js.map +1 -0
  21. package/dist/{chunk-7W4LMPUW.js → chunk-CAXMQJJ3.js} +17 -24
  22. package/dist/chunk-CAXMQJJ3.js.map +1 -0
  23. package/dist/{chunk-UV6UWGEO.js → chunk-D736QUGF.js} +6 -5
  24. package/dist/chunk-D736QUGF.js.map +1 -0
  25. package/dist/chunk-EWJP3YYP.js +21 -0
  26. package/dist/chunk-EWJP3YYP.js.map +1 -0
  27. package/dist/{chunk-TGG26XMK.js → chunk-FV3Z5MBE.js} +10 -5
  28. package/dist/chunk-FV3Z5MBE.js.map +1 -0
  29. package/dist/chunk-G5E74IJB.js +8 -0
  30. package/dist/chunk-G5E74IJB.js.map +1 -0
  31. package/dist/{chunk-27N2SPTN.js → chunk-IXBKFQH5.js} +12 -11
  32. package/dist/chunk-IXBKFQH5.js.map +1 -0
  33. package/dist/{chunk-SQTCS44W.js → chunk-JFFVBEDI.js} +3 -3
  34. package/dist/{chunk-SQTCS44W.js.map → chunk-JFFVBEDI.js.map} +1 -1
  35. package/dist/chunk-LYLDCIPH.js +365 -0
  36. package/dist/chunk-LYLDCIPH.js.map +1 -0
  37. package/dist/{chunk-HJO6VNQI.js → chunk-MU6MCIAC.js} +3 -3
  38. package/dist/{chunk-HJO6VNQI.js.map → chunk-MU6MCIAC.js.map} +1 -1
  39. package/dist/{chunk-UYWUVEP6.js → chunk-MUUROGIH.js} +2 -2
  40. package/dist/chunk-MUUROGIH.js.map +1 -0
  41. package/dist/{chunk-EHIX7NYZ.js → chunk-MVY5DAMF.js} +4 -4
  42. package/dist/{chunk-EHIX7NYZ.js.map → chunk-MVY5DAMF.js.map} +1 -1
  43. package/dist/{chunk-LP7VQBRG.js → chunk-NPERUUUE.js} +76 -95
  44. package/dist/chunk-NPERUUUE.js.map +1 -0
  45. package/dist/{chunk-QLA76GIT.js → chunk-PBDYW2TU.js} +68 -9
  46. package/dist/chunk-PBDYW2TU.js.map +1 -0
  47. package/dist/{chunk-5VNWZADP.js → chunk-Q2UM7BXU.js} +18 -7
  48. package/dist/chunk-Q2UM7BXU.js.map +1 -0
  49. package/dist/chunk-RMX4EOQK.js +26 -0
  50. package/dist/chunk-RMX4EOQK.js.map +1 -0
  51. package/dist/{chunk-2YOE5PIS.js → chunk-S2EGRPCM.js} +8 -6
  52. package/dist/chunk-S2EGRPCM.js.map +1 -0
  53. package/dist/{chunk-ON24RKSE.js → chunk-S4O26D7B.js} +7 -14
  54. package/dist/chunk-S4O26D7B.js.map +1 -0
  55. package/dist/{chunk-3XJWC7VW.js → chunk-SK5JGUY7.js} +3 -3
  56. package/dist/{chunk-3XJWC7VW.js.map → chunk-SK5JGUY7.js.map} +1 -1
  57. package/dist/{chunk-5DEQ5I3U.js → chunk-TPGASTFF.js} +8 -10
  58. package/dist/chunk-TPGASTFF.js.map +1 -0
  59. package/dist/{chunk-SC3FAFZN.js → chunk-UF4MZSLT.js} +2 -2
  60. package/dist/chunk-UF4MZSLT.js.map +1 -0
  61. package/dist/{chunk-PS23H6KQ.js → chunk-VBUCHVCV.js} +6 -5
  62. package/dist/chunk-VBUCHVCV.js.map +1 -0
  63. package/dist/{chunk-S3FQN4SL.js → chunk-WGGAMW7Y.js} +191 -178
  64. package/dist/chunk-WGGAMW7Y.js.map +1 -0
  65. package/dist/chunk-ZJ5AOYBH.js +8 -0
  66. package/dist/chunk-ZJ5AOYBH.js.map +1 -0
  67. package/dist/{chunk-LEC4U6CX.js → chunk-ZVJZ72HY.js} +3 -3
  68. package/dist/{chunk-LEC4U6CX.js.map → chunk-ZVJZ72HY.js.map} +1 -1
  69. package/dist/circuit-breaker/index.d.ts +1 -0
  70. package/dist/circuit-breaker/index.js +1 -1
  71. package/dist/{core-BoB6t7dB.d.ts → core-42kapW0n.d.ts} +105 -6
  72. package/dist/deadline/index.d.ts +77 -11
  73. package/dist/deadline/index.js +3 -3
  74. package/dist/devtools/index.js +8 -28
  75. package/dist/devtools/index.js.map +1 -1
  76. package/dist/do/index.d.ts +483 -339
  77. package/dist/do/index.js +244 -214
  78. package/dist/do/index.js.map +1 -1
  79. package/dist/{durable-effects-CO9Uh971.d.ts → durable-effects-CFRngTNA.d.ts} +3 -3
  80. package/dist/extension/index.d.ts +25 -7
  81. package/dist/extension/index.js +4 -3
  82. package/dist/extension/index.js.map +1 -1
  83. package/dist/extension/react.js +4 -3
  84. package/dist/extension/react.js.map +1 -1
  85. package/dist/extension/subs/index.d.ts +2 -2
  86. package/dist/extension/subs/index.js +7 -10
  87. package/dist/extension/subs/index.js.map +1 -1
  88. package/dist/fan-out/index.d.ts +10 -10
  89. package/dist/fan-out/index.js +3 -3
  90. package/dist/idempotent-intake/index.d.ts +2 -2
  91. package/dist/idempotent-intake/index.js +3 -3
  92. package/dist/index.d.ts +50 -472
  93. package/dist/index.js +2 -2
  94. package/dist/llm-call/index.d.ts +3 -2
  95. package/dist/llm-call/index.js +12 -10
  96. package/dist/machine-B_BF4jij.d.ts +804 -0
  97. package/dist/machine-viz/index.d.ts +1 -1
  98. package/dist/machine-viz/index.js +2 -2
  99. package/dist/mem/index.d.ts +3 -2
  100. package/dist/mem/index.js.map +1 -1
  101. package/dist/monitored-run/index.d.ts +54 -30
  102. package/dist/monitored-run/index.js +7 -7
  103. package/dist/node/index.d.ts +3 -2
  104. package/dist/node/index.js +2 -3
  105. package/dist/node/index.js.map +1 -1
  106. package/dist/paginated-walk/index.d.ts +2 -2
  107. package/dist/paginated-walk/index.js +11 -10
  108. package/dist/parity/index.d.ts +6 -5
  109. package/dist/parity/index.js +5 -4
  110. package/dist/parity/index.js.map +1 -1
  111. package/dist/pbt/arbitraries/index.d.ts +1 -1
  112. package/dist/pbt/index.d.ts +1 -1
  113. package/dist/pbt/index.js +3 -3
  114. package/dist/pbt/index.js.map +1 -1
  115. package/dist/pbt/runners/index.d.ts +1 -1
  116. package/dist/pbt/runners/index.js +3 -3
  117. package/dist/poller/index.d.ts +59 -17
  118. package/dist/poller/index.js +56 -20
  119. package/dist/poller/index.js.map +1 -1
  120. package/dist/prediction/index.d.ts +1 -1
  121. package/dist/prediction/index.js +2 -2
  122. package/dist/pure/index.d.ts +1 -1
  123. package/dist/pure/index.js +2 -2
  124. package/dist/rate-limit/index.d.ts +2 -2
  125. package/dist/rate-limit/index.js +1 -1
  126. package/dist/react/index.d.ts +3 -2
  127. package/dist/react/index.js +2 -2
  128. package/dist/react/index.js.map +1 -1
  129. package/dist/reconciler/index.d.ts +2 -2
  130. package/dist/reconciler/index.js +13 -15
  131. package/dist/reconciler/index.js.map +1 -1
  132. package/dist/recorder/index.d.ts +20 -20
  133. package/dist/recorder/index.js +1 -1
  134. package/dist/resilient-call/index.d.ts +31 -6
  135. package/dist/resilient-call/index.js +10 -9
  136. package/dist/retry-backoff/index.d.ts +191 -14
  137. package/dist/retry-backoff/index.js +1 -1
  138. package/dist/retry-to-success/index.js +1 -1
  139. package/dist/runtime-types-gsog27b6.d.ts +337 -0
  140. package/dist/saga/index.d.ts +3 -2
  141. package/dist/saga/index.js +2 -2
  142. package/dist/saga/index.js.map +1 -1
  143. package/dist/snapshot/index.d.ts +1 -1
  144. package/dist/snapshot/index.js +3 -3
  145. package/dist/subs/index.d.ts +372 -4
  146. package/dist/subs/index.js +4 -1
  147. package/dist/testing/index.d.ts +2 -2
  148. package/dist/testing/index.js +2 -2
  149. package/dist/throttled-input/index.d.ts +2 -2
  150. package/dist/throttled-input/index.js +14 -13
  151. package/dist/throttled-input/index.js.map +1 -1
  152. package/dist/token-refresh/index.d.ts +1 -1
  153. package/dist/token-refresh/index.js +3 -3
  154. package/dist/trace-replay/index.d.ts +12 -7
  155. package/dist/trace-replay/index.js +4 -3
  156. package/dist/{types-B-8bcAp8.d.ts → types-KbL3W1mj.d.ts} +1 -1
  157. package/dist/with-deadline/index.d.ts +1 -1
  158. package/dist/with-deadline/index.js +2 -2
  159. package/dist/with-resilience/index.d.ts +21 -2
  160. package/dist/with-resilience/index.js +12 -23
  161. package/dist/with-resilience/index.js.map +1 -1
  162. package/dist/with-telemetry/index.d.ts +1 -1
  163. package/dist/with-telemetry/index.js +2 -2
  164. package/dist/work-queue/adapter.d.ts +2 -2
  165. package/dist/work-queue/adapter.js +2 -2
  166. package/dist/work-queue/index.d.ts +3 -2
  167. package/dist/work-queue/index.js +1 -1
  168. package/dist/work-queue/index.js.map +1 -1
  169. package/dist/work-queue/ops.d.ts +2 -2
  170. package/dist/work-queue/ops.js +1 -1
  171. package/dist/workflow/index.d.ts +51 -19
  172. package/dist/workflow/index.js +71 -52
  173. package/dist/workflow/index.js.map +1 -1
  174. package/package.json +4 -19
  175. package/dist/chunk-27N2SPTN.js.map +0 -1
  176. package/dist/chunk-2YOE5PIS.js.map +0 -1
  177. package/dist/chunk-3545BOYL.js.map +0 -1
  178. package/dist/chunk-5DEQ5I3U.js.map +0 -1
  179. package/dist/chunk-5VNWZADP.js.map +0 -1
  180. package/dist/chunk-6RGBKODV.js +0 -268
  181. package/dist/chunk-6RGBKODV.js.map +0 -1
  182. package/dist/chunk-7W4LMPUW.js.map +0 -1
  183. package/dist/chunk-DILMKOZ7.js +0 -91
  184. package/dist/chunk-DILMKOZ7.js.map +0 -1
  185. package/dist/chunk-K7Q23EQ4.js +0 -20
  186. package/dist/chunk-K7Q23EQ4.js.map +0 -1
  187. package/dist/chunk-LP7VQBRG.js.map +0 -1
  188. package/dist/chunk-MMH7CW5K.js.map +0 -1
  189. package/dist/chunk-NSDFA6M6.js +0 -198
  190. package/dist/chunk-NSDFA6M6.js.map +0 -1
  191. package/dist/chunk-ON24RKSE.js.map +0 -1
  192. package/dist/chunk-PS23H6KQ.js.map +0 -1
  193. package/dist/chunk-QLA76GIT.js.map +0 -1
  194. package/dist/chunk-S3FQN4SL.js.map +0 -1
  195. package/dist/chunk-SC3FAFZN.js.map +0 -1
  196. package/dist/chunk-TGG26XMK.js.map +0 -1
  197. package/dist/chunk-UV6UWGEO.js.map +0 -1
  198. package/dist/chunk-UYWUVEP6.js.map +0 -1
  199. package/dist/chunk-VLGARN6H.js +0 -202
  200. package/dist/chunk-VLGARN6H.js.map +0 -1
  201. package/dist/raft/demo.d.ts +0 -105
  202. package/dist/raft/demo.js +0 -172
  203. package/dist/raft/demo.js.map +0 -1
  204. package/dist/raft/index.d.ts +0 -548
  205. package/dist/raft/index.js +0 -7
  206. package/dist/raft/index.js.map +0 -1
  207. package/dist/raft/sim.d.ts +0 -222
  208. package/dist/raft/sim.js +0 -8
  209. package/dist/raft/sim.js.map +0 -1
  210. package/dist/raft/timeline.d.ts +0 -46
  211. package/dist/raft/timeline.js +0 -62
  212. package/dist/raft/timeline.js.map +0 -1
package/dist/do/index.js CHANGED
@@ -1,25 +1,27 @@
1
- import { status, agentBootMsg, agentEvents } from '../chunk-S3FQN4SL.js';
2
- import '../chunk-7W4LMPUW.js';
3
- import '../chunk-PS23H6KQ.js';
4
- export { applyEffectEvent, emptyLedger, foldLedger, isOwed, pendingEffectsLedger, survivingEffects } from '../chunk-3545BOYL.js';
5
- import '../chunk-EHIX7NYZ.js';
6
- import '../chunk-27N2SPTN.js';
1
+ import { status, agentBootMsg, agentEvents } from '../chunk-WGGAMW7Y.js';
2
+ export { applyEffectEvent, emptyLedger, foldLedger, isOwed, pendingEffectsLedger, survivingEffects } from '../chunk-25LBDCBC.js';
3
+ import '../chunk-CAXMQJJ3.js';
4
+ import '../chunk-VBUCHVCV.js';
5
+ import '../chunk-MVY5DAMF.js';
6
+ import '../chunk-IXBKFQH5.js';
7
7
  import '../chunk-JELSZN25.js';
8
- import '../chunk-UV6UWGEO.js';
9
- import { createIntake } from '../chunk-LEC4U6CX.js';
10
- import '../chunk-K7Q23EQ4.js';
11
- import { defaultRetryPolicy, initRetry, recordFailure, shouldRetry, nextDelayMs } from '../chunk-5VNWZADP.js';
12
- import '../chunk-2YOE5PIS.js';
8
+ import '../chunk-D736QUGF.js';
9
+ import { createIntake } from '../chunk-ZVJZ72HY.js';
10
+ import '../chunk-RMX4EOQK.js';
11
+ import { defaultRetryPolicy, initRetry, recordFailure, shouldRetry, nextDelayMs } from '../chunk-Q2UM7BXU.js';
12
+ import '../chunk-S2EGRPCM.js';
13
13
  import '../chunk-BYQUGDD3.js';
14
14
  import '../chunk-K575PT4S.js';
15
- import '../chunk-SC3FAFZN.js';
16
- import '../chunk-IN33Q4VJ.js';
17
- import '../chunk-HJO6VNQI.js';
18
- import '../chunk-TGG26XMK.js';
19
- import '../chunk-NSDFA6M6.js';
15
+ import '../chunk-UF4MZSLT.js';
16
+ import '../chunk-2KNLKQVN.js';
17
+ import '../chunk-MU6MCIAC.js';
18
+ import '../chunk-FV3Z5MBE.js';
19
+ import '../chunk-LYLDCIPH.js';
20
20
  import '../chunk-2YFLOCWX.js';
21
- import { run, replay } from '../chunk-MMH7CW5K.js';
22
- import '../chunk-QLA76GIT.js';
21
+ import '../chunk-ZJ5AOYBH.js';
22
+ import '../chunk-G5E74IJB.js';
23
+ import { replay, run } from '../chunk-BP2R7TPP.js';
24
+ import '../chunk-PBDYW2TU.js';
23
25
 
24
26
  // src/do/durable-timer.ts
25
27
  function durableTimer(config) {
@@ -69,6 +71,10 @@ function doEventSourcedStore(storage, machine, ctx, opts = {}) {
69
71
  const meta = JSON.parse(raw);
70
72
  return typeof meta.lastSeq === "number" ? meta.lastSeq : 0;
71
73
  }
74
+ async function ensureLastSeq() {
75
+ if (lastSeq === null) lastSeq = await readMeta();
76
+ return lastSeq;
77
+ }
72
78
  async function readSnapshot() {
73
79
  const raw = await storage.get(snapshotKey);
74
80
  if (raw === void 0 || raw === null) return { state: null, seq: 0 };
@@ -126,8 +132,7 @@ function doEventSourcedStore(storage, machine, ctx, opts = {}) {
126
132
  snapshotSeq = seq;
127
133
  }
128
134
  async function append(msg) {
129
- if (lastSeq === null) lastSeq = await readMeta();
130
- const seq = lastSeq + 1;
135
+ const seq = await ensureLastSeq() + 1;
131
136
  lastSeq = seq;
132
137
  await storage.put(eventKey(eventPrefix, seq), JSON.stringify(msg));
133
138
  await storage.put(
@@ -139,95 +144,15 @@ function doEventSourcedStore(storage, machine, ctx, opts = {}) {
139
144
  }
140
145
  }
141
146
  async function snapshotNow() {
142
- if (lastSeq === null) lastSeq = await readMeta();
143
- if (latestState === null || lastSeq <= snapshotSeq) return false;
144
- await writeSnapshot(lastSeq, latestState);
147
+ const seq = await ensureLastSeq();
148
+ if (latestState === null || seq <= snapshotSeq) return false;
149
+ await writeSnapshot(seq, latestState);
145
150
  return true;
146
151
  }
147
152
  return { store, append, snapshotNow, readEvents };
148
153
  }
149
154
 
150
- // src/do/host.ts
151
- function deferredGateway() {
152
- const pending = /* @__PURE__ */ new Map();
153
- return {
154
- await(callId, send, deadlineMs) {
155
- const existing = pending.get(callId);
156
- if (existing !== void 0) return existing.promise;
157
- let resolve;
158
- let reject;
159
- const promise = new Promise((res, rej) => {
160
- resolve = res;
161
- reject = rej;
162
- });
163
- const timer = setTimeout(() => {
164
- if (pending.delete(callId)) {
165
- reject(new Error(`deadline_exceeded after ${deadlineMs}ms`));
166
- }
167
- }, deadlineMs);
168
- pending.set(callId, {
169
- resolve: (v) => {
170
- clearTimeout(timer);
171
- resolve(v);
172
- },
173
- reject: (e) => {
174
- clearTimeout(timer);
175
- reject(e);
176
- },
177
- promise
178
- });
179
- send();
180
- return promise;
181
- },
182
- settle(callId, result) {
183
- const entry = pending.get(callId);
184
- if (entry === void 0) return;
185
- pending.delete(callId);
186
- entry.resolve(result);
187
- },
188
- fail(callId, reason) {
189
- const entry = pending.get(callId);
190
- if (entry === void 0) return;
191
- pending.delete(callId);
192
- entry.reject(new Error(reason));
193
- },
194
- inFlight() {
195
- return [...pending.keys()];
196
- }
197
- };
198
- }
199
- function durableDeferredGateway(inner, recorder, hooks) {
200
- const idByCallId = /* @__PURE__ */ new Map();
201
- return {
202
- recorder,
203
- await(callId, send, deadlineMs) {
204
- if (!idByCallId.has(callId)) {
205
- const { id, event } = recorder.owe({ callId });
206
- idByCallId.set(callId, id);
207
- hooks.recordOwed(callId, event);
208
- }
209
- return inner.await(callId, send, deadlineMs);
210
- },
211
- settle(callId, result) {
212
- confirm(callId);
213
- inner.settle(callId, result);
214
- },
215
- fail(callId, reason) {
216
- confirm(callId);
217
- inner.fail(callId, reason);
218
- },
219
- inFlight() {
220
- return inner.inFlight();
221
- }
222
- };
223
- function confirm(callId) {
224
- const id = idByCallId.get(callId);
225
- if (id === void 0) return;
226
- idByCallId.delete(callId);
227
- const { event } = recorder.confirm(id);
228
- hooks.recordConfirmed(callId, event);
229
- }
230
- }
155
+ // src/do/resume.ts
231
156
  async function bootResume(booting, port, now = Date.now) {
232
157
  const runtime = await booting.ready;
233
158
  if (port.isResumable(runtime.getState())) {
@@ -244,44 +169,6 @@ async function autoBoot(booting, now = Date.now) {
244
169
  now
245
170
  );
246
171
  }
247
- function acceptCommandSocket(clients, onFrame) {
248
- const pair = new WebSocketPair();
249
- const [client, server] = [pair[0], pair[1]];
250
- server.accept();
251
- clients.add(server);
252
- server.addEventListener("message", (ev) => {
253
- if (typeof ev.data === "string") onFrame(ev.data);
254
- });
255
- server.addEventListener("close", () => clients.delete(server));
256
- return new Response(null, { status: 101, webSocket: client });
257
- }
258
- function broadcast(clients, frame) {
259
- const json = JSON.stringify(frame);
260
- for (const ws of clients) {
261
- try {
262
- ws.send(json);
263
- } catch {
264
- }
265
- }
266
- }
267
- function acceptDurableCommandSocket(ctx) {
268
- const pair = new WebSocketPair();
269
- const [client, server] = [pair[0], pair[1]];
270
- ctx.acceptWebSocket(server);
271
- return new Response(null, { status: 101, webSocket: client });
272
- }
273
- function broadcastHibernatable(ctx, frame) {
274
- const json = JSON.stringify(frame);
275
- for (const ws of ctx.getWebSockets()) {
276
- try {
277
- ws.send(json);
278
- } catch {
279
- }
280
- }
281
- }
282
- function durableCommandCarrier(inner, recorder, hooks) {
283
- return durableDeferredGateway(inner, recorder, hooks);
284
- }
285
172
  function reissueSurvivingEffects(carrier, reissue) {
286
173
  const reemitted = [];
287
174
  for (const { effect } of carrier.recorder.surviving()) {
@@ -290,6 +177,8 @@ function reissueSurvivingEffects(carrier, reissue) {
290
177
  }
291
178
  return reemitted;
292
179
  }
180
+
181
+ // src/do/sse.ts
293
182
  function sseHub() {
294
183
  const sinks = /* @__PURE__ */ new Set();
295
184
  const encoder = new TextEncoder();
@@ -361,13 +250,14 @@ function sseFromAgentEvents(runtime, hub, toFrame) {
361
250
  for (const off of offs) off();
362
251
  };
363
252
  }
253
+
254
+ // src/do/agent-host.ts
364
255
  function createAgentHost(config) {
365
256
  const sse = sseHub();
366
257
  const now = config.now ?? Date.now;
367
258
  const isTerminal = config.terminal ?? ((s) => s.run.phase === "done" || s.run.phase === "failed");
368
259
  let cached = null;
369
- async function runtime() {
370
- if (cached !== null) return cached;
260
+ async function build() {
371
261
  const booting = run(config.buildMachine(), {
372
262
  ctx: config.ctx,
373
263
  store: config.store,
@@ -376,7 +266,15 @@ function createAgentHost(config) {
376
266
  });
377
267
  sseFromAgentEvents(booting, sse, config.toSseFrame);
378
268
  await autoBoot(booting, now);
379
- cached = await booting.ready;
269
+ return booting.ready;
270
+ }
271
+ function runtime() {
272
+ if (cached !== null) return cached;
273
+ const building = build();
274
+ cached = building;
275
+ building.catch(() => {
276
+ if (cached === building) cached = null;
277
+ });
380
278
  return cached;
381
279
  }
382
280
  return {
@@ -390,11 +288,171 @@ function createAgentHost(config) {
390
288
  sse,
391
289
  async reset() {
392
290
  if (cached === null) return;
393
- await cached.stop();
291
+ const built = await cached.catch(() => null);
394
292
  cached = null;
293
+ await built?.stop();
294
+ }
295
+ };
296
+ }
297
+
298
+ // src/do/presence.ts
299
+ var WS_READY_STATE_OPEN = 1;
300
+ function broadcastFrame(sockets, frame, options) {
301
+ const serialize = options?.serialize ?? JSON.stringify;
302
+ const except = options?.except;
303
+ const json = serialize(frame);
304
+ let sent = 0;
305
+ let skipped = 0;
306
+ for (const ws of sockets) {
307
+ if (except !== void 0 && ws === except) {
308
+ skipped++;
309
+ continue;
310
+ }
311
+ if (ws.readyState !== void 0 && ws.readyState !== WS_READY_STATE_OPEN) {
312
+ skipped++;
313
+ continue;
314
+ }
315
+ try {
316
+ ws.send(json);
317
+ sent++;
318
+ } catch {
319
+ skipped++;
320
+ }
321
+ }
322
+ return { sent, skipped };
323
+ }
324
+ function registerHibernatableSocket(ctx, server, options) {
325
+ ctx.acceptWebSocket(
326
+ server,
327
+ options?.tags === void 0 ? void 0 : [...options.tags]
328
+ );
329
+ if (options?.attachment !== void 0) {
330
+ server.serializeAttachment(options.attachment);
331
+ }
332
+ }
333
+ function acceptPresenceSocket(ctx, options) {
334
+ const pair = new WebSocketPair();
335
+ const client = pair[0];
336
+ const server = pair[1];
337
+ registerHibernatableSocket(ctx, server, options);
338
+ return {
339
+ server,
340
+ response: new Response(null, { status: 101, webSocket: client })
341
+ };
342
+ }
343
+ function presenceCount(ctx, tag) {
344
+ return ctx.getWebSockets(tag).length;
345
+ }
346
+
347
+ // src/do/command-socket.ts
348
+ function acceptCommandSocket(clients, onFrame) {
349
+ const pair = new WebSocketPair();
350
+ const [client, server] = [pair[0], pair[1]];
351
+ server.accept();
352
+ clients.add(server);
353
+ server.addEventListener("message", (ev) => {
354
+ if (typeof ev.data === "string") onFrame(ev.data);
355
+ });
356
+ server.addEventListener("close", () => clients.delete(server));
357
+ return new Response(null, { status: 101, webSocket: client });
358
+ }
359
+ function broadcast(clients, frame) {
360
+ broadcastFrame(clients, frame);
361
+ }
362
+ function acceptDurableCommandSocket(ctx) {
363
+ const pair = new WebSocketPair();
364
+ const [client, server] = [pair[0], pair[1]];
365
+ ctx.acceptWebSocket(server);
366
+ return new Response(null, { status: 101, webSocket: client });
367
+ }
368
+ function broadcastHibernatable(ctx, frame) {
369
+ broadcastFrame(ctx.getWebSockets(), frame);
370
+ }
371
+
372
+ // src/do/deferred-gateway.ts
373
+ function deferredGateway() {
374
+ const pending = /* @__PURE__ */ new Map();
375
+ return {
376
+ await(callId, send, deadlineMs) {
377
+ const existing = pending.get(callId);
378
+ if (existing !== void 0) return existing.promise;
379
+ let resolve;
380
+ let reject;
381
+ const promise = new Promise((res, rej) => {
382
+ resolve = res;
383
+ reject = rej;
384
+ });
385
+ const timer = setTimeout(() => {
386
+ if (pending.delete(callId)) {
387
+ reject(new Error(`deadline_exceeded after ${deadlineMs}ms`));
388
+ }
389
+ }, deadlineMs);
390
+ pending.set(callId, {
391
+ resolve: (v) => {
392
+ clearTimeout(timer);
393
+ resolve(v);
394
+ },
395
+ reject: (e) => {
396
+ clearTimeout(timer);
397
+ reject(e);
398
+ },
399
+ promise
400
+ });
401
+ send();
402
+ return promise;
403
+ },
404
+ settle(callId, result) {
405
+ const entry = pending.get(callId);
406
+ if (entry === void 0) return;
407
+ pending.delete(callId);
408
+ entry.resolve(result);
409
+ },
410
+ fail(callId, reason) {
411
+ const entry = pending.get(callId);
412
+ if (entry === void 0) return;
413
+ pending.delete(callId);
414
+ entry.reject(new Error(reason));
415
+ },
416
+ inFlight() {
417
+ return [...pending.keys()];
395
418
  }
396
419
  };
397
420
  }
421
+ function durableDeferredGateway(inner, recorder, hooks) {
422
+ const idByCallId = /* @__PURE__ */ new Map();
423
+ return {
424
+ recorder,
425
+ await(callId, send, deadlineMs) {
426
+ if (!idByCallId.has(callId)) {
427
+ const { id, event } = recorder.owe({ callId });
428
+ idByCallId.set(callId, id);
429
+ hooks.recordOwed(callId, event);
430
+ }
431
+ return inner.await(callId, send, deadlineMs);
432
+ },
433
+ settle(callId, result) {
434
+ confirm(callId);
435
+ inner.settle(callId, result);
436
+ },
437
+ fail(callId, reason) {
438
+ confirm(callId);
439
+ inner.fail(callId, reason);
440
+ },
441
+ inFlight() {
442
+ return inner.inFlight();
443
+ }
444
+ };
445
+ function confirm(callId) {
446
+ const id = idByCallId.get(callId);
447
+ if (id === void 0) return;
448
+ idByCallId.delete(callId);
449
+ const { event } = recorder.confirm(id);
450
+ hooks.recordConfirmed(callId, event);
451
+ }
452
+ }
453
+ function durableCommandCarrier(inner, recorder, hooks) {
454
+ return durableDeferredGateway(inner, recorder, hooks);
455
+ }
398
456
 
399
457
  // src/do/idempotent-effect.ts
400
458
  function emptyApplied() {
@@ -453,55 +511,6 @@ function appliedEffects(restore) {
453
511
  };
454
512
  }
455
513
 
456
- // src/do/presence.ts
457
- var WS_READY_STATE_OPEN = 1;
458
- function broadcastFrame(sockets, frame, options) {
459
- const serialize = options?.serialize ?? JSON.stringify;
460
- const except = options?.except;
461
- const json = serialize(frame);
462
- let sent = 0;
463
- let skipped = 0;
464
- for (const ws of sockets) {
465
- if (except !== void 0 && ws === except) {
466
- skipped++;
467
- continue;
468
- }
469
- if (ws.readyState !== void 0 && ws.readyState !== WS_READY_STATE_OPEN) {
470
- skipped++;
471
- continue;
472
- }
473
- try {
474
- ws.send(json);
475
- sent++;
476
- } catch {
477
- skipped++;
478
- }
479
- }
480
- return { sent, skipped };
481
- }
482
- function registerHibernatableSocket(ctx, server, options) {
483
- ctx.acceptWebSocket(
484
- server,
485
- options?.tags === void 0 ? void 0 : [...options.tags]
486
- );
487
- if (options?.attachment !== void 0) {
488
- server.serializeAttachment(options.attachment);
489
- }
490
- }
491
- function acceptPresenceSocket(ctx, options) {
492
- const pair = new WebSocketPair();
493
- const client = pair[0];
494
- const server = pair[1];
495
- registerHibernatableSocket(ctx, server, options);
496
- return {
497
- server,
498
- response: new Response(null, { status: 101, webSocket: client })
499
- };
500
- }
501
- function presenceCount(ctx, tag) {
502
- return ctx.getWebSockets(tag).length;
503
- }
504
-
505
514
  // src/do/projection.ts
506
515
  function projectionIdString(id) {
507
516
  return `${id.name}-${id.key}`;
@@ -527,7 +536,7 @@ function runProjection(projection, startOffset = 0) {
527
536
  }
528
537
  };
529
538
  }
530
- function projectionRegistry() {
539
+ function projectionRegistry(onError) {
531
540
  const runners = /* @__PURE__ */ new Set();
532
541
  let counter = -1;
533
542
  return {
@@ -542,7 +551,8 @@ function projectionRegistry() {
542
551
  for (const runner of runners) {
543
552
  try {
544
553
  runner.present(update);
545
- } catch {
554
+ } catch (err) {
555
+ onError?.(err, { id: runner.id });
546
556
  }
547
557
  }
548
558
  return offset;
@@ -593,8 +603,12 @@ function constantTimeEqual(a, b) {
593
603
  return diff === 0 && lengthMatches;
594
604
  }
595
605
  var DEFAULT_GIVE_UP_MS = 5 * 6e4;
606
+ function workingBody(retryAfterMs) {
607
+ return retryAfterMs === void 0 ? { done: false, working: true } : { done: false, working: true, retryAfterMs };
608
+ }
596
609
  function stepHost(ctx, engine, config = {}) {
597
610
  const giveUpAfterMs = config.giveUpAfterMs ?? DEFAULT_GIVE_UP_MS;
611
+ const deferResume = "deferResume" in config ? config.deferResume : null;
598
612
  const intake = createIntake({
599
613
  keyOf: (posted) => posted.callId
600
614
  });
@@ -610,23 +624,31 @@ function stepHost(ctx, engine, config = {}) {
610
624
  await ctx.storage.setAlarm(now + giveUpAfterMs);
611
625
  const posted = request.posted;
612
626
  if (posted !== null) {
613
- const [nextIntake, cmds] = intake.receive(
614
- intakeState,
615
- posted,
616
- now,
617
- posted.callId
618
- );
619
- intakeState = nextIntake;
620
- for (const cmd of cmds) {
621
- if (cmd.type === "intake:process") {
622
- await engine.resume(request.runId, posted);
623
- const [completed] = intake.complete(
624
- intakeState,
625
- cmd.key,
626
- "settled",
627
- now
628
- );
629
- intakeState = completed;
627
+ if (deferResume === null) {
628
+ const [nextIntake, cmds] = intake.receive(
629
+ intakeState,
630
+ posted,
631
+ now,
632
+ posted.callId
633
+ );
634
+ intakeState = nextIntake;
635
+ for (const cmd of cmds) {
636
+ if (cmd.type === "intake:process") {
637
+ await engine.resume(request.runId, posted);
638
+ const [completed] = intake.complete(
639
+ intakeState,
640
+ cmd.key,
641
+ "settled",
642
+ now
643
+ );
644
+ intakeState = completed;
645
+ }
646
+ }
647
+ } else {
648
+ const ready = await deferResume.settled(request.runId, posted.callId);
649
+ if (!ready) {
650
+ await deferResume.enqueue(request.runId, posted);
651
+ return { status: 200, body: workingBody(deferResume.retryAfterMs) };
630
652
  }
631
653
  }
632
654
  }
@@ -646,6 +668,7 @@ async function runStepLoop(token, runId, transport, execute, config) {
646
668
  const rng = config.rng;
647
669
  const executed = /* @__PURE__ */ new Map();
648
670
  let posted = null;
671
+ let pollRetry = initRetry();
649
672
  for (; ; ) {
650
673
  if (now() >= config.deadlineMs) return { kind: "deadline_exceeded" };
651
674
  let response;
@@ -662,6 +685,13 @@ async function runStepLoop(token, runId, transport, execute, config) {
662
685
  }
663
686
  }
664
687
  if (response.done) return { kind: "done", output: response.output };
688
+ if ("working" in response) {
689
+ pollRetry = recordFailure(pollRetry, "working");
690
+ if (now() >= config.deadlineMs) return { kind: "deadline_exceeded" };
691
+ await sleep(response.retryAfterMs ?? nextDelayMs(pollRetry, policy, rng));
692
+ continue;
693
+ }
694
+ pollRetry = initRetry();
665
695
  const step = response.step;
666
696
  const cached = executed.get(step.callId);
667
697
  const result = cached !== void 0 ? cached : await execute(step);