UNPKG

@tanstack/ai

Version:

Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.

77 lines (76 loc) • 3.23 kB
import { splitSubagentWire, subagentWireText, wireSubagentRunId } from "../../../utilities/subagent-wire.js"; //#region src/activities/chat/agents/turn.ts /** Key of the router plan in `SUBAGENT_STARTED` metadata (`metadata.tanstack`). */ var SUBAGENT_PLAN_KEY = "subagentPlan"; function planOf(metadata) { const tanstack = metadata?.tanstack; if (typeof tanstack !== "object" || tanstack === null) return void 0; return tanstack[SUBAGENT_PLAN_KEY]; } function uiText(messages) { return messages.flatMap((message) => message.role === "assistant" ? message.parts.flatMap((part) => part.type === "text" && part.content.trim() !== "" ? [part.content.trim()] : []) : []).join("\n\n"); } function partInterruptIds(part) { return [...part.subagent.interruptIds ?? [], ...part.subagent.messages.flatMap((message) => message.parts.flatMap((nested) => nested.type === "subagent" ? partInterruptIds(nested) : []))]; } function groupInterruptIds(group) { return [...group.info.interruptIds ?? [], ...splitSubagentWire(group.messages).groups.flatMap(groupInterruptIds)]; } /** * The subagent cards in `messages`: UI subagent parts, then wire groups. * Nested cards stay inside their parent card. */ function subagentCards(messages) { return [...messages.flatMap((message) => "parts" in message ? message.parts.filter((part) => part.type === "subagent") : []).map(({ subagent }) => ({ subagentRunId: subagent.id, name: subagent.name, status: subagent.status, ...subagent.parentToolCallId !== void 0 && { parentToolCallId: subagent.parentToolCallId }, messages: subagent.messages, text: uiText(subagent.messages), ids: new Set(partInterruptIds({ type: "subagent", subagent })), plan: planOf(subagent.metadata) })), ...splitSubagentWire(messages).groups.map((group) => ({ subagentRunId: group.id, name: group.info.name, status: group.info.status, ...group.info.parentToolCallId !== void 0 && { parentToolCallId: group.info.parentToolCallId }, messages: group.messages, text: subagentWireText(group.messages), ids: new Set(groupInterruptIds(group)), plan: planOf(group.info.metadata) }))]; } /** * Find the children of the trailing assistant turn that `resume` answers. * Returns undefined when no child owns a resume entry. */ function readSubagentTurn(messages, resume) { if (!resume || resume.length === 0) return void 0; const lastUser = messages.findLastIndex((message) => message.role === "user" && wireSubagentRunId(message) === void 0); const before = messages.slice(0, lastUser + 1); const found = subagentCards(messages.slice(lastUser + 1)); const plan = found.find((card) => card.plan !== void 0)?.plan; const owned = /* @__PURE__ */ new Set(); const children = found.map(({ ids, plan: _plan, ...child }) => { const entries = resume.filter((entry) => ids.has(entry.interruptId)); for (const entry of entries) owned.add(entry.interruptId); return { ...child, resume: entries }; }); if (owned.size === 0) return void 0; return { before, children, rest: resume.filter((entry) => !owned.has(entry.interruptId)), ...plan !== void 0 && { plan } }; } //#endregion export { SUBAGENT_PLAN_KEY, readSubagentTurn, subagentCards }; //# sourceMappingURL=turn.js.map