UNPKG

@tanstack/ai

Version:

Core TanStack AI library - Open source AI SDK

234 lines (233 loc) 6.88 kB
function isContentPart(part) { return part.type === "text" || part.type === "image" || part.type === "audio" || part.type === "video" || part.type === "document"; } function collapseContentParts(parts) { if (parts.length === 0) return null; const allText = parts.every((p) => p.type === "text"); if (allText) { const joined = parts.map((p) => p.content).join(""); return joined || null; } return parts; } function getTextContent(content) { if (content === null) return ""; if (typeof content === "string") return content; return content.filter((part) => part.type === "text").map((part) => part.content).join(""); } function convertMessagesToModelMessages(messages) { const modelMessages = []; for (const msg of messages) { if ("parts" in msg) { modelMessages.push(...uiMessageToModelMessages(msg)); } else { modelMessages.push(msg); } } return modelMessages; } function uiMessageToModelMessages(uiMessage) { if (uiMessage.role === "system") { return []; } if (uiMessage.role !== "assistant") { return [buildUserOrToolMessage(uiMessage)]; } return buildAssistantMessages(uiMessage); } function buildUserOrToolMessage(uiMessage) { const contentParts = []; for (const part of uiMessage.parts) { if (isContentPart(part)) { contentParts.push(part); } } return { role: uiMessage.role, content: collapseContentParts(contentParts) }; } function createSegment() { return { contentParts: [], toolCalls: [] }; } function isToolCallIncluded(part) { return part.state === "input-complete" || part.state === "approval-responded" || part.output !== void 0; } function buildAssistantMessages(uiMessage) { const messageList = []; let current = createSegment(); const emittedToolResultIds = /* @__PURE__ */ new Set(); function flushSegment() { const content = collapseContentParts(current.contentParts); const hasContent = content !== null; const hasToolCalls = current.toolCalls.length > 0; if (hasContent || hasToolCalls) { messageList.push({ role: "assistant", content, ...hasToolCalls && { toolCalls: current.toolCalls } }); } current = createSegment(); } for (const part of uiMessage.parts) { switch (part.type) { case "text": case "image": case "audio": case "video": case "document": current.contentParts.push(part); break; case "tool-call": if (isToolCallIncluded(part)) { current.toolCalls.push({ id: part.id, type: "function", function: { name: part.name, arguments: part.arguments } }); } break; case "tool-result": flushSegment(); if ((part.state === "complete" || part.state === "error") && !emittedToolResultIds.has(part.toolCallId)) { messageList.push({ role: "tool", content: part.content, toolCallId: part.toolCallId }); emittedToolResultIds.add(part.toolCallId); } break; } } flushSegment(); for (const part of uiMessage.parts) { if (part.type !== "tool-call") continue; if (part.output !== void 0 && !emittedToolResultIds.has(part.id)) { messageList.push({ role: "tool", content: JSON.stringify(part.output), toolCallId: part.id }); emittedToolResultIds.add(part.id); } if (part.output === void 0 && part.state === "approval-responded" && part.approval?.approved !== void 0 && !emittedToolResultIds.has(part.id)) { const approved = part.approval.approved; messageList.push({ role: "tool", content: JSON.stringify({ approved, ...approved && { pendingExecution: true }, message: approved ? "User approved this action" : "User denied this action" }), toolCallId: part.id }); emittedToolResultIds.add(part.id); } } if (messageList.length === 0) { messageList.push({ role: "assistant", content: null }); } return messageList; } function modelMessageToUIMessage(modelMessage, id) { const parts = []; if (modelMessage.role === "tool" && modelMessage.toolCallId) { parts.push({ type: "tool-result", toolCallId: modelMessage.toolCallId, content: getTextContent(modelMessage.content), state: "complete" }); } else if (Array.isArray(modelMessage.content)) { for (const part of modelMessage.content) { parts.push(part); } } else { const textContent = getTextContent(modelMessage.content); if (textContent) { parts.push({ type: "text", content: textContent }); } } if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) { for (const toolCall of modelMessage.toolCalls) { parts.push({ type: "tool-call", id: toolCall.id, name: toolCall.function.name, arguments: toolCall.function.arguments, state: "input-complete" // Model messages have complete arguments }); } } return { id: id || generateMessageId(), role: modelMessage.role === "tool" ? "assistant" : modelMessage.role, parts }; } function modelMessagesToUIMessages(modelMessages) { const uiMessages = []; let currentAssistantMessage = null; for (const msg of modelMessages) { if (msg.role === "tool") { if (currentAssistantMessage && currentAssistantMessage.role === "assistant") { currentAssistantMessage.parts.push({ type: "tool-result", toolCallId: msg.toolCallId, content: getTextContent(msg.content), state: "complete" }); } else { const toolResultUIMessage = modelMessageToUIMessage(msg); uiMessages.push(toolResultUIMessage); } } else { const uiMessage = modelMessageToUIMessage(msg); uiMessages.push(uiMessage); if (msg.role === "assistant") { currentAssistantMessage = uiMessage; } else { currentAssistantMessage = null; } } } return uiMessages; } function normalizeToUIMessage(message, generateId) { if ("parts" in message) { return { ...message, id: message.id || generateId(), createdAt: message.createdAt || /* @__PURE__ */ new Date() }; } else { return { ...modelMessageToUIMessage(message, generateId()), createdAt: /* @__PURE__ */ new Date() }; } } function generateMessageId() { return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`; } export { convertMessagesToModelMessages, generateMessageId, modelMessageToUIMessage, modelMessagesToUIMessages, normalizeToUIMessage, uiMessageToModelMessages }; //# sourceMappingURL=messages.js.map