experimental-a2 0.18.0 → 0.19.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 (152) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/{actor-Bjce9_5U.d.ts → actor-C7b-1arn.d.ts} +3 -3
  3. package/dist/{actor-Bjce9_5U.d.ts.map → actor-C7b-1arn.d.ts.map} +1 -1
  4. package/dist/actor-client.d.ts +1 -1
  5. package/dist/actor-react.d.ts +1 -1
  6. package/dist/actor-react.js +1 -1
  7. package/dist/actor.d.ts +1 -1
  8. package/dist/actor.js +2 -2
  9. package/dist/{ai-DrUaMyRt.d.ts → ai-Cz3hqVhk.d.ts} +34 -17
  10. package/dist/ai-Cz3hqVhk.d.ts.map +1 -0
  11. package/dist/ai-client.d.ts +1 -1
  12. package/dist/ai-client.js +2 -2
  13. package/dist/ai-control-CvLbW10B.js +46 -0
  14. package/dist/ai-control-CvLbW10B.js.map +1 -0
  15. package/dist/ai-fx.d.ts +1 -1
  16. package/dist/ai-fx.d.ts.map +1 -1
  17. package/dist/ai-fx.js +122 -44
  18. package/dist/ai-fx.js.map +1 -1
  19. package/dist/{ai-harness-BuLh_EYi.js → ai-harness-BuuC-gJ3.js} +79 -15
  20. package/dist/ai-harness-BuuC-gJ3.js.map +1 -0
  21. package/dist/{ai-harness-DvsPeJeB.d.ts → ai-harness-CV6rXbB3.d.ts} +2 -2
  22. package/dist/ai-harness-CV6rXbB3.d.ts.map +1 -0
  23. package/dist/{ai-BpOGm-zB.js → ai-mMiWul1T.js} +117 -78
  24. package/dist/ai-mMiWul1T.js.map +1 -0
  25. package/dist/ai-pi.d.ts +1 -1
  26. package/dist/ai-pi.d.ts.map +1 -1
  27. package/dist/ai-pi.js +114 -23
  28. package/dist/ai-pi.js.map +1 -1
  29. package/dist/ai-react.d.ts +1 -1
  30. package/dist/ai-react.js +2 -2
  31. package/dist/ai-server.d.ts +3 -3
  32. package/dist/ai-server.d.ts.map +1 -1
  33. package/dist/ai-server.js +127 -55
  34. package/dist/ai-server.js.map +1 -1
  35. package/dist/ai-tool-input-DmSqMUQi.js +40 -0
  36. package/dist/ai-tool-input-DmSqMUQi.js.map +1 -0
  37. package/dist/ai.d.ts +2 -2
  38. package/dist/ai.js +1 -1
  39. package/dist/{client-BReKqwZC.js → client-BhHLoNKF.js} +3 -3
  40. package/dist/{client-BReKqwZC.js.map → client-BhHLoNKF.js.map} +1 -1
  41. package/dist/client.js +1 -1
  42. package/dist/index.d.ts +2 -2
  43. package/dist/{internal-B2T3U4Rq.js → internal-CscSY7K_.js} +4 -2
  44. package/dist/{internal-B2T3U4Rq.js.map → internal-CscSY7K_.js.map} +1 -1
  45. package/dist/react.js +1 -1
  46. package/dist/scheduler-qstash.d.ts +2 -2
  47. package/dist/scheduler-qstash.js +3 -3
  48. package/dist/scheduler-qstash.js.map +1 -1
  49. package/dist/scheduler-vercel.d.ts +7 -7
  50. package/dist/scheduler-vercel.d.ts.map +1 -1
  51. package/dist/scheduler-vercel.js +10 -14
  52. package/dist/scheduler-vercel.js.map +1 -1
  53. package/dist/{server-Dw_k_7kO.js → server-D-Y4pqwu.js} +37 -11
  54. package/dist/server-D-Y4pqwu.js.map +1 -0
  55. package/dist/{server-En7cbi3v.d.ts → server-DYAATFuT.d.ts} +11 -5
  56. package/dist/server-DYAATFuT.d.ts.map +1 -0
  57. package/dist/server.d.ts +2 -2
  58. package/dist/server.js +1 -1
  59. package/dist/{session-clear-Bo-XTFEy.d.ts → session-clear-C-QwTXV1.d.ts} +2 -2
  60. package/dist/session-clear-C-QwTXV1.d.ts.map +1 -0
  61. package/dist/{store-Djdv0bnZ.d.ts → store-CyLUy86v.d.ts} +23 -4
  62. package/dist/store-CyLUy86v.d.ts.map +1 -0
  63. package/dist/store-N8PXxDAS.js.map +1 -1
  64. package/dist/store-memory.d.ts +1 -1
  65. package/dist/store-memory.js +25 -6
  66. package/dist/store-memory.js.map +1 -1
  67. package/dist/{store-polling-B5FcwJfo.js → store-polling-7WJV0YWP.js} +2 -2
  68. package/dist/{store-polling-B5FcwJfo.js.map → store-polling-7WJV0YWP.js.map} +1 -1
  69. package/dist/store-postgres.d.ts +1 -1
  70. package/dist/store-postgres.d.ts.map +1 -1
  71. package/dist/store-postgres.js +55 -25
  72. package/dist/store-postgres.js.map +1 -1
  73. package/dist/{store-presence-polling-BAwS8RWn.js → store-presence-polling-B1ixeqIS.js} +3 -3
  74. package/dist/{store-presence-polling-BAwS8RWn.js.map → store-presence-polling-B1ixeqIS.js.map} +1 -1
  75. package/dist/store-redis-http.d.ts +1 -1
  76. package/dist/store-redis-http.js +3 -3
  77. package/dist/{store-redis-notify-BRITti_o.js → store-redis-notify-CM0AfLY0.js} +88 -37
  78. package/dist/store-redis-notify-CM0AfLY0.js.map +1 -0
  79. package/dist/store-redis.d.ts +1 -1
  80. package/dist/store-redis.js +1 -1
  81. package/dist/store-sqlite.d.ts +1 -1
  82. package/dist/store-sqlite.js +35 -20
  83. package/dist/store-sqlite.js.map +1 -1
  84. package/dist/{wire-rSUglYo8.js → wire-BKxH1vbP.js} +2 -2
  85. package/dist/{wire-rSUglYo8.js.map → wire-BKxH1vbP.js.map} +1 -1
  86. package/docs/agents/03-conversations.mdx +27 -15
  87. package/docs/agents/04-harnesses.mdx +51 -5
  88. package/docs/contract/03-sessions.mdx +1 -1
  89. package/docs/index.mdx +3 -3
  90. package/docs/reference/02-server.mdx +12 -7
  91. package/docs/reference/04-ai.mdx +41 -23
  92. package/docs/reference/05-adapters.mdx +6 -6
  93. package/docs/server/01-handlers.mdx +1 -1
  94. package/docs/server/02-timers.mdx +1 -1
  95. package/docs/server/03-cancellation.mdx +3 -2
  96. package/docs/server/05-production.mdx +4 -3
  97. package/docs/server/06-guarantees.mdx +20 -11
  98. package/examples/playground/DEPLOY.md +11 -4
  99. package/examples/playground/app/a0/[appId]/page.tsx +2 -8
  100. package/examples/playground/app/a0/a0.css +244 -5
  101. package/examples/playground/app/a0/app-view.tsx +2 -1
  102. package/examples/playground/app/a0/attachments.ts +133 -0
  103. package/examples/playground/app/a0/chat.test.tsx +504 -0
  104. package/examples/playground/app/a0/chat.tsx +623 -63
  105. package/examples/playground/app/a0/context-menu.tsx +38 -11
  106. package/examples/playground/app/a0/devtools.tsx +2 -8
  107. package/examples/playground/app/a0/model.test.ts +28 -0
  108. package/examples/playground/app/a0/model.ts +30 -0
  109. package/examples/playground/app/a0/server.ts +13 -19
  110. package/examples/playground/app/a0/uploads/route.ts +29 -0
  111. package/examples/playground/app/agent/[agentId]/agent-client.tsx +2 -1
  112. package/examples/playground/app/agent/[agentId]/agent-queue.test.tsx +1 -0
  113. package/examples/playground/app/agent/model.test.ts +12 -3
  114. package/examples/playground/app/chat/[chatId]/agent-state.test.ts +1 -5
  115. package/examples/playground/next.config.ts +7 -4
  116. package/examples/playground/package.json +3 -1
  117. package/package.json +1 -1
  118. package/src/ai-agent.ts +14 -3
  119. package/src/ai-client-state.ts +21 -9
  120. package/src/ai-context-schema.ts +28 -4
  121. package/src/ai-context.ts +83 -3
  122. package/src/ai-control-server.ts +70 -43
  123. package/src/ai-control-state.ts +3 -4
  124. package/src/ai-control.ts +59 -10
  125. package/src/ai-coordinator.ts +7 -6
  126. package/src/ai-fx.ts +184 -67
  127. package/src/ai-harness.ts +153 -29
  128. package/src/ai-message-shape.ts +41 -0
  129. package/src/ai-pi.ts +161 -46
  130. package/src/ai-stored-state.ts +1 -3
  131. package/src/ai-tool-input.ts +45 -0
  132. package/src/ai.ts +116 -77
  133. package/src/internal.ts +6 -0
  134. package/src/libfx.d.ts +8 -1
  135. package/src/scheduler-qstash.ts +5 -5
  136. package/src/scheduler-vercel.ts +15 -27
  137. package/src/server.ts +58 -12
  138. package/src/store-memory.ts +50 -9
  139. package/src/store-postgres.ts +79 -28
  140. package/src/store-redis-core.ts +112 -31
  141. package/src/store-sqlite.ts +61 -28
  142. package/src/store.ts +22 -3
  143. package/dist/ai-BpOGm-zB.js.map +0 -1
  144. package/dist/ai-DrUaMyRt.d.ts.map +0 -1
  145. package/dist/ai-harness-BuLh_EYi.js.map +0 -1
  146. package/dist/ai-harness-DvsPeJeB.d.ts.map +0 -1
  147. package/dist/server-Dw_k_7kO.js.map +0 -1
  148. package/dist/server-En7cbi3v.d.ts.map +0 -1
  149. package/dist/session-clear-Bo-XTFEy.d.ts.map +0 -1
  150. package/dist/store-Djdv0bnZ.d.ts.map +0 -1
  151. package/dist/store-redis-notify-BRITti_o.js.map +0 -1
  152. package/examples/playground/app/a0/no-photon.cjs +0 -4
