@copilotkit/runtime 1.55.1 → 1.55.2-next.1
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/CHANGELOG.md +13 -0
- package/dist/agent/converters/aisdk.cjs +215 -0
- package/dist/agent/converters/aisdk.cjs.map +1 -0
- package/dist/agent/converters/aisdk.d.cts +18 -0
- package/dist/agent/converters/aisdk.d.cts.map +1 -0
- package/dist/agent/converters/aisdk.d.mts +18 -0
- package/dist/agent/converters/aisdk.d.mts.map +1 -0
- package/dist/agent/converters/aisdk.mjs +214 -0
- package/dist/agent/converters/aisdk.mjs.map +1 -0
- package/dist/agent/converters/index.d.mts +3 -0
- package/dist/agent/converters/tanstack.cjs +180 -0
- package/dist/agent/converters/tanstack.cjs.map +1 -0
- package/dist/agent/converters/tanstack.d.cts +68 -0
- package/dist/agent/converters/tanstack.d.cts.map +1 -0
- package/dist/agent/converters/tanstack.d.mts +68 -0
- package/dist/agent/converters/tanstack.d.mts.map +1 -0
- package/dist/agent/converters/tanstack.mjs +178 -0
- package/dist/agent/converters/tanstack.mjs.map +1 -0
- package/dist/agent/index.cjs +111 -17
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +61 -4
- package/dist/agent/index.d.cts.map +1 -1
- package/dist/agent/index.d.mts +62 -4
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +111 -17
- package/dist/agent/index.mjs.map +1 -1
- package/dist/lib/integrations/nextjs/pages-router.cjs.map +1 -1
- package/dist/lib/integrations/nextjs/pages-router.d.cts.map +1 -1
- package/dist/lib/integrations/nextjs/pages-router.d.mts.map +1 -1
- package/dist/lib/integrations/nextjs/pages-router.mjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.cjs +4 -2
- package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.mjs +4 -2
- package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
- package/dist/lib/runtime/mcp-tools-utils.cjs +1 -1
- package/dist/lib/runtime/mcp-tools-utils.cjs.map +1 -1
- package/dist/lib/runtime/mcp-tools-utils.mjs +1 -1
- package/dist/lib/runtime/mcp-tools-utils.mjs.map +1 -1
- package/dist/package.cjs +3 -2
- package/dist/package.mjs +3 -2
- package/dist/service-adapters/anthropic/utils.cjs +1 -1
- package/dist/service-adapters/anthropic/utils.cjs.map +1 -1
- package/dist/service-adapters/anthropic/utils.mjs +1 -1
- package/dist/service-adapters/anthropic/utils.mjs.map +1 -1
- package/dist/service-adapters/openai/utils.cjs +1 -1
- package/dist/service-adapters/openai/utils.cjs.map +1 -1
- package/dist/service-adapters/openai/utils.mjs +1 -1
- package/dist/service-adapters/openai/utils.mjs.map +1 -1
- package/dist/v2/index.cjs +5 -0
- package/dist/v2/index.d.cts +4 -2
- package/dist/v2/index.d.mts +4 -2
- package/dist/v2/index.mjs +3 -1
- package/package.json +4 -3
- package/src/agent/__tests__/agent-test-helpers.ts +446 -0
- package/src/agent/__tests__/agent.test.ts +593 -0
- package/src/agent/__tests__/converter-aisdk.test.ts +692 -0
- package/src/agent/__tests__/converter-custom.test.ts +319 -0
- package/src/agent/__tests__/converter-tanstack-input.test.ts +211 -0
- package/src/agent/__tests__/converter-tanstack.test.ts +314 -0
- package/src/agent/__tests__/mcp-servers-integration.test.ts +373 -0
- package/src/agent/__tests__/multimodal-tanstack.test.ts +284 -0
- package/src/agent/__tests__/test-helpers.ts +12 -8
- package/src/agent/converters/aisdk.ts +326 -0
- package/src/agent/converters/index.ts +7 -0
- package/src/agent/converters/tanstack.ts +286 -0
- package/src/agent/index.ts +245 -26
- package/src/lib/integrations/nextjs/pages-router.ts +1 -0
- package/src/lib/runtime/copilot-runtime.ts +21 -12
- package/src/lib/runtime/mcp-tools-utils.ts +1 -1
- package/src/service-adapters/anthropic/utils.ts +1 -1
- package/src/service-adapters/openai/utils.ts +1 -1
- package/src/v2/runtime/__tests__/mcp-apps-middleware-integration.test.ts +275 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
require("reflect-metadata");
|
|
2
|
+
const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
|
|
3
|
+
let _copilotkit_shared = require("@copilotkit/shared");
|
|
4
|
+
let _ag_ui_client = require("@ag-ui/client");
|
|
5
|
+
|
|
6
|
+
//#region src/agent/converters/tanstack.ts
|
|
7
|
+
/**
|
|
8
|
+
* Converts AG-UI user message content to TanStack AI format.
|
|
9
|
+
* Handles plain strings, multimodal parts (image/audio/video/document),
|
|
10
|
+
* and legacy BinaryInputContent for backward compatibility.
|
|
11
|
+
*/
|
|
12
|
+
function convertUserContent(content) {
|
|
13
|
+
if (!content) return null;
|
|
14
|
+
if (typeof content === "string") return content;
|
|
15
|
+
if (!Array.isArray(content)) return null;
|
|
16
|
+
if (content.length === 0) return "";
|
|
17
|
+
const parts = [];
|
|
18
|
+
for (const part of content) {
|
|
19
|
+
if (!part || typeof part !== "object" || !("type" in part)) continue;
|
|
20
|
+
switch (part.type) {
|
|
21
|
+
case "text": {
|
|
22
|
+
const text = part.text;
|
|
23
|
+
if (text != null) parts.push({
|
|
24
|
+
type: "text",
|
|
25
|
+
content: text
|
|
26
|
+
});
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case "image":
|
|
30
|
+
case "audio":
|
|
31
|
+
case "video":
|
|
32
|
+
case "document": {
|
|
33
|
+
const source = part.source;
|
|
34
|
+
if (!source) break;
|
|
35
|
+
const partType = part.type;
|
|
36
|
+
if (source.type === "data") parts.push({
|
|
37
|
+
type: partType,
|
|
38
|
+
source: {
|
|
39
|
+
type: "data",
|
|
40
|
+
value: source.value,
|
|
41
|
+
mimeType: source.mimeType
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
else if (source.type === "url") parts.push({
|
|
45
|
+
type: partType,
|
|
46
|
+
source: {
|
|
47
|
+
type: "url",
|
|
48
|
+
value: source.value,
|
|
49
|
+
...source.mimeType ? { mimeType: source.mimeType } : {}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case "binary": {
|
|
55
|
+
const legacy = part;
|
|
56
|
+
const mimeType = legacy.mimeType ?? "application/octet-stream";
|
|
57
|
+
const isImage = mimeType.startsWith("image/");
|
|
58
|
+
if (legacy.data) {
|
|
59
|
+
const partType = isImage ? "image" : "document";
|
|
60
|
+
parts.push({
|
|
61
|
+
type: partType,
|
|
62
|
+
source: {
|
|
63
|
+
type: "data",
|
|
64
|
+
value: legacy.data,
|
|
65
|
+
mimeType
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
} else if (legacy.url) {
|
|
69
|
+
const partType = isImage ? "image" : "document";
|
|
70
|
+
parts.push({
|
|
71
|
+
type: partType,
|
|
72
|
+
source: {
|
|
73
|
+
type: "url",
|
|
74
|
+
value: legacy.url,
|
|
75
|
+
mimeType
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return parts.length > 0 ? parts : "";
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Converts a RunAgentInput into the format expected by TanStack AI's `chat()`.
|
|
87
|
+
*
|
|
88
|
+
* - Keeps only user/assistant/tool messages (activity, reasoning, and other roles are also excluded)
|
|
89
|
+
* - Extracts system/developer messages into `systemPrompts`
|
|
90
|
+
* - Appends context entries and application state to `systemPrompts`
|
|
91
|
+
* - Preserves tool calls on assistant messages and toolCallId on tool messages
|
|
92
|
+
*/
|
|
93
|
+
function convertInputToTanStackAI(input) {
|
|
94
|
+
const chatRoles = new Set([
|
|
95
|
+
"user",
|
|
96
|
+
"assistant",
|
|
97
|
+
"tool"
|
|
98
|
+
]);
|
|
99
|
+
const messages = input.messages.filter((m) => chatRoles.has(m.role)).map((m) => {
|
|
100
|
+
const msg = {
|
|
101
|
+
role: m.role,
|
|
102
|
+
content: m.role === "user" ? convertUserContent(m.content) : typeof m.content === "string" ? m.content : null
|
|
103
|
+
};
|
|
104
|
+
if (m.role === "assistant" && "toolCalls" in m && m.toolCalls) msg.toolCalls = m.toolCalls.map((tc) => ({
|
|
105
|
+
id: tc.id,
|
|
106
|
+
type: "function",
|
|
107
|
+
function: {
|
|
108
|
+
name: tc.function.name,
|
|
109
|
+
arguments: tc.function.arguments
|
|
110
|
+
}
|
|
111
|
+
}));
|
|
112
|
+
if (m.role === "tool" && "toolCallId" in m) msg.toolCallId = m.toolCallId;
|
|
113
|
+
return msg;
|
|
114
|
+
});
|
|
115
|
+
const systemPrompts = [];
|
|
116
|
+
for (const m of input.messages) if ((m.role === "system" || m.role === "developer") && m.content) systemPrompts.push(typeof m.content === "string" ? m.content : JSON.stringify(m.content));
|
|
117
|
+
if (input.context?.length) for (const ctx of input.context) systemPrompts.push(`${ctx.description}:\n${ctx.value}`);
|
|
118
|
+
if (input.state !== void 0 && input.state !== null && typeof input.state === "object" && Object.keys(input.state).length > 0) systemPrompts.push(`Application State:\n\`\`\`json\n${JSON.stringify(input.state, null, 2)}\n\`\`\``);
|
|
119
|
+
return {
|
|
120
|
+
messages,
|
|
121
|
+
systemPrompts
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Converts a TanStack AI stream into AG-UI `BaseEvent` objects.
|
|
126
|
+
*
|
|
127
|
+
* This is a pure converter — it does NOT emit lifecycle events
|
|
128
|
+
* (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class)
|
|
129
|
+
* is responsible for those.
|
|
130
|
+
*/
|
|
131
|
+
async function* convertTanStackStream(stream, abortSignal) {
|
|
132
|
+
const messageId = (0, _copilotkit_shared.randomUUID)();
|
|
133
|
+
for await (const chunk of stream) {
|
|
134
|
+
if (abortSignal.aborted) break;
|
|
135
|
+
const raw = chunk;
|
|
136
|
+
const type = raw.type;
|
|
137
|
+
if (type === "TEXT_MESSAGE_CONTENT" && raw.delta) yield {
|
|
138
|
+
type: _ag_ui_client.EventType.TEXT_MESSAGE_CHUNK,
|
|
139
|
+
role: "assistant",
|
|
140
|
+
messageId,
|
|
141
|
+
delta: raw.delta
|
|
142
|
+
};
|
|
143
|
+
else if (type === "TOOL_CALL_START") yield {
|
|
144
|
+
type: _ag_ui_client.EventType.TOOL_CALL_START,
|
|
145
|
+
parentMessageId: messageId,
|
|
146
|
+
toolCallId: raw.toolCallId,
|
|
147
|
+
toolCallName: raw.toolCallName
|
|
148
|
+
};
|
|
149
|
+
else if (type === "TOOL_CALL_ARGS") yield {
|
|
150
|
+
type: _ag_ui_client.EventType.TOOL_CALL_ARGS,
|
|
151
|
+
toolCallId: raw.toolCallId,
|
|
152
|
+
delta: raw.delta
|
|
153
|
+
};
|
|
154
|
+
else if (type === "TOOL_CALL_END") yield {
|
|
155
|
+
type: _ag_ui_client.EventType.TOOL_CALL_END,
|
|
156
|
+
toolCallId: raw.toolCallId
|
|
157
|
+
};
|
|
158
|
+
else if (type === "TOOL_CALL_RESULT") {
|
|
159
|
+
let serializedContent;
|
|
160
|
+
if (typeof raw.content === "string") serializedContent = raw.content;
|
|
161
|
+
else try {
|
|
162
|
+
serializedContent = JSON.stringify(raw.content ?? raw.result ?? null);
|
|
163
|
+
} catch {
|
|
164
|
+
serializedContent = "[Unserializable tool result]";
|
|
165
|
+
}
|
|
166
|
+
yield {
|
|
167
|
+
type: _ag_ui_client.EventType.TOOL_CALL_RESULT,
|
|
168
|
+
role: "tool",
|
|
169
|
+
messageId: (0, _copilotkit_shared.randomUUID)(),
|
|
170
|
+
toolCallId: raw.toolCallId,
|
|
171
|
+
content: serializedContent
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
exports.convertInputToTanStackAI = convertInputToTanStackAI;
|
|
179
|
+
exports.convertTanStackStream = convertTanStackStream;
|
|
180
|
+
//# sourceMappingURL=tanstack.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.cjs","names":["EventType"],"sources":["../../../src/agent/converters/tanstack.ts"],"sourcesContent":["import {\n BaseEvent,\n EventType,\n RunAgentInput,\n Message,\n TextMessageChunkEvent,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallStartEvent,\n ToolCallResultEvent,\n} from \"@ag-ui/client\";\nimport { randomUUID } from \"@copilotkit/shared\";\n\n/**\n * A TanStack AI content part (text, image, audio, video, or document).\n */\nexport type TanStackContentPart =\n | { type: \"text\"; content: string }\n | {\n type: \"image\" | \"audio\" | \"video\" | \"document\";\n source:\n | { type: \"data\"; value: string; mimeType: string }\n | { type: \"url\"; value: string; mimeType?: string };\n };\n\n/**\n * Message format expected by TanStack AI's `chat()`.\n */\nexport interface TanStackChatMessage {\n role: \"user\" | \"assistant\" | \"tool\";\n content: string | null | TanStackContentPart[];\n name?: string;\n toolCalls?: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }>;\n toolCallId?: string;\n}\n\n/**\n * Result of converting RunAgentInput to TanStack AI format.\n */\nexport interface TanStackInputResult {\n /** Chat messages (only user/assistant/tool roles; all others excluded) */\n messages: TanStackChatMessage[];\n /** System prompts extracted from system/developer messages, context, and state */\n systemPrompts: string[];\n}\n\n/**\n * Converts AG-UI user message content to TanStack AI format.\n * Handles plain strings, multimodal parts (image/audio/video/document),\n * and legacy BinaryInputContent for backward compatibility.\n */\nfunction convertUserContent(\n content: unknown,\n): string | null | TanStackContentPart[] {\n if (!content) return null;\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return null;\n if (content.length === 0) return \"\";\n\n const parts: TanStackContentPart[] = [];\n\n for (const part of content) {\n if (!part || typeof part !== \"object\" || !(\"type\" in part)) continue;\n\n switch ((part as { type: string }).type) {\n case \"text\": {\n const text = (part as { text?: string }).text;\n if (text != null) parts.push({ type: \"text\", content: text });\n break;\n }\n\n case \"image\":\n case \"audio\":\n case \"video\":\n case \"document\": {\n const source = (part as { source?: any }).source;\n if (!source) break;\n const partType = (part as { type: string }).type as\n | \"image\"\n | \"audio\"\n | \"video\"\n | \"document\";\n if (source.type === \"data\") {\n parts.push({\n type: partType,\n source: {\n type: \"data\",\n value: source.value,\n mimeType: source.mimeType,\n },\n });\n } else if (source.type === \"url\") {\n parts.push({\n type: partType,\n source: {\n type: \"url\",\n value: source.value,\n ...(source.mimeType ? { mimeType: source.mimeType } : {}),\n },\n });\n }\n break;\n }\n\n // Legacy BinaryInputContent backward compatibility\n case \"binary\": {\n const legacy = part as {\n mimeType?: string;\n data?: string;\n url?: string;\n };\n const mimeType = legacy.mimeType ?? \"application/octet-stream\";\n const isImage = mimeType.startsWith(\"image/\");\n\n if (legacy.data) {\n const partType = isImage ? \"image\" : \"document\";\n parts.push({\n type: partType,\n source: { type: \"data\", value: legacy.data, mimeType },\n });\n } else if (legacy.url) {\n const partType = isImage ? \"image\" : \"document\";\n parts.push({\n type: partType,\n source: { type: \"url\", value: legacy.url, mimeType },\n });\n }\n break;\n }\n }\n }\n\n return parts.length > 0 ? parts : \"\";\n}\n\n/**\n * Converts a RunAgentInput into the format expected by TanStack AI's `chat()`.\n *\n * - Keeps only user/assistant/tool messages (activity, reasoning, and other roles are also excluded)\n * - Extracts system/developer messages into `systemPrompts`\n * - Appends context entries and application state to `systemPrompts`\n * - Preserves tool calls on assistant messages and toolCallId on tool messages\n */\nexport function convertInputToTanStackAI(\n input: RunAgentInput,\n): TanStackInputResult {\n // Allowlist: only pass user/assistant/tool messages to TanStack.\n // Other roles (system, developer, activity, reasoning) are either\n // extracted into systemPrompts or not applicable.\n const chatRoles = new Set([\"user\", \"assistant\", \"tool\"]);\n const messages: TanStackChatMessage[] = input.messages\n .filter((m: Message) => chatRoles.has(m.role))\n .map((m: Message): TanStackChatMessage => {\n const msg: TanStackChatMessage = {\n role: m.role as \"user\" | \"assistant\" | \"tool\",\n content:\n m.role === \"user\"\n ? convertUserContent(m.content)\n : typeof m.content === \"string\"\n ? m.content\n : null,\n };\n if (m.role === \"assistant\" && \"toolCalls\" in m && m.toolCalls) {\n msg.toolCalls = m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: {\n name: tc.function.name,\n arguments: tc.function.arguments,\n },\n }));\n }\n if (m.role === \"tool\" && \"toolCallId\" in m) {\n msg.toolCallId = (m as Record<string, unknown>).toolCallId as string;\n }\n return msg;\n });\n\n const systemPrompts: string[] = [];\n for (const m of input.messages) {\n if ((m.role === \"system\" || m.role === \"developer\") && m.content) {\n systemPrompts.push(\n typeof m.content === \"string\" ? m.content : JSON.stringify(m.content),\n );\n }\n }\n\n if (input.context?.length) {\n for (const ctx of input.context) {\n systemPrompts.push(`${ctx.description}:\\n${ctx.value}`);\n }\n }\n\n if (\n input.state !== undefined &&\n input.state !== null &&\n typeof input.state === \"object\" &&\n Object.keys(input.state).length > 0\n ) {\n systemPrompts.push(\n `Application State:\\n\\`\\`\\`json\\n${JSON.stringify(input.state, null, 2)}\\n\\`\\`\\``,\n );\n }\n\n return { messages, systemPrompts };\n}\n\n/**\n * Converts a TanStack AI stream into AG-UI `BaseEvent` objects.\n *\n * This is a pure converter — it does NOT emit lifecycle events\n * (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class)\n * is responsible for those.\n */\nexport async function* convertTanStackStream(\n stream: AsyncIterable<unknown>,\n abortSignal: AbortSignal,\n): AsyncGenerator<BaseEvent> {\n const messageId = randomUUID();\n\n for await (const chunk of stream) {\n if (abortSignal.aborted) break;\n\n const raw = chunk as Record<string, unknown>;\n const type = raw.type as string;\n\n if (type === \"TEXT_MESSAGE_CONTENT\" && raw.delta) {\n const textEvent: TextMessageChunkEvent = {\n type: EventType.TEXT_MESSAGE_CHUNK,\n role: \"assistant\",\n messageId,\n delta: raw.delta as string,\n };\n yield textEvent;\n } else if (type === \"TOOL_CALL_START\") {\n const startEvent: ToolCallStartEvent = {\n type: EventType.TOOL_CALL_START,\n parentMessageId: messageId,\n toolCallId: raw.toolCallId as string,\n toolCallName: raw.toolCallName as string,\n };\n yield startEvent;\n } else if (type === \"TOOL_CALL_ARGS\") {\n const argsEvent: ToolCallArgsEvent = {\n type: EventType.TOOL_CALL_ARGS,\n toolCallId: raw.toolCallId as string,\n delta: raw.delta as string,\n };\n yield argsEvent;\n } else if (type === \"TOOL_CALL_END\") {\n const endEvent: ToolCallEndEvent = {\n type: EventType.TOOL_CALL_END,\n toolCallId: raw.toolCallId as string,\n };\n yield endEvent;\n } else if (type === \"TOOL_CALL_RESULT\") {\n let serializedContent: string;\n if (typeof raw.content === \"string\") {\n serializedContent = raw.content;\n } else {\n try {\n serializedContent = JSON.stringify(raw.content ?? raw.result ?? null);\n } catch {\n serializedContent = \"[Unserializable tool result]\";\n }\n }\n const resultEvent: ToolCallResultEvent = {\n type: EventType.TOOL_CALL_RESULT,\n role: \"tool\",\n messageId: randomUUID(),\n toolCallId: raw.toolCallId as string,\n content: serializedContent,\n };\n yield resultEvent;\n }\n // Unhandled chunk types are silently ignored.\n // Known gaps: STATE_SNAPSHOT, STATE_DELTA, and REASONING events are not\n // converted from TanStack streams. Shared state and reasoning will not\n // surface when using the TanStack backend. Use the AI SDK backend if these\n // features are required.\n }\n}\n"],"mappings":";;;;;;;;;;;AAuDA,SAAS,mBACP,SACuC;AACvC,KAAI,CAAC,QAAS,QAAO;AACrB,KAAI,OAAO,YAAY,SAAU,QAAO;AACxC,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE,QAAO;AACpC,KAAI,QAAQ,WAAW,EAAG,QAAO;CAEjC,MAAM,QAA+B,EAAE;AAEvC,MAAK,MAAM,QAAQ,SAAS;AAC1B,MAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,EAAE,UAAU,MAAO;AAE5D,UAAS,KAA0B,MAAnC;GACE,KAAK,QAAQ;IACX,MAAM,OAAQ,KAA2B;AACzC,QAAI,QAAQ,KAAM,OAAM,KAAK;KAAE,MAAM;KAAQ,SAAS;KAAM,CAAC;AAC7D;;GAGF,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,YAAY;IACf,MAAM,SAAU,KAA0B;AAC1C,QAAI,CAAC,OAAQ;IACb,MAAM,WAAY,KAA0B;AAK5C,QAAI,OAAO,SAAS,OAClB,OAAM,KAAK;KACT,MAAM;KACN,QAAQ;MACN,MAAM;MACN,OAAO,OAAO;MACd,UAAU,OAAO;MAClB;KACF,CAAC;aACO,OAAO,SAAS,MACzB,OAAM,KAAK;KACT,MAAM;KACN,QAAQ;MACN,MAAM;MACN,OAAO,OAAO;MACd,GAAI,OAAO,WAAW,EAAE,UAAU,OAAO,UAAU,GAAG,EAAE;MACzD;KACF,CAAC;AAEJ;;GAIF,KAAK,UAAU;IACb,MAAM,SAAS;IAKf,MAAM,WAAW,OAAO,YAAY;IACpC,MAAM,UAAU,SAAS,WAAW,SAAS;AAE7C,QAAI,OAAO,MAAM;KACf,MAAM,WAAW,UAAU,UAAU;AACrC,WAAM,KAAK;MACT,MAAM;MACN,QAAQ;OAAE,MAAM;OAAQ,OAAO,OAAO;OAAM;OAAU;MACvD,CAAC;eACO,OAAO,KAAK;KACrB,MAAM,WAAW,UAAU,UAAU;AACrC,WAAM,KAAK;MACT,MAAM;MACN,QAAQ;OAAE,MAAM;OAAO,OAAO,OAAO;OAAK;OAAU;MACrD,CAAC;;AAEJ;;;;AAKN,QAAO,MAAM,SAAS,IAAI,QAAQ;;;;;;;;;;AAWpC,SAAgB,yBACd,OACqB;CAIrB,MAAM,YAAY,IAAI,IAAI;EAAC;EAAQ;EAAa;EAAO,CAAC;CACxD,MAAM,WAAkC,MAAM,SAC3C,QAAQ,MAAe,UAAU,IAAI,EAAE,KAAK,CAAC,CAC7C,KAAK,MAAoC;EACxC,MAAM,MAA2B;GAC/B,MAAM,EAAE;GACR,SACE,EAAE,SAAS,SACP,mBAAmB,EAAE,QAAQ,GAC7B,OAAO,EAAE,YAAY,WACnB,EAAE,UACF;GACT;AACD,MAAI,EAAE,SAAS,eAAe,eAAe,KAAK,EAAE,UAClD,KAAI,YAAY,EAAE,UAAU,KAAK,QAAQ;GACvC,IAAI,GAAG;GACP,MAAM;GACN,UAAU;IACR,MAAM,GAAG,SAAS;IAClB,WAAW,GAAG,SAAS;IACxB;GACF,EAAE;AAEL,MAAI,EAAE,SAAS,UAAU,gBAAgB,EACvC,KAAI,aAAc,EAA8B;AAElD,SAAO;GACP;CAEJ,MAAM,gBAA0B,EAAE;AAClC,MAAK,MAAM,KAAK,MAAM,SACpB,MAAK,EAAE,SAAS,YAAY,EAAE,SAAS,gBAAgB,EAAE,QACvD,eAAc,KACZ,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,KAAK,UAAU,EAAE,QAAQ,CACtE;AAIL,KAAI,MAAM,SAAS,OACjB,MAAK,MAAM,OAAO,MAAM,QACtB,eAAc,KAAK,GAAG,IAAI,YAAY,KAAK,IAAI,QAAQ;AAI3D,KACE,MAAM,UAAU,UAChB,MAAM,UAAU,QAChB,OAAO,MAAM,UAAU,YACvB,OAAO,KAAK,MAAM,MAAM,CAAC,SAAS,EAElC,eAAc,KACZ,mCAAmC,KAAK,UAAU,MAAM,OAAO,MAAM,EAAE,CAAC,UACzE;AAGH,QAAO;EAAE;EAAU;EAAe;;;;;;;;;AAUpC,gBAAuB,sBACrB,QACA,aAC2B;CAC3B,MAAM,gDAAwB;AAE9B,YAAW,MAAM,SAAS,QAAQ;AAChC,MAAI,YAAY,QAAS;EAEzB,MAAM,MAAM;EACZ,MAAM,OAAO,IAAI;AAEjB,MAAI,SAAS,0BAA0B,IAAI,MAOzC,OANyC;GACvC,MAAMA,wBAAU;GAChB,MAAM;GACN;GACA,OAAO,IAAI;GACZ;WAEQ,SAAS,kBAOlB,OANuC;GACrC,MAAMA,wBAAU;GAChB,iBAAiB;GACjB,YAAY,IAAI;GAChB,cAAc,IAAI;GACnB;WAEQ,SAAS,iBAMlB,OALqC;GACnC,MAAMA,wBAAU;GAChB,YAAY,IAAI;GAChB,OAAO,IAAI;GACZ;WAEQ,SAAS,gBAKlB,OAJmC;GACjC,MAAMA,wBAAU;GAChB,YAAY,IAAI;GACjB;WAEQ,SAAS,oBAAoB;GACtC,IAAI;AACJ,OAAI,OAAO,IAAI,YAAY,SACzB,qBAAoB,IAAI;OAExB,KAAI;AACF,wBAAoB,KAAK,UAAU,IAAI,WAAW,IAAI,UAAU,KAAK;WAC/D;AACN,wBAAoB;;AAUxB,SAPyC;IACvC,MAAMA,wBAAU;IAChB,MAAM;IACN,+CAAuB;IACvB,YAAY,IAAI;IAChB,SAAS;IACV"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
import { BaseEvent, RunAgentInput } from "@ag-ui/client";
|
|
3
|
+
|
|
4
|
+
//#region src/agent/converters/tanstack.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A TanStack AI content part (text, image, audio, video, or document).
|
|
7
|
+
*/
|
|
8
|
+
type TanStackContentPart = {
|
|
9
|
+
type: "text";
|
|
10
|
+
content: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: "image" | "audio" | "video" | "document";
|
|
13
|
+
source: {
|
|
14
|
+
type: "data";
|
|
15
|
+
value: string;
|
|
16
|
+
mimeType: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: "url";
|
|
19
|
+
value: string;
|
|
20
|
+
mimeType?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Message format expected by TanStack AI's `chat()`.
|
|
25
|
+
*/
|
|
26
|
+
interface TanStackChatMessage {
|
|
27
|
+
role: "user" | "assistant" | "tool";
|
|
28
|
+
content: string | null | TanStackContentPart[];
|
|
29
|
+
name?: string;
|
|
30
|
+
toolCalls?: Array<{
|
|
31
|
+
id: string;
|
|
32
|
+
type: "function";
|
|
33
|
+
function: {
|
|
34
|
+
name: string;
|
|
35
|
+
arguments: string;
|
|
36
|
+
};
|
|
37
|
+
}>;
|
|
38
|
+
toolCallId?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Result of converting RunAgentInput to TanStack AI format.
|
|
42
|
+
*/
|
|
43
|
+
interface TanStackInputResult {
|
|
44
|
+
/** Chat messages (only user/assistant/tool roles; all others excluded) */
|
|
45
|
+
messages: TanStackChatMessage[];
|
|
46
|
+
/** System prompts extracted from system/developer messages, context, and state */
|
|
47
|
+
systemPrompts: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Converts a RunAgentInput into the format expected by TanStack AI's `chat()`.
|
|
51
|
+
*
|
|
52
|
+
* - Keeps only user/assistant/tool messages (activity, reasoning, and other roles are also excluded)
|
|
53
|
+
* - Extracts system/developer messages into `systemPrompts`
|
|
54
|
+
* - Appends context entries and application state to `systemPrompts`
|
|
55
|
+
* - Preserves tool calls on assistant messages and toolCallId on tool messages
|
|
56
|
+
*/
|
|
57
|
+
declare function convertInputToTanStackAI(input: RunAgentInput): TanStackInputResult;
|
|
58
|
+
/**
|
|
59
|
+
* Converts a TanStack AI stream into AG-UI `BaseEvent` objects.
|
|
60
|
+
*
|
|
61
|
+
* This is a pure converter — it does NOT emit lifecycle events
|
|
62
|
+
* (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class)
|
|
63
|
+
* is responsible for those.
|
|
64
|
+
*/
|
|
65
|
+
declare function convertTanStackStream(stream: AsyncIterable<unknown>, abortSignal: AbortSignal): AsyncGenerator<BaseEvent>;
|
|
66
|
+
//#endregion
|
|
67
|
+
export { TanStackChatMessage, TanStackInputResult, convertInputToTanStackAI, convertTanStackStream };
|
|
68
|
+
//# sourceMappingURL=tanstack.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.d.cts","names":[],"sources":["../../../src/agent/converters/tanstack.ts"],"mappings":";;;;;;AAgBA;KAAY,mBAAA;EACN,IAAA;EAAc,OAAA;AAAA;EAEd,IAAA;EACA,MAAA;IACM,IAAA;IAAc,KAAA;IAAe,QAAA;EAAA;IAC7B,IAAA;IAAa,KAAA;IAAe,QAAA;EAAA;AAAA;AAMxC;;;AAAA,UAAiB,mBAAA;EACf,IAAA;EACA,OAAA,kBAAyB,mBAAA;EACzB,IAAA;EACA,SAAA,GAAY,KAAA;IACV,EAAA;IACA,IAAA;IACA,QAAA;MAAY,IAAA;MAAc,SAAA;IAAA;EAAA;EAE5B,UAAA;AAAA;;AAMF;;UAAiB,mBAAA;EAEc;EAA7B,QAAA,EAAU,mBAAA;EAAA;EAEV,aAAA;AAAA;;AAoGF;;;;;;;iBAAgB,wBAAA,CACd,KAAA,EAAO,aAAA,GACN,mBAAA;;AAqEH;;;;;;iBAAuB,qBAAA,CACrB,MAAA,EAAQ,aAAA,WACR,WAAA,EAAa,WAAA,GACZ,cAAA,CAAe,SAAA"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { BaseEvent, RunAgentInput } from "@ag-ui/client";
|
|
3
|
+
|
|
4
|
+
//#region src/agent/converters/tanstack.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* A TanStack AI content part (text, image, audio, video, or document).
|
|
7
|
+
*/
|
|
8
|
+
type TanStackContentPart = {
|
|
9
|
+
type: "text";
|
|
10
|
+
content: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: "image" | "audio" | "video" | "document";
|
|
13
|
+
source: {
|
|
14
|
+
type: "data";
|
|
15
|
+
value: string;
|
|
16
|
+
mimeType: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: "url";
|
|
19
|
+
value: string;
|
|
20
|
+
mimeType?: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Message format expected by TanStack AI's `chat()`.
|
|
25
|
+
*/
|
|
26
|
+
interface TanStackChatMessage {
|
|
27
|
+
role: "user" | "assistant" | "tool";
|
|
28
|
+
content: string | null | TanStackContentPart[];
|
|
29
|
+
name?: string;
|
|
30
|
+
toolCalls?: Array<{
|
|
31
|
+
id: string;
|
|
32
|
+
type: "function";
|
|
33
|
+
function: {
|
|
34
|
+
name: string;
|
|
35
|
+
arguments: string;
|
|
36
|
+
};
|
|
37
|
+
}>;
|
|
38
|
+
toolCallId?: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Result of converting RunAgentInput to TanStack AI format.
|
|
42
|
+
*/
|
|
43
|
+
interface TanStackInputResult {
|
|
44
|
+
/** Chat messages (only user/assistant/tool roles; all others excluded) */
|
|
45
|
+
messages: TanStackChatMessage[];
|
|
46
|
+
/** System prompts extracted from system/developer messages, context, and state */
|
|
47
|
+
systemPrompts: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Converts a RunAgentInput into the format expected by TanStack AI's `chat()`.
|
|
51
|
+
*
|
|
52
|
+
* - Keeps only user/assistant/tool messages (activity, reasoning, and other roles are also excluded)
|
|
53
|
+
* - Extracts system/developer messages into `systemPrompts`
|
|
54
|
+
* - Appends context entries and application state to `systemPrompts`
|
|
55
|
+
* - Preserves tool calls on assistant messages and toolCallId on tool messages
|
|
56
|
+
*/
|
|
57
|
+
declare function convertInputToTanStackAI(input: RunAgentInput): TanStackInputResult;
|
|
58
|
+
/**
|
|
59
|
+
* Converts a TanStack AI stream into AG-UI `BaseEvent` objects.
|
|
60
|
+
*
|
|
61
|
+
* This is a pure converter — it does NOT emit lifecycle events
|
|
62
|
+
* (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class)
|
|
63
|
+
* is responsible for those.
|
|
64
|
+
*/
|
|
65
|
+
declare function convertTanStackStream(stream: AsyncIterable<unknown>, abortSignal: AbortSignal): AsyncGenerator<BaseEvent>;
|
|
66
|
+
//#endregion
|
|
67
|
+
export { TanStackChatMessage, TanStackInputResult, convertInputToTanStackAI, convertTanStackStream };
|
|
68
|
+
//# sourceMappingURL=tanstack.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.d.mts","names":[],"sources":["../../../src/agent/converters/tanstack.ts"],"mappings":";;;;;;AAgBA;KAAY,mBAAA;EACN,IAAA;EAAc,OAAA;AAAA;EAEd,IAAA;EACA,MAAA;IACM,IAAA;IAAc,KAAA;IAAe,QAAA;EAAA;IAC7B,IAAA;IAAa,KAAA;IAAe,QAAA;EAAA;AAAA;AAMxC;;;AAAA,UAAiB,mBAAA;EACf,IAAA;EACA,OAAA,kBAAyB,mBAAA;EACzB,IAAA;EACA,SAAA,GAAY,KAAA;IACV,EAAA;IACA,IAAA;IACA,QAAA;MAAY,IAAA;MAAc,SAAA;IAAA;EAAA;EAE5B,UAAA;AAAA;;AAMF;;UAAiB,mBAAA;EAEc;EAA7B,QAAA,EAAU,mBAAA;EAAA;EAEV,aAAA;AAAA;;AAoGF;;;;;;;iBAAgB,wBAAA,CACd,KAAA,EAAO,aAAA,GACN,mBAAA;;AAqEH;;;;;;iBAAuB,qBAAA,CACrB,MAAA,EAAQ,aAAA,WACR,WAAA,EAAa,WAAA,GACZ,cAAA,CAAe,SAAA"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { randomUUID } from "@copilotkit/shared";
|
|
3
|
+
import { EventType } from "@ag-ui/client";
|
|
4
|
+
|
|
5
|
+
//#region src/agent/converters/tanstack.ts
|
|
6
|
+
/**
|
|
7
|
+
* Converts AG-UI user message content to TanStack AI format.
|
|
8
|
+
* Handles plain strings, multimodal parts (image/audio/video/document),
|
|
9
|
+
* and legacy BinaryInputContent for backward compatibility.
|
|
10
|
+
*/
|
|
11
|
+
function convertUserContent(content) {
|
|
12
|
+
if (!content) return null;
|
|
13
|
+
if (typeof content === "string") return content;
|
|
14
|
+
if (!Array.isArray(content)) return null;
|
|
15
|
+
if (content.length === 0) return "";
|
|
16
|
+
const parts = [];
|
|
17
|
+
for (const part of content) {
|
|
18
|
+
if (!part || typeof part !== "object" || !("type" in part)) continue;
|
|
19
|
+
switch (part.type) {
|
|
20
|
+
case "text": {
|
|
21
|
+
const text = part.text;
|
|
22
|
+
if (text != null) parts.push({
|
|
23
|
+
type: "text",
|
|
24
|
+
content: text
|
|
25
|
+
});
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case "image":
|
|
29
|
+
case "audio":
|
|
30
|
+
case "video":
|
|
31
|
+
case "document": {
|
|
32
|
+
const source = part.source;
|
|
33
|
+
if (!source) break;
|
|
34
|
+
const partType = part.type;
|
|
35
|
+
if (source.type === "data") parts.push({
|
|
36
|
+
type: partType,
|
|
37
|
+
source: {
|
|
38
|
+
type: "data",
|
|
39
|
+
value: source.value,
|
|
40
|
+
mimeType: source.mimeType
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
else if (source.type === "url") parts.push({
|
|
44
|
+
type: partType,
|
|
45
|
+
source: {
|
|
46
|
+
type: "url",
|
|
47
|
+
value: source.value,
|
|
48
|
+
...source.mimeType ? { mimeType: source.mimeType } : {}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case "binary": {
|
|
54
|
+
const legacy = part;
|
|
55
|
+
const mimeType = legacy.mimeType ?? "application/octet-stream";
|
|
56
|
+
const isImage = mimeType.startsWith("image/");
|
|
57
|
+
if (legacy.data) {
|
|
58
|
+
const partType = isImage ? "image" : "document";
|
|
59
|
+
parts.push({
|
|
60
|
+
type: partType,
|
|
61
|
+
source: {
|
|
62
|
+
type: "data",
|
|
63
|
+
value: legacy.data,
|
|
64
|
+
mimeType
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
} else if (legacy.url) {
|
|
68
|
+
const partType = isImage ? "image" : "document";
|
|
69
|
+
parts.push({
|
|
70
|
+
type: partType,
|
|
71
|
+
source: {
|
|
72
|
+
type: "url",
|
|
73
|
+
value: legacy.url,
|
|
74
|
+
mimeType
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return parts.length > 0 ? parts : "";
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Converts a RunAgentInput into the format expected by TanStack AI's `chat()`.
|
|
86
|
+
*
|
|
87
|
+
* - Keeps only user/assistant/tool messages (activity, reasoning, and other roles are also excluded)
|
|
88
|
+
* - Extracts system/developer messages into `systemPrompts`
|
|
89
|
+
* - Appends context entries and application state to `systemPrompts`
|
|
90
|
+
* - Preserves tool calls on assistant messages and toolCallId on tool messages
|
|
91
|
+
*/
|
|
92
|
+
function convertInputToTanStackAI(input) {
|
|
93
|
+
const chatRoles = new Set([
|
|
94
|
+
"user",
|
|
95
|
+
"assistant",
|
|
96
|
+
"tool"
|
|
97
|
+
]);
|
|
98
|
+
const messages = input.messages.filter((m) => chatRoles.has(m.role)).map((m) => {
|
|
99
|
+
const msg = {
|
|
100
|
+
role: m.role,
|
|
101
|
+
content: m.role === "user" ? convertUserContent(m.content) : typeof m.content === "string" ? m.content : null
|
|
102
|
+
};
|
|
103
|
+
if (m.role === "assistant" && "toolCalls" in m && m.toolCalls) msg.toolCalls = m.toolCalls.map((tc) => ({
|
|
104
|
+
id: tc.id,
|
|
105
|
+
type: "function",
|
|
106
|
+
function: {
|
|
107
|
+
name: tc.function.name,
|
|
108
|
+
arguments: tc.function.arguments
|
|
109
|
+
}
|
|
110
|
+
}));
|
|
111
|
+
if (m.role === "tool" && "toolCallId" in m) msg.toolCallId = m.toolCallId;
|
|
112
|
+
return msg;
|
|
113
|
+
});
|
|
114
|
+
const systemPrompts = [];
|
|
115
|
+
for (const m of input.messages) if ((m.role === "system" || m.role === "developer") && m.content) systemPrompts.push(typeof m.content === "string" ? m.content : JSON.stringify(m.content));
|
|
116
|
+
if (input.context?.length) for (const ctx of input.context) systemPrompts.push(`${ctx.description}:\n${ctx.value}`);
|
|
117
|
+
if (input.state !== void 0 && input.state !== null && typeof input.state === "object" && Object.keys(input.state).length > 0) systemPrompts.push(`Application State:\n\`\`\`json\n${JSON.stringify(input.state, null, 2)}\n\`\`\``);
|
|
118
|
+
return {
|
|
119
|
+
messages,
|
|
120
|
+
systemPrompts
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Converts a TanStack AI stream into AG-UI `BaseEvent` objects.
|
|
125
|
+
*
|
|
126
|
+
* This is a pure converter — it does NOT emit lifecycle events
|
|
127
|
+
* (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class)
|
|
128
|
+
* is responsible for those.
|
|
129
|
+
*/
|
|
130
|
+
async function* convertTanStackStream(stream, abortSignal) {
|
|
131
|
+
const messageId = randomUUID();
|
|
132
|
+
for await (const chunk of stream) {
|
|
133
|
+
if (abortSignal.aborted) break;
|
|
134
|
+
const raw = chunk;
|
|
135
|
+
const type = raw.type;
|
|
136
|
+
if (type === "TEXT_MESSAGE_CONTENT" && raw.delta) yield {
|
|
137
|
+
type: EventType.TEXT_MESSAGE_CHUNK,
|
|
138
|
+
role: "assistant",
|
|
139
|
+
messageId,
|
|
140
|
+
delta: raw.delta
|
|
141
|
+
};
|
|
142
|
+
else if (type === "TOOL_CALL_START") yield {
|
|
143
|
+
type: EventType.TOOL_CALL_START,
|
|
144
|
+
parentMessageId: messageId,
|
|
145
|
+
toolCallId: raw.toolCallId,
|
|
146
|
+
toolCallName: raw.toolCallName
|
|
147
|
+
};
|
|
148
|
+
else if (type === "TOOL_CALL_ARGS") yield {
|
|
149
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
150
|
+
toolCallId: raw.toolCallId,
|
|
151
|
+
delta: raw.delta
|
|
152
|
+
};
|
|
153
|
+
else if (type === "TOOL_CALL_END") yield {
|
|
154
|
+
type: EventType.TOOL_CALL_END,
|
|
155
|
+
toolCallId: raw.toolCallId
|
|
156
|
+
};
|
|
157
|
+
else if (type === "TOOL_CALL_RESULT") {
|
|
158
|
+
let serializedContent;
|
|
159
|
+
if (typeof raw.content === "string") serializedContent = raw.content;
|
|
160
|
+
else try {
|
|
161
|
+
serializedContent = JSON.stringify(raw.content ?? raw.result ?? null);
|
|
162
|
+
} catch {
|
|
163
|
+
serializedContent = "[Unserializable tool result]";
|
|
164
|
+
}
|
|
165
|
+
yield {
|
|
166
|
+
type: EventType.TOOL_CALL_RESULT,
|
|
167
|
+
role: "tool",
|
|
168
|
+
messageId: randomUUID(),
|
|
169
|
+
toolCallId: raw.toolCallId,
|
|
170
|
+
content: serializedContent
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
//#endregion
|
|
177
|
+
export { convertInputToTanStackAI, convertTanStackStream };
|
|
178
|
+
//# sourceMappingURL=tanstack.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.mjs","names":[],"sources":["../../../src/agent/converters/tanstack.ts"],"sourcesContent":["import {\n BaseEvent,\n EventType,\n RunAgentInput,\n Message,\n TextMessageChunkEvent,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallStartEvent,\n ToolCallResultEvent,\n} from \"@ag-ui/client\";\nimport { randomUUID } from \"@copilotkit/shared\";\n\n/**\n * A TanStack AI content part (text, image, audio, video, or document).\n */\nexport type TanStackContentPart =\n | { type: \"text\"; content: string }\n | {\n type: \"image\" | \"audio\" | \"video\" | \"document\";\n source:\n | { type: \"data\"; value: string; mimeType: string }\n | { type: \"url\"; value: string; mimeType?: string };\n };\n\n/**\n * Message format expected by TanStack AI's `chat()`.\n */\nexport interface TanStackChatMessage {\n role: \"user\" | \"assistant\" | \"tool\";\n content: string | null | TanStackContentPart[];\n name?: string;\n toolCalls?: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }>;\n toolCallId?: string;\n}\n\n/**\n * Result of converting RunAgentInput to TanStack AI format.\n */\nexport interface TanStackInputResult {\n /** Chat messages (only user/assistant/tool roles; all others excluded) */\n messages: TanStackChatMessage[];\n /** System prompts extracted from system/developer messages, context, and state */\n systemPrompts: string[];\n}\n\n/**\n * Converts AG-UI user message content to TanStack AI format.\n * Handles plain strings, multimodal parts (image/audio/video/document),\n * and legacy BinaryInputContent for backward compatibility.\n */\nfunction convertUserContent(\n content: unknown,\n): string | null | TanStackContentPart[] {\n if (!content) return null;\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return null;\n if (content.length === 0) return \"\";\n\n const parts: TanStackContentPart[] = [];\n\n for (const part of content) {\n if (!part || typeof part !== \"object\" || !(\"type\" in part)) continue;\n\n switch ((part as { type: string }).type) {\n case \"text\": {\n const text = (part as { text?: string }).text;\n if (text != null) parts.push({ type: \"text\", content: text });\n break;\n }\n\n case \"image\":\n case \"audio\":\n case \"video\":\n case \"document\": {\n const source = (part as { source?: any }).source;\n if (!source) break;\n const partType = (part as { type: string }).type as\n | \"image\"\n | \"audio\"\n | \"video\"\n | \"document\";\n if (source.type === \"data\") {\n parts.push({\n type: partType,\n source: {\n type: \"data\",\n value: source.value,\n mimeType: source.mimeType,\n },\n });\n } else if (source.type === \"url\") {\n parts.push({\n type: partType,\n source: {\n type: \"url\",\n value: source.value,\n ...(source.mimeType ? { mimeType: source.mimeType } : {}),\n },\n });\n }\n break;\n }\n\n // Legacy BinaryInputContent backward compatibility\n case \"binary\": {\n const legacy = part as {\n mimeType?: string;\n data?: string;\n url?: string;\n };\n const mimeType = legacy.mimeType ?? \"application/octet-stream\";\n const isImage = mimeType.startsWith(\"image/\");\n\n if (legacy.data) {\n const partType = isImage ? \"image\" : \"document\";\n parts.push({\n type: partType,\n source: { type: \"data\", value: legacy.data, mimeType },\n });\n } else if (legacy.url) {\n const partType = isImage ? \"image\" : \"document\";\n parts.push({\n type: partType,\n source: { type: \"url\", value: legacy.url, mimeType },\n });\n }\n break;\n }\n }\n }\n\n return parts.length > 0 ? parts : \"\";\n}\n\n/**\n * Converts a RunAgentInput into the format expected by TanStack AI's `chat()`.\n *\n * - Keeps only user/assistant/tool messages (activity, reasoning, and other roles are also excluded)\n * - Extracts system/developer messages into `systemPrompts`\n * - Appends context entries and application state to `systemPrompts`\n * - Preserves tool calls on assistant messages and toolCallId on tool messages\n */\nexport function convertInputToTanStackAI(\n input: RunAgentInput,\n): TanStackInputResult {\n // Allowlist: only pass user/assistant/tool messages to TanStack.\n // Other roles (system, developer, activity, reasoning) are either\n // extracted into systemPrompts or not applicable.\n const chatRoles = new Set([\"user\", \"assistant\", \"tool\"]);\n const messages: TanStackChatMessage[] = input.messages\n .filter((m: Message) => chatRoles.has(m.role))\n .map((m: Message): TanStackChatMessage => {\n const msg: TanStackChatMessage = {\n role: m.role as \"user\" | \"assistant\" | \"tool\",\n content:\n m.role === \"user\"\n ? convertUserContent(m.content)\n : typeof m.content === \"string\"\n ? m.content\n : null,\n };\n if (m.role === \"assistant\" && \"toolCalls\" in m && m.toolCalls) {\n msg.toolCalls = m.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\" as const,\n function: {\n name: tc.function.name,\n arguments: tc.function.arguments,\n },\n }));\n }\n if (m.role === \"tool\" && \"toolCallId\" in m) {\n msg.toolCallId = (m as Record<string, unknown>).toolCallId as string;\n }\n return msg;\n });\n\n const systemPrompts: string[] = [];\n for (const m of input.messages) {\n if ((m.role === \"system\" || m.role === \"developer\") && m.content) {\n systemPrompts.push(\n typeof m.content === \"string\" ? m.content : JSON.stringify(m.content),\n );\n }\n }\n\n if (input.context?.length) {\n for (const ctx of input.context) {\n systemPrompts.push(`${ctx.description}:\\n${ctx.value}`);\n }\n }\n\n if (\n input.state !== undefined &&\n input.state !== null &&\n typeof input.state === \"object\" &&\n Object.keys(input.state).length > 0\n ) {\n systemPrompts.push(\n `Application State:\\n\\`\\`\\`json\\n${JSON.stringify(input.state, null, 2)}\\n\\`\\`\\``,\n );\n }\n\n return { messages, systemPrompts };\n}\n\n/**\n * Converts a TanStack AI stream into AG-UI `BaseEvent` objects.\n *\n * This is a pure converter — it does NOT emit lifecycle events\n * (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class)\n * is responsible for those.\n */\nexport async function* convertTanStackStream(\n stream: AsyncIterable<unknown>,\n abortSignal: AbortSignal,\n): AsyncGenerator<BaseEvent> {\n const messageId = randomUUID();\n\n for await (const chunk of stream) {\n if (abortSignal.aborted) break;\n\n const raw = chunk as Record<string, unknown>;\n const type = raw.type as string;\n\n if (type === \"TEXT_MESSAGE_CONTENT\" && raw.delta) {\n const textEvent: TextMessageChunkEvent = {\n type: EventType.TEXT_MESSAGE_CHUNK,\n role: \"assistant\",\n messageId,\n delta: raw.delta as string,\n };\n yield textEvent;\n } else if (type === \"TOOL_CALL_START\") {\n const startEvent: ToolCallStartEvent = {\n type: EventType.TOOL_CALL_START,\n parentMessageId: messageId,\n toolCallId: raw.toolCallId as string,\n toolCallName: raw.toolCallName as string,\n };\n yield startEvent;\n } else if (type === \"TOOL_CALL_ARGS\") {\n const argsEvent: ToolCallArgsEvent = {\n type: EventType.TOOL_CALL_ARGS,\n toolCallId: raw.toolCallId as string,\n delta: raw.delta as string,\n };\n yield argsEvent;\n } else if (type === \"TOOL_CALL_END\") {\n const endEvent: ToolCallEndEvent = {\n type: EventType.TOOL_CALL_END,\n toolCallId: raw.toolCallId as string,\n };\n yield endEvent;\n } else if (type === \"TOOL_CALL_RESULT\") {\n let serializedContent: string;\n if (typeof raw.content === \"string\") {\n serializedContent = raw.content;\n } else {\n try {\n serializedContent = JSON.stringify(raw.content ?? raw.result ?? null);\n } catch {\n serializedContent = \"[Unserializable tool result]\";\n }\n }\n const resultEvent: ToolCallResultEvent = {\n type: EventType.TOOL_CALL_RESULT,\n role: \"tool\",\n messageId: randomUUID(),\n toolCallId: raw.toolCallId as string,\n content: serializedContent,\n };\n yield resultEvent;\n }\n // Unhandled chunk types are silently ignored.\n // Known gaps: STATE_SNAPSHOT, STATE_DELTA, and REASONING events are not\n // converted from TanStack streams. Shared state and reasoning will not\n // surface when using the TanStack backend. Use the AI SDK backend if these\n // features are required.\n }\n}\n"],"mappings":";;;;;;;;;;AAuDA,SAAS,mBACP,SACuC;AACvC,KAAI,CAAC,QAAS,QAAO;AACrB,KAAI,OAAO,YAAY,SAAU,QAAO;AACxC,KAAI,CAAC,MAAM,QAAQ,QAAQ,CAAE,QAAO;AACpC,KAAI,QAAQ,WAAW,EAAG,QAAO;CAEjC,MAAM,QAA+B,EAAE;AAEvC,MAAK,MAAM,QAAQ,SAAS;AAC1B,MAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,EAAE,UAAU,MAAO;AAE5D,UAAS,KAA0B,MAAnC;GACE,KAAK,QAAQ;IACX,MAAM,OAAQ,KAA2B;AACzC,QAAI,QAAQ,KAAM,OAAM,KAAK;KAAE,MAAM;KAAQ,SAAS;KAAM,CAAC;AAC7D;;GAGF,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,YAAY;IACf,MAAM,SAAU,KAA0B;AAC1C,QAAI,CAAC,OAAQ;IACb,MAAM,WAAY,KAA0B;AAK5C,QAAI,OAAO,SAAS,OAClB,OAAM,KAAK;KACT,MAAM;KACN,QAAQ;MACN,MAAM;MACN,OAAO,OAAO;MACd,UAAU,OAAO;MAClB;KACF,CAAC;aACO,OAAO,SAAS,MACzB,OAAM,KAAK;KACT,MAAM;KACN,QAAQ;MACN,MAAM;MACN,OAAO,OAAO;MACd,GAAI,OAAO,WAAW,EAAE,UAAU,OAAO,UAAU,GAAG,EAAE;MACzD;KACF,CAAC;AAEJ;;GAIF,KAAK,UAAU;IACb,MAAM,SAAS;IAKf,MAAM,WAAW,OAAO,YAAY;IACpC,MAAM,UAAU,SAAS,WAAW,SAAS;AAE7C,QAAI,OAAO,MAAM;KACf,MAAM,WAAW,UAAU,UAAU;AACrC,WAAM,KAAK;MACT,MAAM;MACN,QAAQ;OAAE,MAAM;OAAQ,OAAO,OAAO;OAAM;OAAU;MACvD,CAAC;eACO,OAAO,KAAK;KACrB,MAAM,WAAW,UAAU,UAAU;AACrC,WAAM,KAAK;MACT,MAAM;MACN,QAAQ;OAAE,MAAM;OAAO,OAAO,OAAO;OAAK;OAAU;MACrD,CAAC;;AAEJ;;;;AAKN,QAAO,MAAM,SAAS,IAAI,QAAQ;;;;;;;;;;AAWpC,SAAgB,yBACd,OACqB;CAIrB,MAAM,YAAY,IAAI,IAAI;EAAC;EAAQ;EAAa;EAAO,CAAC;CACxD,MAAM,WAAkC,MAAM,SAC3C,QAAQ,MAAe,UAAU,IAAI,EAAE,KAAK,CAAC,CAC7C,KAAK,MAAoC;EACxC,MAAM,MAA2B;GAC/B,MAAM,EAAE;GACR,SACE,EAAE,SAAS,SACP,mBAAmB,EAAE,QAAQ,GAC7B,OAAO,EAAE,YAAY,WACnB,EAAE,UACF;GACT;AACD,MAAI,EAAE,SAAS,eAAe,eAAe,KAAK,EAAE,UAClD,KAAI,YAAY,EAAE,UAAU,KAAK,QAAQ;GACvC,IAAI,GAAG;GACP,MAAM;GACN,UAAU;IACR,MAAM,GAAG,SAAS;IAClB,WAAW,GAAG,SAAS;IACxB;GACF,EAAE;AAEL,MAAI,EAAE,SAAS,UAAU,gBAAgB,EACvC,KAAI,aAAc,EAA8B;AAElD,SAAO;GACP;CAEJ,MAAM,gBAA0B,EAAE;AAClC,MAAK,MAAM,KAAK,MAAM,SACpB,MAAK,EAAE,SAAS,YAAY,EAAE,SAAS,gBAAgB,EAAE,QACvD,eAAc,KACZ,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,KAAK,UAAU,EAAE,QAAQ,CACtE;AAIL,KAAI,MAAM,SAAS,OACjB,MAAK,MAAM,OAAO,MAAM,QACtB,eAAc,KAAK,GAAG,IAAI,YAAY,KAAK,IAAI,QAAQ;AAI3D,KACE,MAAM,UAAU,UAChB,MAAM,UAAU,QAChB,OAAO,MAAM,UAAU,YACvB,OAAO,KAAK,MAAM,MAAM,CAAC,SAAS,EAElC,eAAc,KACZ,mCAAmC,KAAK,UAAU,MAAM,OAAO,MAAM,EAAE,CAAC,UACzE;AAGH,QAAO;EAAE;EAAU;EAAe;;;;;;;;;AAUpC,gBAAuB,sBACrB,QACA,aAC2B;CAC3B,MAAM,YAAY,YAAY;AAE9B,YAAW,MAAM,SAAS,QAAQ;AAChC,MAAI,YAAY,QAAS;EAEzB,MAAM,MAAM;EACZ,MAAM,OAAO,IAAI;AAEjB,MAAI,SAAS,0BAA0B,IAAI,MAOzC,OANyC;GACvC,MAAM,UAAU;GAChB,MAAM;GACN;GACA,OAAO,IAAI;GACZ;WAEQ,SAAS,kBAOlB,OANuC;GACrC,MAAM,UAAU;GAChB,iBAAiB;GACjB,YAAY,IAAI;GAChB,cAAc,IAAI;GACnB;WAEQ,SAAS,iBAMlB,OALqC;GACnC,MAAM,UAAU;GAChB,YAAY,IAAI;GAChB,OAAO,IAAI;GACZ;WAEQ,SAAS,gBAKlB,OAJmC;GACjC,MAAM,UAAU;GAChB,YAAY,IAAI;GACjB;WAEQ,SAAS,oBAAoB;GACtC,IAAI;AACJ,OAAI,OAAO,IAAI,YAAY,SACzB,qBAAoB,IAAI;OAExB,KAAI;AACF,wBAAoB,KAAK,UAAU,IAAI,WAAW,IAAI,UAAU,KAAK;WAC/D;AACN,wBAAoB;;AAUxB,SAPyC;IACvC,MAAM,UAAU;IAChB,MAAM;IACN,WAAW,YAAY;IACvB,YAAY,IAAI;IAChB,SAAS;IACV"}
|