@tanstack/ai 0.57.0 → 0.59.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/define-agent.d.ts +81 -0
- package/dist/esm/activities/chat/agents/define-agent.js +34 -0
- package/dist/esm/activities/chat/agents/define-agent.js.map +1 -0
- package/dist/esm/activities/chat/agents/route.d.ts +53 -0
- package/dist/esm/activities/chat/agents/route.js +59 -0
- package/dist/esm/activities/chat/agents/route.js.map +1 -0
- package/dist/esm/activities/chat/agents/spawn.d.ts +124 -0
- package/dist/esm/activities/chat/agents/spawn.js +490 -0
- package/dist/esm/activities/chat/agents/spawn.js.map +1 -0
- package/dist/esm/activities/chat/agents/turn.d.ts +36 -0
- package/dist/esm/activities/chat/agents/turn.js +78 -0
- package/dist/esm/activities/chat/agents/turn.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +13 -3
- package/dist/esm/activities/chat/index.js +345 -19
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.d.ts +7 -1
- package/dist/esm/activities/chat/messages.js +94 -18
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/run-store.d.ts +43 -7
- package/dist/esm/activities/chat/middleware/run-store.js +8 -1
- package/dist/esm/activities/chat/middleware/run-store.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +50 -3
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +46 -0
- package/dist/esm/activities/chat/stream/processor.js +280 -7
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +17 -3
- package/dist/esm/activities/chat/tools/tool-calls.js +56 -7
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.js +1 -1
- package/dist/esm/activities/generateImage/index.js +1 -1
- package/dist/esm/activities/generateLiveVideo/index.js +1 -1
- package/dist/esm/activities/generateSpeech/index.js +1 -1
- package/dist/esm/activities/generateTranscription/index.js +1 -1
- package/dist/esm/activities/generateVoice/index.js +1 -1
- package/dist/esm/activities/generateWorld/index.js +1 -1
- package/dist/esm/activities/index.d.ts +3 -0
- package/dist/esm/activities/index.js +5 -3
- package/dist/esm/activities/summarize/index.js +1 -1
- package/dist/esm/client.d.ts +5 -36
- package/dist/esm/client.js +4 -37
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +7 -4
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/stream-to-response.js +12 -6
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.js +2 -1
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/types.d.ts +128 -89
- package/dist/esm/utilities/adapter-yield-chunk.d.ts +5 -1
- package/dist/esm/utilities/ag-ui-usage.d.ts +9 -9
- package/dist/esm/utilities/ag-ui-usage.js +66 -3
- package/dist/esm/utilities/ag-ui-usage.js.map +1 -1
- package/dist/esm/utilities/ag-ui-wire.js +56 -0
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/durability-batch.d.ts +8 -0
- package/dist/esm/utilities/durability-batch.js +45 -0
- package/dist/esm/utilities/durability-batch.js.map +1 -0
- package/dist/esm/utilities/normalize-stream-chunk.js +7 -2
- package/dist/esm/utilities/normalize-stream-chunk.js.map +1 -1
- package/dist/esm/utilities/spec-event-keys.js +13 -8
- package/dist/esm/utilities/spec-event-keys.js.map +1 -1
- package/dist/esm/utilities/subagent-wire.d.ts +36 -0
- package/dist/esm/utilities/subagent-wire.js +131 -0
- package/dist/esm/utilities/subagent-wire.js.map +1 -0
- package/package.json +4 -4
- package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
- package/skills/ai-core/media-generation/SKILL.md +2 -2
- package/skills/ai-core/middleware/SKILL.md +7 -4
- package/src/activities/chat/agents/define-agent.ts +121 -0
- package/src/activities/chat/agents/route.ts +115 -0
- package/src/activities/chat/agents/spawn.ts +806 -0
- package/src/activities/chat/agents/turn.ts +151 -0
- package/src/activities/chat/index.ts +540 -16
- package/src/activities/chat/messages.ts +125 -15
- package/src/activities/chat/middleware/run-store.ts +56 -7
- package/src/activities/chat/middleware/types.ts +55 -2
- package/src/activities/chat/stream/processor.ts +428 -8
- package/src/activities/chat/tools/tool-calls.ts +92 -16
- package/src/activities/index.ts +15 -0
- package/src/client.ts +22 -35
- package/src/index.ts +23 -0
- package/src/middlewares/content-guard.ts +7 -5
- package/src/stream-to-response.ts +16 -6
- package/src/strip-to-spec-middleware.ts +2 -1
- package/src/types.ts +177 -95
- package/src/utilities/adapter-yield-chunk.ts +10 -2
- package/src/utilities/ag-ui-usage.test.ts +38 -0
- package/src/utilities/ag-ui-usage.ts +98 -11
- package/src/utilities/ag-ui-wire.ts +74 -0
- package/src/utilities/durability-batch.ts +48 -0
- package/src/utilities/normalize-stream-chunk.ts +10 -2
- package/src/utilities/spec-event-keys.ts +34 -7
- package/src/utilities/subagent-wire.ts +184 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ag-ui-wire.js","names":[],"sources":["../../../src/utilities/ag-ui-wire.ts"],"sourcesContent":["import type {\n AssistantMessage,\n InputContent,\n ReasoningMessage,\n SystemMessage,\n ToolCall,\n ToolMessage,\n UserMessage,\n} from '@ag-ui/core'\nimport type {\n ContentPart,\n MessagePart,\n ModelMessage,\n StructuredOutputPart,\n TanStackMessageMetadata,\n UIMessage,\n UIResourcePart,\n} from '../types'\nimport type { MetadataRecord } from './merge-metadata'\nimport { tanstackMetadata } from './merge-metadata'\nimport { normalizeToolResult } from './tool-result'\nimport {\n coerceCreatedAt,\n modelMessageToUIMessage,\n} from '../activities/chat/messages'\n\ntype WithMetadata<T> = T & { metadata?: MetadataRecord }\ntype WireSystemMessage = WithMetadata<SystemMessage>\ntype WireUserMessage = WithMetadata<UserMessage>\ntype WireAssistantMessage = WithMetadata<AssistantMessage>\ntype WireToolMessage = WithMetadata<\n ToolMessage & {\n name?: string\n }\n>\ntype WireReasoningMessage = WithMetadata<ReasoningMessage>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction rebuiltToolMetadata(\n metadata: unknown,\n createdAt: unknown,\n id: string | undefined,\n content: string | null | Array<ContentPart>,\n anchorOwnsUiResources = false,\n): MetadataRecord | undefined {\n const source: MetadataRecord = isRecord(metadata) ? metadata : {}\n const tanstack = isRecord(source.tanstack) ? { ...source.tanstack } : {}\n if (anchorOwnsUiResources) delete tanstack.uiResources\n const date = coerceCreatedAt(createdAt)\n const toolResult: NonNullable<TanStackMessageMetadata['toolResult']> = {\n ...(id !== undefined ? { id } : {}),\n ...(date && { createdAt: date.toISOString() }),\n ...(Array.isArray(content) && { content }),\n }\n const result = {\n ...source,\n tanstack: { ...tanstack, toolResult },\n }\n return Object.keys(result).length ? result : undefined\n}\n\nexport type WireMessage =\n | WireSystemMessage\n | WireUserMessage\n | WireAssistantMessage\n | WireToolMessage\n | WireReasoningMessage\n\n/**\n * Serialize TanStack `UIMessage`s and `ModelMessage`s into the AG-UI\n * `RunAgentInput.messages` wire shape. Anchors are spec-only (`id`, `role`,\n * `name`, `content`, `toolCalls`, `metadata`). Tool results and thinking parts\n * on assistant messages are additionally emitted as fan-out\n * `{role:'tool',...}` and `{role:'reasoning',...}` entries for strict AG-UI\n * server consumers. Set `includeSnapshotStructuredOutput` to retain complete\n * structured-output metadata for UI snapshots.\n */\nexport function uiMessagesToWire(\n messages: Array<UIMessage | ModelMessage>,\n options?: { includeSnapshotStructuredOutput: boolean },\n): Array<WireMessage> {\n const wire: Array<WireMessage> = []\n const usedWireIds = new Set<string>(\n messages.flatMap((message) =>\n 'id' in message && message.id && message.role !== 'tool'\n ? [message.id]\n : [],\n ),\n )\n const includeSnapshotStructuredOutput =\n options?.includeSnapshotStructuredOutput ?? false\n\n const assistantIds = new Set<string>()\n for (const msg of messages) {\n if (msg.role === 'assistant' && msg.id !== undefined) {\n assistantIds.add(msg.id)\n }\n }\n\n for (const msg of messages) {\n if (!('parts' in msg) && msg.role === 'tool' && msg.toolCallId) {\n const id = uniqueToolWireId(\n toolWireId(msg.id, msg.toolCallId, assistantIds),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n msg.metadata,\n msg.createdAt,\n msg.id,\n msg.content,\n )\n wire.push({\n role: 'tool',\n id,\n ...(msg.name !== undefined && { name: msg.name }),\n toolCallId: msg.toolCallId,\n content:\n typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content),\n ...(msg.error !== undefined && { error: msg.error }),\n ...(metadata !== undefined && { metadata }),\n })\n continue\n }\n\n const uiMessage: UIMessage =\n 'parts' in msg ? msg : modelMessageToUIMessage(msg, msg.id)\n const parts: ReadonlyArray<MessagePart> = uiMessage.parts\n usedWireIds.add(uiMessage.id)\n\n if (msg.role === 'system') {\n wire.push(\n toAnchor(\n uiMessage,\n 'system',\n {\n content:\n parts.length > 0\n ? collectText(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n if (msg.role === 'user') {\n wire.push(\n toAnchor(\n uiMessage,\n 'user',\n {\n content:\n parts.length > 0\n ? collectUserContent(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n // assistant: emit reasoning fan-outs first, then anchor, then tool fan-outs\n for (const part of parts) {\n if (part.type === 'thinking') {\n const reasoning: WireReasoningMessage = {\n role: 'reasoning',\n id: uniqueWireId(deriveReasoningId(uiMessage.id, part), usedWireIds),\n content: part.content,\n }\n if (part.signature) {\n reasoning.encryptedValue = part.signature\n }\n wire.push(reasoning)\n }\n }\n\n const text = collectText(parts)\n const toolCalls = collectToolCalls(parts)\n wire.push(\n toAnchor(\n uiMessage,\n 'assistant',\n {\n ...(text !== '' && { content: text }),\n ...(toolCalls && { toolCalls }),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n\n const explicitToolResults = new Set(\n parts.flatMap((part) =>\n part.type === 'tool-result' ? [part.toolCallId] : [],\n ),\n )\n for (const part of parts) {\n if (part.type === 'tool-result') {\n const id = uniqueToolWireId(\n part.id ?? deriveToolMessageId(part.toolCallId),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n part.metadata,\n part.createdAt,\n part.id,\n part.content,\n true,\n )\n wire.push({\n role: 'tool',\n id,\n toolCallId: part.toolCallId,\n ...(part.name !== undefined && { name: part.name }),\n content:\n typeof part.content === 'string'\n ? part.content\n : JSON.stringify(part.content),\n ...(part.error !== undefined && { error: part.error }),\n ...(metadata !== undefined && { metadata }),\n })\n } else if (part.type === 'tool-call') {\n const approved = part.approval?.approved\n if (\n explicitToolResults.has(part.id) ||\n (part.output === undefined &&\n (part.state !== 'approval-responded' || approved === undefined))\n ) {\n continue\n }\n const result =\n part.output !== undefined\n ? normalizeToolResult(part.output)\n : JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n })\n const content =\n typeof result === 'string' ? result : JSON.stringify(result)\n wire.push({\n role: 'tool',\n id: uniqueToolWireId(deriveToolMessageId(part.id), usedWireIds),\n toolCallId: part.id,\n content,\n metadata: rebuiltToolMetadata(\n undefined,\n undefined,\n undefined,\n result,\n ),\n })\n }\n }\n }\n\n return wire\n}\n\nfunction toAnchor(\n msg: UIMessage,\n role: 'system',\n extras: { content: string },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'user',\n extras: { content: string | Array<InputContent> },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireUserMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'assistant',\n extras: {\n content?: string\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireAssistantMessage\nfunction toAnchor(\n msg: UIMessage,\n role: UIMessage['role'],\n extras: {\n content?: string | Array<InputContent>\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage | WireUserMessage | WireAssistantMessage {\n const metadata = messageMetadata(msg, parts, includeSnapshotStructuredOutput)\n const base = {\n id: msg.id,\n ...(msg.name !== undefined && { name: msg.name }),\n ...(metadata !== undefined && { metadata }),\n }\n if (role === 'system') {\n return { ...base, role, content: String(extras.content ?? '') }\n }\n if (role === 'user') {\n return { ...base, role, content: extras.content ?? '' }\n }\n return {\n ...base,\n role,\n ...(typeof extras.content === 'string' && { content: extras.content }),\n ...(extras.toolCalls !== undefined && { toolCalls: extras.toolCalls }),\n }\n}\n\nfunction messageMetadata(\n msg: UIMessage,\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): MetadataRecord | undefined {\n const base: MetadataRecord = { ...(msg.metadata ?? {}) }\n const previousTanstack = tanstackMetadata(msg)\n const tanstack: TanStackMessageMetadata = {}\n if (previousTanstack?.model !== undefined)\n tanstack.model = previousTanstack.model\n if (previousTanstack?.signature !== undefined)\n tanstack.signature = previousTanstack.signature\n const createdAt = coerceCreatedAt(msg.createdAt)\n if (createdAt !== undefined) tanstack.createdAt = createdAt.toISOString()\n\n const structuredOutput = serializedStructuredOutput(\n parts,\n includeSnapshotStructuredOutput,\n )\n if (structuredOutput) tanstack.structuredOutput = structuredOutput\n\n const toolCallMetadata: Record<string, unknown> = {}\n for (const part of parts) {\n if (part.type === 'tool-call' && part.metadata !== undefined) {\n toolCallMetadata[part.id] = part.metadata\n }\n }\n if (Object.keys(toolCallMetadata).length > 0) {\n tanstack.toolCallMetadata = toolCallMetadata\n }\n\n const uiResources = parts.filter(\n (p): p is UIResourcePart => p.type === 'ui-resource',\n )\n if (uiResources.length > 0) tanstack.uiResources = uiResources\n\n if (Object.keys(tanstack).length > 0) base.tanstack = tanstack\n else delete base.tanstack\n return Object.keys(base).length > 0 ? base : undefined\n}\n\nfunction serializedStructuredOutput(\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): TanStackMessageMetadata['structuredOutput'] | undefined {\n for (const p of parts) {\n if (\n p.type === 'structured-output' &&\n (includeSnapshotStructuredOutput || p.status !== 'complete')\n ) {\n return structuredOutputMetadata(p, includeSnapshotStructuredOutput)\n }\n }\n return undefined\n}\n\nfunction structuredOutputMetadata(\n part: StructuredOutputPart,\n includeSnapshotStructuredOutput: boolean,\n): NonNullable<TanStackMessageMetadata['structuredOutput']> {\n return {\n status: part.status,\n raw: part.raw,\n ...(includeSnapshotStructuredOutput && part.partial !== undefined\n ? { partial: part.partial }\n : {}),\n ...(includeSnapshotStructuredOutput && part.data !== undefined\n ? { data: part.data }\n : {}),\n ...(includeSnapshotStructuredOutput && part.reasoning\n ? { reasoning: part.reasoning }\n : {}),\n ...(part.errorMessage !== undefined && { errorMessage: part.errorMessage }),\n }\n}\n\nfunction collectText(parts: ReadonlyArray<MessagePart>): string {\n // The streamed JSON of a completed structured-output part is the source of\n // truth for multi-turn coherence — emitting it back as assistant content\n // lets the LLM see its own prior structured response. Streaming/errored\n // parts are skipped: they'd ship malformed JSON fragments and confuse the\n // model. `completeStructuredOutputPart` tries hard to populate `raw`\n // (caller → existing buffer → `JSON.stringify(data)`), but the stringify\n // fallback can leave it empty when `data` is unserializable (BigInt,\n // circular). The `p.raw !== ''` guard below is what enforces \"no malformed\n // round-trip\" in that case — without it we'd ship `''` and the model would\n // see an empty assistant turn.\n const out: Array<string> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push(p.content)\n } else if (\n p.type === 'structured-output' &&\n p.status === 'complete' &&\n p.raw !== ''\n ) {\n out.push(p.raw)\n }\n }\n return out.join('')\n}\n\nfunction collectUserContent(\n parts: ReadonlyArray<MessagePart>,\n): string | Array<InputContent> {\n const hasMultimodal = parts.some(\n (p) =>\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document',\n )\n if (!hasMultimodal) {\n return collectText(parts)\n }\n const out: Array<InputContent> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push({ type: 'text', text: p.content })\n } else if (\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document'\n ) {\n out.push(p)\n }\n }\n return out\n}\n\nfunction thoughtSignatureFromMetadata(metadata: unknown): string | undefined {\n if (\n metadata == null ||\n typeof metadata !== 'object' ||\n Array.isArray(metadata)\n ) {\n return undefined\n }\n if (!('thoughtSignature' in metadata)) return undefined\n const value = metadata.thoughtSignature\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction collectToolCalls(\n parts: ReadonlyArray<MessagePart>,\n): Array<ToolCall> | undefined {\n const calls: Array<ToolCall> = []\n for (const p of parts) {\n if (p.type === 'tool-call') {\n const encryptedValue = thoughtSignatureFromMetadata(p.metadata)\n calls.push({\n id: p.id,\n type: 'function',\n function: { name: p.name, arguments: p.arguments },\n ...(encryptedValue !== undefined ? { encryptedValue } : {}),\n })\n }\n }\n return calls.length > 0 ? calls : undefined\n}\n\nfunction deriveReasoningId(messageId: string, part: MessagePart): string {\n return `${messageId}-reasoning-${(part as { id?: string }).id ?? hashContent((part as { content: string }).content)}`\n}\n\nfunction deriveToolMessageId(toolCallId: string): string {\n return `tool-${toolCallId}`\n}\n\nfunction uniqueToolWireId(id: string, used: Set<string>): string {\n return uniqueWireId(id, used)\n}\n\nfunction uniqueWireId(id: string, used: Set<string>): string {\n if (!used.has(id)) {\n used.add(id)\n return id\n }\n let suffix = 2\n while (used.has(`${id}-${suffix}`)) suffix++\n const unique = `${id}-${suffix}`\n used.add(unique)\n return unique\n}\n\nfunction toolWireId(\n id: string | undefined,\n toolCallId: string,\n assistantIds: ReadonlySet<string>,\n): string {\n const derived = deriveToolMessageId(toolCallId)\n if (id === undefined || assistantIds.has(id)) return derived\n return id\n}\n\nfunction hashContent(s: string): string {\n // Cheap deterministic id suffix; collisions are tolerable since\n // reasoning ids only matter for AG-UI server consumers, not for our\n // own server's dedup logic (which keys on toolCallId, not reasoning id).\n let h = 0\n for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0\n return Math.abs(h).toString(36)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ag-ui-wire.js","names":[],"sources":["../../../src/utilities/ag-ui-wire.ts"],"sourcesContent":["import type {\n AssistantMessage,\n InputContent,\n ReasoningMessage,\n SystemMessage,\n ToolCall,\n ToolMessage,\n UserMessage,\n} from '@ag-ui/core'\nimport type {\n ContentPart,\n MessagePart,\n ModelMessage,\n StructuredOutputPart,\n SubagentPart,\n TanStackMessageMetadata,\n UIMessage,\n UIResourcePart,\n} from '../types'\nimport type { MetadataRecord } from './merge-metadata'\nimport { tanstackMetadata } from './merge-metadata'\nimport { normalizeToolResult } from './tool-result'\nimport { wireSubagentInfo, wireSubagentRunId } from './subagent-wire'\nimport type { SubagentWireInfo } from './subagent-wire'\nimport {\n coerceCreatedAt,\n modelMessageToUIMessage,\n} from '../activities/chat/messages'\n\ntype WithMetadata<T> = T & { metadata?: MetadataRecord }\ntype WireSystemMessage = WithMetadata<SystemMessage>\ntype WireUserMessage = WithMetadata<UserMessage>\ntype WireAssistantMessage = WithMetadata<AssistantMessage>\ntype WireToolMessage = WithMetadata<\n ToolMessage & {\n name?: string\n }\n>\ntype WireReasoningMessage = WithMetadata<ReasoningMessage>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction rebuiltToolMetadata(\n metadata: unknown,\n createdAt: unknown,\n id: string | undefined,\n content: string | null | Array<ContentPart>,\n anchorOwnsUiResources = false,\n): MetadataRecord | undefined {\n const source: MetadataRecord = isRecord(metadata) ? metadata : {}\n const tanstack = isRecord(source.tanstack) ? { ...source.tanstack } : {}\n if (anchorOwnsUiResources) delete tanstack.uiResources\n const date = coerceCreatedAt(createdAt)\n const toolResult: NonNullable<TanStackMessageMetadata['toolResult']> = {\n ...(id !== undefined ? { id } : {}),\n ...(date && { createdAt: date.toISOString() }),\n ...(Array.isArray(content) && { content }),\n }\n const result = {\n ...source,\n tanstack: { ...tanstack, toolResult },\n }\n return Object.keys(result).length ? result : undefined\n}\n\nexport type WireMessage =\n | WireSystemMessage\n | WireUserMessage\n | WireAssistantMessage\n | WireToolMessage\n | WireReasoningMessage\n\n/**\n * Serialize TanStack `UIMessage`s and `ModelMessage`s into the AG-UI\n * `RunAgentInput.messages` wire shape. Anchors are spec-only (`id`, `role`,\n * `name`, `content`, `toolCalls`, `metadata`). Tool results and thinking parts\n * on assistant messages are additionally emitted as fan-out\n * `{role:'tool',...}` and `{role:'reasoning',...}` entries for strict AG-UI\n * server consumers. Set `includeSnapshotStructuredOutput` to retain complete\n * structured-output metadata for UI snapshots.\n */\nexport function uiMessagesToWire(\n messages: Array<UIMessage | ModelMessage>,\n options?: { includeSnapshotStructuredOutput: boolean },\n): Array<WireMessage> {\n const wire: Array<WireMessage> = []\n const usedWireIds = new Set<string>(\n messages.flatMap((message) =>\n 'id' in message && message.id && message.role !== 'tool'\n ? [message.id]\n : [],\n ),\n )\n const includeSnapshotStructuredOutput =\n options?.includeSnapshotStructuredOutput ?? false\n\n const assistantIds = new Set<string>()\n for (const msg of messages) {\n if (msg.role === 'assistant' && msg.id !== undefined) {\n assistantIds.add(msg.id)\n }\n }\n\n for (const msg of messages) {\n if (!('parts' in msg) && msg.role === 'tool' && msg.toolCallId) {\n const id = uniqueToolWireId(\n toolWireId(msg.id, msg.toolCallId, assistantIds),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n msg.metadata,\n msg.createdAt,\n msg.id,\n msg.content,\n )\n wire.push({\n role: 'tool',\n id,\n ...(msg.name !== undefined && { name: msg.name }),\n toolCallId: msg.toolCallId,\n content:\n typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content),\n ...(msg.error !== undefined && { error: msg.error }),\n ...(metadata !== undefined && { metadata }),\n })\n continue\n }\n\n const uiMessage: UIMessage =\n 'parts' in msg ? msg : modelMessageToUIMessage(msg, msg.id)\n const parts: ReadonlyArray<MessagePart> = uiMessage.parts\n usedWireIds.add(uiMessage.id)\n\n if (msg.role === 'system') {\n wire.push(\n toAnchor(\n uiMessage,\n 'system',\n {\n content:\n parts.length > 0\n ? collectText(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n if (msg.role === 'user') {\n wire.push(\n toAnchor(\n uiMessage,\n 'user',\n {\n content:\n parts.length > 0\n ? collectUserContent(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n // assistant: emit reasoning fan-outs first, then anchor, then tool fan-outs\n for (const part of parts) {\n if (part.type === 'thinking') {\n const reasoning: WireReasoningMessage = {\n role: 'reasoning',\n id: uniqueWireId(deriveReasoningId(uiMessage.id, part), usedWireIds),\n content: part.content,\n }\n if (part.signature) {\n reasoning.encryptedValue = part.signature\n }\n wire.push(reasoning)\n }\n }\n\n const text = collectText(parts)\n const toolCalls = collectToolCalls(parts)\n wire.push(\n toAnchor(\n uiMessage,\n 'assistant',\n {\n ...(text !== '' && { content: text }),\n ...(toolCalls && { toolCalls }),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n\n const explicitToolResults = new Set(\n parts.flatMap((part) =>\n part.type === 'tool-result' ? [part.toolCallId] : [],\n ),\n )\n for (const part of parts) {\n if (part.type === 'tool-result') {\n const id = uniqueToolWireId(\n part.id ?? deriveToolMessageId(part.toolCallId),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n part.metadata,\n part.createdAt,\n part.id,\n part.content,\n true,\n )\n wire.push({\n role: 'tool',\n id,\n toolCallId: part.toolCallId,\n ...(part.name !== undefined && { name: part.name }),\n content:\n typeof part.content === 'string'\n ? part.content\n : JSON.stringify(part.content),\n ...(part.error !== undefined && { error: part.error }),\n ...(metadata !== undefined && { metadata }),\n })\n } else if (part.type === 'tool-call') {\n const approved = part.approval?.approved\n if (\n explicitToolResults.has(part.id) ||\n (part.output === undefined &&\n (part.state !== 'approval-responded' || approved === undefined))\n ) {\n continue\n }\n const result =\n part.output !== undefined\n ? normalizeToolResult(part.output)\n : JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n })\n const content =\n typeof result === 'string' ? result : JSON.stringify(result)\n wire.push({\n role: 'tool',\n id: uniqueToolWireId(deriveToolMessageId(part.id), usedWireIds),\n toolCallId: part.id,\n content,\n metadata: rebuiltToolMetadata(\n undefined,\n undefined,\n undefined,\n result,\n ),\n })\n }\n }\n\n for (const part of parts) {\n if (part.type === 'subagent') wire.push(...subagentToWire(part, options))\n }\n }\n\n return wire\n}\n\nfunction toAnchor(\n msg: UIMessage,\n role: 'system',\n extras: { content: string },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'user',\n extras: { content: string | Array<InputContent> },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireUserMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'assistant',\n extras: {\n content?: string\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireAssistantMessage\nfunction toAnchor(\n msg: UIMessage,\n role: UIMessage['role'],\n extras: {\n content?: string | Array<InputContent>\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage | WireUserMessage | WireAssistantMessage {\n const metadata = messageMetadata(msg, parts, includeSnapshotStructuredOutput)\n const base = {\n id: msg.id,\n ...(msg.name !== undefined && { name: msg.name }),\n ...(metadata !== undefined && { metadata }),\n }\n if (role === 'system') {\n return { ...base, role, content: String(extras.content ?? '') }\n }\n if (role === 'user') {\n return { ...base, role, content: extras.content ?? '' }\n }\n return {\n ...base,\n role,\n ...(typeof extras.content === 'string' && { content: extras.content }),\n ...(extras.toolCalls !== undefined && { toolCalls: extras.toolCalls }),\n }\n}\n\nfunction messageMetadata(\n msg: UIMessage,\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): MetadataRecord | undefined {\n const base: MetadataRecord = { ...(msg.metadata ?? {}) }\n const previousTanstack = tanstackMetadata(msg)\n const tanstack: TanStackMessageMetadata = {}\n if (previousTanstack?.model !== undefined)\n tanstack.model = previousTanstack.model\n if (previousTanstack?.runId !== undefined)\n tanstack.runId = previousTanstack.runId\n if (previousTanstack?.signature !== undefined)\n tanstack.signature = previousTanstack.signature\n const createdAt = coerceCreatedAt(msg.createdAt)\n if (createdAt !== undefined) tanstack.createdAt = createdAt.toISOString()\n\n const structuredOutput = serializedStructuredOutput(\n parts,\n includeSnapshotStructuredOutput,\n )\n if (structuredOutput) tanstack.structuredOutput = structuredOutput\n\n const toolCallMetadata: Record<string, unknown> = {}\n for (const part of parts) {\n if (part.type === 'tool-call' && part.metadata !== undefined) {\n toolCallMetadata[part.id] = part.metadata\n }\n }\n if (Object.keys(toolCallMetadata).length > 0) {\n tanstack.toolCallMetadata = toolCallMetadata\n }\n\n const uiResources = parts.filter(\n (p): p is UIResourcePart => p.type === 'ui-resource',\n )\n if (uiResources.length > 0) tanstack.uiResources = uiResources\n\n if (Object.keys(tanstack).length > 0) base.tanstack = tanstack\n else delete base.tanstack\n return Object.keys(base).length > 0 ? base : undefined\n}\n\nfunction serializedStructuredOutput(\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): TanStackMessageMetadata['structuredOutput'] | undefined {\n for (const p of parts) {\n if (\n p.type === 'structured-output' &&\n (includeSnapshotStructuredOutput || p.status !== 'complete')\n ) {\n return structuredOutputMetadata(p, includeSnapshotStructuredOutput)\n }\n }\n return undefined\n}\n\nfunction structuredOutputMetadata(\n part: StructuredOutputPart,\n includeSnapshotStructuredOutput: boolean,\n): NonNullable<TanStackMessageMetadata['structuredOutput']> {\n return {\n status: part.status,\n raw: part.raw,\n ...(includeSnapshotStructuredOutput && part.partial !== undefined\n ? { partial: part.partial }\n : {}),\n ...(includeSnapshotStructuredOutput && part.data !== undefined\n ? { data: part.data }\n : {}),\n ...(includeSnapshotStructuredOutput && part.reasoning\n ? { reasoning: part.reasoning }\n : {}),\n ...(part.errorMessage !== undefined && { errorMessage: part.errorMessage }),\n }\n}\n\nfunction collectText(parts: ReadonlyArray<MessagePart>): string {\n // The streamed JSON of a completed structured-output part is the source of\n // truth for multi-turn coherence — emitting it back as assistant content\n // lets the LLM see its own prior structured response. Streaming/errored\n // parts are skipped: they'd ship malformed JSON fragments and confuse the\n // model. `completeStructuredOutputPart` tries hard to populate `raw`\n // (caller → existing buffer → `JSON.stringify(data)`), but the stringify\n // fallback can leave it empty when `data` is unserializable (BigInt,\n // circular). The `p.raw !== ''` guard below is what enforces \"no malformed\n // round-trip\" in that case — without it we'd ship `''` and the model would\n // see an empty assistant turn.\n const out: Array<string> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push(p.content)\n } else if (\n p.type === 'structured-output' &&\n p.status === 'complete' &&\n p.raw !== ''\n ) {\n out.push(p.raw)\n }\n }\n return out.join('')\n}\n\n/**\n * A child's messages, tagged with its AG-UI `subagentRunId`. The card data\n * rides in `metadata.tanstack.subagent`, so the other side can rebuild the\n * card and continue a suspended child.\n */\nfunction subagentToWire(\n part: SubagentPart,\n options?: { includeSnapshotStructuredOutput: boolean },\n): Array<WireMessage> {\n const { subagent } = part\n const info: SubagentWireInfo = {\n name: subagent.name,\n status: subagent.status,\n ...(subagent.description !== undefined && {\n description: subagent.description,\n }),\n ...(subagent.error !== undefined && { error: subagent.error }),\n ...(subagent.interruptIds !== undefined && {\n interruptIds: subagent.interruptIds,\n }),\n ...(subagent.parentSubagentRunId !== undefined && {\n parentSubagentRunId: subagent.parentSubagentRunId,\n }),\n ...(subagent.parentToolCallId !== undefined && {\n parentToolCallId: subagent.parentToolCallId,\n }),\n ...(subagent.metadata !== undefined && { metadata: subagent.metadata }),\n }\n const child = uiMessagesToWire(subagent.messages, options)\n const own = child.some((message) => wireSubagentRunId(message) === undefined)\n const messages: Array<WireMessage> = own\n ? child\n : [{ id: `subagent:${subagent.id}`, role: 'assistant' }, ...child]\n return messages.map((message, index) => {\n const nestedId = wireSubagentRunId(message)\n if (nestedId !== undefined) {\n const nested = wireSubagentInfo(message)\n if (!nested || nested.parentSubagentRunId !== undefined) return message\n return withSubagentInfo(message, nestedId, {\n ...nested,\n parentSubagentRunId: subagent.id,\n })\n }\n return withSubagentInfo(\n message,\n subagent.id,\n !own && index === 0 ? { ...info, placeholder: true } : info,\n )\n })\n}\n\nfunction withSubagentInfo(\n message: WireMessage,\n subagentRunId: string,\n info: SubagentWireInfo,\n): WireMessage {\n const metadata = isRecord(message.metadata) ? message.metadata : {}\n const tanstack = isRecord(metadata.tanstack) ? metadata.tanstack : {}\n return {\n ...message,\n subagentRunId,\n metadata: { ...metadata, tanstack: { ...tanstack, subagent: info } },\n }\n}\n\nfunction collectUserContent(\n parts: ReadonlyArray<MessagePart>,\n): string | Array<InputContent> {\n const hasMultimodal = parts.some(\n (p) =>\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document',\n )\n if (!hasMultimodal) {\n return collectText(parts)\n }\n const out: Array<InputContent> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push({ type: 'text', text: p.content })\n } else if (\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document'\n ) {\n out.push(p)\n }\n }\n return out\n}\n\nfunction thoughtSignatureFromMetadata(metadata: unknown): string | undefined {\n if (\n metadata == null ||\n typeof metadata !== 'object' ||\n Array.isArray(metadata)\n ) {\n return undefined\n }\n if (!('thoughtSignature' in metadata)) return undefined\n const value = metadata.thoughtSignature\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction collectToolCalls(\n parts: ReadonlyArray<MessagePart>,\n): Array<ToolCall> | undefined {\n const calls: Array<ToolCall> = []\n for (const p of parts) {\n if (p.type === 'tool-call') {\n const encryptedValue = thoughtSignatureFromMetadata(p.metadata)\n calls.push({\n id: p.id,\n type: 'function',\n function: { name: p.name, arguments: p.arguments },\n ...(encryptedValue !== undefined ? { encryptedValue } : {}),\n })\n }\n }\n return calls.length > 0 ? calls : undefined\n}\n\nfunction deriveReasoningId(messageId: string, part: MessagePart): string {\n return `${messageId}-reasoning-${(part as { id?: string }).id ?? hashContent((part as { content: string }).content)}`\n}\n\nfunction deriveToolMessageId(toolCallId: string): string {\n return `tool-${toolCallId}`\n}\n\nfunction uniqueToolWireId(id: string, used: Set<string>): string {\n return uniqueWireId(id, used)\n}\n\nfunction uniqueWireId(id: string, used: Set<string>): string {\n if (!used.has(id)) {\n used.add(id)\n return id\n }\n let suffix = 2\n while (used.has(`${id}-${suffix}`)) suffix++\n const unique = `${id}-${suffix}`\n used.add(unique)\n return unique\n}\n\nfunction toolWireId(\n id: string | undefined,\n toolCallId: string,\n assistantIds: ReadonlySet<string>,\n): string {\n const derived = deriveToolMessageId(toolCallId)\n if (id === undefined || assistantIds.has(id)) return derived\n return id\n}\n\nfunction hashContent(s: string): string {\n // Cheap deterministic id suffix; collisions are tolerable since\n // reasoning ids only matter for AG-UI server consumers, not for our\n // own server's dedup logic (which keys on toolCallId, not reasoning id).\n let h = 0\n for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0\n return Math.abs(h).toString(36)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CustomEvent, StreamChunk } from '../types.js';
|
|
2
|
+
/** Mark a CUSTOM chunk so the durability producer keeps it in the batch. */
|
|
3
|
+
export declare function withDurabilityBatchHint(chunk: CustomEvent): CustomEvent;
|
|
4
|
+
export declare function isDurabilityBatchedCustom(chunk: StreamChunk): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Drop the in-process batch hint so it does not sit in the log or on the wire.
|
|
7
|
+
*/
|
|
8
|
+
export declare function stripDurabilityBatchHint(chunk: StreamChunk): StreamChunk;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { tanstackMetadata, withTanstackMetadata } from "./merge-metadata.js";
|
|
2
|
+
import { CUSTOM_EVENT } from "../custom-events.js";
|
|
3
|
+
//#region src/utilities/durability-batch.ts
|
|
4
|
+
/**
|
|
5
|
+
* High-volume CUSTOM names that stay in the durability batch.
|
|
6
|
+
* Everything else flushes as soon as it is emitted.
|
|
7
|
+
*/
|
|
8
|
+
var BATCHED_CUSTOM_EVENT_NAMES = /* @__PURE__ */ new Set([
|
|
9
|
+
CUSTOM_EVENT.PROCESS_STDOUT,
|
|
10
|
+
CUSTOM_EVENT.PROCESS_STDERR,
|
|
11
|
+
"sandbox.file",
|
|
12
|
+
"sandbox.file.diff"
|
|
13
|
+
]);
|
|
14
|
+
function hasBatchHint(chunk) {
|
|
15
|
+
const tanstack = tanstackMetadata(chunk);
|
|
16
|
+
if (tanstack == null) return false;
|
|
17
|
+
return Reflect.get(tanstack, "batch") === true;
|
|
18
|
+
}
|
|
19
|
+
/** Mark a CUSTOM chunk so the durability producer keeps it in the batch. */
|
|
20
|
+
function withDurabilityBatchHint(chunk) {
|
|
21
|
+
return withTanstackMetadata(chunk, { batch: true });
|
|
22
|
+
}
|
|
23
|
+
function isDurabilityBatchedCustom(chunk) {
|
|
24
|
+
if (chunk.type !== "CUSTOM") return false;
|
|
25
|
+
if (BATCHED_CUSTOM_EVENT_NAMES.has(chunk.name)) return true;
|
|
26
|
+
return hasBatchHint(chunk);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Drop the in-process batch hint so it does not sit in the log or on the wire.
|
|
30
|
+
*/
|
|
31
|
+
function stripDurabilityBatchHint(chunk) {
|
|
32
|
+
const tanstack = tanstackMetadata(chunk);
|
|
33
|
+
if (tanstack == null || Reflect.get(tanstack, "batch") !== true) return chunk;
|
|
34
|
+
Reflect.deleteProperty(tanstack, "batch");
|
|
35
|
+
const metadata = chunk.metadata;
|
|
36
|
+
if (metadata != null && Object.keys(tanstack).length === 0) {
|
|
37
|
+
Reflect.deleteProperty(metadata, "tanstack");
|
|
38
|
+
if (Object.keys(metadata).length === 0) Reflect.deleteProperty(chunk, "metadata");
|
|
39
|
+
}
|
|
40
|
+
return chunk;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { isDurabilityBatchedCustom, stripDurabilityBatchHint, withDurabilityBatchHint };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=durability-batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durability-batch.js","names":[],"sources":["../../../src/utilities/durability-batch.ts"],"sourcesContent":["import { CUSTOM_EVENT } from '../custom-events'\nimport type { CustomEvent, StreamChunk } from '../types'\nimport { tanstackMetadata, withTanstackMetadata } from './merge-metadata'\n\n/**\n * High-volume CUSTOM names that stay in the durability batch.\n * Everything else flushes as soon as it is emitted.\n */\nconst BATCHED_CUSTOM_EVENT_NAMES = new Set<string>([\n CUSTOM_EVENT.PROCESS_STDOUT,\n CUSTOM_EVENT.PROCESS_STDERR,\n 'sandbox.file',\n 'sandbox.file.diff',\n])\n\nfunction hasBatchHint(chunk: StreamChunk): boolean {\n const tanstack = tanstackMetadata(chunk)\n if (tanstack == null) return false\n return Reflect.get(tanstack, 'batch') === true\n}\n\n/** Mark a CUSTOM chunk so the durability producer keeps it in the batch. */\nexport function withDurabilityBatchHint(chunk: CustomEvent): CustomEvent {\n return withTanstackMetadata(chunk, { batch: true })\n}\n\nexport function isDurabilityBatchedCustom(chunk: StreamChunk): boolean {\n if (chunk.type !== 'CUSTOM') return false\n if (BATCHED_CUSTOM_EVENT_NAMES.has(chunk.name)) return true\n return hasBatchHint(chunk)\n}\n\n/**\n * Drop the in-process batch hint so it does not sit in the log or on the wire.\n */\nexport function stripDurabilityBatchHint(chunk: StreamChunk): StreamChunk {\n const tanstack = tanstackMetadata(chunk)\n if (tanstack == null || Reflect.get(tanstack, 'batch') !== true) return chunk\n Reflect.deleteProperty(tanstack, 'batch')\n const metadata = chunk.metadata\n if (metadata != null && Object.keys(tanstack).length === 0) {\n Reflect.deleteProperty(metadata, 'tanstack')\n if (Object.keys(metadata).length === 0) {\n Reflect.deleteProperty(chunk, 'metadata')\n }\n }\n return chunk\n}\n"],"mappings":";;;;;;;AAQA,IAAM,6CAA6B,IAAI,IAAY;CACjD,aAAa;CACb,aAAa;CACb;CACA;AACF,CAAC;AAED,SAAS,aAAa,OAA6B;CACjD,MAAM,WAAW,iBAAiB,KAAK;CACvC,IAAI,YAAY,MAAM,OAAO;CAC7B,OAAO,QAAQ,IAAI,UAAU,OAAO,MAAM;AAC5C;;AAGA,SAAgB,wBAAwB,OAAiC;CACvE,OAAO,qBAAqB,OAAO,EAAE,OAAO,KAAK,CAAC;AACpD;AAEA,SAAgB,0BAA0B,OAA6B;CACrE,IAAI,MAAM,SAAS,UAAU,OAAO;CACpC,IAAI,2BAA2B,IAAI,MAAM,IAAI,GAAG,OAAO;CACvD,OAAO,aAAa,KAAK;AAC3B;;;;AAKA,SAAgB,yBAAyB,OAAiC;CACxE,MAAM,WAAW,iBAAiB,KAAK;CACvC,IAAI,YAAY,QAAQ,QAAQ,IAAI,UAAU,OAAO,MAAM,MAAM,OAAO;CACxE,QAAQ,eAAe,UAAU,OAAO;CACxC,MAAM,WAAW,MAAM;CACvB,IAAI,YAAY,QAAQ,OAAO,KAAK,QAAQ,CAAC,CAAC,WAAW,GAAG;EAC1D,QAAQ,eAAe,UAAU,UAAU;EAC3C,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC,WAAW,GACnC,QAAQ,eAAe,OAAO,UAAU;CAE5C;CACA,OAAO;AACT"}
|
|
@@ -7,11 +7,16 @@ import { specKeysFor } from "./spec-event-keys.js";
|
|
|
7
7
|
function stringField(value) {
|
|
8
8
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
9
9
|
}
|
|
10
|
+
function chunkFields(chunk) {
|
|
11
|
+
const fields = {};
|
|
12
|
+
for (const key of Object.keys(chunk)) fields[key] = Reflect.get(chunk, key);
|
|
13
|
+
return fields;
|
|
14
|
+
}
|
|
10
15
|
function encryptedValueExtras(chunk) {
|
|
11
16
|
const extras = [];
|
|
12
17
|
const timestamp = "timestamp" in chunk && typeof chunk.timestamp === "number" ? chunk.timestamp : void 0;
|
|
13
18
|
if (typeof chunk.signature === "string" && chunk.signature !== "") {
|
|
14
|
-
const source = chunk;
|
|
19
|
+
const source = chunkFields(chunk);
|
|
15
20
|
const toolCallId = stringField(source.toolCallId);
|
|
16
21
|
const entityId = stringField(chunk.stepId) ?? stringField(source.stepName) ?? stringField(source.messageId) ?? toolCallId;
|
|
17
22
|
if (entityId !== void 0) extras.push(reasoningEncryptedValue({
|
|
@@ -34,7 +39,7 @@ function encryptedValueExtras(chunk) {
|
|
|
34
39
|
}
|
|
35
40
|
function normalizeStreamChunk(chunk) {
|
|
36
41
|
const specKeys = specKeysFor(chunk.type);
|
|
37
|
-
const source = chunk;
|
|
42
|
+
const source = chunkFields(chunk);
|
|
38
43
|
const specChunk = {};
|
|
39
44
|
for (const key of Object.keys(chunk)) if (specKeys.has(key)) specChunk[key] = source[key];
|
|
40
45
|
if (chunk.type === EventType.TOOL_CALL_START) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize-stream-chunk.js","names":[],"sources":["../../../src/utilities/normalize-stream-chunk.ts"],"sourcesContent":["import { EventType } from '../types'\nimport type { StreamChunk, ToolCallResultEvent } from '../types'\nimport type { AdapterYieldChunk } from './adapter-yield-chunk'\nimport { isTanstackUsage, toSpecTokenUsage } from './ag-ui-usage'\nimport type { MetadataRecord } from './merge-metadata'\nimport { withTanstackMetadata } from './merge-metadata'\nimport { reasoningEncryptedValue } from './reasoning-encrypted-value'\nimport { specKeysFor } from './spec-event-keys'\n\nfunction stringField(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction encryptedValueExtras(chunk: AdapterYieldChunk): Array<StreamChunk> {\n const extras: Array<StreamChunk> = []\n const timestamp =\n 'timestamp' in chunk && typeof chunk.timestamp === 'number'\n ? chunk.timestamp\n : undefined\n\n if (typeof chunk.signature === 'string' && chunk.signature !== '') {\n const source = chunk
|
|
1
|
+
{"version":3,"file":"normalize-stream-chunk.js","names":[],"sources":["../../../src/utilities/normalize-stream-chunk.ts"],"sourcesContent":["import { EventType } from '../types'\nimport type { StreamChunk, ToolCallResultEvent } from '../types'\nimport type { AdapterYieldChunk } from './adapter-yield-chunk'\nimport { isTanstackUsage, toSpecTokenUsage } from './ag-ui-usage'\nimport type { MetadataRecord } from './merge-metadata'\nimport { withTanstackMetadata } from './merge-metadata'\nimport { reasoningEncryptedValue } from './reasoning-encrypted-value'\nimport { specKeysFor } from './spec-event-keys'\n\nfunction stringField(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction chunkFields(chunk: object) {\n const fields: Record<string, unknown> = {}\n for (const key of Object.keys(chunk)) {\n fields[key] = Reflect.get(chunk, key)\n }\n return fields\n}\n\nfunction encryptedValueExtras(chunk: AdapterYieldChunk): Array<StreamChunk> {\n const extras: Array<StreamChunk> = []\n const timestamp =\n 'timestamp' in chunk && typeof chunk.timestamp === 'number'\n ? chunk.timestamp\n : undefined\n\n if (typeof chunk.signature === 'string' && chunk.signature !== '') {\n const source = chunkFields(chunk)\n const toolCallId = stringField(source.toolCallId)\n const entityId =\n stringField(chunk.stepId) ??\n stringField(source.stepName) ??\n stringField(source.messageId) ??\n toolCallId\n if (entityId !== undefined) {\n extras.push(\n reasoningEncryptedValue({\n subtype: toolCallId && !chunk.stepId ? 'tool-call' : 'message',\n entityId,\n encryptedValue: chunk.signature,\n timestamp,\n }),\n )\n }\n }\n\n if (chunk.type === EventType.TOOL_CALL_START) {\n const thoughtSignature = stringField(\n (chunk.metadata as { thoughtSignature?: unknown } | undefined)\n ?.thoughtSignature,\n )\n if (thoughtSignature !== undefined && chunk.toolCallId) {\n extras.push(\n reasoningEncryptedValue({\n subtype: 'tool-call',\n entityId: chunk.toolCallId,\n encryptedValue: thoughtSignature,\n timestamp,\n }),\n )\n }\n }\n\n return extras\n}\n\nexport function normalizeStreamChunk(\n chunk: AdapterYieldChunk,\n): Array<StreamChunk> {\n const specKeys = specKeysFor(chunk.type)\n const source = chunkFields(chunk)\n const specChunk: Record<string, unknown> & {\n metadata?: MetadataRecord | null\n } = {}\n\n for (const key of Object.keys(chunk)) {\n if (specKeys.has(key)) {\n specChunk[key] = source[key]\n }\n }\n\n if (chunk.type === EventType.TOOL_CALL_START) {\n if (specChunk.toolCallName === undefined && chunk.toolName) {\n specChunk.toolCallName = chunk.toolName\n }\n }\n\n if (chunk.type === EventType.RUN_ERROR && chunk.error != null) {\n if (specChunk.message === undefined && chunk.error.message) {\n specChunk.message = chunk.error.message\n }\n if (specChunk.code === undefined && chunk.error.code !== undefined) {\n specChunk.code = chunk.error.code\n }\n }\n\n const tanstack: MetadataRecord = {}\n\n if (\n chunk.model !== undefined &&\n chunk.type !== EventType.TEXT_MESSAGE_CONTENT &&\n chunk.type !== EventType.TOOL_CALL_ARGS\n ) {\n tanstack.model = chunk.model\n }\n\n if (chunk.finishReason !== undefined) {\n tanstack.finishReason = chunk.finishReason\n }\n\n const interruptErrors = chunk['tanstack:interruptErrors']\n if (interruptErrors !== undefined) {\n tanstack.interruptErrors = interruptErrors\n }\n\n if (chunk.type === EventType.CUSTOM || chunk.type === EventType.RUN_ERROR) {\n if (chunk.threadId !== undefined) {\n tanstack.threadId = chunk.threadId\n }\n if (chunk.runId !== undefined) {\n tanstack.runId = chunk.runId\n }\n }\n\n const skipLeftover = new Set(['result', 'error', 'tanstack:interruptErrors'])\n if (\n chunk.type === EventType.TEXT_MESSAGE_CONTENT ||\n chunk.type === EventType.TOOL_CALL_ARGS\n ) {\n skipLeftover.add('model')\n skipLeftover.add('content')\n skipLeftover.add('args')\n }\n if (chunk.type === EventType.TOOL_CALL_START) {\n skipLeftover.add('toolName')\n }\n for (const key of Object.keys(chunk)) {\n if (specKeys.has(key) || skipLeftover.has(key)) continue\n if (tanstack[key] !== undefined) continue\n const value = source[key]\n if (value !== undefined) {\n tanstack[key] = value\n }\n }\n\n if (\n (chunk.type === EventType.RUN_FINISHED ||\n chunk.type === EventType.RUN_ERROR) &&\n isTanstackUsage(specChunk.usage)\n ) {\n const { usage, leftover } = toSpecTokenUsage(specChunk.usage, {\n model: typeof chunk.model === 'string' ? chunk.model : undefined,\n })\n specChunk.usage = usage\n if (leftover !== undefined) {\n tanstack.usage = leftover\n }\n }\n\n const normalized =\n Object.keys(tanstack).length === 0\n ? specChunk\n : withTanstackMetadata(specChunk, tanstack)\n\n const extras = encryptedValueExtras(chunk)\n const main: Array<StreamChunk> = [normalized as StreamChunk]\n\n if (chunk.type === EventType.TOOL_CALL_END && chunk.result !== undefined) {\n const parentMessageId = source.parentMessageId\n const resultChunk: ToolCallResultEvent = {\n type: EventType.TOOL_CALL_RESULT,\n toolCallId: chunk.toolCallId,\n content: Array.isArray(chunk.result)\n ? JSON.stringify(chunk.result)\n : chunk.result,\n messageId:\n typeof parentMessageId === 'string' && parentMessageId !== ''\n ? parentMessageId\n : chunk.toolCallId,\n }\n if (chunk.state === 'output-error') {\n main.push({\n ...resultChunk,\n metadata: { tanstack: { state: chunk.state } },\n })\n } else {\n main.push(resultChunk)\n }\n }\n\n return [...main, ...extras]\n}\n"],"mappings":"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"}
|
|
@@ -19,11 +19,6 @@ var SPEC_KEYS = /* @__PURE__ */ new Map([
|
|
|
19
19
|
[EventType.TOOL_CALL_END, keys("toolCallId")],
|
|
20
20
|
[EventType.TOOL_CALL_CHUNK, keys("toolCallId", "toolCallName", "parentMessageId", "delta")],
|
|
21
21
|
[EventType.TOOL_CALL_RESULT, keys("messageId", "toolCallId", "content", "role")],
|
|
22
|
-
[EventType.THINKING_START, keys("title")],
|
|
23
|
-
[EventType.THINKING_END, SHARED],
|
|
24
|
-
[EventType.THINKING_TEXT_MESSAGE_START, SHARED],
|
|
25
|
-
[EventType.THINKING_TEXT_MESSAGE_CONTENT, keys("delta")],
|
|
26
|
-
[EventType.THINKING_TEXT_MESSAGE_END, SHARED],
|
|
27
22
|
[EventType.STATE_SNAPSHOT, keys("snapshot")],
|
|
28
23
|
[EventType.STATE_DELTA, keys("delta")],
|
|
29
24
|
[EventType.MESSAGES_SNAPSHOT, keys("messages")],
|
|
@@ -31,7 +26,7 @@ var SPEC_KEYS = /* @__PURE__ */ new Map([
|
|
|
31
26
|
[EventType.ACTIVITY_DELTA, keys("messageId", "activityType", "patch")],
|
|
32
27
|
[EventType.RAW, keys("event", "source")],
|
|
33
28
|
[EventType.CUSTOM, keys("name", "value")],
|
|
34
|
-
[EventType.RUN_STARTED, keys("threadId", "runId", "parentRunId", "input")],
|
|
29
|
+
[EventType.RUN_STARTED, keys("threadId", "runId", "protocolVersion", "parentRunId", "input")],
|
|
35
30
|
[EventType.RUN_FINISHED, keys("threadId", "runId", "result", "outcome", "usage")],
|
|
36
31
|
[EventType.RUN_ERROR, keys("message", "code", "usage")],
|
|
37
32
|
[EventType.STEP_STARTED, keys("stepName")],
|
|
@@ -42,10 +37,20 @@ var SPEC_KEYS = /* @__PURE__ */ new Map([
|
|
|
42
37
|
[EventType.REASONING_MESSAGE_END, keys("messageId")],
|
|
43
38
|
[EventType.REASONING_MESSAGE_CHUNK, keys("messageId", "delta")],
|
|
44
39
|
[EventType.REASONING_END, keys("messageId")],
|
|
45
|
-
[EventType.REASONING_ENCRYPTED_VALUE, keys("subtype", "entityId", "encryptedValue")]
|
|
40
|
+
[EventType.REASONING_ENCRYPTED_VALUE, keys("subtype", "entityId", "encryptedValue")],
|
|
41
|
+
[EventType.SUBAGENT_STARTED, keys("subagentRunId", "name", "description", "parentSubagentRunId", "parentToolCallId", "parentMessageId")],
|
|
42
|
+
[EventType.SUBAGENT_FINISHED, keys("subagentRunId", "result", "outcome")],
|
|
43
|
+
[EventType.SUBAGENT_ERROR, keys("subagentRunId", "message", "code")]
|
|
46
44
|
]);
|
|
45
|
+
var RUN_SCOPED = /* @__PURE__ */ new Set([
|
|
46
|
+
EventType.RUN_STARTED,
|
|
47
|
+
EventType.RUN_FINISHED,
|
|
48
|
+
EventType.RUN_ERROR,
|
|
49
|
+
EventType.MESSAGES_SNAPSHOT
|
|
50
|
+
]);
|
|
51
|
+
var ATTRIBUTABLE_KEYS = new Map([...SPEC_KEYS].filter(([type]) => !RUN_SCOPED.has(type)).map(([type, fields]) => [type, /* @__PURE__ */ new Set([...fields, "subagentRunId"])]));
|
|
47
52
|
function specKeysFor(type) {
|
|
48
|
-
return SPEC_KEYS.get(type) ?? SHARED;
|
|
53
|
+
return ATTRIBUTABLE_KEYS.get(type) ?? SPEC_KEYS.get(type) ?? SHARED;
|
|
49
54
|
}
|
|
50
55
|
function isSpecTopLevelKey(type, key) {
|
|
51
56
|
return specKeysFor(type).has(key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-event-keys.js","names":[],"sources":["../../../src/utilities/spec-event-keys.ts"],"sourcesContent":["import { EventType } from '../types'\n\nconst SHARED: ReadonlySet<string> = new Set([\n 'type',\n 'timestamp',\n 'rawEvent',\n 'metadata',\n])\n\nfunction keys(...fields: Array<string>): ReadonlySet<string> {\n return new Set([...SHARED, ...fields])\n}\n\nconst SPEC_KEYS: ReadonlyMap<string, ReadonlySet<string>> = new Map([\n [EventType.TEXT_MESSAGE_START, keys('messageId', 'role', 'name')],\n [EventType.TEXT_MESSAGE_CONTENT, keys('messageId', 'delta')],\n [EventType.TEXT_MESSAGE_END, keys('messageId')],\n [EventType.TEXT_MESSAGE_CHUNK, keys('messageId', 'role', 'delta', 'name')],\n [\n EventType.TOOL_CALL_START,\n keys('toolCallId', 'toolCallName', 'parentMessageId'),\n ],\n [EventType.TOOL_CALL_ARGS, keys('toolCallId', 'delta')],\n [EventType.TOOL_CALL_END, keys('toolCallId')],\n [\n EventType.TOOL_CALL_CHUNK,\n keys('toolCallId', 'toolCallName', 'parentMessageId', 'delta'),\n ],\n [\n EventType.TOOL_CALL_RESULT,\n keys('messageId', 'toolCallId', 'content', 'role'),\n ],\n [EventType.
|
|
1
|
+
{"version":3,"file":"spec-event-keys.js","names":[],"sources":["../../../src/utilities/spec-event-keys.ts"],"sourcesContent":["import { EventType } from '../types'\n\nconst SHARED: ReadonlySet<string> = new Set([\n 'type',\n 'timestamp',\n 'rawEvent',\n 'metadata',\n])\n\nfunction keys(...fields: Array<string>): ReadonlySet<string> {\n return new Set([...SHARED, ...fields])\n}\n\nconst SPEC_KEYS: ReadonlyMap<string, ReadonlySet<string>> = new Map([\n [EventType.TEXT_MESSAGE_START, keys('messageId', 'role', 'name')],\n [EventType.TEXT_MESSAGE_CONTENT, keys('messageId', 'delta')],\n [EventType.TEXT_MESSAGE_END, keys('messageId')],\n [EventType.TEXT_MESSAGE_CHUNK, keys('messageId', 'role', 'delta', 'name')],\n [\n EventType.TOOL_CALL_START,\n keys('toolCallId', 'toolCallName', 'parentMessageId'),\n ],\n [EventType.TOOL_CALL_ARGS, keys('toolCallId', 'delta')],\n [EventType.TOOL_CALL_END, keys('toolCallId')],\n [\n EventType.TOOL_CALL_CHUNK,\n keys('toolCallId', 'toolCallName', 'parentMessageId', 'delta'),\n ],\n [\n EventType.TOOL_CALL_RESULT,\n keys('messageId', 'toolCallId', 'content', 'role'),\n ],\n [EventType.STATE_SNAPSHOT, keys('snapshot')],\n [EventType.STATE_DELTA, keys('delta')],\n [EventType.MESSAGES_SNAPSHOT, keys('messages')],\n [\n EventType.ACTIVITY_SNAPSHOT,\n keys('messageId', 'activityType', 'content', 'replace'),\n ],\n [EventType.ACTIVITY_DELTA, keys('messageId', 'activityType', 'patch')],\n [EventType.RAW, keys('event', 'source')],\n [EventType.CUSTOM, keys('name', 'value')],\n [\n EventType.RUN_STARTED,\n keys('threadId', 'runId', 'protocolVersion', 'parentRunId', 'input'),\n ],\n [\n EventType.RUN_FINISHED,\n keys('threadId', 'runId', 'result', 'outcome', 'usage'),\n ],\n [EventType.RUN_ERROR, keys('message', 'code', 'usage')],\n [EventType.STEP_STARTED, keys('stepName')],\n [EventType.STEP_FINISHED, keys('stepName')],\n [EventType.REASONING_START, keys('messageId')],\n [EventType.REASONING_MESSAGE_START, keys('messageId', 'role')],\n [EventType.REASONING_MESSAGE_CONTENT, keys('messageId', 'delta')],\n [EventType.REASONING_MESSAGE_END, keys('messageId')],\n [EventType.REASONING_MESSAGE_CHUNK, keys('messageId', 'delta')],\n [EventType.REASONING_END, keys('messageId')],\n [\n EventType.REASONING_ENCRYPTED_VALUE,\n keys('subtype', 'entityId', 'encryptedValue'),\n ],\n [\n EventType.SUBAGENT_STARTED,\n keys(\n 'subagentRunId',\n 'name',\n 'description',\n 'parentSubagentRunId',\n 'parentToolCallId',\n 'parentMessageId',\n ),\n ],\n [EventType.SUBAGENT_FINISHED, keys('subagentRunId', 'result', 'outcome')],\n [EventType.SUBAGENT_ERROR, keys('subagentRunId', 'message', 'code')],\n])\n\nconst RUN_SCOPED = new Set<string>([\n EventType.RUN_STARTED,\n EventType.RUN_FINISHED,\n EventType.RUN_ERROR,\n EventType.MESSAGES_SNAPSHOT,\n])\n\nconst ATTRIBUTABLE_KEYS = new Map(\n [...SPEC_KEYS]\n .filter(([type]) => !RUN_SCOPED.has(type))\n .map(\n ([type, fields]) =>\n [type, new Set([...fields, 'subagentRunId'])] as const,\n ),\n)\n\nexport function specKeysFor(type: string): ReadonlySet<string> {\n return ATTRIBUTABLE_KEYS.get(type) ?? SPEC_KEYS.get(type) ?? SHARED\n}\n\nexport function isSpecTopLevelKey(type: string, key: string): boolean {\n return specKeysFor(type).has(key)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SubagentInfo as AGUISubagentInfo } from '@ag-ui/core';
|
|
2
|
+
import { SubagentHandleData } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Card data that travels on each child wire message, in
|
|
5
|
+
* `metadata.tanstack.subagent`. The messages carry the AG-UI `subagentRunId`.
|
|
6
|
+
*/
|
|
7
|
+
export interface SubagentWireInfo extends AGUISubagentInfo, Pick<SubagentHandleData, 'status' | 'error' | 'interruptIds' | 'parentSubagentRunId' | 'parentToolCallId' | 'metadata'> {
|
|
8
|
+
/** The child has no messages yet. This wire message only holds the card. */
|
|
9
|
+
placeholder?: true;
|
|
10
|
+
}
|
|
11
|
+
export interface SubagentWireGroup<T> {
|
|
12
|
+
id: string;
|
|
13
|
+
info: SubagentWireInfo;
|
|
14
|
+
/** The child's messages without its own tag. Nested children keep theirs. */
|
|
15
|
+
messages: Array<T>;
|
|
16
|
+
/** Index in `top` of the last message before this child, or -1. */
|
|
17
|
+
hostIndex: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function wireSubagentRunId(message: unknown): string | undefined;
|
|
20
|
+
export declare function wireSubagentInfo(message: unknown): SubagentWireInfo | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Split wire messages into the parent's own messages and one group per direct
|
|
23
|
+
* child. A nested child's messages stay inside its parent's group.
|
|
24
|
+
*/
|
|
25
|
+
export declare function splitSubagentWire<T>(messages: ReadonlyArray<T>): {
|
|
26
|
+
top: Array<T>;
|
|
27
|
+
groups: Array<SubagentWireGroup<T>>;
|
|
28
|
+
};
|
|
29
|
+
/** Text a child wrote, for the parent model and for a later child. */
|
|
30
|
+
export declare function subagentWireText(messages: ReadonlyArray<unknown>): string;
|
|
31
|
+
/**
|
|
32
|
+
* The id of the parent assistant message that hosts a routed turn's cards.
|
|
33
|
+
* The persistence recorder writes that message, and a handoff run passes the
|
|
34
|
+
* same id so the stored thread keeps one copy.
|
|
35
|
+
*/
|
|
36
|
+
export declare function subagentHostMessageId(runId: string): string;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
//#region src/utilities/subagent-wire.ts
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function wireSubagentRunId(message) {
|
|
6
|
+
if (!isRecord(message) || "parts" in message) return void 0;
|
|
7
|
+
const id = message.subagentRunId;
|
|
8
|
+
return typeof id === "string" && id !== "" ? id : void 0;
|
|
9
|
+
}
|
|
10
|
+
function wireSubagentInfo(message) {
|
|
11
|
+
if (!isRecord(message) || !isRecord(message.metadata)) return void 0;
|
|
12
|
+
const tanstack = message.metadata.tanstack;
|
|
13
|
+
if (!isRecord(tanstack) || !isRecord(tanstack.subagent)) return void 0;
|
|
14
|
+
const { name, status, error, interruptIds } = tanstack.subagent;
|
|
15
|
+
if (typeof name !== "string" || !isStatus(status)) return void 0;
|
|
16
|
+
const { description, parentSubagentRunId, parentToolCallId, metadata, placeholder } = tanstack.subagent;
|
|
17
|
+
return {
|
|
18
|
+
name,
|
|
19
|
+
status,
|
|
20
|
+
...typeof description === "string" && { description },
|
|
21
|
+
...isRecord(error) && typeof error.message === "string" && { error: {
|
|
22
|
+
message: error.message,
|
|
23
|
+
...typeof error.code === "string" && { code: error.code }
|
|
24
|
+
} },
|
|
25
|
+
...Array.isArray(interruptIds) && { interruptIds: interruptIds.filter((id) => typeof id === "string") },
|
|
26
|
+
...typeof parentSubagentRunId === "string" && { parentSubagentRunId },
|
|
27
|
+
...typeof parentToolCallId === "string" && { parentToolCallId },
|
|
28
|
+
...isRecord(metadata) && { metadata },
|
|
29
|
+
...placeholder === true && { placeholder: true }
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function isStatus(value) {
|
|
33
|
+
return value === "running" || value === "finished" || value === "error" || value === "suspended";
|
|
34
|
+
}
|
|
35
|
+
function untag(message) {
|
|
36
|
+
if (!isRecord(message)) return message;
|
|
37
|
+
const { subagentRunId: _id, ...rest } = message;
|
|
38
|
+
const metadata = isRecord(rest.metadata) ? rest.metadata : void 0;
|
|
39
|
+
const tanstack = isRecord(metadata?.tanstack) ? metadata.tanstack : void 0;
|
|
40
|
+
if (!metadata || !tanstack || !("subagent" in tanstack)) return rest;
|
|
41
|
+
const { subagent: _info, ...tanstackRest } = tanstack;
|
|
42
|
+
return {
|
|
43
|
+
...rest,
|
|
44
|
+
metadata: {
|
|
45
|
+
...metadata,
|
|
46
|
+
tanstack: tanstackRest
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Split wire messages into the parent's own messages and one group per direct
|
|
52
|
+
* child. A nested child's messages stay inside its parent's group.
|
|
53
|
+
*/
|
|
54
|
+
function splitSubagentWire(messages) {
|
|
55
|
+
const parentOf = /* @__PURE__ */ new Map();
|
|
56
|
+
for (const message of messages) {
|
|
57
|
+
const id = wireSubagentRunId(message);
|
|
58
|
+
if (id !== void 0 && !parentOf.has(id)) parentOf.set(id, wireSubagentInfo(message)?.parentSubagentRunId);
|
|
59
|
+
}
|
|
60
|
+
const rootOf = (id) => {
|
|
61
|
+
let current = id;
|
|
62
|
+
for (let depth = 0; depth < 64; depth++) {
|
|
63
|
+
const parent = parentOf.get(current);
|
|
64
|
+
if (parent === void 0 || !parentOf.has(parent)) return current;
|
|
65
|
+
current = parent;
|
|
66
|
+
}
|
|
67
|
+
return current;
|
|
68
|
+
};
|
|
69
|
+
const top = [];
|
|
70
|
+
const groups = /* @__PURE__ */ new Map();
|
|
71
|
+
for (const message of messages) {
|
|
72
|
+
const id = wireSubagentRunId(message);
|
|
73
|
+
if (id === void 0) {
|
|
74
|
+
top.push(message);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const root = rootOf(id);
|
|
78
|
+
let group = groups.get(root);
|
|
79
|
+
if (!group) {
|
|
80
|
+
group = {
|
|
81
|
+
id: root,
|
|
82
|
+
info: {
|
|
83
|
+
name: "subagent",
|
|
84
|
+
status: "finished"
|
|
85
|
+
},
|
|
86
|
+
messages: [],
|
|
87
|
+
hostIndex: top.length - 1
|
|
88
|
+
};
|
|
89
|
+
groups.set(root, group);
|
|
90
|
+
}
|
|
91
|
+
if (id !== root) {
|
|
92
|
+
group.messages.push(message);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const info = wireSubagentInfo(message);
|
|
96
|
+
if (info) group.info = info;
|
|
97
|
+
if (!info?.placeholder) group.messages.push(untag(message));
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
top,
|
|
101
|
+
groups: [...groups.values()]
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** Text a child wrote, for the parent model and for a later child. */
|
|
105
|
+
function subagentWireText(messages) {
|
|
106
|
+
const blocks = [];
|
|
107
|
+
for (const message of messages) {
|
|
108
|
+
if (!isRecord(message) || message.role !== "assistant") continue;
|
|
109
|
+
if (wireSubagentRunId(message) !== void 0) continue;
|
|
110
|
+
const content = message.content;
|
|
111
|
+
if (typeof content === "string" && content.trim() !== "") blocks.push(content.trim());
|
|
112
|
+
}
|
|
113
|
+
const nested = splitSubagentWire(messages).groups;
|
|
114
|
+
for (const group of nested) {
|
|
115
|
+
const text = subagentWireText(group.messages);
|
|
116
|
+
if (text !== "") blocks.push(`${group.info.name}:\n${text}`);
|
|
117
|
+
}
|
|
118
|
+
return blocks.join("\n\n");
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The id of the parent assistant message that hosts a routed turn's cards.
|
|
122
|
+
* The persistence recorder writes that message, and a handoff run passes the
|
|
123
|
+
* same id so the stored thread keeps one copy.
|
|
124
|
+
*/
|
|
125
|
+
function subagentHostMessageId(runId) {
|
|
126
|
+
return `assistant:${runId}`;
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
export { splitSubagentWire, subagentHostMessageId, subagentWireText, wireSubagentInfo, wireSubagentRunId };
|
|
130
|
+
|
|
131
|
+
//# sourceMappingURL=subagent-wire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subagent-wire.js","names":[],"sources":["../../../src/utilities/subagent-wire.ts"],"sourcesContent":["import type { SubagentInfo as AGUISubagentInfo } from '@ag-ui/core'\nimport type { SubagentHandleData } from '../types'\n\n/**\n * Card data that travels on each child wire message, in\n * `metadata.tanstack.subagent`. The messages carry the AG-UI `subagentRunId`.\n */\nexport interface SubagentWireInfo\n extends\n AGUISubagentInfo,\n Pick<\n SubagentHandleData,\n | 'status'\n | 'error'\n | 'interruptIds'\n | 'parentSubagentRunId'\n | 'parentToolCallId'\n | 'metadata'\n > {\n /** The child has no messages yet. This wire message only holds the card. */\n placeholder?: true\n}\n\nexport interface SubagentWireGroup<T> {\n id: string\n info: SubagentWireInfo\n /** The child's messages without its own tag. Nested children keep theirs. */\n messages: Array<T>\n /** Index in `top` of the last message before this child, or -1. */\n hostIndex: number\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nexport function wireSubagentRunId(message: unknown): string | undefined {\n if (!isRecord(message) || 'parts' in message) return undefined\n const id = message.subagentRunId\n return typeof id === 'string' && id !== '' ? id : undefined\n}\n\nexport function wireSubagentInfo(\n message: unknown,\n): SubagentWireInfo | undefined {\n if (!isRecord(message) || !isRecord(message.metadata)) return undefined\n const tanstack = message.metadata.tanstack\n if (!isRecord(tanstack) || !isRecord(tanstack.subagent)) return undefined\n // Wire data comes from the client. Keep only well-formed fields.\n const { name, status, error, interruptIds } = tanstack.subagent\n if (typeof name !== 'string' || !isStatus(status)) return undefined\n const {\n description,\n parentSubagentRunId,\n parentToolCallId,\n metadata,\n placeholder,\n } = tanstack.subagent\n return {\n name,\n status,\n ...(typeof description === 'string' && { description }),\n ...(isRecord(error) &&\n typeof error.message === 'string' && {\n error: {\n message: error.message,\n ...(typeof error.code === 'string' && { code: error.code }),\n },\n }),\n ...(Array.isArray(interruptIds) && {\n interruptIds: interruptIds.filter(\n (id): id is string => typeof id === 'string',\n ),\n }),\n ...(typeof parentSubagentRunId === 'string' && { parentSubagentRunId }),\n ...(typeof parentToolCallId === 'string' && { parentToolCallId }),\n ...(isRecord(metadata) && { metadata }),\n ...(placeholder === true && { placeholder: true as const }),\n }\n}\n\nfunction isStatus(value: unknown): value is SubagentWireInfo['status'] {\n return (\n value === 'running' ||\n value === 'finished' ||\n value === 'error' ||\n value === 'suspended'\n )\n}\n\nfunction untag<T>(message: T): T {\n if (!isRecord(message)) return message\n const { subagentRunId: _id, ...rest } = message\n void _id\n const metadata = isRecord(rest.metadata) ? rest.metadata : undefined\n const tanstack = isRecord(metadata?.tanstack) ? metadata.tanstack : undefined\n if (!metadata || !tanstack || !('subagent' in tanstack)) return rest as T\n const { subagent: _info, ...tanstackRest } = tanstack\n void _info\n return { ...rest, metadata: { ...metadata, tanstack: tanstackRest } } as T\n}\n\n/**\n * Split wire messages into the parent's own messages and one group per direct\n * child. A nested child's messages stay inside its parent's group.\n */\nexport function splitSubagentWire<T>(messages: ReadonlyArray<T>): {\n top: Array<T>\n groups: Array<SubagentWireGroup<T>>\n} {\n const parentOf = new Map<string, string | undefined>()\n for (const message of messages) {\n const id = wireSubagentRunId(message)\n if (id !== undefined && !parentOf.has(id)) {\n parentOf.set(id, wireSubagentInfo(message)?.parentSubagentRunId)\n }\n }\n const rootOf = (id: string) => {\n let current = id\n for (let depth = 0; depth < 64; depth++) {\n const parent = parentOf.get(current)\n if (parent === undefined || !parentOf.has(parent)) return current\n current = parent\n }\n return current\n }\n\n const top: Array<T> = []\n const groups = new Map<string, SubagentWireGroup<T>>()\n for (const message of messages) {\n const id = wireSubagentRunId(message)\n if (id === undefined) {\n top.push(message)\n continue\n }\n const root = rootOf(id)\n let group = groups.get(root)\n if (!group) {\n group = {\n id: root,\n info: { name: 'subagent', status: 'finished' },\n messages: [],\n hostIndex: top.length - 1,\n }\n groups.set(root, group)\n }\n if (id !== root) {\n group.messages.push(message)\n continue\n }\n const info = wireSubagentInfo(message)\n if (info) group.info = info\n if (!info?.placeholder) group.messages.push(untag(message))\n }\n return { top, groups: [...groups.values()] }\n}\n\n/** Text a child wrote, for the parent model and for a later child. */\nexport function subagentWireText(messages: ReadonlyArray<unknown>): string {\n const blocks: Array<string> = []\n for (const message of messages) {\n if (!isRecord(message) || message.role !== 'assistant') continue\n if (wireSubagentRunId(message) !== undefined) continue\n const content = message.content\n if (typeof content === 'string' && content.trim() !== '') {\n blocks.push(content.trim())\n }\n }\n const nested = splitSubagentWire(messages).groups\n for (const group of nested) {\n const text = subagentWireText(group.messages)\n if (text !== '') blocks.push(`${group.info.name}:\\n${text}`)\n }\n return blocks.join('\\n\\n')\n}\n\n/**\n * The id of the parent assistant message that hosts a routed turn's cards.\n * The persistence recorder writes that message, and a handoff run passes the\n * same id so the stored thread keeps one copy.\n */\nexport function subagentHostMessageId(runId: string) {\n return `assistant:${runId}`\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.59.0",
|
|
4
4
|
"description": "Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -85,11 +85,11 @@
|
|
|
85
85
|
"tanstack-intent"
|
|
86
86
|
],
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@ag-ui/core": "
|
|
88
|
+
"@ag-ui/core": "1.0.0",
|
|
89
89
|
"@standard-schema/spec": "^1.1.0",
|
|
90
90
|
"partial-json": "^0.1.7",
|
|
91
|
-
"@tanstack/ai-event-client": "^0.12.
|
|
92
|
-
"@tanstack/ai-utils": "^0.4.
|
|
91
|
+
"@tanstack/ai-event-client": "^0.12.1",
|
|
92
|
+
"@tanstack/ai-utils": "^0.4.1"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
95
|
"@opentelemetry/api": ">=1.9.0"
|
|
@@ -31,7 +31,7 @@ import { grokImage } from '@tanstack/ai-grok'
|
|
|
31
31
|
| `grok-build-0.1` | 256K | Code-specialized; `reasoning` option is not accepted |
|
|
32
32
|
|
|
33
33
|
`GROK_CHAT_MODELS` is exactly these four ids. Image models
|
|
34
|
-
(`GROK_IMAGE_MODELS`): `grok-
|
|
34
|
+
(`GROK_IMAGE_MODELS`): `grok-imagine-image`,
|
|
35
35
|
`grok-imagine-image-2.0`, `grok-imagine-image-quality`.
|
|
36
36
|
|
|
37
37
|
## Provider-Specific modelOptions
|
|
@@ -312,7 +312,7 @@ with `allowUrlFetch: true` on the adapter config
|
|
|
312
312
|
| OpenAI | gpt-image-2 / gpt-image-1 / -mini → `images.edit()` (up to 16). dall-e-2 → edit (1). dall-e-3 throws. | Sora-2 / -pro → `input_reference` (single). Throws if >1. |
|
|
313
313
|
| Gemini | Native (gemini-\*-flash-image, "nano-banana") → multimodal `contents`. Imagen throws. | Veo → first un-roled / `'start_frame'` image is the input image; `'end_frame'` → `lastFrame`; `'reference'` / `'character'` → `referenceImages`. Omni Flash sends image/video parts as interaction content blocks (no role routing). |
|
|
314
314
|
| fal | Per-endpoint field names from a generated map (`pnpm generate:fal-image-fields`). Defaults: 1 input → `image_url`; >1 → `image_urls`; roles → `mask_url` / `control_image_url` / `reference_image_urls`. | Per-endpoint map (e.g. Kling i2v start frame → `image_url`). Defaults: 1 input → `image_url`; `start_frame`/`end_frame` → `start_image_url`/`end_image_url`; `reference` → `reference_image_urls`. |
|
|
315
|
-
| Grok | grok-imagine models → `/v1/images/edits` JSON endpoint (≤3 sources, addressed by xAI in request order; prompt sent verbatim; mask/control throw).
|
|
315
|
+
| Grok | grok-imagine models → `/v1/images/edits` JSON endpoint (≤3 sources, addressed by xAI in request order; prompt sent verbatim; mask/control throw). | Un-roled / `'start_frame'` image → starting frame; `'reference'` / `'character'` → `reference_images` (1.5). On 1.5 a starting frame can be combined with reference inputs (it pins the first frame). A `video` part + `modelOptions.mode: 'edit' \| 'extend'` routes to `/videos/edits` / `/videos/extensions` on `grok-imagine-video` only. |
|
|
316
316
|
| OpenRouter | Prompt parts map 1:1 onto multimodal `text` / `image_url` content parts, preserving interleaved order. | Dedicated async API (`openRouterVideo`): `start_frame`/`end_frame` → `frame_images[]` (`first_frame`/`last_frame`); `reference`/`character` → `input_references[]`; an unroled image defaults to the start frame. Frame roles validated against the model's `supported_frame_images` metadata. |
|
|
317
317
|
| Anthropic | n/a (no image generation API). | n/a |
|
|
318
318
|
|
|
@@ -1174,7 +1174,7 @@ generateSpeech({
|
|
|
1174
1174
|
|
|
1175
1175
|
Not every model accepts image-conditioned prompts. The `prompt` type is
|
|
1176
1176
|
narrowed per model, so passing an image part to a text-only model
|
|
1177
|
-
(dall-e-3, Imagen
|
|
1177
|
+
(dall-e-3, Imagen) is a **compile-time error**; adapters
|
|
1178
1178
|
also throw a clear runtime error as a backstop, so users learn at call
|
|
1179
1179
|
time rather than getting silently wrong output.
|
|
1180
1180
|
|
|
@@ -55,7 +55,7 @@ export async function POST(request: Request) {
|
|
|
55
55
|
|
|
56
56
|
Every hook receives a `ChatMiddlewareContext` as its first argument, which provides
|
|
57
57
|
`requestId`, `streamId`, `phase`, `iteration`, `chunkIndex`, `model`, `provider`,
|
|
58
|
-
`signal`, `abort()`, `defer()`, and more.
|
|
58
|
+
`signal`, `abort()`, `defer()`, and more. `parentRunId` names the run this one continues. `subagentRunId` is set only inside a subagent and names its card.
|
|
59
59
|
|
|
60
60
|
| Hook | When | Second Argument |
|
|
61
61
|
| -------------------------- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
|
|
@@ -609,9 +609,12 @@ driver, or nothing fences a dead host's writes.
|
|
|
609
609
|
a bare string: `message` is the provider's prose, `code` is the stable,
|
|
610
610
|
machine-branchable classification a consumer switches on. Only
|
|
611
611
|
`createOrResume`, `update`, `get`, and `findActiveRun` are required on a
|
|
612
|
-
`RunStore
|
|
613
|
-
leave
|
|
614
|
-
(`store.listReclaimable?.(opts)`).
|
|
612
|
+
`RunStore`. `listByThread`, `listByParentRun`, and `listReclaimable` are
|
|
613
|
+
optional, so a backend can leave any of them out and callers feature-detect
|
|
614
|
+
(`store.listReclaimable?.(opts)`). A subagent child run also stores
|
|
615
|
+
`parentRunId`, `subagentRunId`, and `name`. `createOrResume` writes them on
|
|
616
|
+
the first insert and leaves them unchanged on resume. `reconstructChat` calls
|
|
617
|
+
`listByParentRun` to put the child cards back. Shape your own store with
|
|
615
618
|
`defineRunStore` for autocomplete without a separate `: RunStore` annotation,
|
|
616
619
|
matching `defineLock`; `defineRunStore<const T extends RunStore>(store: T): T`
|
|
617
620
|
returns the argument's own type, so an optional method your store implements
|