// src/index.ts import { generateId } from "@ai-sdk/provider-utils"; // src/assistant-stream-parts.ts var textStreamPart = { code: "0", name: "text", parse: (value) => { if (typeof value !== "string") { throw new Error('"text" parts expect a string value.'); } return { type: "text", value }; } }; var errorStreamPart = { code: "3", name: "error", parse: (value) => { if (typeof value !== "string") { throw new Error('"error" parts expect a string value.'); } return { type: "error", value }; } }; var assistantMessageStreamPart = { code: "4", name: "assistant_message", parse: (value) => { if (value == null || typeof value !== "object" || !("id" in value) || !("role" in value) || !("content" in value) || typeof value.id !== "string" || typeof value.role !== "string" || value.role !== "assistant" || !Array.isArray(value.content) || !value.content.every( (item) => item != null && typeof item === "object" && "type" in item && item.type === "text" && "text" in item && item.text != null && typeof item.text === "object" && "value" in item.text && typeof item.text.value === "string" )) { throw new Error( '"assistant_message" parts expect an object with an "id", "role", and "content" property.' ); } return { type: "assistant_message", value }; } }; var assistantControlDataStreamPart = { code: "5", name: "assistant_control_data", parse: (value) => { if (value == null || typeof value !== "object" || !("threadId" in value) || !("messageId" in value) || typeof value.threadId !== "string" || typeof value.messageId !== "string") { throw new Error( '"assistant_control_data" parts expect an object with a "threadId" and "messageId" property.' ); } return { type: "assistant_control_data", value: { threadId: value.threadId, messageId: value.messageId } }; } }; var dataMessageStreamPart = { code: "6", name: "data_message", parse: (value) => { if (value == null || typeof value !== "object" || !("role" in value) || !("data" in value) || typeof value.role !== "string" || value.role !== "data") { throw new Error( '"data_message" parts expect an object with a "role" and "data" property.' ); } return { type: "data_message", value }; } }; var assistantStreamParts = [ textStreamPart, errorStreamPart, assistantMessageStreamPart, assistantControlDataStreamPart, dataMessageStreamPart ]; var assistantStreamPartsByCode = { [textStreamPart.code]: textStreamPart, [errorStreamPart.code]: errorStreamPart, [assistantMessageStreamPart.code]: assistantMessageStreamPart, [assistantControlDataStreamPart.code]: assistantControlDataStreamPart, [dataMessageStreamPart.code]: dataMessageStreamPart }; var StreamStringPrefixes = { [textStreamPart.name]: textStreamPart.code, [errorStreamPart.name]: errorStreamPart.code, [assistantMessageStreamPart.name]: assistantMessageStreamPart.code, [assistantControlDataStreamPart.name]: assistantControlDataStreamPart.code, [dataMessageStreamPart.name]: dataMessageStreamPart.code }; var validCodes = assistantStreamParts.map((part) => part.code); var parseAssistantStreamPart = (line) => { const firstSeparatorIndex = line.indexOf(":"); if (firstSeparatorIndex === -1) { throw new Error("Failed to parse stream string. No separator found."); } const prefix = line.slice(0, firstSeparatorIndex); if (!validCodes.includes(prefix)) { throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`); } const code = prefix; const textValue = line.slice(firstSeparatorIndex + 1); const jsonValue = JSON.parse(textValue); return assistantStreamPartsByCode[code].parse(jsonValue); }; function formatAssistantStreamPart(type, value) { const streamPart = assistantStreamParts.find((part) => part.name === type); if (!streamPart) { throw new Error(`Invalid stream part type: ${type}`); } return `${streamPart.code}:${JSON.stringify(value)} `; } // src/process-chat-response.ts import { generateId as generateIdFunction } from "@ai-sdk/provider-utils"; // src/duplicated/usage.ts function calculateLanguageModelUsage({ promptTokens, completionTokens }) { return { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens }; } // src/parse-partial-json.ts import { safeParseJSON } from "@ai-sdk/provider-utils"; // src/fix-json.ts function fixJson(input) { const stack = ["ROOT"]; let lastValidIndex = -1; let literalStart = null; function processValueStart(char, i, swapState) { { switch (char) { case '"': { lastValidIndex = i; stack.pop(); stack.push(swapState); stack.push("INSIDE_STRING"); break; } case "f": case "t": case "n": { lastValidIndex = i; literalStart = i; stack.pop(); stack.push(swapState); stack.push("INSIDE_LITERAL"); break; } case "-": { stack.pop(); stack.push(swapState); stack.push("INSIDE_NUMBER"); break; } case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": { lastValidIndex = i; stack.pop(); stack.push(swapState); stack.push("INSIDE_NUMBER"); break; } case "{": { lastValidIndex = i; stack.pop(); stack.push(swapState); stack.push("INSIDE_OBJECT_START"); break; } case "[": { lastValidIndex = i; stack.pop(); stack.push(swapState); stack.push("INSIDE_ARRAY_START"); break; } } } } function processAfterObjectValue(char, i) { switch (char) { case ",": { stack.pop(); stack.push("INSIDE_OBJECT_AFTER_COMMA"); break; } case "}": { lastValidIndex = i; stack.pop(); break; } } } function processAfterArrayValue(char, i) { switch (char) { case ",": { stack.pop(); stack.push("INSIDE_ARRAY_AFTER_COMMA"); break; } case "]": { lastValidIndex = i; stack.pop(); break; } } } for (let i = 0; i < input.length; i++) { const char = input[i]; const currentState = stack[stack.length - 1]; switch (currentState) { case "ROOT": processValueStart(char, i, "FINISH"); break; case "INSIDE_OBJECT_START": { switch (char) { case '"': { stack.pop(); stack.push("INSIDE_OBJECT_KEY"); break; } case "}": { lastValidIndex = i; stack.pop(); break; } } break; } case "INSIDE_OBJECT_AFTER_COMMA": { switch (char) { case '"': { stack.pop(); stack.push("INSIDE_OBJECT_KEY"); break; } } break; } case "INSIDE_OBJECT_KEY": { switch (char) { case '"': { stack.pop(); stack.push("INSIDE_OBJECT_AFTER_KEY"); break; } } break; } case "INSIDE_OBJECT_AFTER_KEY": { switch (char) { case ":": { stack.pop(); stack.push("INSIDE_OBJECT_BEFORE_VALUE"); break; } } break; } case "INSIDE_OBJECT_BEFORE_VALUE": { processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE"); break; } case "INSIDE_OBJECT_AFTER_VALUE": { processAfterObjectValue(char, i); break; } case "INSIDE_STRING": { switch (char) { case '"': { stack.pop(); lastValidIndex = i; break; } case "\\": { stack.push("INSIDE_STRING_ESCAPE"); break; } default: { lastValidIndex = i; } } break; } case "INSIDE_ARRAY_START": { switch (char) { case "]": { lastValidIndex = i; stack.pop(); break; } default: { lastValidIndex = i; processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE"); break; } } break; } case "INSIDE_ARRAY_AFTER_VALUE": { switch (char) { case ",": { stack.pop(); stack.push("INSIDE_ARRAY_AFTER_COMMA"); break; } case "]": { lastValidIndex = i; stack.pop(); break; } default: { lastValidIndex = i; break; } } break; } case "INSIDE_ARRAY_AFTER_COMMA": { processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE"); break; } case "INSIDE_STRING_ESCAPE": { stack.pop(); lastValidIndex = i; break; } case "INSIDE_NUMBER": { switch (char) { case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": { lastValidIndex = i; break; } case "e": case "E": case "-": case ".": { break; } case ",": { stack.pop(); if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") { processAfterArrayValue(char, i); } if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") { processAfterObjectValue(char, i); } break; } case "}": { stack.pop(); if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") { processAfterObjectValue(char, i); } break; } case "]": { stack.pop(); if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") { processAfterArrayValue(char, i); } break; } default: { stack.pop(); break; } } break; } case "INSIDE_LITERAL": { const partialLiteral = input.substring(literalStart, i + 1); if (!"false".startsWith(partialLiteral) && !"true".startsWith(partialLiteral) && !"null".startsWith(partialLiteral)) { stack.pop(); if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") { processAfterObjectValue(char, i); } else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") { processAfterArrayValue(char, i); } } else { lastValidIndex = i; } break; } } } let result = input.slice(0, lastValidIndex + 1); for (let i = stack.length - 1; i >= 0; i--) { const state = stack[i]; switch (state) { case "INSIDE_STRING": { result += '"'; break; } case "INSIDE_OBJECT_KEY": case "INSIDE_OBJECT_AFTER_KEY": case "INSIDE_OBJECT_AFTER_COMMA": case "INSIDE_OBJECT_START": case "INSIDE_OBJECT_BEFORE_VALUE": case "INSIDE_OBJECT_AFTER_VALUE": { result += "}"; break; } case "INSIDE_ARRAY_START": case "INSIDE_ARRAY_AFTER_COMMA": case "INSIDE_ARRAY_AFTER_VALUE": { result += "]"; break; } case "INSIDE_LITERAL": { const partialLiteral = input.substring(literalStart, input.length); if ("true".startsWith(partialLiteral)) { result += "true".slice(partialLiteral.length); } else if ("false".startsWith(partialLiteral)) { result += "false".slice(partialLiteral.length); } else if ("null".startsWith(partialLiteral)) { result += "null".slice(partialLiteral.length); } } } } return result; } // src/parse-partial-json.ts function parsePartialJson(jsonText) { if (jsonText === void 0) { return { value: void 0, state: "undefined-input" }; } let result = safeParseJSON({ text: jsonText }); if (result.success) { return { value: result.value, state: "successful-parse" }; } result = safeParseJSON({ text: fixJson(jsonText) }); if (result.success) { return { value: result.value, state: "repaired-parse" }; } return { value: void 0, state: "failed-parse" }; } // src/data-stream-parts.ts var textStreamPart2 = { code: "0", name: "text", parse: (value) => { if (typeof value !== "string") { throw new Error('"text" parts expect a string value.'); } return { type: "text", value }; } }; var dataStreamPart = { code: "2", name: "data", parse: (value) => { if (!Array.isArray(value)) { throw new Error('"data" parts expect an array value.'); } return { type: "data", value }; } }; var errorStreamPart2 = { code: "3", name: "error", parse: (value) => { if (typeof value !== "string") { throw new Error('"error" parts expect a string value.'); } return { type: "error", value }; } }; var messageAnnotationsStreamPart = { code: "8", name: "message_annotations", parse: (value) => { if (!Array.isArray(value)) { throw new Error('"message_annotations" parts expect an array value.'); } return { type: "message_annotations", value }; } }; var toolCallStreamPart = { code: "9", name: "tool_call", parse: (value) => { if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("toolName" in value) || typeof value.toolName !== "string" || !("args" in value) || typeof value.args !== "object") { throw new Error( '"tool_call" parts expect an object with a "toolCallId", "toolName", and "args" property.' ); } return { type: "tool_call", value }; } }; var toolResultStreamPart = { code: "a", name: "tool_result", parse: (value) => { if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("result" in value)) { throw new Error( '"tool_result" parts expect an object with a "toolCallId" and a "result" property.' ); } return { type: "tool_result", value }; } }; var toolCallStreamingStartStreamPart = { code: "b", name: "tool_call_streaming_start", parse: (value) => { if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("toolName" in value) || typeof value.toolName !== "string") { throw new Error( '"tool_call_streaming_start" parts expect an object with a "toolCallId" and "toolName" property.' ); } return { type: "tool_call_streaming_start", value }; } }; var toolCallDeltaStreamPart = { code: "c", name: "tool_call_delta", parse: (value) => { if (value == null || typeof value !== "object" || !("toolCallId" in value) || typeof value.toolCallId !== "string" || !("argsTextDelta" in value) || typeof value.argsTextDelta !== "string") { throw new Error( '"tool_call_delta" parts expect an object with a "toolCallId" and "argsTextDelta" property.' ); } return { type: "tool_call_delta", value }; } }; var finishMessageStreamPart = { code: "d", name: "finish_message", parse: (value) => { if (value == null || typeof value !== "object" || !("finishReason" in value) || typeof value.finishReason !== "string") { throw new Error( '"finish_message" parts expect an object with a "finishReason" property.' ); } const result = { finishReason: value.finishReason }; if ("usage" in value && value.usage != null && typeof value.usage === "object" && "promptTokens" in value.usage && "completionTokens" in value.usage) { result.usage = { promptTokens: typeof value.usage.promptTokens === "number" ? value.usage.promptTokens : Number.NaN, completionTokens: typeof value.usage.completionTokens === "number" ? value.usage.completionTokens : Number.NaN }; } return { type: "finish_message", value: result }; } }; var finishStepStreamPart = { code: "e", name: "finish_step", parse: (value) => { if (value == null || typeof value !== "object" || !("finishReason" in value) || typeof value.finishReason !== "string") { throw new Error( '"finish_step" parts expect an object with a "finishReason" property.' ); } const result = { finishReason: value.finishReason, isContinued: false }; if ("usage" in value && value.usage != null && typeof value.usage === "object" && "promptTokens" in value.usage && "completionTokens" in value.usage) { result.usage = { promptTokens: typeof value.usage.promptTokens === "number" ? value.usage.promptTokens : Number.NaN, completionTokens: typeof value.usage.completionTokens === "number" ? value.usage.completionTokens : Number.NaN }; } if ("isContinued" in value && typeof value.isContinued === "boolean") { result.isContinued = value.isContinued; } return { type: "finish_step", value: result }; } }; var startStepStreamPart = { code: "f", name: "start_step", parse: (value) => { if (value == null || typeof value !== "object" || !("messageId" in value) || typeof value.messageId !== "string") { throw new Error( '"start_step" parts expect an object with an "id" property.' ); } return { type: "start_step", value: { messageId: value.messageId } }; } }; var reasoningStreamPart = { code: "g", name: "reasoning", parse: (value) => { if (typeof value !== "string") { throw new Error('"reasoning" parts expect a string value.'); } return { type: "reasoning", value }; } }; var sourcePart = { code: "h", name: "source", parse: (value) => { if (value == null || typeof value !== "object") { throw new Error('"source" parts expect a Source object.'); } return { type: "source", value }; } }; var redactedReasoningStreamPart = { code: "i", name: "redacted_reasoning", parse: (value) => { if (value == null || typeof value !== "object" || !("data" in value) || typeof value.data !== "string") { throw new Error( '"redacted_reasoning" parts expect an object with a "data" property.' ); } return { type: "redacted_reasoning", value: { data: value.data } }; } }; var reasoningSignatureStreamPart = { code: "j", name: "reasoning_signature", parse: (value) => { if (value == null || typeof value !== "object" || !("signature" in value) || typeof value.signature !== "string") { throw new Error( '"reasoning_signature" parts expect an object with a "signature" property.' ); } return { type: "reasoning_signature", value: { signature: value.signature } }; } }; var fileStreamPart = { code: "k", name: "file", parse: (value) => { if (value == null || typeof value !== "object" || !("data" in value) || typeof value.data !== "string" || !("mimeType" in value) || typeof value.mimeType !== "string") { throw new Error( '"file" parts expect an object with a "data" and "mimeType" property.' ); } return { type: "file", value }; } }; var dataStreamParts = [ textStreamPart2, dataStreamPart, errorStreamPart2, messageAnnotationsStreamPart, toolCallStreamPart, toolResultStreamPart, toolCallStreamingStartStreamPart, toolCallDeltaStreamPart, finishMessageStreamPart, finishStepStreamPart, startStepStreamPart, reasoningStreamPart, sourcePart, redactedReasoningStreamPart, reasoningSignatureStreamPart, fileStreamPart ]; var dataStreamPartsByCode = Object.fromEntries( dataStreamParts.map((part) => [part.code, part]) ); var DataStreamStringPrefixes = Object.fromEntries( dataStreamParts.map((part) => [part.name, part.code]) ); var validCodes2 = dataStreamParts.map((part) => part.code); var parseDataStreamPart = (line) => { const firstSeparatorIndex = line.indexOf(":"); if (firstSeparatorIndex === -1) { throw new Error("Failed to parse stream string. No separator found."); } const prefix = line.slice(0, firstSeparatorIndex); if (!validCodes2.includes(prefix)) { throw new Error(`Failed to parse stream string. Invalid code ${prefix}.`); } const code = prefix; const textValue = line.slice(firstSeparatorIndex + 1); const jsonValue = JSON.parse(textValue); return dataStreamPartsByCode[code].parse(jsonValue); }; function formatDataStreamPart(type, value) { const streamPart = dataStreamParts.find((part) => part.name === type); if (!streamPart) { throw new Error(`Invalid stream part type: ${type}`); } return `${streamPart.code}:${JSON.stringify(value)} `; } // src/process-data-stream.ts var NEWLINE = "\n".charCodeAt(0); function concatChunks(chunks, totalLength) { const concatenatedChunks = new Uint8Array(totalLength); let offset = 0; for (const chunk of chunks) { concatenatedChunks.set(chunk, offset); offset += chunk.length; } chunks.length = 0; return concatenatedChunks; } async function processDataStream({ stream, onTextPart, onReasoningPart, onReasoningSignaturePart, onRedactedReasoningPart, onSourcePart, onFilePart, onDataPart, onErrorPart, onToolCallStreamingStartPart, onToolCallDeltaPart, onToolCallPart, onToolResultPart, onMessageAnnotationsPart, onFinishMessagePart, onFinishStepPart, onStartStepPart }) { const reader = stream.getReader(); const decoder = new TextDecoder(); const chunks = []; let totalLength = 0; while (true) { const { value } = await reader.read(); if (value) { chunks.push(value); totalLength += value.length; if (value[value.length - 1] !== NEWLINE) { continue; } } if (chunks.length === 0) { break; } const concatenatedChunks = concatChunks(chunks, totalLength); totalLength = 0; const streamParts = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseDataStreamPart); for (const { type, value: value2 } of streamParts) { switch (type) { case "text": await (onTextPart == null ? void 0 : onTextPart(value2)); break; case "reasoning": await (onReasoningPart == null ? void 0 : onReasoningPart(value2)); break; case "reasoning_signature": await (onReasoningSignaturePart == null ? void 0 : onReasoningSignaturePart(value2)); break; case "redacted_reasoning": await (onRedactedReasoningPart == null ? void 0 : onRedactedReasoningPart(value2)); break; case "file": await (onFilePart == null ? void 0 : onFilePart(value2)); break; case "source": await (onSourcePart == null ? void 0 : onSourcePart(value2)); break; case "data": await (onDataPart == null ? void 0 : onDataPart(value2)); break; case "error": await (onErrorPart == null ? void 0 : onErrorPart(value2)); break; case "message_annotations": await (onMessageAnnotationsPart == null ? void 0 : onMessageAnnotationsPart(value2)); break; case "tool_call_streaming_start": await (onToolCallStreamingStartPart == null ? void 0 : onToolCallStreamingStartPart(value2)); break; case "tool_call_delta": await (onToolCallDeltaPart == null ? void 0 : onToolCallDeltaPart(value2)); break; case "tool_call": await (onToolCallPart == null ? void 0 : onToolCallPart(value2)); break; case "tool_result": await (onToolResultPart == null ? void 0 : onToolResultPart(value2)); break; case "finish_message": await (onFinishMessagePart == null ? void 0 : onFinishMessagePart(value2)); break; case "finish_step": await (onFinishStepPart == null ? void 0 : onFinishStepPart(value2)); break; case "start_step": await (onStartStepPart == null ? void 0 : onStartStepPart(value2)); break; default: { const exhaustiveCheck = type; throw new Error(`Unknown stream part type: ${exhaustiveCheck}`); } } } } } // src/process-chat-response.ts async function processChatResponse({ stream, update, onToolCall, onFinish, generateId: generateId2 = generateIdFunction, getCurrentDate = () => /* @__PURE__ */ new Date(), lastMessage }) { var _a, _b; const replaceLastMessage = (lastMessage == null ? void 0 : lastMessage.role) === "assistant"; let step = replaceLastMessage ? 1 + // find max step in existing tool invocations: ((_b = (_a = lastMessage.toolInvocations) == null ? void 0 : _a.reduce((max, toolInvocation) => { var _a2; return Math.max(max, (_a2 = toolInvocation.step) != null ? _a2 : 0); }, 0)) != null ? _b : 0) : 0; const message = replaceLastMessage ? structuredClone(lastMessage) : { id: generateId2(), createdAt: getCurrentDate(), role: "assistant", content: "", parts: [] }; let currentTextPart = void 0; let currentReasoningPart = void 0; let currentReasoningTextDetail = void 0; function updateToolInvocationPart(toolCallId, invocation) { const part = message.parts.find( (part2) => part2.type === "tool-invocation" && part2.toolInvocation.toolCallId === toolCallId ); if (part != null) { part.toolInvocation = invocation; } else { message.parts.push({ type: "tool-invocation", toolInvocation: invocation }); } } const data = []; let messageAnnotations = replaceLastMessage ? lastMessage == null ? void 0 : lastMessage.annotations : void 0; const partialToolCalls = {}; let usage = { completionTokens: NaN, promptTokens: NaN, totalTokens: NaN }; let finishReason = "unknown"; function execUpdate() { const copiedData = [...data]; if (messageAnnotations == null ? void 0 : messageAnnotations.length) { message.annotations = messageAnnotations; } const copiedMessage = { // deep copy the message to ensure that deep changes (msg attachments) are updated // with SolidJS. SolidJS uses referential integration of sub-objects to detect changes. ...structuredClone(message), // add a revision id to ensure that the message is updated with SWR. SWR uses a // hashing approach by default to detect changes, but it only works for shallow // changes. This is why we need to add a revision id to ensure that the message // is updated with SWR (without it, the changes get stuck in SWR and are not // forwarded to rendering): revisionId: generateId2() }; update({ message: copiedMessage, data: copiedData, replaceLastMessage }); } await processDataStream({ stream, onTextPart(value) { if (currentTextPart == null) { currentTextPart = { type: "text", text: value }; message.parts.push(currentTextPart); } else { currentTextPart.text += value; } message.content += value; execUpdate(); }, onReasoningPart(value) { var _a2; if (currentReasoningTextDetail == null) { currentReasoningTextDetail = { type: "text", text: value }; if (currentReasoningPart != null) { currentReasoningPart.details.push(currentReasoningTextDetail); } } else { currentReasoningTextDetail.text += value; } if (currentReasoningPart == null) { currentReasoningPart = { type: "reasoning", reasoning: value, details: [currentReasoningTextDetail] }; message.parts.push(currentReasoningPart); } else { currentReasoningPart.reasoning += value; } message.reasoning = ((_a2 = message.reasoning) != null ? _a2 : "") + value; execUpdate(); }, onReasoningSignaturePart(value) { if (currentReasoningTextDetail != null) { currentReasoningTextDetail.signature = value.signature; } }, onRedactedReasoningPart(value) { if (currentReasoningPart == null) { currentReasoningPart = { type: "reasoning", reasoning: "", details: [] }; message.parts.push(currentReasoningPart); } currentReasoningPart.details.push({ type: "redacted", data: value.data }); currentReasoningTextDetail = void 0; execUpdate(); }, onFilePart(value) { message.parts.push({ type: "file", mimeType: value.mimeType, data: value.data }); execUpdate(); }, onSourcePart(value) { message.parts.push({ type: "source", source: value }); execUpdate(); }, onToolCallStreamingStartPart(value) { if (message.toolInvocations == null) { message.toolInvocations = []; } partialToolCalls[value.toolCallId] = { text: "", step, toolName: value.toolName, index: message.toolInvocations.length }; const invocation = { state: "partial-call", step, toolCallId: value.toolCallId, toolName: value.toolName, args: void 0 }; message.toolInvocations.push(invocation); updateToolInvocationPart(value.toolCallId, invocation); execUpdate(); }, onToolCallDeltaPart(value) { const partialToolCall = partialToolCalls[value.toolCallId]; partialToolCall.text += value.argsTextDelta; const { value: partialArgs } = parsePartialJson(partialToolCall.text); const invocation = { state: "partial-call", step: partialToolCall.step, toolCallId: value.toolCallId, toolName: partialToolCall.toolName, args: partialArgs }; message.toolInvocations[partialToolCall.index] = invocation; updateToolInvocationPart(value.toolCallId, invocation); execUpdate(); }, async onToolCallPart(value) { const invocation = { state: "call", step, ...value }; if (partialToolCalls[value.toolCallId] != null) { message.toolInvocations[partialToolCalls[value.toolCallId].index] = invocation; } else { if (message.toolInvocations == null) { message.toolInvocations = []; } message.toolInvocations.push(invocation); } updateToolInvocationPart(value.toolCallId, invocation); execUpdate(); if (onToolCall) { const result = await onToolCall({ toolCall: value }); if (result != null) { const invocation2 = { state: "result", step, ...value, result }; message.toolInvocations[message.toolInvocations.length - 1] = invocation2; updateToolInvocationPart(value.toolCallId, invocation2); execUpdate(); } } }, onToolResultPart(value) { const toolInvocations = message.toolInvocations; if (toolInvocations == null) { throw new Error("tool_result must be preceded by a tool_call"); } const toolInvocationIndex = toolInvocations.findIndex( (invocation2) => invocation2.toolCallId === value.toolCallId ); if (toolInvocationIndex === -1) { throw new Error( "tool_result must be preceded by a tool_call with the same toolCallId" ); } const invocation = { ...toolInvocations[toolInvocationIndex], state: "result", ...value }; toolInvocations[toolInvocationIndex] = invocation; updateToolInvocationPart(value.toolCallId, invocation); execUpdate(); }, onDataPart(value) { data.push(...value); execUpdate(); }, onMessageAnnotationsPart(value) { if (messageAnnotations == null) { messageAnnotations = [...value]; } else { messageAnnotations.push(...value); } execUpdate(); }, onFinishStepPart(value) { step += 1; currentTextPart = value.isContinued ? currentTextPart : void 0; currentReasoningPart = void 0; currentReasoningTextDetail = void 0; }, onStartStepPart(value) { if (!replaceLastMessage) { message.id = value.messageId; } message.parts.push({ type: "step-start" }); execUpdate(); }, onFinishMessagePart(value) { finishReason = value.finishReason; if (value.usage != null) { usage = calculateLanguageModelUsage(value.usage); } }, onErrorPart(error) { throw new Error(error); } }); onFinish == null ? void 0 : onFinish({ message, finishReason, usage }); } // src/process-chat-text-response.ts import { generateId as generateIdFunction2 } from "@ai-sdk/provider-utils"; // src/process-text-stream.ts async function processTextStream({ stream, onTextPart }) { const reader = stream.pipeThrough(new TextDecoderStream()).getReader(); while (true) { const { done, value } = await reader.read(); if (done) { break; } await onTextPart(value); } } // src/process-chat-text-response.ts async function processChatTextResponse({ stream, update, onFinish, getCurrentDate = () => /* @__PURE__ */ new Date(), generateId: generateId2 = generateIdFunction2 }) { const textPart = { type: "text", text: "" }; const resultMessage = { id: generateId2(), createdAt: getCurrentDate(), role: "assistant", content: "", parts: [textPart] }; await processTextStream({ stream, onTextPart: (chunk) => { resultMessage.content += chunk; textPart.text += chunk; update({ message: { ...resultMessage }, data: [], replaceLastMessage: false }); } }); onFinish == null ? void 0 : onFinish(resultMessage, { usage: { completionTokens: NaN, promptTokens: NaN, totalTokens: NaN }, finishReason: "unknown" }); } // src/call-chat-api.ts var getOriginalFetch = () => fetch; async function callChatApi({ api, body, streamProtocol = "data", credentials, headers, abortController, restoreMessagesOnFailure, onResponse, onUpdate, onFinish, onToolCall, generateId: generateId2, fetch: fetch2 = getOriginalFetch(), lastMessage, requestType = "generate" }) { var _a, _b, _c; const request = requestType === "resume" ? fetch2(`${api}?chatId=${body.id}`, { method: "GET", headers: { "Content-Type": "application/json", ...headers }, signal: (_a = abortController == null ? void 0 : abortController()) == null ? void 0 : _a.signal, credentials }) : fetch2(api, { method: "POST", body: JSON.stringify(body), headers: { "Content-Type": "application/json", ...headers }, signal: (_b = abortController == null ? void 0 : abortController()) == null ? void 0 : _b.signal, credentials }); const response = await request.catch((err) => { restoreMessagesOnFailure(); throw err; }); if (onResponse) { try { await onResponse(response); } catch (err) { throw err; } } if (!response.ok) { restoreMessagesOnFailure(); throw new Error( (_c = await response.text()) != null ? _c : "Failed to fetch the chat response." ); } if (!response.body) { throw new Error("The response body is empty."); } switch (streamProtocol) { case "text": { await processChatTextResponse({ stream: response.body, update: onUpdate, onFinish, generateId: generateId2 }); return; } case "data": { await processChatResponse({ stream: response.body, update: onUpdate, lastMessage, onToolCall, onFinish({ message, finishReason, usage }) { if (onFinish && message != null) { onFinish(message, { usage, finishReason }); } }, generateId: generateId2 }); return; } default: { const exhaustiveCheck = streamProtocol; throw new Error(`Unknown stream protocol: ${exhaustiveCheck}`); } } } // src/call-completion-api.ts var getOriginalFetch2 = () => fetch; async function callCompletionApi({ api, prompt, credentials, headers, body, streamProtocol = "data", setCompletion, setLoading, setError, setAbortController, onResponse, onFinish, onError, onData, fetch: fetch2 = getOriginalFetch2() }) { var _a; try { setLoading(true); setError(void 0); const abortController = new AbortController(); setAbortController(abortController); setCompletion(""); const response = await fetch2(api, { method: "POST", body: JSON.stringify({ prompt, ...body }), credentials, headers: { "Content-Type": "application/json", ...headers }, signal: abortController.signal }).catch((err) => { throw err; }); if (onResponse) { try { await onResponse(response); } catch (err) { throw err; } } if (!response.ok) { throw new Error( (_a = await response.text()) != null ? _a : "Failed to fetch the chat response." ); } if (!response.body) { throw new Error("The response body is empty."); } let result = ""; switch (streamProtocol) { case "text": { await processTextStream({ stream: response.body, onTextPart: (chunk) => { result += chunk; setCompletion(result); } }); break; } case "data": { await processDataStream({ stream: response.body, onTextPart(value) { result += value; setCompletion(result); }, onDataPart(value) { onData == null ? void 0 : onData(value); }, onErrorPart(value) { throw new Error(value); } }); break; } default: { const exhaustiveCheck = streamProtocol; throw new Error(`Unknown stream protocol: ${exhaustiveCheck}`); } } if (onFinish) { onFinish(prompt, result); } setAbortController(null); return result; } catch (err) { if (err.name === "AbortError") { setAbortController(null); return null; } if (err instanceof Error) { if (onError) { onError(err); } } setError(err); } finally { setLoading(false); } } // src/data-url.ts function getTextFromDataUrl(dataUrl) { const [header, base64Content] = dataUrl.split(","); const mimeType = header.split(";")[0].split(":")[1]; if (mimeType == null || base64Content == null) { throw new Error("Invalid data URL format"); } try { return window.atob(base64Content); } catch (error) { throw new Error(`Error decoding data URL`); } } // src/extract-max-tool-invocation-step.ts function extractMaxToolInvocationStep(toolInvocations) { return toolInvocations == null ? void 0 : toolInvocations.reduce((max, toolInvocation) => { var _a; return Math.max(max, (_a = toolInvocation.step) != null ? _a : 0); }, 0); } // src/get-message-parts.ts function getMessageParts(message) { var _a; return (_a = message.parts) != null ? _a : [ ...message.toolInvocations ? message.toolInvocations.map((toolInvocation) => ({ type: "tool-invocation", toolInvocation })) : [], ...message.reasoning ? [ { type: "reasoning", reasoning: message.reasoning, details: [{ type: "text", text: message.reasoning }] } ] : [], ...message.content ? [{ type: "text", text: message.content }] : [] ]; } // src/fill-message-parts.ts function fillMessageParts(messages) { return messages.map((message) => ({ ...message, parts: getMessageParts(message) })); } // src/is-deep-equal-data.ts function isDeepEqualData(obj1, obj2) { if (obj1 === obj2) return true; if (obj1 == null || obj2 == null) return false; if (typeof obj1 !== "object" && typeof obj2 !== "object") return obj1 === obj2; if (obj1.constructor !== obj2.constructor) return false; if (obj1 instanceof Date && obj2 instanceof Date) { return obj1.getTime() === obj2.getTime(); } if (Array.isArray(obj1)) { if (obj1.length !== obj2.length) return false; for (let i = 0; i < obj1.length; i++) { if (!isDeepEqualData(obj1[i], obj2[i])) return false; } return true; } const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2); if (keys1.length !== keys2.length) return false; for (const key of keys1) { if (!keys2.includes(key)) return false; if (!isDeepEqualData(obj1[key], obj2[key])) return false; } return true; } // src/prepare-attachments-for-request.ts async function prepareAttachmentsForRequest(attachmentsFromOptions) { if (!attachmentsFromOptions) { return []; } if (globalThis.FileList && attachmentsFromOptions instanceof globalThis.FileList) { return Promise.all( Array.from(attachmentsFromOptions).map(async (attachment) => { const { name, type } = attachment; const dataUrl = await new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (readerEvent) => { var _a; resolve((_a = readerEvent.target) == null ? void 0 : _a.result); }; reader.onerror = (error) => reject(error); reader.readAsDataURL(attachment); }); return { name, contentType: type, url: dataUrl }; }) ); } if (Array.isArray(attachmentsFromOptions)) { return attachmentsFromOptions; } throw new Error("Invalid attachments type"); } // src/process-assistant-stream.ts var NEWLINE2 = "\n".charCodeAt(0); function concatChunks2(chunks, totalLength) { const concatenatedChunks = new Uint8Array(totalLength); let offset = 0; for (const chunk of chunks) { concatenatedChunks.set(chunk, offset); offset += chunk.length; } chunks.length = 0; return concatenatedChunks; } async function processAssistantStream({ stream, onTextPart, onErrorPart, onAssistantMessagePart, onAssistantControlDataPart, onDataMessagePart }) { const reader = stream.getReader(); const decoder = new TextDecoder(); const chunks = []; let totalLength = 0; while (true) { const { value } = await reader.read(); if (value) { chunks.push(value); totalLength += value.length; if (value[value.length - 1] !== NEWLINE2) { continue; } } if (chunks.length === 0) { break; } const concatenatedChunks = concatChunks2(chunks, totalLength); totalLength = 0; const streamParts = decoder.decode(concatenatedChunks, { stream: true }).split("\n").filter((line) => line !== "").map(parseAssistantStreamPart); for (const { type, value: value2 } of streamParts) { switch (type) { case "text": await (onTextPart == null ? void 0 : onTextPart(value2)); break; case "error": await (onErrorPart == null ? void 0 : onErrorPart(value2)); break; case "assistant_message": await (onAssistantMessagePart == null ? void 0 : onAssistantMessagePart(value2)); break; case "assistant_control_data": await (onAssistantControlDataPart == null ? void 0 : onAssistantControlDataPart(value2)); break; case "data_message": await (onDataMessagePart == null ? void 0 : onDataMessagePart(value2)); break; default: { const exhaustiveCheck = type; throw new Error(`Unknown stream part type: ${exhaustiveCheck}`); } } } } } // src/schema.ts import { validatorSymbol } from "@ai-sdk/provider-utils"; // src/zod-schema.ts import zodToJsonSchema from "zod-to-json-schema"; function zodSchema(zodSchema2, options) { var _a; const useReferences = (_a = options == null ? void 0 : options.useReferences) != null ? _a : false; return jsonSchema( zodToJsonSchema(zodSchema2, { $refStrategy: useReferences ? "root" : "none", target: "jsonSchema7" // note: openai mode breaks various gemini conversions }), { validate: (value) => { const result = zodSchema2.safeParse(value); return result.success ? { success: true, value: result.data } : { success: false, error: result.error }; } } ); } // src/schema.ts var schemaSymbol = Symbol.for("vercel.ai.schema"); function jsonSchema(jsonSchema2, { validate } = {}) { return { [schemaSymbol]: true, _type: void 0, // should never be used directly [validatorSymbol]: true, jsonSchema: jsonSchema2, validate }; } function isSchema(value) { return typeof value === "object" && value !== null && schemaSymbol in value && value[schemaSymbol] === true && "jsonSchema" in value && "validate" in value; } function asSchema(schema) { return isSchema(schema) ? schema : zodSchema(schema); } // src/should-resubmit-messages.ts function shouldResubmitMessages({ originalMaxToolInvocationStep, originalMessageCount, maxSteps, messages }) { var _a; const lastMessage = messages[messages.length - 1]; return ( // check if the feature is enabled: maxSteps > 1 && // ensure there is a last message: lastMessage != null && // ensure we actually have new steps (to prevent infinite loops in case of errors): (messages.length > originalMessageCount || extractMaxToolInvocationStep(lastMessage.toolInvocations) !== originalMaxToolInvocationStep) && // check that next step is possible: isAssistantMessageWithCompletedToolCalls(lastMessage) && // limit the number of automatic steps: ((_a = extractMaxToolInvocationStep(lastMessage.toolInvocations)) != null ? _a : 0) < maxSteps ); } function isAssistantMessageWithCompletedToolCalls(message) { if (message.role !== "assistant") { return false; } const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => { return part.type === "step-start" ? index : lastIndex; }, -1); const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter((part) => part.type === "tool-invocation"); return lastStepToolInvocations.length > 0 && lastStepToolInvocations.every((part) => "result" in part.toolInvocation); } // src/update-tool-call-result.ts function updateToolCallResult({ messages, toolCallId, toolResult: result }) { var _a; const lastMessage = messages[messages.length - 1]; const invocationPart = lastMessage.parts.find( (part) => part.type === "tool-invocation" && part.toolInvocation.toolCallId === toolCallId ); if (invocationPart == null) { return; } const toolResult = { ...invocationPart.toolInvocation, state: "result", result }; invocationPart.toolInvocation = toolResult; lastMessage.toolInvocations = (_a = lastMessage.toolInvocations) == null ? void 0 : _a.map( (toolInvocation) => toolInvocation.toolCallId === toolCallId ? toolResult : toolInvocation ); } export { asSchema, callChatApi, callCompletionApi, extractMaxToolInvocationStep, fillMessageParts, formatAssistantStreamPart, formatDataStreamPart, generateId, getMessageParts, getTextFromDataUrl, isAssistantMessageWithCompletedToolCalls, isDeepEqualData, jsonSchema, parseAssistantStreamPart, parseDataStreamPart, parsePartialJson, prepareAttachmentsForRequest, processAssistantStream, processDataStream, processTextStream, shouldResubmitMessages, updateToolCallResult, zodSchema }; //# sourceMappingURL=index.mjs.map