@tanstack/ai 0.63.0 → 0.64.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/dist/esm/activities/chat/agents/spawn.js +2 -28
- package/dist/esm/activities/chat/agents/spawn.js.map +1 -1
- package/dist/esm/activities/chat/index.d.ts +2 -0
- package/dist/esm/activities/chat/index.js +10 -3
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js +13 -4
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.js +4 -1
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.d.ts +8 -0
- package/dist/esm/activities/chat/tools/schema-converter.js +6 -5
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +5 -2
- package/dist/esm/activities/chat/tools/tool-calls.js +73 -22
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/generateSpeech/index.d.ts +1 -1
- package/dist/esm/activities/generateSpeech/index.js +1 -1
- package/dist/esm/activities/generateSpeech/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/adapter.d.ts +14 -6
- package/dist/esm/activities/generateVideo/adapter.js +6 -3
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.d.ts +5 -4
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/snap.d.ts +12 -3
- package/dist/esm/activities/generateVideo/snap.js +47 -8
- package/dist/esm/activities/generateVideo/snap.js.map +1 -1
- package/dist/esm/activities/generateVoice/index.d.ts +1 -1
- package/dist/esm/activities/generateVoice/index.js +1 -1
- package/dist/esm/activities/generateVoice/index.js.map +1 -1
- package/dist/esm/activities/index.d.ts +2 -2
- package/dist/esm/activities/index.js +2 -2
- package/dist/esm/adapter-internals.d.ts +1 -0
- package/dist/esm/adapter-internals.js +2 -1
- package/dist/esm/types.d.ts +28 -3
- package/dist/esm/utilities/ag-ui-wire.js +3 -1
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/merge-streams.d.ts +6 -0
- package/dist/esm/utilities/merge-streams.js +37 -0
- package/dist/esm/utilities/merge-streams.js.map +1 -0
- package/dist/esm/utilities/reasoning-encrypted-value.d.ts +8 -0
- package/dist/esm/utilities/reasoning-encrypted-value.js +11 -1
- package/dist/esm/utilities/reasoning-encrypted-value.js.map +1 -1
- package/package.json +1 -1
- package/skills/ai-core/media-generation/SKILL.md +3 -3
- package/src/activities/chat/agents/spawn.ts +2 -31
- package/src/activities/chat/index.ts +13 -3
- package/src/activities/chat/messages.ts +14 -2
- package/src/activities/chat/stream/message-updaters.ts +5 -0
- package/src/activities/chat/tools/schema-converter.ts +17 -5
- package/src/activities/chat/tools/tool-calls.ts +121 -63
- package/src/activities/generateSpeech/index.ts +1 -1
- package/src/activities/generateVideo/adapter.ts +21 -7
- package/src/activities/generateVideo/index.ts +5 -4
- package/src/activities/generateVideo/snap.ts +64 -6
- package/src/activities/generateVoice/index.ts +1 -1
- package/src/activities/index.ts +2 -1
- package/src/adapter-internals.ts +1 -0
- package/src/types.ts +28 -4
- package/src/utilities/ag-ui-wire.ts +5 -1
- package/src/utilities/merge-streams.ts +34 -0
- package/src/utilities/reasoning-encrypted-value.ts +12 -0
|
@@ -2,6 +2,7 @@ import { EventType } from "../../../types.js";
|
|
|
2
2
|
import { addTokenUsage, isTanstackUsage, rebuildTokenUsage, toSpecTokenUsage } from "../../../utilities/ag-ui-usage.js";
|
|
3
3
|
import { tanstackMetadata, withTanstackMetadata } from "../../../utilities/merge-metadata.js";
|
|
4
4
|
import { INTERRUPT_BINDING_METADATA_KEY } from "../../../interrupt-resume.js";
|
|
5
|
+
import { mergeStreams } from "../../../utilities/merge-streams.js";
|
|
5
6
|
import { EMIT_STREAM_CHUNK, SUBAGENT_TOOL } from "../tools/tool-calls.js";
|
|
6
7
|
//#region src/activities/chat/agents/spawn.ts
|
|
7
8
|
var SUBAGENT_STARTED = EventType.SUBAGENT_STARTED;
|
|
@@ -309,33 +310,6 @@ async function* spawnAgentStream(agent, ctx, sink, parentToolCallId) {
|
|
|
309
310
|
} catch {}
|
|
310
311
|
}
|
|
311
312
|
}
|
|
312
|
-
async function* mergeAgentStreams(streams) {
|
|
313
|
-
const readers = streams.map((stream) => {
|
|
314
|
-
const iterator = stream[Symbol.asyncIterator]();
|
|
315
|
-
return {
|
|
316
|
-
iterator,
|
|
317
|
-
next: iterator.next()
|
|
318
|
-
};
|
|
319
|
-
});
|
|
320
|
-
try {
|
|
321
|
-
while (readers.length > 0) {
|
|
322
|
-
const indexed = readers.map((reader, index) => reader.next.then((result) => ({
|
|
323
|
-
index,
|
|
324
|
-
result,
|
|
325
|
-
reader
|
|
326
|
-
})));
|
|
327
|
-
const winner = await Promise.race(indexed);
|
|
328
|
-
if (winner.result.done) {
|
|
329
|
-
readers.splice(winner.index, 1);
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
332
|
-
yield winner.result.value;
|
|
333
|
-
winner.reader.next = winner.reader.iterator.next();
|
|
334
|
-
}
|
|
335
|
-
} finally {
|
|
336
|
-
for (const reader of readers) reader.iterator.return?.().catch(() => {});
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
313
|
/** True when a child in these chunks failed or stopped for outside input. */
|
|
340
314
|
function stopsSequence(chunks, id) {
|
|
341
315
|
return chunks.some((chunk) => chunk.type === SUBAGENT_ERROR && chunk.subagentRunId === id || chunk.type === SUBAGENT_FINISHED && chunk.subagentRunId === id && chunk.outcome?.type === "suspended");
|
|
@@ -376,7 +350,7 @@ async function* spawnNamedAgents(entries, bag, ctx, sink) {
|
|
|
376
350
|
yield* onlyStream;
|
|
377
351
|
return;
|
|
378
352
|
}
|
|
379
|
-
yield*
|
|
353
|
+
yield* mergeStreams(streams);
|
|
380
354
|
} finally {
|
|
381
355
|
group.controller.abort();
|
|
382
356
|
group.dispose();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn.js","names":[],"sources":["../../../../../src/activities/chat/agents/spawn.ts"],"sourcesContent":["import { EventType } from '../../../types'\nimport {\n addTokenUsage,\n isTanstackUsage,\n rebuildTokenUsage,\n toSpecTokenUsage,\n} from '../../../utilities/ag-ui-usage'\nimport {\n tanstackMetadata,\n withTanstackMetadata,\n} from '../../../utilities/merge-metadata'\nimport { INTERRUPT_BINDING_METADATA_KEY } from '../../../interrupt-resume'\nimport { EMIT_STREAM_CHUNK, SUBAGENT_TOOL } from '../tools/tool-calls'\nimport type { SubagentToolOutcome } from '../tools/tool-calls'\nimport type { SpecTokenUsage } from '../../../utilities/ag-ui-usage'\nimport type {\n Interrupt,\n ModelMessage,\n RunAgentResumeItem,\n StreamChunk,\n SubagentErrorEvent,\n SubagentFinishedEvent,\n SubagentStartedEvent,\n TokenUsage,\n Tool,\n UIMessage,\n} from '../../../types'\nimport type { DefinedAgent, SubagentRunContext } from './define-agent'\nimport type { ChatMiddleware } from '../middleware/types'\nimport type { SubagentTurn } from './turn'\n\nexport const SUBAGENT_STARTED = EventType.SUBAGENT_STARTED\nexport const SUBAGENT_FINISHED = EventType.SUBAGENT_FINISHED\nexport const SUBAGENT_ERROR = EventType.SUBAGENT_ERROR\n\nexport type SubagentOrder = 'parallel' | 'sequence'\n\nexport interface SubagentRouterPlan {\n names: ReadonlyArray<string>\n /** Overrides `subagents.order` for this turn. */\n order?: SubagentOrder\n}\n\nexport interface SubagentStep {\n names: ReadonlyArray<string>\n /** Overrides `subagents.order` for this step. */\n order?: SubagentOrder\n}\n\nexport interface SubagentStepsPlan {\n steps: ReadonlyArray<SubagentStep>\n}\n\nexport type SubagentRouterPick =\n | 'main'\n | string\n | ReadonlyArray<string>\n | SubagentRouterPlan\n | SubagentStepsPlan\n\nexport interface SubagentsBag<\n TAgents extends ReadonlyArray<DefinedAgent> = ReadonlyArray<DefinedAgent>,\n> {\n agents: TAgents\n router?: (ctx: {\n messages: SubagentRunContext['messages']\n agents: NoInfer<TAgents>\n abortSignal?: AbortSignal\n }) => SubagentRouterPick | Promise<SubagentRouterPick>\n strategy?: 'exclusive' | 'handoff'\n /**\n * How a router list runs. `parallel` starts every name together.\n * `sequence` runs each name after the previous one finishes, and passes\n * that child's text to the next child.\n */\n order?: 'parallel' | 'sequence'\n sandbox?: 'own' | 'inherit'\n}\n\n/** What the children of one parent run left behind for the parent terminal. */\nexport interface SubagentSink {\n interrupts: Array<Interrupt>\n /** One AG-UI entry per child model call. */\n usage: Array<SpecTokenUsage>\n /** Summed full usage of the children, including cost. */\n total?: TokenUsage\n}\n\nexport function createSubagentSink(): SubagentSink {\n return { interrupts: [], usage: [] }\n}\n\n/** One child to start, or a suspended child to continue. */\nexport interface SpawnEntry {\n name: string\n /** The checked tool input for an agent with `inputSchema`. */\n input?: unknown\n resume?: {\n subagentRunId: string\n /** The child's own messages from the interrupted run. */\n messages: Array<UIMessage | ModelMessage>\n entries: Array<RunAgentResumeItem>\n /** Text the child wrote before it stopped. */\n text: string\n }\n}\n\ninterface SpawnContext {\n messages: SubagentRunContext['messages']\n abortSignal?: AbortSignal\n threadId: string\n /** The parent chat run. */\n parentRunId: string\n /** The interrupted parent run, on a resume. */\n interruptedRunId?: string\n}\n\nexport function createSubagentId() {\n return `subagent-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\nfunction childRunId(parentRunId: string, subagentRunId: string) {\n return `${parentRunId}:${subagentRunId}`\n}\n\n/**\n * Bind child interrupts to the parent run. The client resumes the parent run,\n * so each binding must name that run. The resumed child then validates with\n * the parent's interrupted run id.\n */\nexport function rebindInterrupts(\n interrupts: ReadonlyArray<Interrupt>,\n runId: string,\n): Array<Interrupt> {\n return interrupts.map((interrupt) => {\n const binding = interrupt.metadata?.[INTERRUPT_BINDING_METADATA_KEY]\n if (typeof binding !== 'object' || binding === null) return interrupt\n return {\n ...interrupt,\n metadata: {\n ...interrupt.metadata,\n [INTERRUPT_BINDING_METADATA_KEY]: {\n ...binding,\n interruptedRunId: runId,\n generation: 0,\n },\n },\n }\n })\n}\n\nfunction createAbortError() {\n const error = new Error('Aborted')\n error.name = 'AbortError'\n return error\n}\n\nfunction isAbortError(error: unknown, signal?: AbortSignal) {\n if (signal?.aborted) return true\n return (\n error instanceof Error &&\n (error.name === 'AbortError' || error.message === 'Aborted')\n )\n}\n\nfunction stoppedEvent(subagentRunId: string) {\n return {\n type: SUBAGENT_ERROR,\n subagentRunId,\n message: 'Stopped',\n timestamp: Date.now(),\n } satisfies SubagentErrorEvent\n}\n\nfunction childThreadId(\n sandbox: SubagentsBag['sandbox'],\n parentThreadId: string,\n name: string,\n) {\n return sandbox === 'inherit' ? parentThreadId : `${parentThreadId}:${name}`\n}\n\nfunction linkAbort(parent?: AbortSignal) {\n const controller = new AbortController()\n if (!parent) return { controller, dispose: () => {} }\n if (parent.aborted) {\n controller.abort()\n return { controller, dispose: () => {} }\n }\n const onAbort = () => controller.abort()\n parent.addEventListener('abort', onAbort, { once: true })\n return {\n controller,\n dispose: () => parent.removeEventListener('abort', onAbort),\n }\n}\n\nfunction orAbort<T>(promise: Promise<T>, signal?: AbortSignal) {\n if (!signal) return promise\n if (signal.aborted) return Promise.reject(createAbortError())\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => reject(createAbortError())\n signal.addEventListener('abort', onAbort, { once: true })\n promise.then(\n (value) => {\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n },\n (error: unknown) => {\n signal.removeEventListener('abort', onAbort)\n reject(error)\n },\n )\n })\n}\n\nfunction agentByName(agents: ReadonlyArray<DefinedAgent>, name: string) {\n const agent = agents.find((entry) => entry.name === name)\n if (!agent) {\n throw new Error(`Unknown subagent: ${name}`)\n }\n return agent\n}\n\nfunction openAgentStream(\n entry: SpawnEntry,\n bag: SubagentsBag,\n ctx: SpawnContext,\n sink?: SubagentSink,\n parentToolCallId?: string,\n) {\n const agent = agentByName(bag.agents, entry.name)\n const resume = entry.resume\n const subagentRunId = resume?.subagentRunId ?? createSubagentId()\n // The parent binds child interrupts to its own run (see rebindInterrupts),\n // so the resumed child continues from the interrupted parent run id.\n if (resume !== undefined && ctx.interruptedRunId === undefined) {\n throw new Error(\n `Subagent \"${entry.name}\" has interrupt answers, but the run has no parentRunId. Pass the interrupted run id as parentRunId.`,\n )\n }\n const resumed =\n resume !== undefined\n ? {\n messages: [...ctx.messages, ...resume.messages],\n parentRunId: ctx.interruptedRunId,\n resume: resume.entries,\n }\n : undefined\n return spawnAgentStream(\n agent,\n {\n input: entry.input,\n messages: resumed?.messages ?? ctx.messages,\n ...(ctx.abortSignal ? { abortSignal: ctx.abortSignal } : {}),\n threadId: childThreadId(bag.sandbox, ctx.threadId, entry.name),\n runId: childRunId(ctx.parentRunId, subagentRunId),\n parentRunId: resumed?.parentRunId ?? ctx.parentRunId,\n subagentRunId,\n ...(resumed ? { resume: resumed.resume } : {}),\n },\n sink,\n parentToolCallId,\n )\n}\n\nconst ROUTER_PICK_ERROR =\n 'subagents.router must return main, a name, a list of names, { names, order }, or { steps }.'\n\nfunction assertOrder(order: SubagentOrder | undefined) {\n if (order !== undefined && order !== 'parallel' && order !== 'sequence') {\n throw new Error('subagents.router order must be parallel or sequence.')\n }\n}\n\nfunction normalizeNames(\n names: ReadonlyArray<string>,\n agents: ReadonlyArray<DefinedAgent>,\n): ReadonlyArray<string> {\n if (names.length === 0) throw new Error(ROUTER_PICK_ERROR)\n const hasMain = names.includes('main')\n if (hasMain && names.length > 1) {\n throw new Error('Do not mix main into a subagent list.')\n }\n if (hasMain) return ['main']\n for (const name of names) agentByName(agents, name)\n return [...names]\n}\n\nfunction isStringList(pick: SubagentRouterPick): pick is ReadonlyArray<string> {\n return Array.isArray(pick)\n}\n\nexport function normalizeRouterPick(\n pick: SubagentRouterPick,\n agents: ReadonlyArray<DefinedAgent>,\n): { steps: ReadonlyArray<SubagentStep> } {\n if (pick === 'main' || typeof pick === 'string') {\n return { steps: [{ names: normalizeNames([pick], agents) }] }\n }\n if (isStringList(pick)) {\n return { steps: [{ names: normalizeNames(pick, agents) }] }\n }\n if ('steps' in pick) {\n if (pick.steps.length === 0) throw new Error(ROUTER_PICK_ERROR)\n const steps = pick.steps.map((step) => {\n assertOrder(step.order)\n const names = normalizeNames(step.names, agents)\n return step.order === undefined ? { names } : { names, order: step.order }\n })\n const flat = steps.flatMap((step) => step.names)\n if (flat.includes('main') && flat.length > 1) {\n throw new Error('Do not mix main into a subagent list.')\n }\n return { steps }\n }\n assertOrder(pick.order)\n const names = normalizeNames(pick.names, agents)\n return {\n steps: [\n pick.order === undefined ? { names } : { names, order: pick.order },\n ],\n }\n}\n\n/**\n * Tag a child chunk with its subagent. A chunk that a nested child already\n * tagged keeps its own id, and a nested child's start names this child as\n * its parent.\n */\nfunction attributeChunk(\n chunk: StreamChunk,\n subagentRunId: string,\n): StreamChunk {\n if (chunk.type === SUBAGENT_STARTED) {\n return chunk.parentSubagentRunId !== undefined\n ? chunk\n : { ...chunk, parentSubagentRunId: subagentRunId }\n }\n if (chunk.type === SUBAGENT_FINISHED || chunk.type === SUBAGENT_ERROR) {\n return chunk\n }\n if ('subagentRunId' in chunk && typeof chunk.subagentRunId === 'string') {\n return chunk\n }\n // RUN_* and MESSAGES_SNAPSHOT never get here (spawnAgentStream drops them).\n // Everything else is tagged.\n return { ...chunk, subagentRunId } as StreamChunk\n}\n\nfunction runUsage(chunk: StreamChunk | undefined): Array<SpecTokenUsage> {\n if (chunk?.type !== EventType.RUN_FINISHED) return []\n if (Array.isArray(chunk.usage)) return chunk.usage\n return isTanstackUsage(chunk.usage) ? toSpecTokenUsage(chunk.usage).usage : []\n}\n\n/** The full usage of a run: token counts plus cost and the other fields. */\nfunction fullUsage(chunk: StreamChunk | undefined): TokenUsage | undefined {\n if (chunk?.type !== EventType.RUN_FINISHED) return undefined\n return rebuildTokenUsage(chunk.usage, tanstackMetadata(chunk)?.usage)\n}\n\n/** Add a finished child run's usage to the sink. */\nexport function collectUsage(sink: SubagentSink, finished?: StreamChunk) {\n sink.usage.push(...runUsage(finished))\n const full = fullUsage(finished)\n if (full) sink.total = sink.total ? addTokenUsage(sink.total, full) : full\n}\n\n/** A parent run's last chunk: it completed, or it failed. */\ntype ParentTerminal = Extract<\n StreamChunk,\n { type: 'RUN_FINISHED' | 'RUN_ERROR' }\n>\n\n/**\n * Put the children's usage on a parent terminal. `usage[]` keeps one entry per\n * model call. `metadata.tanstack.usage` holds the summed cost and the other\n * TanStack fields, so `fromSpecTokenUsage` reads the full total. Empties the\n * sink, so the next parent terminal does not count it again.\n *\n * `RUN_ERROR` is accepted too: a turn that failed still spent whatever its\n * children spent. Such a chunk carries no usage of its own, so `runUsage` and\n * `fullUsage` return empty for it and the children's total stands alone.\n */\nexport function withChildUsage(\n chunk: ParentTerminal,\n sink: SubagentSink,\n): ParentTerminal {\n if (sink.usage.length === 0 && !sink.total) return chunk\n const own = fullUsage(chunk)\n const total =\n own && sink.total ? addTokenUsage(own, sink.total) : (own ?? sink.total)\n const usage = [...runUsage(chunk), ...sink.usage.splice(0)]\n sink.total = undefined\n const leftover = total ? toSpecTokenUsage(total).leftover : undefined\n const next = { ...chunk, usage }\n if (!leftover) return next\n // `withTanstackMetadata` runs the value through `Omit`, which collapses this\n // union and widens `type` back to `RUN_FINISHED | RUN_ERROR`. It only adds a\n // metadata key, so the runtime shape is the input's: restore that type.\n return withTanstackMetadata(next, { usage: leftover }) as ParentTerminal\n}\n\nexport async function* spawnAgentStream(\n agent: DefinedAgent,\n ctx: SubagentRunContext,\n sink?: SubagentSink,\n parentToolCallId?: string,\n): AsyncIterable<StreamChunk> {\n const id = ctx.subagentRunId\n yield {\n type: SUBAGENT_STARTED,\n subagentRunId: id,\n name: agent.name,\n description: agent.description,\n ...(ctx.parentSubagentRunId !== undefined\n ? { parentSubagentRunId: ctx.parentSubagentRunId }\n : {}),\n ...(parentToolCallId !== undefined ? { parentToolCallId } : {}),\n timestamp: Date.now(),\n } satisfies SubagentStartedEvent\n\n let iterator: AsyncIterator<StreamChunk> | undefined\n let finished: StreamChunk | undefined\n try {\n if (ctx.abortSignal?.aborted) {\n yield stoppedEvent(id)\n return\n }\n const stream = await orAbort(\n Promise.resolve(agent.run(ctx)),\n ctx.abortSignal,\n )\n iterator = stream[Symbol.asyncIterator]()\n while (true) {\n if (ctx.abortSignal?.aborted) {\n yield stoppedEvent(id)\n return\n }\n const result = await orAbort(iterator.next(), ctx.abortSignal)\n if (result.done) break\n const chunk = result.value\n // Run-scoped events describe the child run. The SUBAGENT_* events carry\n // that information for the parent stream.\n if (\n chunk.type === EventType.RUN_STARTED ||\n chunk.type === EventType.MESSAGES_SNAPSHOT\n ) {\n continue\n }\n if (chunk.type === EventType.RUN_FINISHED) {\n // The engine yields one RUN_FINISHED per model call. Add each one.\n if (sink) collectUsage(sink, chunk)\n finished = chunk\n continue\n }\n if (chunk.type === EventType.RUN_ERROR) {\n yield {\n type: SUBAGENT_ERROR,\n subagentRunId: id,\n message: chunk.message || 'Subagent failed',\n ...(chunk.code ? { code: chunk.code } : {}),\n timestamp: Date.now(),\n } satisfies SubagentErrorEvent\n return\n }\n yield attributeChunk(chunk, id)\n }\n if (ctx.abortSignal?.aborted) {\n yield stoppedEvent(id)\n return\n }\n const outcome =\n finished?.type === EventType.RUN_FINISHED ? finished.outcome : undefined\n if (outcome?.type === 'cancelled') {\n yield stoppedEvent(id)\n return\n }\n if (outcome?.type === 'interrupt') {\n const interrupts = outcome.interrupts.map((interrupt) =>\n interrupt.subagentRunId\n ? interrupt\n : { ...interrupt, subagentRunId: id },\n )\n sink?.interrupts.push(...interrupts)\n yield {\n type: SUBAGENT_FINISHED,\n subagentRunId: id,\n outcome: {\n type: 'suspended',\n interruptIds: interrupts\n .filter((interrupt) => interrupt.subagentRunId === id)\n .map((interrupt) => interrupt.id),\n },\n timestamp: Date.now(),\n } satisfies SubagentFinishedEvent\n return\n }\n const result =\n finished?.type === EventType.RUN_FINISHED ? finished.result : undefined\n yield {\n type: SUBAGENT_FINISHED,\n subagentRunId: id,\n ...(result !== undefined ? { result } : {}),\n timestamp: Date.now(),\n } satisfies SubagentFinishedEvent\n } catch (error) {\n yield {\n type: SUBAGENT_ERROR,\n subagentRunId: id,\n message: isAbortError(error, ctx.abortSignal)\n ? 'Stopped'\n : error instanceof Error\n ? error.message\n : String(error),\n timestamp: Date.now(),\n } satisfies SubagentErrorEvent\n } finally {\n try {\n await iterator?.return?.()\n } catch {\n // Child stream may already be closed or aborted.\n }\n }\n}\n\nasync function* mergeAgentStreams(streams: Array<AsyncIterable<StreamChunk>>) {\n const readers = streams.map((stream) => {\n const iterator = stream[Symbol.asyncIterator]()\n return {\n iterator,\n next: iterator.next(),\n }\n })\n\n try {\n while (readers.length > 0) {\n const indexed = readers.map((reader, index) =>\n reader.next.then((result) => ({ index, result, reader })),\n )\n const winner = await Promise.race(indexed)\n if (winner.result.done) {\n readers.splice(winner.index, 1)\n continue\n }\n yield winner.result.value\n winner.reader.next = winner.reader.iterator.next()\n }\n } finally {\n // The reader stopped early. Close every child so its finally runs.\n for (const reader of readers) {\n void reader.iterator.return?.().catch(() => {})\n }\n }\n}\n\n/** True when a child in these chunks failed or stopped for outside input. */\nfunction stopsSequence(chunks: ReadonlyArray<StreamChunk>, id: string) {\n return chunks.some(\n (chunk) =>\n (chunk.type === SUBAGENT_ERROR && chunk.subagentRunId === id) ||\n (chunk.type === SUBAGENT_FINISHED &&\n chunk.subagentRunId === id &&\n chunk.outcome?.type === 'suspended'),\n )\n}\n\nexport async function* spawnNamedAgents(\n entries: ReadonlyArray<SpawnEntry>,\n bag: SubagentsBag,\n ctx: SpawnContext,\n sink?: SubagentSink,\n) {\n if (bag.sandbox === 'inherit' && entries.length > 1) {\n throw new Error(\n \"subagents.sandbox 'inherit' cannot start two children in one turn\",\n )\n }\n // One signal for the group. The finally stops every child that still runs\n // when the reader stops early.\n const group = linkAbort(ctx.abortSignal)\n const groupCtx = { ...ctx, abortSignal: group.controller.signal }\n try {\n if (bag.order === 'sequence') {\n let messages = ctx.messages\n for (const entry of entries) {\n const chunks: Array<StreamChunk> = []\n let id: string | undefined\n for await (const chunk of openAgentStream(\n entry,\n bag,\n { ...groupCtx, messages },\n sink,\n )) {\n if (chunk.type === SUBAGENT_STARTED && id === undefined) {\n id = chunk.subagentRunId\n }\n chunks.push(chunk)\n yield chunk\n }\n if (id !== undefined && stopsSequence(chunks, id)) return\n const text = [\n entry.resume?.text,\n collectNamedText(chunks, [entry.name]),\n ]\n .filter((part) => part !== undefined && part !== '')\n .join('')\n if (text) {\n messages = [...messages, { role: 'assistant', content: text }]\n }\n }\n return\n }\n const streams = entries.map((entry) =>\n openAgentStream(entry, bag, groupCtx, sink),\n )\n const onlyStream = streams.length === 1 ? streams[0] : undefined\n if (onlyStream) {\n yield* onlyStream\n return\n }\n yield* mergeAgentStreams(streams)\n } finally {\n group.controller.abort()\n group.dispose()\n }\n}\n\n/**\n * Text of the named direct children, in `names` order. Text from nested\n * children stays out: their chunks carry their own id.\n */\nexport function collectNamedText(\n chunks: Array<StreamChunk>,\n names: ReadonlyArray<string>,\n) {\n const nameByRunId = new Map<string, string>()\n const textByName = new Map<string, string>()\n for (const chunk of chunks) {\n if (chunk.type === SUBAGENT_STARTED) {\n if (chunk.parentSubagentRunId === undefined) {\n nameByRunId.set(chunk.subagentRunId, chunk.name)\n }\n continue\n }\n if (chunk.type !== EventType.TEXT_MESSAGE_CONTENT) continue\n if (!('subagentRunId' in chunk) || typeof chunk.subagentRunId !== 'string')\n continue\n const name = nameByRunId.get(chunk.subagentRunId)\n if (!name) continue\n textByName.set(name, `${textByName.get(name) ?? ''}${chunk.delta}`)\n }\n return names\n .map((name) => textByName.get(name)?.trim() ?? '')\n .filter((text) => text.length > 0)\n .join('\\n\\n')\n}\n\n/**\n * The parent conversation up to the message that carries this tool call, with\n * that message's tool calls removed. Its string text stays; array content is\n * dropped.\n */\nfunction messagesBeforeCall(\n messages: ReadonlyArray<ModelMessage>,\n toolCallId: string,\n): Array<ModelMessage> {\n const index = messages.findIndex((message) =>\n message.toolCalls?.some((call) => call.id === toolCallId),\n )\n if (index === -1) return [...messages]\n const host = messages[index]\n const kept = messages.slice(0, index)\n if (host && typeof host.content === 'string' && host.content !== '') {\n const { toolCalls: _calls, ...text } = host\n void _calls\n kept.push(text)\n }\n return kept\n}\n\n/**\n * Record the parent messages when the model calls a subagent tool, so the\n * child reads the conversation as it is at that call.\n */\nexport function subagentCallMessages(names: ReadonlySet<string>) {\n const byCall = new Map<string, Array<ModelMessage>>()\n const middleware: ChatMiddleware = {\n name: 'subagent-call-messages',\n onBeforeToolCall(ctx, hook) {\n if (!names.has(hook.toolName)) return undefined\n byCall.set(\n hook.toolCallId,\n messagesBeforeCall(ctx.messages, hook.toolCallId),\n )\n return undefined\n },\n }\n return {\n middleware,\n messagesFor: (toolCallId: string | undefined) =>\n toolCallId === undefined ? undefined : byCall.get(toolCallId),\n }\n}\n\nexport function createSyntheticSubagentTools(\n bag: SubagentsBag,\n parent: {\n /** Messages the parent run started with. Used when no call was recorded. */\n messages: SubagentRunContext['messages']\n /** The parent messages at a tool call. See subagentCallMessages. */\n messagesFor?: (\n toolCallId: string | undefined,\n ) => SubagentRunContext['messages'] | undefined\n threadId: string\n runId: string\n interruptedRunId?: string\n abortSignal?: AbortSignal\n turn?: SubagentTurn\n sink: SubagentSink\n },\n): Array<Tool> {\n return bag.agents.map((agent) => ({\n name: agent.name,\n description: agent.description,\n ...(agent.inputSchema !== undefined && { inputSchema: agent.inputSchema }),\n [SUBAGENT_TOOL]: true,\n // The tool loop checks `input` against `inputSchema` before this runs.\n execute: async (input: unknown, context?: unknown) => {\n const toolContext = context as\n | {\n toolCallId?: string\n [EMIT_STREAM_CHUNK]?: (chunk: StreamChunk) => void\n }\n | undefined\n const toolCallId = toolContext?.toolCallId\n const suspended = parent.turn?.children.find(\n (child) =>\n child.status === 'suspended' &&\n child.parentToolCallId !== undefined &&\n child.parentToolCallId === toolCallId,\n )\n // An agent without `inputSchema` still gets `{}` from the model. Its\n // `ctx.input` stays undefined.\n const entry: SpawnEntry = {\n name: agent.name,\n ...(agent.inputSchema !== undefined && { input }),\n ...(suspended && {\n resume: {\n subagentRunId: suspended.subagentRunId,\n messages: suspended.messages,\n entries: suspended.resume,\n text: suspended.text,\n },\n }),\n }\n const sink = createSubagentSink()\n const link = linkAbort(parent.abortSignal)\n let subagentRunId = suspended?.subagentRunId ?? ''\n let text = suspended?.text ?? ''\n let error: string | undefined\n try {\n for await (const chunk of openAgentStream(\n entry,\n bag,\n {\n messages: parent.messagesFor?.(toolCallId) ?? parent.messages,\n abortSignal: link.controller.signal,\n threadId: parent.threadId,\n parentRunId: parent.runId,\n ...(parent.interruptedRunId !== undefined\n ? { interruptedRunId: parent.interruptedRunId }\n : {}),\n },\n sink,\n toolCallId,\n )) {\n if (chunk.type === SUBAGENT_STARTED && subagentRunId === '') {\n subagentRunId = chunk.subagentRunId\n }\n if (\n chunk.type === EventType.TEXT_MESSAGE_CONTENT &&\n 'subagentRunId' in chunk &&\n chunk.subagentRunId === subagentRunId\n ) {\n text += chunk.delta\n }\n if (\n chunk.type === SUBAGENT_ERROR &&\n chunk.subagentRunId === subagentRunId\n ) {\n error = chunk.message\n }\n toolContext?.[EMIT_STREAM_CHUNK]?.(chunk)\n }\n } finally {\n link.dispose()\n }\n parent.sink.usage.push(...sink.usage)\n if (sink.total) {\n parent.sink.total = parent.sink.total\n ? addTokenUsage(parent.sink.total, sink.total)\n : sink.total\n }\n return {\n subagentRunId,\n text,\n ...(error !== undefined ? { error } : {}),\n ...(sink.interrupts.length > 0 ? { interrupts: sink.interrupts } : {}),\n } satisfies SubagentToolOutcome\n },\n }))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"spawn.js","names":[],"sources":["../../../../../src/activities/chat/agents/spawn.ts"],"sourcesContent":["import { EventType } from '../../../types'\nimport {\n addTokenUsage,\n isTanstackUsage,\n rebuildTokenUsage,\n toSpecTokenUsage,\n} from '../../../utilities/ag-ui-usage'\nimport {\n tanstackMetadata,\n withTanstackMetadata,\n} from '../../../utilities/merge-metadata'\nimport { mergeStreams } from '../../../utilities/merge-streams'\nimport { INTERRUPT_BINDING_METADATA_KEY } from '../../../interrupt-resume'\nimport { EMIT_STREAM_CHUNK, SUBAGENT_TOOL } from '../tools/tool-calls'\nimport type { SubagentToolOutcome } from '../tools/tool-calls'\nimport type { SpecTokenUsage } from '../../../utilities/ag-ui-usage'\nimport type {\n Interrupt,\n ModelMessage,\n RunAgentResumeItem,\n StreamChunk,\n SubagentErrorEvent,\n SubagentFinishedEvent,\n SubagentStartedEvent,\n TokenUsage,\n Tool,\n UIMessage,\n} from '../../../types'\nimport type { DefinedAgent, SubagentRunContext } from './define-agent'\nimport type { ChatMiddleware } from '../middleware/types'\nimport type { SubagentTurn } from './turn'\n\nexport const SUBAGENT_STARTED = EventType.SUBAGENT_STARTED\nexport const SUBAGENT_FINISHED = EventType.SUBAGENT_FINISHED\nexport const SUBAGENT_ERROR = EventType.SUBAGENT_ERROR\n\nexport type SubagentOrder = 'parallel' | 'sequence'\n\nexport interface SubagentRouterPlan {\n names: ReadonlyArray<string>\n /** Overrides `subagents.order` for this turn. */\n order?: SubagentOrder\n}\n\nexport interface SubagentStep {\n names: ReadonlyArray<string>\n /** Overrides `subagents.order` for this step. */\n order?: SubagentOrder\n}\n\nexport interface SubagentStepsPlan {\n steps: ReadonlyArray<SubagentStep>\n}\n\nexport type SubagentRouterPick =\n | 'main'\n | string\n | ReadonlyArray<string>\n | SubagentRouterPlan\n | SubagentStepsPlan\n\nexport interface SubagentsBag<\n TAgents extends ReadonlyArray<DefinedAgent> = ReadonlyArray<DefinedAgent>,\n> {\n agents: TAgents\n router?: (ctx: {\n messages: SubagentRunContext['messages']\n agents: NoInfer<TAgents>\n abortSignal?: AbortSignal\n }) => SubagentRouterPick | Promise<SubagentRouterPick>\n strategy?: 'exclusive' | 'handoff'\n /**\n * How a router list runs. `parallel` starts every name together.\n * `sequence` runs each name after the previous one finishes, and passes\n * that child's text to the next child.\n */\n order?: 'parallel' | 'sequence'\n sandbox?: 'own' | 'inherit'\n}\n\n/** What the children of one parent run left behind for the parent terminal. */\nexport interface SubagentSink {\n interrupts: Array<Interrupt>\n /** One AG-UI entry per child model call. */\n usage: Array<SpecTokenUsage>\n /** Summed full usage of the children, including cost. */\n total?: TokenUsage\n}\n\nexport function createSubagentSink(): SubagentSink {\n return { interrupts: [], usage: [] }\n}\n\n/** One child to start, or a suspended child to continue. */\nexport interface SpawnEntry {\n name: string\n /** The checked tool input for an agent with `inputSchema`. */\n input?: unknown\n resume?: {\n subagentRunId: string\n /** The child's own messages from the interrupted run. */\n messages: Array<UIMessage | ModelMessage>\n entries: Array<RunAgentResumeItem>\n /** Text the child wrote before it stopped. */\n text: string\n }\n}\n\ninterface SpawnContext {\n messages: SubagentRunContext['messages']\n abortSignal?: AbortSignal\n threadId: string\n /** The parent chat run. */\n parentRunId: string\n /** The interrupted parent run, on a resume. */\n interruptedRunId?: string\n}\n\nexport function createSubagentId() {\n return `subagent-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\nfunction childRunId(parentRunId: string, subagentRunId: string) {\n return `${parentRunId}:${subagentRunId}`\n}\n\n/**\n * Bind child interrupts to the parent run. The client resumes the parent run,\n * so each binding must name that run. The resumed child then validates with\n * the parent's interrupted run id.\n */\nexport function rebindInterrupts(\n interrupts: ReadonlyArray<Interrupt>,\n runId: string,\n): Array<Interrupt> {\n return interrupts.map((interrupt) => {\n const binding = interrupt.metadata?.[INTERRUPT_BINDING_METADATA_KEY]\n if (typeof binding !== 'object' || binding === null) return interrupt\n return {\n ...interrupt,\n metadata: {\n ...interrupt.metadata,\n [INTERRUPT_BINDING_METADATA_KEY]: {\n ...binding,\n interruptedRunId: runId,\n generation: 0,\n },\n },\n }\n })\n}\n\nfunction createAbortError() {\n const error = new Error('Aborted')\n error.name = 'AbortError'\n return error\n}\n\nfunction isAbortError(error: unknown, signal?: AbortSignal) {\n if (signal?.aborted) return true\n return (\n error instanceof Error &&\n (error.name === 'AbortError' || error.message === 'Aborted')\n )\n}\n\nfunction stoppedEvent(subagentRunId: string) {\n return {\n type: SUBAGENT_ERROR,\n subagentRunId,\n message: 'Stopped',\n timestamp: Date.now(),\n } satisfies SubagentErrorEvent\n}\n\nfunction childThreadId(\n sandbox: SubagentsBag['sandbox'],\n parentThreadId: string,\n name: string,\n) {\n return sandbox === 'inherit' ? parentThreadId : `${parentThreadId}:${name}`\n}\n\nfunction linkAbort(parent?: AbortSignal) {\n const controller = new AbortController()\n if (!parent) return { controller, dispose: () => {} }\n if (parent.aborted) {\n controller.abort()\n return { controller, dispose: () => {} }\n }\n const onAbort = () => controller.abort()\n parent.addEventListener('abort', onAbort, { once: true })\n return {\n controller,\n dispose: () => parent.removeEventListener('abort', onAbort),\n }\n}\n\nfunction orAbort<T>(promise: Promise<T>, signal?: AbortSignal) {\n if (!signal) return promise\n if (signal.aborted) return Promise.reject(createAbortError())\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => reject(createAbortError())\n signal.addEventListener('abort', onAbort, { once: true })\n promise.then(\n (value) => {\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n },\n (error: unknown) => {\n signal.removeEventListener('abort', onAbort)\n reject(error)\n },\n )\n })\n}\n\nfunction agentByName(agents: ReadonlyArray<DefinedAgent>, name: string) {\n const agent = agents.find((entry) => entry.name === name)\n if (!agent) {\n throw new Error(`Unknown subagent: ${name}`)\n }\n return agent\n}\n\nfunction openAgentStream(\n entry: SpawnEntry,\n bag: SubagentsBag,\n ctx: SpawnContext,\n sink?: SubagentSink,\n parentToolCallId?: string,\n) {\n const agent = agentByName(bag.agents, entry.name)\n const resume = entry.resume\n const subagentRunId = resume?.subagentRunId ?? createSubagentId()\n // The parent binds child interrupts to its own run (see rebindInterrupts),\n // so the resumed child continues from the interrupted parent run id.\n if (resume !== undefined && ctx.interruptedRunId === undefined) {\n throw new Error(\n `Subagent \"${entry.name}\" has interrupt answers, but the run has no parentRunId. Pass the interrupted run id as parentRunId.`,\n )\n }\n const resumed =\n resume !== undefined\n ? {\n messages: [...ctx.messages, ...resume.messages],\n parentRunId: ctx.interruptedRunId,\n resume: resume.entries,\n }\n : undefined\n return spawnAgentStream(\n agent,\n {\n input: entry.input,\n messages: resumed?.messages ?? ctx.messages,\n ...(ctx.abortSignal ? { abortSignal: ctx.abortSignal } : {}),\n threadId: childThreadId(bag.sandbox, ctx.threadId, entry.name),\n runId: childRunId(ctx.parentRunId, subagentRunId),\n parentRunId: resumed?.parentRunId ?? ctx.parentRunId,\n subagentRunId,\n ...(resumed ? { resume: resumed.resume } : {}),\n },\n sink,\n parentToolCallId,\n )\n}\n\nconst ROUTER_PICK_ERROR =\n 'subagents.router must return main, a name, a list of names, { names, order }, or { steps }.'\n\nfunction assertOrder(order: SubagentOrder | undefined) {\n if (order !== undefined && order !== 'parallel' && order !== 'sequence') {\n throw new Error('subagents.router order must be parallel or sequence.')\n }\n}\n\nfunction normalizeNames(\n names: ReadonlyArray<string>,\n agents: ReadonlyArray<DefinedAgent>,\n): ReadonlyArray<string> {\n if (names.length === 0) throw new Error(ROUTER_PICK_ERROR)\n const hasMain = names.includes('main')\n if (hasMain && names.length > 1) {\n throw new Error('Do not mix main into a subagent list.')\n }\n if (hasMain) return ['main']\n for (const name of names) agentByName(agents, name)\n return [...names]\n}\n\nfunction isStringList(pick: SubagentRouterPick): pick is ReadonlyArray<string> {\n return Array.isArray(pick)\n}\n\nexport function normalizeRouterPick(\n pick: SubagentRouterPick,\n agents: ReadonlyArray<DefinedAgent>,\n): { steps: ReadonlyArray<SubagentStep> } {\n if (pick === 'main' || typeof pick === 'string') {\n return { steps: [{ names: normalizeNames([pick], agents) }] }\n }\n if (isStringList(pick)) {\n return { steps: [{ names: normalizeNames(pick, agents) }] }\n }\n if ('steps' in pick) {\n if (pick.steps.length === 0) throw new Error(ROUTER_PICK_ERROR)\n const steps = pick.steps.map((step) => {\n assertOrder(step.order)\n const names = normalizeNames(step.names, agents)\n return step.order === undefined ? { names } : { names, order: step.order }\n })\n const flat = steps.flatMap((step) => step.names)\n if (flat.includes('main') && flat.length > 1) {\n throw new Error('Do not mix main into a subagent list.')\n }\n return { steps }\n }\n assertOrder(pick.order)\n const names = normalizeNames(pick.names, agents)\n return {\n steps: [\n pick.order === undefined ? { names } : { names, order: pick.order },\n ],\n }\n}\n\n/**\n * Tag a child chunk with its subagent. A chunk that a nested child already\n * tagged keeps its own id, and a nested child's start names this child as\n * its parent.\n */\nfunction attributeChunk(\n chunk: StreamChunk,\n subagentRunId: string,\n): StreamChunk {\n if (chunk.type === SUBAGENT_STARTED) {\n return chunk.parentSubagentRunId !== undefined\n ? chunk\n : { ...chunk, parentSubagentRunId: subagentRunId }\n }\n if (chunk.type === SUBAGENT_FINISHED || chunk.type === SUBAGENT_ERROR) {\n return chunk\n }\n if ('subagentRunId' in chunk && typeof chunk.subagentRunId === 'string') {\n return chunk\n }\n // RUN_* and MESSAGES_SNAPSHOT never get here (spawnAgentStream drops them).\n // Everything else is tagged.\n return { ...chunk, subagentRunId } as StreamChunk\n}\n\nfunction runUsage(chunk: StreamChunk | undefined): Array<SpecTokenUsage> {\n if (chunk?.type !== EventType.RUN_FINISHED) return []\n if (Array.isArray(chunk.usage)) return chunk.usage\n return isTanstackUsage(chunk.usage) ? toSpecTokenUsage(chunk.usage).usage : []\n}\n\n/** The full usage of a run: token counts plus cost and the other fields. */\nfunction fullUsage(chunk: StreamChunk | undefined): TokenUsage | undefined {\n if (chunk?.type !== EventType.RUN_FINISHED) return undefined\n return rebuildTokenUsage(chunk.usage, tanstackMetadata(chunk)?.usage)\n}\n\n/** Add a finished child run's usage to the sink. */\nexport function collectUsage(sink: SubagentSink, finished?: StreamChunk) {\n sink.usage.push(...runUsage(finished))\n const full = fullUsage(finished)\n if (full) sink.total = sink.total ? addTokenUsage(sink.total, full) : full\n}\n\n/** A parent run's last chunk: it completed, or it failed. */\ntype ParentTerminal = Extract<\n StreamChunk,\n { type: 'RUN_FINISHED' | 'RUN_ERROR' }\n>\n\n/**\n * Put the children's usage on a parent terminal. `usage[]` keeps one entry per\n * model call. `metadata.tanstack.usage` holds the summed cost and the other\n * TanStack fields, so `fromSpecTokenUsage` reads the full total. Empties the\n * sink, so the next parent terminal does not count it again.\n *\n * `RUN_ERROR` is accepted too: a turn that failed still spent whatever its\n * children spent. Such a chunk carries no usage of its own, so `runUsage` and\n * `fullUsage` return empty for it and the children's total stands alone.\n */\nexport function withChildUsage(\n chunk: ParentTerminal,\n sink: SubagentSink,\n): ParentTerminal {\n if (sink.usage.length === 0 && !sink.total) return chunk\n const own = fullUsage(chunk)\n const total =\n own && sink.total ? addTokenUsage(own, sink.total) : (own ?? sink.total)\n const usage = [...runUsage(chunk), ...sink.usage.splice(0)]\n sink.total = undefined\n const leftover = total ? toSpecTokenUsage(total).leftover : undefined\n const next = { ...chunk, usage }\n if (!leftover) return next\n // `withTanstackMetadata` runs the value through `Omit`, which collapses this\n // union and widens `type` back to `RUN_FINISHED | RUN_ERROR`. It only adds a\n // metadata key, so the runtime shape is the input's: restore that type.\n return withTanstackMetadata(next, { usage: leftover }) as ParentTerminal\n}\n\nexport async function* spawnAgentStream(\n agent: DefinedAgent,\n ctx: SubagentRunContext,\n sink?: SubagentSink,\n parentToolCallId?: string,\n): AsyncIterable<StreamChunk> {\n const id = ctx.subagentRunId\n yield {\n type: SUBAGENT_STARTED,\n subagentRunId: id,\n name: agent.name,\n description: agent.description,\n ...(ctx.parentSubagentRunId !== undefined\n ? { parentSubagentRunId: ctx.parentSubagentRunId }\n : {}),\n ...(parentToolCallId !== undefined ? { parentToolCallId } : {}),\n timestamp: Date.now(),\n } satisfies SubagentStartedEvent\n\n let iterator: AsyncIterator<StreamChunk> | undefined\n let finished: StreamChunk | undefined\n try {\n if (ctx.abortSignal?.aborted) {\n yield stoppedEvent(id)\n return\n }\n const stream = await orAbort(\n Promise.resolve(agent.run(ctx)),\n ctx.abortSignal,\n )\n iterator = stream[Symbol.asyncIterator]()\n while (true) {\n if (ctx.abortSignal?.aborted) {\n yield stoppedEvent(id)\n return\n }\n const result = await orAbort(iterator.next(), ctx.abortSignal)\n if (result.done) break\n const chunk = result.value\n // Run-scoped events describe the child run. The SUBAGENT_* events carry\n // that information for the parent stream.\n if (\n chunk.type === EventType.RUN_STARTED ||\n chunk.type === EventType.MESSAGES_SNAPSHOT\n ) {\n continue\n }\n if (chunk.type === EventType.RUN_FINISHED) {\n // The engine yields one RUN_FINISHED per model call. Add each one.\n if (sink) collectUsage(sink, chunk)\n finished = chunk\n continue\n }\n if (chunk.type === EventType.RUN_ERROR) {\n yield {\n type: SUBAGENT_ERROR,\n subagentRunId: id,\n message: chunk.message || 'Subagent failed',\n ...(chunk.code ? { code: chunk.code } : {}),\n timestamp: Date.now(),\n } satisfies SubagentErrorEvent\n return\n }\n yield attributeChunk(chunk, id)\n }\n if (ctx.abortSignal?.aborted) {\n yield stoppedEvent(id)\n return\n }\n const outcome =\n finished?.type === EventType.RUN_FINISHED ? finished.outcome : undefined\n if (outcome?.type === 'cancelled') {\n yield stoppedEvent(id)\n return\n }\n if (outcome?.type === 'interrupt') {\n const interrupts = outcome.interrupts.map((interrupt) =>\n interrupt.subagentRunId\n ? interrupt\n : { ...interrupt, subagentRunId: id },\n )\n sink?.interrupts.push(...interrupts)\n yield {\n type: SUBAGENT_FINISHED,\n subagentRunId: id,\n outcome: {\n type: 'suspended',\n interruptIds: interrupts\n .filter((interrupt) => interrupt.subagentRunId === id)\n .map((interrupt) => interrupt.id),\n },\n timestamp: Date.now(),\n } satisfies SubagentFinishedEvent\n return\n }\n const result =\n finished?.type === EventType.RUN_FINISHED ? finished.result : undefined\n yield {\n type: SUBAGENT_FINISHED,\n subagentRunId: id,\n ...(result !== undefined ? { result } : {}),\n timestamp: Date.now(),\n } satisfies SubagentFinishedEvent\n } catch (error) {\n yield {\n type: SUBAGENT_ERROR,\n subagentRunId: id,\n message: isAbortError(error, ctx.abortSignal)\n ? 'Stopped'\n : error instanceof Error\n ? error.message\n : String(error),\n timestamp: Date.now(),\n } satisfies SubagentErrorEvent\n } finally {\n try {\n await iterator?.return?.()\n } catch {\n // Child stream may already be closed or aborted.\n }\n }\n}\n\n/** True when a child in these chunks failed or stopped for outside input. */\nfunction stopsSequence(chunks: ReadonlyArray<StreamChunk>, id: string) {\n return chunks.some(\n (chunk) =>\n (chunk.type === SUBAGENT_ERROR && chunk.subagentRunId === id) ||\n (chunk.type === SUBAGENT_FINISHED &&\n chunk.subagentRunId === id &&\n chunk.outcome?.type === 'suspended'),\n )\n}\n\nexport async function* spawnNamedAgents(\n entries: ReadonlyArray<SpawnEntry>,\n bag: SubagentsBag,\n ctx: SpawnContext,\n sink?: SubagentSink,\n) {\n if (bag.sandbox === 'inherit' && entries.length > 1) {\n throw new Error(\n \"subagents.sandbox 'inherit' cannot start two children in one turn\",\n )\n }\n // One signal for the group. The finally stops every child that still runs\n // when the reader stops early.\n const group = linkAbort(ctx.abortSignal)\n const groupCtx = { ...ctx, abortSignal: group.controller.signal }\n try {\n if (bag.order === 'sequence') {\n let messages = ctx.messages\n for (const entry of entries) {\n const chunks: Array<StreamChunk> = []\n let id: string | undefined\n for await (const chunk of openAgentStream(\n entry,\n bag,\n { ...groupCtx, messages },\n sink,\n )) {\n if (chunk.type === SUBAGENT_STARTED && id === undefined) {\n id = chunk.subagentRunId\n }\n chunks.push(chunk)\n yield chunk\n }\n if (id !== undefined && stopsSequence(chunks, id)) return\n const text = [\n entry.resume?.text,\n collectNamedText(chunks, [entry.name]),\n ]\n .filter((part) => part !== undefined && part !== '')\n .join('')\n if (text) {\n messages = [...messages, { role: 'assistant', content: text }]\n }\n }\n return\n }\n const streams = entries.map((entry) =>\n openAgentStream(entry, bag, groupCtx, sink),\n )\n const onlyStream = streams.length === 1 ? streams[0] : undefined\n if (onlyStream) {\n yield* onlyStream\n return\n }\n yield* mergeStreams(streams)\n } finally {\n group.controller.abort()\n group.dispose()\n }\n}\n\n/**\n * Text of the named direct children, in `names` order. Text from nested\n * children stays out: their chunks carry their own id.\n */\nexport function collectNamedText(\n chunks: Array<StreamChunk>,\n names: ReadonlyArray<string>,\n) {\n const nameByRunId = new Map<string, string>()\n const textByName = new Map<string, string>()\n for (const chunk of chunks) {\n if (chunk.type === SUBAGENT_STARTED) {\n if (chunk.parentSubagentRunId === undefined) {\n nameByRunId.set(chunk.subagentRunId, chunk.name)\n }\n continue\n }\n if (chunk.type !== EventType.TEXT_MESSAGE_CONTENT) continue\n if (!('subagentRunId' in chunk) || typeof chunk.subagentRunId !== 'string')\n continue\n const name = nameByRunId.get(chunk.subagentRunId)\n if (!name) continue\n textByName.set(name, `${textByName.get(name) ?? ''}${chunk.delta}`)\n }\n return names\n .map((name) => textByName.get(name)?.trim() ?? '')\n .filter((text) => text.length > 0)\n .join('\\n\\n')\n}\n\n/**\n * The parent conversation up to the message that carries this tool call, with\n * that message's tool calls removed. Its string text stays; array content is\n * dropped.\n */\nfunction messagesBeforeCall(\n messages: ReadonlyArray<ModelMessage>,\n toolCallId: string,\n): Array<ModelMessage> {\n const index = messages.findIndex((message) =>\n message.toolCalls?.some((call) => call.id === toolCallId),\n )\n if (index === -1) return [...messages]\n const host = messages[index]\n const kept = messages.slice(0, index)\n if (host && typeof host.content === 'string' && host.content !== '') {\n const { toolCalls: _calls, ...text } = host\n void _calls\n kept.push(text)\n }\n return kept\n}\n\n/**\n * Record the parent messages when the model calls a subagent tool, so the\n * child reads the conversation as it is at that call.\n */\nexport function subagentCallMessages(names: ReadonlySet<string>) {\n const byCall = new Map<string, Array<ModelMessage>>()\n const middleware: ChatMiddleware = {\n name: 'subagent-call-messages',\n onBeforeToolCall(ctx, hook) {\n if (!names.has(hook.toolName)) return undefined\n byCall.set(\n hook.toolCallId,\n messagesBeforeCall(ctx.messages, hook.toolCallId),\n )\n return undefined\n },\n }\n return {\n middleware,\n messagesFor: (toolCallId: string | undefined) =>\n toolCallId === undefined ? undefined : byCall.get(toolCallId),\n }\n}\n\nexport function createSyntheticSubagentTools(\n bag: SubagentsBag,\n parent: {\n /** Messages the parent run started with. Used when no call was recorded. */\n messages: SubagentRunContext['messages']\n /** The parent messages at a tool call. See subagentCallMessages. */\n messagesFor?: (\n toolCallId: string | undefined,\n ) => SubagentRunContext['messages'] | undefined\n threadId: string\n runId: string\n interruptedRunId?: string\n abortSignal?: AbortSignal\n turn?: SubagentTurn\n sink: SubagentSink\n },\n): Array<Tool> {\n return bag.agents.map((agent) => ({\n name: agent.name,\n description: agent.description,\n ...(agent.inputSchema !== undefined && { inputSchema: agent.inputSchema }),\n [SUBAGENT_TOOL]: true,\n // The tool loop checks `input` against `inputSchema` before this runs.\n execute: async (input: unknown, context?: unknown) => {\n const toolContext = context as\n | {\n toolCallId?: string\n [EMIT_STREAM_CHUNK]?: (chunk: StreamChunk) => void\n }\n | undefined\n const toolCallId = toolContext?.toolCallId\n const suspended = parent.turn?.children.find(\n (child) =>\n child.status === 'suspended' &&\n child.parentToolCallId !== undefined &&\n child.parentToolCallId === toolCallId,\n )\n // An agent without `inputSchema` still gets `{}` from the model. Its\n // `ctx.input` stays undefined.\n const entry: SpawnEntry = {\n name: agent.name,\n ...(agent.inputSchema !== undefined && { input }),\n ...(suspended && {\n resume: {\n subagentRunId: suspended.subagentRunId,\n messages: suspended.messages,\n entries: suspended.resume,\n text: suspended.text,\n },\n }),\n }\n const sink = createSubagentSink()\n const link = linkAbort(parent.abortSignal)\n let subagentRunId = suspended?.subagentRunId ?? ''\n let text = suspended?.text ?? ''\n let error: string | undefined\n try {\n for await (const chunk of openAgentStream(\n entry,\n bag,\n {\n messages: parent.messagesFor?.(toolCallId) ?? parent.messages,\n abortSignal: link.controller.signal,\n threadId: parent.threadId,\n parentRunId: parent.runId,\n ...(parent.interruptedRunId !== undefined\n ? { interruptedRunId: parent.interruptedRunId }\n : {}),\n },\n sink,\n toolCallId,\n )) {\n if (chunk.type === SUBAGENT_STARTED && subagentRunId === '') {\n subagentRunId = chunk.subagentRunId\n }\n if (\n chunk.type === EventType.TEXT_MESSAGE_CONTENT &&\n 'subagentRunId' in chunk &&\n chunk.subagentRunId === subagentRunId\n ) {\n text += chunk.delta\n }\n if (\n chunk.type === SUBAGENT_ERROR &&\n chunk.subagentRunId === subagentRunId\n ) {\n error = chunk.message\n }\n toolContext?.[EMIT_STREAM_CHUNK]?.(chunk)\n }\n } finally {\n link.dispose()\n }\n parent.sink.usage.push(...sink.usage)\n if (sink.total) {\n parent.sink.total = parent.sink.total\n ? addTokenUsage(parent.sink.total, sink.total)\n : sink.total\n }\n return {\n subagentRunId,\n text,\n ...(error !== undefined ? { error } : {}),\n ...(sink.interrupts.length > 0 ? { interrupts: sink.interrupts } : {}),\n } satisfies SubagentToolOutcome\n },\n }))\n}\n"],"mappings":"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"}
|
|
@@ -113,6 +113,8 @@ export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema ex
|
|
|
113
113
|
abortController?: TextOptions['abortController'];
|
|
114
114
|
/** Strategy for controlling the agent loop */
|
|
115
115
|
agentLoopStrategy?: TextOptions['agentLoopStrategy'];
|
|
116
|
+
/** How the server tools of one model turn run. Default `'parallel'`. */
|
|
117
|
+
toolExecution?: TextOptions['toolExecution'];
|
|
116
118
|
/**
|
|
117
119
|
* Optional configuration for lazy-tool discovery (tools marked `lazy: true`).
|
|
118
120
|
* Tunes how much of each lazy tool's description appears in the discovery
|
|
@@ -7,6 +7,7 @@ import { EventType } from "../../types.js";
|
|
|
7
7
|
import { rebuildTokenUsage } from "../../utilities/ag-ui-usage.js";
|
|
8
8
|
import { tanstackMetadata, withTanstackMetadata } from "../../utilities/merge-metadata.js";
|
|
9
9
|
import { withDurabilityBatchHint } from "../../utilities/durability-batch.js";
|
|
10
|
+
import { isRedactedThinkingId } from "../../utilities/reasoning-encrypted-value.js";
|
|
10
11
|
import { normalizeStreamChunk } from "../../utilities/normalize-stream-chunk.js";
|
|
11
12
|
import { resolveDebugOption } from "../../logger/resolve.js";
|
|
12
13
|
import { streamToText } from "../../stream-to-response.js";
|
|
@@ -149,6 +150,7 @@ var TextEngine = class {
|
|
|
149
150
|
turnParts = [];
|
|
150
151
|
currentThinkingContent = "";
|
|
151
152
|
currentThinkingSignature = "";
|
|
153
|
+
currentThinkingRedacted = false;
|
|
152
154
|
eventOptions;
|
|
153
155
|
eventToolNames;
|
|
154
156
|
finishedEvent = null;
|
|
@@ -519,6 +521,7 @@ var TextEngine = class {
|
|
|
519
521
|
this.turnParts = [];
|
|
520
522
|
this.currentThinkingContent = "";
|
|
521
523
|
this.currentThinkingSignature = "";
|
|
524
|
+
this.currentThinkingRedacted = false;
|
|
522
525
|
this.finishedEvent = null;
|
|
523
526
|
this.streamedToolErrorResults.clear();
|
|
524
527
|
this.middlewareCtx.currentMessageId = this.currentMessageId;
|
|
@@ -779,7 +782,8 @@ var TextEngine = class {
|
|
|
779
782
|
if (this.currentThinkingContent || this.currentThinkingSignature) {
|
|
780
783
|
this.accumulatedThinking.push({
|
|
781
784
|
content: this.currentThinkingContent,
|
|
782
|
-
...this.currentThinkingSignature && { signature: this.currentThinkingSignature }
|
|
785
|
+
...this.currentThinkingSignature && { signature: this.currentThinkingSignature },
|
|
786
|
+
...this.currentThinkingRedacted && { redacted: true }
|
|
783
787
|
});
|
|
784
788
|
if (this.turnParts) {
|
|
785
789
|
const placeholder = [...this.turnParts].reverse().find((part) => part.type === "thinking" && part.index === -1);
|
|
@@ -792,6 +796,7 @@ var TextEngine = class {
|
|
|
792
796
|
}
|
|
793
797
|
this.currentThinkingContent = "";
|
|
794
798
|
this.currentThinkingSignature = "";
|
|
799
|
+
this.currentThinkingRedacted = false;
|
|
795
800
|
}
|
|
796
801
|
}
|
|
797
802
|
/**
|
|
@@ -813,6 +818,7 @@ var TextEngine = class {
|
|
|
813
818
|
if (typeof chunk.signature === "string" && chunk.signature !== "") {
|
|
814
819
|
this.noteThinkingStepPosition();
|
|
815
820
|
this.currentThinkingSignature = chunk.signature;
|
|
821
|
+
this.currentThinkingRedacted = isRedactedThinkingId(chunk.stepId);
|
|
816
822
|
}
|
|
817
823
|
}
|
|
818
824
|
handleReasoningMessageContentEvent(chunk) {
|
|
@@ -830,6 +836,7 @@ var TextEngine = class {
|
|
|
830
836
|
}
|
|
831
837
|
this.noteThinkingStepPosition();
|
|
832
838
|
this.currentThinkingSignature = chunk.encryptedValue;
|
|
839
|
+
this.currentThinkingRedacted = isRedactedThinkingId(chunk.entityId);
|
|
833
840
|
}
|
|
834
841
|
/**
|
|
835
842
|
* Tools available for execution this turn. The discovery tool is dropped
|
|
@@ -900,7 +907,7 @@ var TextEngine = class {
|
|
|
900
907
|
deniedToolResults: this.resumeDeniedToolResults,
|
|
901
908
|
cancelledToolCallIds: this.resumeCancelledToolCallIds,
|
|
902
909
|
inputResponses: this.resumeInputResponses
|
|
903
|
-
});
|
|
910
|
+
}, this.params.toolExecution);
|
|
904
911
|
const executionResult = yield* this.drainToolCallGenerator(generator);
|
|
905
912
|
if (this.isMiddlewareAborted()) {
|
|
906
913
|
this.setToolPhase("stop");
|
|
@@ -994,7 +1001,7 @@ var TextEngine = class {
|
|
|
994
1001
|
deniedToolResults: this.resumeDeniedToolResults,
|
|
995
1002
|
cancelledToolCallIds: this.resumeCancelledToolCallIds,
|
|
996
1003
|
inputResponses: this.resumeInputResponses
|
|
997
|
-
});
|
|
1004
|
+
}, this.params.toolExecution);
|
|
998
1005
|
const executionResult = yield* this.drainToolCallGenerator(generator);
|
|
999
1006
|
this.middlewareCtx.phase = "afterTools";
|
|
1000
1007
|
if (this.isMiddlewareAborted()) {
|