@tanstack/ai 0.49.1 → 0.50.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/index.js +4 -4
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.d.ts +7 -0
- package/dist/esm/activities/chat/messages.js +270 -64
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.js +7 -7
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/client.js +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/types.d.ts +18 -0
- package/dist/esm/utilities/ag-ui-wire.d.ts +20 -44
- package/dist/esm/utilities/ag-ui-wire.js +143 -34
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/package.json +2 -2
- package/src/activities/chat/index.ts +3 -4
- package/src/activities/chat/messages.ts +344 -61
- package/src/activities/chat/stream/processor.ts +19 -10
- package/src/types.ts +18 -0
- package/src/utilities/ag-ui-wire.ts +278 -73
package/dist/esm/index.js
CHANGED
|
@@ -15,15 +15,15 @@ import { hashSchemaInput, normalizeApprovalSchema } from "./activities/chat/tool
|
|
|
15
15
|
import { INTERRUPT_BINDING_METADATA_KEY, InterruptResumeValidationError, interruptItemError, readInterruptBinding, readUnopenedInterruptBinding, validateInterruptResumeBatch, withInterruptBinding, withoutInterruptBinding } from "./interrupt-resume.js";
|
|
16
16
|
import { INTERRUPT_PAYLOAD_METADATA_KEY, createInterruptBinding, defineInterrupt } from "./interrupt-definition.js";
|
|
17
17
|
import { INTERRUPT_CONTINUATION_METADATA_KEY, INTERRUPT_CONTINUATION_VERSION, genericInterruptContinuationFromDescriptor, readGenericInterruptContinuation, wrapGenericInterruptContinuation } from "./generic-interrupt-continuation.js";
|
|
18
|
-
import { uiMessagesToWire } from "./utilities/ag-ui-wire.js";
|
|
19
18
|
import { isContentPart, isContentPartArray, normalizeToolResult } from "./utilities/tool-result.js";
|
|
20
19
|
import { getProviderExecutedMetadata, isProviderExecutedToolCall } from "./utilities/provider-executed.js";
|
|
20
|
+
import { convertMessagesToModelMessages, generateMessageId, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeToUIMessage, uiMessageToModelMessages } from "./activities/chat/messages.js";
|
|
21
|
+
import { uiMessagesToWire } from "./utilities/ag-ui-wire.js";
|
|
21
22
|
import { firstSentence, renderLazyCatalogEntry } from "./activities/chat/tools/lazy-tools.js";
|
|
22
23
|
import { DISCOVERY_TOOL_NAME } from "./activities/chat/tools/lazy-tool-manager.js";
|
|
23
24
|
import { DuplicateToolNameError } from "./activities/chat/tools/unique-tool-names.js";
|
|
24
25
|
import { ToolCallManager } from "./activities/chat/tools/tool-calls.js";
|
|
25
26
|
import { combineStrategies, maxIterations, untilFinishReason } from "./activities/chat/agent-loop-strategies.js";
|
|
26
|
-
import { convertMessagesToModelMessages, generateMessageId, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeToUIMessage, uiMessageToModelMessages } from "./activities/chat/messages.js";
|
|
27
27
|
import { MCPDuplicateToolNameError } from "./activities/chat/mcp/manager.js";
|
|
28
28
|
import { chat, createChatOptions } from "./activities/chat/index.js";
|
|
29
29
|
import { createSummarizeOptions, summarize } from "./activities/summarize/index.js";
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -250,6 +250,10 @@ export interface ModelMessage<TContent extends string | null | Array<ContentPart
|
|
|
250
250
|
content: string;
|
|
251
251
|
signature?: string;
|
|
252
252
|
}>;
|
|
253
|
+
/** Error reported by an AG-UI tool message. */
|
|
254
|
+
error?: string;
|
|
255
|
+
/** Optional AG-UI message metadata. TanStack-owned fields live under `tanstack`. */
|
|
256
|
+
metadata?: Record<string, any>;
|
|
253
257
|
/**
|
|
254
258
|
* Completed structured output represented by this assistant message.
|
|
255
259
|
* `content` remains the provider-facing JSON text; this field preserves the
|
|
@@ -310,10 +314,14 @@ export interface ToolCallPart<TMetadata = unknown> {
|
|
|
310
314
|
}
|
|
311
315
|
export interface ToolResultPart {
|
|
312
316
|
type: 'tool-result';
|
|
317
|
+
id?: string;
|
|
318
|
+
name?: string;
|
|
313
319
|
toolCallId: string;
|
|
314
320
|
content: string | Array<ContentPart>;
|
|
315
321
|
state: ToolResultState;
|
|
316
322
|
error?: string;
|
|
323
|
+
metadata?: Record<string, unknown>;
|
|
324
|
+
createdAt?: Date;
|
|
317
325
|
}
|
|
318
326
|
export interface ThinkingPart {
|
|
319
327
|
type: 'thinking';
|
|
@@ -385,9 +393,17 @@ export interface TanStackMessageMetadata {
|
|
|
385
393
|
signature?: string;
|
|
386
394
|
/** Per-tool-call provider metadata keyed by tool call id (e.g. Gemini thoughtSignature). */
|
|
387
395
|
toolCallMetadata?: Record<string, unknown>;
|
|
396
|
+
toolResult?: {
|
|
397
|
+
id?: string;
|
|
398
|
+
createdAt?: string;
|
|
399
|
+
content?: Array<ContentPart>;
|
|
400
|
+
};
|
|
388
401
|
structuredOutput?: {
|
|
389
402
|
status?: 'streaming' | 'complete' | 'error';
|
|
403
|
+
partial?: unknown;
|
|
404
|
+
data?: unknown;
|
|
390
405
|
raw?: string;
|
|
406
|
+
reasoning?: string;
|
|
391
407
|
errorMessage?: string;
|
|
392
408
|
};
|
|
393
409
|
uiResources?: Array<UIResourcePart>;
|
|
@@ -421,6 +437,8 @@ export interface UIMessage<TData = unknown> {
|
|
|
421
437
|
role: 'system' | 'user' | 'assistant';
|
|
422
438
|
parts: Array<MessagePart<TData>>;
|
|
423
439
|
createdAt?: Date;
|
|
440
|
+
/** Optional AG-UI sender name. Converters preserve it across wire and persist. */
|
|
441
|
+
name?: string;
|
|
424
442
|
/**
|
|
425
443
|
* Optional AG-UI metadata bag. TanStack writes the `tanstack` key.
|
|
426
444
|
* User keys stay at the top.
|
|
@@ -1,51 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AssistantMessage, ReasoningMessage, SystemMessage, ToolMessage, UserMessage } from '@ag-ui/core';
|
|
2
|
+
import { ModelMessage, UIMessage } from '../types.js';
|
|
2
3
|
import { MetadataRecord } from './merge-metadata.js';
|
|
3
|
-
type
|
|
4
|
-
type: 'text';
|
|
5
|
-
text: string;
|
|
6
|
-
};
|
|
7
|
-
type AGUIInputContent = AGUITextInputContent | (ContentPart & {
|
|
8
|
-
type: 'image' | 'audio' | 'video' | 'document';
|
|
9
|
-
});
|
|
10
|
-
type AGUIToolCallMirror = {
|
|
11
|
-
id: string;
|
|
12
|
-
type: 'function';
|
|
13
|
-
function: {
|
|
14
|
-
name: string;
|
|
15
|
-
arguments: string;
|
|
16
|
-
};
|
|
17
|
-
encryptedValue?: string;
|
|
18
|
-
};
|
|
19
|
-
type AGUIToolMessage = {
|
|
20
|
-
role: 'tool';
|
|
21
|
-
id: string;
|
|
22
|
-
toolCallId: string;
|
|
23
|
-
content: string;
|
|
24
|
-
error?: string;
|
|
25
|
-
};
|
|
26
|
-
type AGUIReasoningMessage = {
|
|
27
|
-
role: 'reasoning';
|
|
28
|
-
id: string;
|
|
29
|
-
content: string;
|
|
30
|
-
encryptedValue?: string;
|
|
4
|
+
type WithMetadata<T> = T & {
|
|
31
5
|
metadata?: MetadataRecord;
|
|
32
6
|
};
|
|
33
|
-
|
|
34
|
-
type
|
|
35
|
-
|
|
36
|
-
|
|
7
|
+
type WireSystemMessage = WithMetadata<SystemMessage>;
|
|
8
|
+
type WireUserMessage = WithMetadata<UserMessage>;
|
|
9
|
+
type WireAssistantMessage = WithMetadata<AssistantMessage>;
|
|
10
|
+
type WireToolMessage = WithMetadata<ToolMessage & {
|
|
37
11
|
name?: string;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
};
|
|
42
|
-
export type WireMessage = WireAnchorMessage | AGUIToolMessage | AGUIReasoningMessage;
|
|
12
|
+
}>;
|
|
13
|
+
type WireReasoningMessage = WithMetadata<ReasoningMessage>;
|
|
14
|
+
export type WireMessage = WireSystemMessage | WireUserMessage | WireAssistantMessage | WireToolMessage | WireReasoningMessage;
|
|
43
15
|
/**
|
|
44
|
-
* Serialize TanStack `UIMessage`s into the AG-UI
|
|
45
|
-
* wire shape. Anchors are spec-only (`id`, `role`,
|
|
46
|
-
* `toolCalls`, `metadata`). Tool results and thinking parts
|
|
47
|
-
* messages are additionally emitted as fan-out
|
|
48
|
-
* `{role:'reasoning',...}` entries for strict AG-UI
|
|
16
|
+
* Serialize TanStack `UIMessage`s and `ModelMessage`s into the AG-UI
|
|
17
|
+
* `RunAgentInput.messages` wire shape. Anchors are spec-only (`id`, `role`,
|
|
18
|
+
* `name`, `content`, `toolCalls`, `metadata`). Tool results and thinking parts
|
|
19
|
+
* on assistant messages are additionally emitted as fan-out
|
|
20
|
+
* `{role:'tool',...}` and `{role:'reasoning',...}` entries for strict AG-UI
|
|
21
|
+
* server consumers. Set `includeSnapshotStructuredOutput` to retain complete
|
|
22
|
+
* structured-output metadata for UI snapshots.
|
|
49
23
|
*/
|
|
50
|
-
export declare function uiMessagesToWire(messages: Array<UIMessage
|
|
24
|
+
export declare function uiMessagesToWire(messages: Array<UIMessage | ModelMessage>, options?: {
|
|
25
|
+
includeSnapshotStructuredOutput: boolean;
|
|
26
|
+
}): Array<WireMessage>;
|
|
51
27
|
export {};
|
|
@@ -1,28 +1,74 @@
|
|
|
1
1
|
import { tanstackMetadata } from "./merge-metadata.js";
|
|
2
|
+
import { normalizeToolResult } from "./tool-result.js";
|
|
3
|
+
import { coerceCreatedAt, modelMessageToUIMessage } from "../activities/chat/messages.js";
|
|
2
4
|
//#region src/utilities/ag-ui-wire.ts
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
function rebuiltToolMetadata(metadata, createdAt, id, content, anchorOwnsUiResources = false) {
|
|
9
|
+
const source = isRecord(metadata) ? metadata : {};
|
|
10
|
+
const tanstack = isRecord(source.tanstack) ? { ...source.tanstack } : {};
|
|
11
|
+
if (anchorOwnsUiResources) delete tanstack.uiResources;
|
|
12
|
+
const date = coerceCreatedAt(createdAt);
|
|
13
|
+
const toolResult = {
|
|
14
|
+
...id !== void 0 ? { id } : {},
|
|
15
|
+
...date && { createdAt: date.toISOString() },
|
|
16
|
+
...Array.isArray(content) && { content }
|
|
17
|
+
};
|
|
18
|
+
const result = {
|
|
19
|
+
...source,
|
|
20
|
+
tanstack: {
|
|
21
|
+
...tanstack,
|
|
22
|
+
toolResult
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
return Object.keys(result).length ? result : void 0;
|
|
26
|
+
}
|
|
3
27
|
/**
|
|
4
|
-
* Serialize TanStack `UIMessage`s into the AG-UI
|
|
5
|
-
* wire shape. Anchors are spec-only (`id`, `role`,
|
|
6
|
-
* `toolCalls`, `metadata`). Tool results and thinking parts
|
|
7
|
-
* messages are additionally emitted as fan-out
|
|
8
|
-
* `{role:'reasoning',...}` entries for strict AG-UI
|
|
28
|
+
* Serialize TanStack `UIMessage`s and `ModelMessage`s into the AG-UI
|
|
29
|
+
* `RunAgentInput.messages` wire shape. Anchors are spec-only (`id`, `role`,
|
|
30
|
+
* `name`, `content`, `toolCalls`, `metadata`). Tool results and thinking parts
|
|
31
|
+
* on assistant messages are additionally emitted as fan-out
|
|
32
|
+
* `{role:'tool',...}` and `{role:'reasoning',...}` entries for strict AG-UI
|
|
33
|
+
* server consumers. Set `includeSnapshotStructuredOutput` to retain complete
|
|
34
|
+
* structured-output metadata for UI snapshots.
|
|
9
35
|
*/
|
|
10
|
-
function uiMessagesToWire(messages) {
|
|
36
|
+
function uiMessagesToWire(messages, options) {
|
|
11
37
|
const wire = [];
|
|
38
|
+
const usedWireIds = new Set(messages.flatMap((message) => "id" in message && message.id && message.role !== "tool" ? [message.id] : []));
|
|
39
|
+
const includeSnapshotStructuredOutput = options?.includeSnapshotStructuredOutput ?? false;
|
|
40
|
+
const assistantIds = /* @__PURE__ */ new Set();
|
|
41
|
+
for (const msg of messages) if (msg.role === "assistant" && msg.id !== void 0) assistantIds.add(msg.id);
|
|
12
42
|
for (const msg of messages) {
|
|
13
|
-
|
|
43
|
+
if (!("parts" in msg) && msg.role === "tool" && msg.toolCallId) {
|
|
44
|
+
const id = uniqueToolWireId(toolWireId(msg.id, msg.toolCallId, assistantIds), usedWireIds);
|
|
45
|
+
const metadata = rebuiltToolMetadata(msg.metadata, msg.createdAt, msg.id, msg.content);
|
|
46
|
+
wire.push({
|
|
47
|
+
role: "tool",
|
|
48
|
+
id,
|
|
49
|
+
...msg.name !== void 0 && { name: msg.name },
|
|
50
|
+
toolCallId: msg.toolCallId,
|
|
51
|
+
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content),
|
|
52
|
+
...msg.error !== void 0 && { error: msg.error },
|
|
53
|
+
...metadata !== void 0 && { metadata }
|
|
54
|
+
});
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const uiMessage = "parts" in msg ? msg : modelMessageToUIMessage(msg, msg.id);
|
|
58
|
+
const parts = uiMessage.parts;
|
|
59
|
+
usedWireIds.add(uiMessage.id);
|
|
14
60
|
if (msg.role === "system") {
|
|
15
|
-
wire.push(toAnchor(
|
|
61
|
+
wire.push(toAnchor(uiMessage, "system", { content: parts.length > 0 ? collectText(parts) : msg.content ?? "" }, parts, includeSnapshotStructuredOutput));
|
|
16
62
|
continue;
|
|
17
63
|
}
|
|
18
64
|
if (msg.role === "user") {
|
|
19
|
-
wire.push(toAnchor(
|
|
65
|
+
wire.push(toAnchor(uiMessage, "user", { content: parts.length > 0 ? collectUserContent(parts) : msg.content ?? "" }, parts, includeSnapshotStructuredOutput));
|
|
20
66
|
continue;
|
|
21
67
|
}
|
|
22
68
|
for (const part of parts) if (part.type === "thinking") {
|
|
23
69
|
const reasoning = {
|
|
24
70
|
role: "reasoning",
|
|
25
|
-
id: deriveReasoningId(
|
|
71
|
+
id: uniqueWireId(deriveReasoningId(uiMessage.id, part), usedWireIds),
|
|
26
72
|
content: part.content
|
|
27
73
|
};
|
|
28
74
|
if (part.signature) reasoning.encryptedValue = part.signature;
|
|
@@ -30,52 +76,96 @@ function uiMessagesToWire(messages) {
|
|
|
30
76
|
}
|
|
31
77
|
const text = collectText(parts);
|
|
32
78
|
const toolCalls = collectToolCalls(parts);
|
|
33
|
-
wire.push(toAnchor(
|
|
79
|
+
wire.push(toAnchor(uiMessage, "assistant", {
|
|
34
80
|
...text !== "" && { content: text },
|
|
35
81
|
...toolCalls && { toolCalls }
|
|
36
|
-
}, parts));
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
id
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
82
|
+
}, parts, includeSnapshotStructuredOutput));
|
|
83
|
+
const explicitToolResults = new Set(parts.flatMap((part) => part.type === "tool-result" ? [part.toolCallId] : []));
|
|
84
|
+
for (const part of parts) if (part.type === "tool-result") {
|
|
85
|
+
const id = uniqueToolWireId(part.id ?? deriveToolMessageId(part.toolCallId), usedWireIds);
|
|
86
|
+
const metadata = rebuiltToolMetadata(part.metadata, part.createdAt, part.id, part.content, true);
|
|
87
|
+
wire.push({
|
|
88
|
+
role: "tool",
|
|
89
|
+
id,
|
|
90
|
+
toolCallId: part.toolCallId,
|
|
91
|
+
...part.name !== void 0 && { name: part.name },
|
|
92
|
+
content: typeof part.content === "string" ? part.content : JSON.stringify(part.content),
|
|
93
|
+
...part.error !== void 0 && { error: part.error },
|
|
94
|
+
...metadata !== void 0 && { metadata }
|
|
95
|
+
});
|
|
96
|
+
} else if (part.type === "tool-call") {
|
|
97
|
+
const approved = part.approval?.approved;
|
|
98
|
+
if (explicitToolResults.has(part.id) || part.output === void 0 && (part.state !== "approval-responded" || approved === void 0)) continue;
|
|
99
|
+
const result = part.output !== void 0 ? normalizeToolResult(part.output) : JSON.stringify({
|
|
100
|
+
approved,
|
|
101
|
+
...approved && { pendingExecution: true },
|
|
102
|
+
message: approved ? "User approved this action" : "User denied this action"
|
|
103
|
+
});
|
|
104
|
+
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
105
|
+
wire.push({
|
|
106
|
+
role: "tool",
|
|
107
|
+
id: uniqueToolWireId(deriveToolMessageId(part.id), usedWireIds),
|
|
108
|
+
toolCallId: part.id,
|
|
109
|
+
content,
|
|
110
|
+
metadata: rebuiltToolMetadata(void 0, void 0, void 0, result)
|
|
111
|
+
});
|
|
112
|
+
}
|
|
44
113
|
}
|
|
45
114
|
return wire;
|
|
46
115
|
}
|
|
47
|
-
function toAnchor(msg, extras, parts) {
|
|
48
|
-
const metadata = messageMetadata(msg, parts);
|
|
49
|
-
const
|
|
50
|
-
return {
|
|
116
|
+
function toAnchor(msg, role, extras, parts, includeSnapshotStructuredOutput) {
|
|
117
|
+
const metadata = messageMetadata(msg, parts, includeSnapshotStructuredOutput);
|
|
118
|
+
const base = {
|
|
51
119
|
id: msg.id,
|
|
52
|
-
|
|
53
|
-
...name !== void 0 && { name },
|
|
54
|
-
...extras,
|
|
120
|
+
...msg.name !== void 0 && { name: msg.name },
|
|
55
121
|
...metadata !== void 0 && { metadata }
|
|
56
122
|
};
|
|
123
|
+
if (role === "system") return {
|
|
124
|
+
...base,
|
|
125
|
+
role,
|
|
126
|
+
content: String(extras.content ?? "")
|
|
127
|
+
};
|
|
128
|
+
if (role === "user") return {
|
|
129
|
+
...base,
|
|
130
|
+
role,
|
|
131
|
+
content: extras.content ?? ""
|
|
132
|
+
};
|
|
133
|
+
return {
|
|
134
|
+
...base,
|
|
135
|
+
role,
|
|
136
|
+
...typeof extras.content === "string" && { content: extras.content },
|
|
137
|
+
...extras.toolCalls !== void 0 && { toolCalls: extras.toolCalls }
|
|
138
|
+
};
|
|
57
139
|
}
|
|
58
|
-
function messageMetadata(msg, parts) {
|
|
140
|
+
function messageMetadata(msg, parts, includeSnapshotStructuredOutput) {
|
|
59
141
|
const base = { ...msg.metadata ?? {} };
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (
|
|
142
|
+
const previousTanstack = tanstackMetadata(msg);
|
|
143
|
+
const tanstack = {};
|
|
144
|
+
if (previousTanstack?.model !== void 0) tanstack.model = previousTanstack.model;
|
|
145
|
+
if (previousTanstack?.signature !== void 0) tanstack.signature = previousTanstack.signature;
|
|
146
|
+
const createdAt = coerceCreatedAt(msg.createdAt);
|
|
147
|
+
if (createdAt !== void 0) tanstack.createdAt = createdAt.toISOString();
|
|
148
|
+
const structuredOutput = serializedStructuredOutput(parts, includeSnapshotStructuredOutput);
|
|
149
|
+
if (structuredOutput) tanstack.structuredOutput = structuredOutput;
|
|
64
150
|
const toolCallMetadata = {};
|
|
65
151
|
for (const part of parts) if (part.type === "tool-call" && part.metadata !== void 0) toolCallMetadata[part.id] = part.metadata;
|
|
66
152
|
if (Object.keys(toolCallMetadata).length > 0) tanstack.toolCallMetadata = toolCallMetadata;
|
|
67
153
|
const uiResources = parts.filter((p) => p.type === "ui-resource");
|
|
68
154
|
if (uiResources.length > 0) tanstack.uiResources = uiResources;
|
|
69
155
|
if (Object.keys(tanstack).length > 0) base.tanstack = tanstack;
|
|
156
|
+
else delete base.tanstack;
|
|
70
157
|
return Object.keys(base).length > 0 ? base : void 0;
|
|
71
158
|
}
|
|
72
|
-
function
|
|
73
|
-
for (const p of parts) if (p.type === "structured-output" && p.status !== "complete") return
|
|
159
|
+
function serializedStructuredOutput(parts, includeSnapshotStructuredOutput) {
|
|
160
|
+
for (const p of parts) if (p.type === "structured-output" && (includeSnapshotStructuredOutput || p.status !== "complete")) return structuredOutputMetadata(p, includeSnapshotStructuredOutput);
|
|
74
161
|
}
|
|
75
|
-
function
|
|
162
|
+
function structuredOutputMetadata(part, includeSnapshotStructuredOutput) {
|
|
76
163
|
return {
|
|
77
164
|
status: part.status,
|
|
78
165
|
raw: part.raw,
|
|
166
|
+
...includeSnapshotStructuredOutput && part.partial !== void 0 ? { partial: part.partial } : {},
|
|
167
|
+
...includeSnapshotStructuredOutput && part.data !== void 0 ? { data: part.data } : {},
|
|
168
|
+
...includeSnapshotStructuredOutput && part.reasoning ? { reasoning: part.reasoning } : {},
|
|
79
169
|
...part.errorMessage !== void 0 && { errorMessage: part.errorMessage }
|
|
80
170
|
};
|
|
81
171
|
}
|
|
@@ -123,6 +213,25 @@ function deriveReasoningId(messageId, part) {
|
|
|
123
213
|
function deriveToolMessageId(toolCallId) {
|
|
124
214
|
return `tool-${toolCallId}`;
|
|
125
215
|
}
|
|
216
|
+
function uniqueToolWireId(id, used) {
|
|
217
|
+
return uniqueWireId(id, used);
|
|
218
|
+
}
|
|
219
|
+
function uniqueWireId(id, used) {
|
|
220
|
+
if (!used.has(id)) {
|
|
221
|
+
used.add(id);
|
|
222
|
+
return id;
|
|
223
|
+
}
|
|
224
|
+
let suffix = 2;
|
|
225
|
+
while (used.has(`${id}-${suffix}`)) suffix++;
|
|
226
|
+
const unique = `${id}-${suffix}`;
|
|
227
|
+
used.add(unique);
|
|
228
|
+
return unique;
|
|
229
|
+
}
|
|
230
|
+
function toolWireId(id, toolCallId, assistantIds) {
|
|
231
|
+
const derived = deriveToolMessageId(toolCallId);
|
|
232
|
+
if (id === void 0 || assistantIds.has(id)) return derived;
|
|
233
|
+
return id;
|
|
234
|
+
}
|
|
126
235
|
function hashContent(s) {
|
|
127
236
|
let h = 0;
|
|
128
237
|
for (let i = 0; i < s.length; i++) h = h * 31 + s.charCodeAt(i) | 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ag-ui-wire.js","names":[],"sources":["../../../src/utilities/ag-ui-wire.ts"],"sourcesContent":["import type {\n ContentPart,\n MessagePart,\n StructuredOutputPart,\n TanStackMessageMetadata,\n UIMessage,\n UIResourcePart,\n} from '../types'\nimport type { MetadataRecord } from './merge-metadata'\nimport { tanstackMetadata } from './merge-metadata'\n\ntype AGUITextInputContent = { type: 'text'; text: string }\ntype AGUIInputContent =\n | AGUITextInputContent\n | (ContentPart & { type: 'image' | 'audio' | 'video' | 'document' })\n\ntype AGUIToolCallMirror = {\n id: string\n type: 'function'\n function: { name: string; arguments: string }\n encryptedValue?: string\n}\n\ntype AGUIToolMessage = {\n role: 'tool'\n id: string\n toolCallId: string\n content: string\n error?: string\n}\n\ntype AGUIReasoningMessage = {\n role: 'reasoning'\n id: string\n content: string\n encryptedValue?: string\n metadata?: MetadataRecord\n}\n\n/** Spec AG-UI message. No `parts`, no `createdAt` Date. */\ntype WireAnchorMessage = {\n id: string\n role: UIMessage['role']\n name?: string\n content?: string | Array<AGUIInputContent>\n toolCalls?: Array<AGUIToolCallMirror>\n metadata?: MetadataRecord\n}\n\nexport type WireMessage =\n | WireAnchorMessage\n | AGUIToolMessage\n | AGUIReasoningMessage\n\n/**\n * Serialize TanStack `UIMessage`s into the AG-UI `RunAgentInput.messages`\n * wire shape. Anchors are spec-only (`id`, `role`, `name`, `content`,\n * `toolCalls`, `metadata`). Tool results and thinking parts on assistant\n * messages are additionally emitted as fan-out `{role:'tool',...}` and\n * `{role:'reasoning',...}` entries for strict AG-UI server consumers.\n */\nexport function uiMessagesToWire(\n messages: Array<UIMessage>,\n): Array<WireMessage> {\n const wire: Array<WireMessage> = []\n\n for (const msg of messages) {\n // Defensive: ModelMessage-shaped input has no `parts`; fall back to `content`.\n const parts: ReadonlyArray<MessagePart> =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- runtime input may be ModelMessage-shaped (no `parts`); cast forces the optional-chain fallback below to remain in scope\n (msg.parts as ReadonlyArray<MessagePart> | undefined) ?? []\n\n if (msg.role === 'system') {\n wire.push(\n toAnchor(\n msg,\n {\n content:\n parts.length > 0\n ? collectText(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n ),\n )\n continue\n }\n\n if (msg.role === 'user') {\n wire.push(\n toAnchor(\n msg,\n {\n content:\n parts.length > 0\n ? collectUserContent(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n ),\n )\n continue\n }\n\n // assistant: emit reasoning fan-outs first, then anchor, then tool fan-outs\n for (const part of parts) {\n if (part.type === 'thinking') {\n const reasoning: AGUIReasoningMessage = {\n role: 'reasoning',\n id: deriveReasoningId(msg.id, part),\n content: part.content,\n }\n if (part.signature) {\n reasoning.encryptedValue = part.signature\n }\n wire.push(reasoning)\n }\n }\n\n const text = collectText(parts)\n const toolCalls = collectToolCalls(parts)\n wire.push(\n toAnchor(\n msg,\n {\n ...(text !== '' && { content: text }),\n ...(toolCalls && { toolCalls }),\n },\n parts,\n ),\n )\n\n for (const part of parts) {\n if (part.type === 'tool-result') {\n wire.push({\n role: 'tool',\n id: deriveToolMessageId(part.toolCallId),\n toolCallId: part.toolCallId,\n content:\n typeof part.content === 'string'\n ? part.content\n : JSON.stringify(part.content),\n ...(part.error !== undefined && { error: part.error }),\n })\n }\n }\n }\n\n return wire\n}\n\nfunction toAnchor(\n msg: UIMessage,\n extras: {\n content?: string | Array<AGUIInputContent>\n toolCalls?: Array<AGUIToolCallMirror>\n },\n parts: ReadonlyArray<MessagePart>,\n): WireAnchorMessage {\n const metadata = messageMetadata(msg, parts)\n const name = (msg as { name?: string }).name\n return {\n id: msg.id,\n role: msg.role,\n ...(name !== undefined && { name }),\n ...extras,\n ...(metadata !== undefined && { metadata }),\n }\n}\n\nfunction messageMetadata(\n msg: UIMessage,\n parts: ReadonlyArray<MessagePart>,\n): MetadataRecord | undefined {\n const base: MetadataRecord = { ...(msg.metadata ?? {}) }\n const tanstack: MetadataRecord = { ...(tanstackMetadata(msg) ?? {}) }\n if (msg.createdAt) tanstack.createdAt = msg.createdAt.toISOString()\n\n const leftover = unfinishedStructuredOutput(parts)\n if (leftover) tanstack.structuredOutput = leftover\n\n const toolCallMetadata: Record<string, unknown> = {}\n for (const part of parts) {\n if (part.type === 'tool-call' && part.metadata !== undefined) {\n toolCallMetadata[part.id] = part.metadata\n }\n }\n if (Object.keys(toolCallMetadata).length > 0) {\n tanstack.toolCallMetadata = toolCallMetadata\n }\n\n const uiResources = parts.filter(\n (p): p is UIResourcePart => p.type === 'ui-resource',\n )\n if (uiResources.length > 0) tanstack.uiResources = uiResources\n\n if (Object.keys(tanstack).length > 0) base.tanstack = tanstack\n return Object.keys(base).length > 0 ? base : undefined\n}\n\nfunction unfinishedStructuredOutput(\n parts: ReadonlyArray<MessagePart>,\n): TanStackMessageMetadata['structuredOutput'] | undefined {\n for (const p of parts) {\n if (p.type === 'structured-output' && p.status !== 'complete') {\n return structuredOutputLeftover(p)\n }\n }\n return undefined\n}\n\nfunction structuredOutputLeftover(\n part: StructuredOutputPart,\n): NonNullable<TanStackMessageMetadata['structuredOutput']> {\n return {\n status: part.status,\n raw: part.raw,\n ...(part.errorMessage !== undefined && { errorMessage: part.errorMessage }),\n }\n}\n\nfunction collectText(parts: ReadonlyArray<MessagePart>): string {\n // The streamed JSON of a completed structured-output part is the source of\n // truth for multi-turn coherence — emitting it back as assistant content\n // lets the LLM see its own prior structured response. Streaming/errored\n // parts are skipped: they'd ship malformed JSON fragments and confuse the\n // model. `completeStructuredOutputPart` tries hard to populate `raw`\n // (caller → existing buffer → `JSON.stringify(data)`), but the stringify\n // fallback can leave it empty when `data` is unserializable (BigInt,\n // circular). The `p.raw !== ''` guard below is what enforces \"no malformed\n // round-trip\" in that case — without it we'd ship `''` and the model would\n // see an empty assistant turn.\n const out: Array<string> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push(p.content)\n } else if (\n p.type === 'structured-output' &&\n p.status === 'complete' &&\n p.raw !== ''\n ) {\n out.push(p.raw)\n }\n }\n return out.join('')\n}\n\nfunction collectUserContent(\n parts: ReadonlyArray<MessagePart>,\n): string | Array<AGUIInputContent> {\n const hasMultimodal = parts.some(\n (p) =>\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document',\n )\n if (!hasMultimodal) {\n return collectText(parts)\n }\n const out: Array<AGUIInputContent> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push({ type: 'text', text: p.content })\n } else if (\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document'\n ) {\n out.push(p)\n }\n }\n return out\n}\n\nfunction thoughtSignatureFromMetadata(metadata: unknown): string | undefined {\n if (\n metadata == null ||\n typeof metadata !== 'object' ||\n Array.isArray(metadata)\n ) {\n return undefined\n }\n if (!('thoughtSignature' in metadata)) return undefined\n const value = metadata.thoughtSignature\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction collectToolCalls(\n parts: ReadonlyArray<MessagePart>,\n): Array<AGUIToolCallMirror> | undefined {\n const calls: Array<AGUIToolCallMirror> = []\n for (const p of parts) {\n if (p.type === 'tool-call') {\n const encryptedValue = thoughtSignatureFromMetadata(p.metadata)\n calls.push({\n id: p.id,\n type: 'function',\n function: { name: p.name, arguments: p.arguments },\n ...(encryptedValue !== undefined ? { encryptedValue } : {}),\n })\n }\n }\n return calls.length > 0 ? calls : undefined\n}\n\nfunction deriveReasoningId(messageId: string, part: MessagePart): string {\n return `${messageId}-reasoning-${(part as { id?: string }).id ?? hashContent((part as { content: string }).content)}`\n}\n\nfunction deriveToolMessageId(toolCallId: string): string {\n return `tool-${toolCallId}`\n}\n\nfunction hashContent(s: string): string {\n // Cheap deterministic id suffix; collisions are tolerable since\n // reasoning ids only matter for AG-UI server consumers, not for our\n // own server's dedup logic (which keys on toolCallId, not reasoning id).\n let h = 0\n for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0\n return Math.abs(h).toString(36)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ag-ui-wire.js","names":[],"sources":["../../../src/utilities/ag-ui-wire.ts"],"sourcesContent":["import type {\n AssistantMessage,\n InputContent,\n ReasoningMessage,\n SystemMessage,\n ToolCall,\n ToolMessage,\n UserMessage,\n} from '@ag-ui/core'\nimport type {\n ContentPart,\n MessagePart,\n ModelMessage,\n StructuredOutputPart,\n TanStackMessageMetadata,\n UIMessage,\n UIResourcePart,\n} from '../types'\nimport type { MetadataRecord } from './merge-metadata'\nimport { tanstackMetadata } from './merge-metadata'\nimport { normalizeToolResult } from './tool-result'\nimport {\n coerceCreatedAt,\n modelMessageToUIMessage,\n} from '../activities/chat/messages'\n\ntype WithMetadata<T> = T & { metadata?: MetadataRecord }\ntype WireSystemMessage = WithMetadata<SystemMessage>\ntype WireUserMessage = WithMetadata<UserMessage>\ntype WireAssistantMessage = WithMetadata<AssistantMessage>\ntype WireToolMessage = WithMetadata<\n ToolMessage & {\n name?: string\n }\n>\ntype WireReasoningMessage = WithMetadata<ReasoningMessage>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction rebuiltToolMetadata(\n metadata: unknown,\n createdAt: unknown,\n id: string | undefined,\n content: string | null | Array<ContentPart>,\n anchorOwnsUiResources = false,\n): MetadataRecord | undefined {\n const source: MetadataRecord = isRecord(metadata) ? metadata : {}\n const tanstack = isRecord(source.tanstack) ? { ...source.tanstack } : {}\n if (anchorOwnsUiResources) delete tanstack.uiResources\n const date = coerceCreatedAt(createdAt)\n const toolResult: NonNullable<TanStackMessageMetadata['toolResult']> = {\n ...(id !== undefined ? { id } : {}),\n ...(date && { createdAt: date.toISOString() }),\n ...(Array.isArray(content) && { content }),\n }\n const result = {\n ...source,\n tanstack: { ...tanstack, toolResult },\n }\n return Object.keys(result).length ? result : undefined\n}\n\nexport type WireMessage =\n | WireSystemMessage\n | WireUserMessage\n | WireAssistantMessage\n | WireToolMessage\n | WireReasoningMessage\n\n/**\n * Serialize TanStack `UIMessage`s and `ModelMessage`s into the AG-UI\n * `RunAgentInput.messages` wire shape. Anchors are spec-only (`id`, `role`,\n * `name`, `content`, `toolCalls`, `metadata`). Tool results and thinking parts\n * on assistant messages are additionally emitted as fan-out\n * `{role:'tool',...}` and `{role:'reasoning',...}` entries for strict AG-UI\n * server consumers. Set `includeSnapshotStructuredOutput` to retain complete\n * structured-output metadata for UI snapshots.\n */\nexport function uiMessagesToWire(\n messages: Array<UIMessage | ModelMessage>,\n options?: { includeSnapshotStructuredOutput: boolean },\n): Array<WireMessage> {\n const wire: Array<WireMessage> = []\n const usedWireIds = new Set<string>(\n messages.flatMap((message) =>\n 'id' in message && message.id && message.role !== 'tool'\n ? [message.id]\n : [],\n ),\n )\n const includeSnapshotStructuredOutput =\n options?.includeSnapshotStructuredOutput ?? false\n\n const assistantIds = new Set<string>()\n for (const msg of messages) {\n if (msg.role === 'assistant' && msg.id !== undefined) {\n assistantIds.add(msg.id)\n }\n }\n\n for (const msg of messages) {\n if (!('parts' in msg) && msg.role === 'tool' && msg.toolCallId) {\n const id = uniqueToolWireId(\n toolWireId(msg.id, msg.toolCallId, assistantIds),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n msg.metadata,\n msg.createdAt,\n msg.id,\n msg.content,\n )\n wire.push({\n role: 'tool',\n id,\n ...(msg.name !== undefined && { name: msg.name }),\n toolCallId: msg.toolCallId,\n content:\n typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content),\n ...(msg.error !== undefined && { error: msg.error }),\n ...(metadata !== undefined && { metadata }),\n })\n continue\n }\n\n const uiMessage: UIMessage =\n 'parts' in msg ? msg : modelMessageToUIMessage(msg, msg.id)\n const parts: ReadonlyArray<MessagePart> = uiMessage.parts\n usedWireIds.add(uiMessage.id)\n\n if (msg.role === 'system') {\n wire.push(\n toAnchor(\n uiMessage,\n 'system',\n {\n content:\n parts.length > 0\n ? collectText(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n if (msg.role === 'user') {\n wire.push(\n toAnchor(\n uiMessage,\n 'user',\n {\n content:\n parts.length > 0\n ? collectUserContent(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n // assistant: emit reasoning fan-outs first, then anchor, then tool fan-outs\n for (const part of parts) {\n if (part.type === 'thinking') {\n const reasoning: WireReasoningMessage = {\n role: 'reasoning',\n id: uniqueWireId(deriveReasoningId(uiMessage.id, part), usedWireIds),\n content: part.content,\n }\n if (part.signature) {\n reasoning.encryptedValue = part.signature\n }\n wire.push(reasoning)\n }\n }\n\n const text = collectText(parts)\n const toolCalls = collectToolCalls(parts)\n wire.push(\n toAnchor(\n uiMessage,\n 'assistant',\n {\n ...(text !== '' && { content: text }),\n ...(toolCalls && { toolCalls }),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n\n const explicitToolResults = new Set(\n parts.flatMap((part) =>\n part.type === 'tool-result' ? [part.toolCallId] : [],\n ),\n )\n for (const part of parts) {\n if (part.type === 'tool-result') {\n const id = uniqueToolWireId(\n part.id ?? deriveToolMessageId(part.toolCallId),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n part.metadata,\n part.createdAt,\n part.id,\n part.content,\n true,\n )\n wire.push({\n role: 'tool',\n id,\n toolCallId: part.toolCallId,\n ...(part.name !== undefined && { name: part.name }),\n content:\n typeof part.content === 'string'\n ? part.content\n : JSON.stringify(part.content),\n ...(part.error !== undefined && { error: part.error }),\n ...(metadata !== undefined && { metadata }),\n })\n } else if (part.type === 'tool-call') {\n const approved = part.approval?.approved\n if (\n explicitToolResults.has(part.id) ||\n (part.output === undefined &&\n (part.state !== 'approval-responded' || approved === undefined))\n ) {\n continue\n }\n const result =\n part.output !== undefined\n ? normalizeToolResult(part.output)\n : JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n })\n const content =\n typeof result === 'string' ? result : JSON.stringify(result)\n wire.push({\n role: 'tool',\n id: uniqueToolWireId(deriveToolMessageId(part.id), usedWireIds),\n toolCallId: part.id,\n content,\n metadata: rebuiltToolMetadata(\n undefined,\n undefined,\n undefined,\n result,\n ),\n })\n }\n }\n }\n\n return wire\n}\n\nfunction toAnchor(\n msg: UIMessage,\n role: 'system',\n extras: { content: string },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'user',\n extras: { content: string | Array<InputContent> },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireUserMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'assistant',\n extras: {\n content?: string\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireAssistantMessage\nfunction toAnchor(\n msg: UIMessage,\n role: UIMessage['role'],\n extras: {\n content?: string | Array<InputContent>\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage | WireUserMessage | WireAssistantMessage {\n const metadata = messageMetadata(msg, parts, includeSnapshotStructuredOutput)\n const base = {\n id: msg.id,\n ...(msg.name !== undefined && { name: msg.name }),\n ...(metadata !== undefined && { metadata }),\n }\n if (role === 'system') {\n return { ...base, role, content: String(extras.content ?? '') }\n }\n if (role === 'user') {\n return { ...base, role, content: extras.content ?? '' }\n }\n return {\n ...base,\n role,\n ...(typeof extras.content === 'string' && { content: extras.content }),\n ...(extras.toolCalls !== undefined && { toolCalls: extras.toolCalls }),\n }\n}\n\nfunction messageMetadata(\n msg: UIMessage,\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): MetadataRecord | undefined {\n const base: MetadataRecord = { ...(msg.metadata ?? {}) }\n const previousTanstack = tanstackMetadata(msg)\n const tanstack: TanStackMessageMetadata = {}\n if (previousTanstack?.model !== undefined)\n tanstack.model = previousTanstack.model\n if (previousTanstack?.signature !== undefined)\n tanstack.signature = previousTanstack.signature\n const createdAt = coerceCreatedAt(msg.createdAt)\n if (createdAt !== undefined) tanstack.createdAt = createdAt.toISOString()\n\n const structuredOutput = serializedStructuredOutput(\n parts,\n includeSnapshotStructuredOutput,\n )\n if (structuredOutput) tanstack.structuredOutput = structuredOutput\n\n const toolCallMetadata: Record<string, unknown> = {}\n for (const part of parts) {\n if (part.type === 'tool-call' && part.metadata !== undefined) {\n toolCallMetadata[part.id] = part.metadata\n }\n }\n if (Object.keys(toolCallMetadata).length > 0) {\n tanstack.toolCallMetadata = toolCallMetadata\n }\n\n const uiResources = parts.filter(\n (p): p is UIResourcePart => p.type === 'ui-resource',\n )\n if (uiResources.length > 0) tanstack.uiResources = uiResources\n\n if (Object.keys(tanstack).length > 0) base.tanstack = tanstack\n else delete base.tanstack\n return Object.keys(base).length > 0 ? base : undefined\n}\n\nfunction serializedStructuredOutput(\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): TanStackMessageMetadata['structuredOutput'] | undefined {\n for (const p of parts) {\n if (\n p.type === 'structured-output' &&\n (includeSnapshotStructuredOutput || p.status !== 'complete')\n ) {\n return structuredOutputMetadata(p, includeSnapshotStructuredOutput)\n }\n }\n return undefined\n}\n\nfunction structuredOutputMetadata(\n part: StructuredOutputPart,\n includeSnapshotStructuredOutput: boolean,\n): NonNullable<TanStackMessageMetadata['structuredOutput']> {\n return {\n status: part.status,\n raw: part.raw,\n ...(includeSnapshotStructuredOutput && part.partial !== undefined\n ? { partial: part.partial }\n : {}),\n ...(includeSnapshotStructuredOutput && part.data !== undefined\n ? { data: part.data }\n : {}),\n ...(includeSnapshotStructuredOutput && part.reasoning\n ? { reasoning: part.reasoning }\n : {}),\n ...(part.errorMessage !== undefined && { errorMessage: part.errorMessage }),\n }\n}\n\nfunction collectText(parts: ReadonlyArray<MessagePart>): string {\n // The streamed JSON of a completed structured-output part is the source of\n // truth for multi-turn coherence — emitting it back as assistant content\n // lets the LLM see its own prior structured response. Streaming/errored\n // parts are skipped: they'd ship malformed JSON fragments and confuse the\n // model. `completeStructuredOutputPart` tries hard to populate `raw`\n // (caller → existing buffer → `JSON.stringify(data)`), but the stringify\n // fallback can leave it empty when `data` is unserializable (BigInt,\n // circular). The `p.raw !== ''` guard below is what enforces \"no malformed\n // round-trip\" in that case — without it we'd ship `''` and the model would\n // see an empty assistant turn.\n const out: Array<string> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push(p.content)\n } else if (\n p.type === 'structured-output' &&\n p.status === 'complete' &&\n p.raw !== ''\n ) {\n out.push(p.raw)\n }\n }\n return out.join('')\n}\n\nfunction collectUserContent(\n parts: ReadonlyArray<MessagePart>,\n): string | Array<InputContent> {\n const hasMultimodal = parts.some(\n (p) =>\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document',\n )\n if (!hasMultimodal) {\n return collectText(parts)\n }\n const out: Array<InputContent> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push({ type: 'text', text: p.content })\n } else if (\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document'\n ) {\n out.push(p)\n }\n }\n return out\n}\n\nfunction thoughtSignatureFromMetadata(metadata: unknown): string | undefined {\n if (\n metadata == null ||\n typeof metadata !== 'object' ||\n Array.isArray(metadata)\n ) {\n return undefined\n }\n if (!('thoughtSignature' in metadata)) return undefined\n const value = metadata.thoughtSignature\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction collectToolCalls(\n parts: ReadonlyArray<MessagePart>,\n): Array<ToolCall> | undefined {\n const calls: Array<ToolCall> = []\n for (const p of parts) {\n if (p.type === 'tool-call') {\n const encryptedValue = thoughtSignatureFromMetadata(p.metadata)\n calls.push({\n id: p.id,\n type: 'function',\n function: { name: p.name, arguments: p.arguments },\n ...(encryptedValue !== undefined ? { encryptedValue } : {}),\n })\n }\n }\n return calls.length > 0 ? calls : undefined\n}\n\nfunction deriveReasoningId(messageId: string, part: MessagePart): string {\n return `${messageId}-reasoning-${(part as { id?: string }).id ?? hashContent((part as { content: string }).content)}`\n}\n\nfunction deriveToolMessageId(toolCallId: string): string {\n return `tool-${toolCallId}`\n}\n\nfunction uniqueToolWireId(id: string, used: Set<string>): string {\n return uniqueWireId(id, used)\n}\n\nfunction uniqueWireId(id: string, used: Set<string>): string {\n if (!used.has(id)) {\n used.add(id)\n return id\n }\n let suffix = 2\n while (used.has(`${id}-${suffix}`)) suffix++\n const unique = `${id}-${suffix}`\n used.add(unique)\n return unique\n}\n\nfunction toolWireId(\n id: string | undefined,\n toolCallId: string,\n assistantIds: ReadonlySet<string>,\n): string {\n const derived = deriveToolMessageId(toolCallId)\n if (id === undefined || assistantIds.has(id)) return derived\n return id\n}\n\nfunction hashContent(s: string): string {\n // Cheap deterministic id suffix; collisions are tolerable since\n // reasoning ids only matter for AG-UI server consumers, not for our\n // own server's dedup logic (which keys on toolCallId, not reasoning id).\n let h = 0\n for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0\n return Math.abs(h).toString(36)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.0",
|
|
4
4
|
"description": "Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"@ag-ui/core": "0.1.1-canary.beta.0",
|
|
89
89
|
"@standard-schema/spec": "^1.1.0",
|
|
90
90
|
"partial-json": "^0.1.7",
|
|
91
|
-
"@tanstack/ai-event-client": "^0.
|
|
91
|
+
"@tanstack/ai-event-client": "^0.11.0",
|
|
92
92
|
"@tanstack/ai-utils": "^0.4.0"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
@@ -103,7 +103,6 @@ import type {
|
|
|
103
103
|
Interrupt,
|
|
104
104
|
JSONSchema,
|
|
105
105
|
LazyToolsConfig,
|
|
106
|
-
MessagesSnapshotEvent,
|
|
107
106
|
ModelMessage,
|
|
108
107
|
ProviderTool,
|
|
109
108
|
RunFinishedEvent,
|
|
@@ -2756,9 +2755,9 @@ class TextEngine<
|
|
|
2756
2755
|
return {
|
|
2757
2756
|
type: EventType.MESSAGES_SNAPSHOT,
|
|
2758
2757
|
timestamp: Date.now(),
|
|
2759
|
-
messages: uiMessagesToWire(
|
|
2760
|
-
|
|
2761
|
-
)
|
|
2758
|
+
messages: uiMessagesToWire(modelMessagesToUIMessages(withIds), {
|
|
2759
|
+
includeSnapshotStructuredOutput: true,
|
|
2760
|
+
}),
|
|
2762
2761
|
}
|
|
2763
2762
|
}
|
|
2764
2763
|
|