@tanstack/ai 0.58.0 → 0.61.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/adapter.d.ts +9 -0
- package/dist/esm/activities/chat/adapter.js +1 -0
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- 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 +462 -26
- 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 +99 -19
- 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 +47 -1
- package/dist/esm/activities/chat/middleware/types.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.js +9 -2
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +46 -1
- package/dist/esm/activities/chat/stream/processor.js +294 -18
- 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 -5
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/embed/adapter.d.ts +7 -0
- package/dist/esm/activities/embed/adapter.js +1 -0
- package/dist/esm/activities/embed/adapter.js.map +1 -1
- package/dist/esm/activities/embed/index.js +2 -0
- package/dist/esm/activities/embed/index.js.map +1 -1
- package/dist/esm/activities/files/adapter.d.ts +97 -0
- package/dist/esm/activities/files/adapter.js +45 -0
- package/dist/esm/activities/files/adapter.js.map +1 -0
- package/dist/esm/activities/files/index.d.ts +66 -0
- package/dist/esm/activities/files/index.js +78 -0
- package/dist/esm/activities/files/index.js.map +1 -0
- package/dist/esm/activities/generateAudio/index.js +1 -1
- package/dist/esm/activities/generateImage/adapter.d.ts +8 -0
- package/dist/esm/activities/generateImage/adapter.js +1 -0
- package/dist/esm/activities/generateImage/adapter.js.map +1 -1
- package/dist/esm/activities/generateImage/index.js +3 -1
- package/dist/esm/activities/generateImage/index.js.map +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/generateVideo/adapter.d.ts +8 -0
- package/dist/esm/activities/generateVideo/adapter.js +1 -0
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.js +3 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateVoice/index.js +1 -1
- package/dist/esm/activities/generateWorld/adapter.d.ts +4 -2
- package/dist/esm/activities/generateWorld/adapter.js.map +1 -1
- package/dist/esm/activities/generateWorld/index.d.ts +4 -3
- package/dist/esm/activities/generateWorld/index.js +6 -5
- package/dist/esm/activities/generateWorld/index.js.map +1 -1
- package/dist/esm/activities/index.d.ts +9 -3
- package/dist/esm/activities/index.js +17 -13
- package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +2 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js +8 -8
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
- package/dist/esm/activities/summarize/index.js +1 -1
- package/dist/esm/client.d.ts +7 -36
- package/dist/esm/client.js +5 -37
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +8 -2
- package/dist/esm/index.js +9 -4
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/types.d.ts +179 -98
- 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 +90 -13
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/content-source.d.ts +60 -0
- package/dist/esm/utilities/content-source.js +85 -0
- package/dist/esm/utilities/content-source.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/provider-executed.d.ts +7 -0
- package/dist/esm/utilities/provider-executed.js +10 -1
- package/dist/esm/utilities/provider-executed.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/dist/esm/utilities/tool-result.d.ts +12 -2
- package/dist/esm/utilities/tool-result.js +23 -3
- package/dist/esm/utilities/tool-result.js.map +1 -1
- package/package.json +3 -3
- package/skills/ai-core/adapter-configuration/SKILL.md +62 -0
- package/skills/ai-core/adapter-configuration/references/grok-adapter.md +1 -1
- package/skills/ai-core/chat-experience/SKILL.md +14 -0
- package/skills/ai-core/media-generation/SKILL.md +10 -2
- package/skills/ai-core/middleware/SKILL.md +7 -4
- package/src/activities/chat/adapter.ts +10 -0
- 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 +734 -30
- package/src/activities/chat/messages.ts +137 -16
- package/src/activities/chat/middleware/run-store.ts +56 -7
- package/src/activities/chat/middleware/types.ts +47 -0
- package/src/activities/chat/stream/message-updaters.ts +24 -2
- package/src/activities/chat/stream/processor.ts +452 -30
- package/src/activities/chat/tools/tool-calls.ts +83 -11
- package/src/activities/embed/adapter.ts +7 -0
- package/src/activities/embed/index.ts +5 -0
- package/src/activities/files/adapter.ts +120 -0
- package/src/activities/files/index.ts +113 -0
- package/src/activities/generateImage/adapter.ts +8 -0
- package/src/activities/generateImage/index.ts +4 -0
- package/src/activities/generateVideo/adapter.ts +8 -0
- package/src/activities/generateVideo/index.ts +7 -0
- package/src/activities/generateWorld/adapter.ts +4 -2
- package/src/activities/generateWorld/index.ts +7 -6
- package/src/activities/index.ts +40 -1
- package/src/activities/summarize/chat-stream-summarize.ts +22 -12
- package/src/client.ts +29 -35
- package/src/index.ts +39 -0
- package/src/middlewares/content-guard.ts +7 -5
- package/src/types.ts +226 -103
- 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 +134 -16
- package/src/utilities/content-source.ts +138 -0
- package/src/utilities/normalize-stream-chunk.ts +10 -2
- package/src/utilities/provider-executed.ts +13 -0
- package/src/utilities/spec-event-keys.ts +34 -7
- package/src/utilities/subagent-wire.ts +184 -0
- package/src/utilities/tool-result.ts +38 -2
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Message as AGUIMessage } from '@ag-ui/core';
|
|
2
|
-
import { ModelMessage, UIMessage, UIResourcePart } from '../../types.js';
|
|
2
|
+
import { ContentPart, ModelMessage, SubagentPart, UIMessage, UIResourcePart } from '../../types.js';
|
|
3
3
|
export declare function safeJsonStringify(value: unknown): string;
|
|
4
|
+
/** Child text for a later turn. The name stays so the next agent can tell the notes apart. */
|
|
5
|
+
export declare function subagentHistoryText(part: SubagentPart): string;
|
|
4
6
|
/**
|
|
5
7
|
* Convert UIMessages or ModelMessages to ModelMessages
|
|
6
8
|
*/
|
|
@@ -82,6 +84,10 @@ export declare function modelMessageToUIMessage(modelMessage: ModelMessage, id?:
|
|
|
82
84
|
* unchanged apart from ensuring an id.
|
|
83
85
|
*/
|
|
84
86
|
export declare function aguiSnapshotMessageToUIMessage(message: AGUIMessage | UIMessage): UIMessage;
|
|
87
|
+
/** Convert wire content parts. Data, url, and file sources pass through. */
|
|
88
|
+
export declare function aguiContentToContentParts(content: Extract<AGUIMessage, {
|
|
89
|
+
role: 'user';
|
|
90
|
+
}>['content']): string | Array<ContentPart>;
|
|
85
91
|
/**
|
|
86
92
|
* Convert an array of ModelMessages to UIMessages
|
|
87
93
|
*
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { tanstackMetadata } from "../../utilities/merge-metadata.js";
|
|
2
|
+
import { isAssistantSegmentOf, isProviderExecutedToolCall } from "../../utilities/provider-executed.js";
|
|
2
3
|
import { isContentPartArray, normalizeToolResult } from "../../utilities/tool-result.js";
|
|
3
|
-
import {
|
|
4
|
+
import { splitSubagentWire, subagentWireText } from "../../utilities/subagent-wire.js";
|
|
4
5
|
//#region src/activities/chat/messages.ts
|
|
5
6
|
function isRecord(value) {
|
|
6
7
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -72,6 +73,27 @@ function getTextContent(content) {
|
|
|
72
73
|
if (typeof content === "string") return content;
|
|
73
74
|
return content.filter((part) => part.type === "text").map((part) => part.content).join("");
|
|
74
75
|
}
|
|
76
|
+
function historyTextFromParts(parts) {
|
|
77
|
+
const blocks = [];
|
|
78
|
+
for (const part of parts) if (part.type === "text" && part.content !== "") blocks.push(part.content);
|
|
79
|
+
else if (part.type === "structured-output" && part.status === "complete" && part.raw !== "") blocks.push(part.raw);
|
|
80
|
+
else if (part.type === "subagent") {
|
|
81
|
+
const nested = subagentHistoryText(part);
|
|
82
|
+
if (nested !== "") blocks.push(nested);
|
|
83
|
+
}
|
|
84
|
+
return blocks.join("\n\n");
|
|
85
|
+
}
|
|
86
|
+
/** Child text for a later turn. The name stays so the next agent can tell the notes apart. */
|
|
87
|
+
function subagentHistoryText(part) {
|
|
88
|
+
const blocks = [];
|
|
89
|
+
for (const message of part.subagent.messages) {
|
|
90
|
+
if (!("parts" in message)) continue;
|
|
91
|
+
const text = historyTextFromParts(message.parts).trim();
|
|
92
|
+
if (text !== "") blocks.push(text);
|
|
93
|
+
}
|
|
94
|
+
if (blocks.length === 0) return "";
|
|
95
|
+
return `${part.subagent.name}:\n${blocks.join("\n\n")}`;
|
|
96
|
+
}
|
|
75
97
|
function toolResultContent(content) {
|
|
76
98
|
return Array.isArray(content) ? content : getTextContent(content);
|
|
77
99
|
}
|
|
@@ -79,6 +101,40 @@ function toolResultContent(content) {
|
|
|
79
101
|
* Convert UIMessages or ModelMessages to ModelMessages
|
|
80
102
|
*/
|
|
81
103
|
function convertMessagesToModelMessages(messages) {
|
|
104
|
+
const { top, groups } = splitSubagentWire(messages);
|
|
105
|
+
if (groups.length === 0) return convertOwnMessages(messages);
|
|
106
|
+
const blocks = /* @__PURE__ */ new Map();
|
|
107
|
+
for (const group of groups) {
|
|
108
|
+
if (group.info.parentToolCallId !== void 0) continue;
|
|
109
|
+
const text = subagentWireText(group.messages);
|
|
110
|
+
if (text === "") continue;
|
|
111
|
+
const host = top.slice(0, group.hostIndex + 1).findLast((message) => message.role === "assistant");
|
|
112
|
+
const hostId = host && "id" in host ? host.id : void 0;
|
|
113
|
+
blocks.set(hostId, [...blocks.get(hostId) ?? [], `${group.info.name}:\n${text}`]);
|
|
114
|
+
}
|
|
115
|
+
const converted = convertOwnMessages(top);
|
|
116
|
+
for (const [hostId, texts] of blocks) {
|
|
117
|
+
const block = texts.join("\n\n");
|
|
118
|
+
const index = hostId === void 0 ? -1 : converted.findIndex((message) => message.role === "assistant" && message.id === hostId);
|
|
119
|
+
const host = converted[index];
|
|
120
|
+
if (!host) {
|
|
121
|
+
converted.push({
|
|
122
|
+
role: "assistant",
|
|
123
|
+
content: block
|
|
124
|
+
});
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
converted[index] = {
|
|
128
|
+
...host,
|
|
129
|
+
content: typeof host.content === "string" && host.content !== "" ? `${host.content}\n\n${block}` : Array.isArray(host.content) ? [...host.content, {
|
|
130
|
+
type: "text",
|
|
131
|
+
content: block
|
|
132
|
+
}] : block
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return converted;
|
|
136
|
+
}
|
|
137
|
+
function convertOwnMessages(messages) {
|
|
82
138
|
const anchoredToolCallIds = /* @__PURE__ */ new Set();
|
|
83
139
|
for (const msg of messages) if ("parts" in msg) {
|
|
84
140
|
for (const part of msg.parts) if (part.type === "tool-result") anchoredToolCallIds.add(part.toolCallId);
|
|
@@ -294,6 +350,7 @@ function assistantMetadata(uiMessage) {
|
|
|
294
350
|
const previous = tanstackMetadata(uiMessage);
|
|
295
351
|
const tanstack = {};
|
|
296
352
|
if (previous?.model !== void 0) tanstack.model = previous.model;
|
|
353
|
+
if (previous?.runId !== void 0) tanstack.runId = previous.runId;
|
|
297
354
|
if (previous?.signature !== void 0) tanstack.signature = previous.signature;
|
|
298
355
|
if (fromParts.length > 0) tanstack.uiResources = fromParts;
|
|
299
356
|
const result = { ...current };
|
|
@@ -436,15 +493,29 @@ function buildAssistantMessages(uiMessage) {
|
|
|
436
493
|
});
|
|
437
494
|
}
|
|
438
495
|
break;
|
|
439
|
-
case "structured-output":
|
|
440
|
-
|
|
441
|
-
|
|
496
|
+
case "structured-output":
|
|
497
|
+
if (part.status === "complete") {
|
|
498
|
+
const serialized = part.raw !== "" ? part.raw : part.data !== void 0 ? safeJsonStringify(part.data) : "";
|
|
499
|
+
if (serialized !== "") {
|
|
500
|
+
current.contentParts.push({
|
|
501
|
+
type: "text",
|
|
502
|
+
content: serialized
|
|
503
|
+
});
|
|
504
|
+
current.structuredOutput = part;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
break;
|
|
508
|
+
case "ui-resource": break;
|
|
509
|
+
case "subagent": {
|
|
510
|
+
const block = part.subagent.parentToolCallId === void 0 ? subagentHistoryText(part) : "";
|
|
511
|
+
if (block !== "") {
|
|
512
|
+
const prefix = current.contentParts.length > 0 ? "\n\n" : "";
|
|
442
513
|
current.contentParts.push({
|
|
443
514
|
type: "text",
|
|
444
|
-
content:
|
|
515
|
+
content: `${prefix}${block}`
|
|
445
516
|
});
|
|
446
|
-
current.structuredOutput = part;
|
|
447
517
|
}
|
|
518
|
+
break;
|
|
448
519
|
}
|
|
449
520
|
}
|
|
450
521
|
flushSegment();
|
|
@@ -612,7 +683,7 @@ function aguiSnapshotMessageToUIMessage(message) {
|
|
|
612
683
|
const createdAt = coerceCreatedAt("createdAt" in message ? message.createdAt : void 0) ?? createdAtFromMetadata(message);
|
|
613
684
|
return applySnapshotMetadata(message, modelMessageToUIMessage({
|
|
614
685
|
role: "tool",
|
|
615
|
-
content: message.content,
|
|
686
|
+
content: isContentPartArray(message.content) ? message.content : aguiContentToContentParts(message.content),
|
|
616
687
|
toolCallId: message.toolCallId,
|
|
617
688
|
..."name" in message && typeof message.name === "string" ? { name: message.name } : {},
|
|
618
689
|
..."id" in message && typeof message.id === "string" ? { id: message.id } : {},
|
|
@@ -704,21 +775,26 @@ function snapshotStructuredOutput(value) {
|
|
|
704
775
|
* AG-UI user content is either a plain string or a multimodal array whose text
|
|
705
776
|
* entries use `{ type: 'text', text }` (vs. TanStack's `{ type: 'text', content }`).
|
|
706
777
|
* Text entries are rewritten to the TanStack shape; image/audio/video/document
|
|
707
|
-
* entries already match `ContentPart` and pass through.
|
|
708
|
-
* TanStack equivalent and are dropped.
|
|
778
|
+
* entries already match `ContentPart` and pass through.
|
|
709
779
|
*/
|
|
710
780
|
function aguiUserContentToParts(content) {
|
|
711
|
-
|
|
781
|
+
const converted = aguiContentToContentParts(content);
|
|
782
|
+
return typeof converted === "string" ? converted ? [{
|
|
712
783
|
type: "text",
|
|
713
|
-
content
|
|
714
|
-
}] : [];
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
784
|
+
content: converted
|
|
785
|
+
}] : [] : converted;
|
|
786
|
+
}
|
|
787
|
+
/** Convert wire content parts. Data, url, and file sources pass through. */
|
|
788
|
+
function aguiContentToContentParts(content) {
|
|
789
|
+
if (typeof content === "string") return content;
|
|
790
|
+
return content.map((part) => {
|
|
791
|
+
if (part.type !== "text") return part;
|
|
792
|
+
const { text, ...rest } = part;
|
|
793
|
+
return {
|
|
794
|
+
...rest,
|
|
795
|
+
content: text
|
|
796
|
+
};
|
|
719
797
|
});
|
|
720
|
-
else if (part.type !== "binary") parts.push(part);
|
|
721
|
-
return parts;
|
|
722
798
|
}
|
|
723
799
|
/**
|
|
724
800
|
* Convert an array of ModelMessages to UIMessages
|
|
@@ -756,6 +832,10 @@ function modelMessagesToUIMessages(modelMessages) {
|
|
|
756
832
|
}
|
|
757
833
|
} else {
|
|
758
834
|
const uiMessage = modelMessageToUIMessage(msg, msg.id);
|
|
835
|
+
if (msg.role === "assistant" && currentAssistantMessage && isAssistantSegmentOf(msg.id, currentAssistantMessage.id)) {
|
|
836
|
+
currentAssistantMessage.parts.push(...uiMessage.parts);
|
|
837
|
+
continue;
|
|
838
|
+
}
|
|
759
839
|
uiMessages.push(uiMessage);
|
|
760
840
|
if (msg.role === "assistant") currentAssistantMessage = uiMessage;
|
|
761
841
|
else currentAssistantMessage = null;
|
|
@@ -791,6 +871,6 @@ function generateMessageId() {
|
|
|
791
871
|
return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`;
|
|
792
872
|
}
|
|
793
873
|
//#endregion
|
|
794
|
-
export { aguiSnapshotMessageToUIMessage, appendUiResourceToModelMessages, coerceCreatedAt, convertMessagesToModelMessages, generateMessageId, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeToUIMessage, restoreToolResultOwnership, safeJsonStringify, uiMessageToModelMessages, uiResourcePartFromCustomValue };
|
|
874
|
+
export { aguiContentToContentParts, aguiSnapshotMessageToUIMessage, appendUiResourceToModelMessages, coerceCreatedAt, convertMessagesToModelMessages, generateMessageId, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeToUIMessage, restoreToolResultOwnership, safeJsonStringify, subagentHistoryText, uiMessageToModelMessages, uiResourcePartFromCustomValue };
|
|
795
875
|
|
|
796
876
|
//# sourceMappingURL=messages.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","names":[],"sources":["../../../../src/activities/chat/messages.ts"],"sourcesContent":["import { isProviderExecutedToolCall } from '../../utilities/provider-executed'\nimport {\n isContentPartArray,\n normalizeToolResult,\n} from '../../utilities/tool-result'\nimport { tanstackMetadata } from '../../utilities/merge-metadata'\nimport type { Message as AGUIMessage } from '@ag-ui/core'\nimport type {\n ContentPart,\n MessagePart,\n ModelMessage,\n StructuredOutputPart,\n TanStackMessageMetadata,\n TextPart,\n ToolCall,\n ToolCallPart,\n UIMessage,\n UIResourcePart,\n} from '../../types'\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n// ===========================\n// Message Converters\n// ===========================\n\n/**\n * Check if a MessagePart is a content part (text, image, audio, video, document)\n * that maps directly to a ModelMessage ContentPart.\n */\nfunction isContentPart(part: MessagePart): part is ContentPart {\n return (\n part.type === 'text' ||\n part.type === 'image' ||\n part.type === 'audio' ||\n part.type === 'video' ||\n part.type === 'document'\n )\n}\n\nexport function safeJsonStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? ''\n } catch {\n return ''\n }\n}\n\nfunction nonEmptyString(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction encryptedValueFrom(value: object): string | undefined {\n if ('encryptedValue' in value) {\n const fromSpec = nonEmptyString(value.encryptedValue)\n if (fromSpec !== undefined) return fromSpec\n }\n return nonEmptyString(tanstackMetadata(value)?.signature)\n}\n\nfunction toolCallFromWire(toolCall: ToolCall, bag: unknown): ToolCall {\n const fromBag =\n bag != null && typeof bag === 'object' && !Array.isArray(bag)\n ? bag\n : undefined\n const encrypted = encryptedValueFrom(toolCall)\n if (bag === null && encrypted === undefined) {\n return { ...toolCall, metadata: null }\n }\n if (fromBag === undefined && encrypted === undefined) return toolCall\n return {\n ...toolCall,\n metadata: {\n ...(fromBag ?? {}),\n ...(encrypted !== undefined ? { thoughtSignature: encrypted } : {}),\n },\n }\n}\n\nfunction parseToolResultContent(content: string): unknown {\n try {\n return JSON.parse(content)\n } catch {\n return content\n }\n}\n\n/**\n * Collapse an array of ContentParts into the most compact ModelMessage content:\n * - Empty array → null\n * - All text parts → joined string (or null if empty)\n * - Mixed content → ContentPart array as-is\n */\nfunction collapseContentParts(\n parts: Array<ContentPart>,\n): string | null | Array<ContentPart> {\n if (parts.length === 0) return null\n\n const allText = parts.every((p) => p.type === 'text')\n if (allText) {\n const joined = parts.map((p) => p.content).join('')\n return joined || null\n }\n\n return parts\n}\n\n/**\n * Extract text content from ModelMessage content (string, null, or ContentPart array).\n * Used when only the text portion is needed (e.g., tool result content).\n */\nfunction getTextContent(\n content: string | null | undefined | Array<ContentPart>,\n): string {\n // Tool-call-only assistant turns carry no text and reach here as `null` or\n // `undefined`; both must collapse to an empty string rather than crash on\n // `.filter` (issue #532 — the interrupt-boundary MessagesSnapshot).\n if (content === null || content === undefined) return ''\n if (typeof content === 'string') return content\n return content\n .filter((part): part is TextPart => part.type === 'text')\n .map((part) => part.content)\n .join('')\n}\n\nfunction toolResultContent(\n content: string | null | undefined | Array<ContentPart>,\n): string | Array<ContentPart> {\n return Array.isArray(content) ? content : getTextContent(content)\n}\n\n/**\n * Convert UIMessages or ModelMessages to ModelMessages\n */\nexport function convertMessagesToModelMessages(\n messages: Array<UIMessage | ModelMessage>,\n): Array<ModelMessage> {\n // Pre-pass: collect toolCallIds already represented in anchor UIMessage parts.\n // Fan-out tool messages whose toolCallId matches an anchored ToolResultPart\n // are AG-UI duplicates and must be dropped to avoid double-feeding the LLM.\n const anchoredToolCallIds = new Set<string>()\n for (const msg of messages) {\n if ('parts' in msg) {\n for (const part of msg.parts) {\n if (part.type === 'tool-result') {\n anchoredToolCallIds.add(part.toolCallId)\n }\n }\n }\n }\n\n const modelMessages: Array<ModelMessage> = []\n let pendingThinking: Array<{ content: string; signature?: string }> = []\n for (const msg of messages) {\n if ('parts' in msg) {\n modelMessages.push(...uiMessageToModelMessages(msg))\n continue\n }\n\n const modelMessage = restoreModelMessageCreatedAt(\n restoreToolResultOwnership(msg),\n )\n const role = (modelMessage as { role: string }).role\n\n if (\n role === 'tool' &&\n modelMessage.toolCallId &&\n anchoredToolCallIds.has(modelMessage.toolCallId)\n ) {\n continue\n }\n\n if (role === 'reasoning') {\n const content = (msg as { content?: string }).content\n const signature = encryptedValueFrom(msg)\n if (content || signature !== undefined) {\n pendingThinking.push({\n content: typeof content === 'string' ? content : '',\n ...(signature !== undefined ? { signature } : {}),\n })\n }\n continue\n }\n\n if (role === 'activity') {\n continue\n }\n\n if (role === 'developer') {\n modelMessages.push({\n role: 'system' as ModelMessage['role'],\n content: (msg as { content: string }).content,\n ...optionalName(modelMessage),\n ...optionalCreatedAt(modelMessage),\n ...(modelMessage.metadata !== undefined && {\n metadata: modelMessage.metadata,\n }),\n })\n continue\n }\n\n if (\n role === 'user' &&\n Array.isArray((msg as { content?: unknown }).content)\n ) {\n const content = (msg as { content: Array<{ type: string }> }).content\n // TanStack ModelMessage text parts use `{ content }`. AG-UI wire text\n // parts use `{ text }`. Only rewrite the AG-UI shape.\n if (\n !content.some(\n (part) =>\n part.type === 'text' && 'text' in part && !('content' in part),\n )\n ) {\n modelMessages.push(modelMessage)\n continue\n }\n const parts = aguiUserContentToParts(\n content as Extract<AGUIMessage, { role: 'user' }>['content'],\n )\n const contentParts = parts.filter(isContentPart)\n modelMessages.push({\n role: 'user',\n content: collapseContentParts(contentParts),\n ...((msg as { id?: string }).id !== undefined && {\n id: (msg as { id: string }).id,\n }),\n ...optionalName(modelMessage),\n ...optionalCreatedAt(modelMessage),\n ...(modelMessage.metadata !== undefined && {\n metadata: modelMessage.metadata,\n }),\n })\n continue\n }\n\n if (role === 'assistant') {\n const source = modelMessage\n const toolCallMetadata = tanstackMetadata(msg)?.toolCallMetadata\n const toolCalls = source.toolCalls?.map((toolCall) =>\n toolCallFromWire(toolCall, toolCallMetadata?.[toolCall.id]),\n )\n modelMessages.push({\n ...source,\n ...(toolCalls !== undefined ? { toolCalls } : {}),\n ...(pendingThinking.length > 0\n ? {\n thinking: [...(source.thinking ?? []), ...pendingThinking],\n }\n : {}),\n })\n pendingThinking = []\n continue\n }\n\n modelMessages.push(modelMessage)\n }\n return modelMessages\n}\n\nfunction restoreModelMessageCreatedAt(message: ModelMessage): ModelMessage {\n const createdAt =\n coerceCreatedAt(message.createdAt) ?? createdAtFromMetadata(message)\n if (createdAt === undefined) {\n if (message.createdAt === undefined) return message\n const { createdAt: _invalid, ...rest } = message\n return rest\n }\n return Object.is(message.createdAt, createdAt)\n ? message\n : { ...message, createdAt }\n}\n\nexport function restoreToolResultOwnership<T extends object>(message: T): T {\n if (!('role' in message) || message.role !== 'tool') return message\n const source = message\n const metadata = tanstackMetadata(source)\n const owned = metadata?.toolResult\n if (!isRecord(owned)) return message\n if ('content' in owned && !isContentPartArray(owned.content)) return message\n const next = { ...message }\n if (!('id' in owned)) Reflect.deleteProperty(next, 'id')\n if (!('createdAt' in owned)) Reflect.deleteProperty(next, 'createdAt')\n if (typeof owned.id === 'string') Reflect.set(next, 'id', owned.id)\n if (typeof owned.createdAt === 'string') {\n const createdAt = coerceCreatedAt(owned.createdAt)\n if (createdAt) Reflect.set(next, 'createdAt', createdAt)\n }\n if (isContentPartArray(owned.content)) {\n Reflect.set(next, 'content', owned.content)\n }\n const sourceMetadata: unknown = Reflect.get(source, 'metadata')\n if (isRecord(sourceMetadata)) {\n const tanstack = sourceMetadata.tanstack\n if (isRecord(tanstack)) {\n const { toolResult: _toolResult, ...restTanstack } = tanstack\n const restMetadata = { ...sourceMetadata }\n if (Object.keys(restTanstack).length) restMetadata.tanstack = restTanstack\n else delete restMetadata.tanstack\n if (Object.keys(restMetadata).length)\n Reflect.set(next, 'metadata', restMetadata)\n else Reflect.deleteProperty(next, 'metadata')\n }\n }\n return next\n}\n\n/**\n * Rebuild a `Date` from a live `Date` or from an ISO string.\n * `JSON.stringify` turns `Date` into a string, so persistence reload\n * and AG-UI wire both land here as strings.\n */\nexport function coerceCreatedAt(value: unknown): Date | undefined {\n if (value instanceof Date) {\n return Number.isNaN(value.getTime()) ? undefined : value\n }\n if (typeof value !== 'string') return undefined\n const createdAt = new Date(value)\n return Number.isNaN(createdAt.getTime()) ? undefined : createdAt\n}\n\nfunction normalizeMessagePart(part: MessagePart): MessagePart {\n if (part.type !== 'tool-result') return part\n const createdAt = coerceCreatedAt(part.createdAt)\n const { createdAt: _createdAt, ...rest } = part\n return createdAt === undefined ? rest : { ...rest, createdAt }\n}\n\nfunction createdAtFromMetadata(source: object): Date | undefined {\n return coerceCreatedAt(tanstackMetadata(source)?.createdAt)\n}\n\nfunction optionalCreatedAt(source: { createdAt?: unknown }): {\n createdAt?: Date\n} {\n const createdAt = coerceCreatedAt(source.createdAt)\n return createdAt !== undefined ? { createdAt } : {}\n}\n\nfunction optionalName(source: { name?: string }): { name?: string } {\n return source.name !== undefined ? { name: source.name } : {}\n}\n\nfunction isUiResourcePart(value: unknown): value is UIResourcePart {\n if (value == null || typeof value !== 'object' || Array.isArray(value)) {\n return false\n }\n if (!('type' in value) || value.type !== 'ui-resource') return false\n if (!('toolCallId' in value) || typeof value.toolCallId !== 'string') {\n return false\n }\n if (!('toolName' in value) || typeof value.toolName !== 'string') {\n return false\n }\n if (\n !('resource' in value) ||\n value.resource == null ||\n typeof value.resource !== 'object' ||\n Array.isArray(value.resource)\n ) {\n return false\n }\n const resource = value.resource\n return (\n 'uri' in resource &&\n typeof resource.uri === 'string' &&\n 'mimeType' in resource &&\n typeof resource.mimeType === 'string'\n )\n}\n\nfunction uiResourceKey(part: UIResourcePart): string {\n return `${part.toolCallId}\\0${part.toolName}\\0${part.resource.uri}`\n}\n\nfunction appendUiResources(\n ui: UIMessage,\n resources: ReadonlyArray<UIResourcePart>,\n): UIMessage {\n if (resources.length === 0) return ui\n const seen = new Set(\n ui.parts.filter(isUiResourcePart).map((part) => uiResourceKey(part)),\n )\n const extra = resources.filter((part) => !seen.has(uiResourceKey(part)))\n if (extra.length === 0) return ui\n return { ...ui, parts: [...ui.parts, ...extra] }\n}\n\n/**\n * Build a UIResourcePart from the value of a CUSTOM `ui-resource` chunk\n * emitted via `ctx.emitCustomEvent('ui-resource', ...)` (MCP Apps). The\n * emission-side value carries `resource`/`serverId`/`toolName` plus the\n * `toolCallId` stamped by the tool-call context wrapper — the `type`\n * discriminator is added here. Returns undefined when the value does not\n * match the ui-resource shape.\n */\nexport function uiResourcePartFromCustomValue(\n value: unknown,\n): UIResourcePart | undefined {\n if (!isRecord(value)) return undefined\n const part: unknown = { type: 'ui-resource', ...value }\n return isUiResourcePart(part) ? part : undefined\n}\n\n/**\n * Store an emitted ui-resource part on the assistant ModelMessage that owns\n * its `toolCallId` (the tool-call anchor), so it survives later\n * MESSAGES_SNAPSHOT chunks — e.g. the interrupt snapshot emitted when the\n * run pauses on a client tool (#1397). Mirrors how `toolCallMetadata` is\n * preserved on the anchor (#867).\n *\n * Returns the SAME array reference when no anchor owns the tool call or the\n * resource is already stored (idempotent).\n */\nexport function appendUiResourceToModelMessages(\n messages: Array<ModelMessage>,\n part: UIResourcePart,\n): Array<ModelMessage> {\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index]\n if (!message || message.role !== 'assistant') continue\n const ownsToolCall = message.toolCalls?.some(\n (toolCall) => toolCall.id === part.toolCallId,\n )\n if (!ownsToolCall) continue\n const previous = tanstackMetadata(message)?.uiResources ?? []\n if (\n previous.some((stored) => uiResourceKey(stored) === uiResourceKey(part))\n ) {\n return messages\n }\n const nextMessage = {\n ...message,\n metadata: {\n ...message.metadata,\n tanstack: {\n ...tanstackMetadata(message),\n uiResources: [...previous, part],\n },\n },\n }\n const next = messages.slice()\n next[index] = nextMessage\n return next\n }\n return messages\n}\n\nfunction assistantMetadata(\n uiMessage: UIMessage,\n): UIMessage['metadata'] | undefined {\n const fromParts = uiMessage.parts.filter(isUiResourcePart)\n const current = uiMessage.metadata ?? {}\n const previous = tanstackMetadata(uiMessage)\n const tanstack: TanStackMessageMetadata = {}\n if (previous?.model !== undefined) tanstack.model = previous.model\n if (previous?.signature !== undefined) tanstack.signature = previous.signature\n if (fromParts.length > 0) tanstack.uiResources = fromParts\n const result = { ...current }\n if (Object.keys(tanstack).length > 0) result.tanstack = tanstack\n else delete result.tanstack\n return Object.keys(result).length > 0 ? result : undefined\n}\n\n/**\n * Convert a UIMessage to ModelMessage(s)\n *\n * Walks the parts array IN ORDER to preserve the interleaving of text,\n * tool calls, and tool results. This is critical for multi-round tool\n * flows where the model generates text, calls a tool, gets the result,\n * then generates more text and calls another tool.\n *\n * The output preserves the sequential structure:\n * text1 → toolCall1 → toolResult1 → text2 → toolCall2 → toolResult2\n * becomes:\n * assistant: {content: \"text1\", toolCalls: [toolCall1]}\n * tool: toolResult1\n * assistant: {content: \"text2\", toolCalls: [toolCall2]}\n * tool: toolResult2\n *\n * @param uiMessage - The UIMessage to convert\n * @returns An array of ModelMessages preserving part ordering\n */\nexport function uiMessageToModelMessages(\n uiMessage: UIMessage,\n): Array<ModelMessage> {\n // Skip system messages - they're handled via systemPrompts, not ModelMessages\n if (uiMessage.role === 'system') {\n return []\n }\n\n // For non-assistant messages (user), use the simpler path since they\n // don't have tool calls or tool results to interleave\n if (uiMessage.role !== 'assistant') {\n return [buildUserOrToolMessage(uiMessage)]\n }\n\n // For assistant messages, walk parts in order to preserve interleaving\n return buildAssistantMessages(uiMessage)\n}\n\n/**\n * Build a single ModelMessage for user messages (simple path).\n * Preserves ordering of text and multimodal content parts.\n */\nfunction buildUserOrToolMessage(uiMessage: UIMessage): ModelMessage {\n const contentParts: Array<ContentPart> = []\n for (const part of uiMessage.parts) {\n if (isContentPart(part)) {\n contentParts.push(part)\n }\n }\n\n return {\n id: uiMessage.id,\n role: uiMessage.role as 'user' | 'assistant' | 'tool',\n content: collapseContentParts(contentParts),\n ...optionalName(uiMessage),\n ...optionalCreatedAt(uiMessage),\n ...(uiMessage.metadata !== undefined && { metadata: uiMessage.metadata }),\n }\n}\n\n// Accumulator for building an assistant segment (content + tool calls)\ninterface AssistantSegment {\n contentParts: Array<ContentPart>\n structuredOutput?: StructuredOutputPart\n toolCalls: Array<{\n id: string\n type: 'function'\n function: { name: string; arguments: string }\n /** Provider-specific metadata that round-trips with the tool call.\n * Untyped at this framework layer; adapters narrow it via their\n * `TToolCallMetadata` generic. */\n metadata?: unknown\n }>\n}\n\nfunction createSegment(): AssistantSegment {\n return { contentParts: [], toolCalls: [] }\n}\n\nfunction isToolCallIncluded(part: ToolCallPart): boolean {\n return (\n part.state === 'input-complete' ||\n part.state === 'complete' ||\n part.state === 'approval-requested' ||\n part.state === 'approval-responded' ||\n part.state === 'error' ||\n part.output !== undefined\n )\n}\n\n/**\n * Build ModelMessages for an assistant UIMessage, preserving the\n * sequential interleaving of text, tool calls, and tool results.\n *\n * Walks parts in order. Text and tool-call parts accumulate into the\n * current \"segment\". When a tool-result part is encountered, the\n * current segment is flushed as an assistant message, then the tool\n * result is emitted as a tool message.\n */\nfunction buildAssistantMessages(uiMessage: UIMessage): Array<ModelMessage> {\n // A single UI message can fan out into several model messages. Keep the\n // shared UI id on each one so persistence can retain the original identity.\n const messageList: Array<ModelMessage> = []\n let current = createSegment()\n let pendingThinking: Array<{ content: string; signature?: string }> = []\n\n // Track emitted tool result IDs to avoid duplicates.\n // A tool call can have BOTH an explicit tool-result part AND an output\n // field on the tool-call part. We only want one per tool call ID.\n const emittedToolResultIds = new Set<string>()\n const identityFields = {\n id: uiMessage.id,\n ...optionalName(uiMessage),\n ...optionalCreatedAt(uiMessage),\n }\n const metadata = assistantMetadata(uiMessage)\n const assistantFields = {\n ...identityFields,\n ...(metadata !== undefined && { metadata }),\n }\n\n function flushSegment(force = false): void {\n const content = collapseContentParts(current.contentParts)\n const hasContent = content !== null\n const hasToolCalls = current.toolCalls.length > 0\n const hasThinking = pendingThinking.length > 0\n\n if (force || hasContent || hasToolCalls || hasThinking) {\n messageList.push({\n ...assistantFields,\n role: 'assistant',\n content,\n ...(hasToolCalls && { toolCalls: current.toolCalls }),\n ...(hasThinking && { thinking: pendingThinking }),\n ...(current.structuredOutput && {\n structuredOutput: current.structuredOutput,\n }),\n })\n pendingThinking = []\n }\n current = createSegment()\n }\n\n for (const part of uiMessage.parts) {\n switch (part.type) {\n case 'text':\n case 'image':\n case 'audio':\n case 'video':\n case 'document':\n current.contentParts.push(part)\n break\n\n case 'tool-call':\n if (isToolCallIncluded(part)) {\n current.toolCalls.push({\n id: part.id,\n type: 'function' as const,\n function: {\n name: part.name,\n arguments: part.arguments,\n },\n ...(part.metadata !== undefined && { metadata: part.metadata }),\n })\n }\n break\n\n case 'tool-result':\n // Flush the current assistant segment before emitting the tool result\n flushSegment(messageList.length === 0)\n\n // Emit the tool result\n if (\n (part.state === 'complete' || part.state === 'error') &&\n !emittedToolResultIds.has(part.toolCallId)\n ) {\n messageList.push({\n ...(part.id !== undefined && { id: part.id }),\n ...optionalCreatedAt(part),\n role: 'tool',\n content: part.content,\n toolCallId: part.toolCallId,\n ...(part.name !== undefined && { name: part.name }),\n ...(part.metadata !== undefined && { metadata: part.metadata }),\n ...(part.error !== undefined && { error: part.error }),\n })\n emittedToolResultIds.add(part.toolCallId)\n }\n break\n\n case 'thinking':\n if (part.content || part.signature) {\n // Provider-executed tools have no tool-result part, so thinking\n // after them has to start the next segment or it replays first.\n if (current.toolCalls.some(isProviderExecutedToolCall)) {\n flushSegment()\n }\n pendingThinking.push({\n content: part.content,\n ...(part.signature && { signature: part.signature }),\n })\n }\n break\n\n case 'structured-output':\n // Only emit completed structured responses into history. Streaming or\n // errored buffers would push malformed JSON into the next LLM turn's\n // assistant content. `raw` is the source of truth; `data` is the\n // defensive fallback for terminal-only completes that didn't ship raw.\n if (part.status === 'complete') {\n const serialized =\n part.raw !== ''\n ? part.raw\n : part.data !== undefined\n ? safeJsonStringify(part.data)\n : ''\n if (serialized !== '') {\n current.contentParts.push({ type: 'text', content: serialized })\n current.structuredOutput = part\n }\n }\n break\n\n case 'ui-resource':\n // MCP Apps widget — rendered client-side only. It must never enter\n // model input, so it is intentionally dropped from the model message.\n break\n\n default:\n break\n }\n }\n\n // Flush any remaining accumulated content\n flushSegment()\n\n // Emit tool results from client tool-call parts with output or approval,\n // but only if not already covered by an explicit tool-result part above.\n // These are appended at the end since they don't have explicit tool-result\n // parts in the parts array to trigger inline emission.\n for (const part of uiMessage.parts) {\n if (part.type !== 'tool-call') continue\n\n // Output takes priority — if the tool has already produced a result,\n // emit the concrete output regardless of approval metadata.\n if (part.output !== undefined && !emittedToolResultIds.has(part.id)) {\n messageList.push({\n role: 'tool',\n content: normalizeToolResult(part.output),\n toolCallId: part.id,\n })\n emittedToolResultIds.add(part.id)\n }\n\n // Approval response without output — emit approval status for iteration tracking\n if (\n part.output === undefined &&\n part.state === 'approval-responded' &&\n part.approval?.approved !== undefined &&\n !emittedToolResultIds.has(part.id)\n ) {\n const approved = part.approval.approved\n messageList.push({\n role: 'tool',\n content: JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n }),\n toolCallId: part.id,\n })\n emittedToolResultIds.add(part.id)\n }\n }\n\n // If no messages were produced (e.g., empty parts), emit a minimal assistant message\n if (messageList.length === 0) {\n messageList.push({\n ...assistantFields,\n role: 'assistant',\n content: null,\n })\n }\n\n return messageList\n}\n\n/**\n * Convert a ModelMessage to UIMessage\n *\n * This conversion creates a parts-based structure:\n * - content field → TextPart\n * - toolCalls array → ToolCallPart[]\n * - role=\"tool\" messages should be converted separately and merged\n *\n * @param modelMessage - The ModelMessage to convert\n * @param id - Optional ID for the UIMessage (generated if not provided)\n * @returns A UIMessage with parts\n */\nexport function modelMessageToUIMessage(\n modelMessage: ModelMessage,\n id?: string,\n): UIMessage {\n const parts: Array<MessagePart> = []\n const createdAt = coerceCreatedAt(modelMessage.createdAt)\n\n if (modelMessage.role === 'assistant' && modelMessage.thinking?.length) {\n for (const thinking of modelMessage.thinking) {\n if (!thinking.content && !thinking.signature) continue\n parts.push({\n type: 'thinking',\n content: thinking.content,\n ...(thinking.signature && { signature: thinking.signature }),\n })\n }\n }\n\n // Handle tool results (when role is \"tool\") - only produce tool-result part,\n // not a text part (the content IS the tool result, not display text)\n const structuredOutput =\n modelMessage.structuredOutput ??\n snapshotStructuredOutput(tanstackMetadata(modelMessage)?.structuredOutput)\n if (modelMessage.role === 'assistant' && structuredOutput) {\n if (\n typeof modelMessage.content === 'string' &&\n modelMessage.content &&\n modelMessage.content !== structuredOutput.raw\n ) {\n const suffix = structuredOutput.raw\n const text =\n suffix !== '' && modelMessage.content.endsWith(suffix)\n ? modelMessage.content.slice(0, -suffix.length)\n : modelMessage.content\n if (text) parts.push({ type: 'text', content: text })\n }\n parts.push(structuredOutput)\n } else if (modelMessage.role === 'tool' && modelMessage.toolCallId) {\n parts.push({\n type: 'tool-result',\n toolCallId: modelMessage.toolCallId,\n content: toolResultContent(modelMessage.content),\n state: modelMessage.error === undefined ? 'complete' : 'error',\n ...(modelMessage.id !== undefined && { id: modelMessage.id }),\n ...(modelMessage.name !== undefined && { name: modelMessage.name }),\n ...(modelMessage.metadata !== undefined && {\n metadata: modelMessage.metadata,\n }),\n ...(createdAt !== undefined && { createdAt }),\n ...(modelMessage.error !== undefined && { error: modelMessage.error }),\n })\n } else if (Array.isArray(modelMessage.content)) {\n // Multimodal content - preserve all content parts as MessageParts\n for (const part of modelMessage.content) {\n parts.push(part)\n }\n } else {\n // String or null content\n const textContent = getTextContent(modelMessage.content)\n if (textContent) {\n parts.push({\n type: 'text',\n content: textContent,\n })\n }\n }\n\n // Handle tool calls\n if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) {\n for (const toolCall of modelMessage.toolCalls) {\n // Model-message arguments are complete, so surface the parsed input.\n // A malformed arguments string just leaves `input` undefined.\n let input: unknown\n try {\n input = JSON.parse(toolCall.function.arguments)\n } catch {\n input = undefined\n }\n parts.push({\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n state: 'input-complete', // Model messages have complete arguments\n ...(input !== undefined && { input }),\n ...(toolCall.metadata !== undefined && { metadata: toolCall.metadata }),\n })\n }\n }\n\n const ui: UIMessage = {\n id: id || generateMessageId(),\n role: modelMessage.role === 'tool' ? 'assistant' : modelMessage.role,\n parts,\n ...optionalName(modelMessage),\n ...(createdAt !== undefined && { createdAt }),\n ...(modelMessage.metadata !== undefined && {\n metadata: modelMessage.metadata,\n }),\n }\n const storedResources = tanstackMetadata(modelMessage)?.uiResources\n return appendUiResources(\n ui,\n Array.isArray(storedResources)\n ? storedResources.filter(isUiResourcePart)\n : [],\n )\n}\n\n/**\n * Normalize a single AG-UI `MESSAGES_SNAPSHOT` message into a `UIMessage`.\n *\n * AG-UI snapshot messages use the wire shape `{ id, role, content }` and have\n * no `parts` array. Casting them directly to `UIMessage` is unsafe: any code\n * that later reads `message.parts` (e.g. the devtools `onToolCallStateChange`\n * handler) crashes with \"Cannot read properties of undefined (reading 'find')\".\n *\n * Each role is mapped to the canonical `UIMessage` shape, reusing\n * `modelMessageToUIMessage` for the roles that share `ModelMessage`'s structure.\n * The original AG-UI `id` is preserved so later `TEXT_MESSAGE_CONTENT` /\n * `TOOL_CALL_*` events still route by `messageId` (falling back to a generated\n * id only when the snapshot omits one). Messages that already carry `parts`\n * (e.g. a TanStack server echoing `UIMessage`s back over the wire) pass through\n * unchanged apart from ensuring an id.\n */\nexport function aguiSnapshotMessageToUIMessage(\n message: AGUIMessage | UIMessage,\n): UIMessage {\n if ('parts' in message) {\n return applySnapshotMetadata(message, {\n ...message,\n id: message.id || generateMessageId(),\n })\n }\n\n const id = message.id || generateMessageId()\n\n switch (message.role) {\n case 'user':\n return applySnapshotMetadata(message, {\n id,\n role: 'user',\n parts: aguiUserContentToParts(message.content),\n })\n case 'assistant': {\n const metadata = tanstackMetadata(message)\n const toolCallMetadata = metadata?.toolCallMetadata\n const structuredOutput = snapshotStructuredOutput(\n metadata?.structuredOutput,\n )\n const toolCalls = message.toolCalls?.map((toolCall) => {\n const callMetadata =\n toolCallMetadata != null && typeof toolCallMetadata === 'object'\n ? (toolCallMetadata as Record<string, unknown>)[toolCall.id]\n : undefined\n return callMetadata !== undefined\n ? { ...toolCall, metadata: callMetadata }\n : toolCall\n })\n return applySnapshotMetadata(\n message,\n modelMessageToUIMessage(\n {\n role: 'assistant',\n content: message.content ?? null,\n ...optionalName(message),\n ...(toolCalls && { toolCalls }),\n ...(structuredOutput && { structuredOutput }),\n },\n id,\n ),\n )\n }\n case 'tool': {\n message = restoreToolResultOwnership(message)\n const createdAt =\n coerceCreatedAt(\n 'createdAt' in message ? message.createdAt : undefined,\n ) ?? createdAtFromMetadata(message)\n return applySnapshotMetadata(\n message,\n modelMessageToUIMessage(\n {\n role: 'tool',\n content: message.content,\n toolCallId: message.toolCallId,\n ...('name' in message && typeof message.name === 'string'\n ? { name: message.name }\n : {}),\n ...('id' in message && typeof message.id === 'string'\n ? { id: message.id }\n : {}),\n ...('metadata' in message && message.metadata != null\n ? { metadata: message.metadata }\n : {}),\n ...(createdAt !== undefined ? { createdAt } : {}),\n ...(message.error !== undefined && { error: message.error }),\n },\n id,\n ),\n )\n }\n case 'system':\n case 'developer':\n // `ModelMessage` has no system/developer role; build the part directly.\n return applySnapshotMetadata(message, {\n id,\n role: 'system',\n parts: message.content\n ? [{ type: 'text', content: message.content }]\n : [],\n })\n case 'reasoning': {\n const signature = encryptedValueFrom(message)\n const content = typeof message.content === 'string' ? message.content : ''\n return applySnapshotMetadata(message, {\n id,\n role: 'assistant',\n parts:\n content || signature !== undefined\n ? [\n {\n type: 'thinking' as const,\n content,\n ...(signature !== undefined ? { signature } : {}),\n },\n ]\n : [],\n })\n }\n case 'activity':\n default:\n // `activity` (and any future role) has no text/parts equivalent today.\n return applySnapshotMetadata(message, {\n id,\n role: 'assistant',\n parts: [],\n })\n }\n}\n\n/** Copy snapshot metadata when it is a record. Rebuild createdAt from tanstack.createdAt. */\nfunction applySnapshotMetadata(source: object, ui: UIMessage): UIMessage {\n const normalizedParts = ui.parts.map((part) => normalizeMessagePart(part))\n if (normalizedParts !== ui.parts) ui = { ...ui, parts: normalizedParts }\n const name =\n 'name' in source && typeof source.name === 'string'\n ? source.name\n : undefined\n let next = name !== undefined ? { ...ui, name } : ui\n\n let metadata: NonNullable<UIMessage['metadata']> | undefined\n if ('metadata' in source) {\n const raw = source.metadata\n if (raw != null && typeof raw === 'object' && !Array.isArray(raw)) {\n metadata = raw as NonNullable<UIMessage['metadata']>\n next = { ...next, metadata }\n }\n }\n\n const createdAt =\n coerceCreatedAt(next.createdAt) ??\n (metadata !== undefined ? createdAtFromMetadata(metadata) : undefined)\n if (createdAt !== undefined && !Object.is(createdAt, next.createdAt)) {\n next = { ...next, createdAt }\n } else if (createdAt === undefined && next.createdAt !== undefined) {\n const { createdAt: _invalid, ...rest } = next\n next = rest\n }\n\n const uiResources = tanstackMetadata(metadata)?.uiResources\n const resources = Array.isArray(uiResources)\n ? uiResources.filter(isUiResourcePart)\n : []\n return appendUiResources(next, resources)\n}\n\nfunction snapshotStructuredOutput(\n value: TanStackMessageMetadata['structuredOutput'],\n): StructuredOutputPart | undefined {\n if (\n value == null ||\n (value.status !== 'streaming' &&\n value.status !== 'complete' &&\n value.status !== 'error') ||\n typeof value.raw !== 'string'\n ) {\n return undefined\n }\n return {\n type: 'structured-output',\n status: value.status,\n raw: value.raw,\n ...(value.partial !== undefined ? { partial: value.partial } : {}),\n ...(value.data !== undefined ? { data: value.data } : {}),\n ...(value.reasoning ? { reasoning: value.reasoning } : {}),\n ...(value.errorMessage !== undefined\n ? { errorMessage: value.errorMessage }\n : {}),\n }\n}\n\n/**\n * Convert AG-UI user message content into `UIMessage` parts.\n *\n * AG-UI user content is either a plain string or a multimodal array whose text\n * entries use `{ type: 'text', text }` (vs. TanStack's `{ type: 'text', content }`).\n * Text entries are rewritten to the TanStack shape; image/audio/video/document\n * entries already match `ContentPart` and pass through. `binary` entries have no\n * TanStack equivalent and are dropped.\n */\nfunction aguiUserContentToParts(\n content: Extract<AGUIMessage, { role: 'user' }>['content'],\n): Array<MessagePart> {\n if (typeof content === 'string') {\n return content ? [{ type: 'text', content }] : []\n }\n\n const parts: Array<MessagePart> = []\n for (const part of content) {\n if (part.type === 'text') {\n parts.push({ type: 'text', content: part.text })\n } else if (part.type !== 'binary') {\n parts.push(part)\n }\n }\n return parts\n}\n\n/**\n * Convert an array of ModelMessages to UIMessages\n *\n * This handles merging tool result messages with their corresponding assistant messages\n *\n * @param modelMessages - Array of ModelMessages to convert\n * @returns Array of UIMessages\n */\nexport function modelMessagesToUIMessages(\n modelMessages: Array<ModelMessage>,\n): Array<UIMessage> {\n const uiMessages: Array<UIMessage> = []\n let currentAssistantMessage: UIMessage | null = null\n\n for (const msg of modelMessages) {\n if (msg.role === 'tool') {\n // Tool result - merge into the last assistant message if possible\n if (\n msg.toolCallId !== undefined &&\n currentAssistantMessage &&\n currentAssistantMessage.role === 'assistant'\n ) {\n const content = toolResultContent(msg.content)\n const toolCallPart = currentAssistantMessage.parts.find(\n (part): part is ToolCallPart =>\n part.type === 'tool-call' && part.id === msg.toolCallId,\n )\n\n if (toolCallPart) {\n toolCallPart.output =\n typeof content === 'string'\n ? parseToolResultContent(content)\n : content\n toolCallPart.state = msg.error === undefined ? 'complete' : 'error'\n }\n\n currentAssistantMessage.parts.push({\n type: 'tool-result',\n toolCallId: msg.toolCallId,\n content,\n state: msg.error === undefined ? 'complete' : 'error',\n ...(msg.id !== undefined &&\n msg.id !== currentAssistantMessage.id && { id: msg.id }),\n ...(msg.name !== undefined && { name: msg.name }),\n ...(msg.metadata !== undefined && { metadata: msg.metadata }),\n ...optionalCreatedAt(msg),\n ...(msg.error !== undefined && { error: msg.error }),\n })\n } else {\n // No assistant message to merge into, create a standalone one\n const toolResultUIMessage = modelMessageToUIMessage(msg, msg.id)\n uiMessages.push(toolResultUIMessage)\n }\n } else {\n // Regular message. Preserve a persisted stable id so a hydrated message\n // keeps the same identity as its live stream (enables in-place resume).\n const uiMessage = modelMessageToUIMessage(msg, msg.id)\n uiMessages.push(uiMessage)\n\n // Track assistant messages for potential tool result merging\n if (msg.role === 'assistant') {\n currentAssistantMessage = uiMessage\n } else {\n currentAssistantMessage = null\n }\n }\n }\n\n return uiMessages\n}\n\n/**\n * Normalize a message (UIMessage or ModelMessage) to a UIMessage\n * Ensures the message has an ID and createdAt timestamp\n *\n * @param message - Either a UIMessage or ModelMessage\n * @param generateId - Function to generate a message ID if needed\n * @returns A UIMessage with guaranteed id and createdAt\n */\nexport function normalizeToUIMessage(\n message: UIMessage | ModelMessage,\n generateId: () => string,\n): UIMessage {\n if ('parts' in message) {\n // Already a UIMessage\n const parts = message.parts.map((part) => normalizeMessagePart(part))\n return {\n ...message,\n parts,\n id: message.id || generateId(),\n createdAt: coerceCreatedAt(message.createdAt) ?? new Date(),\n }\n } else {\n // ModelMessage - convert to UIMessage\n return {\n ...modelMessageToUIMessage(message, generateId()),\n createdAt: coerceCreatedAt(message.createdAt) ?? new Date(),\n }\n }\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"messages.js","names":[],"sources":["../../../../src/activities/chat/messages.ts"],"sourcesContent":["import {\n isAssistantSegmentOf,\n isProviderExecutedToolCall,\n} from '../../utilities/provider-executed'\nimport {\n isContentPartArray,\n normalizeToolResult,\n} from '../../utilities/tool-result'\nimport { tanstackMetadata } from '../../utilities/merge-metadata'\nimport {\n splitSubagentWire,\n subagentWireText,\n} from '../../utilities/subagent-wire'\nimport type { Message as AGUIMessage } from '@ag-ui/core'\nimport type {\n ContentPart,\n MessagePart,\n ModelMessage,\n StructuredOutputPart,\n TanStackMessageMetadata,\n TextPart,\n ToolCall,\n ToolCallPart,\n SubagentPart,\n UIMessage,\n UIResourcePart,\n} from '../../types'\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n// ===========================\n// Message Converters\n// ===========================\n\n/**\n * Check if a MessagePart is a content part (text, image, audio, video, document)\n * that maps directly to a ModelMessage ContentPart.\n */\nfunction isContentPart(part: MessagePart): part is ContentPart {\n return (\n part.type === 'text' ||\n part.type === 'image' ||\n part.type === 'audio' ||\n part.type === 'video' ||\n part.type === 'document'\n )\n}\n\nexport function safeJsonStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? ''\n } catch {\n return ''\n }\n}\n\nfunction nonEmptyString(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction encryptedValueFrom(value: object): string | undefined {\n if ('encryptedValue' in value) {\n const fromSpec = nonEmptyString(value.encryptedValue)\n if (fromSpec !== undefined) return fromSpec\n }\n return nonEmptyString(tanstackMetadata(value)?.signature)\n}\n\nfunction toolCallFromWire(toolCall: ToolCall, bag: unknown): ToolCall {\n const fromBag =\n bag != null && typeof bag === 'object' && !Array.isArray(bag)\n ? bag\n : undefined\n const encrypted = encryptedValueFrom(toolCall)\n if (bag === null && encrypted === undefined) {\n return { ...toolCall, metadata: null }\n }\n if (fromBag === undefined && encrypted === undefined) return toolCall\n return {\n ...toolCall,\n metadata: {\n ...(fromBag ?? {}),\n ...(encrypted !== undefined ? { thoughtSignature: encrypted } : {}),\n },\n }\n}\n\nfunction parseToolResultContent(content: string): unknown {\n try {\n return JSON.parse(content)\n } catch {\n return content\n }\n}\n\n/**\n * Collapse an array of ContentParts into the most compact ModelMessage content:\n * - Empty array → null\n * - All text parts → joined string (or null if empty)\n * - Mixed content → ContentPart array as-is\n */\nfunction collapseContentParts(\n parts: Array<ContentPart>,\n): string | null | Array<ContentPart> {\n if (parts.length === 0) return null\n\n const allText = parts.every((p) => p.type === 'text')\n if (allText) {\n const joined = parts.map((p) => p.content).join('')\n return joined || null\n }\n\n return parts\n}\n\n/**\n * Extract text content from ModelMessage content (string, null, or ContentPart array).\n * Used when only the text portion is needed (e.g., tool result content).\n */\nfunction getTextContent(\n content: string | null | undefined | Array<ContentPart>,\n): string {\n // Tool-call-only assistant turns carry no text and reach here as `null` or\n // `undefined`; both must collapse to an empty string rather than crash on\n // `.filter` (issue #532 — the interrupt-boundary MessagesSnapshot).\n if (content === null || content === undefined) return ''\n if (typeof content === 'string') return content\n return content\n .filter((part): part is TextPart => part.type === 'text')\n .map((part) => part.content)\n .join('')\n}\n\nfunction historyTextFromParts(parts: ReadonlyArray<MessagePart>): string {\n const blocks: Array<string> = []\n for (const part of parts) {\n if (part.type === 'text' && part.content !== '') {\n blocks.push(part.content)\n } else if (\n part.type === 'structured-output' &&\n part.status === 'complete' &&\n part.raw !== ''\n ) {\n blocks.push(part.raw)\n } else if (part.type === 'subagent') {\n const nested = subagentHistoryText(part)\n if (nested !== '') blocks.push(nested)\n }\n }\n return blocks.join('\\n\\n')\n}\n\n/** Child text for a later turn. The name stays so the next agent can tell the notes apart. */\nexport function subagentHistoryText(part: SubagentPart): string {\n const blocks: Array<string> = []\n for (const message of part.subagent.messages) {\n if (!('parts' in message)) continue\n const text = historyTextFromParts(message.parts).trim()\n if (text !== '') blocks.push(text)\n }\n if (blocks.length === 0) return ''\n return `${part.subagent.name}:\\n${blocks.join('\\n\\n')}`\n}\n\nfunction toolResultContent(\n content: string | null | undefined | Array<ContentPart>,\n): string | Array<ContentPart> {\n return Array.isArray(content) ? content : getTextContent(content)\n}\n\n/**\n * Convert UIMessages or ModelMessages to ModelMessages\n */\nexport function convertMessagesToModelMessages(\n messages: Array<UIMessage | ModelMessage>,\n): Array<ModelMessage> {\n const { top, groups } = splitSubagentWire(messages)\n if (groups.length === 0) return convertOwnMessages(messages)\n\n // Child wire messages leave the parent history. The parent model reads each\n // child's text on the assistant message before it, the same as for a UI\n // subagent part. A child that a tool call started reports through the tool\n // result instead.\n const blocks = new Map<string | undefined, Array<string>>()\n for (const group of groups) {\n if (group.info.parentToolCallId !== undefined) continue\n const text = subagentWireText(group.messages)\n if (text === '') continue\n const host = top\n .slice(0, group.hostIndex + 1)\n .findLast((message) => message.role === 'assistant')\n const hostId = host && 'id' in host ? host.id : undefined\n blocks.set(hostId, [\n ...(blocks.get(hostId) ?? []),\n `${group.info.name}:\\n${text}`,\n ])\n }\n const converted = convertOwnMessages(top)\n for (const [hostId, texts] of blocks) {\n const block = texts.join('\\n\\n')\n const index =\n hostId === undefined\n ? -1\n : converted.findIndex(\n (message) => message.role === 'assistant' && message.id === hostId,\n )\n const host = converted[index]\n if (!host) {\n converted.push({ role: 'assistant', content: block })\n continue\n }\n converted[index] = {\n ...host,\n content:\n typeof host.content === 'string' && host.content !== ''\n ? `${host.content}\\n\\n${block}`\n : Array.isArray(host.content)\n ? [...host.content, { type: 'text', content: block }]\n : block,\n }\n }\n return converted\n}\n\nfunction convertOwnMessages(\n messages: Array<UIMessage | ModelMessage>,\n): Array<ModelMessage> {\n // Pre-pass: collect toolCallIds already represented in anchor UIMessage parts.\n // Fan-out tool messages whose toolCallId matches an anchored ToolResultPart\n // are AG-UI duplicates and must be dropped to avoid double-feeding the LLM.\n const anchoredToolCallIds = new Set<string>()\n for (const msg of messages) {\n if ('parts' in msg) {\n for (const part of msg.parts) {\n if (part.type === 'tool-result') {\n anchoredToolCallIds.add(part.toolCallId)\n }\n }\n }\n }\n\n const modelMessages: Array<ModelMessage> = []\n let pendingThinking: Array<{ content: string; signature?: string }> = []\n for (const msg of messages) {\n if ('parts' in msg) {\n modelMessages.push(...uiMessageToModelMessages(msg))\n continue\n }\n\n const modelMessage = restoreModelMessageCreatedAt(\n restoreToolResultOwnership(msg),\n )\n const role = (modelMessage as { role: string }).role\n\n if (\n role === 'tool' &&\n modelMessage.toolCallId &&\n anchoredToolCallIds.has(modelMessage.toolCallId)\n ) {\n continue\n }\n\n if (role === 'reasoning') {\n const content = (msg as { content?: string }).content\n const signature = encryptedValueFrom(msg)\n if (content || signature !== undefined) {\n pendingThinking.push({\n content: typeof content === 'string' ? content : '',\n ...(signature !== undefined ? { signature } : {}),\n })\n }\n continue\n }\n\n if (role === 'activity') {\n continue\n }\n\n if (role === 'developer') {\n modelMessages.push({\n role: 'system' as ModelMessage['role'],\n content: (msg as { content: string }).content,\n ...optionalName(modelMessage),\n ...optionalCreatedAt(modelMessage),\n ...(modelMessage.metadata !== undefined && {\n metadata: modelMessage.metadata,\n }),\n })\n continue\n }\n\n if (\n role === 'user' &&\n Array.isArray((msg as { content?: unknown }).content)\n ) {\n const content = (msg as { content: Array<{ type: string }> }).content\n // TanStack ModelMessage text parts use `{ content }`. AG-UI wire text\n // parts use `{ text }`. Only rewrite the AG-UI shape.\n if (\n !content.some(\n (part) =>\n part.type === 'text' && 'text' in part && !('content' in part),\n )\n ) {\n modelMessages.push(modelMessage)\n continue\n }\n const parts = aguiUserContentToParts(\n content as Extract<AGUIMessage, { role: 'user' }>['content'],\n )\n const contentParts = parts.filter(isContentPart)\n modelMessages.push({\n role: 'user',\n content: collapseContentParts(contentParts),\n ...((msg as { id?: string }).id !== undefined && {\n id: (msg as { id: string }).id,\n }),\n ...optionalName(modelMessage),\n ...optionalCreatedAt(modelMessage),\n ...(modelMessage.metadata !== undefined && {\n metadata: modelMessage.metadata,\n }),\n })\n continue\n }\n\n if (role === 'assistant') {\n const source = modelMessage\n const toolCallMetadata = tanstackMetadata(msg)?.toolCallMetadata\n const toolCalls = source.toolCalls?.map((toolCall) =>\n toolCallFromWire(toolCall, toolCallMetadata?.[toolCall.id]),\n )\n modelMessages.push({\n ...source,\n ...(toolCalls !== undefined ? { toolCalls } : {}),\n ...(pendingThinking.length > 0\n ? {\n thinking: [...(source.thinking ?? []), ...pendingThinking],\n }\n : {}),\n })\n pendingThinking = []\n continue\n }\n\n modelMessages.push(modelMessage)\n }\n return modelMessages\n}\n\nfunction restoreModelMessageCreatedAt(message: ModelMessage): ModelMessage {\n const createdAt =\n coerceCreatedAt(message.createdAt) ?? createdAtFromMetadata(message)\n if (createdAt === undefined) {\n if (message.createdAt === undefined) return message\n const { createdAt: _invalid, ...rest } = message\n return rest\n }\n return Object.is(message.createdAt, createdAt)\n ? message\n : { ...message, createdAt }\n}\n\nexport function restoreToolResultOwnership<T extends object>(message: T): T {\n if (!('role' in message) || message.role !== 'tool') return message\n const source = message\n const metadata = tanstackMetadata(source)\n const owned = metadata?.toolResult\n if (!isRecord(owned)) return message\n if ('content' in owned && !isContentPartArray(owned.content)) return message\n const next = { ...message }\n if (!('id' in owned)) Reflect.deleteProperty(next, 'id')\n if (!('createdAt' in owned)) Reflect.deleteProperty(next, 'createdAt')\n if (typeof owned.id === 'string') Reflect.set(next, 'id', owned.id)\n if (typeof owned.createdAt === 'string') {\n const createdAt = coerceCreatedAt(owned.createdAt)\n if (createdAt) Reflect.set(next, 'createdAt', createdAt)\n }\n if (isContentPartArray(owned.content)) {\n Reflect.set(next, 'content', owned.content)\n }\n const sourceMetadata: unknown = Reflect.get(source, 'metadata')\n if (isRecord(sourceMetadata)) {\n const tanstack = sourceMetadata.tanstack\n if (isRecord(tanstack)) {\n const { toolResult: _toolResult, ...restTanstack } = tanstack\n const restMetadata = { ...sourceMetadata }\n if (Object.keys(restTanstack).length) restMetadata.tanstack = restTanstack\n else delete restMetadata.tanstack\n if (Object.keys(restMetadata).length)\n Reflect.set(next, 'metadata', restMetadata)\n else Reflect.deleteProperty(next, 'metadata')\n }\n }\n return next\n}\n\n/**\n * Rebuild a `Date` from a live `Date` or from an ISO string.\n * `JSON.stringify` turns `Date` into a string, so persistence reload\n * and AG-UI wire both land here as strings.\n */\nexport function coerceCreatedAt(value: unknown): Date | undefined {\n if (value instanceof Date) {\n return Number.isNaN(value.getTime()) ? undefined : value\n }\n if (typeof value !== 'string') return undefined\n const createdAt = new Date(value)\n return Number.isNaN(createdAt.getTime()) ? undefined : createdAt\n}\n\nfunction normalizeMessagePart(part: MessagePart): MessagePart {\n if (part.type !== 'tool-result') return part\n const createdAt = coerceCreatedAt(part.createdAt)\n const { createdAt: _createdAt, ...rest } = part\n return createdAt === undefined ? rest : { ...rest, createdAt }\n}\n\nfunction createdAtFromMetadata(source: object): Date | undefined {\n return coerceCreatedAt(tanstackMetadata(source)?.createdAt)\n}\n\nfunction optionalCreatedAt(source: { createdAt?: unknown }): {\n createdAt?: Date\n} {\n const createdAt = coerceCreatedAt(source.createdAt)\n return createdAt !== undefined ? { createdAt } : {}\n}\n\nfunction optionalName(source: { name?: string }): { name?: string } {\n return source.name !== undefined ? { name: source.name } : {}\n}\n\nfunction isUiResourcePart(value: unknown): value is UIResourcePart {\n if (value == null || typeof value !== 'object' || Array.isArray(value)) {\n return false\n }\n if (!('type' in value) || value.type !== 'ui-resource') return false\n if (!('toolCallId' in value) || typeof value.toolCallId !== 'string') {\n return false\n }\n if (!('toolName' in value) || typeof value.toolName !== 'string') {\n return false\n }\n if (\n !('resource' in value) ||\n value.resource == null ||\n typeof value.resource !== 'object' ||\n Array.isArray(value.resource)\n ) {\n return false\n }\n const resource = value.resource\n return (\n 'uri' in resource &&\n typeof resource.uri === 'string' &&\n 'mimeType' in resource &&\n typeof resource.mimeType === 'string'\n )\n}\n\nfunction uiResourceKey(part: UIResourcePart): string {\n return `${part.toolCallId}\\0${part.toolName}\\0${part.resource.uri}`\n}\n\nfunction appendUiResources(\n ui: UIMessage,\n resources: ReadonlyArray<UIResourcePart>,\n): UIMessage {\n if (resources.length === 0) return ui\n const seen = new Set(\n ui.parts.filter(isUiResourcePart).map((part) => uiResourceKey(part)),\n )\n const extra = resources.filter((part) => !seen.has(uiResourceKey(part)))\n if (extra.length === 0) return ui\n return { ...ui, parts: [...ui.parts, ...extra] }\n}\n\n/**\n * Build a UIResourcePart from the value of a CUSTOM `ui-resource` chunk\n * emitted via `ctx.emitCustomEvent('ui-resource', ...)` (MCP Apps). The\n * emission-side value carries `resource`/`serverId`/`toolName` plus the\n * `toolCallId` stamped by the tool-call context wrapper — the `type`\n * discriminator is added here. Returns undefined when the value does not\n * match the ui-resource shape.\n */\nexport function uiResourcePartFromCustomValue(\n value: unknown,\n): UIResourcePart | undefined {\n if (!isRecord(value)) return undefined\n const part: unknown = { type: 'ui-resource', ...value }\n return isUiResourcePart(part) ? part : undefined\n}\n\n/**\n * Store an emitted ui-resource part on the assistant ModelMessage that owns\n * its `toolCallId` (the tool-call anchor), so it survives later\n * MESSAGES_SNAPSHOT chunks — e.g. the interrupt snapshot emitted when the\n * run pauses on a client tool (#1397). Mirrors how `toolCallMetadata` is\n * preserved on the anchor (#867).\n *\n * Returns the SAME array reference when no anchor owns the tool call or the\n * resource is already stored (idempotent).\n */\nexport function appendUiResourceToModelMessages(\n messages: Array<ModelMessage>,\n part: UIResourcePart,\n): Array<ModelMessage> {\n for (let index = messages.length - 1; index >= 0; index--) {\n const message = messages[index]\n if (!message || message.role !== 'assistant') continue\n const ownsToolCall = message.toolCalls?.some(\n (toolCall) => toolCall.id === part.toolCallId,\n )\n if (!ownsToolCall) continue\n const previous = tanstackMetadata(message)?.uiResources ?? []\n if (\n previous.some((stored) => uiResourceKey(stored) === uiResourceKey(part))\n ) {\n return messages\n }\n const nextMessage = {\n ...message,\n metadata: {\n ...message.metadata,\n tanstack: {\n ...tanstackMetadata(message),\n uiResources: [...previous, part],\n },\n },\n }\n const next = messages.slice()\n next[index] = nextMessage\n return next\n }\n return messages\n}\n\nfunction assistantMetadata(\n uiMessage: UIMessage,\n): UIMessage['metadata'] | undefined {\n const fromParts = uiMessage.parts.filter(isUiResourcePart)\n const current = uiMessage.metadata ?? {}\n const previous = tanstackMetadata(uiMessage)\n const tanstack: TanStackMessageMetadata = {}\n if (previous?.model !== undefined) tanstack.model = previous.model\n if (previous?.runId !== undefined) tanstack.runId = previous.runId\n if (previous?.signature !== undefined) tanstack.signature = previous.signature\n if (fromParts.length > 0) tanstack.uiResources = fromParts\n const result = { ...current }\n if (Object.keys(tanstack).length > 0) result.tanstack = tanstack\n else delete result.tanstack\n return Object.keys(result).length > 0 ? result : undefined\n}\n\n/**\n * Convert a UIMessage to ModelMessage(s)\n *\n * Walks the parts array IN ORDER to preserve the interleaving of text,\n * tool calls, and tool results. This is critical for multi-round tool\n * flows where the model generates text, calls a tool, gets the result,\n * then generates more text and calls another tool.\n *\n * The output preserves the sequential structure:\n * text1 → toolCall1 → toolResult1 → text2 → toolCall2 → toolResult2\n * becomes:\n * assistant: {content: \"text1\", toolCalls: [toolCall1]}\n * tool: toolResult1\n * assistant: {content: \"text2\", toolCalls: [toolCall2]}\n * tool: toolResult2\n *\n * @param uiMessage - The UIMessage to convert\n * @returns An array of ModelMessages preserving part ordering\n */\nexport function uiMessageToModelMessages(\n uiMessage: UIMessage,\n): Array<ModelMessage> {\n // Skip system messages - they're handled via systemPrompts, not ModelMessages\n if (uiMessage.role === 'system') {\n return []\n }\n\n // For non-assistant messages (user), use the simpler path since they\n // don't have tool calls or tool results to interleave\n if (uiMessage.role !== 'assistant') {\n return [buildUserOrToolMessage(uiMessage)]\n }\n\n // For assistant messages, walk parts in order to preserve interleaving\n return buildAssistantMessages(uiMessage)\n}\n\n/**\n * Build a single ModelMessage for user messages (simple path).\n * Preserves ordering of text and multimodal content parts.\n */\nfunction buildUserOrToolMessage(uiMessage: UIMessage): ModelMessage {\n const contentParts: Array<ContentPart> = []\n for (const part of uiMessage.parts) {\n if (isContentPart(part)) {\n contentParts.push(part)\n }\n }\n\n return {\n id: uiMessage.id,\n role: uiMessage.role as 'user' | 'assistant' | 'tool',\n content: collapseContentParts(contentParts),\n ...optionalName(uiMessage),\n ...optionalCreatedAt(uiMessage),\n ...(uiMessage.metadata !== undefined && { metadata: uiMessage.metadata }),\n }\n}\n\n// Accumulator for building an assistant segment (content + tool calls)\ninterface AssistantSegment {\n contentParts: Array<ContentPart>\n structuredOutput?: StructuredOutputPart\n toolCalls: Array<{\n id: string\n type: 'function'\n function: { name: string; arguments: string }\n /** Provider-specific metadata that round-trips with the tool call.\n * Untyped at this framework layer; adapters narrow it via their\n * `TToolCallMetadata` generic. */\n metadata?: unknown\n }>\n}\n\nfunction createSegment(): AssistantSegment {\n return { contentParts: [], toolCalls: [] }\n}\n\nfunction isToolCallIncluded(part: ToolCallPart): boolean {\n return (\n part.state === 'input-complete' ||\n part.state === 'complete' ||\n part.state === 'approval-requested' ||\n part.state === 'approval-responded' ||\n part.state === 'error' ||\n part.output !== undefined\n )\n}\n\n/**\n * Build ModelMessages for an assistant UIMessage, preserving the\n * sequential interleaving of text, tool calls, and tool results.\n *\n * Walks parts in order. Text and tool-call parts accumulate into the\n * current \"segment\". When a tool-result part is encountered, the\n * current segment is flushed as an assistant message, then the tool\n * result is emitted as a tool message.\n */\nfunction buildAssistantMessages(uiMessage: UIMessage): Array<ModelMessage> {\n // A single UI message can fan out into several model messages. Keep the\n // shared UI id on each one so persistence can retain the original identity.\n const messageList: Array<ModelMessage> = []\n let current = createSegment()\n let pendingThinking: Array<{ content: string; signature?: string }> = []\n\n // Track emitted tool result IDs to avoid duplicates.\n // A tool call can have BOTH an explicit tool-result part AND an output\n // field on the tool-call part. We only want one per tool call ID.\n const emittedToolResultIds = new Set<string>()\n const identityFields = {\n id: uiMessage.id,\n ...optionalName(uiMessage),\n ...optionalCreatedAt(uiMessage),\n }\n const metadata = assistantMetadata(uiMessage)\n const assistantFields = {\n ...identityFields,\n ...(metadata !== undefined && { metadata }),\n }\n\n function flushSegment(force = false): void {\n const content = collapseContentParts(current.contentParts)\n const hasContent = content !== null\n const hasToolCalls = current.toolCalls.length > 0\n const hasThinking = pendingThinking.length > 0\n\n if (force || hasContent || hasToolCalls || hasThinking) {\n messageList.push({\n ...assistantFields,\n role: 'assistant',\n content,\n ...(hasToolCalls && { toolCalls: current.toolCalls }),\n ...(hasThinking && { thinking: pendingThinking }),\n ...(current.structuredOutput && {\n structuredOutput: current.structuredOutput,\n }),\n })\n pendingThinking = []\n }\n current = createSegment()\n }\n\n for (const part of uiMessage.parts) {\n switch (part.type) {\n case 'text':\n case 'image':\n case 'audio':\n case 'video':\n case 'document':\n current.contentParts.push(part)\n break\n\n case 'tool-call':\n if (isToolCallIncluded(part)) {\n current.toolCalls.push({\n id: part.id,\n type: 'function' as const,\n function: {\n name: part.name,\n arguments: part.arguments,\n },\n ...(part.metadata !== undefined && { metadata: part.metadata }),\n })\n }\n break\n\n case 'tool-result':\n // Flush the current assistant segment before emitting the tool result\n flushSegment(messageList.length === 0)\n\n // Emit the tool result\n if (\n (part.state === 'complete' || part.state === 'error') &&\n !emittedToolResultIds.has(part.toolCallId)\n ) {\n messageList.push({\n ...(part.id !== undefined && { id: part.id }),\n ...optionalCreatedAt(part),\n role: 'tool',\n content: part.content,\n toolCallId: part.toolCallId,\n ...(part.name !== undefined && { name: part.name }),\n ...(part.metadata !== undefined && { metadata: part.metadata }),\n ...(part.error !== undefined && { error: part.error }),\n })\n emittedToolResultIds.add(part.toolCallId)\n }\n break\n\n case 'thinking':\n if (part.content || part.signature) {\n // Provider-executed tools have no tool-result part, so thinking\n // after them has to start the next segment or it replays first.\n if (current.toolCalls.some(isProviderExecutedToolCall)) {\n flushSegment()\n }\n pendingThinking.push({\n content: part.content,\n ...(part.signature && { signature: part.signature }),\n })\n }\n break\n\n case 'structured-output':\n // Only emit completed structured responses into history. Streaming or\n // errored buffers would push malformed JSON into the next LLM turn's\n // assistant content. `raw` is the source of truth; `data` is the\n // defensive fallback for terminal-only completes that didn't ship raw.\n if (part.status === 'complete') {\n const serialized =\n part.raw !== ''\n ? part.raw\n : part.data !== undefined\n ? safeJsonStringify(part.data)\n : ''\n if (serialized !== '') {\n current.contentParts.push({ type: 'text', content: serialized })\n current.structuredOutput = part\n }\n }\n break\n\n case 'ui-resource':\n // MCP Apps widget — rendered client-side only. It must never enter\n // model input, so it is intentionally dropped from the model message.\n break\n\n case 'subagent': {\n // A child that a tool call started reports through the tool result.\n const block =\n part.subagent.parentToolCallId === undefined\n ? subagentHistoryText(part)\n : ''\n if (block !== '') {\n const prefix = current.contentParts.length > 0 ? '\\n\\n' : ''\n current.contentParts.push({\n type: 'text',\n content: `${prefix}${block}`,\n })\n }\n break\n }\n\n default:\n break\n }\n }\n\n // Flush any remaining accumulated content\n flushSegment()\n\n // Emit tool results from client tool-call parts with output or approval,\n // but only if not already covered by an explicit tool-result part above.\n // These are appended at the end since they don't have explicit tool-result\n // parts in the parts array to trigger inline emission.\n for (const part of uiMessage.parts) {\n if (part.type !== 'tool-call') continue\n\n // Output takes priority — if the tool has already produced a result,\n // emit the concrete output regardless of approval metadata.\n if (part.output !== undefined && !emittedToolResultIds.has(part.id)) {\n messageList.push({\n role: 'tool',\n content: normalizeToolResult(part.output),\n toolCallId: part.id,\n })\n emittedToolResultIds.add(part.id)\n }\n\n // Approval response without output — emit approval status for iteration tracking\n if (\n part.output === undefined &&\n part.state === 'approval-responded' &&\n part.approval?.approved !== undefined &&\n !emittedToolResultIds.has(part.id)\n ) {\n const approved = part.approval.approved\n messageList.push({\n role: 'tool',\n content: JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n }),\n toolCallId: part.id,\n })\n emittedToolResultIds.add(part.id)\n }\n }\n\n // If no messages were produced (e.g., empty parts), emit a minimal assistant message\n if (messageList.length === 0) {\n messageList.push({\n ...assistantFields,\n role: 'assistant',\n content: null,\n })\n }\n\n return messageList\n}\n\n/**\n * Convert a ModelMessage to UIMessage\n *\n * This conversion creates a parts-based structure:\n * - content field → TextPart\n * - toolCalls array → ToolCallPart[]\n * - role=\"tool\" messages should be converted separately and merged\n *\n * @param modelMessage - The ModelMessage to convert\n * @param id - Optional ID for the UIMessage (generated if not provided)\n * @returns A UIMessage with parts\n */\nexport function modelMessageToUIMessage(\n modelMessage: ModelMessage,\n id?: string,\n): UIMessage {\n const parts: Array<MessagePart> = []\n const createdAt = coerceCreatedAt(modelMessage.createdAt)\n\n if (modelMessage.role === 'assistant' && modelMessage.thinking?.length) {\n for (const thinking of modelMessage.thinking) {\n if (!thinking.content && !thinking.signature) continue\n parts.push({\n type: 'thinking',\n content: thinking.content,\n ...(thinking.signature && { signature: thinking.signature }),\n })\n }\n }\n\n // Handle tool results (when role is \"tool\") - only produce tool-result part,\n // not a text part (the content IS the tool result, not display text)\n const structuredOutput =\n modelMessage.structuredOutput ??\n snapshotStructuredOutput(tanstackMetadata(modelMessage)?.structuredOutput)\n if (modelMessage.role === 'assistant' && structuredOutput) {\n if (\n typeof modelMessage.content === 'string' &&\n modelMessage.content &&\n modelMessage.content !== structuredOutput.raw\n ) {\n const suffix = structuredOutput.raw\n const text =\n suffix !== '' && modelMessage.content.endsWith(suffix)\n ? modelMessage.content.slice(0, -suffix.length)\n : modelMessage.content\n if (text) parts.push({ type: 'text', content: text })\n }\n parts.push(structuredOutput)\n } else if (modelMessage.role === 'tool' && modelMessage.toolCallId) {\n parts.push({\n type: 'tool-result',\n toolCallId: modelMessage.toolCallId,\n content: toolResultContent(modelMessage.content),\n state: modelMessage.error === undefined ? 'complete' : 'error',\n ...(modelMessage.id !== undefined && { id: modelMessage.id }),\n ...(modelMessage.name !== undefined && { name: modelMessage.name }),\n ...(modelMessage.metadata !== undefined && {\n metadata: modelMessage.metadata,\n }),\n ...(createdAt !== undefined && { createdAt }),\n ...(modelMessage.error !== undefined && { error: modelMessage.error }),\n })\n } else if (Array.isArray(modelMessage.content)) {\n // Multimodal content - preserve all content parts as MessageParts\n for (const part of modelMessage.content) {\n parts.push(part)\n }\n } else {\n // String or null content\n const textContent = getTextContent(modelMessage.content)\n if (textContent) {\n parts.push({\n type: 'text',\n content: textContent,\n })\n }\n }\n\n // Handle tool calls\n if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) {\n for (const toolCall of modelMessage.toolCalls) {\n // Model-message arguments are complete, so surface the parsed input.\n // A malformed arguments string just leaves `input` undefined.\n let input: unknown\n try {\n input = JSON.parse(toolCall.function.arguments)\n } catch {\n input = undefined\n }\n parts.push({\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n state: 'input-complete', // Model messages have complete arguments\n ...(input !== undefined && { input }),\n ...(toolCall.metadata !== undefined && { metadata: toolCall.metadata }),\n })\n }\n }\n\n const ui: UIMessage = {\n id: id || generateMessageId(),\n role: modelMessage.role === 'tool' ? 'assistant' : modelMessage.role,\n parts,\n ...optionalName(modelMessage),\n ...(createdAt !== undefined && { createdAt }),\n ...(modelMessage.metadata !== undefined && {\n metadata: modelMessage.metadata,\n }),\n }\n const storedResources = tanstackMetadata(modelMessage)?.uiResources\n return appendUiResources(\n ui,\n Array.isArray(storedResources)\n ? storedResources.filter(isUiResourcePart)\n : [],\n )\n}\n\n/**\n * Normalize a single AG-UI `MESSAGES_SNAPSHOT` message into a `UIMessage`.\n *\n * AG-UI snapshot messages use the wire shape `{ id, role, content }` and have\n * no `parts` array. Casting them directly to `UIMessage` is unsafe: any code\n * that later reads `message.parts` (e.g. the devtools `onToolCallStateChange`\n * handler) crashes with \"Cannot read properties of undefined (reading 'find')\".\n *\n * Each role is mapped to the canonical `UIMessage` shape, reusing\n * `modelMessageToUIMessage` for the roles that share `ModelMessage`'s structure.\n * The original AG-UI `id` is preserved so later `TEXT_MESSAGE_CONTENT` /\n * `TOOL_CALL_*` events still route by `messageId` (falling back to a generated\n * id only when the snapshot omits one). Messages that already carry `parts`\n * (e.g. a TanStack server echoing `UIMessage`s back over the wire) pass through\n * unchanged apart from ensuring an id.\n */\nexport function aguiSnapshotMessageToUIMessage(\n message: AGUIMessage | UIMessage,\n): UIMessage {\n if ('parts' in message) {\n return applySnapshotMetadata(message, {\n ...message,\n id: message.id || generateMessageId(),\n })\n }\n\n const id = message.id || generateMessageId()\n\n switch (message.role) {\n case 'user':\n return applySnapshotMetadata(message, {\n id,\n role: 'user',\n parts: aguiUserContentToParts(message.content),\n })\n case 'assistant': {\n const metadata = tanstackMetadata(message)\n const toolCallMetadata = metadata?.toolCallMetadata\n const structuredOutput = snapshotStructuredOutput(\n metadata?.structuredOutput,\n )\n const toolCalls = message.toolCalls?.map((toolCall) => {\n const callMetadata =\n toolCallMetadata != null && typeof toolCallMetadata === 'object'\n ? (toolCallMetadata as Record<string, unknown>)[toolCall.id]\n : undefined\n return callMetadata !== undefined\n ? { ...toolCall, metadata: callMetadata }\n : toolCall\n })\n return applySnapshotMetadata(\n message,\n modelMessageToUIMessage(\n {\n role: 'assistant',\n content: message.content ?? null,\n ...optionalName(message),\n ...(toolCalls && { toolCalls }),\n ...(structuredOutput && { structuredOutput }),\n },\n id,\n ),\n )\n }\n case 'tool': {\n message = restoreToolResultOwnership(message)\n const createdAt =\n coerceCreatedAt(\n 'createdAt' in message ? message.createdAt : undefined,\n ) ?? createdAtFromMetadata(message)\n return applySnapshotMetadata(\n message,\n modelMessageToUIMessage(\n {\n role: 'tool',\n content: isContentPartArray(message.content)\n ? message.content\n : aguiContentToContentParts(message.content),\n toolCallId: message.toolCallId,\n ...('name' in message && typeof message.name === 'string'\n ? { name: message.name }\n : {}),\n ...('id' in message && typeof message.id === 'string'\n ? { id: message.id }\n : {}),\n ...('metadata' in message && message.metadata != null\n ? { metadata: message.metadata }\n : {}),\n ...(createdAt !== undefined ? { createdAt } : {}),\n ...(message.error !== undefined && { error: message.error }),\n },\n id,\n ),\n )\n }\n case 'system':\n case 'developer':\n // `ModelMessage` has no system/developer role; build the part directly.\n return applySnapshotMetadata(message, {\n id,\n role: 'system',\n parts: message.content\n ? [{ type: 'text', content: message.content }]\n : [],\n })\n case 'reasoning': {\n const signature = encryptedValueFrom(message)\n const content = typeof message.content === 'string' ? message.content : ''\n return applySnapshotMetadata(message, {\n id,\n role: 'assistant',\n parts:\n content || signature !== undefined\n ? [\n {\n type: 'thinking' as const,\n content,\n ...(signature !== undefined ? { signature } : {}),\n },\n ]\n : [],\n })\n }\n case 'activity':\n default:\n // `activity` (and any future role) has no text/parts equivalent today.\n return applySnapshotMetadata(message, {\n id,\n role: 'assistant',\n parts: [],\n })\n }\n}\n\n/** Copy snapshot metadata when it is a record. Rebuild createdAt from tanstack.createdAt. */\nfunction applySnapshotMetadata(source: object, ui: UIMessage): UIMessage {\n const normalizedParts = ui.parts.map((part) => normalizeMessagePart(part))\n if (normalizedParts !== ui.parts) ui = { ...ui, parts: normalizedParts }\n const name =\n 'name' in source && typeof source.name === 'string'\n ? source.name\n : undefined\n let next = name !== undefined ? { ...ui, name } : ui\n\n let metadata: NonNullable<UIMessage['metadata']> | undefined\n if ('metadata' in source) {\n const raw = source.metadata\n if (raw != null && typeof raw === 'object' && !Array.isArray(raw)) {\n metadata = raw as NonNullable<UIMessage['metadata']>\n next = { ...next, metadata }\n }\n }\n\n const createdAt =\n coerceCreatedAt(next.createdAt) ??\n (metadata !== undefined ? createdAtFromMetadata(metadata) : undefined)\n if (createdAt !== undefined && !Object.is(createdAt, next.createdAt)) {\n next = { ...next, createdAt }\n } else if (createdAt === undefined && next.createdAt !== undefined) {\n const { createdAt: _invalid, ...rest } = next\n next = rest\n }\n\n const uiResources = tanstackMetadata(metadata)?.uiResources\n const resources = Array.isArray(uiResources)\n ? uiResources.filter(isUiResourcePart)\n : []\n return appendUiResources(next, resources)\n}\n\nfunction snapshotStructuredOutput(\n value: TanStackMessageMetadata['structuredOutput'],\n): StructuredOutputPart | undefined {\n if (\n value == null ||\n (value.status !== 'streaming' &&\n value.status !== 'complete' &&\n value.status !== 'error') ||\n typeof value.raw !== 'string'\n ) {\n return undefined\n }\n return {\n type: 'structured-output',\n status: value.status,\n raw: value.raw,\n ...(value.partial !== undefined ? { partial: value.partial } : {}),\n ...(value.data !== undefined ? { data: value.data } : {}),\n ...(value.reasoning ? { reasoning: value.reasoning } : {}),\n ...(value.errorMessage !== undefined\n ? { errorMessage: value.errorMessage }\n : {}),\n }\n}\n\n/**\n * Convert AG-UI user message content into `UIMessage` parts.\n *\n * AG-UI user content is either a plain string or a multimodal array whose text\n * entries use `{ type: 'text', text }` (vs. TanStack's `{ type: 'text', content }`).\n * Text entries are rewritten to the TanStack shape; image/audio/video/document\n * entries already match `ContentPart` and pass through.\n */\nfunction aguiUserContentToParts(\n content: Extract<AGUIMessage, { role: 'user' }>['content'],\n): Array<MessagePart> {\n const converted = aguiContentToContentParts(content)\n return typeof converted === 'string'\n ? converted\n ? [{ type: 'text', content: converted }]\n : []\n : converted\n}\n\n/** Convert wire content parts. Data, url, and file sources pass through. */\nexport function aguiContentToContentParts(\n content: Extract<AGUIMessage, { role: 'user' }>['content'],\n): string | Array<ContentPart> {\n if (typeof content === 'string') return content\n return content.map((part) => {\n if (part.type !== 'text') return part\n const { text, ...rest } = part\n return { ...rest, content: text }\n })\n}\n\n/**\n * Convert an array of ModelMessages to UIMessages\n *\n * This handles merging tool result messages with their corresponding assistant messages\n *\n * @param modelMessages - Array of ModelMessages to convert\n * @returns Array of UIMessages\n */\nexport function modelMessagesToUIMessages(\n modelMessages: Array<ModelMessage>,\n): Array<UIMessage> {\n const uiMessages: Array<UIMessage> = []\n let currentAssistantMessage: UIMessage | null = null\n\n for (const msg of modelMessages) {\n if (msg.role === 'tool') {\n // Tool result - merge into the last assistant message if possible\n if (\n msg.toolCallId !== undefined &&\n currentAssistantMessage &&\n currentAssistantMessage.role === 'assistant'\n ) {\n const content = toolResultContent(msg.content)\n const toolCallPart = currentAssistantMessage.parts.find(\n (part): part is ToolCallPart =>\n part.type === 'tool-call' && part.id === msg.toolCallId,\n )\n\n if (toolCallPart) {\n toolCallPart.output =\n typeof content === 'string'\n ? parseToolResultContent(content)\n : content\n toolCallPart.state = msg.error === undefined ? 'complete' : 'error'\n }\n\n currentAssistantMessage.parts.push({\n type: 'tool-result',\n toolCallId: msg.toolCallId,\n content,\n state: msg.error === undefined ? 'complete' : 'error',\n ...(msg.id !== undefined &&\n msg.id !== currentAssistantMessage.id && { id: msg.id }),\n ...(msg.name !== undefined && { name: msg.name }),\n ...(msg.metadata !== undefined && { metadata: msg.metadata }),\n ...optionalCreatedAt(msg),\n ...(msg.error !== undefined && { error: msg.error }),\n })\n } else {\n // No assistant message to merge into, create a standalone one\n const toolResultUIMessage = modelMessageToUIMessage(msg, msg.id)\n uiMessages.push(toolResultUIMessage)\n }\n } else {\n // Regular message. Preserve a persisted stable id so a hydrated message\n // keeps the same identity as its live stream (enables in-place resume).\n const uiMessage = modelMessageToUIMessage(msg, msg.id)\n if (\n msg.role === 'assistant' &&\n currentAssistantMessage &&\n isAssistantSegmentOf(msg.id, currentAssistantMessage.id)\n ) {\n currentAssistantMessage.parts.push(...uiMessage.parts)\n continue\n }\n uiMessages.push(uiMessage)\n\n // Track assistant messages for potential tool result merging\n if (msg.role === 'assistant') {\n currentAssistantMessage = uiMessage\n } else {\n currentAssistantMessage = null\n }\n }\n }\n\n return uiMessages\n}\n\n/**\n * Normalize a message (UIMessage or ModelMessage) to a UIMessage\n * Ensures the message has an ID and createdAt timestamp\n *\n * @param message - Either a UIMessage or ModelMessage\n * @param generateId - Function to generate a message ID if needed\n * @returns A UIMessage with guaranteed id and createdAt\n */\nexport function normalizeToUIMessage(\n message: UIMessage | ModelMessage,\n generateId: () => string,\n): UIMessage {\n if ('parts' in message) {\n // Already a UIMessage\n const parts = message.parts.map((part) => normalizeMessagePart(part))\n return {\n ...message,\n parts,\n id: message.id || generateId(),\n createdAt: coerceCreatedAt(message.createdAt) ?? new Date(),\n }\n } else {\n // ModelMessage - convert to UIMessage\n return {\n ...modelMessageToUIMessage(message, generateId()),\n createdAt: coerceCreatedAt(message.createdAt) ?? new Date(),\n }\n }\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`\n}\n"],"mappings":"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"}
|
|
@@ -71,8 +71,25 @@ export interface RunRecord {
|
|
|
71
71
|
* reuse this record by faking `threadId = requestId`; they need a separate
|
|
72
72
|
* job store. `withGenerationPersistence` currently does exactly that and
|
|
73
73
|
* labels itself a stopgap — do not copy it.
|
|
74
|
+
*
|
|
75
|
+
* A subagent child record stores `subagent:<subagentRunId>` here, the key of
|
|
76
|
+
* its own transcript, so `findActiveRun` and `listByThread` on the
|
|
77
|
+
* conversation never return children. Use `listByParentRun`.
|
|
74
78
|
*/
|
|
75
79
|
threadId: string;
|
|
80
|
+
/**
|
|
81
|
+
* Parent chat run that started this child, when this record is a subagent.
|
|
82
|
+
* Absent on the parent run itself.
|
|
83
|
+
*/
|
|
84
|
+
parentRunId?: string;
|
|
85
|
+
/**
|
|
86
|
+
* The child's AG-UI subagentRunId, the id on its `SUBAGENT_*` chunks and on
|
|
87
|
+
* every chunk it streams. On a child record this equals `runId`. Absent on
|
|
88
|
+
* the parent run.
|
|
89
|
+
*/
|
|
90
|
+
subagentRunId?: string;
|
|
91
|
+
/** Agent name (`researcher`, `writer`) when this record is a subagent. */
|
|
92
|
+
name?: string;
|
|
76
93
|
status: RunStatus;
|
|
77
94
|
startedAt: number;
|
|
78
95
|
finishedAt?: number;
|
|
@@ -130,9 +147,10 @@ export interface RunRecord {
|
|
|
130
147
|
* instead of failing at build time. It was optional for exactly one release
|
|
131
148
|
* cycle and cost precisely that.
|
|
132
149
|
*
|
|
133
|
-
* OPTIONAL: `listByThread`, `listReclaimable`. Each serves
|
|
134
|
-
* feature (thread history,
|
|
135
|
-
* degrading
|
|
150
|
+
* OPTIONAL: `listByThread`, `listByParentRun`, `listReclaimable`. Each serves
|
|
151
|
+
* one higher-level feature (thread history, subagent card reload, reclaim
|
|
152
|
+
* reaping) and callers feature-detect them, degrading when a backend omits
|
|
153
|
+
* them.
|
|
136
154
|
*/
|
|
137
155
|
export interface RunStore {
|
|
138
156
|
/**
|
|
@@ -140,11 +158,16 @@ export interface RunStore {
|
|
|
140
158
|
* already present.
|
|
141
159
|
*
|
|
142
160
|
* INVARIANT (idempotency): an existing record is returned **unchanged** and
|
|
143
|
-
* the passed `threadId
|
|
144
|
-
*
|
|
161
|
+
* the passed `threadId`, `startedAt`, `status`, `parentRunId`,
|
|
162
|
+
* `subagentRunId`, and `name` are ignored. This is what makes resuming a
|
|
163
|
+
* run safe. `status` defaults to `'running'` on first creation. The three
|
|
164
|
+
* link fields are copied only on the first insert.
|
|
145
165
|
*/
|
|
146
166
|
createOrResume: (input: Pick<RunRecord, 'runId' | 'threadId' | 'startedAt'> & {
|
|
147
167
|
status?: RunStatus;
|
|
168
|
+
parentRunId?: string;
|
|
169
|
+
subagentRunId?: string;
|
|
170
|
+
name?: string;
|
|
148
171
|
}) => Promise<RunRecord>;
|
|
149
172
|
/**
|
|
150
173
|
* Patch a record's mutable fields.
|
|
@@ -156,10 +179,19 @@ export interface RunStore {
|
|
|
156
179
|
/** Current record, or null when unknown. */
|
|
157
180
|
get: (runId: string) => Promise<RunRecord | null>;
|
|
158
181
|
/**
|
|
159
|
-
* Every run in a conversation, ascending by `startedAt`. OPTIONAL
|
|
160
|
-
*
|
|
182
|
+
* Every run in a conversation, ascending by `startedAt`. OPTIONAL.
|
|
183
|
+
* `reconstructChat` calls it to find the parent runs of children that a
|
|
184
|
+
* tool call started. Without it those cards stay absent on reload.
|
|
185
|
+
* Consumers feature-detect.
|
|
161
186
|
*/
|
|
162
187
|
listByThread?: (threadId: string) => Promise<Array<RunRecord>>;
|
|
188
|
+
/**
|
|
189
|
+
* Child runs started by `parentRunId`, ascending by `startedAt`.
|
|
190
|
+
* OPTIONAL. `reconstructChat` uses this to put subagent cards back
|
|
191
|
+
* on the parent assistant message. A store that omits it reloads the
|
|
192
|
+
* text and not the cards.
|
|
193
|
+
*/
|
|
194
|
+
listByParentRun?: (parentRunId: string) => Promise<Array<RunRecord>>;
|
|
163
195
|
/**
|
|
164
196
|
* Runs that may be reclaimed: ALL THREE of `status === 'running'`,
|
|
165
197
|
* `detachedSince` is set, and `detachedSince <= now - ttlMs`. The cutoff is
|
|
@@ -271,10 +303,14 @@ export declare class InMemoryRunStore implements RunStore {
|
|
|
271
303
|
private readonly runs;
|
|
272
304
|
createOrResume(input: Pick<RunRecord, 'runId' | 'threadId' | 'startedAt'> & {
|
|
273
305
|
status?: RunStatus;
|
|
306
|
+
parentRunId?: string;
|
|
307
|
+
subagentRunId?: string;
|
|
308
|
+
name?: string;
|
|
274
309
|
}): Promise<RunRecord>;
|
|
275
310
|
update(runId: string, patch: Partial<Pick<RunRecord, 'status' | 'finishedAt' | 'error' | 'usage' | 'sandboxKey' | 'detachedSince' | 'cancelRequested' | 'driverEpoch'>>): Promise<void>;
|
|
276
311
|
get(runId: string): Promise<RunRecord | null>;
|
|
277
312
|
listByThread(threadId: string): Promise<Array<RunRecord>>;
|
|
313
|
+
listByParentRun(parentRunId: string): Promise<Array<RunRecord>>;
|
|
278
314
|
listReclaimable(opts: {
|
|
279
315
|
now: number;
|
|
280
316
|
ttlMs: number;
|
|
@@ -136,7 +136,10 @@ var InMemoryRunStore = class {
|
|
|
136
136
|
runId: input.runId,
|
|
137
137
|
threadId: input.threadId,
|
|
138
138
|
status: input.status ?? "running",
|
|
139
|
-
startedAt: input.startedAt
|
|
139
|
+
startedAt: input.startedAt,
|
|
140
|
+
...input.parentRunId !== void 0 ? { parentRunId: input.parentRunId } : {},
|
|
141
|
+
...input.subagentRunId !== void 0 ? { subagentRunId: input.subagentRunId } : {},
|
|
142
|
+
...input.name !== void 0 ? { name: input.name } : {}
|
|
140
143
|
};
|
|
141
144
|
this.runs.set(record.runId, record);
|
|
142
145
|
return Promise.resolve(record);
|
|
@@ -156,6 +159,10 @@ var InMemoryRunStore = class {
|
|
|
156
159
|
const matching = [...this.runs.values()].filter((run) => run.threadId === threadId).sort((a, b) => a.startedAt - b.startedAt);
|
|
157
160
|
return Promise.resolve(matching);
|
|
158
161
|
}
|
|
162
|
+
listByParentRun(parentRunId) {
|
|
163
|
+
const matching = [...this.runs.values()].filter((run) => run.parentRunId === parentRunId).sort((a, b) => a.startedAt - b.startedAt);
|
|
164
|
+
return Promise.resolve(matching);
|
|
165
|
+
}
|
|
159
166
|
listReclaimable(opts) {
|
|
160
167
|
const cutoff = opts.now - opts.ttlMs;
|
|
161
168
|
const matching = [...this.runs.values()].filter((run) => run.status === "running" && run.detachedSince !== void 0 && run.detachedSince <= cutoff);
|