UNPKG

@copilotkit/runtime

Version:

<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />

276 lines (274 loc) 8.64 kB
require("reflect-metadata"); const require_runtime = require('../../_virtual/_rolldown/runtime.cjs'); let _copilotkit_shared = require("@copilotkit/shared"); let _ag_ui_client = require("@ag-ui/client"); //#region src/agent/converters/tanstack.ts /** * Converts AG-UI user message content to TanStack AI format. * Handles plain strings, multimodal parts (image/audio/video/document), * and legacy BinaryInputContent for backward compatibility. */ function convertUserContent(content) { if (!content) return null; if (typeof content === "string") return content; if (!Array.isArray(content)) return null; if (content.length === 0) return ""; const parts = []; for (const part of content) { if (!part || typeof part !== "object" || !("type" in part)) continue; switch (part.type) { case "text": { const text = part.text; if (text != null) parts.push({ type: "text", content: text }); break; } case "image": case "audio": case "video": case "document": { const source = part.source; if (!source) break; const partType = part.type; if (source.type === "data") parts.push({ type: partType, source: { type: "data", value: source.value, mimeType: source.mimeType } }); else if (source.type === "url") parts.push({ type: partType, source: { type: "url", value: source.value, ...source.mimeType ? { mimeType: source.mimeType } : {} } }); break; } case "binary": { const legacy = part; const mimeType = legacy.mimeType ?? "application/octet-stream"; const isImage = mimeType.startsWith("image/"); if (legacy.data) { const partType = isImage ? "image" : "document"; parts.push({ type: partType, source: { type: "data", value: legacy.data, mimeType } }); } else if (legacy.url) { const partType = isImage ? "image" : "document"; parts.push({ type: partType, source: { type: "url", value: legacy.url, mimeType } }); } break; } } } return parts.length > 0 ? parts : ""; } /** * Converts a RunAgentInput into the format expected by TanStack AI's `chat()`. * * - Keeps only user/assistant/tool messages (activity, reasoning, and other roles are also excluded) * - Extracts system/developer messages into `systemPrompts` * - Appends context entries and application state to `systemPrompts` * - Preserves tool calls on assistant messages and toolCallId on tool messages */ function convertInputToTanStackAI(input) { const chatRoles = new Set([ "user", "assistant", "tool" ]); const messages = input.messages.filter((m) => chatRoles.has(m.role)).map((m) => { const msg = { role: m.role, content: m.role === "user" ? convertUserContent(m.content) : typeof m.content === "string" ? m.content : null }; if (m.role === "assistant" && "toolCalls" in m && m.toolCalls) msg.toolCalls = m.toolCalls.map((tc) => ({ id: tc.id, type: "function", function: { name: tc.function.name, arguments: tc.function.arguments } })); if (m.role === "tool" && "toolCallId" in m) msg.toolCallId = m.toolCallId; return msg; }); const systemPrompts = []; 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)); if (input.context?.length) for (const ctx of input.context) systemPrompts.push(`${ctx.description}:\n${ctx.value}`); 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\`\`\``); return { messages, systemPrompts }; } /** * Converts a TanStack AI stream into AG-UI `BaseEvent` objects. * * This is a pure converter — it does NOT emit lifecycle events * (RUN_STARTED / RUN_FINISHED / RUN_ERROR). The caller (Agent class) * is responsible for those. */ async function* convertTanStackStream(stream, abortSignal) { const messageId = (0, _copilotkit_shared.randomUUID)(); const toolNamesById = /* @__PURE__ */ new Map(); let reasoningRunOpen = false; let reasoningMessageOpen = false; let reasoningMessageId = (0, _copilotkit_shared.randomUUID)(); function* closeReasoningIfOpen() { if (reasoningMessageOpen) { reasoningMessageOpen = false; yield { type: _ag_ui_client.EventType.REASONING_MESSAGE_END, messageId: reasoningMessageId }; } if (reasoningRunOpen) { reasoningRunOpen = false; yield { type: _ag_ui_client.EventType.REASONING_END, messageId: reasoningMessageId }; } } let runFinished = false; for await (const chunk of stream) { if (abortSignal.aborted) break; const raw = chunk; const type = raw.type; if (type === "RUN_FINISHED") { runFinished = true; continue; } if (runFinished) continue; if (type === "TEXT_MESSAGE_CONTENT" && raw.delta != null) { yield* closeReasoningIfOpen(); yield { type: _ag_ui_client.EventType.TEXT_MESSAGE_CHUNK, role: "assistant", messageId, delta: raw.delta }; } else if (type === "TOOL_CALL_START") { yield* closeReasoningIfOpen(); toolNamesById.set(raw.toolCallId, raw.toolCallName); yield { type: _ag_ui_client.EventType.TOOL_CALL_START, parentMessageId: messageId, toolCallId: raw.toolCallId, toolCallName: raw.toolCallName }; } else if (type === "TOOL_CALL_ARGS") { yield* closeReasoningIfOpen(); yield { type: _ag_ui_client.EventType.TOOL_CALL_ARGS, toolCallId: raw.toolCallId, delta: raw.delta }; } else if (type === "TOOL_CALL_END") { yield* closeReasoningIfOpen(); yield { type: _ag_ui_client.EventType.TOOL_CALL_END, toolCallId: raw.toolCallId }; } else if (type === "TOOL_CALL_RESULT") { yield* closeReasoningIfOpen(); const toolCallId = raw.toolCallId; const toolName = toolNamesById.get(toolCallId); const rawPayload = raw.content ?? raw.result; const parsedContent = typeof rawPayload === "string" ? safeParse(rawPayload) : rawPayload; if (toolName === "AGUISendStateSnapshot" && parsedContent && typeof parsedContent === "object" && "snapshot" in parsedContent) yield { type: _ag_ui_client.EventType.STATE_SNAPSHOT, snapshot: parsedContent.snapshot }; if (toolName === "AGUISendStateDelta" && parsedContent && typeof parsedContent === "object" && "delta" in parsedContent) yield { type: _ag_ui_client.EventType.STATE_DELTA, delta: parsedContent.delta }; let serializedContent; if (typeof rawPayload === "string") serializedContent = rawPayload; else try { serializedContent = JSON.stringify(rawPayload ?? null); } catch { serializedContent = "[Unserializable tool result]"; } yield { type: _ag_ui_client.EventType.TOOL_CALL_RESULT, role: "tool", messageId: (0, _copilotkit_shared.randomUUID)(), toolCallId, content: serializedContent }; toolNamesById.delete(toolCallId); } else if (type === "REASONING_START") { yield* closeReasoningIfOpen(); reasoningRunOpen = true; reasoningMessageId = raw.messageId ?? (0, _copilotkit_shared.randomUUID)(); yield { type: _ag_ui_client.EventType.REASONING_START, messageId: reasoningMessageId }; } else if (type === "REASONING_MESSAGE_START") { reasoningMessageOpen = true; yield { type: _ag_ui_client.EventType.REASONING_MESSAGE_START, messageId: reasoningMessageId, role: "reasoning" }; } else if (type === "REASONING_MESSAGE_CONTENT") yield { type: _ag_ui_client.EventType.REASONING_MESSAGE_CONTENT, messageId: reasoningMessageId, delta: raw.delta }; else if (type === "REASONING_MESSAGE_END") { reasoningMessageOpen = false; yield { type: _ag_ui_client.EventType.REASONING_MESSAGE_END, messageId: reasoningMessageId }; } else if (type === "REASONING_END") { if (reasoningMessageOpen) { reasoningMessageOpen = false; yield { type: _ag_ui_client.EventType.REASONING_MESSAGE_END, messageId: reasoningMessageId }; } reasoningRunOpen = false; yield { type: _ag_ui_client.EventType.REASONING_END, messageId: reasoningMessageId }; } } yield* closeReasoningIfOpen(); } function safeParse(value) { try { return JSON.parse(value); } catch { return value; } } //#endregion exports.convertInputToTanStackAI = convertInputToTanStackAI; exports.convertTanStackStream = convertTanStackStream; //# sourceMappingURL=tanstack.cjs.map