experimental-a2 0.22.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.23.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 70c8e92: New `experimental-a2/store-valkey` entry point: `valkey({ url, clientOptions })` is the Redis store on node-redis connections, for Valkey and Redis servers that need TLS settings, rotating credentials such as ElastiCache IAM tokens, or your own reconnect and timeout policy. `clientOptions` takes node-redis `createClient` options, including an async `credentialsProvider`, and A2 creates one command client and one shared subscriber from them. After the subscriber reconnects, live streams read what they missed right away instead of waiting for the safety re-read, and a client whose reconnect strategy gave up is replaced on next use. Commands sent while a client connects follow node-redis's offline queue, `disableOfflineQueue`, and `commandOptions.timeout`. `redis` (node-redis 5.8 or later, or 6) is a new optional peer dependency.
8
+
9
+ ### Patch Changes
10
+
11
+ - fcdcb2e: Under `fx()`, a step that rebuilds its kernel and replays a response stopped during a model call now sends the model what a kept kernel sends. FX can read the request's abort before the stop and fail the turn without recording the interruption, while libfx still reports it as cancelled, so the next turn went out without the interruption notes. The step now reads FX's answer to each replayed turn and, when FX failed it, replays on a new kernel, at most three times before failing with a divergence error.
12
+ - 70c8e92: `redis()` and `redisHttp()` now retry the subscriber's readiness check on the next live stream or presence subscription when it fails, instead of failing every later live stream with the first error.
13
+
3
14
  ## 0.22.0
4
15
 
5
16
  ### Minor Changes
package/dist/ai-fx.js CHANGED
@@ -37,6 +37,8 @@ const SNAPSHOT_VERSION = 1;
37
37
  const CATALOG_TTL_MS = 36e5;
38
38
  /** The Gateway model catalog libfx reads for each new kernel. */
39
39
  const CATALOG_PATH = "/coding-agent/v1/models";
