UNPKG

ai

Version:

Vercel AI SDK - The AI Toolkit for TypeScript and JavaScript

1,626 lines (1,593 loc) • 64.3 kB
// rsc/ai-state.tsx import * as jsondiffpatch from "jsondiffpatch"; import { AsyncLocalStorage } from "async_hooks"; // util/create-resolvable-promise.ts function createResolvablePromise() { let resolve; let reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve, reject }; } // util/is-function.ts var isFunction = (value) => typeof value === "function"; // rsc/ai-state.tsx var asyncAIStateStorage = new AsyncLocalStorage(); function getAIStateStoreOrThrow(message) { const store = asyncAIStateStorage.getStore(); if (!store) { throw new Error(message); } return store; } function withAIState({ state, options }, fn) { return asyncAIStateStorage.run( { currentState: state, originalState: state, sealed: false, options }, fn ); } function getAIStateDeltaPromise() { const store = getAIStateStoreOrThrow("Internal error occurred."); return store.mutationDeltaPromise; } function sealMutableAIState() { const store = getAIStateStoreOrThrow("Internal error occurred."); store.sealed = true; } function getAIState(...args) { const store = getAIStateStoreOrThrow( "`getAIState` must be called within an AI Action." ); if (args.length > 0) { const key = args[0]; if (typeof store.currentState !== "object") { throw new Error( `You can't get the "${String( key )}" field from the AI state because it's not an object.` ); } return store.currentState[key]; } return store.currentState; } function getMutableAIState(...args) { const store = getAIStateStoreOrThrow( "`getMutableAIState` must be called within an AI Action." ); if (store.sealed) { throw new Error( "`getMutableAIState` must be called before returning from an AI Action. Please move it to the top level of the Action's function body." ); } if (!store.mutationDeltaPromise) { const { promise, resolve } = createResolvablePromise(); store.mutationDeltaPromise = promise; store.mutationDeltaResolve = resolve; } function doUpdate(newState, done) { var _a8, _b; if (args.length > 0) { if (typeof store.currentState !== "object") { const key = args[0]; throw new Error( `You can't modify the "${String( key )}" field of the AI state because it's not an object.` ); } } if (isFunction(newState)) { if (args.length > 0) { store.currentState[args[0]] = newState(store.currentState[args[0]]); } else { store.currentState = newState(store.currentState); } } else { if (args.length > 0) { store.currentState[args[0]] = newState; } else { store.currentState = newState; } } (_b = (_a8 = store.options).onSetAIState) == null ? void 0 : _b.call(_a8, { key: args.length > 0 ? args[0] : void 0, state: store.currentState, done }); } const mutableState = { get: () => { if (args.length > 0) { const key = args[0]; if (typeof store.currentState !== "object") { throw new Error( `You can't get the "${String( key )}" field from the AI state because it's not an object.` ); } return store.currentState[key]; } return store.currentState; }, update: function update(newAIState) { doUpdate(newAIState, false); }, done: function done(...doneArgs) { if (doneArgs.length > 0) { doUpdate(doneArgs[0], true); } const delta = jsondiffpatch.diff(store.originalState, store.currentState); store.mutationDeltaResolve(delta); } }; return mutableState; } // rsc/constants.ts var STREAMABLE_VALUE_TYPE = Symbol.for("ui.streamable.value"); var DEV_DEFAULT_STREAMABLE_WARNING_TIME = 15 * 1e3; // rsc/create-suspended-chunk.tsx import { Suspense } from "react"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var R = [ async ({ c: current, n: next }) => { const chunk = await next; if (chunk.done) { return chunk.value; } if (chunk.append) { return /* @__PURE__ */ jsxs(Fragment, { children: [ current, /* @__PURE__ */ jsx(Suspense, { fallback: chunk.value, children: /* @__PURE__ */ jsx(R, { c: chunk.value, n: chunk.next }) }) ] }); } return /* @__PURE__ */ jsx(Suspense, { fallback: chunk.value, children: /* @__PURE__ */ jsx(R, { c: chunk.value, n: chunk.next }) }); } ][0]; function createSuspendedChunk(initialValue) { const { promise, resolve, reject } = createResolvablePromise(); return { row: /* @__PURE__ */ jsx(Suspense, { fallback: initialValue, children: /* @__PURE__ */ jsx(R, { c: initialValue, n: promise }) }), resolve, reject }; } // rsc/streamable.tsx function createStreamableUI(initialValue) { let currentValue = initialValue; let closed = false; let { row, resolve, reject } = createSuspendedChunk(initialValue); function assertStream(method) { if (closed) { throw new Error(method + ": UI stream is already closed."); } } let warningTimeout; function warnUnclosedStream() { if (process.env.NODE_ENV === "development") { if (warningTimeout) { clearTimeout(warningTimeout); } warningTimeout = setTimeout(() => { console.warn( "The streamable UI has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`." ); }, DEV_DEFAULT_STREAMABLE_WARNING_TIME); } } warnUnclosedStream(); const streamable2 = { value: row, update(value) { assertStream(".update()"); if (value === currentValue) { warnUnclosedStream(); return streamable2; } const resolvable = createResolvablePromise(); currentValue = value; resolve({ value: currentValue, done: false, next: resolvable.promise }); resolve = resolvable.resolve; reject = resolvable.reject; warnUnclosedStream(); return streamable2; }, append(value) { assertStream(".append()"); const resolvable = createResolvablePromise(); currentValue = value; resolve({ value, done: false, append: true, next: resolvable.promise }); resolve = resolvable.resolve; reject = resolvable.reject; warnUnclosedStream(); return streamable2; }, error(error) { assertStream(".error()"); if (warningTimeout) { clearTimeout(warningTimeout); } closed = true; reject(error); return streamable2; }, done(...args) { assertStream(".done()"); if (warningTimeout) { clearTimeout(warningTimeout); } closed = true; if (args.length) { resolve({ value: args[0], done: true }); return streamable2; } resolve({ value: currentValue, done: true }); return streamable2; } }; return streamable2; } var STREAMABLE_VALUE_INTERNAL_LOCK = Symbol("streamable.value.lock"); function createStreamableValue(initialValue) { const isReadableStream = initialValue instanceof ReadableStream || typeof initialValue === "object" && initialValue !== null && "getReader" in initialValue && typeof initialValue.getReader === "function" && "locked" in initialValue && typeof initialValue.locked === "boolean"; if (!isReadableStream) { return createStreamableValueImpl(initialValue); } const streamableValue = createStreamableValueImpl(); streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = true; (async () => { try { const reader = initialValue.getReader(); while (true) { const { value, done } = await reader.read(); if (done) { break; } streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false; if (typeof value === "string") { streamableValue.append(value); } else { streamableValue.update(value); } streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = true; } streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false; streamableValue.done(); } catch (e) { streamableValue[STREAMABLE_VALUE_INTERNAL_LOCK] = false; streamableValue.error(e); } })(); return streamableValue; } function createStreamableValueImpl(initialValue) { let closed = false; let locked = false; let resolvable = createResolvablePromise(); let currentValue = initialValue; let currentError; let currentPromise = resolvable.promise; let currentPatchValue; function assertStream(method) { if (closed) { throw new Error(method + ": Value stream is already closed."); } if (locked) { throw new Error( method + ": Value stream is locked and cannot be updated." ); } } let warningTimeout; function warnUnclosedStream() { if (process.env.NODE_ENV === "development") { if (warningTimeout) { clearTimeout(warningTimeout); } warningTimeout = setTimeout(() => { console.warn( "The streamable value has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`." ); }, DEV_DEFAULT_STREAMABLE_WARNING_TIME); } } warnUnclosedStream(); function createWrapped(initialChunk) { let init; if (currentError !== void 0) { init = { error: currentError }; } else { if (currentPatchValue && !initialChunk) { init = { diff: currentPatchValue }; } else { init = { curr: currentValue }; } } if (currentPromise) { init.next = currentPromise; } if (initialChunk) { init.type = STREAMABLE_VALUE_TYPE; } return init; } function updateValueStates(value) { currentPatchValue = void 0; if (typeof value === "string") { if (typeof currentValue === "string") { if (value.startsWith(currentValue)) { currentPatchValue = [0, value.slice(currentValue.length)]; } } } currentValue = value; } const streamable2 = { set [STREAMABLE_VALUE_INTERNAL_LOCK](state) { locked = state; }, get value() { return createWrapped(true); }, update(value) { assertStream(".update()"); const resolvePrevious = resolvable.resolve; resolvable = createResolvablePromise(); updateValueStates(value); currentPromise = resolvable.promise; resolvePrevious(createWrapped()); warnUnclosedStream(); return streamable2; }, append(value) { assertStream(".append()"); if (typeof currentValue !== "string" && typeof currentValue !== "undefined") { throw new Error( `.append(): The current value is not a string. Received: ${typeof currentValue}` ); } if (typeof value !== "string") { throw new Error( `.append(): The value is not a string. Received: ${typeof value}` ); } const resolvePrevious = resolvable.resolve; resolvable = createResolvablePromise(); if (typeof currentValue === "string") { currentPatchValue = [0, value]; currentValue = currentValue + value; } else { currentPatchValue = void 0; currentValue = value; } currentPromise = resolvable.promise; resolvePrevious(createWrapped()); warnUnclosedStream(); return streamable2; }, error(error) { assertStream(".error()"); if (warningTimeout) { clearTimeout(warningTimeout); } closed = true; currentError = error; currentPromise = void 0; resolvable.resolve({ error }); return streamable2; }, done(...args) { assertStream(".done()"); if (warningTimeout) { clearTimeout(warningTimeout); } closed = true; currentPromise = void 0; if (args.length) { updateValueStates(args[0]); resolvable.resolve(createWrapped()); return streamable2; } resolvable.resolve({}); return streamable2; } }; return streamable2; } // rsc/render.ts import zodToJsonSchema2 from "zod-to-json-schema"; // util/retry-with-exponential-backoff.ts import { APICallError } from "@ai-sdk/provider"; import { getErrorMessage, isAbortError } from "@ai-sdk/provider-utils"; // util/delay.ts async function delay(delayInMs) { return new Promise((resolve) => setTimeout(resolve, delayInMs)); } // util/retry-error.ts import { AISDKError } from "@ai-sdk/provider"; var name = "AI_RetryError"; var marker = `vercel.ai.error.${name}`; var symbol = Symbol.for(marker); var _a; var RetryError = class extends AISDKError { constructor({ message, reason, errors }) { super({ name, message }); this[_a] = true; this.reason = reason; this.errors = errors; this.lastError = errors[errors.length - 1]; } static isInstance(error) { return AISDKError.hasMarker(error, marker); } /** * @deprecated use `isInstance` instead */ static isRetryError(error) { return error instanceof Error && error.name === name && typeof error.reason === "string" && Array.isArray(error.errors); } /** * @deprecated Do not use this method. It will be removed in the next major version. */ toJSON() { return { name: this.name, message: this.message, reason: this.reason, lastError: this.lastError, errors: this.errors }; } }; _a = symbol; // util/retry-with-exponential-backoff.ts var retryWithExponentialBackoff = ({ maxRetries = 2, initialDelayInMs = 2e3, backoffFactor = 2 } = {}) => async (f) => _retryWithExponentialBackoff(f, { maxRetries, delayInMs: initialDelayInMs, backoffFactor }); async function _retryWithExponentialBackoff(f, { maxRetries, delayInMs, backoffFactor }, errors = []) { try { return await f(); } catch (error) { if (isAbortError(error)) { throw error; } if (maxRetries === 0) { throw error; } const errorMessage = getErrorMessage(error); const newErrors = [...errors, error]; const tryNumber = newErrors.length; if (tryNumber > maxRetries) { throw new RetryError({ message: `Failed after ${tryNumber} attempts. Last error: ${errorMessage}`, reason: "maxRetriesExceeded", errors: newErrors }); } if (error instanceof Error && APICallError.isAPICallError(error) && error.isRetryable === true && tryNumber <= maxRetries) { await delay(delayInMs); return _retryWithExponentialBackoff( f, { maxRetries, delayInMs: backoffFactor * delayInMs, backoffFactor }, newErrors ); } if (tryNumber === 1) { throw error; } throw new RetryError({ message: `Failed after ${tryNumber} attempts with non-retryable error: '${errorMessage}'`, reason: "errorNotRetryable", errors: newErrors }); } } // core/prompt/convert-to-language-model-prompt.ts import { getErrorMessage as getErrorMessage2 } from "@ai-sdk/provider-utils"; // util/download-error.ts import { AISDKError as AISDKError2 } from "@ai-sdk/provider"; var name2 = "AI_DownloadError"; var marker2 = `vercel.ai.error.${name2}`; var symbol2 = Symbol.for(marker2); var _a2; var DownloadError = class extends AISDKError2 { constructor({ url, statusCode, statusText, cause, message = cause == null ? `Failed to download ${url}: ${statusCode} ${statusText}` : `Failed to download ${url}: ${cause}` }) { super({ name: name2, message, cause }); this[_a2] = true; this.url = url; this.statusCode = statusCode; this.statusText = statusText; } static isInstance(error) { return AISDKError2.hasMarker(error, marker2); } /** * @deprecated use `isInstance` instead */ static isDownloadError(error) { return error instanceof Error && error.name === name2 && typeof error.url === "string" && (error.statusCode == null || typeof error.statusCode === "number") && (error.statusText == null || typeof error.statusText === "string"); } /** * @deprecated Do not use this method. It will be removed in the next major version. */ toJSON() { return { name: this.name, message: this.message, url: this.url, statusCode: this.statusCode, statusText: this.statusText, cause: this.cause }; } }; _a2 = symbol2; // util/download.ts async function download({ url, fetchImplementation = fetch }) { var _a8; const urlText = url.toString(); try { const response = await fetchImplementation(urlText); if (!response.ok) { throw new DownloadError({ url: urlText, statusCode: response.status, statusText: response.statusText }); } return { data: new Uint8Array(await response.arrayBuffer()), mimeType: (_a8 = response.headers.get("content-type")) != null ? _a8 : void 0 }; } catch (error) { if (DownloadError.isInstance(error)) { throw error; } throw new DownloadError({ url: urlText, cause: error }); } } // core/util/detect-image-mimetype.ts var mimeTypeSignatures = [ { mimeType: "image/gif", bytes: [71, 73, 70] }, { mimeType: "image/png", bytes: [137, 80, 78, 71] }, { mimeType: "image/jpeg", bytes: [255, 216] }, { mimeType: "image/webp", bytes: [82, 73, 70, 70] } ]; function detectImageMimeType(image) { for (const { bytes, mimeType } of mimeTypeSignatures) { if (image.length >= bytes.length && bytes.every((byte, index) => image[index] === byte)) { return mimeType; } } return void 0; } // core/prompt/data-content.ts import { convertBase64ToUint8Array, convertUint8ArrayToBase64 } from "@ai-sdk/provider-utils"; // core/prompt/invalid-data-content-error.ts import { AISDKError as AISDKError3 } from "@ai-sdk/provider"; var name3 = "AI_InvalidDataContentError"; var marker3 = `vercel.ai.error.${name3}`; var symbol3 = Symbol.for(marker3); var _a3; var InvalidDataContentError = class extends AISDKError3 { constructor({ content, cause, message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.` }) { super({ name: name3, message, cause }); this[_a3] = true; this.content = content; } static isInstance(error) { return AISDKError3.hasMarker(error, marker3); } /** * @deprecated use `isInstance` instead */ static isInvalidDataContentError(error) { return error instanceof Error && error.name === name3 && error.content != null; } /** * @deprecated Do not use this method. It will be removed in the next major version. */ toJSON() { return { name: this.name, message: this.message, stack: this.stack, cause: this.cause, content: this.content }; } }; _a3 = symbol3; // core/prompt/data-content.ts function convertDataContentToUint8Array(content) { if (content instanceof Uint8Array) { return content; } if (typeof content === "string") { try { return convertBase64ToUint8Array(content); } catch (error) { throw new InvalidDataContentError({ message: "Invalid data content. Content string is not a base64-encoded media.", content, cause: error }); } } if (content instanceof ArrayBuffer) { return new Uint8Array(content); } throw new InvalidDataContentError({ content }); } // core/prompt/invalid-message-role-error.ts import { AISDKError as AISDKError4 } from "@ai-sdk/provider"; var name4 = "AI_InvalidMessageRoleError"; var marker4 = `vercel.ai.error.${name4}`; var symbol4 = Symbol.for(marker4); var _a4; var InvalidMessageRoleError = class extends AISDKError4 { constructor({ role, message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".` }) { super({ name: name4, message }); this[_a4] = true; this.role = role; } static isInstance(error) { return AISDKError4.hasMarker(error, marker4); } /** * @deprecated use `isInstance` instead */ static isInvalidMessageRoleError(error) { return error instanceof Error && error.name === name4 && typeof error.role === "string"; } /** * @deprecated Do not use this method. It will be removed in the next major version. */ toJSON() { return { name: this.name, message: this.message, stack: this.stack, role: this.role }; } }; _a4 = symbol4; // core/prompt/convert-to-language-model-prompt.ts async function convertToLanguageModelPrompt({ prompt, modelSupportsImageUrls = true, downloadImplementation = download }) { const languageModelMessages = []; if (prompt.system != null) { languageModelMessages.push({ role: "system", content: prompt.system }); } const downloadedImages = modelSupportsImageUrls || prompt.messages == null ? null : await downloadImages(prompt.messages, downloadImplementation); const promptType = prompt.type; switch (promptType) { case "prompt": { languageModelMessages.push({ role: "user", content: [{ type: "text", text: prompt.prompt }] }); break; } case "messages": { languageModelMessages.push( ...prompt.messages.map( (message) => convertToLanguageModelMessage(message, downloadedImages) ) ); break; } default: { const _exhaustiveCheck = promptType; throw new Error(`Unsupported prompt type: ${_exhaustiveCheck}`); } } return languageModelMessages; } function convertToLanguageModelMessage(message, downloadedImages) { const role = message.role; switch (role) { case "system": { return { role: "system", content: message.content }; } case "user": { if (typeof message.content === "string") { return { role: "user", content: [{ type: "text", text: message.content }] }; } return { role: "user", content: message.content.map( (part) => { var _a8, _b, _c; switch (part.type) { case "text": { return part; } case "image": { if (part.image instanceof URL) { if (downloadedImages == null) { return { type: "image", image: part.image, mimeType: part.mimeType }; } else { const downloadedImage = downloadedImages[part.image.toString()]; return { type: "image", image: downloadedImage.data, mimeType: (_a8 = part.mimeType) != null ? _a8 : downloadedImage.mimeType }; } } if (typeof part.image === "string") { try { const url = new URL(part.image); switch (url.protocol) { case "http:": case "https:": { if (downloadedImages == null) { return { type: "image", image: url, mimeType: part.mimeType }; } else { const downloadedImage = downloadedImages[part.image]; return { type: "image", image: downloadedImage.data, mimeType: (_b = part.mimeType) != null ? _b : downloadedImage.mimeType }; } } case "data:": { try { const [header, base64Content] = part.image.split(","); const mimeType = header.split(";")[0].split(":")[1]; if (mimeType == null || base64Content == null) { throw new Error("Invalid data URL format"); } return { type: "image", image: convertDataContentToUint8Array(base64Content), mimeType }; } catch (error) { throw new Error( `Error processing data URL: ${getErrorMessage2( message )}` ); } } default: { throw new Error( `Unsupported URL protocol: ${url.protocol}` ); } } } catch (_ignored) { } } const imageUint8 = convertDataContentToUint8Array(part.image); return { type: "image", image: imageUint8, mimeType: (_c = part.mimeType) != null ? _c : detectImageMimeType(imageUint8) }; } } } ) }; } case "assistant": { if (typeof message.content === "string") { return { role: "assistant", content: [{ type: "text", text: message.content }] }; } return { role: "assistant", content: message.content.filter( // remove empty text parts: (part) => part.type !== "text" || part.text !== "" ) }; } case "tool": { return message; } default: { const _exhaustiveCheck = role; throw new InvalidMessageRoleError({ role: _exhaustiveCheck }); } } } async function downloadImages(messages, downloadImplementation) { const urls = messages.filter((message) => message.role === "user").map((message) => message.content).filter( (content) => Array.isArray(content) ).flat().filter((part) => part.type === "image").map((part) => part.image).map( (part) => ( // support string urls in image parts: typeof part === "string" && (part.startsWith("http:") || part.startsWith("https:")) ? new URL(part) : part ) ).filter((image) => image instanceof URL); const downloadedImages = await Promise.all( urls.map(async (url) => ({ url, data: await downloadImplementation({ url }) })) ); return Object.fromEntries( downloadedImages.map(({ url, data }) => [url.toString(), data]) ); } // core/prompt/get-validated-prompt.ts import { InvalidPromptError } from "@ai-sdk/provider"; function getValidatedPrompt(prompt) { if (prompt.prompt == null && prompt.messages == null) { throw new InvalidPromptError({ prompt, message: "prompt or messages must be defined" }); } if (prompt.prompt != null && prompt.messages != null) { throw new InvalidPromptError({ prompt, message: "prompt and messages cannot be defined at the same time" }); } if (prompt.messages != null) { for (const message of prompt.messages) { if (message.role === "system" && typeof message.content !== "string") { throw new InvalidPromptError({ prompt, message: "system message content must be a string" }); } } } return prompt.prompt != null ? { type: "prompt", prompt: prompt.prompt, messages: void 0, system: prompt.system } : { type: "messages", prompt: void 0, messages: prompt.messages, // only possible case bc of checks above system: prompt.system }; } // errors/invalid-argument-error.ts import { AISDKError as AISDKError5 } from "@ai-sdk/provider"; var name5 = "AI_InvalidArgumentError"; var marker5 = `vercel.ai.error.${name5}`; var symbol5 = Symbol.for(marker5); var _a5; var InvalidArgumentError = class extends AISDKError5 { constructor({ parameter, value, message }) { super({ name: name5, message: `Invalid argument for parameter ${parameter}: ${message}` }); this[_a5] = true; this.parameter = parameter; this.value = value; } static isInstance(error) { return AISDKError5.hasMarker(error, marker5); } /** * @deprecated use `isInstance` instead */ static isInvalidArgumentError(error) { return error instanceof Error && error.name === name5 && typeof error.parameter === "string" && typeof error.value === "string"; } toJSON() { return { name: this.name, message: this.message, stack: this.stack, parameter: this.parameter, value: this.value }; } }; _a5 = symbol5; // core/prompt/prepare-call-settings.ts function prepareCallSettings({ maxTokens, temperature, topP, presencePenalty, frequencyPenalty, stopSequences, seed, maxRetries }) { if (maxTokens != null) { if (!Number.isInteger(maxTokens)) { throw new InvalidArgumentError({ parameter: "maxTokens", value: maxTokens, message: "maxTokens must be an integer" }); } if (maxTokens < 1) { throw new InvalidArgumentError({ parameter: "maxTokens", value: maxTokens, message: "maxTokens must be >= 1" }); } } if (temperature != null) { if (typeof temperature !== "number") { throw new InvalidArgumentError({ parameter: "temperature", value: temperature, message: "temperature must be a number" }); } } if (topP != null) { if (typeof topP !== "number") { throw new InvalidArgumentError({ parameter: "topP", value: topP, message: "topP must be a number" }); } } if (presencePenalty != null) { if (typeof presencePenalty !== "number") { throw new InvalidArgumentError({ parameter: "presencePenalty", value: presencePenalty, message: "presencePenalty must be a number" }); } } if (frequencyPenalty != null) { if (typeof frequencyPenalty !== "number") { throw new InvalidArgumentError({ parameter: "frequencyPenalty", value: frequencyPenalty, message: "frequencyPenalty must be a number" }); } } if (seed != null) { if (!Number.isInteger(seed)) { throw new InvalidArgumentError({ parameter: "seed", value: seed, message: "seed must be an integer" }); } } if (maxRetries != null) { if (!Number.isInteger(maxRetries)) { throw new InvalidArgumentError({ parameter: "maxRetries", value: maxRetries, message: "maxRetries must be an integer" }); } if (maxRetries < 0) { throw new InvalidArgumentError({ parameter: "maxRetries", value: maxRetries, message: "maxRetries must be >= 0" }); } } return { maxTokens, temperature: temperature != null ? temperature : 0, topP, presencePenalty, frequencyPenalty, stopSequences: stopSequences != null && stopSequences.length > 0 ? stopSequences : void 0, seed, maxRetries: maxRetries != null ? maxRetries : 2 }; } // core/types/token-usage.ts function calculateCompletionTokenUsage(usage) { return { promptTokens: usage.promptTokens, completionTokens: usage.completionTokens, totalTokens: usage.promptTokens + usage.completionTokens }; } // core/util/schema.ts import { validatorSymbol } from "@ai-sdk/provider-utils"; import zodToJsonSchema from "zod-to-json-schema"; 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); } function zodSchema(zodSchema2) { return jsonSchema( // we assume that zodToJsonSchema will return a valid JSONSchema7: zodToJsonSchema(zodSchema2), { validate: (value) => { const result = zodSchema2.safeParse(value); return result.success ? { success: true, value: result.data } : { success: false, error: result.error }; } } ); } // core/util/is-non-empty-object.ts function isNonEmptyObject(object) { return object != null && Object.keys(object).length > 0; } // core/prompt/prepare-tools-and-tool-choice.ts function prepareToolsAndToolChoice({ tools, toolChoice }) { if (!isNonEmptyObject(tools)) { return { tools: void 0, toolChoice: void 0 }; } return { tools: Object.entries(tools).map(([name8, tool]) => ({ type: "function", name: name8, description: tool.description, parameters: asSchema(tool.parameters).jsonSchema })), toolChoice: toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : { type: "tool", toolName: toolChoice.toolName } }; } // errors/invalid-tool-arguments-error.ts import { AISDKError as AISDKError6, getErrorMessage as getErrorMessage3 } from "@ai-sdk/provider"; var name6 = "AI_InvalidToolArgumentsError"; var marker6 = `vercel.ai.error.${name6}`; var symbol6 = Symbol.for(marker6); var _a6; var InvalidToolArgumentsError = class extends AISDKError6 { constructor({ toolArgs, toolName, cause, message = `Invalid arguments for tool ${toolName}: ${getErrorMessage3( cause )}` }) { super({ name: name6, message, cause }); this[_a6] = true; this.toolArgs = toolArgs; this.toolName = toolName; } static isInstance(error) { return AISDKError6.hasMarker(error, marker6); } /** * @deprecated use `isInstance` instead */ static isInvalidToolArgumentsError(error) { return error instanceof Error && error.name === name6 && typeof error.toolName === "string" && typeof error.toolArgs === "string"; } /** * @deprecated Do not use this method. It will be removed in the next major version. */ toJSON() { return { name: this.name, message: this.message, cause: this.cause, stack: this.stack, toolName: this.toolName, toolArgs: this.toolArgs }; } }; _a6 = symbol6; // errors/no-such-tool-error.ts import { AISDKError as AISDKError7 } from "@ai-sdk/provider"; var name7 = "AI_NoSuchToolError"; var marker7 = `vercel.ai.error.${name7}`; var symbol7 = Symbol.for(marker7); var _a7; var NoSuchToolError = class extends AISDKError7 { constructor({ toolName, availableTools = void 0, message = `Model tried to call unavailable tool '${toolName}'. ${availableTools === void 0 ? "No tools are available." : `Available tools: ${availableTools.join(", ")}.`}` }) { super({ name: name7, message }); this[_a7] = true; this.toolName = toolName; this.availableTools = availableTools; } static isInstance(error) { return AISDKError7.hasMarker(error, marker7); } /** * @deprecated use `isInstance` instead */ static isNoSuchToolError(error) { return error instanceof Error && error.name === name7 && "toolName" in error && error.toolName != void 0 && typeof error.name === "string"; } /** * @deprecated Do not use this method. It will be removed in the next major version. */ toJSON() { return { name: this.name, message: this.message, stack: this.stack, toolName: this.toolName, availableTools: this.availableTools }; } }; _a7 = symbol7; // streams/ai-stream.ts import { createParser } from "eventsource-parser"; function createEventStreamTransformer(customParser) { const textDecoder = new TextDecoder(); let eventSourceParser; return new TransformStream({ async start(controller) { eventSourceParser = createParser( (event) => { if ("data" in event && event.type === "event" && event.data === "[DONE]" || // Replicate doesn't send [DONE] but does send a 'done' event // @see https://replicate.com/docs/streaming event.event === "done") { controller.terminate(); return; } if ("data" in event) { const parsedMessage = customParser ? customParser(event.data, { event: event.event }) : event.data; if (parsedMessage) controller.enqueue(parsedMessage); } } ); }, transform(chunk) { eventSourceParser.feed(textDecoder.decode(chunk)); } }); } function createCallbacksTransformer(cb) { const textEncoder = new TextEncoder(); let aggregatedResponse = ""; const callbacks = cb || {}; return new TransformStream({ async start() { if (callbacks.onStart) await callbacks.onStart(); }, async transform(message, controller) { const content = typeof message === "string" ? message : message.content; controller.enqueue(textEncoder.encode(content)); aggregatedResponse += content; if (callbacks.onToken) await callbacks.onToken(content); if (callbacks.onText && typeof message === "string") { await callbacks.onText(message); } }, async flush() { const isOpenAICallbacks = isOfTypeOpenAIStreamCallbacks(callbacks); if (callbacks.onCompletion) { await callbacks.onCompletion(aggregatedResponse); } if (callbacks.onFinal && !isOpenAICallbacks) { await callbacks.onFinal(aggregatedResponse); } } }); } function isOfTypeOpenAIStreamCallbacks(callbacks) { return "experimental_onFunctionCall" in callbacks; } function trimStartOfStreamHelper() { let isStreamStart = true; return (text) => { if (isStreamStart) { text = text.trimStart(); if (text) isStreamStart = false; } return text; }; } function AIStream(response, customParser, callbacks) { if (!response.ok) { if (response.body) { const reader = response.body.getReader(); return new ReadableStream({ async start(controller) { const { done, value } = await reader.read(); if (!done) { const errorText = new TextDecoder().decode(value); controller.error(new Error(`Response error: ${errorText}`)); } } }); } else { return new ReadableStream({ start(controller) { controller.error(new Error("Response error: No response body")); } }); } } const responseBodyStream = response.body || createEmptyReadableStream(); return responseBodyStream.pipeThrough(createEventStreamTransformer(customParser)).pipeThrough(createCallbacksTransformer(callbacks)); } function createEmptyReadableStream() { return new ReadableStream({ start(controller) { controller.close(); } }); } function readableFromAsyncIterable(iterable) { let it = iterable[Symbol.asyncIterator](); return new ReadableStream({ async pull(controller) { const { done, value } = await it.next(); if (done) controller.close(); else controller.enqueue(value); }, async cancel(reason) { var _a8; await ((_a8 = it.return) == null ? void 0 : _a8.call(it, reason)); } }); } // streams/stream-data.ts import { formatStreamPart } from "@ai-sdk/ui-utils"; var STREAM_DATA_WARNING_TIME_MS = 15 * 1e3; function createStreamDataTransformer() { const encoder = new TextEncoder(); const decoder = new TextDecoder(); return new TransformStream({ transform: async (chunk, controller) => { const message = decoder.decode(chunk); controller.enqueue(encoder.encode(formatStreamPart("text", message))); } }); } // streams/openai-stream.ts import { createChunkDecoder, formatStreamPart as formatStreamPart2 } from "@ai-sdk/ui-utils"; function parseOpenAIStream() { const extract = chunkToText(); return (data) => extract(JSON.parse(data)); } async function* streamable(stream) { const extract = chunkToText(); for await (let chunk of stream) { if ("promptFilterResults" in chunk) { chunk = { id: chunk.id, created: chunk.created.getDate(), object: chunk.object, // not exposed by Azure API model: chunk.model, // not exposed by Azure API choices: chunk.choices.map((choice) => { var _a8, _b, _c, _d, _e, _f, _g; return { delta: { content: (_a8 = choice.delta) == null ? void 0 : _a8.content, function_call: (_b = choice.delta) == null ? void 0 : _b.functionCall, role: (_c = choice.delta) == null ? void 0 : _c.role, tool_calls: ((_e = (_d = choice.delta) == null ? void 0 : _d.toolCalls) == null ? void 0 : _e.length) ? (_g = (_f = choice.delta) == null ? void 0 : _f.toolCalls) == null ? void 0 : _g.map((toolCall, index) => ({ index, id: toolCall.id, function: toolCall.function, type: toolCall.type })) : void 0 }, finish_reason: choice.finishReason, index: choice.index }; }) }; } const text = extract(chunk); if (text) yield text; } } function chunkToText() { const trimStartOfStream = trimStartOfStreamHelper(); let isFunctionStreamingIn; return (json) => { var _a8, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r; if (isChatCompletionChunk(json)) { const delta = (_a8 = json.choices[0]) == null ? void 0 : _a8.delta; if ((_b = delta.function_call) == null ? void 0 : _b.name) { isFunctionStreamingIn = true; return { isText: false, content: `{"function_call": {"name": "${delta.function_call.name}", "arguments": "` }; } else if ((_e = (_d = (_c = delta.tool_calls) == null ? void 0 : _c[0]) == null ? void 0 : _d.function) == null ? void 0 : _e.name) { isFunctionStreamingIn = true; const toolCall = delta.tool_calls[0]; if (toolCall.index === 0) { return { isText: false, content: `{"tool_calls":[ {"id": "${toolCall.id}", "type": "function", "function": {"name": "${(_f = toolCall.function) == null ? void 0 : _f.name}", "arguments": "` }; } else { return { isText: false, content: `"}}, {"id": "${toolCall.id}", "type": "function", "function": {"name": "${(_g = toolCall.function) == null ? void 0 : _g.name}", "arguments": "` }; } } else if ((_h = delta.function_call) == null ? void 0 : _h.arguments) { return { isText: false, content: cleanupArguments((_i = delta.function_call) == null ? void 0 : _i.arguments) }; } else if ((_l = (_k = (_j = delta.tool_calls) == null ? void 0 : _j[0]) == null ? void 0 : _k.function) == null ? void 0 : _l.arguments) { return { isText: false, content: cleanupArguments((_o = (_n = (_m = delta.tool_calls) == null ? void 0 : _m[0]) == null ? void 0 : _n.function) == null ? void 0 : _o.arguments) }; } else if (isFunctionStreamingIn && (((_p = json.choices[0]) == null ? void 0 : _p.finish_reason) === "function_call" || ((_q = json.choices[0]) == null ? void 0 : _q.finish_reason) === "stop")) { isFunctionStreamingIn = false; return { isText: false, content: '"}}' }; } else if (isFunctionStreamingIn && ((_r = json.choices[0]) == null ? void 0 : _r.finish_reason) === "tool_calls") { isFunctionStreamingIn = false; return { isText: false, content: '"}}]}' }; } } const text = trimStartOfStream( isChatCompletionChunk(json) && json.choices[0].delta.content ? json.choices[0].delta.content : isCompletion(json) ? json.choices[0].text : "" ); return text; }; function cleanupArguments(argumentChunk) { let escapedPartialJson = argumentChunk.replace(/\\/g, "\\\\").replace(/\//g, "\\/").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/\f/g, "\\f"); return `${escapedPartialJson}`; } } var __internal__OpenAIFnMessagesSymbol = Symbol( "internal_openai_fn_messages" ); function isChatCompletionChunk(data) { return "choices" in data && data.choices && data.choices[0] && "delta" in data.choices[0]; } function isCompletion(data) { return "choices" in data && data.choices && data.choices[0] && "text" in data.choices[0]; } function OpenAIStream(res, callbacks) { const cb = callbacks; let stream; if (Symbol.asyncIterator in res) { stream = readableFromAsyncIterable(streamable(res)).pipeThrough( createCallbacksTransformer( (cb == null ? void 0 : cb.experimental_onFunctionCall) || (cb == null ? void 0 : cb.experimental_onToolCall) ? { ...cb, onFinal: void 0 } : { ...cb } ) ); } else { stream = AIStream( res, parseOpenAIStream(), (cb == null ? void 0 : cb.experimental_onFunctionCall) || (cb == null ? void 0 : cb.experimental_onToolCall) ? { ...cb, onFinal: void 0 } : { ...cb } ); } if (cb && (cb.experimental_onFunctionCall || cb.experimental_onToolCall)) { const functionCallTransformer = createFunctionCallTransformer(cb); return stream.pipeThrough(functionCallTransformer); } else { return stream.pipeThrough(createStreamDataTransformer()); } } function createFunctionCallTransformer(callbacks) { const textEncoder = new TextEncoder(); let isFirstChunk = true; let aggregatedResponse = ""; let aggregatedFinalCompletionResponse = ""; let isFunctionStreamingIn = false; let functionCallMessages = callbacks[__internal__OpenAIFnMessagesSymbol] || []; const decode = createChunkDecoder(); return new TransformStream({ async transform(chunk, controller) { const message = decode(chunk); aggregatedFinalCompletionResponse += message; const shouldHandleAsFunction = isFirstChunk && (message.startsWith('{"function_call":') || message.startsWith('{"tool_calls":')); if (shouldHandleAsFunction) { isFunctionStreamingIn = true; aggregatedResponse += message; isFirstChunk = false; return; } if (!isFunctionStreamingIn) { controller.enqueue( textEncoder.encode(formatStreamPart2("text", message)) ); return; } else { aggregatedResponse += message; } }, async flush(controller) { try { if (!isFirstChunk && isFunctionStreamingIn && (callbacks.experimental_onFunctionCall || callbacks.experimental_onToolCall)) { isFunctionStreamingIn = false; const payload = JSON.parse(aggregatedResponse); let newFunctionCallMessages = [ ...functionCallMessages ]; let functionResponse = void 0; if (callbacks.experimental_onFunctionCall) { if (payload.function_call === void 0) { console.warn( "experimental_onFunctionCall should not be defined when using tools" ); } const argumentsPayload = JSON.parse( payload.function_call.arguments ); functionResponse = await callbacks.experimental_onFunctionCall( { name: payload.function_call.name, arguments: argumentsPayload }, (result) => { newFunctionCallMessages = [ ...functionCallMessages, { role: "assistant", content: "", function_call: payload.function_call }, { role: "function", name: payload.function_call.name, content: JSON.stringify(result) } ]; return newFunctionCallMessages; } ); } if (callbacks.experimental_onToolCall) { const toolCalls = { tools: [] }; for (const tool of payload.tool_calls) { toolCalls.tools.push({ id: tool.id, type: "function", func: { name: tool.function.name, arguments: JSON.parse(tool.function.arguments) } }); } let responseIndex = 0; try { functionResponse = await callbacks.experimental_onToolCall( toolCalls, (result) => { if (result) { const { tool_call_id, function_name, tool_call_result } = result; newFunctionCallMessages = [ ...newFunctionCallMessages, // Only append the assistant message if it's the first response ...responseIndex === 0 ? [ { role: "assistant", content: "", tool_calls: payload.tool_calls.map( (tc) => ({