ai
Version:
AI SDK by Vercel - The AI Toolkit for TypeScript and JavaScript
1,699 lines (1,656 loc) • 63.5 kB
JavaScript
// 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: JSON.parse(JSON.stringify(state)),
// deep clone object
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 _a9, _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 = (_a9 = store.options).onSetAIState) == null ? void 0 : _b.call(_a9, {
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/provider.tsx
import * as React from "react";
import { InternalAIProvider } from "./rsc-shared.mjs";
import { jsx } from "react/jsx-runtime";
async function innerAction({
action,
options
}, state, ...args) {
"use server";
return await withAIState(
{
state,
options
},
async () => {
const result = await action(...args);
sealMutableAIState();
return [getAIStateDeltaPromise(), result];
}
);
}
function wrapAction(action, options) {
return innerAction.bind(null, { action, options });
}
function createAI({
actions,
initialAIState,
initialUIState,
onSetAIState,
onGetUIState
}) {
const wrappedActions = {};
for (const name9 in actions) {
wrappedActions[name9] = wrapAction(actions[name9], {
onSetAIState
});
}
const wrappedSyncUIState = onGetUIState ? wrapAction(onGetUIState, {}) : void 0;
const AI = async (props) => {
var _a9, _b;
if ("useState" in React) {
throw new Error(
"This component can only be used inside Server Components."
);
}
let uiState = (_a9 = props.initialUIState) != null ? _a9 : initialUIState;
let aiState = (_b = props.initialAIState) != null ? _b : initialAIState;
let aiStateDelta = void 0;
if (wrappedSyncUIState) {
const [newAIStateDelta, newUIState] = await wrappedSyncUIState(aiState);
if (newUIState !== void 0) {
aiStateDelta = newAIStateDelta;
uiState = newUIState;
}
}
return /* @__PURE__ */ jsx(
InternalAIProvider,
{
wrappedActions,
wrappedSyncUIState,
initialUIState: uiState,
initialAIState: aiState,
initialAIStatePatch: aiStateDelta,
children: props.children
}
);
};
return AI;
}
// rsc/stream-ui/stream-ui.tsx
import { safeParseJSON } from "@ai-sdk/provider-utils";
// util/download-error.ts
import { AISDKError } from "@ai-sdk/provider";
var name = "AI_DownloadError";
var marker = `vercel.ai.error.${name}`;
var symbol = Symbol.for(marker);
var _a;
var DownloadError = class extends AISDKError {
constructor({
url,
statusCode,
statusText,
cause,
message = cause == null ? `Failed to download ${url}: ${statusCode} ${statusText}` : `Failed to download ${url}: ${cause}`
}) {
super({ name, message, cause });
this[_a] = true;
this.url = url;
this.statusCode = statusCode;
this.statusText = statusText;
}
static isInstance(error) {
return AISDKError.hasMarker(error, marker);
}
};
_a = symbol;
// util/download.ts
async function download({ url }) {
var _a9;
const urlText = url.toString();
try {
const response = await fetch(urlText);
if (!response.ok) {
throw new DownloadError({
url: urlText,
statusCode: response.status,
statusText: response.statusText
});
}
return {
data: new Uint8Array(await response.arrayBuffer()),
mimeType: (_a9 = response.headers.get("content-type")) != null ? _a9 : void 0
};
} catch (error) {
if (DownloadError.isInstance(error)) {
throw error;
}
throw new DownloadError({ url: urlText, cause: error });
}
}
// core/util/detect-mimetype.ts
import { convertBase64ToUint8Array } from "@ai-sdk/provider-utils";
var imageMimeTypeSignatures = [
{
mimeType: "image/gif",
bytesPrefix: [71, 73, 70],
base64Prefix: "R0lG"
},
{
mimeType: "image/png",
bytesPrefix: [137, 80, 78, 71],
base64Prefix: "iVBORw"
},
{
mimeType: "image/jpeg",
bytesPrefix: [255, 216],
base64Prefix: "/9j/"
},
{
mimeType: "image/webp",
bytesPrefix: [82, 73, 70, 70],
base64Prefix: "UklGRg"
},
{
mimeType: "image/bmp",
bytesPrefix: [66, 77],
base64Prefix: "Qk"
},
{
mimeType: "image/tiff",
bytesPrefix: [73, 73, 42, 0],
base64Prefix: "SUkqAA"
},
{
mimeType: "image/tiff",
bytesPrefix: [77, 77, 0, 42],
base64Prefix: "TU0AKg"
},
{
mimeType: "image/avif",
bytesPrefix: [
0,
0,
0,
32,
102,
116,
121,
112,
97,
118,
105,
102
],
base64Prefix: "AAAAIGZ0eXBhdmlm"
},
{
mimeType: "image/heic",
bytesPrefix: [
0,
0,
0,
32,
102,
116,
121,
112,
104,
101,
105,
99
],
base64Prefix: "AAAAIGZ0eXBoZWlj"
}
];
var stripID3 = (data) => {
const bytes = typeof data === "string" ? convertBase64ToUint8Array(data) : data;
const id3Size = (bytes[6] & 127) << 21 | (bytes[7] & 127) << 14 | (bytes[8] & 127) << 7 | bytes[9] & 127;
return bytes.slice(id3Size + 10);
};
function stripID3TagsIfPresent(data) {
const hasId3 = typeof data === "string" && data.startsWith("SUQz") || typeof data !== "string" && data.length > 10 && data[0] === 73 && // 'I'
data[1] === 68 && // 'D'
data[2] === 51;
return hasId3 ? stripID3(data) : data;
}
function detectMimeType({
data,
signatures
}) {
const processedData = stripID3TagsIfPresent(data);
for (const signature of signatures) {
if (typeof processedData === "string" ? processedData.startsWith(signature.base64Prefix) : processedData.length >= signature.bytesPrefix.length && signature.bytesPrefix.every(
(byte, index) => processedData[index] === byte
)) {
return signature.mimeType;
}
}
return void 0;
}
// core/prompt/data-content.ts
import {
convertBase64ToUint8Array as convertBase64ToUint8Array2,
convertUint8ArrayToBase64
} from "@ai-sdk/provider-utils";
// core/prompt/invalid-data-content-error.ts
import { AISDKError as AISDKError2 } from "@ai-sdk/provider";
var name2 = "AI_InvalidDataContentError";
var marker2 = `vercel.ai.error.${name2}`;
var symbol2 = Symbol.for(marker2);
var _a2;
var InvalidDataContentError = class extends AISDKError2 {
constructor({
content,
cause,
message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`
}) {
super({ name: name2, message, cause });
this[_a2] = true;
this.content = content;
}
static isInstance(error) {
return AISDKError2.hasMarker(error, marker2);
}
};
_a2 = symbol2;
// core/prompt/data-content.ts
import { z } from "zod";
var dataContentSchema = z.union([
z.string(),
z.instanceof(Uint8Array),
z.instanceof(ArrayBuffer),
z.custom(
// Buffer might not be available in some environments such as CloudFlare:
(value) => {
var _a9, _b;
return (_b = (_a9 = globalThis.Buffer) == null ? void 0 : _a9.isBuffer(value)) != null ? _b : false;
},
{ message: "Must be a Buffer" }
)
]);
function convertDataContentToBase64String(content) {
if (typeof content === "string") {
return content;
}
if (content instanceof ArrayBuffer) {
return convertUint8ArrayToBase64(new Uint8Array(content));
}
return convertUint8ArrayToBase64(content);
}
function convertDataContentToUint8Array(content) {
if (content instanceof Uint8Array) {
return content;
}
if (typeof content === "string") {
try {
return convertBase64ToUint8Array2(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 });
}
function convertUint8ArrayToText(uint8Array) {
try {
return new TextDecoder().decode(uint8Array);
} catch (error) {
throw new Error("Error decoding Uint8Array to text");
}
}
// core/prompt/invalid-message-role-error.ts
import { AISDKError as AISDKError3 } from "@ai-sdk/provider";
var name3 = "AI_InvalidMessageRoleError";
var marker3 = `vercel.ai.error.${name3}`;
var symbol3 = Symbol.for(marker3);
var _a3;
var InvalidMessageRoleError = class extends AISDKError3 {
constructor({
role,
message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".`
}) {
super({ name: name3, message });
this[_a3] = true;
this.role = role;
}
static isInstance(error) {
return AISDKError3.hasMarker(error, marker3);
}
};
_a3 = symbol3;
// core/prompt/split-data-url.ts
function splitDataUrl(dataUrl) {
try {
const [header, base64Content] = dataUrl.split(",");
return {
mimeType: header.split(";")[0].split(":")[1],
base64Content
};
} catch (error) {
return {
mimeType: void 0,
base64Content: void 0
};
}
}
// core/prompt/convert-to-language-model-prompt.ts
async function convertToLanguageModelPrompt({
prompt,
modelSupportsImageUrls = true,
modelSupportsUrl = () => false,
downloadImplementation = download
}) {
const downloadedAssets = await downloadAssets(
prompt.messages,
downloadImplementation,
modelSupportsImageUrls,
modelSupportsUrl
);
return [
...prompt.system != null ? [{ role: "system", content: prompt.system }] : [],
...prompt.messages.map(
(message) => convertToLanguageModelMessage(message, downloadedAssets)
)
];
}
function convertToLanguageModelMessage(message, downloadedAssets) {
var _a9, _b, _c, _d, _e, _f;
const role = message.role;
switch (role) {
case "system": {
return {
role: "system",
content: message.content,
providerMetadata: (_a9 = message.providerOptions) != null ? _a9 : message.experimental_providerMetadata
};
}
case "user": {
if (typeof message.content === "string") {
return {
role: "user",
content: [{ type: "text", text: message.content }],
providerMetadata: (_b = message.providerOptions) != null ? _b : message.experimental_providerMetadata
};
}
return {
role: "user",
content: message.content.map((part) => convertPartToLanguageModelPart(part, downloadedAssets)).filter((part) => part.type !== "text" || part.text !== ""),
providerMetadata: (_c = message.providerOptions) != null ? _c : message.experimental_providerMetadata
};
}
case "assistant": {
if (typeof message.content === "string") {
return {
role: "assistant",
content: [{ type: "text", text: message.content }],
providerMetadata: (_d = message.providerOptions) != null ? _d : message.experimental_providerMetadata
};
}
return {
role: "assistant",
content: message.content.filter(
// remove empty text parts:
(part) => part.type !== "text" || part.text !== ""
).map((part) => {
var _a10;
const providerOptions = (_a10 = part.providerOptions) != null ? _a10 : part.experimental_providerMetadata;
switch (part.type) {
case "file": {
return {
type: "file",
data: part.data instanceof URL ? part.data : convertDataContentToBase64String(part.data),
filename: part.filename,
mimeType: part.mimeType,
providerMetadata: providerOptions
};
}
case "reasoning": {
return {
type: "reasoning",
text: part.text,
signature: part.signature,
providerMetadata: providerOptions
};
}
case "redacted-reasoning": {
return {
type: "redacted-reasoning",
data: part.data,
providerMetadata: providerOptions
};
}
case "text": {
return {
type: "text",
text: part.text,
providerMetadata: providerOptions
};
}
case "tool-call": {
return {
type: "tool-call",
toolCallId: part.toolCallId,
toolName: part.toolName,
args: part.args,
providerMetadata: providerOptions
};
}
}
}),
providerMetadata: (_e = message.providerOptions) != null ? _e : message.experimental_providerMetadata
};
}
case "tool": {
return {
role: "tool",
content: message.content.map((part) => {
var _a10;
return {
type: "tool-result",
toolCallId: part.toolCallId,
toolName: part.toolName,
result: part.result,
content: part.experimental_content,
isError: part.isError,
providerMetadata: (_a10 = part.providerOptions) != null ? _a10 : part.experimental_providerMetadata
};
}),
providerMetadata: (_f = message.providerOptions) != null ? _f : message.experimental_providerMetadata
};
}
default: {
const _exhaustiveCheck = role;
throw new InvalidMessageRoleError({ role: _exhaustiveCheck });
}
}
}
async function downloadAssets(messages, downloadImplementation, modelSupportsImageUrls, modelSupportsUrl) {
const urls = messages.filter((message) => message.role === "user").map((message) => message.content).filter(
(content) => Array.isArray(content)
).flat().filter(
(part) => part.type === "image" || part.type === "file"
).filter(
(part) => !(part.type === "image" && modelSupportsImageUrls === true)
).map((part) => part.type === "image" ? part.image : part.data).map(
(part) => (
// support string urls:
typeof part === "string" && (part.startsWith("http:") || part.startsWith("https:")) ? new URL(part) : part
)
).filter((image) => image instanceof URL).filter((url) => !modelSupportsUrl(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])
);
}
function convertPartToLanguageModelPart(part, downloadedAssets) {
var _a9, _b, _c, _d;
if (part.type === "text") {
return {
type: "text",
text: part.text,
providerMetadata: (_a9 = part.providerOptions) != null ? _a9 : part.experimental_providerMetadata
};
}
let mimeType = part.mimeType;
let data;
let content;
let normalizedData;
const type = part.type;
switch (type) {
case "image":
data = part.image;
break;
case "file":
data = part.data;
break;
default:
throw new Error(`Unsupported part type: ${type}`);
}
try {
content = typeof data === "string" ? new URL(data) : data;
} catch (error) {
content = data;
}
if (content instanceof URL) {
if (content.protocol === "data:") {
const { mimeType: dataUrlMimeType, base64Content } = splitDataUrl(
content.toString()
);
if (dataUrlMimeType == null || base64Content == null) {
throw new Error(`Invalid data URL format in part ${type}`);
}
mimeType = dataUrlMimeType;
normalizedData = convertDataContentToUint8Array(base64Content);
} else {
const downloadedFile = downloadedAssets[content.toString()];
if (downloadedFile) {
normalizedData = downloadedFile.data;
mimeType != null ? mimeType : mimeType = downloadedFile.mimeType;
} else {
normalizedData = content;
}
}
} else {
normalizedData = convertDataContentToUint8Array(content);
}
switch (type) {
case "image": {
if (normalizedData instanceof Uint8Array) {
mimeType = (_b = detectMimeType({
data: normalizedData,
signatures: imageMimeTypeSignatures
})) != null ? _b : mimeType;
}
return {
type: "image",
image: normalizedData,
mimeType,
providerMetadata: (_c = part.providerOptions) != null ? _c : part.experimental_providerMetadata
};
}
case "file": {
if (mimeType == null) {
throw new Error(`Mime type is missing for file part`);
}
return {
type: "file",
data: normalizedData instanceof Uint8Array ? convertDataContentToBase64String(normalizedData) : normalizedData,
filename: part.filename,
mimeType,
providerMetadata: (_d = part.providerOptions) != null ? _d : part.experimental_providerMetadata
};
}
}
}
// errors/invalid-argument-error.ts
import { AISDKError as AISDKError4 } from "@ai-sdk/provider";
var name4 = "AI_InvalidArgumentError";
var marker4 = `vercel.ai.error.${name4}`;
var symbol4 = Symbol.for(marker4);
var _a4;
var InvalidArgumentError = class extends AISDKError4 {
constructor({
parameter,
value,
message
}) {
super({
name: name4,
message: `Invalid argument for parameter ${parameter}: ${message}`
});
this[_a4] = true;
this.parameter = parameter;
this.value = value;
}
static isInstance(error) {
return AISDKError4.hasMarker(error, marker4);
}
};
_a4 = symbol4;
// core/prompt/prepare-call-settings.ts
function prepareCallSettings({
maxTokens,
temperature,
topP,
topK,
presencePenalty,
frequencyPenalty,
stopSequences,
seed
}) {
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 (topK != null) {
if (typeof topK !== "number") {
throw new InvalidArgumentError({
parameter: "topK",
value: topK,
message: "topK 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"
});
}
}
return {
maxTokens,
// TODO v5 remove default 0 for temperature
temperature: temperature != null ? temperature : 0,
topP,
topK,
presencePenalty,
frequencyPenalty,
stopSequences: stopSequences != null && stopSequences.length > 0 ? stopSequences : void 0,
seed
};
}
// util/retry-with-exponential-backoff.ts
import { APICallError } from "@ai-sdk/provider";
import { delay, getErrorMessage, isAbortError } from "@ai-sdk/provider-utils";
// util/retry-error.ts
import { AISDKError as AISDKError5 } from "@ai-sdk/provider";
var name5 = "AI_RetryError";
var marker5 = `vercel.ai.error.${name5}`;
var symbol5 = Symbol.for(marker5);
var _a5;
var RetryError = class extends AISDKError5 {
constructor({
message,
reason,
errors
}) {
super({ name: name5, message });
this[_a5] = true;
this.reason = reason;
this.errors = errors;
this.lastError = errors[errors.length - 1];
}
static isInstance(error) {
return AISDKError5.hasMarker(error, marker5);
}
};
_a5 = symbol5;
// 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.isInstance(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/prepare-retries.ts
function prepareRetries({
maxRetries
}) {
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"
});
}
}
const maxRetriesResult = maxRetries != null ? maxRetries : 2;
return {
maxRetries: maxRetriesResult,
retry: retryWithExponentialBackoff({ maxRetries: maxRetriesResult })
};
}
// core/prompt/prepare-tools-and-tool-choice.ts
import { asSchema } from "@ai-sdk/ui-utils";
// 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,
activeTools
}) {
if (!isNonEmptyObject(tools)) {
return {
tools: void 0,
toolChoice: void 0
};
}
const filteredTools = activeTools != null ? Object.entries(tools).filter(
([name9]) => activeTools.includes(name9)
) : Object.entries(tools);
return {
tools: filteredTools.map(([name9, tool]) => {
const toolType = tool.type;
switch (toolType) {
case void 0:
case "function":
return {
type: "function",
name: name9,
description: tool.description,
parameters: asSchema(tool.parameters).jsonSchema
};
case "provider-defined":
return {
type: "provider-defined",
name: name9,
id: tool.id,
args: tool.args
};
default: {
const exhaustiveCheck = toolType;
throw new Error(`Unsupported tool type: ${exhaustiveCheck}`);
}
}
}),
toolChoice: toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : { type: "tool", toolName: toolChoice.toolName }
};
}
// core/prompt/standardize-prompt.ts
import { InvalidPromptError } from "@ai-sdk/provider";
import { safeValidateTypes } from "@ai-sdk/provider-utils";
import { z as z7 } from "zod";
// core/prompt/attachments-to-parts.ts
function attachmentsToParts(attachments) {
var _a9, _b, _c;
const parts = [];
for (const attachment of attachments) {
let url;
try {
url = new URL(attachment.url);
} catch (error) {
throw new Error(`Invalid URL: ${attachment.url}`);
}
switch (url.protocol) {
case "http:":
case "https:": {
if ((_a9 = attachment.contentType) == null ? void 0 : _a9.startsWith("image/")) {
parts.push({ type: "image", image: url });
} else {
if (!attachment.contentType) {
throw new Error(
"If the attachment is not an image, it must specify a content type"
);
}
parts.push({
type: "file",
data: url,
mimeType: attachment.contentType
});
}
break;
}
case "data:": {
let header;
let base64Content;
let mimeType;
try {
[header, base64Content] = attachment.url.split(",");
mimeType = header.split(";")[0].split(":")[1];
} catch (error) {
throw new Error(`Error processing data URL: ${attachment.url}`);
}
if (mimeType == null || base64Content == null) {
throw new Error(`Invalid data URL format: ${attachment.url}`);
}
if ((_b = attachment.contentType) == null ? void 0 : _b.startsWith("image/")) {
parts.push({
type: "image",
image: convertDataContentToUint8Array(base64Content)
});
} else if ((_c = attachment.contentType) == null ? void 0 : _c.startsWith("text/")) {
parts.push({
type: "text",
text: convertUint8ArrayToText(
convertDataContentToUint8Array(base64Content)
)
});
} else {
if (!attachment.contentType) {
throw new Error(
"If the attachment is not an image or text, it must specify a content type"
);
}
parts.push({
type: "file",
data: base64Content,
mimeType: attachment.contentType
});
}
break;
}
default: {
throw new Error(`Unsupported URL protocol: ${url.protocol}`);
}
}
}
return parts;
}
// core/prompt/message-conversion-error.ts
import { AISDKError as AISDKError6 } from "@ai-sdk/provider";
var name6 = "AI_MessageConversionError";
var marker6 = `vercel.ai.error.${name6}`;
var symbol6 = Symbol.for(marker6);
var _a6;
var MessageConversionError = class extends AISDKError6 {
constructor({
originalMessage,
message
}) {
super({ name: name6, message });
this[_a6] = true;
this.originalMessage = originalMessage;
}
static isInstance(error) {
return AISDKError6.hasMarker(error, marker6);
}
};
_a6 = symbol6;
// core/prompt/convert-to-core-messages.ts
function convertToCoreMessages(messages, options) {
var _a9, _b;
const tools = (_a9 = options == null ? void 0 : options.tools) != null ? _a9 : {};
const coreMessages = [];
for (let i = 0; i < messages.length; i++) {
const message = messages[i];
const isLastMessage = i === messages.length - 1;
const { role, content, experimental_attachments } = message;
switch (role) {
case "system": {
coreMessages.push({
role: "system",
content
});
break;
}
case "user": {
if (message.parts == null) {
coreMessages.push({
role: "user",
content: experimental_attachments ? [
{ type: "text", text: content },
...attachmentsToParts(experimental_attachments)
] : content
});
} else {
const textParts = message.parts.filter((part) => part.type === "text").map((part) => ({
type: "text",
text: part.text
}));
coreMessages.push({
role: "user",
content: experimental_attachments ? [...textParts, ...attachmentsToParts(experimental_attachments)] : textParts
});
}
break;
}
case "assistant": {
if (message.parts != null) {
let processBlock2 = function() {
const content2 = [];
for (const part of block) {
switch (part.type) {
case "file":
case "text": {
content2.push(part);
break;
}
case "reasoning": {
for (const detail of part.details) {
switch (detail.type) {
case "text":
content2.push({
type: "reasoning",
text: detail.text,
signature: detail.signature
});
break;
case "redacted":
content2.push({
type: "redacted-reasoning",
data: detail.data
});
break;
}
}
break;
}
case "tool-invocation":
content2.push({
type: "tool-call",
toolCallId: part.toolInvocation.toolCallId,
toolName: part.toolInvocation.toolName,
args: part.toolInvocation.args
});
break;
default: {
const _exhaustiveCheck = part;
throw new Error(`Unsupported part: ${_exhaustiveCheck}`);
}
}
}
coreMessages.push({
role: "assistant",
content: content2
});
const stepInvocations = block.filter(
(part) => part.type === "tool-invocation"
).map((part) => part.toolInvocation);
if (stepInvocations.length > 0) {
coreMessages.push({
role: "tool",
content: stepInvocations.map(
(toolInvocation) => {
if (!("result" in toolInvocation)) {
throw new MessageConversionError({
originalMessage: message,
message: "ToolInvocation must have a result: " + JSON.stringify(toolInvocation)
});
}
const { toolCallId, toolName, result } = toolInvocation;
const tool = tools[toolName];
return (tool == null ? void 0 : tool.experimental_toToolResultContent) != null ? {
type: "tool-result",
toolCallId,
toolName,
result: tool.experimental_toToolResultContent(result),
experimental_content: tool.experimental_toToolResultContent(result)
} : {
type: "tool-result",
toolCallId,
toolName,
result
};
}
)
});
}
block = [];
blockHasToolInvocations = false;
currentStep++;
};
var processBlock = processBlock2;
let currentStep = 0;
let blockHasToolInvocations = false;
let block = [];
for (const part of message.parts) {
switch (part.type) {
case "text": {
if (blockHasToolInvocations) {
processBlock2();
}
block.push(part);
break;
}
case "file":
case "reasoning": {
block.push(part);
break;
}
case "tool-invocation": {
if (((_b = part.toolInvocation.step) != null ? _b : 0) !== currentStep) {
processBlock2();
}
block.push(part);
blockHasToolInvocations = true;
break;
}
}
}
processBlock2();
break;
}
const toolInvocations = message.toolInvocations;
if (toolInvocations == null || toolInvocations.length === 0) {
coreMessages.push({ role: "assistant", content });
break;
}
const maxStep = toolInvocations.reduce((max, toolInvocation) => {
var _a10;
return Math.max(max, (_a10 = toolInvocation.step) != null ? _a10 : 0);
}, 0);
for (let i2 = 0; i2 <= maxStep; i2++) {
const stepInvocations = toolInvocations.filter(
(toolInvocation) => {
var _a10;
return ((_a10 = toolInvocation.step) != null ? _a10 : 0) === i2;
}
);
if (stepInvocations.length === 0) {
continue;
}
coreMessages.push({
role: "assistant",
content: [
...isLastMessage && content && i2 === 0 ? [{ type: "text", text: content }] : [],
...stepInvocations.map(
({ toolCallId, toolName, args }) => ({
type: "tool-call",
toolCallId,
toolName,
args
})
)
]
});
coreMessages.push({
role: "tool",
content: stepInvocations.map((toolInvocation) => {
if (!("result" in toolInvocation)) {
throw new MessageConversionError({
originalMessage: message,
message: "ToolInvocation must have a result: " + JSON.stringify(toolInvocation)
});
}
const { toolCallId, toolName, result } = toolInvocation;
const tool = tools[toolName];
return (tool == null ? void 0 : tool.experimental_toToolResultContent) != null ? {
type: "tool-result",
toolCallId,
toolName,
result: tool.experimental_toToolResultContent(result),
experimental_content: tool.experimental_toToolResultContent(result)
} : {
type: "tool-result",
toolCallId,
toolName,
result
};
})
});
}
if (content && !isLastMessage) {
coreMessages.push({ role: "assistant", content });
}
break;
}
case "data": {
break;
}
default: {
const _exhaustiveCheck = role;
throw new MessageConversionError({
originalMessage: message,
message: `Unsupported role: ${_exhaustiveCheck}`
});
}
}
}
return coreMessages;
}
// core/prompt/message.ts
import { z as z6 } from "zod";
// core/types/provider-metadata.ts
import { z as z3 } from "zod";
// core/types/json-value.ts
import { z as z2 } from "zod";
var jsonValueSchema = z2.lazy(
() => z2.union([
z2.null(),
z2.string(),
z2.number(),
z2.boolean(),
z2.record(z2.string(), jsonValueSchema),
z2.array(jsonValueSchema)
])
);
// core/types/provider-metadata.ts
var providerMetadataSchema = z3.record(
z3.string(),
z3.record(z3.string(), jsonValueSchema)
);
// core/prompt/content-part.ts
import { z as z5 } from "zod";
// core/prompt/tool-result-content.ts
import { z as z4 } from "zod";
var toolResultContentSchema = z4.array(
z4.union([
z4.object({ type: z4.literal("text"), text: z4.string() }),
z4.object({
type: z4.literal("image"),
data: z4.string(),
mimeType: z4.string().optional()
})
])
);
// core/prompt/content-part.ts
var textPartSchema = z5.object({
type: z5.literal("text"),
text: z5.string(),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var imagePartSchema = z5.object({
type: z5.literal("image"),
image: z5.union([dataContentSchema, z5.instanceof(URL)]),
mimeType: z5.string().optional(),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var filePartSchema = z5.object({
type: z5.literal("file"),
data: z5.union([dataContentSchema, z5.instanceof(URL)]),
filename: z5.string().optional(),
mimeType: z5.string(),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var reasoningPartSchema = z5.object({
type: z5.literal("reasoning"),
text: z5.string(),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var redactedReasoningPartSchema = z5.object({
type: z5.literal("redacted-reasoning"),
data: z5.string(),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var toolCallPartSchema = z5.object({
type: z5.literal("tool-call"),
toolCallId: z5.string(),
toolName: z5.string(),
args: z5.unknown(),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var toolResultPartSchema = z5.object({
type: z5.literal("tool-result"),
toolCallId: z5.string(),
toolName: z5.string(),
result: z5.unknown(),
content: toolResultContentSchema.optional(),
isError: z5.boolean().optional(),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
// core/prompt/message.ts
var coreSystemMessageSchema = z6.object({
role: z6.literal("system"),
content: z6.string(),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var coreUserMessageSchema = z6.object({
role: z6.literal("user"),
content: z6.union([
z6.string(),
z6.array(z6.union([textPartSchema, imagePartSchema, filePartSchema]))
]),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var coreAssistantMessageSchema = z6.object({
role: z6.literal("assistant"),
content: z6.union([
z6.string(),
z6.array(
z6.union([
textPartSchema,
filePartSchema,
reasoningPartSchema,
redactedReasoningPartSchema,
toolCallPartSchema
])
)
]),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var coreToolMessageSchema = z6.object({
role: z6.literal("tool"),
content: z6.array(toolResultPartSchema),
providerOptions: providerMetadataSchema.optional(),
experimental_providerMetadata: providerMetadataSchema.optional()
});
var coreMessageSchema = z6.union([
coreSystemMessageSchema,
coreUserMessageSchema,
coreAssistantMessageSchema,
coreToolMessageSchema
]);
// core/prompt/standardize-prompt.ts
function standardizePrompt({
prompt,
tools
}) {
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.system != null && typeof prompt.system !== "string") {
throw new InvalidPromptError({
prompt,
message: "system must be a string"
});
}
if (prompt.prompt != null) {
if (typeof prompt.prompt !== "string") {
throw new InvalidPromptError({
prompt,
message: "prompt must be a string"
});
}
return {
type: "prompt",
system: prompt.system,
messages: [
{
role: "user",
content: prompt.prompt
}
]
};
}
if (prompt.messages != null) {
const promptType = detectPromptType(prompt.messages);
const messages = promptType === "ui-messages" ? convertToCoreMessages(prompt.messages, {
tools
}) : prompt.messages;
if (messages.length === 0) {
throw new InvalidPromptError({
prompt,
message: "messages must not be empty"
});
}
const validationResult = safeValidateTypes({
value: messages,
schema: z7.array(coreMessageSchema)
});
if (!validationResult.success) {
throw new InvalidPromptError({
prompt,
message: [
"message must be a CoreMessage or a UI message",
`Validation error: ${validationResult.error.message}`
].join("\n"),
cause: validationResult.error
});
}
return {
type: "messages",
messages,
system: prompt.system
};
}
throw new Error("unreachable");
}
function detectPromptType(prompt) {
if (!Array.isArray(prompt)) {
throw new InvalidPromptError({
prompt,
message: [
"messages must be an array of CoreMessage or UIMessage",
`Received non-array value: ${JSON.stringify(prompt)}`
].join("\n"),
cause: prompt
});
}
if (prompt.length === 0) {
return "messages";
}
const characteristics = prompt.map(detectSingleMessageCharacteristics);
if (characteristics.some((c) => c === "has-ui-specific-parts")) {
return "ui-messages";
}
const nonMessageIndex = characteristics.findIndex(
(c) => c !== "has-core-specific-parts" && c !== "message"
);
if (nonMessageIndex === -1) {
return "messages";
}
throw new InvalidPromptError({
prompt,
message: [
"messages must be an array of CoreMessage or UIMessage",
`Received message of type: "${characteristics[nonMessageIndex]}" at index ${nonMessageIndex}`,
`messages[${nonMessageIndex}]: ${JSON.stringify(prompt[nonMessageIndex])}`
].join("\n"),
cause: prompt
});
}
function detectSingleMessageCharacteristics(message) {
if (typeof message === "object" && message !== null && (message.role === "function" || // UI-only role
message.role === "data" || // UI-only role
"toolInvocations" in message || // UI-specific field
"parts" in message || // UI-specific field
"experimental_attachments" in message)) {
return "has-ui-specific-parts";
} else if (typeof message === "object" && message !== null && "content" in message && (Array.isArray(message.content) || // Core messages can have array content
"experimental_providerMetadata" in message || "providerOptions" in message)) {
return "has-core-specific-parts";
} else if (typeof message === "object" && message !== null && "role" in message && "content" in message && typeof message.content === "string" && ["system", "user", "assistant", "tool"].includes(message.role)) {
return "message";
} else {
return "other";
}
}
// core/types/usage.ts
function calculateLanguageModelUsage({
promptTokens,
completionTokens
}) {
return {
promptTokens,
completionTokens,
totalTokens: promptTokens + completionTokens
};
}
// errors/invalid-tool-arguments-error.ts
import { AISDKError as AISDKError7, getErrorMessage as getErrorMessage2 } from "@ai-sdk/provider";
var name7 = "AI_InvalidToolArgumentsError";
var marker7 = `vercel.ai.error.${name7}`;
var symbol7 = Symbol.for(marker7);
var _a7;
var InvalidToolArgumentsError = class extends AISDKError7 {
constructor({
toolArgs,
toolName,
cause,
message = `Invalid arguments for tool ${toolName}: ${getErrorMessage2(
cause
)}`
}) {
super({ name: name7, message, cause });
this[_a7] = true;
this.toolArgs = toolArgs;
this.toolName = toolName;
}
static isInstance(error) {
return AISDKError7.hasMarker(error, marker7);
}
};
_a7 = symbol7;
// errors/no-such-tool-error.ts
import { AISDKError as AISDKError8 } from "@ai-sdk/provider";
var name8 = "AI_NoSuchToolError";
var marker8 = `vercel.ai.error.${name8}`;
var symbol8 = Symbol.for(marker8);
var _a8;
var NoSuchToolError = class extends AISDKError8 {
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: name8, message });
this[_a8] = true;
this.toolName = toolName;
this.availableTools = availableTools;
}
static isInstance(error) {
return AISDKError8.hasMarker(error, marker8);
}
};
_a8 = symbol8;
// util/is-async-generator.ts
function isAsyncGenerator(value) {
return value != null && typeof value === "object" && Symbol.asyncIterator in value;
}
// util/is-generator.ts
function isGenerator(value) {
return value != null && typeof value === "object" && Symbol.iterator in value;
}
// util/constants.ts
var HANGING_STREAM_WARNING_TIME_MS = 15 * 1e3;
// rsc/streamable-ui/create-suspended-chunk.tsx
import { Suspense } from "react";
import { Fragment, jsx as jsx2, 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__ */ jsx2(Suspense, { fallback: chunk.value, children: /* @__PURE__ */ jsx2(R, { c: chunk.value, n: chunk.next }) })
] });
}
return /* @__PURE__ */ jsx2(Suspense, { fallback: chunk.value, children: /* @__PURE__ */ jsx2(R, { c: chunk.value, n: chunk.next }) });
}
][0];
function createSuspendedChunk(initialValue) {
const { promise, resolve, reject } = createResolvablePromise();
return {
row: /* @__PURE__ */ jsx2(Suspense, { fallback: initialValue, children