40
+ /** Times a step rebuilds its kernel for a stopped turn FX failed on replay. */
41
+ const REPLAY_REBUILDS = 3;
40
42
  function fail(state, error) {
41
43
  state.failure ??= error;
42
44
  state.fxTurn.cancel();
@@ -112,8 +114,12 @@ async function runStep(step, lot) {
112
114
  await resume(controller, turns.at(-1), adopted);
113
115
  return;
114
116
  }
115
- for (const plan of turns) {
117
+ let rebuilds = 0;
118
+ let next = 0;
119
+ while (next < turns.length) {
116
120
  if (stopped || step.signal.aborted) return;
121
+ const plan = turns[next];
122
+ next += 1;
117
123
  const fxTurn = kernel.agent.prompt(plan.prompt);
118
124
  const state = {
119
125
  plan,
@@ -138,6 +144,13 @@ async function runStep(step, lot) {
138
144
  if (state.failure) throw state.failure;
139
145
  const expected = plan.end === "stop" ? "end_turn" : "cancelled";
140
146
  if (result.stopReason !== expected) throw diverged(`a recorded turn ended with ${result.stopReason}, not ${expected}`);
147
+ if (kernel.failed) {
148
+ if (rebuilds === REPLAY_REBUILDS) throw diverged("FX failed a stopped turn instead of cancelling it");
149
+ rebuilds += 1;
150
+ await kernel.agent.close().catch(() => {});
151
+ kernel = await create(read.saved);
152
+ next = 0;
153
+ }
141
154
  continue;
142
155
  }
143
156
  await finishLive(controller, state, drained);
@@ -365,8 +378,10 @@ async function runStep(step, lot) {
365
378
  const create = async (checkpoint) => {
366
379
  const created = {
367
380
  hooks,
368
- waiting: []
381
+ waiting: [],
382
+ failed: false
369
383
  };
384
+ let prompt;
370
385
  const agent = await createFxAgent({
371
386
  apiKey: credential.token,
372
387
  model: kernelModel(step),
@@ -376,7 +391,14 @@ async function runStep(step, lot) {
376
391
  execute: (toolInput) => created.hooks.tool(definition.name, toolInput)
377
392
  })),
378
393
  ...checkpoint === void 0 ? {} : { checkpoint },
379
- fetch: (input, init) => created.hooks.fetch(input, init)
394
+ fetch: (input, init) => created.hooks.fetch(input, init),
395
+ onEvent: ({ type, message }) => {
396
+ const rpc = message ?? {};
397
+ if (type === "acp.send" && rpc.method === "session/prompt") {
398
+ prompt = rpc.id;
399
+ created.failed = false;
400
+ } else if (type === "acp.receive" && rpc.method === void 0 && rpc.id === prompt) created.failed = rpc.error !== void 0;
401
+ }
380
402
  });
381
403
  return Object.assign(created, { agent });
382
404
  };
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, FxPromptBlock, FxTurn } from 'libfx'\nimport {\n type Deferred,\n defineHarness,\n deferred,\n Divergence,\n gatewayCredential,\n type GatewayCredential,\n gatewaySessionAffinity,\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 { HARNESS_PARKING } from './internal.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 * unless this process holds the kernel the step before left waiting on its\n * tool calls.\n */\nexport function fx(): Harness<'fx', never> {\n // Per agent, as its saved states are: sessions of two agents never share one.\n const lots = new WeakMap<object, ParkingLot>()\n const lotOf = (scope: object): ParkingLot => {\n let lot = lots.get(scope)\n if (lot === undefined) {\n lot = parkingLot()\n lots.set(scope, lot)\n }\n return lot\n }\n return defineHarness('fx', {\n tools: {},\n step: (step) => runStep(step, lotOf(step.scope)),\n release: ({ scope, sessionId }) => {\n const entry = lots.get(scope)?.take(sessionId)\n if (entry !== undefined) closeParked(entry)\n },\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 /** The attempt that made its last committed model call. */\n generationId?: string\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\n/** A model request as the kernel sends it to the Gateway. */\ntype GatewayRequest = {\n toolChoice?: { type?: string }\n providerOptions?: Record<string, Record<string, unknown> | undefined>\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// ------------------------------------------------------------- kernels\n\n/** A tool call the kernel waits on while A2's tool consumer runs it. */\ntype Waiting = {\n toolName: string\n input: unknown\n resolve: (output: unknown) => void\n reject: (error: unknown) => void\n}\n\n/** What a kernel's fetch and tools call: the step driving it now. */\ntype KernelHooks = {\n fetch: (\n input: string | URL | Request,\n init?: RequestInit,\n ) => Promise<Response>\n tool: (toolName: string, input: unknown) => unknown\n}\n\ntype Kernel = { agent: FxAgent; hooks: KernelHooks; waiting: Waiting[] }\n\n/**\n * A kernel a step left waiting on its tool calls. The session's next step in\n * this process, in the same response or one that steered it, continues it\n * with their results instead of rebuilding one from the log.\n */\ntype Parked = {\n kernel: Kernel\n fxTurn: FxTurn\n drained: Promise<void>\n /** The attempt whose model call the kernel made. */\n generationId: string\n settings: string\n}\n\ntype ParkingLot = {\n /** Removes the session's parked kernel; the caller then owns it. */\n take(sessionId: string): Parked | undefined\n park(sessionId: string, entry: Parked): void\n}\n\nfunction closeParked(entry: Parked): void {\n entry.fxTurn.cancel()\n void entry.kernel.agent.close().catch(() => {})\n}\n\n/**\n * One agent's parked kernels: one per session, at most `maxKernels`. Each is\n * closed when its session has nothing left to run in this process (the\n * agent's release), when its turn ends, or when another takes its place.\n */\nfunction parkingLot(): ParkingLot {\n const held = new Map<string, Parked>()\n const take = (sessionId: string): Parked | undefined => {\n const entry = held.get(sessionId)\n held.delete(sessionId)\n return entry\n }\n return {\n take,\n park(sessionId, entry) {\n const replaced = take(sessionId)\n if (replaced !== undefined) closeParked(replaced)\n held.set(sessionId, entry)\n // A turn that ends while it waits, as a cancelled one does, is done.\n const ended = () => {\n if (held.get(sessionId) !== entry) return\n held.delete(sessionId)\n closeParked(entry)\n }\n entry.fxTurn.result.then(ended, ended)\n const oldest = held.keys().next().value\n if (held.size > HARNESS_PARKING.maxKernels && oldest !== undefined) {\n const evicted = take(oldest)\n if (evicted !== undefined) closeParked(evicted)\n }\n },\n }\n}\n\n// ---------------------------------------------------------------- step\n\nasync function runStep(\n step: HarnessStep,\n lot: ParkingLot,\n): Promise<HarnessGeneration> {\n const { createFxAgent } = await loadLibfx()\n const credential = gatewayCredential('fx')\n const name = `${step.agentName}.a2.harness.fx`\n const definitions = await toolDefinitions(step.tools)\n // What the kernel is made with: one made otherwise can't continue the step.\n const settings = JSON.stringify([\n kernelModel(step),\n step.instructions,\n definitions,\n ])\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 kernel: Kernel | undefined\n /** Whether this step left its kernel for the next one. */\n let parked = false\n let turn: TurnState | undefined\n\n const run = async (\n controller: ReadableStreamDefaultController<UIMessageChunk>,\n turns: TurnPlan[],\n adopted: Parked | undefined,\n ): Promise<void> => {\n controller.enqueue({ type: 'start', messageId: step.responseMessageId })\n if (adopted !== undefined) {\n await resume(controller, turns.at(-1)!, adopted)\n return\n }\n for (const plan of turns) {\n if (stopped || step.signal.aborted) return\n // The step's abort cancels the turn; the turn outlives it when parked.\n const fxTurn = kernel!.agent.prompt(plan.prompt)\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 await finishLive(controller, state, drained)\n }\n }\n\n /** Continues a parked kernel: the results it waits on are in the log. */\n const resume = async (\n controller: ReadableStreamDefaultController<UIMessageChunk>,\n plan: TurnPlan,\n adopted: Parked,\n ): Promise<void> => {\n const state: TurnState = {\n plan,\n fxTurn: adopted.fxTurn,\n next: plan.calls.length,\n served: plan.calls.at(-1)!.toolCalls,\n answered: new Set(),\n live: false,\n liveStep: false,\n toolsRequested: deferred(),\n }\n turn = state\n // Steering goes in before any tool result, so FX's next model call can't\n // start without it, as replay queues it before the recorded call ends.\n for (const text of plan.steers.get(plan.calls.length - 1) ?? [])\n await adopted.fxTurn.steer(text)\n for (const waiting of kernel!.waiting.splice(0)) {\n try {\n const answered = answer(state, waiting.toolName, waiting.input)\n if (answered === undefined)\n fail(state, diverged(`no recorded result for ${waiting.toolName}`))\n waiting.resolve(answered.output)\n } catch (error) {\n waiting.reject(error)\n }\n }\n await finishLive(controller, state, adopted.drained)\n }\n\n const finishLive = async (\n controller: ReadableStreamDefaultController<UIMessageChunk>,\n state: TurnState,\n drained: Promise<void>,\n ): Promise<void> => {\n const outcome = await Promise.race([\n state.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 if (\n outcome.result.stopReason === 'cancelled' &&\n !stopped &&\n !step.signal.aborted\n )\n throw diverged('the turn was cancelled while this step ran it')\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 if (kernel!.waiting.length > 0 && !stopped && !closed) {\n // FX now waits on tools that A2's tool consumer runs; the next step in\n // this process can answer it with their results.\n lot.park(step.sessionId, {\n kernel: kernel!,\n fxTurn: state.fxTurn,\n drained,\n generationId: step.generationId,\n settings,\n })\n parked = true\n } else {\n state.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 * Whether a parked kernel stands where this step's log does: made the same\n * way, its model call the last one the log's live turn committed, and a\n * recorded result for each tool call it waits on. A steered response\n * continues the same turn, so its steps qualify too.\n */\n const adoptable = (entry: Parked, turns: TurnPlan[]): boolean => {\n const plan = turns.at(-1)\n if (\n entry.settings !== settings ||\n plan?.end !== 'live' ||\n plan.generationId !== entry.generationId\n )\n return false\n const unanswered = [...(plan.calls.at(-1)?.toolCalls ?? [])]\n return entry.kernel.waiting.every((waiting) => {\n const at = unanswered.findIndex(\n (call) =>\n call.toolName === waiting.toolName &&\n sameJson(call.input, waiting.input) &&\n results.has(call.toolCallId),\n )\n if (at === -1) return false\n unanswered.splice(at, 1)\n return true\n })\n }\n\n const saveCheckpoint = async (): Promise<void> => {\n let checkpoint: Uint8Array\n try {\n checkpoint = await kernel!.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 request = JSON.parse(body) as GatewayRequest\n const compaction = request.toolChoice?.type === 'none'\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(\n state,\n url,\n { ...init, body: withGatewayCaching(body, request) },\n compaction,\n )\n }\n\n const affinity = gatewaySessionAffinity({\n agentName: step.agentName,\n sessionId: step.sessionId,\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 headers = withAuth(init.headers, credential)\n // The kernel's own affinity is new with every rebuild; A2's lasts the session.\n headers.set('x-session-affinity', affinity)\n const response = await fetch(url, { ...init, headers, signal: network })\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 /** The recorded result of a call from the step the kernel was served. */\n const answer = (\n state: TurnState,\n toolName: string,\n toolInput: unknown,\n ): { output: unknown } | undefined => {\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) return 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 { output: result.output ?? null }\n }\n\n const hostTool = (toolName: string, toolInput: unknown): unknown => {\n const state = turn!\n if (state.failure) throw state.failure\n const answered = answer(state, toolName, toolInput)\n if (answered !== undefined) return answered.output\n if (state.live) {\n state.toolsRequested.resolve()\n return new Promise((resolve, reject) => {\n kernel!.waiting.push({ toolName, input: toolInput, resolve, reject })\n })\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 hooks: KernelHooks = { fetch: hostFetch, tool: hostTool }\n const planTurns = (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 = async (\n checkpoint: Uint8Array | undefined,\n ): Promise<Kernel> => {\n const created = { hooks, waiting: [] as Waiting[] }\n const agent = await createFxAgent({\n apiKey: credential.token,\n model: kernelModel(step),\n ...(step.instructions.length === 0\n ? {}\n : { instructions: step.instructions }),\n tools: definitions.map((definition): FxHostTool => ({\n ...definition,\n execute: (toolInput: unknown) =>\n created.hooks.tool(definition.name, toolInput),\n })),\n ...(checkpoint === undefined ? {} : { checkpoint }),\n fetch: (input, init) => created.hooks.fetch(input, init),\n })\n return Object.assign(created, { agent })\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 let turns = await planTurns(read.turns)\n // An aborted step leaves a parked kernel for a later attempt.\n const candidate = step.signal.aborted\n ? undefined\n : lot.take(step.sessionId)\n const adopted =\n candidate !== undefined && adoptable(candidate, turns)\n ? candidate\n : undefined\n if (candidate !== undefined && adopted === undefined)\n closeParked(candidate)\n if (adopted !== undefined) {\n kernel = adopted.kernel\n kernel.hooks = hooks\n } else {\n try {\n kernel = 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 kernel = await create(undefined)\n turns = await planTurns(read.turns)\n }\n }\n await run(streamController, turns, adopted)\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 if (!parked) await kernel?.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 turn.generations.forEach((generation, index) => {\n calls.push(...recordedCalls(generation.chunks, generation.completed))\n const inputs = turn.steers.get(index)\n // A generation's step is its last call.\n if (inputs !== undefined)\n steers.set(calls.length - 1, inputs.map(steerText))\n })\n const images = await harnessImages({\n harness: 'fx()',\n input: turn.prompt,\n signal,\n })\n const generationId = turn.generations.at(-1)?.completed.generationId\n return {\n ...(generationId === undefined ? {} : { generationId }),\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\n/**\n * A model request with Gateway's automatic caching, as the AI SDK harness\n * asks for it; options the request already has take precedence. Every other\n * byte stays as the kernel wrote it, a tool input's spacing included.\n */\nfunction withGatewayCaching(body: string, request: GatewayRequest): string {\n const options = request.providerOptions\n if (options === undefined)\n return body.replace(\n /^\\{/,\n '{\"providerOptions\":{\"gateway\":{\"caching\":\"auto\"}},',\n )\n // The kernel writes its own options last; any other shape goes unchanged.\n const own = `\"providerOptions\":${JSON.stringify(options)}}`\n if (!body.endsWith(own)) return body\n const merged = {\n ...options,\n gateway: { caching: 'auto', ...options['gateway'] },\n }\n return `${body.slice(0, -own.length)}\"providerOptions\":${JSON.stringify(merged)}}`\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 // A parked kernel keeps the credential it was made with; the step's is current.\n if (result.has('authorization'))\n result.set('authorization', `Bearer ${credential.token}`)\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\n/** The agent's tools as the kernel takes them, without their execution. */\nasync function toolDefinitions(\n tools: ToolSet,\n): Promise<{ name: string; description: string; inputSchema: object }[]> {\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 })),\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 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
+ {"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 gatewaySessionAffinity,\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 { HARNESS_PARKING } from './internal.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 * unless this process holds the kernel the step before left waiting on its\n * tool calls.\n */\nexport function fx(): Harness<'fx', never> {\n // Per agent, as its saved states are: sessions of two agents never share one.\n const lots = new WeakMap<object, ParkingLot>()\n const lotOf = (scope: object): ParkingLot => {\n let lot = lots.get(scope)\n if (lot === undefined) {\n lot = parkingLot()\n lots.set(scope, lot)\n }\n return lot\n }\n return defineHarness('fx', {\n tools: {},\n step: (step) => runStep(step, lotOf(step.scope)),\n release: ({ scope, sessionId }) => {\n const entry = lots.get(scope)?.take(sessionId)\n if (entry !== undefined) closeParked(entry)\n },\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/** Times a step rebuilds its kernel for a stopped turn FX failed on replay. */\nconst REPLAY_REBUILDS = 3\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 /** The attempt that made its last committed model call. */\n generationId?: string\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\n/** A model request as the kernel sends it to the Gateway. */\ntype GatewayRequest = {\n toolChoice?: { type?: string }\n providerOptions?: Record<string, Record<string, unknown> | undefined>\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// ------------------------------------------------------------- kernels\n\n/** A tool call the kernel waits on while A2's tool consumer runs it. */\ntype Waiting = {\n toolName: string\n input: unknown\n resolve: (output: unknown) => void\n reject: (error: unknown) => void\n}\n\n/** What a kernel's fetch and tools call: the step driving it now. */\ntype KernelHooks = {\n fetch: (\n input: string | URL | Request,\n init?: RequestInit,\n ) => Promise<Response>\n tool: (toolName: string, input: unknown) => unknown\n}\n\ntype Kernel = {\n agent: FxAgent\n hooks: KernelHooks\n waiting: Waiting[]\n /** Whether FX answered the kernel's latest prompt with an error. */\n failed: boolean\n}\n\n/**\n * A kernel a step left waiting on its tool calls. The session's next step in\n * this process, in the same response or one that steered it, continues it\n * with their results instead of rebuilding one from the log.\n */\ntype Parked = {\n kernel: Kernel\n fxTurn: FxTurn\n drained: Promise<void>\n /** The attempt whose model call the kernel made. */\n generationId: string\n settings: string\n}\n\ntype ParkingLot = {\n /** Removes the session's parked kernel; the caller then owns it. */\n take(sessionId: string): Parked | undefined\n park(sessionId: string, entry: Parked): void\n}\n\nfunction closeParked(entry: Parked): void {\n entry.fxTurn.cancel()\n void entry.kernel.agent.close().catch(() => {})\n}\n\n/**\n * One agent's parked kernels: one per session, at most `maxKernels`. Each is\n * closed when its session has nothing left to run in this process (the\n * agent's release), when its turn ends, or when another takes its place.\n */\nfunction parkingLot(): ParkingLot {\n const held = new Map<string, Parked>()\n const take = (sessionId: string): Parked | undefined => {\n const entry = held.get(sessionId)\n held.delete(sessionId)\n return entry\n }\n return {\n take,\n park(sessionId, entry) {\n const replaced = take(sessionId)\n if (replaced !== undefined) closeParked(replaced)\n held.set(sessionId, entry)\n // A turn that ends while it waits, as a cancelled one does, is done.\n const ended = () => {\n if (held.get(sessionId) !== entry) return\n held.delete(sessionId)\n closeParked(entry)\n }\n entry.fxTurn.result.then(ended, ended)\n const oldest = held.keys().next().value\n if (held.size > HARNESS_PARKING.maxKernels && oldest !== undefined) {\n const evicted = take(oldest)\n if (evicted !== undefined) closeParked(evicted)\n }\n },\n }\n}\n\n// ---------------------------------------------------------------- step\n\nasync function runStep(\n step: HarnessStep,\n lot: ParkingLot,\n): Promise<HarnessGeneration> {\n const { createFxAgent } = await loadLibfx()\n const credential = gatewayCredential('fx')\n const name = `${step.agentName}.a2.harness.fx`\n const definitions = await toolDefinitions(step.tools)\n // What the kernel is made with: one made otherwise can't continue the step.\n const settings = JSON.stringify([\n kernelModel(step),\n step.instructions,\n definitions,\n ])\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 kernel: Kernel | undefined\n /** Whether this step left its kernel for the next one. */\n let parked = false\n let turn: TurnState | undefined\n\n const run = async (\n controller: ReadableStreamDefaultController<UIMessageChunk>,\n turns: TurnPlan[],\n adopted: Parked | undefined,\n ): Promise<void> => {\n controller.enqueue({ type: 'start', messageId: step.responseMessageId })\n if (adopted !== undefined) {\n await resume(controller, turns.at(-1)!, adopted)\n return\n }\n let rebuilds = 0\n let next = 0\n while (next < turns.length) {\n if (stopped || step.signal.aborted) return\n const plan = turns[next]!\n next += 1\n // The step's abort cancels the turn; the turn outlives it when parked.\n const fxTurn = kernel!.agent.prompt(plan.prompt)\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 if (kernel!.failed) {\n // libfx's cancel aborts the request FX waits on as it sends the\n // stop, and FX fails the turn when it reads the abort first. That\n // kernel holds no interruption where the log has one, so the turns\n // replay on a new kernel.\n if (rebuilds === REPLAY_REBUILDS)\n throw diverged('FX failed a stopped turn instead of cancelling it')\n rebuilds += 1\n await kernel!.agent.close().catch(() => {})\n kernel = await create(read.saved)\n next = 0\n }\n continue\n }\n await finishLive(controller, state, drained)\n }\n }\n\n /** Continues a parked kernel: the results it waits on are in the log. */\n const resume = async (\n controller: ReadableStreamDefaultController<UIMessageChunk>,\n plan: TurnPlan,\n adopted: Parked,\n ): Promise<void> => {\n const state: TurnState = {\n plan,\n fxTurn: adopted.fxTurn,\n next: plan.calls.length,\n served: plan.calls.at(-1)!.toolCalls,\n answered: new Set(),\n live: false,\n liveStep: false,\n toolsRequested: deferred(),\n }\n turn = state\n // Steering goes in before any tool result, so FX's next model call can't\n // start without it, as replay queues it before the recorded call ends.\n for (const text of plan.steers.get(plan.calls.length - 1) ?? [])\n await adopted.fxTurn.steer(text)\n for (const waiting of kernel!.waiting.splice(0)) {\n try {\n const answered = answer(state, waiting.toolName, waiting.input)\n if (answered === undefined)\n fail(state, diverged(`no recorded result for ${waiting.toolName}`))\n waiting.resolve(answered.output)\n } catch (error) {\n waiting.reject(error)\n }\n }\n await finishLive(controller, state, adopted.drained)\n }\n\n const finishLive = async (\n controller: ReadableStreamDefaultController<UIMessageChunk>,\n state: TurnState,\n drained: Promise<void>,\n ): Promise<void> => {\n const outcome = await Promise.race([\n state.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 if (\n outcome.result.stopReason === 'cancelled' &&\n !stopped &&\n !step.signal.aborted\n )\n throw diverged('the turn was cancelled while this step ran it')\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 if (kernel!.waiting.length > 0 && !stopped && !closed) {\n // FX now waits on tools that A2's tool consumer runs; the next step in\n // this process can answer it with their results.\n lot.park(step.sessionId, {\n kernel: kernel!,\n fxTurn: state.fxTurn,\n drained,\n generationId: step.generationId,\n settings,\n })\n parked = true\n } else {\n state.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 * Whether a parked kernel stands where this step's log does: made the same\n * way, its model call the last one the log's live turn committed, and a\n * recorded result for each tool call it waits on. A steered response\n * continues the same turn, so its steps qualify too.\n */\n const adoptable = (entry: Parked, turns: TurnPlan[]): boolean => {\n const plan = turns.at(-1)\n if (\n entry.settings !== settings ||\n plan?.end !== 'live' ||\n plan.generationId !== entry.generationId\n )\n return false\n const unanswered = [...(plan.calls.at(-1)?.toolCalls ?? [])]\n return entry.kernel.waiting.every((waiting) => {\n const at = unanswered.findIndex(\n (call) =>\n call.toolName === waiting.toolName &&\n sameJson(call.input, waiting.input) &&\n results.has(call.toolCallId),\n )\n if (at === -1) return false\n unanswered.splice(at, 1)\n return true\n })\n }\n\n const saveCheckpoint = async (): Promise<void> => {\n let checkpoint: Uint8Array\n try {\n checkpoint = await kernel!.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 request = JSON.parse(body) as GatewayRequest\n const compaction = request.toolChoice?.type === 'none'\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(\n state,\n url,\n { ...init, body: withGatewayCaching(body, request) },\n compaction,\n )\n }\n\n const affinity = gatewaySessionAffinity({\n agentName: step.agentName,\n sessionId: step.sessionId,\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 headers = withAuth(init.headers, credential)\n // The kernel's own affinity is new with every rebuild; A2's lasts the session.\n headers.set('x-session-affinity', affinity)\n const response = await fetch(url, { ...init, headers, signal: network })\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 /** The recorded result of a call from the step the kernel was served. */\n const answer = (\n state: TurnState,\n toolName: string,\n toolInput: unknown,\n ): { output: unknown } | undefined => {\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) return 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 { output: result.output ?? null }\n }\n\n const hostTool = (toolName: string, toolInput: unknown): unknown => {\n const state = turn!\n if (state.failure) throw state.failure\n const answered = answer(state, toolName, toolInput)\n if (answered !== undefined) return answered.output\n if (state.live) {\n state.toolsRequested.resolve()\n return new Promise((resolve, reject) => {\n kernel!.waiting.push({ toolName, input: toolInput, resolve, reject })\n })\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 hooks: KernelHooks = { fetch: hostFetch, tool: hostTool }\n const planTurns = (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 = async (\n checkpoint: Uint8Array | undefined,\n ): Promise<Kernel> => {\n const created = { hooks, waiting: [] as Waiting[], failed: false }\n let prompt: unknown\n const agent = await createFxAgent({\n apiKey: credential.token,\n model: kernelModel(step),\n ...(step.instructions.length === 0\n ? {}\n : { instructions: step.instructions }),\n tools: definitions.map((definition): FxHostTool => ({\n ...definition,\n execute: (toolInput: unknown) =>\n created.hooks.tool(definition.name, toolInput),\n })),\n ...(checkpoint === undefined ? {} : { checkpoint }),\n fetch: (input, init) => created.hooks.fetch(input, init),\n // libfx reports a turn FX failed after its cancel as cancelled; only\n // the ACP response to the turn's prompt tells the two apart.\n onEvent: ({ type, message }) => {\n const rpc = (message ?? {}) as {\n id?: unknown\n method?: unknown\n error?: unknown\n }\n if (type === 'acp.send' && rpc.method === 'session/prompt') {\n prompt = rpc.id\n created.failed = false\n } else if (\n type === 'acp.receive' &&\n rpc.method === undefined &&\n rpc.id === prompt\n )\n created.failed = rpc.error !== undefined\n },\n })\n return Object.assign(created, { agent })\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 let turns = await planTurns(read.turns)\n // An aborted step leaves a parked kernel for a later attempt.\n const candidate = step.signal.aborted\n ? undefined\n : lot.take(step.sessionId)\n const adopted =\n candidate !== undefined && adoptable(candidate, turns)\n ? candidate\n : undefined\n if (candidate !== undefined && adopted === undefined)\n closeParked(candidate)\n if (adopted !== undefined) {\n kernel = adopted.kernel\n kernel.hooks = hooks\n } else {\n try {\n kernel = 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 kernel = await create(undefined)\n turns = await planTurns(read.turns)\n }\n }\n await run(streamController, turns, adopted)\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 if (!parked) await kernel?.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 turn.generations.forEach((generation, index) => {\n calls.push(...recordedCalls(generation.chunks, generation.completed))\n const inputs = turn.steers.get(index)\n // A generation's step is its last call.\n if (inputs !== undefined)\n steers.set(calls.length - 1, inputs.map(steerText))\n })\n const images = await harnessImages({\n harness: 'fx()',\n input: turn.prompt,\n signal,\n })\n const generationId = turn.generations.at(-1)?.completed.generationId\n return {\n ...(generationId === undefined ? {} : { generationId }),\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\n/**\n * A model request with Gateway's automatic caching, as the AI SDK harness\n * asks for it; options the request already has take precedence. Every other\n * byte stays as the kernel wrote it, a tool input's spacing included.\n */\nfunction withGatewayCaching(body: string, request: GatewayRequest): string {\n const options = request.providerOptions\n if (options === undefined)\n return body.replace(\n /^\\{/,\n '{\"providerOptions\":{\"gateway\":{\"caching\":\"auto\"}},',\n )\n // The kernel writes its own options last; any other shape goes unchanged.\n const own = `\"providerOptions\":${JSON.stringify(options)}}`\n if (!body.endsWith(own)) return body\n const merged = {\n ...options,\n gateway: { caching: 'auto', ...options['gateway'] },\n }\n return `${body.slice(0, -own.length)}\"providerOptions\":${JSON.stringify(merged)}}`\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 // A parked kernel keeps the credential it was made with; the step's is current.\n if (result.has('authorization'))\n result.set('authorization', `Bearer ${credential.token}`)\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\n/** The agent's tools as the kernel takes them, without their execution. */\nasync function toolDefinitions(\n tools: ToolSet,\n): Promise<{ name: string; description: string; inputSchema: object }[]> {\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 })),\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 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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"}
@@ -2,7 +2,7 @@ import { i as A2Error } from "./session-clear-wHd5GCpZ.js";
2
2
  import { i as NOTIFY_TIMINGS } from "./internal-CvsrprnU.js";
3
3
  import { t as defaultSleep } from "./store-polling-BZt2Rf3D.js";
4
4
  import { n as SYSTEM_CLOCK, t as RANDOM_IDS } from "./store-N8PXxDAS.js";
5
- import { t as createRedisNotifyStore } from "./store-redis-notify-CsJw_hfD.js";
5
+ import { t as createRedisNotifyStore } from "./store-redis-notify-CBDVJxA_.js";
6
6
  //#region src/redis-http-subscriptions.ts
7
7
  function redisHttpSubscriptions({ url, token, onReconnect, fallback }) {
8
8
  const subscriptions = /* @__PURE__ */ new Map();
@@ -2673,11 +2673,16 @@ function createRedisNotifyStore(options) {
2673
2673
  */
2674
2674
  let subscriberGate = null;
2675
2675
  const gatedSubscriber = () => {
2676
- subscriberGate ??= getSubscriber().then(async (conn) => {
2676
+ if (subscriberGate) return subscriberGate;
2677
+ const gate = getSubscriber().then(async (conn) => {
2677
2678
  await conn.call("echo", "ready");
2678
2679
  return conn;
2679
2680
  });
2680
- return subscriberGate;
2681
+ subscriberGate = gate;
2682
+ gate.catch(() => {
2683
+ if (subscriberGate === gate) subscriberGate = null;
2684
+ });
2685
+ return gate;
2681
2686
  };
2682
2687
  const acquireChannel = async (channel) => {
2683
2688
  const existing = subscriptions.get(channel);
@@ -3057,4 +3062,4 @@ function createRedisNotifyStore(options) {
3057
3062
  //#endregion
3058
3063
  export { createRedisNotifyStore as t };
3059
3064
 
3060
- //# sourceMappingURL=store-redis-notify-CsJw_hfD.js.map
3065
+ //# sourceMappingURL=store-redis-notify-CBDVJxA_.js.map