ai
Version:
AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.
1,649 lines (1,617 loc) • 107 kB
JavaScript
// internal/index.ts
import { convertAsyncIteratorToReadableStream } from "@ai-sdk/provider-utils";
// src/util/async-iterable-stream.ts
function createAsyncIterableStream(source) {
return asAsyncIterableStream(source.pipeThrough(new TransformStream()));
}
function asAsyncIterableStream(stream) {
stream[Symbol.asyncIterator] = function() {
const reader = this.getReader();
let finished = false;
async function cleanup(cancelStream) {
var _a12;
if (finished)
return;
finished = true;
try {
if (cancelStream) {
await ((_a12 = reader.cancel) == null ? void 0 : _a12.call(reader));
}
} finally {
try {
reader.releaseLock();
} catch (e) {
}
}
}
return {
/**
* Reads the next chunk from the stream.
* @returns A promise resolving to the next IteratorResult.
*/
async next() {
if (finished) {
return { done: true, value: void 0 };
}
const { done, value } = await reader.read();
if (done) {
await cleanup(true);
return { done: true, value: void 0 };
}
return { done: false, value };
},
/**
* May be called on early exit (e.g., break from for-await) or after completion.
* Ensures the stream is cancelled and resources are released.
* @returns A promise resolving to a completed IteratorResult.
*/
async return() {
await cleanup(true);
return { done: true, value: void 0 };
},
/**
* Called on early exit with error.
* Ensures the stream is cancelled and resources are released, then rethrows the error.
* @param err The error to throw.
* @returns A promise that rejects with the provided error.
*/
async throw(err) {
await cleanup(true);
throw err;
}
};
};
return stream;
}
// src/prompt/convert-to-language-model-prompt.ts
import {
asArray,
detectMediaType,
isFullMediaType,
isUrlSupported
} from "@ai-sdk/provider-utils";
// src/util/download/download.ts
import {
cancelResponseBody,
DownloadError,
readResponseWithSizeLimit,
DEFAULT_MAX_DOWNLOAD_SIZE,
fetchWithValidatedRedirects,
withUserAgentSuffix,
getRuntimeEnvironmentUserAgent
} from "@ai-sdk/provider-utils";
// src/version.ts
var VERSION = true ? "7.0.22" : "0.0.0-test";
// src/util/download/download.ts
var download = async ({
url,
maxBytes,
abortSignal
}) => {
var _a12;
const urlText = url.toString();
try {
const headers = withUserAgentSuffix(
{},
`ai-sdk/${VERSION}`,
getRuntimeEnvironmentUserAgent()
);
const response = await fetchWithValidatedRedirects({
url: urlText,
headers,
abortSignal
});
if (!response.ok) {
await cancelResponseBody(response);
throw new DownloadError({
url: urlText,
statusCode: response.status,
statusText: response.statusText
});
}
const data = await readResponseWithSizeLimit({
response,
url: urlText,
maxBytes: maxBytes != null ? maxBytes : DEFAULT_MAX_DOWNLOAD_SIZE
});
return {
data,
mediaType: (_a12 = response.headers.get("content-type")) != null ? _a12 : void 0
};
} catch (error) {
if (DownloadError.isInstance(error)) {
throw error;
}
throw new DownloadError({ url: urlText, cause: error });
}
};
// src/util/download/download-function.ts
var createDefaultDownloadFunction = (download2 = download) => (requestedDownloads) => Promise.all(
requestedDownloads.map(
async (requestedDownload) => requestedDownload.isUrlSupportedByModel ? null : await download2(requestedDownload)
)
);
// src/prompt/file-part-data.ts
import {
isBuffer,
isProviderReference
} from "@ai-sdk/provider-utils";
// src/prompt/invalid-data-content-error.ts
import { AISDKError } from "@ai-sdk/provider";
var name = "AI_InvalidDataContentError";
var marker = `vercel.ai.error.${name}`;
var symbol = Symbol.for(marker);
var _a;
var InvalidDataContentError = class extends AISDKError {
constructor({
content,
cause,
message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.`
}) {
super({ name, message, cause });
this[_a] = true;
this.content = content;
}
static isInstance(error) {
return AISDKError.hasMarker(error, marker);
}
};
_a = symbol;
// src/prompt/split-data-url.ts
function splitDataUrl(dataUrl) {
try {
const [header, base64Content] = dataUrl.split(",");
return {
mediaType: header.split(";")[0].split(":")[1],
base64Content
};
} catch (e) {
return {
mediaType: void 0,
base64Content: void 0
};
}
}
// src/prompt/file-part-data.ts
function isTaggedFileData(value) {
if (typeof value !== "object" || value === null)
return false;
const type = value.type;
return type === "data" || type === "url" || type === "reference" || type === "text";
}
function convertUrlToFilePartData(url) {
if (url.protocol === "data:") {
const { mediaType, base64Content } = splitDataUrl(url.toString());
if (mediaType == null || base64Content == null) {
throw new InvalidDataContentError({
content: url,
message: `Invalid data URL format in content ${url.toString()}`
});
}
return { data: { type: "data", data: base64Content }, mediaType };
}
return { data: { type: "url", url }, mediaType: void 0 };
}
function convertInlineDataToFilePartData(content) {
if (content instanceof Uint8Array) {
return { data: { type: "data", data: content }, mediaType: void 0 };
}
if (content instanceof ArrayBuffer) {
return {
data: { type: "data", data: new Uint8Array(content) },
mediaType: void 0
};
}
if (isBuffer(content)) {
return {
data: { type: "data", data: new Uint8Array(content) },
mediaType: void 0
};
}
return {
data: { type: "data", data: content },
mediaType: void 0
};
}
function convertToLanguageModelV4FilePart(content) {
if (isTaggedFileData(content)) {
switch (content.type) {
case "data":
if (typeof content.data === "string" && content.data.startsWith("data:")) {
throw new InvalidDataContentError({
content: content.data,
message: 'Data URLs are not valid inline data. Pass them as { type: "url", url } instead.'
});
}
return convertInlineDataToFilePartData(content.data);
case "url":
return convertUrlToFilePartData(content.url);
case "reference":
return {
data: { type: "reference", reference: content.reference },
mediaType: void 0
};
case "text":
return {
data: { type: "text", text: content.text },
mediaType: void 0
};
}
}
if (content instanceof URL) {
return convertUrlToFilePartData(content);
}
if (typeof content === "string") {
try {
return convertUrlToFilePartData(new URL(content));
} catch (e) {
return convertInlineDataToFilePartData(content);
}
}
if (isProviderReference(content)) {
return {
data: { type: "reference", reference: content },
mediaType: void 0
};
}
return convertInlineDataToFilePartData(content);
}
// src/logger/log-warnings.ts
function formatWarning({
warning,
provider,
model
}) {
const scope = provider != null && model != null ? ` (${provider} / ${model})` : "";
const prefix = `AI SDK Warning${scope}:`;
switch (warning.type) {
case "unsupported": {
let message = `${prefix} The feature "${warning.feature}" is not supported.`;
if (warning.details) {
message += ` ${warning.details}`;
}
return message;
}
case "compatibility": {
let message = `${prefix} The feature "${warning.feature}" is used in a compatibility mode.`;
if (warning.details) {
message += ` ${warning.details}`;
}
return message;
}
case "deprecated": {
return `${prefix} Deprecated: "${warning.setting}". ${warning.message}`;
}
case "other": {
return `${prefix} ${warning.message}`;
}
default: {
return `${prefix} ${JSON.stringify(warning, null, 2)}`;
}
}
}
var FIRST_WARNING_INFO_MESSAGE = "AI SDK Warning System: To turn off warning logging, set the AI_SDK_LOG_WARNINGS global to false.";
var hasLoggedBefore = false;
var logWarnings = (options) => {
if (options.warnings.length === 0) {
return;
}
const logger = globalThis.AI_SDK_LOG_WARNINGS;
if (logger === false) {
return;
}
if (typeof logger === "function") {
logger(options);
return;
}
if (!hasLoggedBefore) {
hasLoggedBefore = true;
console.info(FIRST_WARNING_INFO_MESSAGE);
}
for (const warning of options.warnings) {
const message = formatWarning({
warning,
provider: options.provider,
model: options.model
});
if (typeof process !== "undefined" && typeof process.emitWarning === "function") {
process.emitWarning(message, {
type: warning.type === "deprecated" ? "DeprecationWarning" : "Warning"
});
} else {
console.warn(message);
}
}
};
// src/prompt/invalid-message-role-error.ts
import { AISDKError as AISDKError2 } from "@ai-sdk/provider";
var name2 = "AI_InvalidMessageRoleError";
var marker2 = `vercel.ai.error.${name2}`;
var symbol2 = Symbol.for(marker2);
var _a2;
var InvalidMessageRoleError = class extends AISDKError2 {
constructor({
role,
message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".`
}) {
super({ name: name2, message });
this[_a2] = true;
this.role = role;
}
static isInstance(error) {
return AISDKError2.hasMarker(error, marker2);
}
};
_a2 = symbol2;
// src/error/missing-tool-result-error.ts
import { AISDKError as AISDKError3 } from "@ai-sdk/provider";
var name3 = "AI_MissingToolResultsError";
var marker3 = `vercel.ai.error.${name3}`;
var symbol3 = Symbol.for(marker3);
var _a3;
var MissingToolResultsError = class extends AISDKError3 {
constructor({ toolCallIds }) {
super({
name: name3,
message: `Tool result${toolCallIds.length > 1 ? "s are" : " is"} missing for tool call${toolCallIds.length > 1 ? "s" : ""} ${toolCallIds.join(
", "
)}.`
});
this[_a3] = true;
this.toolCallIds = toolCallIds;
}
static isInstance(error) {
return AISDKError3.hasMarker(error, marker3);
}
};
_a3 = symbol3;
// src/prompt/convert-to-language-model-prompt.ts
async function convertToLanguageModelPrompt({
prompt,
supportedUrls,
download: download2 = createDefaultDownloadFunction(),
// `provider` is only needed here to convert legacy tool output types via `mapToolResultOutput`.
// TODO: remove in v8 when "file-id" and "image-file-id" types are removed
provider
}) {
const downloadedAssets = await downloadAssets(
prompt.messages,
download2,
supportedUrls
);
const approvalIdToToolCallId = /* @__PURE__ */ new Map();
for (const message of prompt.messages) {
if (message.role === "assistant" && Array.isArray(message.content)) {
for (const part of message.content) {
if (part.type === "tool-approval-request" && "approvalId" in part && "toolCallId" in part) {
approvalIdToToolCallId.set(
part.approvalId,
part.toolCallId
);
}
}
}
}
const approvedToolCallIds = /* @__PURE__ */ new Set();
for (const message of prompt.messages) {
if (message.role === "tool") {
for (const part of message.content) {
if (part.type === "tool-approval-response") {
const toolCallId = approvalIdToToolCallId.get(part.approvalId);
if (toolCallId) {
approvedToolCallIds.add(toolCallId);
}
}
}
}
}
const messages = [
...prompt.instructions != null ? typeof prompt.instructions === "string" ? [{ role: "system", content: prompt.instructions }] : asArray(prompt.instructions).map((message) => ({
role: "system",
content: message.content,
providerOptions: message.providerOptions
})) : [],
...prompt.messages.map(
(message) => convertToLanguageModelMessage({ message, downloadedAssets, provider })
)
];
const combinedMessages = [];
for (const message of messages) {
if (message.role !== "tool") {
combinedMessages.push(message);
continue;
}
const lastCombinedMessage = combinedMessages.at(-1);
if ((lastCombinedMessage == null ? void 0 : lastCombinedMessage.role) === "tool") {
lastCombinedMessage.content.push(...message.content);
} else {
combinedMessages.push(message);
}
}
const toolCallIds = /* @__PURE__ */ new Set();
for (const message of combinedMessages) {
switch (message.role) {
case "assistant": {
for (const content of message.content) {
if (content.type === "tool-call" && !content.providerExecuted) {
toolCallIds.add(content.toolCallId);
}
}
break;
}
case "tool": {
for (const content of message.content) {
if (content.type === "tool-result") {
toolCallIds.delete(content.toolCallId);
}
}
break;
}
case "user":
case "system":
for (const id of approvedToolCallIds) {
toolCallIds.delete(id);
}
if (toolCallIds.size > 0) {
throw new MissingToolResultsError({
toolCallIds: Array.from(toolCallIds)
});
}
break;
}
}
for (const id of approvedToolCallIds) {
toolCallIds.delete(id);
}
if (toolCallIds.size > 0) {
throw new MissingToolResultsError({ toolCallIds: Array.from(toolCallIds) });
}
return combinedMessages.filter(
// Filter out empty tool messages (e.g. if they only contained
// tool-approval-response parts that were removed).
// This prevents sending invalid empty messages to the provider.
// Note: provider-executed tool-approval-response parts are preserved.
(message) => message.role !== "tool" || message.content.length > 0
);
}
function convertToLanguageModelMessage({
message,
downloadedAssets,
// `provider` is only needed here to convert legacy tool output types via `mapToolResultOutput`.
// TODO: remove in v8 when "file-id" and "image-file-id" types are removed
provider
}) {
const warnings = [];
const role = message.role;
switch (role) {
case "system": {
return {
role: "system",
content: message.content,
providerOptions: message.providerOptions
};
}
case "user": {
if (typeof message.content === "string") {
return {
role: "user",
content: [{ type: "text", text: message.content }],
providerOptions: message.providerOptions
};
}
const converted = {
role: "user",
content: message.content.map((part) => {
if (part.type === "image") {
warnings.push({
type: "deprecated",
setting: '"image" content part',
message: `The "image" content part type is deprecated. Use a "file" part with mediaType: 'image' (or a more specific image/* subtype) instead.`
});
}
return convertImagePartToFilePart(part);
}).map((part) => convertPartToLanguageModelPart(part, downloadedAssets)).filter((part) => part.type !== "text" || part.text !== ""),
providerOptions: message.providerOptions
};
if (warnings.length > 0) {
logWarnings({ warnings });
}
return converted;
}
case "assistant": {
if (typeof message.content === "string") {
return {
role: "assistant",
content: [{ type: "text", text: message.content }],
providerOptions: message.providerOptions
};
}
const converted = {
role: "assistant",
content: message.content.filter(
// remove empty text parts (no text, and no provider options):
(part) => part.type !== "text" || part.text !== "" || part.providerOptions != null
).filter(
(part) => part.type !== "tool-approval-request"
).map((part) => {
const providerOptions = part.providerOptions;
switch (part.type) {
case "custom": {
return {
type: "custom",
kind: part.kind,
providerOptions
};
}
case "file": {
const { data, mediaType } = convertToLanguageModelV4FilePart(
part.data
);
return {
type: "file",
data,
filename: part.filename,
mediaType: mediaType != null ? mediaType : part.mediaType,
providerOptions
};
}
case "reasoning": {
return {
type: "reasoning",
text: part.text,
providerOptions
};
}
case "reasoning-file": {
const { data, mediaType } = convertToLanguageModelV4FilePart(
part.data
);
if (data.type !== "data" && data.type !== "url") {
throw new Error(
`Unsupported reasoning-file data type: ${data.type}`
);
}
return {
type: "reasoning-file",
data,
mediaType: mediaType != null ? mediaType : part.mediaType,
providerOptions
};
}
case "text": {
return {
type: "text",
text: part.text,
providerOptions
};
}
case "tool-call": {
return {
type: "tool-call",
toolCallId: part.toolCallId,
toolName: part.toolName,
input: part.input,
providerExecuted: part.providerExecuted,
providerOptions
};
}
case "tool-result": {
return {
type: "tool-result",
toolCallId: part.toolCallId,
toolName: part.toolName,
output: mapToolResultOutput({
output: part.output,
provider,
warnings,
downloadedAssets
}),
providerOptions
};
}
}
}),
providerOptions: message.providerOptions
};
if (warnings.length > 0) {
logWarnings({ warnings });
}
return converted;
}
case "tool": {
const converted = {
role: "tool",
content: message.content.filter(
// Only include tool-approval-response for provider-executed tools
(part) => part.type !== "tool-approval-response" || part.providerExecuted
).map((part) => {
switch (part.type) {
case "tool-result": {
return {
type: "tool-result",
toolCallId: part.toolCallId,
toolName: part.toolName,
output: mapToolResultOutput({
output: part.output,
provider,
warnings,
downloadedAssets
}),
providerOptions: part.providerOptions
};
}
case "tool-approval-response": {
return {
type: "tool-approval-response",
approvalId: part.approvalId,
approved: part.approved,
reason: part.reason
};
}
}
}),
providerOptions: message.providerOptions
};
if (warnings.length > 0) {
logWarnings({ warnings });
}
return converted;
}
default: {
const _exhaustiveCheck = role;
throw new InvalidMessageRoleError({ role: _exhaustiveCheck });
}
}
}
function convertImagePartToFilePart(part) {
var _a12;
if (part.type !== "image") {
return part;
}
return {
type: "file",
data: part.image,
mediaType: (_a12 = part.mediaType) != null ? _a12 : "image",
providerOptions: part.providerOptions
};
}
async function downloadAssets(messages, download2, supportedUrls) {
const downloadableFiles = [];
for (const message of messages) {
if (message.role === "user" && Array.isArray(message.content)) {
for (const part of message.content) {
const filePart = convertImagePartToFilePart(part);
if (filePart.type === "file") {
downloadableFiles.push(filePart);
}
}
}
if (message.role === "tool") {
for (const part of message.content) {
if (part.type !== "tool-result") {
continue;
}
if (part.output.type !== "content") {
continue;
}
for (const contentPart of part.output.value) {
if (contentPart.type === "file") {
downloadableFiles.push(contentPart);
}
}
}
}
if (message.role === "assistant" && Array.isArray(message.content)) {
for (const part of message.content) {
if (part.type !== "tool-result") {
continue;
}
if (part.output.type !== "content") {
continue;
}
for (const contentPart of part.output.value) {
if (contentPart.type === "file") {
downloadableFiles.push(contentPart);
}
}
}
}
}
const plannedDownloads = downloadableFiles.map((part) => {
const mediaType = part.mediaType;
const { data } = convertToLanguageModelV4FilePart(part.data);
return { mediaType, data };
}).filter((part) => part.data.type === "url").map((part) => ({
url: part.data.url,
isUrlSupportedByModel: part.mediaType != null && isUrlSupported({
url: part.data.url.toString(),
mediaType: part.mediaType,
supportedUrls
})
}));
const downloadedFiles = await download2(plannedDownloads);
return Object.fromEntries(
downloadedFiles.map(
(file, index) => file == null ? null : [
plannedDownloads[index].url.toString(),
{ data: file.data, mediaType: file.mediaType }
]
).filter((file) => file != null)
);
}
function convertPartToLanguageModelPart(part, downloadedAssets) {
if (part.type === "text") {
return {
type: "text",
text: part.text,
providerOptions: part.providerOptions
};
}
const { data: normalizedData, mediaType: dataUrlMediaType } = convertToLanguageModelV4FilePart(part.data);
let mediaType = dataUrlMediaType != null ? dataUrlMediaType : part.mediaType;
let data = normalizedData;
if (data.type === "url") {
const downloadedFile = downloadedAssets[data.url.toString()];
if (downloadedFile) {
data = { type: "data", data: downloadedFile.data };
if (downloadedFile.mediaType != null && (mediaType == null || !isFullMediaType(mediaType))) {
mediaType = downloadedFile.mediaType;
}
}
}
if (data.type === "data" && (data.data instanceof Uint8Array || typeof data.data === "string")) {
const imageMediaType = detectMediaType({
data: data.data,
topLevelType: "image"
});
if (imageMediaType != null) {
mediaType = imageMediaType;
}
}
if (mediaType == null) {
throw new Error(`Media type is missing for file part`);
}
return {
type: "file",
mediaType,
filename: part.filename,
data,
providerOptions: part.providerOptions
};
}
function mapToolResultOutput({
output,
// `provider` is only needed here to convert legacy "file-id" and "image-file-id" types to provider references, in case they are using string ID values.
// TODO: remove in v8 when "file-id" and "image-file-id" types are removed
provider,
warnings = [],
downloadedAssets
}) {
if (output.type !== "content") {
return output;
}
return {
type: "content",
value: output.value.map((item) => {
var _a12;
switch (item.type) {
case "file": {
const convertedPart = convertPartToLanguageModelPart(
item,
downloadedAssets
);
if (convertedPart.type !== "file") {
throw new Error(
"Expected tool result file content to convert to file."
);
}
return convertedPart;
}
case "file-data": {
warnings.push({
type: "deprecated",
setting: '"tool-result" content of type "file-data"',
message: `The "file-data" type for tool result content is deprecated. Use the "file" type with mediaType and { type: 'data', data } instead.`
});
return {
type: "file",
data: { type: "data", data: item.data },
filename: item.filename,
mediaType: item.mediaType,
providerOptions: item.providerOptions
};
}
case "file-url": {
const mediaType = (_a12 = item.mediaType) != null ? _a12 : getMediaTypeFromUrl(item.url);
let message = `The "file-url" type for tool result content is deprecated. Use the "file" type with mediaType and { type: 'url', url } instead.`;
if (!item.mediaType) {
const inferenceSuffix = mediaType === "application/octet-stream" ? `Unable to infer media type from URL. Defaulting to 'application/octet-stream'.` : `Inferred media type '${mediaType}' from URL.`;
message = `The "file-url" tool result content part with URL "${item.url}" is missing a "mediaType". ${inferenceSuffix} ${message}`;
}
warnings.push({
type: "deprecated",
setting: '"tool-result" content of type "file-url"',
message
});
return {
type: "file",
data: { type: "url", url: new URL(item.url) },
mediaType,
providerOptions: item.providerOptions
};
}
case "file-id": {
warnings.push({
type: "deprecated",
setting: '"tool-result" content of type "file-id"',
message: `The "file-id" type for tool result content is deprecated. Use the "file" type with mediaType and { type: 'reference', reference } instead.`
});
return {
type: "file",
data: {
type: "reference",
reference: convertFileIdToProviderReference({
fileId: item.fileId,
provider
})
},
mediaType: "application",
providerOptions: item.providerOptions
};
}
case "file-reference": {
warnings.push({
type: "deprecated",
setting: '"tool-result" content of type "file-reference"',
message: `The "file-reference" type for tool result content is deprecated. Use the "file" type with mediaType and { type: 'reference', reference } instead.`
});
return {
type: "file",
data: {
type: "reference",
reference: item.providerReference
},
mediaType: "application",
providerOptions: item.providerOptions
};
}
case "image-data": {
warnings.push({
type: "deprecated",
setting: '"tool-result" content of type "image-data"',
message: `The "image-data" type for tool result content is deprecated. Use the "file" type with mediaType and { type: 'data', data } instead.`
});
return {
type: "file",
data: { type: "data", data: item.data },
mediaType: item.mediaType,
providerOptions: item.providerOptions
};
}
case "image-url": {
warnings.push({
type: "deprecated",
setting: '"tool-result" content of type "image-url"',
message: `The "image-url" type for tool result content is deprecated. Use the "file" type with mediaType 'image' (or a specific image/* subtype) and { type: 'url', url } instead.`
});
return {
type: "file",
data: { type: "url", url: new URL(item.url) },
mediaType: "image",
providerOptions: item.providerOptions
};
}
case "image-file-id": {
warnings.push({
type: "deprecated",
setting: '"tool-result" content of type "image-file-id"',
message: `The "image-file-id" type for tool result content is deprecated. Use the "file" type with mediaType and { type: 'reference', reference } instead.`
});
return {
type: "file",
data: {
type: "reference",
reference: convertFileIdToProviderReference({
fileId: item.fileId,
provider
})
},
mediaType: "image",
providerOptions: item.providerOptions
};
}
case "image-file-reference": {
warnings.push({
type: "deprecated",
setting: '"tool-result" content of type "image-file-reference"',
message: `The "image-file-reference" type for tool result content is deprecated. Use the "file" type with mediaType and { type: 'reference', reference } instead.`
});
return {
type: "file",
data: {
type: "reference",
reference: item.providerReference
},
mediaType: "image",
providerOptions: item.providerOptions
};
}
default:
return item;
}
})
};
}
function convertFileIdToProviderReference({
fileId,
provider
}) {
if (typeof fileId === "object") {
return fileId;
}
if (provider == null) {
throw new Error(
"Cannot convert string fileId to provider reference without a provider ID. Use a Record<string, string> fileId or switch to the file-reference type."
);
}
return { [provider]: fileId };
}
var URL_EXTENSION_TO_MEDIA_TYPE = {
jpg: "image/jpeg",
jpeg: "image/jpeg",
png: "image/png",
gif: "image/gif",
webp: "image/webp",
svg: "image/svg+xml",
avif: "image/avif",
heic: "image/heic",
bmp: "image/bmp",
tiff: "image/tiff",
tif: "image/tiff",
pdf: "application/pdf",
mp4: "video/mp4",
webm: "video/webm",
mp3: "audio/mpeg",
wav: "audio/wav",
ogg: "audio/ogg"
};
function getMediaTypeFromUrl(url, fallbackMediaType = "application/octet-stream") {
var _a12;
try {
const pathname = new URL(url).pathname;
const fileExtension = (_a12 = pathname.split(".").pop()) == null ? void 0 : _a12.toLowerCase();
if (fileExtension && Object.hasOwn(URL_EXTENSION_TO_MEDIA_TYPE, fileExtension)) {
return URL_EXTENSION_TO_MEDIA_TYPE[fileExtension];
}
} catch (e) {
}
return fallbackMediaType;
}
// src/prompt/create-tool-model-output.ts
import { getErrorMessage } from "@ai-sdk/provider";
async function createToolModelOutput({
toolCallId,
input,
output,
tool,
errorMode
}) {
if (errorMode === "text") {
return { type: "error-text", value: getErrorMessage(output) };
} else if (errorMode === "json") {
return { type: "error-json", value: toJSONValue(output) };
}
if (tool == null ? void 0 : tool.toModelOutput) {
return await tool.toModelOutput({ toolCallId, input, output });
}
return typeof output === "string" ? { type: "text", value: output } : { type: "json", value: toJSONValue(output) };
}
function toJSONValue(value) {
return value === void 0 ? null : value;
}
// src/prompt/prepare-tool-choice.ts
function prepareToolChoice({
toolChoice
}) {
return toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : { type: "tool", toolName: toolChoice.toolName };
}
// src/prompt/prepare-tools.ts
import {
asSchema
} from "@ai-sdk/provider-utils";
// src/util/is-non-empty-object.ts
function isNonEmptyObject(object) {
return object != null && Object.keys(object).length > 0;
}
// src/prompt/prepare-tools.ts
async function prepareTools({
tools,
toolOrder,
toolsContext = {},
experimental_sandbox: sandbox
}) {
if (!isNonEmptyObject(tools)) {
return void 0;
}
const languageModelTools = [];
for (const [name12, tool] of orderToolEntries({ tools, toolOrder })) {
const toolType = tool.type;
switch (toolType) {
case void 0:
case "dynamic":
case "function": {
const description = resolveToolDescription({
tool,
toolName: name12,
toolsContext,
experimental_sandbox: sandbox
});
const providerOptions = tool.providerOptions;
const inputExamples = tool.inputExamples;
const strict = tool.strict;
languageModelTools.push({
type: "function",
name: name12,
inputSchema: await asSchema(tool.inputSchema).jsonSchema,
...description != null ? { description } : {},
...inputExamples != null ? { inputExamples } : {},
...providerOptions != null ? { providerOptions } : {},
...strict != null ? { strict } : {}
});
break;
}
case "provider": {
languageModelTools.push({
type: "provider",
name: name12,
id: tool.id,
args: tool.args
});
break;
}
default: {
const exhaustiveCheck = toolType;
throw new Error(`Unsupported tool type: ${exhaustiveCheck}`);
}
}
}
return languageModelTools;
}
function orderToolEntries({
tools,
toolOrder
}) {
if (toolOrder == null) {
return Object.entries(tools);
}
const toolEntries = Object.entries(tools);
const orderedTools = toolEntries.filter(([name12]) => toolOrder.includes(name12)).sort(
([nameA], [nameB]) => toolOrder.indexOf(nameA) - toolOrder.indexOf(nameB)
);
const unorderedTools = toolEntries.filter(([name12]) => !toolOrder.includes(name12)).sort(([nameA], [nameB]) => nameA < nameB ? -1 : nameA > nameB ? 1 : 0);
return [...orderedTools, ...unorderedTools];
}
function resolveToolDescription({
tool,
toolName,
toolsContext,
experimental_sandbox: sandbox
}) {
return tool.description === void 0 ? void 0 : typeof tool.description === "string" ? tool.description : tool.description({
context: toolsContext[toolName],
experimental_sandbox: sandbox
});
}
// src/prompt/standardize-prompt.ts
import { InvalidPromptError } from "@ai-sdk/provider";
import {
asArray as asArray2,
safeValidateTypes
} from "@ai-sdk/provider-utils";
import { z as z5 } from "zod/v4";
// src/prompt/message.ts
import { z as z4 } from "zod/v4";
// src/types/provider-metadata.ts
import { z as z2 } from "zod/v4";
// src/types/json-value.ts
import { z } from "zod/v4";
var jsonValueSchema = z.lazy(
() => z.union([
z.null(),
z.string(),
z.number(),
z.boolean(),
z.record(z.string(), jsonValueSchema.optional()),
z.array(jsonValueSchema)
])
);
// src/types/provider-metadata.ts
var providerMetadataSchema = z2.record(
z2.string(),
z2.record(z2.string(), jsonValueSchema.optional())
);
// src/prompt/content-part.ts
import {
isBuffer as isBuffer2
} from "@ai-sdk/provider-utils";
import { z as z3 } from "zod/v4";
var fileInlineDataSchema = z3.union([
z3.string(),
z3.instanceof(Uint8Array),
z3.instanceof(ArrayBuffer),
z3.custom(isBuffer2, { message: "Must be a Buffer" })
]);
var providerReferenceSchema = z3.record(z3.string(), z3.string());
var textPartSchema = z3.object({
type: z3.literal("text"),
text: z3.string(),
providerOptions: providerMetadataSchema.optional()
});
var imagePartSchema = z3.object({
type: z3.literal("image"),
image: z3.union([
fileInlineDataSchema,
z3.instanceof(URL),
providerReferenceSchema
]),
mediaType: z3.string().optional(),
providerOptions: providerMetadataSchema.optional()
});
var taggedFileDataSchema = z3.discriminatedUnion("type", [
z3.object({ type: z3.literal("data"), data: fileInlineDataSchema }),
z3.object({ type: z3.literal("url"), url: z3.instanceof(URL) }),
z3.object({
type: z3.literal("reference"),
reference: providerReferenceSchema
}),
z3.object({ type: z3.literal("text"), text: z3.string() })
]);
var taggedReasoningFileDataSchema = z3.discriminatedUnion("type", [
z3.object({ type: z3.literal("data"), data: fileInlineDataSchema }),
z3.object({ type: z3.literal("url"), url: z3.instanceof(URL) })
]);
var filePartSchema = z3.object({
type: z3.literal("file"),
data: z3.union([
taggedFileDataSchema,
fileInlineDataSchema,
z3.instanceof(URL),
providerReferenceSchema
]),
filename: z3.string().optional(),
mediaType: z3.string(),
providerOptions: providerMetadataSchema.optional()
});
var reasoningPartSchema = z3.object({
type: z3.literal("reasoning"),
text: z3.string(),
providerOptions: providerMetadataSchema.optional()
});
var customPartSchema = z3.object({
type: z3.literal("custom"),
kind: z3.string().transform((value) => value),
providerOptions: providerMetadataSchema.optional()
});
var reasoningFilePartSchema = z3.object({
type: z3.literal("reasoning-file"),
data: z3.union([
taggedReasoningFileDataSchema,
fileInlineDataSchema,
z3.instanceof(URL)
]),
mediaType: z3.string(),
providerOptions: providerMetadataSchema.optional()
});
var toolCallPartSchema = z3.object({
type: z3.literal("tool-call"),
toolCallId: z3.string(),
toolName: z3.string(),
input: z3.unknown(),
providerOptions: providerMetadataSchema.optional(),
providerExecuted: z3.boolean().optional()
});
var outputSchema = z3.discriminatedUnion(
"type",
[
z3.object({
type: z3.literal("text"),
value: z3.string(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
type: z3.literal("json"),
value: jsonValueSchema,
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
type: z3.literal("execution-denied"),
reason: z3.string().optional(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
type: z3.literal("error-text"),
value: z3.string(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
type: z3.literal("error-json"),
value: jsonValueSchema,
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
type: z3.literal("content"),
value: z3.array(
z3.union([
z3.object({
type: z3.literal("text"),
text: z3.string(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
type: z3.literal("file"),
data: taggedFileDataSchema,
mediaType: z3.string(),
filename: z3.string().optional(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
// Deprecated.
type: z3.literal("file-data"),
data: z3.string(),
mediaType: z3.string(),
filename: z3.string().optional(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
// Deprecated.
type: z3.literal("file-url"),
url: z3.string(),
mediaType: z3.string().optional(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
// Deprecated.
type: z3.literal("file-id"),
fileId: z3.union([z3.string(), z3.record(z3.string(), z3.string())]),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
// Deprecated.
type: z3.literal("file-reference"),
providerReference: z3.record(z3.string(), z3.string()),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
// Deprecated.
type: z3.literal("image-data"),
data: z3.string(),
mediaType: z3.string(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
// Deprecated.
type: z3.literal("image-url"),
url: z3.string(),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
// Deprecated.
type: z3.literal("image-file-id"),
fileId: z3.union([z3.string(), z3.record(z3.string(), z3.string())]),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
// Deprecated.
type: z3.literal("image-file-reference"),
providerReference: z3.record(z3.string(), z3.string()),
providerOptions: providerMetadataSchema.optional()
}),
z3.object({
type: z3.literal("custom"),
providerOptions: providerMetadataSchema.optional()
})
])
)
})
]
);
var toolResultPartSchema = z3.object({
type: z3.literal("tool-result"),
toolCallId: z3.string(),
toolName: z3.string(),
output: outputSchema,
providerOptions: providerMetadataSchema.optional()
});
var toolApprovalRequestSchema = z3.object({
type: z3.literal("tool-approval-request"),
approvalId: z3.string(),
toolCallId: z3.string()
});
var toolApprovalResponseSchema = z3.object({
type: z3.literal("tool-approval-response"),
approvalId: z3.string(),
approved: z3.boolean(),
reason: z3.string().optional()
});
// src/prompt/message.ts
var systemModelMessageSchema = z4.object(
{
role: z4.literal("system"),
content: z4.string(),
providerOptions: providerMetadataSchema.optional()
}
);
var userModelMessageSchema = z4.object({
role: z4.literal("user"),
content: z4.union([
z4.string(),
z4.array(z4.union([textPartSchema, imagePartSchema, filePartSchema]))
]),
providerOptions: providerMetadataSchema.optional()
});
var assistantModelMessageSchema = z4.object({
role: z4.literal("assistant"),
content: z4.union([
z4.string(),
z4.array(
z4.union([
textPartSchema,
customPartSchema,
filePartSchema,
reasoningPartSchema,
reasoningFilePartSchema,
toolCallPartSchema,
toolResultPartSchema,
toolApprovalRequestSchema
])
)
]),
providerOptions: providerMetadataSchema.optional()
});
var toolModelMessageSchema = z4.object({
role: z4.literal("tool"),
content: z4.array(z4.union([toolResultPartSchema, toolApprovalResponseSchema])),
providerOptions: providerMetadataSchema.optional()
});
var modelMessageSchema = z4.union([
systemModelMessageSchema,
userModelMessageSchema,
assistantModelMessageSchema,
toolModelMessageSchema
]);
// src/prompt/standardize-prompt.ts
async function standardizePrompt({
allowSystemInMessages = false,
system,
instructions = system,
prompt,
messages
}) {
if (prompt == null && messages == null) {
throw new InvalidPromptError({
prompt,
message: "prompt or messages must be defined"
});
}
if (prompt != null && messages != null) {
throw new InvalidPromptError({
prompt,
message: "prompt and messages cannot be defined at the same time"
});
}
if (typeof instructions !== "string" && !asArray2(instructions).every((message) => message.role === "system")) {
throw new InvalidPromptError({
prompt,
message: "instructions must be a string, SystemModelMessage, or array of SystemModelMessage"
});
}
if (prompt != null && typeof prompt === "string") {
messages = [{ role: "user", content: prompt }];
} else if (prompt != null && Array.isArray(prompt)) {
messages = prompt;
} else if (messages == null) {
throw new InvalidPromptError({
prompt,
message: "prompt or messages must be defined"
});
}
if (messages.length === 0) {
throw new InvalidPromptError({
prompt,
message: "messages must not be empty"
});
}
if (!allowSystemInMessages && messages.some((message) => message.role === "system")) {
throw new InvalidPromptError({
prompt,
message: "System messages are not allowed in the prompt or messages fields. Use the instructions option instead."
});
}
const validationResult = await safeValidateTypes({
value: messages,
schema: z5.array(modelMessageSchema)
});
if (!validationResult.success) {
throw new InvalidPromptError({
prompt,
message: "The messages do not match the ModelMessage[] schema.",
cause: validationResult.error
});
}
return { messages, instructions };
}
// src/error/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;
// src/prompt/prepare-language-model-call-options.ts
function prepareLanguageModelCallOptions({
maxOutputTokens,
temperature,
topP,
topK,
presencePenalty,
frequencyPenalty,
seed,
stopSequences,
reasoning
}) {
if (maxOutputTokens != null) {
if (!Number.isInteger(maxOutputTokens)) {
throw new InvalidArgumentError({
parameter: "maxOutputTokens",
value: maxOutputTokens,
message: "maxOutputTokens must be an integer"
});
}
if (maxOutputTokens < 1) {
throw new InvalidArgumentError({
parameter: "maxOutputTokens",
value: maxOutputTokens,
message: "maxOutputTokens 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 {
maxOutputTokens,
temperature,
topP,
topK,
presencePenalty,
frequencyPenalty,
stopSequences,
seed,
reasoning
};
}
// src/util/retry-with-exponential-backoff.ts
import { APICallError } from "@ai-sdk/provider";
import { GatewayError } from "@ai-sdk/gateway";
import {
retryWithExponentialBackoff
} from "@ai-sdk/provider-utils";
// src/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;
// src/util/retry-with-exponential-backoff.ts
function getRetryDelayInMs({
error,
exponentialBackoffDelay
}) {
const headers = APICallError.isInstance(error) ? error.responseHeaders : APICallError.isInstance(error.cause) ? error.cause.responseHeaders : void 0;
if (!headers)
return exponentialBackoffDelay;
let ms;
const retryAfterMs = headers["retry-after-ms"];
if (retryAfterMs) {
const timeoutMs = parseFloat(retryAfterMs);
if (!Number.isNaN(timeoutMs)) {
ms = timeoutMs;
}
}
const retryAfter = headers["retry-after"];
if (retryAfter && ms === void 0) {
const timeoutSeconds = parseFloat(retryAfter);
if (!Number.isNaN(timeoutSeconds)) {
ms = timeoutSeconds * 1e3;
} else {
ms = Date.parse(retryAfter) - Date.now();
}
}
if (ms != null && !Number.isNaN(ms) && 0 <= ms && (ms < 60 * 1e3 || ms < exponentialBackoffDelay)) {
retu