experimental-a2 0.18.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/{actor-Bjce9_5U.d.ts → actor-C7b-1arn.d.ts} +3 -3
- package/dist/{actor-Bjce9_5U.d.ts.map → actor-C7b-1arn.d.ts.map} +1 -1
- package/dist/actor-client.d.ts +1 -1
- package/dist/actor-react.d.ts +1 -1
- package/dist/actor-react.js +1 -1
- package/dist/actor.d.ts +1 -1
- package/dist/actor.js +2 -2
- package/dist/{ai-DrUaMyRt.d.ts → ai-BMLlI2Ff.d.ts} +2 -2
- package/dist/{ai-DrUaMyRt.d.ts.map → ai-BMLlI2Ff.d.ts.map} +1 -1
- package/dist/{ai-BpOGm-zB.js → ai-D6mGlO8j.js} +2 -2
- package/dist/{ai-BpOGm-zB.js.map → ai-D6mGlO8j.js.map} +1 -1
- package/dist/ai-client.d.ts +1 -1
- package/dist/ai-client.js +2 -2
- package/dist/ai-fx.d.ts +1 -1
- package/dist/ai-fx.d.ts.map +1 -1
- package/dist/ai-fx.js +92 -34
- package/dist/ai-fx.js.map +1 -1
- package/dist/{ai-harness-DvsPeJeB.d.ts → ai-harness-B2suP2Qh.d.ts} +2 -2
- package/dist/{ai-harness-DvsPeJeB.d.ts.map → ai-harness-B2suP2Qh.d.ts.map} +1 -1
- package/dist/ai-pi.d.ts +1 -1
- package/dist/ai-pi.d.ts.map +1 -1
- package/dist/ai-pi.js +59 -13
- package/dist/ai-pi.js.map +1 -1
- package/dist/ai-react.d.ts +1 -1
- package/dist/ai-react.js +2 -2
- package/dist/ai-server.d.ts +3 -3
- package/dist/ai-server.d.ts.map +1 -1
- package/dist/ai-server.js +10 -6
- package/dist/ai-server.js.map +1 -1
- package/dist/ai-tool-input-DmSqMUQi.js +40 -0
- package/dist/ai-tool-input-DmSqMUQi.js.map +1 -0
- package/dist/ai.d.ts +1 -1
- package/dist/ai.js +1 -1
- package/dist/{client-BReKqwZC.js → client-BhHLoNKF.js} +3 -3
- package/dist/{client-BReKqwZC.js.map → client-BhHLoNKF.js.map} +1 -1
- package/dist/client.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/{internal-B2T3U4Rq.js → internal-CscSY7K_.js} +4 -2
- package/dist/{internal-B2T3U4Rq.js.map → internal-CscSY7K_.js.map} +1 -1
- package/dist/react.js +1 -1
- package/dist/scheduler-qstash.d.ts +2 -2
- package/dist/scheduler-qstash.js +3 -3
- package/dist/scheduler-qstash.js.map +1 -1
- package/dist/scheduler-vercel.d.ts +7 -7
- package/dist/scheduler-vercel.d.ts.map +1 -1
- package/dist/scheduler-vercel.js +9 -10
- package/dist/scheduler-vercel.js.map +1 -1
- package/dist/{server-Dw_k_7kO.js → server-D-Y4pqwu.js} +37 -11
- package/dist/server-D-Y4pqwu.js.map +1 -0
- package/dist/{server-En7cbi3v.d.ts → server-DYAATFuT.d.ts} +11 -5
- package/dist/server-DYAATFuT.d.ts.map +1 -0
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1 -1
- package/dist/{session-clear-Bo-XTFEy.d.ts → session-clear-C-QwTXV1.d.ts} +2 -2
- package/dist/session-clear-C-QwTXV1.d.ts.map +1 -0
- package/dist/{store-Djdv0bnZ.d.ts → store-CyLUy86v.d.ts} +23 -4
- package/dist/store-CyLUy86v.d.ts.map +1 -0
- package/dist/store-N8PXxDAS.js.map +1 -1
- package/dist/store-memory.d.ts +1 -1
- package/dist/store-memory.js +25 -6
- package/dist/store-memory.js.map +1 -1
- package/dist/{store-polling-B5FcwJfo.js → store-polling-7WJV0YWP.js} +2 -2
- package/dist/{store-polling-B5FcwJfo.js.map → store-polling-7WJV0YWP.js.map} +1 -1
- package/dist/store-postgres.d.ts +1 -1
- package/dist/store-postgres.d.ts.map +1 -1
- package/dist/store-postgres.js +55 -25
- package/dist/store-postgres.js.map +1 -1
- package/dist/{store-presence-polling-BAwS8RWn.js → store-presence-polling-B1ixeqIS.js} +3 -3
- package/dist/{store-presence-polling-BAwS8RWn.js.map → store-presence-polling-B1ixeqIS.js.map} +1 -1
- package/dist/store-redis-http.d.ts +1 -1
- package/dist/store-redis-http.js +3 -3
- package/dist/{store-redis-notify-BRITti_o.js → store-redis-notify-CM0AfLY0.js} +88 -37
- package/dist/store-redis-notify-CM0AfLY0.js.map +1 -0
- package/dist/store-redis.d.ts +1 -1
- package/dist/store-redis.js +1 -1
- package/dist/store-sqlite.d.ts +1 -1
- package/dist/store-sqlite.js +35 -20
- package/dist/store-sqlite.js.map +1 -1
- package/dist/{wire-rSUglYo8.js → wire-BKxH1vbP.js} +2 -2
- package/dist/{wire-rSUglYo8.js.map → wire-BKxH1vbP.js.map} +1 -1
- package/docs/agents/03-conversations.mdx +2 -2
- package/docs/index.mdx +3 -3
- package/docs/reference/02-server.mdx +12 -7
- package/docs/reference/04-ai.mdx +16 -7
- package/docs/reference/05-adapters.mdx +4 -4
- package/docs/server/01-handlers.mdx +1 -1
- package/docs/server/03-cancellation.mdx +3 -2
- package/docs/server/05-production.mdx +2 -1
- package/docs/server/06-guarantees.mdx +20 -11
- package/examples/playground/DEPLOY.md +2 -4
- package/examples/playground/app/a0/[appId]/page.tsx +2 -8
- package/examples/playground/app/a0/devtools.tsx +2 -8
- package/examples/playground/app/a0/server.ts +8 -19
- package/examples/playground/package.json +1 -1
- package/package.json +1 -1
- package/src/ai-agent.ts +10 -3
- package/src/ai-fx.ts +126 -47
- package/src/ai-pi.ts +74 -15
- package/src/ai-tool-input.ts +45 -0
- package/src/internal.ts +6 -0
- package/src/scheduler-qstash.ts +5 -5
- package/src/scheduler-vercel.ts +14 -15
- package/src/server.ts +58 -12
- package/src/store-memory.ts +50 -9
- package/src/store-postgres.ts +79 -28
- package/src/store-redis-core.ts +112 -31
- package/src/store-sqlite.ts +61 -28
- package/src/store.ts +22 -3
- package/dist/server-Dw_k_7kO.js.map +0 -1
- package/dist/server-En7cbi3v.d.ts.map +0 -1
- package/dist/session-clear-Bo-XTFEy.d.ts.map +0 -1
- package/dist/store-Djdv0bnZ.d.ts.map +0 -1
- package/dist/store-redis-notify-BRITti_o.js.map +0 -1
package/dist/ai-client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { s as CreateClientOptions, t as A2Client } from "./client-h_DKFAjj.js";
|
|
2
|
-
import { a as AI_STATE_REDUCER, i as AIState, r as AIMessageOf, t as AIEventDefs } from "./ai-
|
|
2
|
+
import { a as AI_STATE_REDUCER, i as AIState, r as AIMessageOf, t as AIEventDefs } from "./ai-BMLlI2Ff.js";
|
|
3
3
|
//#region src/ai-client.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* The structural shape of `typeof` an `agent({ name })` server: one whose
|
package/dist/ai-client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as createClient } from "./client-
|
|
2
|
-
import { n as agentContract } from "./ai-
|
|
1
|
+
import { t as createClient } from "./client-BhHLoNKF.js";
|
|
2
|
+
import { n as agentContract } from "./ai-D6mGlO8j.js";
|
|
3
3
|
//#region src/ai-client.ts
|
|
4
4
|
/**
|
|
5
5
|
* experimental-a2/ai/client — a client for an `agent()` route that needs no
|
package/dist/ai-fx.d.ts
CHANGED
package/dist/ai-fx.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-fx.d.ts","names":[],"sources":["../src/ai-fx.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"ai-fx.d.ts","names":[],"sources":["../src/ai-fx.ts"],"mappings":";;;;;;iBAyCgB,MAAM"}
|
package/dist/ai-fx.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { t as boundedCache } from "./bounded-cache-CPHWF-8h.js";
|
|
2
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";
|
|
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
|
/**
|
|
@@ -36,6 +37,8 @@ async function runStep(step) {
|
|
|
36
37
|
let read = first;
|
|
37
38
|
let completion = {};
|
|
38
39
|
let stopped = false;
|
|
40
|
+
const released = new AbortController();
|
|
41
|
+
const network = AbortSignal.any([step.signal, released.signal]);
|
|
39
42
|
let agent;
|
|
40
43
|
let turn;
|
|
41
44
|
const run = async (controller, turns) => {
|
|
@@ -141,10 +144,16 @@ async function runStep(step) {
|
|
|
141
144
|
const live = async (state, url, init, compaction) => {
|
|
142
145
|
const response = await fetch(url, {
|
|
143
146
|
...init,
|
|
144
|
-
headers: withAuth(init.headers, credential)
|
|
147
|
+
headers: withAuth(init.headers, credential),
|
|
148
|
+
signal: network
|
|
145
149
|
});
|
|
150
|
+
if (init.signal?.aborted) {
|
|
151
|
+
response.body?.cancel();
|
|
152
|
+
throw init.signal.reason;
|
|
153
|
+
}
|
|
146
154
|
if (!response.ok || response.body === null) return response;
|
|
147
|
-
const [
|
|
155
|
+
const [fromNetwork, forLog] = response.body.tee();
|
|
156
|
+
const forKernel = init.signal ? fromNetwork.pipeThrough(new TransformStream(), { signal: init.signal }) : fromNetwork;
|
|
148
157
|
const previous = state.parsed;
|
|
149
158
|
if (compaction) {
|
|
150
159
|
const id = `fx-compaction:${step.requestIndex}:${compactions++}`;
|
|
@@ -162,8 +171,13 @@ async function runStep(step) {
|
|
|
162
171
|
state.parsed = (async () => {
|
|
163
172
|
await previous;
|
|
164
173
|
emit({ type: "start-step" });
|
|
165
|
-
await streamStep(
|
|
166
|
-
|
|
174
|
+
await streamStep({
|
|
175
|
+
body: forLog,
|
|
176
|
+
tools: step.tools,
|
|
177
|
+
emit,
|
|
178
|
+
finished: (finished) => {
|
|
179
|
+
completion = finished;
|
|
180
|
+
}
|
|
167
181
|
});
|
|
168
182
|
})();
|
|
169
183
|
}
|
|
@@ -236,6 +250,7 @@ async function runStep(step) {
|
|
|
236
250
|
closed = true;
|
|
237
251
|
streamController.error(step.signal.aborted ? step.signal.reason : error);
|
|
238
252
|
} finally {
|
|
253
|
+
released.abort();
|
|
239
254
|
step.signal.removeEventListener("abort", abort);
|
|
240
255
|
await agent?.close().catch(() => {});
|
|
241
256
|
}
|
|
@@ -244,6 +259,7 @@ async function runStep(step) {
|
|
|
244
259
|
cancel() {
|
|
245
260
|
closed = true;
|
|
246
261
|
stopped = true;
|
|
262
|
+
released.abort();
|
|
247
263
|
turn?.fxTurn.cancel();
|
|
248
264
|
}
|
|
249
265
|
}),
|
|
@@ -321,34 +337,27 @@ function recordedCalls(chunks, completed) {
|
|
|
321
337
|
});
|
|
322
338
|
break;
|
|
323
339
|
case "tool-input-error":
|
|
340
|
+
case "tool-input-available": {
|
|
341
|
+
const text = inputText.get(chunk.toolCallId) || (chunk.type === "tool-input-error" && typeof chunk.input === "string" ? chunk.input : JSON.stringify(chunk.input));
|
|
324
342
|
if (inputText.has(chunk.toolCallId)) parts.push({
|
|
325
343
|
type: "tool-input-end",
|
|
326
344
|
id: chunk.toolCallId
|
|
327
345
|
});
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
toolCallId: chunk.toolCallId,
|
|
331
|
-
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({
|
|
346
|
+
const input = parseJson(text);
|
|
347
|
+
if (input !== void 0) toolCalls.push({
|
|
341
348
|
toolCallId: chunk.toolCallId,
|
|
342
349
|
toolName: chunk.toolName,
|
|
343
|
-
input
|
|
350
|
+
input
|
|
344
351
|
});
|
|
345
352
|
parts.push({
|
|
346
353
|
type: "tool-call",
|
|
347
354
|
toolCallId: chunk.toolCallId,
|
|
348
355
|
toolName: chunk.toolName,
|
|
349
|
-
input:
|
|
356
|
+
input: text,
|
|
350
357
|
...metadata
|
|
351
358
|
});
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
352
361
|
}
|
|
353
362
|
}
|
|
354
363
|
parts.push({
|
|
@@ -386,7 +395,8 @@ function compactionSse(data) {
|
|
|
386
395
|
]);
|
|
387
396
|
}
|
|
388
397
|
/** Streams one live step response as UI chunks and reports its finish. */
|
|
389
|
-
async function streamStep(body, emit, finished) {
|
|
398
|
+
async function streamStep({ body, tools, emit, finished }) {
|
|
399
|
+
const streamed = /* @__PURE__ */ new Map();
|
|
390
400
|
for await (const part of sseParts(body)) {
|
|
391
401
|
const metadata = part["providerMetadata"] === void 0 ? {} : { providerMetadata: part["providerMetadata"] };
|
|
392
402
|
switch (part.type) {
|
|
@@ -410,6 +420,7 @@ async function streamStep(body, emit, finished) {
|
|
|
410
420
|
});
|
|
411
421
|
break;
|
|
412
422
|
case "tool-input-start":
|
|
423
|
+
streamed.set(part["id"], false);
|
|
413
424
|
emit({
|
|
414
425
|
type: "tool-input-start",
|
|
415
426
|
toolCallId: part["id"],
|
|
@@ -418,6 +429,7 @@ async function streamStep(body, emit, finished) {
|
|
|
418
429
|
});
|
|
419
430
|
break;
|
|
420
431
|
case "tool-input-delta":
|
|
432
|
+
if (part["delta"] !== "") streamed.set(part["id"], true);
|
|
421
433
|
emit({
|
|
422
434
|
type: "tool-input-delta",
|
|
423
435
|
toolCallId: part["id"],
|
|
@@ -425,25 +437,38 @@ async function streamStep(body, emit, finished) {
|
|
|
425
437
|
});
|
|
426
438
|
break;
|
|
427
439
|
case "tool-call": {
|
|
440
|
+
const toolCallId = part["toolCallId"];
|
|
441
|
+
const toolName = part["toolName"];
|
|
428
442
|
const text = part["input"];
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
443
|
+
if (streamed.get(toolCallId) !== true && text !== "") {
|
|
444
|
+
if (!streamed.has(toolCallId)) emit({
|
|
445
|
+
type: "tool-input-start",
|
|
446
|
+
toolCallId,
|
|
447
|
+
toolName
|
|
448
|
+
});
|
|
433
449
|
emit({
|
|
434
|
-
type: "tool-input-
|
|
435
|
-
toolCallId
|
|
436
|
-
|
|
437
|
-
input: text,
|
|
438
|
-
errorText: error instanceof Error ? error.message : String(error)
|
|
450
|
+
type: "tool-input-delta",
|
|
451
|
+
toolCallId,
|
|
452
|
+
inputTextDelta: text
|
|
439
453
|
});
|
|
440
|
-
break;
|
|
441
454
|
}
|
|
442
|
-
|
|
455
|
+
const input = await parseToolInput({
|
|
456
|
+
tools,
|
|
457
|
+
toolName,
|
|
458
|
+
text
|
|
459
|
+
});
|
|
460
|
+
emit(input.success ? {
|
|
443
461
|
type: "tool-input-available",
|
|
444
|
-
toolCallId
|
|
445
|
-
toolName
|
|
446
|
-
input,
|
|
462
|
+
toolCallId,
|
|
463
|
+
toolName,
|
|
464
|
+
input: input.value,
|
|
465
|
+
...metadata
|
|
466
|
+
} : {
|
|
467
|
+
type: "tool-input-error",
|
|
468
|
+
toolCallId,
|
|
469
|
+
toolName,
|
|
470
|
+
input: input.input,
|
|
471
|
+
errorText: input.errorText,
|
|
447
472
|
...metadata
|
|
448
473
|
});
|
|
449
474
|
break;
|
|
@@ -463,6 +488,32 @@ async function streamStep(body, emit, finished) {
|
|
|
463
488
|
}
|
|
464
489
|
}
|
|
465
490
|
}
|
|
491
|
+
/**
|
|
492
|
+
* A live call's input as the AI SDK step reads it: JSON, then the tool's
|
|
493
|
+
* schema with its defaults. Input that fails either is an input error, which
|
|
494
|
+
* A2 answers without running the tool.
|
|
495
|
+
*/
|
|
496
|
+
async function parseToolInput({ tools, toolName, text }) {
|
|
497
|
+
let value;
|
|
498
|
+
try {
|
|
499
|
+
value = JSON.parse(text);
|
|
500
|
+
} catch (error) {
|
|
501
|
+
return {
|
|
502
|
+
success: false,
|
|
503
|
+
input: text,
|
|
504
|
+
errorText: errorText(error)
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
const input = await schemaInput({
|
|
508
|
+
tools,
|
|
509
|
+
toolName,
|
|
510
|
+
value
|
|
511
|
+
});
|
|
512
|
+
return input.success ? input : {
|
|
513
|
+
...input,
|
|
514
|
+
input: value
|
|
515
|
+
};
|
|
516
|
+
}
|
|
466
517
|
async function readParts(body) {
|
|
467
518
|
const all = [];
|
|
468
519
|
for await (const part of sseParts(body)) all.push(part);
|
|
@@ -581,6 +632,13 @@ function decodeBody(body) {
|
|
|
581
632
|
if (body instanceof Uint8Array || body instanceof ArrayBuffer) return new TextDecoder().decode(body);
|
|
582
633
|
throw new TypeError("FX sent an unexpected request body");
|
|
583
634
|
}
|
|
635
|
+
function parseJson(text) {
|
|
636
|
+
try {
|
|
637
|
+
return JSON.parse(text);
|
|
638
|
+
} catch {
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
584
642
|
function sameJson(a, b) {
|
|
585
643
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
586
644
|
}
|
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, 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 { 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\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\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 // 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 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 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 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\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 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)\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 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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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "./ai-
|
|
1
|
+
import "./ai-BMLlI2Ff.js";
|
|
2
2
|
import { Experimental_SandboxSession, ToolSet, UIMessage, UIMessageChunk } from "ai";
|
|
3
3
|
//#region src/ai-harness.d.ts
|
|
4
4
|
declare const harnessBrand: unique symbol;
|
|
@@ -23,4 +23,4 @@ type HarnessSandboxContext = {
|
|
|
23
23
|
type HarnessSandbox = (context: HarnessSandboxContext) => Experimental_SandboxSession | Promise<Experimental_SandboxSession>;
|
|
24
24
|
//#endregion
|
|
25
25
|
export { HarnessSandbox as n, HarnessSandboxContext as r, Harness as t };
|
|
26
|
-
//# sourceMappingURL=ai-harness-
|
|
26
|
+
//# sourceMappingURL=ai-harness-B2suP2Qh.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-harness-
|
|
1
|
+
{"version":3,"file":"ai-harness-B2suP2Qh.d.ts","names":[],"sources":["../src/ai-harness.ts"],"mappings":";;;cAgBc;;;;;KAMF,QACV,wCACA;WAES,MAAM;YACL;aAA0B,OAAO;;;;KAIjC;EACV;aAAoB;;EACpB,QAAQ;;;KAIE,kBACV,SAAS,0BACN,8BAA8B,QAAQ"}
|
package/dist/ai-pi.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as HarnessSandbox, r as HarnessSandboxContext, t as Harness } from "./ai-harness-
|
|
1
|
+
import { n as HarnessSandbox, r as HarnessSandboxContext, t as Harness } from "./ai-harness-B2suP2Qh.js";
|
|
2
2
|
//#region src/ai-pi.d.ts
|
|
3
3
|
/** What `pi()` takes. */
|
|
4
4
|
type PiOptions = {
|
package/dist/ai-pi.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-pi.d.ts","names":[],"sources":["../src/ai-pi.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ai-pi.d.ts","names":[],"sources":["../src/ai-pi.ts"],"mappings":";;;KAyEY;;EAEV,SAAS;;;;;;iBAOK,GAAG,SAAS,YAAY,cAAc;cAuBhD;KACD,kBAAkB"}
|
package/dist/ai-pi.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { u as ambientToolScopeStorage } from "./internal-
|
|
1
|
+
import { u as ambientToolScopeStorage } from "./internal-CscSY7K_.js";
|
|
2
2
|
import { t as boundedCache } from "./bounded-cache-CPHWF-8h.js";
|
|
3
3
|
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";
|
|
4
|
+
import { t as schemaInput } from "./ai-tool-input-DmSqMUQi.js";
|
|
4
5
|
import { createHash } from "node:crypto";
|
|
5
6
|
import { asSchema, jsonSchema } from "ai";
|
|
6
7
|
import { readFile, unlink } from "node:fs/promises";
|
|
@@ -113,7 +114,7 @@ async function runStep(step, sandbox) {
|
|
|
113
114
|
});
|
|
114
115
|
const live = kind === "step" ? liveStep() : void 0;
|
|
115
116
|
for await (const event of upstream) {
|
|
116
|
-
live?.(event);
|
|
117
|
+
await live?.(event);
|
|
117
118
|
if (event.type === "done" || event.type === "error") {
|
|
118
119
|
const response = event.type === "done" ? event.message : event.error;
|
|
119
120
|
if (kind === "compaction") state.compactions.push(response);
|
|
@@ -125,11 +126,47 @@ async function runStep(step, sandbox) {
|
|
|
125
126
|
out.push(event);
|
|
126
127
|
}
|
|
127
128
|
};
|
|
129
|
+
/**
|
|
130
|
+
* A live call's input as Pi's loop, then the AI SDK step, read it. Pi
|
|
131
|
+
* answers a call to no tool, or whose arguments it cannot prepare or
|
|
132
|
+
* validate, itself. The agent's tool reads the arguments Pi accepts through
|
|
133
|
+
* its own schema; A2 runs Pi's own tools from the model's arguments, as
|
|
134
|
+
* Pi's loop does.
|
|
135
|
+
*/
|
|
136
|
+
const callInput = async (block) => {
|
|
137
|
+
const definition = tools.find((tool) => tool.name === block.name);
|
|
138
|
+
if (definition === void 0) return {
|
|
139
|
+
success: false,
|
|
140
|
+
errorText: `Tool ${block.name} not found`
|
|
141
|
+
};
|
|
142
|
+
let args;
|
|
143
|
+
try {
|
|
144
|
+
const prepared = definition.prepareArguments?.(block.arguments);
|
|
145
|
+
args = modules.ai.validateToolArguments(definition, prepared === void 0 ? block : {
|
|
146
|
+
...block,
|
|
147
|
+
arguments: prepared
|
|
148
|
+
});
|
|
149
|
+
} catch (error) {
|
|
150
|
+
return {
|
|
151
|
+
success: false,
|
|
152
|
+
errorText: asError(error).message
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (builtinOf(step.tools, block.name) !== void 0) return {
|
|
156
|
+
success: true,
|
|
157
|
+
value: block.arguments
|
|
158
|
+
};
|
|
159
|
+
return schemaInput({
|
|
160
|
+
tools: step.tools,
|
|
161
|
+
toolName: block.name,
|
|
162
|
+
value: args
|
|
163
|
+
});
|
|
164
|
+
};
|
|
128
165
|
/** Streams one live step response as UI chunks and records it. */
|
|
129
166
|
const liveStep = () => {
|
|
130
167
|
const ref = (index) => `pi:${step.requestIndex}:${index}`;
|
|
131
168
|
const started = /* @__PURE__ */ new Set();
|
|
132
|
-
return (event) => {
|
|
169
|
+
return async (event) => {
|
|
133
170
|
switch (event.type) {
|
|
134
171
|
case "start":
|
|
135
172
|
emit({ type: "start-step" });
|
|
@@ -194,6 +231,7 @@ async function runStep(step, sandbox) {
|
|
|
194
231
|
case "done":
|
|
195
232
|
case "error": {
|
|
196
233
|
const response = event.type === "done" ? event.message : event.error;
|
|
234
|
+
const changed = /* @__PURE__ */ new Set();
|
|
197
235
|
if (event.type === "done") for (const block of response.content) {
|
|
198
236
|
if (block.type !== "toolCall") continue;
|
|
199
237
|
if (!started.has(block.id)) emit({
|
|
@@ -201,22 +239,27 @@ async function runStep(step, sandbox) {
|
|
|
201
239
|
toolCallId: block.id,
|
|
202
240
|
toolName: block.name
|
|
203
241
|
});
|
|
204
|
-
|
|
205
|
-
|
|
242
|
+
const input = response.stopReason === "length" ? {
|
|
243
|
+
success: false,
|
|
244
|
+
errorText: "The response hit the output token limit before this call was complete."
|
|
245
|
+
} : await callInput(block);
|
|
246
|
+
if (input.success && JSON.stringify(input.value) !== JSON.stringify(block.arguments)) changed.add(block.id);
|
|
247
|
+
emit(input.success ? {
|
|
248
|
+
type: "tool-input-available",
|
|
206
249
|
toolCallId: block.id,
|
|
207
250
|
toolName: block.name,
|
|
208
|
-
input:
|
|
209
|
-
errorText: "The response hit the output token limit before this call was complete."
|
|
251
|
+
input: input.value
|
|
210
252
|
} : {
|
|
211
|
-
type: "tool-input-
|
|
253
|
+
type: "tool-input-error",
|
|
212
254
|
toolCallId: block.id,
|
|
213
255
|
toolName: block.name,
|
|
214
|
-
input: block.arguments
|
|
256
|
+
input: block.arguments,
|
|
257
|
+
errorText: input.errorText
|
|
215
258
|
});
|
|
216
259
|
}
|
|
217
260
|
record({
|
|
218
261
|
call: "step",
|
|
219
|
-
response: storedResponse(response, ref)
|
|
262
|
+
response: storedResponse(response, ref, changed)
|
|
220
263
|
});
|
|
221
264
|
completion = {
|
|
222
265
|
finishReason: finishReason(response.stopReason),
|
|
@@ -437,7 +480,7 @@ function recordedCalls(generation) {
|
|
|
437
480
|
if (!calls.some((call) => call.kind === "step")) throw diverged("a completed generation has no recorded response");
|
|
438
481
|
return calls;
|
|
439
482
|
}
|
|
440
|
-
function storedResponse(response, ref) {
|
|
483
|
+
function storedResponse(response, ref, changed) {
|
|
441
484
|
return {
|
|
442
485
|
...response,
|
|
443
486
|
content: response.content.map((block, index) => {
|
|
@@ -457,6 +500,7 @@ function storedResponse(response, ref) {
|
|
|
457
500
|
};
|
|
458
501
|
}
|
|
459
502
|
case "toolCall": {
|
|
503
|
+
if (changed.has(block.id)) return block;
|
|
460
504
|
const { arguments: _, ...rest } = block;
|
|
461
505
|
return rest;
|
|
462
506
|
}
|
|
@@ -470,7 +514,7 @@ function restoredResponse(stored, texts, inputs) {
|
|
|
470
514
|
content: stored.content.map((block) => {
|
|
471
515
|
if (block.type === "toolCall") return {
|
|
472
516
|
...block,
|
|
473
|
-
arguments: inputs.get(block.id) ?? {}
|
|
517
|
+
arguments: block.arguments ?? inputs.get(block.id) ?? {}
|
|
474
518
|
};
|
|
475
519
|
const { ref, ...rest } = block;
|
|
476
520
|
const text = texts.get(ref) ?? "";
|
|
@@ -606,6 +650,8 @@ async function recordedResult(result, sandbox) {
|
|
|
606
650
|
}
|
|
607
651
|
};
|
|
608
652
|
}
|
|
653
|
+
/** The Pi tool a name in the agent's tool set runs, unless the agent replaced it. */
|
|
654
|
+
const builtinOf = (tools, name) => BUILTINS.find((candidate) => candidate === name && Object.hasOwn(tools, name) && tools[name] === builtinTools[name]);
|
|
609
655
|
const untyped = (definition) => definition;
|
|
610
656
|
function builtinDefinition(modules, name, cwd, call) {
|
|
611
657
|
const sandbox = call?.sandbox;
|
|
@@ -626,7 +672,7 @@ function builtinDefinition(modules, name, cwd, call) {
|
|
|
626
672
|
*/
|
|
627
673
|
async function sessionTools(modules, tools, cwd, result) {
|
|
628
674
|
return Promise.all(Object.entries(tools).filter(([, tool]) => tool.type !== "provider").map(async ([name, tool]) => {
|
|
629
|
-
const builtin =
|
|
675
|
+
const builtin = builtinOf(tools, name);
|
|
630
676
|
if (builtin !== void 0) return Object.assign(builtinDefinition(modules, builtin, cwd), { execute: (toolCallId, _params, signal) => result(toolCallId, signal, "pi") });
|
|
631
677
|
return {
|
|
632
678
|
name,
|