UNPKG

@tanstack/ai

Version:

Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.

254 lines (253 loc) 7.31 kB
import { parsePartialJSON } from "./json-parser.js"; function updateTextPart(messages, messageId, content) { return messages.map((msg) => { if (msg.id !== messageId) { return msg; } const parts = [...msg.parts]; const lastPart = parts.length > 0 ? parts[parts.length - 1] : null; if (lastPart && lastPart.type === "text") { parts[parts.length - 1] = { type: "text", content }; } else { parts.push({ type: "text", content }); } return { ...msg, parts }; }); } function updateToolCallPart(messages, messageId, toolCall) { return messages.map((msg) => { if (msg.id !== messageId) { return msg; } const parts = [...msg.parts]; const existing = parts.find( (p) => p.type === "tool-call" && p.id === toolCall.id ); const metadata = toolCall.metadata ?? existing?.metadata; const toolCallPart = { type: "tool-call", id: toolCall.id, name: toolCall.name, arguments: toolCall.arguments, state: toolCall.state, // Carry forward approval and output from the existing part ...existing?.approval && { approval: { ...existing.approval } }, ...existing?.output !== void 0 && { output: existing.output }, ...metadata !== void 0 && { metadata } }; if (existing) { parts[parts.indexOf(existing)] = toolCallPart; } else { parts.push(toolCallPart); } return { ...msg, parts }; }); } function updateToolResultPart(messages, messageId, toolCallId, content, state, error) { return messages.map((msg) => { if (msg.id !== messageId) { return msg; } const parts = [...msg.parts]; const resultPartIndex = parts.findIndex( (p) => p.type === "tool-result" && p.toolCallId === toolCallId ); const toolResultPart = { type: "tool-result", toolCallId, content, state, ...error && { error } }; if (resultPartIndex >= 0) { parts[resultPartIndex] = toolResultPart; } else { parts.push(toolResultPart); } return { ...msg, parts }; }); } function updateToolCallApproval(messages, messageId, toolCallId, approvalId) { return messages.map((msg) => { if (msg.id !== messageId) { return msg; } const parts = [...msg.parts]; const toolCallPart = parts.find( (p) => p.type === "tool-call" && p.id === toolCallId ); if (toolCallPart) { const index = parts.indexOf(toolCallPart); parts[index] = { ...toolCallPart, state: "approval-requested", approval: { id: approvalId, needsApproval: true } }; } return { ...msg, parts }; }); } function updateToolCallWithOutput(messages, toolCallId, output, state, errorText) { return messages.map((msg) => { const parts = [...msg.parts]; const toolCallPart = parts.find( (p) => p.type === "tool-call" && p.id === toolCallId ); if (toolCallPart) { const index = parts.indexOf(toolCallPart); parts[index] = { ...toolCallPart, output: errorText ? { error: errorText } : output, state: state ?? (errorText ? "error" : "complete") }; } return { ...msg, parts }; }); } function updateToolCallApprovalResponse(messages, approvalId, approved) { return messages.map((msg) => { const parts = [...msg.parts]; const toolCallPart = parts.find( (p) => p.type === "tool-call" && p.approval?.id === approvalId ); if (toolCallPart && toolCallPart.approval) { const index = parts.indexOf(toolCallPart); parts[index] = { ...toolCallPart, approval: { ...toolCallPart.approval, approved }, state: "approval-responded" }; } return { ...msg, parts }; }); } function appendStructuredOutputDelta(messages, messageId, delta) { return messages.map((msg) => { if (msg.id !== messageId) { return msg; } const parts = [...msg.parts]; const existingIndex = parts.findIndex( (p) => p.type === "structured-output" ); const existing = existingIndex >= 0 ? parts[existingIndex] : null; const nextRaw = (existing?.raw ?? "") + delta; const progressive = parsePartialJSON(nextRaw); const nextPartial = progressive !== void 0 && progressive !== null ? progressive : existing?.partial; const nextPart = { type: "structured-output", status: "streaming", raw: nextRaw, ...nextPartial !== void 0 ? { partial: nextPartial } : {}, ...existing?.reasoning !== void 0 ? { reasoning: existing.reasoning } : {} }; if (existingIndex >= 0) { parts[existingIndex] = nextPart; } else { parts.push(nextPart); } return { ...msg, parts }; }); } function completeStructuredOutputPart(messages, messageId, data, raw, reasoning) { return messages.map((msg) => { if (msg.id !== messageId) { return msg; } const parts = [...msg.parts]; const existingIndex = parts.findIndex( (p) => p.type === "structured-output" ); const existingRaw = existingIndex >= 0 ? parts[existingIndex].raw : ""; let resolvedRaw = raw || existingRaw; if (resolvedRaw === "" && data !== void 0) { try { resolvedRaw = JSON.stringify(data); } catch { } } const nextPart = { type: "structured-output", status: "complete", data, partial: data, raw: resolvedRaw, ...reasoning !== void 0 ? { reasoning } : {} }; if (existingIndex >= 0) { parts[existingIndex] = nextPart; } else { parts.push(nextPart); } return { ...msg, parts }; }); } function errorStructuredOutputPart(messages, messageId, errorMessage) { return messages.map((msg) => { if (msg.id !== messageId) { return msg; } const parts = [...msg.parts]; const existingIndex = parts.findIndex( (p) => p.type === "structured-output" ); if (existingIndex < 0) { parts.push({ type: "structured-output", status: "error", raw: "", errorMessage }); return { ...msg, parts }; } const existing = parts[existingIndex]; if (existing.status === "complete") { return msg; } parts[existingIndex] = { ...existing, status: "error", errorMessage }; return { ...msg, parts }; }); } function updateThinkingPart(messages, messageId, stepId, content, signature) { return messages.map((msg) => { if (msg.id !== messageId) { return msg; } const parts = [...msg.parts]; const thinkingPartIndex = parts.findIndex( (p) => p.type === "thinking" && p.stepId === stepId ); const thinkingPart = { type: "thinking", content, stepId, ...signature && { signature } }; if (thinkingPartIndex >= 0) { parts[thinkingPartIndex] = thinkingPart; } else { parts.push(thinkingPart); } return { ...msg, parts }; }); } export { appendStructuredOutputDelta, completeStructuredOutputPart, errorStructuredOutputPart, updateTextPart, updateThinkingPart, updateToolCallApproval, updateToolCallApprovalResponse, updateToolCallPart, updateToolCallWithOutput, updateToolResultPart }; //# sourceMappingURL=message-updaters.js.map