package/dist/ai-fx.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { t as boundedCache } from "./bounded-cache-CPHWF-8h.js";
2
- import { c as pending, d as saveHarness, i as gatewayCredential, l as readHarness, n as deferred, r as defineHarness, t as Divergence } from "./ai-harness-BuLh_EYi.js";
2
+ import { f as saveHarness, i as gatewayCredential, l as pending, n as deferred, o as harnessImages, r as defineHarness, t as Divergence, u as readHarness } from "./ai-harness-BuuC-gJ3.js";
3
+ import { t as schemaInput } from "./ai-tool-input-DmSqMUQi.js";
3
4
  import { asSchema } from "ai";
4
5
  //#region src/ai-fx.ts
5
6
  /**
@@ -18,6 +19,8 @@ function fx() {
18
19
  }
19
20
  const SNAPSHOT_VERSION = 1;
20
21
  const CATALOG_TTL_MS = 36e5;
22
+ /** The Gateway model catalog libfx reads for each new kernel. */
23
+ const CATALOG_PATH = "/coding-agent/v1/models";
21
24
  function fail(state, error) {
22
25
  state.failure ??= error;
23
26
  state.fxTurn.cancel();
@@ -36,6 +39,8 @@ async function runStep(step) {
36
39
  let read = first;
37
40
  let completion = {};
38
41
  let stopped = false;
42
+ const released = new AbortController();
43
+ const network = AbortSignal.any([step.signal, released.signal]);
39
44
  let agent;
40
45
  let turn;
41
46
  const run = async (controller, turns) => {
@@ -108,7 +113,9 @@ async function runStep(step) {
108
113
  };
109
114
  const hostFetch = async (input, init = {}) => {
110
115
  const url = input instanceof Request ? input.url : String(input);
111
- if ((init.method ?? "GET").toUpperCase() === "GET") return catalog(url, credential, withAuth(init.headers, credential));
116
+ const method = (init.method ?? "GET").toUpperCase();
117
+ if (method === "GET" && new URL(url).pathname === CATALOG_PATH) return catalog(url, credential, withAuth(init.headers, credential));
118
+ if (method === "GET") return fetch(input, init);
112
119
  const state = turn;
113
120
  if (state.failure) throw state.failure;
114
121
  const compaction = isCompaction(decodeBody(init.body));
@@ -141,10 +148,16 @@ async function runStep(step) {
141
148
  const live = async (state, url, init, compaction) => {
142
149
  const response = await fetch(url, {
143
150
  ...init,
144
- headers: withAuth(init.headers, credential)
151
+ headers: withAuth(init.headers, credential),
152
+ signal: network
145
153
  });
154
+ if (init.signal?.aborted) {
155
+ response.body?.cancel();
156
+ throw init.signal.reason;
157
+ }
146
158
  if (!response.ok || response.body === null) return response;
147
- const [forKernel, forLog] = response.body.tee();
159
+ const [fromNetwork, forLog] = response.body.tee();
160
+ const forKernel = init.signal ? fromNetwork.pipeThrough(new TransformStream(), { signal: init.signal }) : fromNetwork;
148
161
  const previous = state.parsed;
149
162
  if (compaction) {
150
163
  const id = `fx-compaction:${step.requestIndex}:${compactions++}`;
@@ -162,8 +175,13 @@ async function runStep(step) {
162
175
  state.parsed = (async () => {
163
176
  await previous;
164
177
  emit({ type: "start-step" });
165
- await streamStep(forLog, emit, (finished) => {
166
- completion = finished;
178
+ await streamStep({
179
+ body: forLog,
180
+ tools: step.tools,
181
+ emit,
182
+ finished: (finished) => {
183
+ completion = finished;
184
+ }
167
185
  });
168
186
  })();
169
187
  }
@@ -194,7 +212,7 @@ async function runStep(step) {
194
212
  }
195
213
  return fail(state, diverged(`no recorded result for ${toolName}`));
196
214
  });
197
- let turns = read.turns.map(turnPlan);
215
+ const plans = (turns) => Promise.all(turns.map((recorded) => turnPlan(recorded, step.signal)));
198
216
  let results = read.results;
199
217
  let controller;
200
218
  let closed = false;
@@ -225,17 +243,17 @@ async function runStep(step) {
225
243
  } catch (error) {
226
244
  if (read.saved === void 0) throw error;
227
245
  read = await replayAll();
228
- turns = read.turns.map(turnPlan);
229
246
  results = read.results;
230
247
  agent = await create(void 0);
231
248
  }
232
- await run(streamController, turns);
249
+ await run(streamController, await plans(read.turns));
233
250
  closed = true;
234
251
  streamController.close();
235
252
  } catch (error) {
236
253
  closed = true;
237
254
  streamController.error(step.signal.aborted ? step.signal.reason : error);
238
255
  } finally {
256
+ released.abort();
239
257
  step.signal.removeEventListener("abort", abort);
240
258
  await agent?.close().catch(() => {});
241
259
  }
@@ -244,30 +262,48 @@ async function runStep(step) {
244
262
  cancel() {
245
263
  closed = true;
246
264
  stopped = true;
265
+ released.abort();
247
266
  turn?.fxTurn.cancel();
248
267
  }
249
268
  }),
250
269
  completion: () => completion
251
270
  };
252
271
  }
253
- function turnPlan(turn) {
272
+ async function turnPlan(turn, signal) {
254
273
  const calls = [];
255
274
  const steers = /* @__PURE__ */ new Map();
256
- const steer = (at, texts) => {
257
- if (texts !== void 0) steers.set(Math.max(0, at), texts);
275
+ const steer = (at, inputs) => {
276
+ if (inputs !== void 0) steers.set(Math.max(0, at), inputs.map(steerText));
258
277
  };
259
278
  steer(0, turn.generations.length === 0 ? turn.steers.get(0) : void 0);
260
279
  turn.generations.forEach((generation, index) => {
261
280
  calls.push(...recordedCalls(generation.chunks, generation.completed));
262
281
  steer(calls.length - 1, turn.steers.get(index));
263
282
  });
283
+ const images = await harnessImages({
284
+ harness: "fx()",
285
+ input: turn.prompt,
286
+ signal
287
+ });
264
288
  return {
265
- prompt: turn.prompt,
289
+ prompt: images.length === 0 ? turn.prompt.text : [...images.map((image) => ({
290
+ type: "image",
291
+ data: image.data,
292
+ mimeType: image.mediaType
293
+ })), ...turn.prompt.text === "" ? [] : [{
294
+ type: "text",
295
+ text: turn.prompt.text
296
+ }]],
266
297
  calls,
267
298
  steers,
268
299
  end: turn.end
269
300
  };
270
301
  }
302
+ /** libfx steers with text alone, so a steer's files fail the step. */
303
+ function steerText(input) {
304
+ if (input.files.length > 0) throw new Error("fx() steers with text only: send files in a message of their own");
305
+ return input.text;
306
+ }
271
307
  /** A completed generation's model calls: its compactions, then its step. */
272
308
  function recordedCalls(chunks, completed) {
273
309
  const calls = [];
@@ -321,34 +357,27 @@ function recordedCalls(chunks, completed) {
321
357
  });
322
358
  break;
323
359
  case "tool-input-error":
360
+ case "tool-input-available": {
361
+ const text = inputText.get(chunk.toolCallId) || (chunk.type === "tool-input-error" && typeof chunk.input === "string" ? chunk.input : JSON.stringify(chunk.input));
324
362
  if (inputText.has(chunk.toolCallId)) parts.push({
325
363
  type: "tool-input-end",
326
364
  id: chunk.toolCallId
327
365
  });
328
- parts.push({
329
- type: "tool-call",
366
+ const input = parseJson(text);
367
+ if (input !== void 0) toolCalls.push({
330
368
  toolCallId: chunk.toolCallId,
331
369
  toolName: chunk.toolName,
332
- input: inputText.get(chunk.toolCallId) || (typeof chunk.input === "string" ? chunk.input : JSON.stringify(chunk.input))
333
- });
334
- break;
335
- case "tool-input-available":
336
- if (inputText.has(chunk.toolCallId)) parts.push({
337
- type: "tool-input-end",
338
- id: chunk.toolCallId
339
- });
340
- toolCalls.push({
341
- toolCallId: chunk.toolCallId,
342
- toolName: chunk.toolName,
343
- input: chunk.input
370
+ input
344
371
  });
345
372
  parts.push({
346
373
  type: "tool-call",
347
374
  toolCallId: chunk.toolCallId,
348
375
  toolName: chunk.toolName,
349
- input: inputText.get(chunk.toolCallId) || JSON.stringify(chunk.input),
376
+ input: text,
350
377
  ...metadata
351
378
  });
379
+ break;
380
+ }
352
381
  }
353
382
  }
354
383
  parts.push({
@@ -386,7 +415,8 @@ function compactionSse(data) {
386
415
  ]);
387
416
  }
388
417
  /** Streams one live step response as UI chunks and reports its finish. */
389
- async function streamStep(body, emit, finished) {
418
+ async function streamStep({ body, tools, emit, finished }) {
419
+ const streamed = /* @__PURE__ */ new Map();
390
420
  for await (const part of sseParts(body)) {
391
421
  const metadata = part["providerMetadata"] === void 0 ? {} : { providerMetadata: part["providerMetadata"] };
392
422
  switch (part.type) {
@@ -410,6 +440,7 @@ async function streamStep(body, emit, finished) {
410
440
  });
411
441
  break;
412
442
  case "tool-input-start":
443
+ streamed.set(part["id"], false);
413
444
  emit({
414
445
  type: "tool-input-start",
415
446
  toolCallId: part["id"],
@@ -418,6 +449,7 @@ async function streamStep(body, emit, finished) {
418
449
  });
419
450
  break;
420
451
  case "tool-input-delta":
452
+ if (part["delta"] !== "") streamed.set(part["id"], true);
421
453
  emit({
422
454
  type: "tool-input-delta",
423
455
  toolCallId: part["id"],
@@ -425,25 +457,38 @@ async function streamStep(body, emit, finished) {
425
457
  });
426
458
  break;
427
459
  case "tool-call": {
460
+ const toolCallId = part["toolCallId"];
461
+ const toolName = part["toolName"];
428
462
  const text = part["input"];
429
- let input;
430
- try {
431
- input = JSON.parse(text);
432
- } catch (error) {
463
+ if (streamed.get(toolCallId) !== true && text !== "") {
464
+ if (!streamed.has(toolCallId)) emit({
465
+ type: "tool-input-start",
466
+ toolCallId,
467
+ toolName
468
+ });
433
469
  emit({
434
- type: "tool-input-error",
435
- toolCallId: part["toolCallId"],
436
- toolName: part["toolName"],
437
- input: text,
438
- errorText: error instanceof Error ? error.message : String(error)
470
+ type: "tool-input-delta",
471
+ toolCallId,
472
+ inputTextDelta: text
439
473
  });
440
- break;
441
474
  }
442
- emit({
475
+ const input = await parseToolInput({
476
+ tools,
477
+ toolName,
478
+ text
479
+ });
480
+ emit(input.success ? {
443
481
  type: "tool-input-available",
444
- toolCallId: part["toolCallId"],
445
- toolName: part["toolName"],
446
- input,
482
+ toolCallId,
483
+ toolName,
484
+ input: input.value,
485
+ ...metadata
486
+ } : {
487
+ type: "tool-input-error",
488
+ toolCallId,
489
+ toolName,
490
+ input: input.input,
491
+ errorText: input.errorText,
447
492
  ...metadata
448
493
  });
449
494
  break;
@@ -463,6 +508,32 @@ async function streamStep(body, emit, finished) {
463
508
  }
464
509
  }
465
510
  }
511
+ /**
512
+ * A live call's input as the AI SDK step reads it: JSON, then the tool's
513
+ * schema with its defaults. Input that fails either is an input error, which
514
+ * A2 answers without running the tool.
515
+ */
516
+ async function parseToolInput({ tools, toolName, text }) {
517
+ let value;
518
+ try {
519
+ value = JSON.parse(text);
520
+ } catch (error) {
521
+ return {
522
+ success: false,
523
+ input: text,
524
+ errorText: errorText(error)
525
+ };
526
+ }
527
+ const input = await schemaInput({
528
+ tools,
529
+ toolName,
530
+ value
531
+ });
532
+ return input.success ? input : {
533
+ ...input,
534
+ input: value
535
+ };
536
+ }
466
537
  async function readParts(body) {
467
538
  const all = [];
468
539
  for await (const part of sseParts(body)) all.push(part);
@@ -534,7 +605,7 @@ function kernelModel(step) {
534
605
  };
535
606
  }
536
607
  async function kernelTools(tools, execute) {
537
- return Promise.all(Object.entries(tools).filter(([, tool]) => tool.type !== "provider").map(async ([toolName, tool]) => ({
608
+ return Promise.all(Object.entries(tools).map(async ([toolName, tool]) => ({
538
609
  name: toolName,
539
610
  description: typeof tool.description === "string" ? tool.description : toolName,
540
611
  inputSchema: await asSchema(tool.inputSchema).jsonSchema,
@@ -581,6 +652,13 @@ function decodeBody(body) {
581
652
  if (body instanceof Uint8Array || body instanceof ArrayBuffer) return new TextDecoder().decode(body);
582
653
  throw new TypeError("FX sent an unexpected request body");
583
654
  }
655
+ function parseJson(text) {
656
+ try {
657
+ return JSON.parse(text);
658
+ } catch {
659
+ return;
660
+ }
661
+ }
584
662
  function sameJson(a, b) {
585
663
  return JSON.stringify(a) === JSON.stringify(b);
586
664
  }
package/dist/ai-fx.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ai-fx.js","names":[],"sources":["../src/ai-fx.ts"],"sourcesContent":["/**\n * experimental-a2/ai/fx — `fx()`: the FX harness for `agent({ harness })`.\n * Server-only; FX's kernel comes from the optional `libfx` peer dependency.\n */\n\n// oxlint-disable no-await-in-loop -- turns replay in order, each on the kernel the last one left.\n\nimport {\n asSchema,\n type FinishReason,\n type LanguageModelUsage,\n type ToolSet,\n type UIMessageChunk,\n} from 'ai'\nimport type { FxAgent, FxHostTool, FxTurn } from 'libfx'\nimport {\n type Deferred,\n defineHarness,\n deferred,\n Divergence,\n gatewayCredential,\n type GatewayCredential,\n type Harness,\n type HarnessGeneration,\n type HarnessRead,\n type HarnessStep,\n type HarnessTurn,\n pending,\n readHarness,\n saveHarness,\n} from './ai-harness.ts'\nimport type { CompactionPartData, GenerationCompletedPayload } from './ai.ts'\nimport { boundedCache } from './bounded-cache.ts'\n\nexport type { Harness } from './ai-harness.ts'\n\n/**\n * The FX harness. Every model call FX makes is one durable step; A2 rebuilds\n * the kernel for each step from its latest checkpoint and the log since.\n */\nexport function fx(): Harness<'fx', never> {\n return defineHarness('fx', {\n tools: {},\n step: runStep,\n })\n}\n\nconst SNAPSHOT_VERSION = 1\nconst CATALOG_TTL_MS = 60 * 60 * 1000\n\ntype StreamPart = { type: string } & Record<string, unknown>\ntype ToolCall = { toolCallId: string; toolName: string; input: unknown }\n\n/** A model response A2 recorded, in the Gateway's stream format. */\ntype RecordedCall = {\n kind: 'step' | 'compaction'\n sse: string\n toolCalls: ToolCall[]\n}\n\n/** One FX turn to replay: its prompt, recorded calls, and how it ended. */\ntype TurnPlan = {\n prompt: string\n calls: RecordedCall[]\n /** Steering to queue while serving the call at that index. */\n steers: Map<number, string[]>\n end: 'stop' | 'interrupted' | 'live'\n}\n\ntype Completion = { finishReason?: FinishReason; usage?: LanguageModelUsage }\n\n/** The turn being replayed or run live, as the fetch and tool hooks see it. */\ntype TurnState = {\n plan: TurnPlan\n fxTurn: FxTurn\n next: number\n /** Tool calls of the last served step and the ones already answered. */\n served: ToolCall[]\n answered: Set<string>\n live: boolean\n liveStep: boolean\n failure?: Error\n /** Resolves when the live step is over: FX asked for its tools. */\n toolsRequested: Deferred\n parsed?: Promise<void>\n}\n\nfunction fail(state: TurnState, error: Error): never {\n state.failure ??= error\n state.fxTurn.cancel()\n throw state.failure\n}\n\nconst diverged = (message: string): Divergence => new Divergence('FX', message)\n\n// ---------------------------------------------------------------- step\n\nasync function runStep(step: HarnessStep): Promise<HarnessGeneration> {\n const { createFxAgent } = await loadLibfx()\n const credential = gatewayCredential('fx')\n const name = `${step.agentName}.a2.harness.fx`\n const { replayAll, ...first } = await readHarness({\n step,\n name,\n parse: savedCheckpoint,\n })\n let read: HarnessRead<Uint8Array> = first\n\n let completion: Completion = {}\n let stopped = false\n let agent: FxAgent | undefined\n let turn: TurnState | undefined\n\n const run = async (\n controller: ReadableStreamDefaultController<UIMessageChunk>,\n turns: TurnPlan[],\n ): Promise<void> => {\n controller.enqueue({ type: 'start', messageId: step.responseMessageId })\n for (const plan of turns) {\n if (stopped) return\n const fxTurn = agent!.prompt(plan.prompt, { signal: step.signal })\n const state: TurnState = {\n plan,\n fxTurn,\n next: 0,\n served: [],\n answered: new Set(),\n live: false,\n liveStep: false,\n toolsRequested: deferred(),\n }\n turn = state\n const drained = (async () => {\n for await (const _ of fxTurn) {\n // Live output reaches A2 from the Gateway response itself.\n }\n })()\n // A failed turn surfaces through its result.\n drained.catch(() => {})\n if (plan.end !== 'live') {\n const result = await fxTurn.result.catch((error: unknown) => {\n throw state.failure ?? error\n })\n await drained\n if (state.failure) throw state.failure\n const expected = plan.end === 'stop' ? 'end_turn' : 'cancelled'\n if (result.stopReason !== expected)\n throw diverged(\n `a recorded turn ended with ${result.stopReason}, not ${expected}`,\n )\n continue\n }\n const outcome = await Promise.race([\n fxTurn.result.then((result) => ({ ended: true, result })),\n state.toolsRequested.promise.then(() => ({ ended: false as const })),\n ]).catch((error: unknown) => {\n throw state.failure ?? error\n })\n if (state.failure) throw state.failure\n await state.parsed\n if (outcome.ended) {\n await drained\n // Only a turn this attempt finished describes the log.\n if (outcome.result.stopReason === 'end_turn' && !step.signal.aborted)\n await saveCheckpoint()\n } else {\n // FX now waits on tools that A2's tool handlers run.\n fxTurn.cancel()\n }\n controller.enqueue({ type: 'finish-step' })\n controller.enqueue({\n type: 'finish',\n ...(completion.finishReason === undefined\n ? {}\n : { finishReason: completion.finishReason }),\n })\n }\n }\n\n const saveCheckpoint = async (): Promise<void> => {\n let checkpoint: Uint8Array\n try {\n checkpoint = await agent!.checkpoint()\n } catch {\n // Over libfx's bound: later steps replay from the previous snapshot.\n return\n }\n await saveHarness({\n step,\n name,\n state: {\n version: SNAPSHOT_VERSION,\n checkpoint: Buffer.from(checkpoint).toString('base64'),\n },\n })\n }\n\n const hostFetch = async (\n input: string | URL | Request,\n init: RequestInit = {},\n ): Promise<Response> => {\n const url = input instanceof Request ? input.url : String(input)\n if ((init.method ?? 'GET').toUpperCase() === 'GET')\n return catalog(url, credential, withAuth(init.headers, credential))\n const state = turn!\n if (state.failure) throw state.failure\n const body = decodeBody(init.body)\n const compaction = isCompaction(body)\n const recorded = state.plan.calls[state.next]\n if (recorded !== undefined) {\n if ((recorded.kind === 'compaction') !== compaction)\n fail(state, diverged(`request ${state.next} is not a ${recorded.kind}`))\n const index = state.next++\n if (recorded.kind === 'step') {\n state.served = recorded.toolCalls\n state.answered = new Set()\n }\n const steers = state.plan.steers.get(index) ?? []\n return relay(recorded.sse, async () => {\n for (const text of steers) await state.fxTurn.steer(text)\n })\n }\n if (state.plan.end === 'stop')\n fail(state, diverged('FX continued a turn the log ended'))\n if (state.plan.end === 'interrupted') {\n state.fxTurn.cancel()\n throw new DOMException('The recorded turn was interrupted', 'AbortError')\n }\n if (state.liveStep && !compaction) {\n // One generation is one step; the next step is A2's next generation.\n state.toolsRequested.resolve()\n return pending(init.signal)\n }\n state.live = true\n return live(state, url, init, compaction)\n }\n\n let compactions = 0\n const live = async (\n state: TurnState,\n url: string,\n init: RequestInit,\n compaction: boolean,\n ): Promise<Response> => {\n const response = await fetch(url, {\n ...init,\n headers: withAuth(init.headers, credential),\n })\n if (!response.ok || response.body === null) return response\n const [forKernel, forLog] = response.body.tee()\n // Live responses reach the log in request order: a compaction's part\n // precedes the step that follows it.\n const previous = state.parsed\n if (compaction) {\n // Unique across the response's generations: the transcript keys data parts by ID.\n const id = `fx-compaction:${step.requestIndex}:${compactions++}`\n state.parsed = (async () => {\n const all = await readParts(forLog)\n await previous\n emit({\n type: 'data-a2-compaction',\n id,\n data: compactionData(all),\n })\n })()\n } else {\n state.liveStep = true\n state.parsed = (async () => {\n await previous\n emit({ type: 'start-step' })\n await streamStep(forLog, emit, (finished) => {\n completion = finished\n })\n })()\n }\n // A stopped step abandons its parse; its failure surfaces through the turn.\n state.parsed.catch(() => {})\n return new Response(forKernel, {\n status: response.status,\n headers: response.headers,\n })\n }\n\n const hostTools = await kernelTools(step.tools, (toolName, toolInput) => {\n const state = turn!\n if (state.failure) throw state.failure\n const call = state.served.find(\n (candidate) =>\n candidate.toolName === toolName &&\n !state.answered.has(candidate.toolCallId) &&\n sameJson(candidate.input, toolInput),\n )\n const result = call === undefined ? undefined : results.get(call.toolCallId)\n if (call !== undefined && result !== undefined) {\n state.answered.add(call.toolCallId)\n if (result.error !== undefined) throw new Error(result.error)\n if (result.denied === true) throw new Error('The tool call was denied.')\n return result.output ?? null\n }\n if (state.live) {\n state.toolsRequested.resolve()\n return pending(undefined)\n }\n if (state.plan.end === 'interrupted') {\n state.fxTurn.cancel()\n return pending(undefined)\n }\n return fail(state, diverged(`no recorded result for ${toolName}`))\n })\n\n let turns = read.turns.map(turnPlan)\n let results = read.results\n let controller: ReadableStreamDefaultController<UIMessageChunk> | undefined\n let closed = false\n const emit = (chunk: UIMessageChunk): void => {\n if (!closed) controller!.enqueue(chunk)\n }\n\n const create = (checkpoint: Uint8Array | undefined) =>\n createFxAgent({\n apiKey: credential.token,\n model: kernelModel(step),\n ...(step.instructions.length === 0\n ? {}\n : { instructions: step.instructions }),\n tools: hostTools,\n ...(checkpoint === undefined ? {} : { checkpoint }),\n fetch: hostFetch,\n })\n\n const stream = new ReadableStream<UIMessageChunk>({\n start(streamController) {\n controller = streamController\n const abort = () => {\n stopped = true\n turn?.fxTurn.cancel()\n }\n step.signal.addEventListener('abort', abort, { once: true })\n void (async () => {\n try {\n try {\n agent = await create(read.saved)\n } catch (error) {\n if (read.saved === undefined) throw error\n // An unusable checkpoint: replay the whole log instead.\n read = await replayAll()\n turns = read.turns.map(turnPlan)\n results = read.results\n agent = await create(undefined)\n }\n await run(streamController, turns)\n closed = true\n streamController.close()\n } catch (error) {\n closed = true\n streamController.error(\n step.signal.aborted ? step.signal.reason : error,\n )\n } finally {\n step.signal.removeEventListener('abort', abort)\n await agent?.close().catch(() => {})\n }\n })()\n },\n cancel() {\n closed = true\n stopped = true\n turn?.fxTurn.cancel()\n },\n })\n\n return { stream, completion: () => completion }\n}\n\n// ------------------------------------------------------------ the plan\n\nfunction turnPlan(turn: HarnessTurn): TurnPlan {\n const calls: RecordedCall[] = []\n const steers = new Map<number, string[]>()\n const steer = (at: number, texts: string[] | undefined) => {\n if (texts !== undefined) steers.set(Math.max(0, at), texts)\n }\n steer(0, turn.generations.length === 0 ? turn.steers.get(0) : undefined)\n turn.generations.forEach((generation, index) => {\n calls.push(...recordedCalls(generation.chunks, generation.completed))\n // A generation's step is its last call.\n steer(calls.length - 1, turn.steers.get(index))\n })\n return { prompt: turn.prompt, calls, steers, end: turn.end }\n}\n\n/** A completed generation's model calls: its compactions, then its step. */\nfunction recordedCalls(\n chunks: readonly UIMessageChunk[],\n completed: GenerationCompletedPayload,\n): RecordedCall[] {\n const calls: RecordedCall[] = []\n const parts: StreamPart[] = []\n const toolCalls: ToolCall[] = []\n // A streamed call's input is the provider's exact text; the kernel copies it.\n const inputText = new Map<string, string>()\n for (const chunk of chunks) {\n const metadata =\n 'providerMetadata' in chunk && chunk.providerMetadata !== undefined\n ? { providerMetadata: chunk.providerMetadata }\n : {}\n switch (chunk.type) {\n case 'data-a2-compaction':\n calls.push({\n kind: 'compaction',\n sse: compactionSse(chunk.data as CompactionPartData),\n toolCalls: [],\n })\n break\n case 'text-start':\n case 'text-end':\n case 'reasoning-start':\n case 'reasoning-end':\n parts.push({ type: chunk.type, id: chunk.id, ...metadata })\n break\n case 'text-delta':\n case 'reasoning-delta':\n parts.push({\n type: chunk.type,\n id: chunk.id,\n delta: chunk.delta,\n ...metadata,\n })\n break\n case 'tool-input-start':\n inputText.set(chunk.toolCallId, '')\n parts.push({\n type: 'tool-input-start',\n id: chunk.toolCallId,\n toolName: chunk.toolName,\n ...metadata,\n })\n break\n case 'tool-input-delta':\n inputText.set(\n chunk.toolCallId,\n (inputText.get(chunk.toolCallId) ?? '') + chunk.inputTextDelta,\n )\n parts.push({\n type: 'tool-input-delta',\n id: chunk.toolCallId,\n delta: chunk.inputTextDelta,\n })\n break\n case 'tool-input-error':\n // A call whose input did not parse: FX answered it itself.\n if (inputText.has(chunk.toolCallId))\n parts.push({ type: 'tool-input-end', id: chunk.toolCallId })\n parts.push({\n type: 'tool-call',\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input:\n inputText.get(chunk.toolCallId) ||\n (typeof chunk.input === 'string'\n ? chunk.input\n : JSON.stringify(chunk.input)),\n })\n break\n case 'tool-input-available':\n if (inputText.has(chunk.toolCallId))\n parts.push({ type: 'tool-input-end', id: chunk.toolCallId })\n toolCalls.push({\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input: chunk.input,\n })\n parts.push({\n type: 'tool-call',\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input: inputText.get(chunk.toolCallId) || JSON.stringify(chunk.input),\n ...metadata,\n })\n break\n }\n }\n parts.push({\n type: 'finish',\n finishReason: { unified: completed.finishReason ?? 'other' },\n usage: streamUsage(completed.usage),\n })\n calls.push({ kind: 'step', sse: sse(parts), toolCalls })\n return calls\n}\n\nfunction compactionSse(data: CompactionPartData): string {\n return sse([\n { type: 'text-start', id: '0' },\n { type: 'text-delta', id: '0', delta: data.summary ?? '' },\n { type: 'text-end', id: '0' },\n {\n type: 'finish',\n finishReason: { unified: 'stop' },\n usage: streamUsage(data.usage),\n },\n ])\n}\n\n// ------------------------------------------------------- live responses\n\n/** Streams one live step response as UI chunks and reports its finish. */\nasync function streamStep(\n body: ReadableStream<Uint8Array>,\n emit: (chunk: UIMessageChunk) => void,\n finished: (completion: Completion) => void,\n): Promise<void> {\n for await (const part of sseParts(body)) {\n const metadata =\n part['providerMetadata'] === undefined\n ? {}\n : { providerMetadata: part['providerMetadata'] as never }\n switch (part.type) {\n case 'text-start':\n case 'text-end':\n case 'reasoning-start':\n case 'reasoning-end':\n emit({ type: part.type, id: part['id'] as string, ...metadata })\n break\n case 'text-delta':\n case 'reasoning-delta':\n emit({\n type: part.type,\n id: part['id'] as string,\n delta: part['delta'] as string,\n ...metadata,\n })\n break\n case 'tool-input-start':\n emit({\n type: 'tool-input-start',\n toolCallId: part['id'] as string,\n toolName: part['toolName'] as string,\n ...metadata,\n })\n break\n case 'tool-input-delta':\n emit({\n type: 'tool-input-delta',\n toolCallId: part['id'] as string,\n inputTextDelta: part['delta'] as string,\n })\n break\n case 'tool-call': {\n const text = part['input'] as string\n let input: unknown\n try {\n input = JSON.parse(text)\n } catch (error) {\n emit({\n type: 'tool-input-error',\n toolCallId: part['toolCallId'] as string,\n toolName: part['toolName'] as string,\n input: text,\n errorText: error instanceof Error ? error.message : String(error),\n })\n break\n }\n emit({\n type: 'tool-input-available',\n toolCallId: part['toolCallId'] as string,\n toolName: part['toolName'] as string,\n input,\n ...metadata,\n })\n break\n }\n case 'finish': {\n const reason = part['finishReason'] as { unified?: FinishReason }\n finished({\n ...(reason?.unified === undefined\n ? {}\n : { finishReason: reason.unified }),\n usage: modelUsage(part['usage']),\n })\n break\n }\n case 'error':\n emit({ type: 'error', errorText: errorText(part['error']) })\n break\n }\n }\n}\n\nasync function readParts(\n body: ReadableStream<Uint8Array>,\n): Promise<StreamPart[]> {\n const all: StreamPart[] = []\n for await (const part of sseParts(body)) all.push(part)\n return all\n}\n\nfunction compactionData(all: readonly StreamPart[]): CompactionPartData {\n const finish = all.find((part) => part.type === 'finish')\n return {\n status: 'completed',\n summary: all\n .filter((part) => part.type === 'text-delta')\n .map((part) => part['delta'] as string)\n .join(''),\n ...(finish === undefined ? {} : { usage: modelUsage(finish['usage']) }),\n }\n}\n\nasync function* sseParts(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamPart> {\n const decoder = new TextDecoder()\n let pendingText = ''\n for await (const chunk of body) {\n pendingText += decoder.decode(chunk, { stream: true })\n let end: number\n while ((end = pendingText.indexOf('\\n\\n')) !== -1) {\n const frame = pendingText.slice(0, end)\n pendingText = pendingText.slice(end + 2)\n if (frame.startsWith('data: {')) yield JSON.parse(frame.slice(6))\n }\n }\n}\n\n/**\n * Hands a recorded response to the kernel frame by frame. Steering due after\n * it is queued before its finish part, while the kernel still waits on it.\n */\nfunction relay(text: string, beforeFinish: () => Promise<void>): Response {\n const encoder = new TextEncoder()\n const frames = text.split(/(?<=\\n\\n)/)\n let index = 0\n let steered = false\n return new Response(\n new ReadableStream({\n async pull(controller) {\n const frame = frames[index++]\n if (frame === undefined) {\n controller.close()\n return\n }\n if (!steered && frame.includes('\"type\":\"finish\"')) {\n steered = true\n await beforeFinish()\n }\n controller.enqueue(encoder.encode(frame))\n },\n }),\n { headers: { 'content-type': 'text/event-stream' } },\n )\n}\n\n// ----------------------------------------------------------- the kernel\n\nasync function loadLibfx(): Promise<typeof import('libfx')> {\n try {\n return await import('libfx')\n } catch (error) {\n throw new Error('fx() needs the libfx package: install libfx', {\n cause: error,\n })\n }\n}\n\nfunction withAuth(\n headers: HeadersInit | undefined,\n credential: GatewayCredential,\n): Headers {\n const result = new Headers(headers)\n result.set('ai-gateway-auth-method', credential.method)\n return result\n}\n\nfunction kernelModel(\n step: HarnessStep,\n): string | { id: string; effort?: string; fast?: boolean } {\n const effort =\n step.reasoning === undefined || step.reasoning === 'provider-default'\n ? undefined\n : step.reasoning\n const fast = step.speed === 'fast'\n if (effort === undefined && !fast) return step.model\n return {\n id: step.model,\n ...(effort === undefined ? {} : { effort }),\n ...(fast ? { fast } : {}),\n }\n}\n\nasync function kernelTools(\n tools: ToolSet,\n execute: (toolName: string, input: unknown) => unknown,\n): Promise<FxHostTool[]> {\n return Promise.all(\n Object.entries(tools)\n .filter(([, tool]) => tool.type !== 'provider')\n .map(async ([toolName, tool]) => ({\n name: toolName,\n description:\n typeof tool.description === 'string' ? tool.description : toolName,\n inputSchema: (await asSchema(tool.inputSchema).jsonSchema) as object,\n execute: (input: unknown) => execute(toolName, input),\n })),\n )\n}\n\n// Keyed by credential, and Vercel's OIDC tokens rotate, so it is bounded.\nconst catalogCache = boundedCache<\n string,\n { expires: number; body: Promise<string> }\n>({ maxEntries: 16, maxBytes: 16 })\n\n/**\n * Model catalog reads, shared for an hour by every step in the process that\n * uses the same credential; credentials can see different catalogs.\n */\nasync function catalog(\n url: string,\n credential: GatewayCredential,\n headers: Headers,\n): Promise<Response> {\n const key = `${url}\\n${credential.token}`\n const now = Date.now()\n let entry = catalogCache.get(key)\n if (entry === undefined || entry.expires <= now) {\n const body = fetch(url, { headers }).then(async (response) => {\n if (!response.ok)\n throw new Error(`catalog request failed: ${response.status}`)\n return response.text()\n })\n entry = { expires: now + CATALOG_TTL_MS, body }\n catalogCache.set(key, entry, 1)\n body.catch(() => catalogCache.delete(key))\n }\n return new Response(await entry.body, {\n headers: { 'content-type': 'application/json' },\n })\n}\n\n// ------------------------------------------------------------- helpers\n\nfunction savedCheckpoint(state: unknown): Uint8Array | undefined {\n if (typeof state !== 'object' || state === null) return undefined\n const { version, checkpoint } = state as Record<string, unknown>\n if (version !== SNAPSHOT_VERSION || typeof checkpoint !== 'string')\n return undefined\n return new Uint8Array(Buffer.from(checkpoint, 'base64'))\n}\n\nfunction isCompaction(body: string): boolean {\n const request = JSON.parse(body) as { toolChoice?: { type?: string } }\n return request.toolChoice?.type === 'none'\n}\n\nfunction decodeBody(body: BodyInit | null | undefined): string {\n if (typeof body === 'string') return body\n if (body instanceof Uint8Array || body instanceof ArrayBuffer)\n return new TextDecoder().decode(body)\n throw new TypeError('FX sent an unexpected request body')\n}\n\nfunction sameJson(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b)\n}\n\nfunction sse(all: readonly object[]): string {\n return (\n all.map((part) => `data: ${JSON.stringify(part)}\\n\\n`).join('') +\n 'data: [DONE]\\n\\n'\n )\n}\n\nfunction errorText(error: unknown): string {\n if (typeof error === 'string') return error\n if (error instanceof Error) return error.message\n return JSON.stringify(error)\n}\n\ntype StreamUsage = {\n inputTokens?: {\n total?: number | undefined\n noCache?: number | undefined\n cacheRead?: number | undefined\n cacheWrite?: number | undefined\n }\n outputTokens?: {\n total?: number | undefined\n text?: number | undefined\n reasoning?: number | undefined\n }\n}\n\n/** A Gateway stream usage, as AI SDK normalizes it. */\nfunction modelUsage(value: unknown): LanguageModelUsage {\n const usage = (value ?? {}) as StreamUsage\n const input = usage.inputTokens ?? {}\n const output = usage.outputTokens ?? {}\n return {\n inputTokens: input.total,\n inputTokenDetails: {\n noCacheTokens: input.noCache,\n cacheReadTokens: input.cacheRead,\n cacheWriteTokens: input.cacheWrite,\n },\n outputTokens: output.total,\n outputTokenDetails: {\n textTokens: output.text,\n reasoningTokens: output.reasoning,\n },\n totalTokens:\n input.total === undefined && output.total === undefined\n ? undefined\n : (input.total ?? 0) + (output.total ?? 0),\n }\n}\n\n/** The inverse of `modelUsage`, for replay. */\nfunction streamUsage(usage: LanguageModelUsage | undefined): StreamUsage {\n return {\n inputTokens: {\n total: usage?.inputTokens,\n noCache: usage?.inputTokenDetails?.noCacheTokens,\n cacheRead: usage?.inputTokenDetails?.cacheReadTokens,\n cacheWrite: usage?.inputTokenDetails?.cacheWriteTokens,\n },\n outputTokens: {\n total: usage?.outputTokens,\n text: usage?.outputTokenDetails?.textTokens,\n reasoning: usage?.outputTokenDetails?.reasoningTokens,\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ai-fx.js","names":[],"sources":["../src/ai-fx.ts"],"sourcesContent":["/**\n * experimental-a2/ai/fx — `fx()`: the FX harness for `agent({ harness })`.\n * Server-only; FX's kernel comes from the optional `libfx` peer dependency.\n */\n\n// oxlint-disable no-await-in-loop -- turns replay in order, each on the kernel the last one left.\n\nimport {\n asSchema,\n type FinishReason,\n type LanguageModelUsage,\n type ToolSet,\n type UIMessageChunk,\n} from 'ai'\nimport type { FxAgent, FxHostTool, FxPromptBlock, FxTurn } from 'libfx'\nimport {\n type Deferred,\n defineHarness,\n deferred,\n Divergence,\n gatewayCredential,\n type GatewayCredential,\n type Harness,\n type HarnessGeneration,\n harnessImages,\n type HarnessInput,\n type HarnessRead,\n type HarnessStep,\n type HarnessTurn,\n pending,\n readHarness,\n saveHarness,\n} from './ai-harness.ts'\nimport type { CompactionPartData, GenerationCompletedPayload } from './ai.ts'\nimport { schemaInput } from './ai-tool-input.ts'\nimport { boundedCache } from './bounded-cache.ts'\n\nexport type { Harness } from './ai-harness.ts'\n\n/**\n * The FX harness. Every model call FX makes is one durable step; A2 rebuilds\n * the kernel for each step from its latest checkpoint and the log since.\n */\nexport function fx(): Harness<'fx', never> {\n return defineHarness('fx', {\n tools: {},\n step: runStep,\n })\n}\n\nconst SNAPSHOT_VERSION = 1\nconst CATALOG_TTL_MS = 60 * 60 * 1000\n/** The Gateway model catalog libfx reads for each new kernel. */\nconst CATALOG_PATH = '/coding-agent/v1/models'\n\ntype StreamPart = { type: string } & Record<string, unknown>\n/** A recorded tool call, with the input the kernel reads from its text. */\ntype ToolCall = { toolCallId: string; toolName: string; input: unknown }\n\n/** A model response A2 recorded, in the Gateway's stream format. */\ntype RecordedCall = {\n kind: 'step' | 'compaction'\n sse: string\n toolCalls: ToolCall[]\n}\n\n/** One FX turn to replay: its prompt, recorded calls, and how it ended. */\ntype TurnPlan = {\n prompt: string | FxPromptBlock[]\n calls: RecordedCall[]\n /** Steering to queue while serving the call at that index. */\n steers: Map<number, string[]>\n end: 'stop' | 'interrupted' | 'live'\n}\n\ntype Completion = { finishReason?: FinishReason; usage?: LanguageModelUsage }\n\n/** The turn being replayed or run live, as the fetch and tool hooks see it. */\ntype TurnState = {\n plan: TurnPlan\n fxTurn: FxTurn\n next: number\n /** Tool calls of the last served step and the ones already answered. */\n served: ToolCall[]\n answered: Set<string>\n live: boolean\n liveStep: boolean\n failure?: Error\n /** Resolves when the live step is over: FX asked for its tools. */\n toolsRequested: Deferred\n parsed?: Promise<void>\n}\n\nfunction fail(state: TurnState, error: Error): never {\n state.failure ??= error\n state.fxTurn.cancel()\n throw state.failure\n}\n\nconst diverged = (message: string): Divergence => new Divergence('FX', message)\n\n// ---------------------------------------------------------------- step\n\nasync function runStep(step: HarnessStep): Promise<HarnessGeneration> {\n const { createFxAgent } = await loadLibfx()\n const credential = gatewayCredential('fx')\n const name = `${step.agentName}.a2.harness.fx`\n const { replayAll, ...first } = await readHarness({\n step,\n name,\n parse: savedCheckpoint,\n })\n let read: HarnessRead<Uint8Array> = first\n\n let completion: Completion = {}\n let stopped = false\n // Live responses belong to the step: the kernel aborts its fetch once it\n // has read a response's finish, while A2 may still be reading its copy.\n const released = new AbortController()\n const network = AbortSignal.any([step.signal, released.signal])\n let agent: FxAgent | undefined\n let turn: TurnState | undefined\n\n const run = async (\n controller: ReadableStreamDefaultController<UIMessageChunk>,\n turns: TurnPlan[],\n ): Promise<void> => {\n controller.enqueue({ type: 'start', messageId: step.responseMessageId })\n for (const plan of turns) {\n if (stopped) return\n const fxTurn = agent!.prompt(plan.prompt, { signal: step.signal })\n const state: TurnState = {\n plan,\n fxTurn,\n next: 0,\n served: [],\n answered: new Set(),\n live: false,\n liveStep: false,\n toolsRequested: deferred(),\n }\n turn = state\n const drained = (async () => {\n for await (const _ of fxTurn) {\n // Live output reaches A2 from the Gateway response itself.\n }\n })()\n // A failed turn surfaces through its result.\n drained.catch(() => {})\n if (plan.end !== 'live') {\n const result = await fxTurn.result.catch((error: unknown) => {\n throw state.failure ?? error\n })\n await drained\n if (state.failure) throw state.failure\n const expected = plan.end === 'stop' ? 'end_turn' : 'cancelled'\n if (result.stopReason !== expected)\n throw diverged(\n `a recorded turn ended with ${result.stopReason}, not ${expected}`,\n )\n continue\n }\n const outcome = await Promise.race([\n fxTurn.result.then((result) => ({ ended: true, result })),\n state.toolsRequested.promise.then(() => ({ ended: false as const })),\n ]).catch((error: unknown) => {\n throw state.failure ?? error\n })\n if (state.failure) throw state.failure\n await state.parsed\n if (outcome.ended) {\n await drained\n // Only a turn this attempt finished describes the log.\n if (outcome.result.stopReason === 'end_turn' && !step.signal.aborted)\n await saveCheckpoint()\n } else {\n // FX now waits on tools that A2's tool handlers run.\n fxTurn.cancel()\n }\n controller.enqueue({ type: 'finish-step' })\n controller.enqueue({\n type: 'finish',\n ...(completion.finishReason === undefined\n ? {}\n : { finishReason: completion.finishReason }),\n })\n }\n }\n\n const saveCheckpoint = async (): Promise<void> => {\n let checkpoint: Uint8Array\n try {\n checkpoint = await agent!.checkpoint()\n } catch {\n // Later steps replay from the previous snapshot.\n return\n }\n await saveHarness({\n step,\n name,\n state: {\n version: SNAPSHOT_VERSION,\n checkpoint: Buffer.from(checkpoint).toString('base64'),\n },\n })\n }\n\n const hostFetch = async (\n input: string | URL | Request,\n init: RequestInit = {},\n ): Promise<Response> => {\n const url = input instanceof Request ? input.url : String(input)\n const method = (init.method ?? 'GET').toUpperCase()\n if (method === 'GET' && new URL(url).pathname === CATALOG_PATH)\n return catalog(url, credential, withAuth(init.headers, credential))\n if (method === 'GET') return fetch(input, init)\n const state = turn!\n if (state.failure) throw state.failure\n const body = decodeBody(init.body)\n const compaction = isCompaction(body)\n const recorded = state.plan.calls[state.next]\n if (recorded !== undefined) {\n if ((recorded.kind === 'compaction') !== compaction)\n fail(state, diverged(`request ${state.next} is not a ${recorded.kind}`))\n const index = state.next++\n if (recorded.kind === 'step') {\n state.served = recorded.toolCalls\n state.answered = new Set()\n }\n const steers = state.plan.steers.get(index) ?? []\n return relay(recorded.sse, async () => {\n for (const text of steers) await state.fxTurn.steer(text)\n })\n }\n if (state.plan.end === 'stop')\n fail(state, diverged('FX continued a turn the log ended'))\n if (state.plan.end === 'interrupted') {\n state.fxTurn.cancel()\n throw new DOMException('The recorded turn was interrupted', 'AbortError')\n }\n if (state.liveStep && !compaction) {\n // One generation is one step; the next step is A2's next generation.\n state.toolsRequested.resolve()\n return pending(init.signal)\n }\n state.live = true\n return live(state, url, init, compaction)\n }\n\n let compactions = 0\n const live = async (\n state: TurnState,\n url: string,\n init: RequestInit,\n compaction: boolean,\n ): Promise<Response> => {\n const response = await fetch(url, {\n ...init,\n headers: withAuth(init.headers, credential),\n signal: network,\n })\n // Abandoned before its headers came: the kernel has moved on without it.\n if (init.signal?.aborted) {\n void response.body?.cancel()\n throw init.signal.reason\n }\n if (!response.ok || response.body === null) return response\n const [fromNetwork, forLog] = response.body.tee()\n const forKernel = init.signal\n ? fromNetwork.pipeThrough(new TransformStream(), { signal: init.signal })\n : fromNetwork\n // Live responses reach the log in request order: a compaction's part\n // precedes the step that follows it.\n const previous = state.parsed\n if (compaction) {\n // Unique across the response's generations: the transcript keys data parts by ID.\n const id = `fx-compaction:${step.requestIndex}:${compactions++}`\n state.parsed = (async () => {\n const all = await readParts(forLog)\n await previous\n emit({\n type: 'data-a2-compaction',\n id,\n data: compactionData(all),\n })\n })()\n } else {\n state.liveStep = true\n state.parsed = (async () => {\n await previous\n emit({ type: 'start-step' })\n await streamStep({\n body: forLog,\n tools: step.tools,\n emit,\n finished: (finished) => {\n completion = finished\n },\n })\n })()\n }\n // A stopped step abandons its parse; its failure surfaces through the turn.\n state.parsed.catch(() => {})\n return new Response(forKernel, {\n status: response.status,\n headers: response.headers,\n })\n }\n\n const hostTools = await kernelTools(step.tools, (toolName, toolInput) => {\n const state = turn!\n if (state.failure) throw state.failure\n const call = state.served.find(\n (candidate) =>\n candidate.toolName === toolName &&\n !state.answered.has(candidate.toolCallId) &&\n sameJson(candidate.input, toolInput),\n )\n const result = call === undefined ? undefined : results.get(call.toolCallId)\n if (call !== undefined && result !== undefined) {\n state.answered.add(call.toolCallId)\n if (result.error !== undefined) throw new Error(result.error)\n if (result.denied === true) throw new Error('The tool call was denied.')\n return result.output ?? null\n }\n if (state.live) {\n state.toolsRequested.resolve()\n return pending(undefined)\n }\n if (state.plan.end === 'interrupted') {\n state.fxTurn.cancel()\n return pending(undefined)\n }\n return fail(state, diverged(`no recorded result for ${toolName}`))\n })\n\n const plans = (turns: HarnessTurn[]): Promise<TurnPlan[]> =>\n Promise.all(turns.map((recorded) => turnPlan(recorded, step.signal)))\n let results = read.results\n let controller: ReadableStreamDefaultController<UIMessageChunk> | undefined\n let closed = false\n const emit = (chunk: UIMessageChunk): void => {\n if (!closed) controller!.enqueue(chunk)\n }\n\n const create = (checkpoint: Uint8Array | undefined) =>\n createFxAgent({\n apiKey: credential.token,\n model: kernelModel(step),\n ...(step.instructions.length === 0\n ? {}\n : { instructions: step.instructions }),\n tools: hostTools,\n ...(checkpoint === undefined ? {} : { checkpoint }),\n fetch: hostFetch,\n })\n\n const stream = new ReadableStream<UIMessageChunk>({\n start(streamController) {\n controller = streamController\n const abort = () => {\n stopped = true\n turn?.fxTurn.cancel()\n }\n step.signal.addEventListener('abort', abort, { once: true })\n void (async () => {\n try {\n try {\n agent = await create(read.saved)\n } catch (error) {\n if (read.saved === undefined) throw error\n // An unusable checkpoint: replay the whole log instead.\n read = await replayAll()\n results = read.results\n agent = await create(undefined)\n }\n await run(streamController, await plans(read.turns))\n closed = true\n streamController.close()\n } catch (error) {\n closed = true\n streamController.error(\n step.signal.aborted ? step.signal.reason : error,\n )\n } finally {\n released.abort()\n step.signal.removeEventListener('abort', abort)\n await agent?.close().catch(() => {})\n }\n })()\n },\n cancel() {\n closed = true\n stopped = true\n released.abort()\n turn?.fxTurn.cancel()\n },\n })\n\n return { stream, completion: () => completion }\n}\n\n// ------------------------------------------------------------ the plan\n\nasync function turnPlan(\n turn: HarnessTurn,\n signal: AbortSignal,\n): Promise<TurnPlan> {\n const calls: RecordedCall[] = []\n const steers = new Map<number, string[]>()\n const steer = (at: number, inputs: HarnessInput[] | undefined) => {\n if (inputs !== undefined) steers.set(Math.max(0, at), inputs.map(steerText))\n }\n steer(0, turn.generations.length === 0 ? turn.steers.get(0) : undefined)\n turn.generations.forEach((generation, index) => {\n calls.push(...recordedCalls(generation.chunks, generation.completed))\n // A generation's step is its last call.\n steer(calls.length - 1, turn.steers.get(index))\n })\n const images = await harnessImages({\n harness: 'fx()',\n input: turn.prompt,\n signal,\n })\n return {\n prompt:\n images.length === 0\n ? turn.prompt.text\n : [\n ...images.map((image): FxPromptBlock => ({\n type: 'image',\n data: image.data,\n mimeType: image.mediaType,\n })),\n ...(turn.prompt.text === ''\n ? []\n : [{ type: 'text' as const, text: turn.prompt.text }]),\n ],\n calls,\n steers,\n end: turn.end,\n }\n}\n\n/** libfx steers with text alone, so a steer's files fail the step. */\nfunction steerText(input: HarnessInput): string {\n if (input.files.length > 0)\n throw new Error(\n 'fx() steers with text only: send files in a message of their own',\n )\n return input.text\n}\n\n/** A completed generation's model calls: its compactions, then its step. */\nfunction recordedCalls(\n chunks: readonly UIMessageChunk[],\n completed: GenerationCompletedPayload,\n): RecordedCall[] {\n const calls: RecordedCall[] = []\n const parts: StreamPart[] = []\n const toolCalls: ToolCall[] = []\n // A streamed call's input is the provider's exact text; the kernel copies it.\n const inputText = new Map<string, string>()\n for (const chunk of chunks) {\n const metadata =\n 'providerMetadata' in chunk && chunk.providerMetadata !== undefined\n ? { providerMetadata: chunk.providerMetadata }\n : {}\n switch (chunk.type) {\n case 'data-a2-compaction':\n calls.push({\n kind: 'compaction',\n sse: compactionSse(chunk.data as CompactionPartData),\n toolCalls: [],\n })\n break\n case 'text-start':\n case 'text-end':\n case 'reasoning-start':\n case 'reasoning-end':\n parts.push({ type: chunk.type, id: chunk.id, ...metadata })\n break\n case 'text-delta':\n case 'reasoning-delta':\n parts.push({\n type: chunk.type,\n id: chunk.id,\n delta: chunk.delta,\n ...metadata,\n })\n break\n case 'tool-input-start':\n inputText.set(chunk.toolCallId, '')\n parts.push({\n type: 'tool-input-start',\n id: chunk.toolCallId,\n toolName: chunk.toolName,\n ...metadata,\n })\n break\n case 'tool-input-delta':\n inputText.set(\n chunk.toolCallId,\n (inputText.get(chunk.toolCallId) ?? '') + chunk.inputTextDelta,\n )\n parts.push({\n type: 'tool-input-delta',\n id: chunk.toolCallId,\n delta: chunk.inputTextDelta,\n })\n break\n case 'tool-input-error':\n case 'tool-input-available': {\n // A call recorded without its text: input that failed to parse is\n // that text.\n const text =\n inputText.get(chunk.toolCallId) ||\n (chunk.type === 'tool-input-error' && typeof chunk.input === 'string'\n ? chunk.input\n : JSON.stringify(chunk.input))\n if (inputText.has(chunk.toolCallId))\n parts.push({ type: 'tool-input-end', id: chunk.toolCallId })\n // The kernel calls back with this text's JSON, not the input the\n // tool's schema made of it. A call it answers itself, such as one\n // whose text is not JSON, is never asked for.\n const input = parseJson(text)\n if (input !== undefined)\n toolCalls.push({\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input,\n })\n parts.push({\n type: 'tool-call',\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n input: text,\n ...metadata,\n })\n break\n }\n }\n }\n parts.push({\n type: 'finish',\n finishReason: { unified: completed.finishReason ?? 'other' },\n usage: streamUsage(completed.usage),\n })\n calls.push({ kind: 'step', sse: sse(parts), toolCalls })\n return calls\n}\n\nfunction compactionSse(data: CompactionPartData): string {\n return sse([\n { type: 'text-start', id: '0' },\n { type: 'text-delta', id: '0', delta: data.summary ?? '' },\n { type: 'text-end', id: '0' },\n {\n type: 'finish',\n finishReason: { unified: 'stop' },\n usage: streamUsage(data.usage),\n },\n ])\n}\n\n// ------------------------------------------------------- live responses\n\n/** Streams one live step response as UI chunks and reports its finish. */\nasync function streamStep({\n body,\n tools,\n emit,\n finished,\n}: {\n body: ReadableStream<Uint8Array>\n tools: ToolSet\n emit: (chunk: UIMessageChunk) => void\n finished: (completion: Completion) => void\n}): Promise<void> {\n // The tool calls whose input started streaming, and whether text arrived.\n const streamed = new Map<string, boolean>()\n for await (const part of sseParts(body)) {\n const metadata =\n part['providerMetadata'] === undefined\n ? {}\n : { providerMetadata: part['providerMetadata'] as never }\n switch (part.type) {\n case 'text-start':\n case 'text-end':\n case 'reasoning-start':\n case 'reasoning-end':\n emit({ type: part.type, id: part['id'] as string, ...metadata })\n break\n case 'text-delta':\n case 'reasoning-delta':\n emit({\n type: part.type,\n id: part['id'] as string,\n delta: part['delta'] as string,\n ...metadata,\n })\n break\n case 'tool-input-start':\n streamed.set(part['id'] as string, false)\n emit({\n type: 'tool-input-start',\n toolCallId: part['id'] as string,\n toolName: part['toolName'] as string,\n ...metadata,\n })\n break\n case 'tool-input-delta':\n if (part['delta'] !== '') streamed.set(part['id'] as string, true)\n emit({\n type: 'tool-input-delta',\n toolCallId: part['id'] as string,\n inputTextDelta: part['delta'] as string,\n })\n break\n case 'tool-call': {\n const toolCallId = part['toolCallId'] as string\n const toolName = part['toolName'] as string\n const text = part['input'] as string\n // Replay hands the kernel the text the log holds, so the log keeps\n // the provider's text when it streamed none.\n if (streamed.get(toolCallId) !== true && text !== '') {\n if (!streamed.has(toolCallId))\n emit({ type: 'tool-input-start', toolCallId, toolName })\n emit({ type: 'tool-input-delta', toolCallId, inputTextDelta: text })\n }\n const input = await parseToolInput({\n tools,\n toolName,\n text,\n })\n emit(\n input.success\n ? {\n type: 'tool-input-available',\n toolCallId,\n toolName,\n input: input.value,\n ...metadata,\n }\n : {\n type: 'tool-input-error',\n toolCallId,\n toolName,\n input: input.input,\n errorText: input.errorText,\n ...metadata,\n },\n )\n break\n }\n case 'finish': {\n const reason = part['finishReason'] as { unified?: FinishReason }\n finished({\n ...(reason?.unified === undefined\n ? {}\n : { finishReason: reason.unified }),\n usage: modelUsage(part['usage']),\n })\n break\n }\n case 'error':\n emit({ type: 'error', errorText: errorText(part['error']) })\n break\n }\n }\n}\n\ntype ToolInput =\n | { success: true; value: unknown }\n | { success: false; input: unknown; errorText: string }\n\n/**\n * A live call's input as the AI SDK step reads it: JSON, then the tool's\n * schema with its defaults. Input that fails either is an input error, which\n * A2 answers without running the tool.\n */\nasync function parseToolInput({\n tools,\n toolName,\n text,\n}: {\n tools: ToolSet\n toolName: string\n text: string\n}): Promise<ToolInput> {\n let value: unknown\n try {\n value = JSON.parse(text)\n } catch (error) {\n return { success: false, input: text, errorText: errorText(error) }\n }\n const input = await schemaInput({ tools, toolName, value })\n return input.success ? input : { ...input, input: value }\n}\n\nasync function readParts(\n body: ReadableStream<Uint8Array>,\n): Promise<StreamPart[]> {\n const all: StreamPart[] = []\n for await (const part of sseParts(body)) all.push(part)\n return all\n}\n\nfunction compactionData(all: readonly StreamPart[]): CompactionPartData {\n const finish = all.find((part) => part.type === 'finish')\n return {\n status: 'completed',\n summary: all\n .filter((part) => part.type === 'text-delta')\n .map((part) => part['delta'] as string)\n .join(''),\n ...(finish === undefined ? {} : { usage: modelUsage(finish['usage']) }),\n }\n}\n\nasync function* sseParts(\n body: ReadableStream<Uint8Array>,\n): AsyncGenerator<StreamPart> {\n const decoder = new TextDecoder()\n let pendingText = ''\n for await (const chunk of body) {\n pendingText += decoder.decode(chunk, { stream: true })\n let end: number\n while ((end = pendingText.indexOf('\\n\\n')) !== -1) {\n const frame = pendingText.slice(0, end)\n pendingText = pendingText.slice(end + 2)\n if (frame.startsWith('data: {')) yield JSON.parse(frame.slice(6))\n }\n }\n}\n\n/**\n * Hands a recorded response to the kernel frame by frame. Steering due after\n * it is queued before its finish part, while the kernel still waits on it.\n */\nfunction relay(text: string, beforeFinish: () => Promise<void>): Response {\n const encoder = new TextEncoder()\n const frames = text.split(/(?<=\\n\\n)/)\n let index = 0\n let steered = false\n return new Response(\n new ReadableStream({\n async pull(controller) {\n const frame = frames[index++]\n if (frame === undefined) {\n controller.close()\n return\n }\n if (!steered && frame.includes('\"type\":\"finish\"')) {\n steered = true\n await beforeFinish()\n }\n controller.enqueue(encoder.encode(frame))\n },\n }),\n { headers: { 'content-type': 'text/event-stream' } },\n )\n}\n\n// ----------------------------------------------------------- the kernel\n\nasync function loadLibfx(): Promise<typeof import('libfx')> {\n try {\n return await import('libfx')\n } catch (error) {\n throw new Error('fx() needs the libfx package: install libfx', {\n cause: error,\n })\n }\n}\n\nfunction withAuth(\n headers: HeadersInit | undefined,\n credential: GatewayCredential,\n): Headers {\n const result = new Headers(headers)\n result.set('ai-gateway-auth-method', credential.method)\n return result\n}\n\nfunction kernelModel(\n step: HarnessStep,\n): string | { id: string; effort?: string; fast?: boolean } {\n const effort =\n step.reasoning === undefined || step.reasoning === 'provider-default'\n ? undefined\n : step.reasoning\n const fast = step.speed === 'fast'\n if (effort === undefined && !fast) return step.model\n return {\n id: step.model,\n ...(effort === undefined ? {} : { effort }),\n ...(fast ? { fast } : {}),\n }\n}\n\nasync function kernelTools(\n tools: ToolSet,\n execute: (toolName: string, input: unknown) => unknown,\n): Promise<FxHostTool[]> {\n return Promise.all(\n Object.entries(tools).map(async ([toolName, tool]) => ({\n name: toolName,\n description:\n typeof tool.description === 'string' ? tool.description : toolName,\n inputSchema: (await asSchema(tool.inputSchema).jsonSchema) as object,\n execute: (input: unknown) => execute(toolName, input),\n })),\n )\n}\n\n// Keyed by credential, and Vercel's OIDC tokens rotate, so it is bounded.\nconst catalogCache = boundedCache<\n string,\n { expires: number; body: Promise<string> }\n>({ maxEntries: 16, maxBytes: 16 })\n\n/**\n * Model catalog reads, shared for an hour by every step in the process that\n * uses the same credential; credentials can see different catalogs.\n */\nasync function catalog(\n url: string,\n credential: GatewayCredential,\n headers: Headers,\n): Promise<Response> {\n const key = `${url}\\n${credential.token}`\n const now = Date.now()\n let entry = catalogCache.get(key)\n if (entry === undefined || entry.expires <= now) {\n const body = fetch(url, { headers }).then(async (response) => {\n if (!response.ok)\n throw new Error(`catalog request failed: ${response.status}`)\n return response.text()\n })\n entry = { expires: now + CATALOG_TTL_MS, body }\n catalogCache.set(key, entry, 1)\n body.catch(() => catalogCache.delete(key))\n }\n return new Response(await entry.body, {\n headers: { 'content-type': 'application/json' },\n })\n}\n\n// ------------------------------------------------------------- helpers\n\nfunction savedCheckpoint(state: unknown): Uint8Array | undefined {\n if (typeof state !== 'object' || state === null) return undefined\n const { version, checkpoint } = state as Record<string, unknown>\n if (version !== SNAPSHOT_VERSION || typeof checkpoint !== 'string')\n return undefined\n return new Uint8Array(Buffer.from(checkpoint, 'base64'))\n}\n\nfunction isCompaction(body: string): boolean {\n const request = JSON.parse(body) as { toolChoice?: { type?: string } }\n return request.toolChoice?.type === 'none'\n}\n\nfunction decodeBody(body: BodyInit | null | undefined): string {\n if (typeof body === 'string') return body\n if (body instanceof Uint8Array || body instanceof ArrayBuffer)\n return new TextDecoder().decode(body)\n throw new TypeError('FX sent an unexpected request body')\n}\n\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n\nfunction sameJson(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b)\n}\n\nfunction sse(all: readonly object[]): string {\n return (\n all.map((part) => `data: ${JSON.stringify(part)}\\n\\n`).join('') +\n 'data: [DONE]\\n\\n'\n )\n}\n\nfunction errorText(error: unknown): string {\n if (typeof error === 'string') return error\n if (error instanceof Error) return error.message\n return JSON.stringify(error)\n}\n\ntype StreamUsage = {\n inputTokens?: {\n total?: number | undefined\n noCache?: number | undefined\n cacheRead?: number | undefined\n cacheWrite?: number | undefined\n }\n outputTokens?: {\n total?: number | undefined\n text?: number | undefined\n reasoning?: number | undefined\n }\n}\n\n/** A Gateway stream usage, as AI SDK normalizes it. */\nfunction modelUsage(value: unknown): LanguageModelUsage {\n const usage = (value ?? {}) as StreamUsage\n const input = usage.inputTokens ?? {}\n const output = usage.outputTokens ?? {}\n return {\n inputTokens: input.total,\n inputTokenDetails: {\n noCacheTokens: input.noCache,\n cacheReadTokens: input.cacheRead,\n cacheWriteTokens: input.cacheWrite,\n },\n outputTokens: output.total,\n outputTokenDetails: {\n textTokens: output.text,\n reasoningTokens: output.reasoning,\n },\n totalTokens:\n input.total === undefined && output.total === undefined\n ? undefined\n : (input.total ?? 0) + (output.total ?? 0),\n }\n}\n\n/** The inverse of `modelUsage`, for replay. */\nfunction streamUsage(usage: LanguageModelUsage | undefined): StreamUsage {\n return {\n inputTokens: {\n total: usage?.inputTokens,\n noCache: usage?.inputTokenDetails?.noCacheTokens,\n cacheRead: usage?.inputTokenDetails?.cacheReadTokens,\n cacheWrite: usage?.inputTokenDetails?.cacheWriteTokens,\n },\n outputTokens: {\n total: usage?.outputTokens,\n text: usage?.outputTokenDetails?.textTokens,\n reasoning: usage?.outputTokenDetails?.reasoningTokens,\n },\n }\n}\n"],"mappings":"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"}