UNPKG

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.

22,902 lines • 834 kB
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
import { GatewayAuthenticationError, GatewayError, createGateway, gateway, gateway as gateway$1 } from "@ai-sdk/gateway";
import { DEFAULT_MAX_DOWNLOAD_SIZE, DelayedPromise, DownloadError, DownloadError as DownloadError$1, EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL, EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER, asArray, asSchema, asSchema as asSchema$1, cancelResponseBody, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertUint8ArrayToBase64, createIdGenerator, createIdGenerator as createIdGenerator$1, delay, detectMediaType, dynamicTool, executeTool, experimental_getToolCaller, experimental_toolCaller, fetchUntrustedUrl, filterNullable, generateId, generateId as generateId$1, getErrorMessage, getRuntimeEnvironmentUserAgent, getTopLevelMediaType, getWebSocketConstructor, isAbortError, isArrayBuffer, isBuffer, isExecutableTool, isFullMediaType, isNonNullable, isProviderReference, isProviderStreamError, isUint8Array, isUrlSupported, jsonSchema, jsonSchema as jsonSchema$1, lazySchema, normalizeHeaders, parseJsonEventStream, parseJsonEventStream as parseJsonEventStream$1, readResponseWithSizeLimit, readWebSocketMessageText, redactTelemetryValue, resolve, retryWithExponentialBackoff, safeParseJSON, safeValidateTypes, toWebSocketUrl, tool, tool as tool$1, validateTypes, waitForWebSocketBufferDrain, withUserAgentSuffix, zodSchema, zodSchema as zodSchema$1 } from "@ai-sdk/provider-utils";
import { AISDKError, AISDKError as AISDKError$1, APICallError, APICallError as APICallError$1, EmptyResponseBodyError, EmptyResponseBodyError as EmptyResponseBodyError$1, Experimental_DecisionRefusalError, Experimental_DecisionRefusalError as Experimental_DecisionRefusalError$1, Experimental_DecisionUnsupportedQuestionTypeError, Experimental_DecisionUnsupportedQuestionTypeError as Experimental_DecisionUnsupportedQuestionTypeError$1, Experimental_ExtractionRefusalError, Experimental_ExtractionRefusalError as Experimental_ExtractionRefusalError$1, Experimental_ExtractionUnsupportedFieldTypeError, Experimental_ExtractionUnsupportedFieldTypeError as Experimental_ExtractionUnsupportedFieldTypeError$1, InvalidPromptError, InvalidPromptError as InvalidPromptError$1, InvalidResponseDataError, InvalidResponseDataError as InvalidResponseDataError$1, JSONParseError, JSONParseError as JSONParseError$1, LoadAPIKeyError, LoadSettingError, NoContentGeneratedError, NoSuchModelError, NoSuchModelError as NoSuchModelError$1, NoSuchProviderReferenceError, TooManyEmbeddingValuesForCallError, TypeValidationError, TypeValidationError as TypeValidationError$1, UnsupportedFunctionalityError, UnsupportedFunctionalityError as UnsupportedFunctionalityError$1, getErrorMessage as getErrorMessage$1, isJSONArray, isJSONObject } from "@ai-sdk/provider";
import { NEVER, array, boolean, custom, discriminatedUnion, enum as enum$1, extend, int, literal, looseObject, maximum, minLength, never, nonnegative, number, object, optional, pipe, positive, record, refine, safeParse, startsWith, string, transform, union, unknown } from "zod/v4/mini";
import { array as array$1, boolean as boolean$1, custom as custom$1, discriminatedUnion as discriminatedUnion$1, instanceof as instanceof$1, lazy, literal as literal$1, null as null$1, number as number$1, object as object$1, record as record$1, string as string$1, union as union$1, unknown as unknown$1 } from "zod/v4";
//#region src/telemetry/get-request-origin.ts
/** Remove credentials, paths, queries, and fragments before emitting telemetry. */
function getRequestOrigin(url) {
	if (url == null) return void 0;
	try {
		const endpoint = new URL(url);
		return endpoint.protocol === "http:" || endpoint.protocol === "https:" ? endpoint.origin : void 0;
	} catch {
		return;
	}
}
/** Preserve request metadata while keeping unknown or sensitive URL fields out of results. */
function sanitizeRequestMetadata(request) {
	if (request == null || !("url" in request)) return request;
	const { url, ...rest } = request;
	const origin = getRequestOrigin(url);
	return {
		...rest,
		...origin != null ? { url: origin } : {}
	};
}
//#endregion
//#region src/error/invalid-argument-error.ts
const name$23 = "AI_InvalidArgumentError";
const marker$23 = `vercel.ai.error.${name$23}`;
const symbol$23 = Symbol.for(marker$23);
var InvalidArgumentError = class extends AISDKError$1 {
	constructor({ parameter, value, message }) {
		super({
			name: name$23,
			message: `Invalid argument for parameter ${parameter}: ${message}`
		});
		this[symbol$23] = true;
		this.parameter = parameter;
		this.value = value;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$23);
	}
};
//#endregion
//#region src/error/invalid-stream-part-error.ts
const name$22 = "AI_InvalidStreamPartError";
const marker$22 = `vercel.ai.error.${name$22}`;
const symbol$22 = Symbol.for(marker$22);
var InvalidStreamPartError = class extends AISDKError$1 {
	constructor({ chunk, message }) {
		super({
			name: name$22,
			message
		});
		this[symbol$22] = true;
		this.chunk = chunk;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$22);
	}
};
//#endregion
//#region src/error/invalid-tool-approval-error.ts
const name$21 = "AI_InvalidToolApprovalError";
const marker$21 = `vercel.ai.error.${name$21}`;
const symbol$21 = Symbol.for(marker$21);
var InvalidToolApprovalError = class extends AISDKError$1 {
	constructor({ approvalId }) {
		super({
			name: name$21,
			message: `Tool approval response references unknown approvalId: "${approvalId}". No matching tool-approval-request found in message history.`
		});
		this[symbol$21] = true;
		this.approvalId = approvalId;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$21);
	}
};
//#endregion
//#region src/error/invalid-tool-approval-signature-error.ts
const name$20 = "AI_InvalidToolApprovalSignatureError";
const marker$20 = `vercel.ai.error.${name$20}`;
const symbol$20 = Symbol.for(marker$20);
var InvalidToolApprovalSignatureError = class extends AISDKError$1 {
	constructor({ approvalId, toolCallId, reason }) {
		super({
			name: name$20,
			message: `Tool approval signature verification failed for approval "${approvalId}" (tool call "${toolCallId}"): ${reason}`
		});
		this[symbol$20] = true;
		this.approvalId = approvalId;
		this.toolCallId = toolCallId;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$20);
	}
};
//#endregion
//#region src/error/invalid-tool-input-error.ts
const name$19 = "AI_InvalidToolInputError";
const marker$19 = `vercel.ai.error.${name$19}`;
const symbol$19 = Symbol.for(marker$19);
var InvalidToolInputError = class extends AISDKError$1 {
	constructor({ toolInput, toolName, cause, message = `Invalid input for tool ${toolName}: ${getErrorMessage$1(cause)}` }) {
		super({
			name: name$19,
			message,
			cause
		});
		this[symbol$19] = true;
		this.toolInput = toolInput;
		this.toolName = toolName;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$19);
	}
};
//#endregion
//#region src/error/tool-call-not-found-for-approval-error.ts
const name$18 = "AI_ToolCallNotFoundForApprovalError";
const marker$18 = `vercel.ai.error.${name$18}`;
const symbol$18 = Symbol.for(marker$18);
var ToolCallNotFoundForApprovalError = class extends AISDKError$1 {
	constructor({ toolCallId, approvalId }) {
		super({
			name: name$18,
			message: `Tool call "${toolCallId}" not found for approval request "${approvalId}".`
		});
		this[symbol$18] = true;
		this.toolCallId = toolCallId;
		this.approvalId = approvalId;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$18);
	}
};
//#endregion
//#region src/error/missing-tool-result-error.ts
const name$17 = "AI_MissingToolResultsError";
const marker$17 = `vercel.ai.error.${name$17}`;
const symbol$17 = Symbol.for(marker$17);
var MissingToolResultsError = class extends AISDKError$1 {
	constructor({ toolCallIds }) {
		super({
			name: name$17,
			message: `Tool result${toolCallIds.length > 1 ? "s are" : " is"} missing for tool call${toolCallIds.length > 1 ? "s" : ""} ${toolCallIds.join(", ")}.`
		});
		this[symbol$17] = true;
		this.toolCallIds = toolCallIds;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$17);
	}
};
//#endregion
//#region src/error/no-image-generated-error.ts
const name$16 = "AI_NoImageGeneratedError";
const marker$16 = `vercel.ai.error.${name$16}`;
const symbol$16 = Symbol.for(marker$16);
/**
* Thrown when no image could be generated. This can have multiple causes:
*
* - The model failed to generate a response.
* - The model generated a response that could not be parsed.
*/
var NoImageGeneratedError = class extends AISDKError$1 {
	constructor({ message = "No image generated.", cause, calls, responses }) {
		super({
			name: name$16,
			message,
			cause
		});
		this[symbol$16] = true;
		this.calls = calls;
		this.responses = responses;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$16);
	}
};
//#endregion
//#region src/error/no-object-generated-error.ts
const name$15 = "AI_NoObjectGeneratedError";
const marker$15 = `vercel.ai.error.${name$15}`;
const symbol$15 = Symbol.for(marker$15);
/**
* Thrown when no object could be generated. This can have several causes:
*
* - The model failed to generate a response.
* - The model generated a response that could not be parsed.
* - The model generated a response that could not be validated against the schema.
*
* The error contains the following properties:
*
* - `text`: The text that was generated by the model. This can be the raw text or the tool call text, depending on the model.
*/
var NoObjectGeneratedError = class extends AISDKError$1 {
	constructor({ message = "No object generated.", cause, text, response, usage, finishReason }) {
		super({
			name: name$15,
			message,
			cause
		});
		this[symbol$15] = true;
		this.text = text;
		this.response = response;
		this.usage = usage;
		this.finishReason = finishReason;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$15);
	}
};
//#endregion
//#region src/error/no-output-generated-error.ts
const name$14 = "AI_NoOutputGeneratedError";
const marker$14 = `vercel.ai.error.${name$14}`;
const symbol$14 = Symbol.for(marker$14);
/**
* Thrown when no LLM output was generated, e.g. because of errors.
*/
var NoOutputGeneratedError = class extends AISDKError$1 {
	constructor({ message = "No output generated.", cause } = {}) {
		super({
			name: name$14,
			message,
			cause
		});
		this[symbol$14] = true;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$14);
	}
};
//#endregion
//#region src/error/no-speech-generated-error.ts
const name$13 = "AI_NoSpeechGeneratedError";
const marker$13 = `vercel.ai.error.${name$13}`;
const symbol$13 = Symbol.for(marker$13);
/**
* Error that is thrown when no speech audio was generated.
*/
var NoSpeechGeneratedError = class extends AISDKError$1 {
	constructor(options) {
		super({
			name: name$13,
			message: "No speech audio generated.",
			...options.cause !== void 0 && { cause: options.cause }
		});
		this[symbol$13] = true;
		this.responses = options.responses;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$13);
	}
};
//#endregion
//#region src/error/no-transcript-generated-error.ts
const name$12 = "AI_NoTranscriptGeneratedError";
const marker$12 = `vercel.ai.error.${name$12}`;
const symbol$12 = Symbol.for(marker$12);
/**
* Error that is thrown when no transcript was generated.
*/
var NoTranscriptGeneratedError = class extends AISDKError$1 {
	constructor(options) {
		super({
			name: name$12,
			message: "No transcript generated."
		});
		this[symbol$12] = true;
		this.responses = options.responses;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$12);
	}
};
//#endregion
//#region src/error/no-translation-generated-error.ts
const name$11 = "AI_NoTranslationGeneratedError";
const marker$11 = `vercel.ai.error.${name$11}`;
const symbol$11 = Symbol.for(marker$11);
/**
* Error that is thrown when no translation was generated.
*/
var NoTranslationGeneratedError = class extends AISDKError$1 {
	constructor(options) {
		super({
			name: name$11,
			message: "No translation generated."
		});
		this[symbol$11] = true;
		this.response = options.response;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$11);
	}
};
//#endregion
//#region src/error/no-video-generated-error.ts
const name$10 = "AI_NoVideoGeneratedError";
const marker$10 = `vercel.ai.error.${name$10}`;
const symbol$10 = Symbol.for(marker$10);
var NoVideoGeneratedError = class extends AISDKError$1 {
	constructor({ message = "No video generated.", cause, responses }) {
		super({
			name: name$10,
			message,
			cause
		});
		this[symbol$10] = true;
		this.responses = responses;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$10);
	}
	/**
	* @deprecated use `isInstance` instead
	*/
	static isNoVideoGeneratedError(error) {
		return error instanceof Error && error.name === name$10 && typeof error.responses !== "undefined" ? true : false;
	}
	/**
	* @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,
			responses: this.responses
		};
	}
};
//#endregion
//#region src/error/no-such-tool-error.ts
const name$9 = "AI_NoSuchToolError";
const marker$9 = `vercel.ai.error.${name$9}`;
const symbol$9 = Symbol.for(marker$9);
var NoSuchToolError = class extends AISDKError$1 {
	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: name$9,
			message
		});
		this[symbol$9] = true;
		this.toolName = toolName;
		this.availableTools = availableTools;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$9);
	}
};
//#endregion
//#region src/error/stream-provider-error.ts
const name$8 = "AI_StreamProviderError";
const marker$8 = `vercel.ai.error.${name$8}`;
const symbol$8 = Symbol.for(marker$8);
/**
* Error reported by a provider after a model response stream has started.
*/
var StreamProviderError = class extends AISDKError$1 {
	constructor({ message, type, code, statusCode, isRetryable = isRetryableStatusCode$1(statusCode), data, cause }) {
		super({
			name: name$8,
			message,
			cause
		});
		this[symbol$8] = true;
		this.type = type;
		this.code = code;
		this.statusCode = statusCode;
		this.isRetryable = isRetryable;
		this.data = data;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$8);
	}
};
function isRetryableStatusCode$1(statusCode) {
	return statusCode != null && (statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500);
}
//#endregion
//#region src/error/tool-call-repair-error.ts
const name$7 = "AI_ToolCallRepairError";
const marker$7 = `vercel.ai.error.${name$7}`;
const symbol$7 = Symbol.for(marker$7);
var ToolCallRepairError = class extends AISDKError$1 {
	constructor({ cause, originalError, message = `Error repairing tool call: ${getErrorMessage$1(cause)}` }) {
		super({
			name: name$7,
			message,
			cause
		});
		this[symbol$7] = true;
		this.originalError = originalError;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$7);
	}
};
//#endregion
//#region src/error/tool-choice-violation-error.ts
const name$6 = "AI_ToolChoiceViolationError";
const marker$6 = `vercel.ai.error.${name$6}`;
const symbol$6 = Symbol.for(marker$6);
/**
* Thrown when a model response does not satisfy an enforced tool choice.
*/
var ToolChoiceViolationError = class extends AISDKError$1 {
	constructor({ toolChoice, finishReason, provider, modelId, content, message = toolChoice.type === "none" ? "Model response contained a tool call even though tool choice was none." : toolChoice.type === "required" ? "Model response did not contain a tool call even though tool choice was required." : `Model response did not contain a call to the required tool '${toolChoice.toolName}'.` }) {
		super({
			name: name$6,
			message
		});
		this[symbol$6] = true;
		this.toolChoice = toolChoice;
		this.finishReason = finishReason;
		this.provider = provider;
		this.modelId = modelId;
		this.content = content;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$6);
	}
};
//#endregion
//#region src/error/unsupported-model-version-error.ts
/**
* Error that is thrown when a model with an unsupported version is used.
*/
var UnsupportedModelVersionError = class extends AISDKError$1 {
	constructor(options) {
		super({
			name: "AI_UnsupportedModelVersionError",
			message: `Unsupported model version ${options.version} for provider "${options.provider}" and model "${options.modelId}". AI SDK 5 only supports models that implement specification version "v2".`
		});
		this.version = options.version;
		this.provider = options.provider;
		this.modelId = options.modelId;
	}
};
//#endregion
//#region src/error/ui-message-stream-error.ts
const name$5 = "AI_UIMessageStreamError";
const marker$5 = `vercel.ai.error.${name$5}`;
const symbol$5 = Symbol.for(marker$5);
/**
* Error thrown when a UI message stream reports an error or contains invalid
* or out-of-sequence chunks.
*
* This typically occurs when:
* - An error chunk is received
* - A delta chunk is received without a corresponding start chunk
* - An end chunk is received without a corresponding start chunk
* - A tool invocation is not found for the given toolCallId
*
* @see https://ai-sdk.dev/docs/reference/ai-sdk-errors/ai-ui-message-stream-error
*/
var UIMessageStreamError = class extends AISDKError$1 {
	constructor({ chunkType, chunkId, message }) {
		super({
			name: name$5,
			message
		});
		this[symbol$5] = true;
		this.chunkType = chunkType;
		this.chunkId = chunkId;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$5);
	}
};
//#endregion
//#region src/prompt/invalid-data-content-error.ts
const name$4 = "AI_InvalidDataContentError";
const marker$4 = `vercel.ai.error.${name$4}`;
const symbol$4 = Symbol.for(marker$4);
var InvalidDataContentError = class extends AISDKError$1 {
	constructor({ content, cause, message = `Invalid data content. Expected a base64 string, Uint8Array, ArrayBuffer, or Buffer, but got ${typeof content}.` }) {
		super({
			name: name$4,
			message,
			cause
		});
		this[symbol$4] = true;
		this.content = content;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$4);
	}
};
//#endregion
//#region src/prompt/invalid-message-role-error.ts
const name$3 = "AI_InvalidMessageRoleError";
const marker$3 = `vercel.ai.error.${name$3}`;
const symbol$3 = Symbol.for(marker$3);
var InvalidMessageRoleError = class extends AISDKError$1 {
	constructor({ role, message = `Invalid message role: '${role}'. Must be one of: "system", "user", "assistant", "tool".` }) {
		super({
			name: name$3,
			message
		});
		this[symbol$3] = true;
		this.role = role;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$3);
	}
};
//#endregion
//#region src/prompt/message-conversion-error.ts
const name$2 = "AI_MessageConversionError";
const marker$2 = `vercel.ai.error.${name$2}`;
const symbol$2 = Symbol.for(marker$2);
var MessageConversionError = class extends AISDKError$1 {
	constructor({ originalMessage, message }) {
		super({
			name: name$2,
			message
		});
		this[symbol$2] = true;
		this.originalMessage = originalMessage;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$2);
	}
};
//#endregion
//#region src/util/retry-error.ts
const name$1 = "AI_RetryError";
const marker$1 = `vercel.ai.error.${name$1}`;
const symbol$1 = Symbol.for(marker$1);
var RetryError = class extends AISDKError$1 {
	constructor({ message, reason, errors }) {
		super({
			name: name$1,
			message
		});
		this[symbol$1] = true;
		this.reason = reason;
		this.errors = errors;
		this.lastError = errors[errors.length - 1];
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker$1);
	}
};
//#endregion
//#region src/error/index.ts
/** @deprecated Use `Experimental_DecisionUnsupportedQuestionTypeError` instead. */
const Experimental_EvaluationUnsupportedQuestionTypeError = Experimental_DecisionUnsupportedQuestionTypeError$1;
//#endregion
//#region src/logger/deprecations.ts
const deprecationCodes = /* @__PURE__ */ new Map([
	["generateObject", "AISDK_DEP_GENERATE_OBJECT"],
	["streamObject", "AISDK_DEP_STREAM_OBJECT"],
	["experimental_generateSpeech", "AISDK_DEP_EXPERIMENTAL_GENERATE_SPEECH"],
	["experimental_transcribe", "AISDK_DEP_EXPERIMENTAL_TRANSCRIBE"],
	["\"image\" content part", "AISDK_DEP_IMAGE_CONTENT_PART"],
	["\"tool-result\" content of type \"file-data\"", "AISDK_DEP_TOOL_RESULT_FILE_DATA"],
	["\"tool-result\" content of type \"file-url\"", "AISDK_DEP_TOOL_RESULT_FILE_URL"],
	["\"tool-result\" content of type \"file-id\"", "AISDK_DEP_TOOL_RESULT_FILE_ID"],
	["\"tool-result\" content of type \"file-reference\"", "AISDK_DEP_TOOL_RESULT_FILE_REFERENCE"],
	["\"tool-result\" content of type \"image-data\"", "AISDK_DEP_TOOL_RESULT_IMAGE_DATA"],
	["\"tool-result\" content of type \"image-url\"", "AISDK_DEP_TOOL_RESULT_IMAGE_URL"],
	["\"tool-result\" content of type \"image-file-id\"", "AISDK_DEP_TOOL_RESULT_IMAGE_FILE_ID"],
	["\"tool-result\" content of type \"image-file-reference\"", "AISDK_DEP_TOOL_RESULT_IMAGE_FILE_REFERENCE"],
	["rawInput in output-error UI message parts", "AISDK_DEP_UI_MESSAGE_RAW_INPUT"]
]);
/**
* Escape punctuation and UTF-16 code units without losing case or collapsing
* distinct settings. Underscores are escaped too, so `__` separates code parts.
*/
function encodeCodePart(value) {
	return value.replace(/[^a-zA-Z0-9]/g, (character) => `_${character.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0")}`);
}
function getDeprecationCode({ setting, provider }) {
	if (provider == null) return deprecationCodes.get(setting) ?? `AISDK_DEP_SETTING_${encodeCodePart(setting)}`;
	return `AISDK_DEP_PROVIDER_${encodeCodePart(provider)}__${encodeCodePart(setting)}`;
}
//#endregion
//#region src/logger/log-warnings.ts
/**
* Formats a warning object into a human-readable string with clear AI SDK branding.
*
* @param options - The options for formatting the warning.
* @param options.warning - The warning to format.
* @param options.provider - The provider id used for the call, if scoped to a specific provider.
* @param options.model - The model id used for the call, if scoped to a specific provider.
* @returns A formatted warning message string.
*/
function formatWarning({ warning, provider, model }) {
	const prefix = `AI SDK Warning${provider != null && model != null ? ` (${provider} / ${model})` : ""}:`;
	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)}`;
	}
}
const FIRST_WARNING_INFO_MESSAGE = "AI SDK Warning System: To turn off warning logging, set the AI_SDK_LOG_WARNINGS global to false.";
let hasLoggedBefore = false;
const emittedDeprecationCodes = /* @__PURE__ */ new Set();
function emitWarning({ message, type, code }) {
	if (typeof process !== "undefined" && typeof process.emitWarning === "function") process.emitWarning(message, code == null ? { type } : {
		type,
		code
	});
	else console.warn(code == null ? message : `[${code}] ${message}`);
}
/**
* Logs warnings to the console or uses a custom logger if configured.
*
* The behavior can be customized via the `AI_SDK_LOG_WARNINGS` global variable:
* - If set to `false`, warnings are suppressed.
* - If set to a function, that function is called with the warnings.
* - Otherwise, warnings use `process.emitWarning` when available, falling back
*   to `console.warn`. Deprecations have stable codes and are emitted once per
*   code by the default logger. Custom loggers receive every warning.
*
* @param options - The options containing warnings and context.
* @param options.warnings - The warnings to log.
* @param options.provider - The provider id used for the call, if scoped to a specific provider.
* @param options.model - The model id used for the call, if scoped to a specific provider.
*/
const 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;
		emitWarning({
			message: FIRST_WARNING_INFO_MESSAGE,
			type: "Warning"
		});
	}
	for (const warning of options.warnings) {
		const code = warning.type === "deprecated" ? getDeprecationCode({
			setting: warning.setting,
			provider: options.provider
		}) : void 0;
		if (code != null) {
			if (emittedDeprecationCodes.has(code)) continue;
			emittedDeprecationCodes.add(code);
		}
		emitWarning({
			message: formatWarning({
				warning,
				provider: options.provider,
				model: options.model
			}),
			type: warning.type === "deprecated" ? "DeprecationWarning" : "Warning",
			code
		});
	}
};
//#endregion
//#region src/util/log-v2-compatibility-warning.ts
function logV2CompatibilityWarning({ provider, modelId }) {
	logWarnings({
		warnings: [{
			type: "compatibility",
			feature: "specificationVersion",
			details: `Using v2 specification compatibility mode. Some features may not be available.`
		}],
		provider,
		model: modelId
	});
}
//#endregion
//#region src/model/as-embedding-model-v3.ts
function asEmbeddingModelV3(model) {
	if (model.specificationVersion === "v3") return model;
	logV2CompatibilityWarning({
		provider: model.provider,
		modelId: model.modelId
	});
	return new Proxy(model, { get(target, prop) {
		if (prop === "specificationVersion") return "v3";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-embedding-model-v4.ts
function asEmbeddingModelV4(model) {
	if (model.specificationVersion === "v4") return model;
	const v3Model = model.specificationVersion === "v2" ? asEmbeddingModelV3(model) : model;
	return new Proxy(v3Model, { get(target, prop) {
		if (prop === "specificationVersion") return "v4";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-image-model-v3.ts
function asImageModelV3(model) {
	if (model.specificationVersion === "v3") return model;
	logV2CompatibilityWarning({
		provider: model.provider,
		modelId: model.modelId
	});
	return new Proxy(model, { get(target, prop) {
		if (prop === "specificationVersion") return "v3";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-image-model-v4.ts
function asImageModelV4(model) {
	if (model.specificationVersion === "v4") return model;
	const v3Model = model.specificationVersion === "v2" ? asImageModelV3(model) : model;
	return new Proxy(v3Model, { get(target, prop) {
		if (prop === "specificationVersion") return "v4";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-language-model-v3.ts
function asLanguageModelV3(model) {
	if (model.specificationVersion === "v3") return model;
	logV2CompatibilityWarning({
		provider: model.provider,
		modelId: model.modelId
	});
	return new Proxy(model, { get(target, prop) {
		switch (prop) {
			case "specificationVersion": return "v3";
			case "doGenerate": return async (...args) => {
				const result = await target.doGenerate(...args);
				return {
					...result,
					finishReason: convertV2FinishReasonToV3(result.finishReason),
					usage: convertV2UsageToV3(result.usage)
				};
			};
			case "doStream": return async (...args) => {
				const result = await target.doStream(...args);
				return {
					...result,
					stream: convertV2StreamToV3(result.stream)
				};
			};
			default: return target[prop];
		}
	} });
}
function convertV2StreamToV3(stream) {
	return stream.pipeThrough(new TransformStream({ transform(chunk, controller) {
		switch (chunk.type) {
			case "finish":
				controller.enqueue({
					...chunk,
					finishReason: convertV2FinishReasonToV3(chunk.finishReason),
					usage: convertV2UsageToV3(chunk.usage)
				});
				break;
			default: controller.enqueue(chunk);
		}
	} }));
}
function convertV2FinishReasonToV3(finishReason) {
	return {
		unified: finishReason === "unknown" ? "other" : finishReason,
		raw: void 0
	};
}
function convertV2UsageToV3(usage) {
	return {
		inputTokens: {
			total: usage.inputTokens,
			noCache: void 0,
			cacheRead: usage.cachedInputTokens,
			cacheWrite: void 0
		},
		outputTokens: {
			total: usage.outputTokens,
			text: void 0,
			reasoning: usage.reasoningTokens
		},
		raw: usage.totalTokens == null ? void 0 : { totalTokens: usage.totalTokens }
	};
}
//#endregion
//#region src/model/as-language-model-v4.ts
function asLanguageModelV4(model) {
	if (model.specificationVersion === "v4") return model;
	const v3Model = model.specificationVersion === "v2" ? asLanguageModelV3(model) : model;
	return new Proxy(v3Model, { get(target, prop) {
		switch (prop) {
			case "specificationVersion": return "v4";
			case "doGenerate": return async (options) => {
				const result = await target.doGenerate({
					...options,
					prompt: convertV4PromptToV3(options.prompt)
				});
				return {
					...result,
					content: result.content.map(convertV3ContentToV4)
				};
			};
			case "doStream": return async (options) => {
				const result = await target.doStream({
					...options,
					prompt: convertV4PromptToV3(options.prompt)
				});
				return {
					...result,
					stream: convertV3StreamToV4(result.stream)
				};
			};
			default: return target[prop];
		}
	} });
}
function convertV4PromptToV3(prompt) {
	return prompt.map((message) => {
		if (message.role === "system") return message;
		return {
			...message,
			content: message.content.map((part) => {
				switch (part.type) {
					case "file": return {
						...part,
						data: convertV4FileDataToV3(part.data)
					};
					case "tool-result": return {
						...part,
						output: convertV4ToolResultOutputToV3(part.output)
					};
					default: return part;
				}
			})
		};
	});
}
function convertV4FileDataToV3(data) {
	switch (data.type) {
		case "data": return data.data;
		case "url": return data.url;
		case "reference":
		case "text": return data;
	}
}
function convertV4ToolResultOutputToV3(output) {
	if (output.type !== "content") return output;
	return {
		...output,
		value: output.value.map((part) => {
			if (part.type !== "file") return part;
			switch (part.data.type) {
				case "data": return {
					type: "file-data",
					data: typeof part.data.data === "string" ? part.data.data : convertUint8ArrayToBase64(part.data.data),
					mediaType: part.mediaType,
					filename: part.filename,
					providerOptions: part.providerOptions
				};
				case "url": return {
					type: "file-url",
					url: part.data.url.toString(),
					providerOptions: part.providerOptions
				};
				case "reference": return {
					type: "file-id",
					fileId: part.data.reference,
					providerOptions: part.providerOptions
				};
				case "text": return part;
			}
		})
	};
}
function convertV3ContentToV4(content) {
	return content.type === "file" ? {
		...content,
		data: {
			type: "data",
			data: content.data
		}
	} : content;
}
function convertV3StreamToV4(stream) {
	return stream.pipeThrough(new TransformStream({ transform(chunk, controller) {
		controller.enqueue(chunk.type === "file" ? {
			...chunk,
			data: {
				type: "data",
				data: chunk.data
			}
		} : chunk);
	} }));
}
//#endregion
//#region src/model/as-reranking-model-v4.ts
function asRerankingModelV4(model) {
	if (model.specificationVersion === "v4") return model;
	return new Proxy(model, { get(target, prop) {
		if (prop === "specificationVersion") return "v4";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-speech-model-v3.ts
function asSpeechModelV3(model) {
	if (model.specificationVersion === "v3") return model;
	logV2CompatibilityWarning({
		provider: model.provider,
		modelId: model.modelId
	});
	return new Proxy(model, { get(target, prop) {
		if (prop === "specificationVersion") return "v3";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-speech-model-v4.ts
function asSpeechModelV4(model) {
	if (model.specificationVersion === "v4") return model;
	const v3Model = model.specificationVersion === "v2" ? asSpeechModelV3(model) : model;
	return new Proxy(v3Model, { get(target, prop) {
		if (prop === "specificationVersion") return "v4";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-transcription-model-v3.ts
function asTranscriptionModelV3(model) {
	if (model.specificationVersion === "v3") return model;
	logV2CompatibilityWarning({
		provider: model.provider,
		modelId: model.modelId
	});
	return new Proxy(model, { get(target, prop) {
		if (prop === "specificationVersion") return "v3";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-transcription-model-v4.ts
function asTranscriptionModelV4(model) {
	if (model.specificationVersion === "v4") return model;
	const v3Model = model.specificationVersion === "v2" ? asTranscriptionModelV3(model) : model;
	return new Proxy(v3Model, { get(target, prop) {
		if (prop === "specificationVersion") return "v4";
		if (prop === "doGenerate") return async ({ timestampGranularities, ...options }) => {
			const result = await target.doGenerate.call(model, options);
			if (!timestampGranularities?.length) return result;
			return {
				...result,
				warnings: [...result.warnings, {
					type: "unsupported",
					feature: "timestampGranularities",
					details: `Shared timestamp granularities are not supported by ${model.specificationVersion} transcription models.`
				}]
			};
		};
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-video-model-v4.ts
function asVideoModelV4(model) {
	if (model.specificationVersion === "v4") return model;
	return new Proxy(model, { get(target, prop) {
		if (prop === "specificationVersion") return "v4";
		return target[prop];
	} });
}
//#endregion
//#region src/model/as-provider-v3.ts
function asProviderV3(provider) {
	if ("specificationVersion" in provider && provider.specificationVersion === "v3") return provider;
	const v2Provider = provider;
	return {
		specificationVersion: "v3",
		languageModel: (modelId) => asLanguageModelV3(v2Provider.languageModel(modelId)),
		embeddingModel: (modelId) => asEmbeddingModelV3(v2Provider.textEmbeddingModel(modelId)),
		imageModel: (modelId) => asImageModelV3(v2Provider.imageModel(modelId)),
		transcriptionModel: v2Provider.transcriptionModel ? (modelId) => asTranscriptionModelV3(v2Provider.transcriptionModel(modelId)) : void 0,
		speechModel: v2Provider.speechModel ? (modelId) => asSpeechModelV3(v2Provider.speechModel(modelId)) : void 0,
		rerankingModel: void 0
	};
}
//#endregion
//#region src/model/as-provider-v4.ts
function asProviderV4(provider) {
	if ("specificationVersion" in provider && provider.specificationVersion === "v4") return provider;
	const v3Provider = !("specificationVersion" in provider) || provider.specificationVersion !== "v3" ? asProviderV3(provider) : provider;
	return {
		specificationVersion: "v4",
		languageModel: (modelId) => asLanguageModelV4(v3Provider.languageModel(modelId)),
		embeddingModel: (modelId) => asEmbeddingModelV4(v3Provider.embeddingModel(modelId)),
		imageModel: (modelId) => asImageModelV4(v3Provider.imageModel(modelId)),
		transcriptionModel: v3Provider.transcriptionModel ? (modelId) => asTranscriptionModelV4(v3Provider.transcriptionModel(modelId)) : void 0,
		speechModel: v3Provider.speechModel ? (modelId) => asSpeechModelV4(v3Provider.speechModel(modelId)) : void 0,
		rerankingModel: v3Provider.rerankingModel ? (modelId) => asRerankingModelV4(v3Provider.rerankingModel(modelId)) : void 0
	};
}
//#endregion
//#region src/model/resolve-model.ts
function resolveLanguageModel(model) {
	if (typeof model === "string") return getGlobalProvider().languageModel(model);
	if (![
		"v4",
		"v3",
		"v2"
	].includes(model.specificationVersion)) {
		const unsupportedModel = model;
		throw new UnsupportedModelVersionError({
			version: unsupportedModel.specificationVersion,
			provider: unsupportedModel.provider,
			modelId: unsupportedModel.modelId
		});
	}
	return asLanguageModelV4(model);
}
function resolveEmbeddingModel(model) {
	if (typeof model === "string") return getGlobalProvider().embeddingModel(model);
	if (![
		"v4",
		"v3",
		"v2"
	].includes(model.specificationVersion)) {
		const unsupportedModel = model;
		throw new UnsupportedModelVersionError({
			version: unsupportedModel.specificationVersion,
			provider: unsupportedModel.provider,
			modelId: unsupportedModel.modelId
		});
	}
	return asEmbeddingModelV4(model);
}
function resolveTranscriptionModel(model) {
	if (typeof model === "string") return getGlobalProvider().transcriptionModel?.(model);
	if (![
		"v4",
		"v3",
		"v2"
	].includes(model.specificationVersion)) {
		const unsupportedModel = model;
		throw new UnsupportedModelVersionError({
			version: unsupportedModel.specificationVersion,
			provider: unsupportedModel.provider,
			modelId: unsupportedModel.modelId
		});
	}
	return asTranscriptionModelV4(model);
}
function resolveSpeechTranslationModel(model) {
	if (typeof model === "string") {
		const speechTranslationModel = (globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway$1).speechTranslationModel;
		if (!speechTranslationModel) throw new Error("The default provider does not support speech translation models. Please pass a provider model instance that implements the experimental speech translation model specification.");
		return speechTranslationModel(model);
	}
	if (model.specificationVersion !== "v4") {
		const unsupportedModel = model;
		throw new UnsupportedModelVersionError({
			version: unsupportedModel.specificationVersion,
			provider: unsupportedModel.provider,
			modelId: unsupportedModel.modelId
		});
	}
	return model;
}
function resolveSpeechModel(model) {
	if (typeof model === "string") return getGlobalProvider().speechModel?.(model);
	if (![
		"v4",
		"v3",
		"v2"
	].includes(model.specificationVersion)) {
		const unsupportedModel = model;
		throw new UnsupportedModelVersionError({
			version: unsupportedModel.specificationVersion,
			provider: unsupportedModel.provider,
			modelId: unsupportedModel.modelId
		});
	}
	return asSpeechModelV4(model);
}
function resolveImageModel(model) {
	if (typeof model === "string") return getGlobalProvider().imageModel(model);
	if (![
		"v4",
		"v3",
		"v2"
	].includes(model.specificationVersion)) {
		const unsupportedModel = model;
		throw new UnsupportedModelVersionError({
			version: unsupportedModel.specificationVersion,
			provider: unsupportedModel.provider,
			modelId: unsupportedModel.modelId
		});
	}
	return asImageModelV4(model);
}
function resolveVideoModel(model) {
	if (typeof model === "string") {
		const videoModel = (globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway$1).videoModel;
		if (!videoModel) throw new Error("The default provider does not support video models. Please use a Experimental_VideoModelV4 object from a provider (e.g., vertex.video(\"model-id\")).");
		return videoModel(model);
	}
	if (!["v4", "v3"].includes(model.specificationVersion)) {
		const unsupportedModel = model;
		throw new UnsupportedModelVersionError({
			version: unsupportedModel.specificationVersion,
			provider: unsupportedModel.provider,
			modelId: unsupportedModel.modelId
		});
	}
	return asVideoModelV4(model);
}
function resolveRerankingModel(model) {
	if (typeof model === "string") {
		const rerankingModel = getGlobalProvider().rerankingModel;
		if (!rerankingModel) throw new Error("The default provider does not support reranking models. Please use a RerankingModel object from a provider (e.g., gateway.rerankingModel(\"model-id\")).");
		return rerankingModel(model);
	}
	if (model.specificationVersion !== "v4" && model.specificationVersion !== "v3") {
		const unsupportedModel = model;
		throw new UnsupportedModelVersionError({
			version: unsupportedModel.specificationVersion,
			provider: unsupportedModel.provider,
			modelId: unsupportedModel.modelId
		});
	}
	return asRerankingModelV4(model);
}
function resolveDecisionModel(model) {
	if (typeof model === "string") {
		const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway$1;
		const factory = provider.decisionModel ?? provider.evaluationModel;
		if (typeof factory !== "function") throw new NoSuchModelError$1({
			modelId: model,
			modelType: "decisionModel",
			message: "The default provider does not support decision models. Pass a decision model instance or configure AI_SDK_DEFAULT_PROVIDER with a decisionModel method."
		});
		const resolvedModel = factory.call(provider, model);
		if (resolvedModel == null) throw new NoSuchModelError$1({
			modelId: model,
			modelType: "decisionModel"
		});
		model = resolvedModel;
	}
	if (model.specificationVersion !== "v4") throw new UnsupportedModelVersionError({
		version: model.specificationVersion,
		provider: model.provider,
		modelId: model.modelId
	});
	if ("doDecide" in model) return model;
	const legacyModel = model;
	return {
		specificationVersion: legacyModel.specificationVersion,
		provider: legacyModel.provider,
		modelId: legacyModel.modelId,
		supportedQuestionTypes: legacyModel.supportedQuestionTypes,
		doDecide: (options) => legacyModel.doEvaluate(options)
	};
}
function resolveExtractionModel(model) {
	const version = model.specificationVersion;
	if (version !== "v4") throw new UnsupportedModelVersionError({
		version,
		provider: model.provider,
		modelId: model.modelId
	});
	return model;
}
function getGlobalProvider() {
	return asProviderV4(globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway$1);
}
/** Internal adapter for deprecated provider factories. */
function asEvaluationModel(model) {
	if ("doEvaluate" in model && typeof model.doEvaluate === "function") return model;
	return {
		specificationVersion: model.specificationVersion,
		provider: model.provider,
		modelId: model.modelId,
		supportedQuestionTypes: model.supportedQuestionTypes,
		doDecide: (options) => model.doDecide(options),
		doEvaluate: (options) => model.doDecide(options)
	};
}
//#endregion
//#region src/prompt/clone-model-message.ts
/**
* Clone model messages while preserving URL instances. Node's structuredClone
* currently rejects URL objects, which are valid file/image prompt payloads.
*/
function cloneModelMessages(messages) {
	return cloneValue(messages, /* @__PURE__ */ new Map());
}
function cloneValue(value, seen) {
	if (value == null || typeof value !== "object") return value;
	if (seen.has(value)) return seen.get(value);
	if (value instanceof URL) {
		const copy = new URL(value.href);
		seen.set(value, copy);
		return copy;
	}
	if (Array.isArray(value)) {
		const copy = new Array(value.length);
		seen.set(value, copy);
		value.forEach((item, index) => {
			copy[index] = cloneValue(item, seen);
		});
		return copy;
	}
	if (isUint8Array(value)) {
		const copy = new Uint8Array(value);
		seen.set(value, copy);
		return copy;
	}
	if (isArrayBuffer(value)) {
		const copy = new Uint8Array(value).slice().buffer;
		seen.set(value, copy);
		return copy;
	}
	if (value instanceof Date || Object.prototype.toString.call(value) === "[object Date]") try {
		const copy = new Date(Date.prototype.getTime.call(value));
		seen.set(value, copy);
		return copy;
	} catch {}
	const copy = {};
	seen.set(value, copy);
	for (const [key, val] of Object.entries(value)) Object.defineProperty(copy, key, {
		value: cloneValue(val, seen),
		writable: true,
		enumerable: true,
		configurable: true
	});
	return copy;
}
//#endregion
//#region src/version.ts
const VERSION = "7.0.173";
//#endregion
//#region src/util/download/download.ts
/**
* Download a file from a URL.
*
* @param url - The URL to download from.
* @param maxBytes - Maximum allowed download size in bytes. Defaults to 100 MiB.
* @param abortSignal - An optional abort signal to cancel the download.
* @param fetch - An optional fetch transport.
* @returns The downloaded data and media type.
*
* @throws DownloadError if the download fails or exceeds maxBytes.
*/
const download = async ({ url, maxBytes, abortSignal, fetch }) => {
	const urlText = url.toString();
	try {
		const headers = withUserAgentSuffix({}, `ai-sdk/${VERSION}`, getRuntimeEnvironmentUserAgent());
		const response = await fetchUntrustedUrl({
			url: urlText,
			headers,
			abortSignal,
			fetch
		});
		if (!response.ok) {
			await cancelResponseBody(response);
			throw new DownloadError$1({
				url: urlText,
				statusCode: response.status,
				statusText: response.statusText
			});
		}
		return {
			data: await readResponseWithSizeLimit({
				response,
				url: urlText,
				maxBytes: maxBytes ?? DEFAULT_MAX_DOWNLOAD_SIZE
			}),
			mediaType: response.headers.get("content-type") ?? void 0
		};
	} catch (error) {
		if (DownloadError$1.isInstance(error)) throw error;
		throw new DownloadError$1({
			url: urlText,
			cause: error
		});
	}
};
//#endregion
//#region src/util/download/download-function.ts
/**
* Default download function.
* Downloads the file if it is not supported by the model.
*/
const createDefaultDownloadFunction = (download$3 = download, abortSignal) => (requestedDownloads) => Promise.all(requestedDownloads.map(async (requestedDownload) => requestedDownload.isUrlSupportedByModel ? null : await download$3({
	...requestedDownload,
	abortSignal: abortSignal ?? requestedDownload.abortSignal
})));
//#endregion
//#region src/util/merge-objects.ts
/**
* Deeply merges two objects together.
* - Properties from the `overrides` object override those in the `base` object with the same key.
* - For nested objects, the merge is performed recursively (deep merge).
* - Arrays are replaced, not merged.
* - Primitive values are replaced.
* - If both `base` and `overrides` are undefined, returns undefined.
* - If one of `base` or `overrides` is undefined, returns the other.
*
* @param base The target object to merge into
* @param overrides The source object to merge from
* @returns A new object with the merged properties, or undefined if both inputs are undefined
*/
function mergeObjects(base, overrides) {
	if (base === void 0 && overrides === void 0) return;
	if (base === void 0) return overrides;
	if (overrides === void 0) return base;
	const result = { ...base };
	for (const key in overrides) {
		if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
		if (Object.prototype.hasOwnProperty.call(overrides, key)) {
			const overridesValue = overrides[key];
			if (overridesValue === void 0) continue;
			const baseValue = key in base ? base[key] : void 0;
			const isSourceObject = overridesValue !== null && typeof overridesValue === "object" && !Array.isArray(overridesValue) && !(overridesValue instanceof Date) && !(overridesValue instanceof RegExp);
			const isTargetObject = baseValue !== null && baseValue !== void 0 && typeof baseValue === "object" && !Array.isArray(baseValue) && !(baseValue instanceof Date) && !(baseValue instanceof RegExp);
			if (isSourceObject && isTargetObject) result[key] = mergeObjects(baseValue, overridesValue);
			else result[key] = overridesValue;
		}
	}
	return result;
}
//#endregion
//#region src/prompt/data-content.ts
/**
* Converts data content to a base64-encoded string.
*
* @param content - Data content to convert.
* @returns Base64-encoded string.
*/
function convertDataContentToBase64String(content) {
	if (typeof content === "string") return content;
	return convertUint8ArrayToBase64(convertDataContentToUint8Array(content));
}
/**
* Converts data content to a Uint8Array.
*
* @param content - Data content to convert.
* @returns Uint8Array.
*/
function convertDataContentToUint8Array(content) {
	if (isUint8Array(content)) {
		if (content instanceof Uint8Array) return content;
		const { buffer, byteOffset, byteLength } = content;
		return new Uint8Array(buffer, byteOffset, byteLength);
	}
	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 (isArrayBuffer(content)) return new Uint8Array(content);
	throw new InvalidDataContentError({ content });
}
//#endregion
//#region src/prompt/split-data-url.ts
function splitDataUrl(dataUrl) {
	try {
		const [header, base64Content] = dataUrl.split(",");
		return {
			mediaType: header.split(";")[0].split(":")[1],
			base64Content
		};
	} catch {
		return {
			mediaType: void 0,
			base64Content: void 0
		};
	}
}
//#endregion
//#region 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, originalUrl) {
	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,
			...originalUrl != null ? { originalUrl } : {}
		},
		mediaType: void 0
	};
}
function convertUrlStringToFilePartData(content) {
	const result = convertUrlToFilePartData(new URL(content));
	if (result.data.type === "url" && result.data.url.toString() !== content) result.data.originalUrl = content;
	return result;
}
function convertInlineDataToFilePartData(content) {
	if (isUint8Array(content) || isArrayBuffer(content)) return {
		data: {
			type: "data",
			data: convertDataContentToUint8Array(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
	};
}
/**
* Converts any legacy-or-tagged top-level `FilePart.data` /
* `ReasoningFilePart.data` value into the tagged v4 provider prompt shape.
*
* Returns the tagged `data` together with the resolved mediaType (extracted
* from a `data:` URL when applicable).
*/
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, content.originalUrl);
		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 convertUrlStringToFilePartData(content);
	} catch {
		return convertInlineDataToFilePartData(content);
	}
	if (isUint8Array(content) || isArrayBuffer(content)) return convertInlineDataToFilePartData(content);
	if (isProviderReference(content)) return {
		data: {
			type: "reference",
			reference: content
		},
		mediaType: void 0
	};
	return convertInlineDataToFilePartData(content);
}
//#endregion
//#region src/prompt/convert-to-language-model-prompt.ts
async function convertToLanguageModelPrompt({ prompt, supportedUrls, download, abortSignal, provider }) {
	const downloadedAssets = await downloadAssets(prompt.messages, download ?? createDefaultDownloadFunction(void 0, abortSignal), supportedUrls, abortSignal);
	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?.role === "tool") {
			const lastContentPart = lastCombinedMessage.content.at(-1);
			if (lastContentPart != null && lastCombinedMessage.providerOptions != null) lastContentPart.providerOptions = mergeObjects(lastCombinedMessage.providerOptions, lastContentPart.providerOptions);
			lastCombinedMessage.content.push(...message.content);
			lastCombinedMessage.providerOptions = lastContentPart == null ? mergeObjects(lastCombinedMessage.providerOptions, message.providerOptions) : message.providerOptions;
		} 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": if (toolCallIds.size > 0) throw new MissingToolResultsError({ toolCallIds: Array.from(toolCallIds) });
	}
	if (toolCallIds.size > 0) throw new MissingToolResultsError({ toolCallIds: Array.from(toolCallIds) });
	return combinedMessages.filter((message) => message.role !== "tool" || message.content.length > 0);
}
/**
* Convert a ModelMessage to a LanguageModelV4Message.
*
* @param message - The ModelMessage to convert.
* @param downloadedAssets - A map of URLs to their downloaded data. Only
* available if the model does not support URLs, null otherwise.
*/
function convertToLanguageModelMessage({ message, downloadedAssets, 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((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 ?? 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 ?? 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((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: throw new InvalidMessageRoleError({ role });
	}
}
function convertImagePartToFilePart(part) {
	if (part.type !== "image") return part;
	return {
		type: "file",
		data: part.image,
		mediaType: part.mediaType ?? "image",
		providerOptions: part.providerOptions
	};
}
/**
* Downloads files from URLs in the user messages.
*/
async function downloadAssets(messages, download, supportedUrls, abortSignal) {
	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) {
				const filePart = getDownloadableFilePart(contentPart);
				if (filePart != null) downloadableFiles.push(filePart);
			}
		}
		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) {
				const filePart = getDownloadableFilePart(contentPart);
				if (filePart != null) downloadableFiles.push(filePart);
			}
		}
	}
	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,
		abortSignal,
		isUrlSupportedByModel: part.mediaType != null && isUrlSupported({
			url: part.data.url.toString(),
			mediaType: part.mediaType,
			supportedUrls
		})
	}));
	const downloadedFiles = await download(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));
}
/**
* Resolves the tool result content parts that point at a remote file to the
* tagged file shape, including the deprecated `file-url` and `image-url`
* types, so that they are downloaded and inlined exactly like their `file`
* replacement. Returns `undefined` for content that is already inline or
* provider-referenced.
*/
function getDownloadableFilePart(contentPart) {
	switch (contentPart.type) {
		case "file": return contentPart;
		case "file-url": return {
			type: "file",
			data: {
				type: "url",
				url: new URL(contentPart.url)
			},
			mediaType: contentPart.mediaType ?? getMediaTypeFromUrl(contentPart.url),
			providerOptions: contentPart.providerOptions
		};
		case "image-url": return {
			type: "file",
			data: {
				type: "url",
				url: new URL(contentPart.url)
			},
			mediaType: "image",
			providerOptions: contentPart.providerOptions
		};
		default: return;
	}
}
/**
* Resolves file data and media type for a remote tool result content part: the downloaded
* bytes when the asset was fetched, otherwise the URL reference. `originalUrl`
* is preserved when the URL string does not round-trip through `URL`.
*/
function resolveDownloadedFile({ url, originalUrl, downloadedAssets, mediaType }) {
	const convertedPart = convertPartToLanguageModelPart({
		type: "file",
		data: {
			type: "url",
			url,
			...url.toString() !== originalUrl ? { originalUrl } : {}
		},
		mediaType
	}, downloadedAssets);
	return {
		data: convertedPart.data,
		mediaType: convertedPart.mediaType
	};
}
/**
* Convert part of a user message to a LanguageModelV4Part.
*
* @param part - The part to convert.
* @param downloadedAssets - A map of URLs to their downloaded data. Only
* available if the model does not support URLs, null otherwise.
* @returns The converted part.
*/
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 ?? 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, warnings = [], downloadedAssets }) {
	if (output.type !== "content") return output;
	return {
		type: "content",
		value: output.value.map((item) => {
			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 = item.mediaType ?? getMediaTypeFromUrl(item.url);
					const url = new URL(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",
						...resolveDownloadedFile({
							url,
							originalUrl: item.url,
							downloadedAssets,
							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": {
					const url = new URL(item.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",
						...resolveDownloadedFile({
							url,
							originalUrl: item.url,
							downloadedAssets,
							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 };
}
const 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") {
	try {
		const fileExtension = new URL(url).pathname.split(".").pop()?.toLowerCase();
		if (fileExtension && Object.hasOwn(URL_EXTENSION_TO_MEDIA_TYPE, fileExtension)) return URL_EXTENSION_TO_MEDIA_TYPE[fileExtension];
	} catch {}
	return fallbackMediaType;
}
//#endregion
//#region src/prompt/create-tool-model-output.ts
async function createToolModelOutput({ toolCallId, input, output, tool, errorMode }) {
	if (errorMode === "text") return {
		type: "error-text",
		value: getErrorMessage$1(output)
	};
	else if (errorMode === "json") return {
		type: "error-json",
		value: toJSONValue(output)
	};
	if (tool?.toModelOutput) return await tool.toModelOutput({
		toolCallId,
		input,
		output
	});
	return typeof output === "string" ? {
		type: "text",
		value: output
	} : {
		type: "json",
		value: toJSONValue(output)
	};
}
/**
* Normalizes an in-process tool output to a plain JSON value
* (applies `toJSON`, converts `Date`, drops `undefined`, etc.)
* by round-tripping it through `JSON.stringify`.
*
* The parsed text is produced by `JSON.stringify` from a value that is
* already materialized in this process, so it is not untrusted input.
* `JSON.parse` is used deliberately instead of the secure parser from
* `@ai-sdk/provider-utils`: the secure parser rejects own `__proto__` and
* `constructor.prototype` keys, which are valid data in tool outputs
* (e.g. rows from an external API). `JSON.parse` defines `__proto__` as an
* own data property and never modifies the prototype chain, so preserving
* these keys here is safe. Do not reuse this pattern for text that comes
* from outside the process; use `parseJSON` / `safeParseJSON` instead.
*/
function toJSONValue(value) {
	if (value === void 0) return null;
	const serialized = JSON.stringify(value);
	return serialized === void 0 ? null : JSON.parse(serialized);
}
//#endregion
//#region src/prompt/prepare-language-model-call-options.ts
/**
* Validates model call options and returns a new object with normalized values.
*/
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 (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
	};
}
//#endregion
//#region src/prompt/prepare-tool-choice.ts
function prepareToolChoice({ toolChoice }) {
	return toolChoice == null ? { type: "auto" } : typeof toolChoice === "string" ? { type: toolChoice } : {
		type: "tool",
		toolName: toolChoice.toolName
	};
}
//#endregion
//#region src/util/is-non-empty-object.ts
function isNonEmptyObject(object) {
	return object != null && Object.keys(object).length > 0;
}
//#endregion
//#region src/prompt/prepare-tools.ts
async function prepareTools({ tools, toolOrder, toolsContext = {}, experimental_sandbox: sandbox }) {
	if (!isNonEmptyObject(tools)) return;
	const languageModelTools = [];
	for (const [name, tool] of orderToolEntries({
		tools,
		toolOrder
	})) {
		const toolType = tool.type;
		switch (toolType) {
			case void 0:
			case "dynamic":
			case "function": {
				const description = resolveToolDescription({
					tool,
					toolName: name,
					toolsContext,
					experimental_sandbox: sandbox
				});
				const providerOptions = tool.providerOptions;
				const inputExamples = tool.inputExamples;
				const strict = tool.strict;
				languageModelTools.push({
					type: "function",
					name,
					inputSchema: await asSchema$1(tool.inputSchema).jsonSchema,
					...description != null ? { description } : {},
					...inputExamples != null ? { inputExamples } : {},
					...providerOptions != null ? { providerOptions } : {},
					...strict != null ? { strict } : {}
				});
				break;
			}
			case "provider":
				languageModelTools.push({
					type: "provider",
					name,
					id: tool.id,
					args: tool.args
				});
				break;
			default: throw new Error(`Unsupported tool type: ${toolType}`);
		}
	}
	return languageModelTools;
}
function orderToolEntries({ tools, toolOrder }) {
	if (toolOrder == null) return Object.entries(tools);
	const toolEntries = Object.entries(tools);
	const orderedTools = toolEntries.filter(([name]) => toolOrder.includes(name)).sort(([nameA], [nameB]) => toolOrder.indexOf(nameA) - toolOrder.indexOf(nameB));
	const unorderedTools = toolEntries.filter(([name]) => !toolOrder.includes(name)).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
	});
}
//#endregion
//#region src/prompt/request-options.ts
/**
* Extracts the total timeout value in milliseconds from a TimeoutConfiguration.
*
* @param timeout - The timeout configuration.
* @returns The total timeout in milliseconds, or undefined if no timeout is configured.
*/
function getTotalTimeoutMs(timeout) {
	if (timeout == null) return;
	if (typeof timeout === "number") return timeout;
	return timeout.totalMs;
}
/**
* Extracts the step timeout value in milliseconds from a TimeoutConfiguration.
*
* @param timeout - The timeout configuration.
* @returns The step timeout in milliseconds, or undefined if no step timeout is configured.
*/
function getStepTimeoutMs(timeout) {
	if (timeout == null || typeof timeout === "number") return;
	return timeout.stepMs;
}
/**
* Extracts the first chunk timeout value in milliseconds from a TimeoutConfiguration.
* This timeout is for streaming only - it aborts if no content chunk is received within the specified duration.
*
* @param timeout - The timeout configuration.
* @returns The first chunk timeout in milliseconds, or undefined if no first chunk timeout is configured.
*/
function getFirstChunkTimeoutMs(timeout) {
	if (timeout == null || typeof timeout === "number") return;
	return timeout.firstChunkMs;
}
/**
* Extracts the chunk timeout value in milliseconds from a TimeoutConfiguration.
* This timeout is for streaming only - it aborts if no new content chunk is received within the specified duration.
*
* @param timeout - The timeout configuration.
* @returns The chunk timeout in milliseconds, or undefined if no chunk timeout is configured.
*/
function getChunkTimeoutMs(timeout) {
	if (timeout == null || typeof timeout === "number") return;
	return timeout.chunkMs;
}
function getToolTimeoutMs(timeout, toolName) {
	if (timeout == null || typeof timeout === "number") return;
	return timeout.tools?.[`${toolName}Ms`] ?? timeout.toolMs;
}
//#endregion
//#region src/prompt/standardize-prompt.ts
/**
* Converts a prompt input into a standardized prompt with model messages.
*
* @param prompt - The prompt definition to standardize.
* Set `allowSystemInMessages` to true to allow system messages in the
* `prompt` or `messages` fields. System messages in the `instructions`
* option are always allowed.
* @returns The standardized prompt.
* @throws {InvalidPromptError} When the prompt is invalid.
*/
async function standardizePrompt({ allowSystemInMessages = false, system, instructions = system, prompt, messages }) {
	messages = prompt == null ? messages : typeof prompt === "string" ? [{
		role: "user",
		content: prompt
	}] : prompt;
	if (messages.length === 0) throw new InvalidPromptError$1({
		prompt,
		message: "messages must not be empty"
	});
	if (!allowSystemInMessages && messages.some((message) => message.role === "system")) throw new InvalidPromptError$1({
		prompt,
		message: "System messages are not allowed in the prompt or messages fields. Use the instructions option instead."
	});
	return {
		messages,
		instructions
	};
}
//#endregion
//#region src/prompt/wrap-gateway-error.ts
function wrapGatewayError(error) {
	if (!GatewayAuthenticationError.isInstance(error)) return error;
	const isProductionEnv = process?.env.NODE_ENV === "production";
	const moreInfoURL = "https://ai-sdk.dev/unauthenticated-ai-gateway";
	if (isProductionEnv) return new AISDKError$1({
		name: "GatewayError",
		message: `Unauthenticated. Configure AI_GATEWAY_API_KEY or use a provider module. Learn more: ${moreInfoURL}`
	});
	return Object.assign(/* @__PURE__ */ new Error(`\u001b[1m\u001b[31mUnauthenticated request to AI Gateway.\u001b[0m

To authenticate, set the \u001b[33mAI_GATEWAY_API_KEY\u001b[0m environment variable with your API key.

Alternatively, you can use a provider module instead of the AI Gateway.

Learn more: \u001b[34m${moreInfoURL}\u001b[0m

`), { name: "GatewayAuthenticationError" });
}
//#endregion
//#region src/types/usage.ts
function asLanguageModelUsage(usage) {
	return {
		inputTokens: usage.inputTokens.total,
		inputTokenDetails: {
			noCacheTokens: usage.inputTokens.noCache,
			cacheReadTokens: usage.inputTokens.cacheRead,
			cacheWriteTokens: usage.inputTokens.cacheWrite
		},
		outputTokens: usage.outputTokens.total,
		outputTokenDetails: {
			textTokens: usage.outputTokens.text,
			reasoningTokens: usage.outputTokens.reasoning
		},
		totalTokens: addTokenCounts(usage.inputTokens.total, usage.outputTokens.total),
		raw: usage.raw
	};
}
function createNullLanguageModelUsage() {
	return {
		inputTokens: void 0,
		inputTokenDetails: {
			noCacheTokens: void 0,
			cacheReadTokens: void 0,
			cacheWriteTokens: void 0
		},
		outputTokens: void 0,
		outputTokenDetails: {
			textTokens: void 0,
			reasoningTokens: void 0
		},
		totalTokens: void 0,
		raw: void 0
	};
}
function addLanguageModelUsage(usage1, usage2) {
	const raw = isNullLanguageModelUsage(usage1) ? usage2.raw : isNullLanguageModelUsage(usage2) ? usage1.raw : void 0;
	return {
		inputTokens: addTokenCounts(usage1.inputTokens, usage2.inputTokens),
		inputTokenDetails: {
			noCacheTokens: addTokenCounts(usage1.inputTokenDetails?.noCacheTokens, usage2.inputTokenDetails?.noCacheTokens),
			cacheReadTokens: addTokenCounts(usage1.inputTokenDetails?.cacheReadTokens, usage2.inputTokenDetails?.cacheReadTokens),
			cacheWriteTokens: addTokenCounts(usage1.inputTokenDetails?.cacheWriteTokens, usage2.inputTokenDetails?.cacheWriteTokens)
		},
		outputTokens: addTokenCounts(usage1.outputTokens, usage2.outputTokens),
		outputTokenDetails: {
			textTokens: addTokenCounts(usage1.outputTokenDetails?.textTokens, usage2.outputTokenDetails?.textTokens),
			reasoningTokens: addTokenCounts(usage1.outputTokenDetails?.reasoningTokens, usage2.outputTokenDetails?.reasoningTokens)
		},
		totalTokens: addTokenCounts(usage1.totalTokens, usage2.totalTokens),
		...raw == null ? {} : { raw }
	};
}
function isNullLanguageModelUsage(usage) {
	return usage.inputTokens == null && usage.inputTokenDetails?.noCacheTokens == null && usage.inputTokenDetails?.cacheReadTokens == null && usage.inputTokenDetails?.cacheWriteTokens == null && usage.outputTokens == null && usage.outputTokenDetails?.textTokens == null && usage.outputTokenDetails?.reasoningTokens == null && usage.totalTokens == null && usage.raw == null;
}
function addTokenCounts(tokenCount1, tokenCount2) {
	return tokenCount1 == null && tokenCount2 == null ? void 0 : (tokenCount1 ?? 0) + (tokenCount2 ?? 0);
}
function addImageModelUsage(usage1, usage2) {
	return {
		inputTokens: addTokenCounts(usage1.inputTokens, usage2.inputTokens),
		outputTokens: addTokenCounts(usage1.outputTokens, usage2.outputTokens),
		totalTokens: addTokenCounts(usage1.totalTokens, usage2.totalTokens)
	};
}
//#endregion
//#region src/util/get-own.ts
/**
* Reads a property by an untrusted key, ignoring inherited prototype members.
*
* Tool sets, tool contexts, and similar lookup objects are indexed by names
* that can come from model output or client-supplied message history. Plain
* bracket access (`obj[name]`) resolves names such as `constructor`,
* `toString`, or `__proto__` to values on `Object.prototype`, which would slip
* past the `== null` / `!value` guards that treat an unknown name as "not
* present". This helper returns `undefined` unless `key` is an own property.
*/
function getOwn(obj, key) {
	return obj != null && Object.hasOwn(obj, key) ? obj[key] : void 0;
}
//#endregion
//#region src/util/merge-abort-signals.ts
/**
* Merges multiple abort sources into a single `AbortSignal`.
* The returned signal will abort when any input signal aborts or when any
* numeric timeout elapses, using the reason from the first source to abort.
*
* @param signals - Abort signals or timeout durations in milliseconds.
* `null` and `undefined` values are ignored.
* @returns An `AbortSignal` that aborts when any valid source aborts,
* or `undefined` if no valid sources are provided.
*/
function mergeAbortSignals(...signals) {
	const validSignals = filterNullable(...signals).map((signal) => typeof signal === "number" ? AbortSignal.timeout(signal) : signal);
	return validSignals.length === 0 ? void 0 : validSignals.length === 1 ? validSignals[0] : AbortSignal.any(validSignals);
}
//#endregion
//#region src/util/now.ts
function now() {
	return globalThis?.performance?.now() ?? Date.now();
}
//#endregion
//#region src/util/notify.ts
/**
* Notifies all provided callbacks with the given event in parallel.
* Errors in callbacks do not break the generation flow.
*/
async function notify(options) {
	await Promise.all(asArray(options.callbacks).map(async (callback) => {
		try {
			await callback?.(options.event);
		} catch {}
	}));
}
//#endregion
//#region src/util/retry-with-exponential-backoff.ts
function getRetryDelayInMs({ error, exponentialBackoffDelay }) {
	const headers = APICallError$1.isInstance(error) ? error.responseHeaders : APICallError$1.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 < 6e4 || ms < exponentialBackoffDelay)) return ms;
	return exponentialBackoffDelay;
}
/**
* The `retryWithExponentialBackoffRespectingRetryHeaders` strategy retries a failed API call with an exponential backoff,
* while respecting rate limit headers (retry-after-ms and retry-after) if they are provided and reasonable (0-60 seconds).
* You can configure the maximum number of retries, the initial delay, and the backoff factor.
*/
const retryWithExponentialBackoffRespectingRetryHeaders = ({ maxRetries = 2, initialDelayInMs = 2e3, backoffFactor = 2, abortSignal, additionalRetryableError } = {}) => retryWithExponentialBackoff({
	maxRetries,
	initialDelayInMs,
	backoffFactor,
	abortSignal,
	shouldRetry: async (error) => error instanceof Error && (APICallError$1.isInstance(error) && error.isRetryable === true || GatewayError.isInstance(error) && error.isRetryable === true) || additionalRetryableError != null && await additionalRetryableError(error),
	getDelayInMs: ({ error, exponentialBackoffDelay }) => getRetryDelayInMs({
		error,
		exponentialBackoffDelay
	}),
	createRetryError: ({ message, reason, errors }) => new RetryError({
		message,
		reason,
		errors
	})
});
//#endregion
//#region src/util/prepare-retries.ts
/**
* Validate and prepare retries.
*/
function prepareRetries({ maxRetries, abortSignal, additionalRetryableError, parameter = "maxRetries", defaultMaxRetries = 2 }) {
	if (maxRetries != null) {
		if (!Number.isInteger(maxRetries)) throw new InvalidArgumentError({
			parameter,
			value: maxRetries,
			message: `${parameter} must be an integer`
		});
		if (maxRetries < 0) throw new InvalidArgumentError({
			parameter,
			value: maxRetries,
			message: `${parameter} must be >= 0`
		});
	}
	const maxRetriesResult = maxRetries ?? defaultMaxRetries;
	return {
		maxRetries: maxRetriesResult,
		retry: retryWithExponentialBackoffRespectingRetryHeaders({
			maxRetries: maxRetriesResult,
			abortSignal,
			additionalRetryableError
		})
	};
}
//#endregion
//#region src/util/set-abort-timeout.ts
/**
* Schedules a timeout that aborts the given controller with a `TimeoutError`
* `DOMException`, matching the reason produced by `AbortSignal.timeout(ms)`.
*
* @param abortController - The controller to abort when the timeout elapses.
* If undefined, no timeout is scheduled.
* @param label - Human-readable label included in the error message
* (e.g. "Step", "Chunk").
* @param timeoutMs - Duration in milliseconds before the controller is aborted.
* If undefined, no timeout is scheduled.
* @returns The timeout id (suitable for passing to `clearTimeout`), or
* `undefined` if no timeout was scheduled.
*/
function setAbortTimeout({ abortController, label, timeoutMs }) {
	if (abortController == null || timeoutMs == null) return;
	return setTimeout(() => abortController.abort(new DOMException(`${label} timeout of ${timeoutMs}ms exceeded`, "TimeoutError")), timeoutMs);
}
//#endregion
//#region src/generate-text/calculate-tokens-per-second.ts
/**
* Calculates a token rate in tokens per second.
*
* Returns 0 when the token count is unknown, the duration is unknown or 0, or
* the computed rate cannot be represented as a finite JSON-safe number.
*/
function calculateTokensPerSecond({ tokens, durationMs }) {
	const tokenRate = 1e3 * (tokens ?? 0) / (durationMs ?? 0);
	return Number.isFinite(tokenRate) ? tokenRate : 0;
}
//#endregion
//#region src/generate-text/collect-tool-approvals.ts
/**
* If the last message is a tool message, this function collects all tool approvals
* from that message.
*/
function collectToolApprovals({ messages }) {
	const lastMessage = messages.at(-1);
	if (lastMessage?.role != "tool") return {
		approvedToolApprovals: [],
		deniedToolApprovals: []
	};
	const toolCallsByToolCallId = Object.create(null);
	const toolCallOrder = Object.create(null);
	let nextToolCallIndex = 0;
	for (const message of messages) if (message.role === "assistant" && typeof message.content !== "string") {
		const content = message.content;
		for (const part of content) if (part.type === "tool-call") {
			toolCallsByToolCallId[part.toolCallId] = part;
			toolCallOrder[part.toolCallId] = nextToolCallIndex++;
		}
	}
	const toolApprovalRequestsByApprovalId = Object.create(null);
	for (const message of messages) if (message.role === "assistant" && typeof message.content !== "string") {
		const content = message.content;
		for (const part of content) if (part.type === "tool-approval-request") toolApprovalRequestsByApprovalId[part.approvalId] = part;
	}
	const toolResults = Object.create(null);
	for (const part of lastMessage.content) if (part.type === "tool-result") toolResults[part.toolCallId] = part;
	const approvedToolApprovals = [];
	const deniedToolApprovals = [];
	const collectedToolCallIds = /* @__PURE__ */ new Set();
	const approvalResponses = lastMessage.content.filter((part) => part.type === "tool-approval-response");
	for (const approvalResponse of approvalResponses) {
		const approvalRequest = toolApprovalRequestsByApprovalId[approvalResponse.approvalId];
		if (approvalRequest == null) throw new InvalidToolApprovalError({ approvalId: approvalResponse.approvalId });
		const existingToolResult = toolResults[approvalRequest.toolCallId];
		if (existingToolResult != null && (approvalResponse.approved || existingToolResult.output.type !== "execution-denied")) continue;
		const toolCall = toolCallsByToolCallId[approvalRequest.toolCallId];
		if (toolCall == null) throw new ToolCallNotFoundForApprovalError({
			toolCallId: approvalRequest.toolCallId,
			approvalId: approvalRequest.approvalId
		});
		if (collectedToolCallIds.has(toolCall.toolCallId)) continue;
		collectedToolCallIds.add(toolCall.toolCallId);
		const approval = {
			approvalRequest,
			approvalResponse,
			toolCall,
			...existingToolResult != null ? { existingToolResult } : {}
		};
		if (approvalResponse.approved) approvedToolApprovals.push(approval);
		else deniedToolApprovals.push(approval);
	}
	approvedToolApprovals.sort((a, b) => toolCallOrder[a.toolCall.toolCallId] - toolCallOrder[b.toolCall.toolCallId]);
	return {
		approvedToolApprovals,
		deniedToolApprovals
	};
}
//#endregion
//#region src/generate-text/generated-file.ts
var DefaultGeneratedFile = class {
	constructor({ data, mediaType, providerMetadata }) {
		this.base64Data = typeof data === "string" ? data : void 0;
		this.uint8ArrayData = typeof data === "string" ? void 0 : convertDataContentToUint8Array(data);
		this.mediaType = mediaType;
		this.providerMetadata = providerMetadata;
	}
	get base64() {
		if (this.base64Data == null) this.base64Data = convertUint8ArrayToBase64(this.uint8ArrayData);
		return this.base64Data;
	}
	get uint8Array() {
		if (this.uint8ArrayData == null) this.uint8ArrayData = convertBase64ToUint8Array(this.base64Data);
		return this.uint8ArrayData;
	}
};
var DefaultGeneratedFileWithType = class extends DefaultGeneratedFile {
	constructor(..._args) {
		super(..._args);
		this.type = "file";
	}
};
//#endregion
//#region src/generate-text/resolve-generated-file-data.ts
async function resolveGeneratedFileData({ data, download: download$2, abortSignal, cache }) {
	if (data.type === "data") return data.data;
	const cachedData = cache?.get(data);
	if (cachedData != null) return cachedData;
	const downloadedData = download$2 == null ? (await download({
		url: data.url,
		abortSignal
	})).data : await downloadGeneratedFile({
		url: data.url,
		download: download$2,
		abortSignal
	});
	cache?.set(data, downloadedData);
	return downloadedData;
}
async function downloadGeneratedFile({ url, download, abortSignal }) {
	const [result] = await download([{
		url,
		isUrlSupportedByModel: false,
		abortSignal
	}]);
	if (result == null) throw new DownloadError$1({
		url: url.toString(),
		message: `Generated file URL ${url} must be downloaded, but the download function returned null`
	});
	return result.data;
}
//#endregion
//#region src/generate-text/convert-language-model-content.ts
async function convertLanguageModelContent({ content, toolCalls, toolOutputs, toolApprovalRequests, toolApprovalResponses, tools, download, abortSignal, generatedFileDataCache }) {
	const contentParts = [];
	const toolOutputsWithApprovalResponses = [];
	const toolOutputsWithoutApprovalResponses = [];
	const toolCallIdsWithApprovalResponses = new Set(toolApprovalResponses.map((toolApprovalResponse) => toolApprovalResponse.toolCall.toolCallId));
	for (const part of content) switch (part.type) {
		case "text":
		case "reasoning":
		case "custom":
		case "source":
			contentParts.push(part);
			break;
		case "file":
		case "reasoning-file":
			contentParts.push({
				type: part.type,
				file: new DefaultGeneratedFile({
					data: await resolveGeneratedFileData({
						data: part.data,
						download,
						abortSignal,
						cache: generatedFileDataCache
					}),
					mediaType: part.mediaType
				}),
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
			});
			break;
		case "tool-call": {
			const toolCall = toolCalls.find((toolCall) => toolCall.toolCallId === part.toolCallId);
			if (toolCall == null) throw new Error(`Tool call ${part.toolCallId} not found.`);
			contentParts.push(toolCall);
			break;
		}
		case "tool-result": {
			const toolCall = toolCalls.find((toolCall) => toolCall.toolCallId === part.toolCallId);
			if (toolCall == null) {
				const tool = getOwn(tools, part.toolName);
				if (!(tool?.type === "provider" && tool.supportsDeferredResults)) throw new Error(`Tool call ${part.toolCallId} not found.`);
				if (part.isError) contentParts.push({
					type: "tool-error",
					toolCallId: part.toolCallId,
					toolName: part.toolName,
					input: void 0,
					error: part.result,
					providerExecuted: true,
					dynamic: part.dynamic,
					...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
					...tool?.metadata != null ? { toolMetadata: tool.metadata } : {}
				});
				else contentParts.push({
					type: "tool-result",
					toolCallId: part.toolCallId,
					toolName: part.toolName,
					input: void 0,
					output: part.result,
					providerExecuted: true,
					dynamic: part.dynamic,
					...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
					...tool?.metadata != null ? { toolMetadata: tool.metadata } : {}
				});
				break;
			}
			if (part.isError) contentParts.push({
				type: "tool-error",
				toolCallId: part.toolCallId,
				toolName: part.toolName,
				input: toolCall.input,
				error: part.result,
				providerExecuted: true,
				dynamic: toolCall.dynamic,
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
				...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
			});
			else contentParts.push({
				type: "tool-result",
				toolCallId: part.toolCallId,
				toolName: part.toolName,
				input: toolCall.input,
				output: part.result,
				providerExecuted: true,
				dynamic: toolCall.dynamic,
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
				...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
			});
			break;
		}
		case "tool-approval-request": {
			const toolCall = toolCalls.find((toolCall) => toolCall.toolCallId === part.toolCallId);
			if (toolCall == null) throw new ToolCallNotFoundForApprovalError({
				toolCallId: part.toolCallId,
				approvalId: part.approvalId
			});
			contentParts.push({
				type: "tool-approval-request",
				approvalId: part.approvalId,
				toolCall
			});
			break;
		}
	}
	for (const toolOutput of toolOutputs) if (toolCallIdsWithApprovalResponses.has(toolOutput.toolCallId)) toolOutputsWithApprovalResponses.push(toolOutput);
	else toolOutputsWithoutApprovalResponses.push(toolOutput);
	return [
		...contentParts,
		...toolOutputsWithoutApprovalResponses,
		...toolApprovalRequests,
		...toolApprovalResponses,
		...toolOutputsWithApprovalResponses
	];
}
function resolveToolCallerConfiguration({ tools, toolCallers }) {
	if (tools == null || toolCallers == null) return;
	const resolved = {};
	for (const [toolName, callers] of Object.entries(toolCallers)) {
		if (!Object.prototype.hasOwnProperty.call(tools, toolName)) throw new InvalidArgumentError({
			parameter: "experimental_toolCallers",
			value: toolCallers,
			message: `unknown tool "${toolName}".`
		});
		if (callers != null) resolved[toolName] = callers;
	}
	return resolved;
}
function prepareToolsForToolCallers({ tools, toolCallers }) {
	if (tools == null || toolCallers == null) return {
		executionTools: tools,
		modelTools: tools,
		toolCallerMessages: []
	};
	const executionTools = { ...tools };
	const modelTools = { ...tools };
	const localToolsByCaller = /* @__PURE__ */ new Map();
	const toolCallerMessages = [];
	for (const [toolName, callerNames] of Object.entries(toolCallers)) {
		const tool = executionTools[toolName];
		if (tool == null) continue;
		let availableDirectly = false;
		let availableToProvider = false;
		let preparedTool = tool;
		for (const callerName of callerNames) {
			if (callerName === "AI_SDK_DIRECT_TOOL_CALL") {
				availableDirectly = true;
				continue;
			}
			const caller = experimental_getToolCaller(executionTools[callerName]);
			if (caller == null) continue;
			if (caller.type === "provider") {
				availableToProvider = true;
				preparedTool = {
					...preparedTool,
					providerOptions: caller.prepareProviderOptions(preparedTool.providerOptions)
				};
			} else {
				const localTools = localToolsByCaller.get(callerName) ?? {};
				localTools[toolName] = preparedTool;
				localToolsByCaller.set(callerName, localTools);
			}
		}
		executionTools[toolName] = preparedTool;
		if (availableDirectly || availableToProvider) modelTools[toolName] = preparedTool;
		else delete modelTools[toolName];
	}
	for (const [callerName, callerTool] of Object.entries(executionTools)) {
		const caller = experimental_getToolCaller(callerTool);
		if (caller?.type !== "local") continue;
		const callerTools = localToolsByCaller.get(callerName) ?? {};
		const boundCaller = caller.bind(callerTools);
		executionTools[callerName] = boundCaller;
		if (Object.prototype.hasOwnProperty.call(modelTools, callerName)) {
			if (caller.prepareModelMessage == null) modelTools[callerName] = boundCaller;
			else {
				const content = caller.prepareModelMessage(callerTools);
				if (content != null) toolCallerMessages.push({
					role: "user",
					content
				});
			}
		}
	}
	return {
		executionTools,
		modelTools,
		toolCallerMessages
	};
}
function appendToolCallerMessages({ messages, toolCallerMessages }) {
	if (toolCallerMessages.length === 0) return messages;
	const latestUserText = messages.findLast((message) => message.role === "user" && typeof message.content === "string")?.content;
	const existingUserText = new Set(latestUserText == null ? [] : [latestUserText]);
	const additions = toolCallerMessages.filter((message) => {
		if (typeof message.content !== "string" || existingUserText.has(message.content)) return false;
		existingUserText.add(message.content);
		return true;
	});
	return additions.length === 0 ? messages : [...messages, ...additions];
}
//#endregion
//#region src/tool-search/tool-search.ts
const toolSearchSymbol = Symbol.for("vercel.ai.toolSearch");
const toolSearchFunctionSymbol = Symbol.for("vercel.ai.toolSearch.search");
const toolSearchMaxResultsSymbol = Symbol.for("vercel.ai.toolSearch.maxResults");
/**
* Search deferred tools by name and description. The surrounding generation
* binds the search registry and makes matches available on the next step.
* Use directly or through code mode with `toolDiscovery: 'conversation'`.
*/
function toolSearch({ search, maxResults = 5 } = {}) {
	if (!Number.isSafeInteger(maxResults) || maxResults < 1) throw new InvalidArgumentError({
		parameter: "maxResults",
		value: maxResults,
		message: "maxResults must be a positive safe integer."
	});
	return Object.assign(tool$1({
		description: `${search == null ? "Search for tools by keywords in their names and descriptions." : "Search for tools matching a query."} Returns up to ${maxResults === 5 ? "five" : maxResults} matching tools. Matches become available on the next model step, after this execution finishes. Wait for their tool definitions before calling the discovered tools. If no tools match, try different keywords.`,
		inputSchema: jsonSchema$1({
			type: "object",
			properties: { query: {
				type: "string",
				minLength: 1
			} },
			required: ["query"],
			additionalProperties: false
		}),
		outputSchema: jsonSchema$1({
			type: "object",
			properties: { tools: {
				type: "array",
				items: {
					type: "object",
					properties: {
						name: { type: "string" },
						description: { type: "string" }
					},
					required: ["name"],
					additionalProperties: false
				}
			} },
			required: ["tools"],
			additionalProperties: false
		}),
		execute: () => {
			throw new Error("toolSearch must be bound by an AI SDK generation.");
		}
	}), {
		type: "function",
		[toolSearchSymbol]: true,
		[toolSearchFunctionSymbol]: search,
		[toolSearchMaxResultsSymbol]: maxResults
	});
}
function getToolSearchMaxResults(tool) {
	return tool[toolSearchMaxResultsSymbol] ?? 5;
}
function getToolSearchFunction(tool) {
	return tool[toolSearchFunctionSymbol];
}
function isToolSearch(tool) {
	return tool[toolSearchSymbol] === true;
}
//#endregion
//#region src/tool-search/prepare-tool-search.ts
/** Create discovery state for one generation, never for a shared tool instance. */
function createToolSearchState({ tools, toolCallers }) {
	const searchTools = Object.entries(tools ?? {}).filter(([, tool]) => tool.deferLoading || isToolSearch(tool));
	if (searchTools.length === 0) return (activeTools) => activeTools;
	const discovered = /* @__PURE__ */ new Set();
	const getCallers = (name) => getOwn(toolCallers, name) ?? ["AI_SDK_DIRECT_TOOL_CALL"];
	for (const [name, tool] of searchTools) if (getCallers(name).some((name) => {
		if (name === "AI_SDK_DIRECT_TOOL_CALL") return false;
		const caller = experimental_getToolCaller(tools?.[name]);
		return caller?.type !== "local" || caller.prepareModelMessage == null;
	}) || isToolSearch(tool) && tool.deferLoading) throw new InvalidArgumentError({
		parameter: "tools",
		value: name,
		message: `tool "${name}" must be callable directly or through code mode with toolDiscovery: 'conversation'. The search tool itself must not defer loading.`
	});
	return (activeTools, { toolsContext = {}, experimental_sandbox } = {}) => {
		if (activeTools == null) return;
		const entries = Object.entries(activeTools);
		return Object.fromEntries(entries.filter(([name, tool]) => !tool.deferLoading || discovered.has(name)).map(([searchName, tool]) => {
			if (!isToolSearch(tool)) return [searchName, tool];
			const callers = getCallers(searchName).filter((name) => name === "AI_SDK_DIRECT_TOOL_CALL" || Object.hasOwn(activeTools, name));
			const candidates = entries.filter(([name, candidate]) => candidate.deferLoading && !isToolSearch(candidate) && callers.some((caller) => getCallers(name).includes(caller)));
			return [searchName, {
				...tool,
				execute: async ({ query }) => {
					const availableTools = candidates.map(([name, candidate]) => {
						const description = resolveToolDescription({
							tool: candidate,
							toolName: name,
							toolsContext,
							experimental_sandbox
						});
						return {
							name,
							...description == null ? {} : { description }
						};
					});
					const toolsByName = new Map(availableTools.map((tool) => [tool.name, tool]));
					const customSearch = getToolSearchFunction(tool);
					const terms = [...new Set(tokenize(query))];
					const rankedNames = customSearch ? await customSearch({
						query,
						tools: availableTools.map((tool) => ({ ...tool }))
					}) : availableTools.map(({ name, description }) => {
						const nameTerms = tokenize(name);
						const descriptionTerms = tokenize(description ?? "");
						return {
							name,
							score: terms.reduce((score, term) => score + (nameTerms.includes(term) ? 2 : 0) + (descriptionTerms.includes(term) ? 1 : 0), 0)
						};
					}).filter((match) => match.score > 0).sort((a, b) => b.score - a.score).map((match) => match.name);
					const matches = [...new Set(rankedNames)].flatMap((name) => {
						const match = toolsByName.get(name);
						return match == null ? [] : [match];
					}).slice(0, getToolSearchMaxResults(tool));
					for (const { name } of matches) discovered.add(name);
					return { tools: matches };
				}
			}];
		}));
	};
}
function tokenize(text) {
	return text.replace(/([a-z\d])([A-Z])/g, "$1 $2").toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
}
//#endregion
//#region src/generate-text/validate-tool-context.ts
/**
* Validates a tool context value against the tool's optional context schema.
*
* When no context schema is defined, the original context value is returned as-is.
* Otherwise, the context is validated and normalized through the schema before
* being passed into tool execution and approval hooks.
*
* @throws {TypeValidationError} When the provided tool context does not match
* the tool's declared `contextSchema`.
*/
async function validateToolContext({ toolName, context, contextSchema }) {
	if (contextSchema == null) return context;
	return await validateTypes({
		value: context,
		schema: contextSchema,
		context: {
			field: "tool context",
			entityName: toolName
		}
	});
}
//#endregion
//#region src/generate-text/execute-tool-call.ts
/**
* Executes a single tool call and manages its lifecycle callbacks.
*
* This function handles the complete tool execution flow:
* 1. Invokes `onToolExecutionStart` callback before execution
* 2. Executes the tool's `execute` function with proper context
* 3. Handles streaming outputs via `onPreliminaryToolResult`
* 4. Invokes `onToolExecutionEnd` callback with success or error result
*
* @returns The tool output with performance metrics, or undefined if the tool has no execute function.
*/
async function executeToolCall({ toolCall, tools, toolsContext, callId, messages, abortSignal, timeout, experimental_sandbox: sandbox, onPreliminaryToolResult, onToolExecutionStart, onToolExecutionEnd, executeToolInTelemetryContext = async ({ execute }) => await execute(), runInTracingChannelSpan = async ({ execute }) => await execute() }) {
	const { toolName, toolCallId, input } = toolCall;
	const tool = getOwn(tools, toolName);
	if (!isExecutableTool(tool)) return;
	const context = await validateToolContext({
		toolName,
		context: getOwn(toolsContext, toolName),
		contextSchema: tool.contextSchema
	});
	const toolExecutionContext = {
		toolCall,
		messages,
		toolContext: context
	};
	const baseCallbackEvent = {
		callId,
		...toolExecutionContext
	};
	return await runInTracingChannelSpan({
		type: "executeTool",
		event: baseCallbackEvent,
		execute: async () => {
			let output;
			await notify({
				event: baseCallbackEvent,
				callbacks: onToolExecutionStart
			});
			const toolAbortSignal = mergeAbortSignals(abortSignal, getToolTimeoutMs(timeout, toolName));
			let toolExecutionMs = 0;
			try {
				await executeToolInTelemetryContext({
					callId,
					toolCallId,
					...toolExecutionContext,
					execute: async () => {
						const startTime = now();
						try {
							const stream = executeTool({
								tool,
								input,
								options: {
									toolCallId,
									messages,
									abortSignal: toolAbortSignal,
									context,
									experimental_sandbox: sandbox
								}
							});
							for await (const part of stream) if (part.type === "preliminary") onPreliminaryToolResult?.({
								...toolCall,
								type: "tool-result",
								output: part.output,
								preliminary: true
							});
							else output = part.output;
						} finally {
							toolExecutionMs = now() - startTime;
						}
					}
				});
			} catch (error) {
				const toolError = {
					type: "tool-error",
					toolCallId,
					toolName,
					input,
					error,
					dynamic: tool.type === "dynamic",
					...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {},
					...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
				};
				await notify({
					event: {
						...baseCallbackEvent,
						toolOutput: toolError,
						toolExecutionMs
					},
					callbacks: onToolExecutionEnd
				});
				return {
					output: toolError,
					toolExecutionMs
				};
			}
			const toolResult = {
				type: "tool-result",
				toolCallId,
				toolName,
				input,
				output,
				dynamic: tool.type === "dynamic",
				...toolCall.providerMetadata != null ? { providerMetadata: toolCall.providerMetadata } : {},
				...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
			};
			await notify({
				event: {
					...baseCallbackEvent,
					toolOutput: toolResult,
					toolExecutionMs
				},
				callbacks: onToolExecutionEnd
			});
			return {
				output: toolResult,
				toolExecutionMs
			};
		}
	});
}
//#endregion
//#region src/generate-text/filter-active-tools.ts
/**
* Filters the tools to only include the active tools.
* When activeTools is provided, we only include the tools that are in the list.
*
* @param tools - The tools to filter.
* @param activeTools - The active tools to include.
* @returns The filtered tools.
*/
function filterActiveTools({ tools, activeTools }) {
	if (tools == null || activeTools == null) return tools;
	return Object.fromEntries(Object.entries(tools).filter(([name]) => activeTools.includes(name)));
}
//#endregion
//#region src/generate-text/reasoning-output.ts
function unwrapReasoningFileData(data) {
	if (typeof data === "object" && data !== null && "type" in data) return data.type === "data" ? data.data : data.url;
	return data;
}
function convertFromReasoningOutputs(parts) {
	return parts.map((part) => {
		if (part.type === "reasoning") return {
			type: "reasoning",
			text: part.text,
			...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
		};
		return {
			type: "reasoning-file",
			data: part.file.base64,
			mediaType: part.file.mediaType,
			...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
		};
	});
}
function convertToReasoningOutputs(parts) {
	return parts.map((part) => {
		if (part.type === "reasoning") return {
			type: "reasoning",
			text: part.text,
			...part.providerOptions != null ? { providerMetadata: part.providerOptions } : {}
		};
		const rawData = unwrapReasoningFileData(part.data);
		return {
			type: "reasoning-file",
			file: new DefaultGeneratedFile({
				data: rawData instanceof ArrayBuffer ? new Uint8Array(rawData) : rawData instanceof URL ? rawData.toString() : rawData,
				mediaType: part.mediaType
			}),
			...part.providerOptions != null ? { providerMetadata: part.providerOptions } : {}
		};
	});
}
//#endregion
//#region src/generate-text/default-generate-text-result.ts
var DefaultGenerateTextResult = class {
	constructor(options) {
		this.initialResponseMessages = options.initialResponseMessages;
		this.steps = options.steps;
		this._output = options.output;
		this.totalUsage = options.totalUsage;
	}
	get finalStep() {
		return this.steps.at(-1);
	}
	get content() {
		return this.steps.flatMap((step) => step.content);
	}
	get text() {
		return this.finalStep.text;
	}
	get files() {
		return this.steps.flatMap((step) => step.files);
	}
	get reasoningText() {
		return this.finalStep.reasoningText;
	}
	get reasoning() {
		return convertToReasoningOutputs(this.finalStep.reasoning);
	}
	get toolCalls() {
		return this.steps.flatMap((step) => step.toolCalls);
	}
	get staticToolCalls() {
		return this.steps.flatMap((step) => step.staticToolCalls);
	}
	get dynamicToolCalls() {
		return this.steps.flatMap((step) => step.dynamicToolCalls);
	}
	get toolResults() {
		return this.steps.flatMap((step) => step.toolResults);
	}
	get staticToolResults() {
		return this.steps.flatMap((step) => step.staticToolResults);
	}
	get dynamicToolResults() {
		return this.steps.flatMap((step) => step.dynamicToolResults);
	}
	get sources() {
		return this.steps.flatMap((step) => step.sources);
	}
	get finishReason() {
		return this.finalStep.finishReason;
	}
	get rawFinishReason() {
		return this.finalStep.rawFinishReason;
	}
	get warnings() {
		return this.steps.flatMap((step) => step.warnings ?? []);
	}
	get providerMetadata() {
		return this.finalStep.providerMetadata;
	}
	get response() {
		return this.finalStep.response;
	}
	get responseMessages() {
		return [...this.initialResponseMessages, ...this.steps.flatMap((step) => step.response.messages)];
	}
	get request() {
		return this.finalStep.request;
	}
	get usage() {
		return this.totalUsage;
	}
	get output() {
		if (this._output == null) throw new NoOutputGeneratedError();
		return this._output;
	}
};
//#endregion
//#region src/generate-text/is-tool-execution-allowed-finish-reason.ts
function isToolExecutionAllowedFinishReason(finishReason) {
	return finishReason === "stop" || finishReason === "tool-calls";
}
//#endregion
//#region src/util/array-output-stream.ts
const arrayStreamParserFactories = /* @__PURE__ */ new WeakMap();
function createArrayStreamParser(output) {
	return arrayStreamParserFactories.get(output)?.();
}
/**
* Scan only new text and parse/validate each delimited element once. Keep the
* last element pending until another starts or the enclosing object closes,
* matching the partial JSON parser's treatment of an incomplete response.
* Nonstandard envelopes and malformed JSON use the existing partial parser.
*/
function createArrayOutputStreamParser(schema, skipInvalidElements) {
	let phase = 0;
	let prefix = "";
	let elementText = "";
	let depth = 0;
	let inString = false;
	let escaped = false;
	let afterComma = false;
	let pending = [];
	const elements = [];
	let publishedCount;
	async function finishElement() {
		const parsed = await safeParseJSON({ text: elementText });
		if (!parsed.success) return false;
		const validated = await safeValidateTypes({
			value: parsed.value,
			schema
		});
		if (validated.success) pending = [validated.value];
		else if (!skipInvalidElements) return false;
		elementText = "";
		return true;
	}
	function publishPending() {
		elements.push(...pending);
		pending = [];
	}
	return async (textDelta) => {
		for (const char of textDelta) {
			if (phase === 0) {
				prefix += char;
				if (char === "[") {
					if (!/^\s*\{\s*"elements"\s*:\s*\[$/.test(prefix)) return "fallback";
					phase = 1;
				} else if (prefix.length > 256) return "fallback";
				continue;
			}
			if (phase === 2 || phase === 3) {
				if (/\s/.test(char)) continue;
				if (phase === 2 && char === "}") {
					publishPending();
					phase = 3;
					continue;
				}
				return "fallback";
			}
			if (!inString && depth === 0 && (char === "," || char === "]")) {
				if (elementText.length > 0) {
					if (!await finishElement()) return "fallback";
				} else if (char === "," || afterComma) return "fallback";
				afterComma = char === ",";
				if (char === "]") phase = 2;
				continue;
			}
			if (elementText.length === 0) {
				if (/\s/.test(char)) continue;
				publishPending();
				afterComma = false;
			}
			elementText += char;
			if (inString) {
				if (escaped) escaped = false;
				else if (char === "\\") escaped = true;
				else if (char === "\"") inString = false;
			} else if (char === "\"") inString = true;
			else if (char === "{" || char === "[") depth++;
			else if (char === "}" || char === "]") depth--;
		}
		if (phase === 0 || publishedCount === elements.length) return;
		const previousCount = publishedCount ?? 0;
		const delta = (publishedCount == null ? "[" : "") + (previousCount > 0 && elements.length > previousCount ? "," : "") + elements.slice(previousCount).map((value) => JSON.stringify(value)).join(",") + (phase === 3 ? "]" : "");
		publishedCount = elements.length;
		return {
			partial: elements.slice(),
			textDelta: delta
		};
	};
}
//#endregion
//#region src/util/fix-json.ts
function fixJson(input) {
	const stack = ["ROOT"];
	let lastValidIndex = -1;
	let literalStart = null;
	let unicodeEscapeDigits = 0;
	function isHexDigit(char) {
		return char >= "0" && char <= "9" || char >= "A" && char <= "F" || char >= "a" && char <= "f";
	}
	function processValueStart(char, i, swapState) {
		switch (char) {
			case "\"":
				lastValidIndex = i;
				stack.pop();
				stack.push(swapState);
				stack.push("INSIDE_STRING");
				break;
			case "f":
			case "t":
			case "n":
				lastValidIndex = i;
				literalStart = i;
				stack.pop();
				stack.push(swapState);
				stack.push("INSIDE_LITERAL");
				break;
			case "-":
				stack.pop();
				stack.push(swapState);
				stack.push("INSIDE_NUMBER");
				break;
			case "0":
			case "1":
			case "2":
			case "3":
			case "4":
			case "5":
			case "6":
			case "7":
			case "8":
			case "9":
				lastValidIndex = i;
				stack.pop();
				stack.push(swapState);
				stack.push("INSIDE_NUMBER");
				break;
			case "{":
				lastValidIndex = i;
				stack.pop();
				stack.push(swapState);
				stack.push("INSIDE_OBJECT_START");
				break;
			case "[":
				lastValidIndex = i;
				stack.pop();
				stack.push(swapState);
				stack.push("INSIDE_ARRAY_START");
		}
	}
	function processAfterObjectValue(char, i) {
		switch (char) {
			case ",":
				stack.pop();
				stack.push("INSIDE_OBJECT_AFTER_COMMA");
				break;
			case "}":
				lastValidIndex = i;
				stack.pop();
		}
	}
	function processAfterArrayValue(char, i) {
		switch (char) {
			case ",":
				stack.pop();
				stack.push("INSIDE_ARRAY_AFTER_COMMA");
				break;
			case "]":
				lastValidIndex = i;
				stack.pop();
		}
	}
	for (let i = 0; i < input.length; i++) {
		const char = input[i];
		switch (stack[stack.length - 1]) {
			case "ROOT":
				processValueStart(char, i, "FINISH");
				break;
			case "INSIDE_OBJECT_START":
				switch (char) {
					case "\"":
						stack.pop();
						stack.push("INSIDE_OBJECT_KEY");
						break;
					case "}":
						lastValidIndex = i;
						stack.pop();
				}
				break;
			case "INSIDE_OBJECT_AFTER_COMMA":
				switch (char) {
					case "\"":
						stack.pop();
						stack.push("INSIDE_OBJECT_KEY");
				}
				break;
			case "INSIDE_OBJECT_KEY":
				switch (char) {
					case "\"":
						stack.pop();
						stack.push("INSIDE_OBJECT_AFTER_KEY");
				}
				break;
			case "INSIDE_OBJECT_AFTER_KEY":
				switch (char) {
					case ":":
						stack.pop();
						stack.push("INSIDE_OBJECT_BEFORE_VALUE");
				}
				break;
			case "INSIDE_OBJECT_BEFORE_VALUE":
				processValueStart(char, i, "INSIDE_OBJECT_AFTER_VALUE");
				break;
			case "INSIDE_OBJECT_AFTER_VALUE":
				processAfterObjectValue(char, i);
				break;
			case "INSIDE_STRING":
				switch (char) {
					case "\"":
						stack.pop();
						lastValidIndex = i;
						break;
					case "\\":
						stack.push("INSIDE_STRING_ESCAPE");
						break;
					default: lastValidIndex = i;
				}
				break;
			case "INSIDE_ARRAY_START":
				switch (char) {
					case "]":
						lastValidIndex = i;
						stack.pop();
						break;
					default: processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
				}
				break;
			case "INSIDE_ARRAY_AFTER_VALUE":
				switch (char) {
					case ",":
						stack.pop();
						stack.push("INSIDE_ARRAY_AFTER_COMMA");
						break;
					case "]":
						lastValidIndex = i;
						stack.pop();
						break;
					default: lastValidIndex = i;
				}
				break;
			case "INSIDE_ARRAY_AFTER_COMMA":
				processValueStart(char, i, "INSIDE_ARRAY_AFTER_VALUE");
				break;
			case "INSIDE_STRING_ESCAPE":
				stack.pop();
				if (char === "u") {
					unicodeEscapeDigits = 0;
					stack.push("INSIDE_STRING_UNICODE_ESCAPE");
				} else lastValidIndex = i;
				break;
			case "INSIDE_STRING_UNICODE_ESCAPE":
				if (isHexDigit(char)) {
					unicodeEscapeDigits++;
					if (unicodeEscapeDigits === 4) {
						stack.pop();
						lastValidIndex = i;
					}
				}
				break;
			case "INSIDE_NUMBER":
				switch (char) {
					case "0":
					case "1":
					case "2":
					case "3":
					case "4":
					case "5":
					case "6":
					case "7":
					case "8":
					case "9":
						lastValidIndex = i;
						break;
					case "e":
					case "E":
					case "-":
					case ".": break;
					case ",":
						stack.pop();
						if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
						if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
						break;
					case "}":
						stack.pop();
						if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
						break;
					case "]":
						stack.pop();
						if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
						break;
					default: stack.pop();
				}
				break;
			case "INSIDE_LITERAL": {
				const partialLiteral = input.substring(literalStart, i + 1);
				if (!"false".startsWith(partialLiteral) && !"true".startsWith(partialLiteral) && !"null".startsWith(partialLiteral)) {
					stack.pop();
					if (stack[stack.length - 1] === "INSIDE_OBJECT_AFTER_VALUE") processAfterObjectValue(char, i);
					else if (stack[stack.length - 1] === "INSIDE_ARRAY_AFTER_VALUE") processAfterArrayValue(char, i);
				} else lastValidIndex = i;
				break;
			}
		}
	}
	let result = input.slice(0, lastValidIndex + 1);
	for (let i = stack.length - 1; i >= 0; i--) switch (stack[i]) {
		case "INSIDE_STRING":
			result += "\"";
			break;
		case "INSIDE_OBJECT_KEY":
		case "INSIDE_OBJECT_AFTER_KEY":
		case "INSIDE_OBJECT_AFTER_COMMA":
		case "INSIDE_OBJECT_START":
		case "INSIDE_OBJECT_BEFORE_VALUE":
		case "INSIDE_OBJECT_AFTER_VALUE":
			result += "}";
			break;
		case "INSIDE_ARRAY_START":
		case "INSIDE_ARRAY_AFTER_COMMA":
		case "INSIDE_ARRAY_AFTER_VALUE":
			result += "]";
			break;
		case "INSIDE_LITERAL": {
			const partialLiteral = input.substring(literalStart, input.length);
			if ("true".startsWith(partialLiteral)) result += "true".slice(partialLiteral.length);
			else if ("false".startsWith(partialLiteral)) result += "false".slice(partialLiteral.length);
			else if ("null".startsWith(partialLiteral)) result += "null".slice(partialLiteral.length);
		}
	}
	return result;
}
//#endregion
//#region src/util/parse-partial-json.ts
async function parsePartialJson(jsonText) {
	if (jsonText === void 0) return {
		value: void 0,
		state: "undefined-input"
	};
	let result = await safeParseJSON({ text: jsonText });
	if (result.success) return {
		value: result.value,
		state: "successful-parse"
	};
	result = await safeParseJSON({ text: fixJson(jsonText) });
	if (result.success) return {
		value: result.value,
		state: "repaired-parse"
	};
	return {
		value: void 0,
		state: "failed-parse"
	};
}
//#endregion
//#region src/generate-text/output.ts
var output_exports = /* @__PURE__ */ __exportAll({
	array: () => array$2,
	choice: () => choice,
	json: () => json,
	object: () => object$2,
	text: () => text
});
/**
* Output specification for text generation.
* This is the default output mode that generates plain text.
*
* @returns An output specification for generating text.
*/
const text = () => ({
	name: "text",
	responseFormat: Promise.resolve({ type: "text" }),
	async parseCompleteOutput({ text }) {
		return text;
	},
	async parsePartialOutput({ text }) {
		return { partial: text };
	},
	createElementStreamTransform() {}
});
function object$2({ schema: inputSchema, name, description }) {
	const schema = asSchema$1(inputSchema);
	return {
		name: "object",
		responseFormat: resolve(schema.jsonSchema).then((jsonSchema) => ({
			type: "json",
			schema: jsonSchema,
			...name != null && { name },
			...description != null && { description }
		})),
		async parseCompleteOutput({ text }, context) {
			const parseResult = await safeParseJSON({ text });
			if (!parseResult.success) throw new NoObjectGeneratedError({
				...context,
				message: "No object generated: could not parse the response.",
				cause: parseResult.error,
				text
			});
			const validationResult = await safeValidateTypes({
				value: parseResult.value,
				schema
			});
			if (!validationResult.success) throw new NoObjectGeneratedError({
				...context,
				message: "No object generated: response did not match schema.",
				cause: validationResult.error,
				text
			});
			return validationResult.value;
		},
		async parsePartialOutput({ text }) {
			const result = await parsePartialJson(text);
			switch (result.state) {
				case "failed-parse":
				case "undefined-input": return;
				case "repaired-parse":
				case "successful-parse": return { partial: result.value };
			}
		},
		createElementStreamTransform() {}
	};
}
function array$2({ element: inputElementSchema, minItems, maxItems, name, description }) {
	validateArrayBound({
		name: "minItems",
		value: minItems
	});
	validateArrayBound({
		name: "maxItems",
		value: maxItems
	});
	if (minItems != null && maxItems != null && minItems > maxItems) throw new InvalidArgumentError({
		parameter: "minItems",
		value: minItems,
		message: "minItems must be less than or equal to maxItems"
	});
	const elementSchema = asSchema$1(inputElementSchema);
	const output = {
		name: "array",
		responseFormat: resolve(elementSchema.jsonSchema).then((jsonSchema) => {
			const { $schema: _$schema, definitions, $defs, ...itemSchema } = jsonSchema;
			return {
				type: "json",
				schema: {
					$schema: "http://json-schema.org/draft-07/schema#",
					...definitions != null && { definitions },
					...$defs != null && { $defs },
					type: "object",
					properties: { elements: {
						type: "array",
						items: itemSchema,
						...minItems != null && { minItems },
						...maxItems != null && { maxItems }
					} },
					required: ["elements"],
					additionalProperties: false
				},
				...name != null && { name },
				...description != null && { description }
			};
		}),
		async parseCompleteOutput({ text }, context) {
			const parseResult = await safeParseJSON({ text });
			if (!parseResult.success) throw new NoObjectGeneratedError({
				...context,
				message: "No object generated: could not parse the response.",
				cause: parseResult.error,
				text
			});
			const outerValue = parseResult.value;
			if (outerValue == null || typeof outerValue !== "object" || !("elements" in outerValue) || !Array.isArray(outerValue.elements)) throw new NoObjectGeneratedError({
				...context,
				message: "No object generated: response did not match schema.",
				cause: new TypeValidationError$1({
					value: outerValue,
					cause: "response must be an object with an elements array"
				}),
				text
			});
			const lengthValidationError = getArrayLengthValidationError({
				value: outerValue.elements,
				minItems,
				maxItems
			});
			if (lengthValidationError != null) throw new NoObjectGeneratedError({
				...context,
				message: "No object generated: response did not match schema.",
				cause: lengthValidationError,
				text
			});
			const validatedElements = [];
			for (const element of outerValue.elements) {
				const validationResult = await safeValidateTypes({
					value: element,
					schema: elementSchema
				});
				if (!validationResult.success) throw new NoObjectGeneratedError({
					...context,
					message: "No object generated: response did not match schema.",
					cause: validationResult.error,
					text
				});
				validatedElements.push(validationResult.value);
			}
			return validatedElements;
		},
		async parsePartialOutput({ text }) {
			const result = await parsePartialJson(text);
			switch (result.state) {
				case "failed-parse":
				case "undefined-input": return;
				case "repaired-parse":
				case "successful-parse": {
					const outerValue = result.value;
					if (outerValue == null || typeof outerValue !== "object" || !("elements" in outerValue) || !Array.isArray(outerValue.elements)) return;
					const rawElements = result.state === "repaired-parse" && outerValue.elements.length > 0 ? outerValue.elements.slice(0, -1) : outerValue.elements;
					const parsedElements = [];
					for (const rawElement of rawElements) {
						const validationResult = await safeValidateTypes({
							value: rawElement,
							schema: elementSchema
						});
						if (validationResult.success) parsedElements.push(validationResult.value);
					}
					return { partial: parsedElements };
				}
			}
		},
		createElementStreamTransform() {
			let publishedElements = 0;
			return new TransformStream({ transform({ partialOutput }, controller) {
				if (partialOutput != null) for (; publishedElements < partialOutput.length; publishedElements++) {
					if (maxItems != null && publishedElements >= maxItems) {
						controller.error(getArrayLengthValidationError({
							value: partialOutput,
							maxItems
						}));
						return;
					}
					controller.enqueue(partialOutput[publishedElements]);
				}
			} });
		}
	};
	const parsePartialOutput = output.parsePartialOutput;
	arrayStreamParserFactories.set(output, () => output.parsePartialOutput === parsePartialOutput ? createArrayOutputStreamParser(elementSchema, true) : void 0);
	return output;
}
function validateArrayBound({ name, value }) {
	if (value == null) return;
	if (!Number.isInteger(value)) throw new InvalidArgumentError({
		parameter: name,
		value,
		message: `${name} must be an integer`
	});
	if (value < 0) throw new InvalidArgumentError({
		parameter: name,
		value,
		message: `${name} must be greater than or equal to 0`
	});
}
function getArrayLengthValidationError({ value, minItems, maxItems }) {
	if (minItems != null && value.length < minItems) return new TypeValidationError$1({
		value,
		cause: `elements array must contain at least ${minItems} items`
	});
	if (maxItems != null && value.length > maxItems) return new TypeValidationError$1({
		value,
		cause: `elements array must contain at most ${maxItems} items`
	});
}
/**
* Output specification for choice generation.
* When the model generates a text response, it will return one of the choice options.
*
* @param options - The available choices.
* @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.
* @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description.
*
* @returns An output specification for generating a choice.
*/
const choice = ({ options: choiceOptions, name, description }) => {
	return {
		name: "choice",
		responseFormat: Promise.resolve({
			type: "json",
			schema: {
				$schema: "http://json-schema.org/draft-07/schema#",
				type: "object",
				properties: { result: {
					type: "string",
					enum: choiceOptions
				} },
				required: ["result"],
				additionalProperties: false
			},
			...name != null && { name },
			...description != null && { description }
		}),
		async parseCompleteOutput({ text }, context) {
			const parseResult = await safeParseJSON({ text });
			if (!parseResult.success) throw new NoObjectGeneratedError({
				...context,
				message: "No object generated: could not parse the response.",
				cause: parseResult.error,
				text
			});
			const outerValue = parseResult.value;
			if (outerValue == null || typeof outerValue !== "object" || !("result" in outerValue) || typeof outerValue.result !== "string" || !choiceOptions.includes(outerValue.result)) throw new NoObjectGeneratedError({
				...context,
				message: "No object generated: response did not match schema.",
				cause: new TypeValidationError$1({
					value: outerValue,
					cause: "response must be an object that contains a choice value."
				}),
				text
			});
			return outerValue.result;
		},
		async parsePartialOutput({ text }) {
			const result = await parsePartialJson(text);
			switch (result.state) {
				case "failed-parse":
				case "undefined-input": return;
				case "repaired-parse":
				case "successful-parse": {
					const outerValue = result.value;
					if (outerValue == null || typeof outerValue !== "object" || !("result" in outerValue) || typeof outerValue.result !== "string") return;
					const potentialMatches = choiceOptions.filter((choiceOption) => choiceOption.startsWith(outerValue.result));
					if (result.state === "successful-parse") return potentialMatches.includes(outerValue.result) ? { partial: outerValue.result } : void 0;
					else return potentialMatches.length === 1 ? { partial: potentialMatches[0] } : void 0;
				}
			}
		},
		createElementStreamTransform() {}
	};
};
/**
* Output specification for unstructured JSON generation.
* When the model generates a text response, it will return a JSON object.
*
* @param name - Optional name of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema name.
* @param description - Optional description of the output that should be generated. Used by some providers for additional LLM guidance, e.g. via tool or schema description.
*
* @returns An output specification for generating JSON.
*/
const json = ({ name, description } = {}) => {
	return {
		name: "json",
		responseFormat: Promise.resolve({
			type: "json",
			...name != null && { name },
			...description != null && { description }
		}),
		async parseCompleteOutput({ text }, context) {
			const parseResult = await safeParseJSON({ text });
			if (!parseResult.success) throw new NoObjectGeneratedError({
				...context,
				message: "No object generated: could not parse the response.",
				cause: parseResult.error,
				text
			});
			return parseResult.value;
		},
		async parsePartialOutput({ text }) {
			const result = await parsePartialJson(text);
			switch (result.state) {
				case "failed-parse":
				case "undefined-input": return;
				case "repaired-parse":
				case "successful-parse": return result.value === void 0 ? void 0 : { partial: result.value };
			}
		},
		createElementStreamTransform() {}
	};
};
//#endregion
//#region src/generate-text/tool-call.ts
const inputSchemaInputSymbol = Symbol("ai-sdk-tool-call-input-schema-input");
function setToolCallInputSchemaInput(toolCall, inputSchemaInput) {
	Object.defineProperty(toolCall, inputSchemaInputSymbol, { value: inputSchemaInput });
	return toolCall;
}
function getToolCallInputSchemaInput(toolCall) {
	return inputSchemaInputSymbol in toolCall ? { value: toolCall[inputSchemaInputSymbol] } : void 0;
}
//#endregion
//#region src/generate-text/parse-tool-call.ts
async function parseToolCall({ toolCall, tools, repairToolCall, refineToolInput, messages, instructions, abortSignal }) {
	try {
		if (tools == null) {
			if (toolCall.providerExecuted && toolCall.dynamic) return await refineParsedToolCallInput({
				toolCall: await parseProviderExecutedDynamicToolCall(toolCall),
				refineToolInput
			});
			throw new NoSuchToolError({ toolName: toolCall.toolName });
		}
		try {
			return await refineParsedToolCallInput({
				toolCall: await doParseToolCall({
					toolCall,
					tools
				}),
				refineToolInput
			});
		} catch (error) {
			if (repairToolCall == null || !(NoSuchToolError.isInstance(error) || InvalidToolInputError.isInstance(error))) throw error;
			let repairedToolCall = null;
			try {
				abortSignal?.throwIfAborted();
				repairedToolCall = await waitForPromiseWithAbortSignal({
					promise: repairToolCall({
						toolCall,
						tools,
						inputSchema: async ({ toolName }) => {
							const inputSchema = getOwn(tools, toolName)?.inputSchema;
							return await asSchema$1(inputSchema).jsonSchema;
						},
						instructions,
						system: instructions,
						messages,
						error,
						abortSignal
					}),
					abortSignal
				});
			} catch (repairError) {
				abortSignal?.throwIfAborted();
				throw new ToolCallRepairError({
					cause: repairError,
					originalError: error
				});
			}
			if (repairedToolCall == null) throw error;
			const parsedRepairedToolCall = await refineParsedToolCallInput({
				toolCall: await doParseToolCall({
					toolCall: repairedToolCall,
					tools
				}),
				refineToolInput
			});
			abortSignal?.throwIfAborted();
			return parsedRepairedToolCall;
		}
	} catch (error) {
		abortSignal?.throwIfAborted();
		const parsedInput = await safeParseJSON({ text: toolCall.input });
		const input = parsedInput.success ? parsedInput.value : toolCall.input;
		const tool = getOwn(tools, toolCall.toolName);
		return {
			type: "tool-call",
			toolCallId: toolCall.toolCallId,
			toolName: toolCall.toolName,
			input,
			dynamic: true,
			invalid: true,
			error,
			title: tool?.title,
			providerExecuted: toolCall.providerExecuted,
			providerMetadata: toolCall.providerMetadata,
			...tool?.metadata != null ? { toolMetadata: tool.metadata } : {}
		};
	}
}
async function waitForPromiseWithAbortSignal({ promise, abortSignal }) {
	if (abortSignal == null) return await promise;
	return await new Promise((resolve, reject) => {
		const cleanup = () => {
			abortSignal.removeEventListener("abort", onAbort);
		};
		const onAbort = () => {
			cleanup();
			reject(abortSignal.reason);
		};
		Promise.resolve(promise).then((value) => {
			cleanup();
			resolve(value);
		}).catch((error) => {
			cleanup();
			reject(error);
		});
		abortSignal.addEventListener("abort", onAbort, { once: true });
		if (abortSignal.aborted) onAbort();
	});
}
async function refineParsedToolCallInput({ toolCall, refineToolInput }) {
	const refine = getOwn(refineToolInput, toolCall.toolName);
	if (refine == null) return toolCall;
	const refinedToolCall = {
		...toolCall,
		input: await refine(toolCall.input)
	};
	const inputSchemaInput = getToolCallInputSchemaInput(toolCall);
	return inputSchemaInput == null ? refinedToolCall : setToolCallInputSchemaInput(refinedToolCall, inputSchemaInput.value);
}
async function parseProviderExecutedDynamicToolCall(toolCall) {
	const parseResult = toolCall.input.trim() === "" ? {
		success: true,
		value: {}
	} : await safeParseJSON({ text: toolCall.input });
	if (parseResult.success === false) throw new InvalidToolInputError({
		toolName: toolCall.toolName,
		toolInput: toolCall.input,
		cause: parseResult.error
	});
	return {
		type: "tool-call",
		toolCallId: toolCall.toolCallId,
		toolName: toolCall.toolName,
		input: parseResult.value,
		providerExecuted: true,
		dynamic: true,
		providerMetadata: toolCall.providerMetadata
	};
}
async function doParseToolCall({ toolCall, tools }) {
	const toolName = toolCall.toolName;
	const tool = getOwn(tools, toolName);
	if (tool == null) {
		if (toolCall.providerExecuted && toolCall.dynamic) return await parseProviderExecutedDynamicToolCall(toolCall);
		throw new NoSuchToolError({
			toolName: toolCall.toolName,
			availableTools: Object.keys(tools)
		});
	}
	const schema = asSchema$1(tool.inputSchema);
	const parseResult = toolCall.input.trim() === "" ? await safeValidateTypes({
		value: {},
		schema
	}) : await safeParseJSON({
		text: toolCall.input,
		schema
	});
	if (parseResult.success === false) throw new InvalidToolInputError({
		toolName,
		toolInput: toolCall.input,
		cause: parseResult.error
	});
	return setToolCallInputSchemaInput(tool.type === "dynamic" ? {
		type: "tool-call",
		toolCallId: toolCall.toolCallId,
		toolName: toolCall.toolName,
		input: parseResult.value,
		providerExecuted: toolCall.providerExecuted,
		providerMetadata: toolCall.providerMetadata,
		...tool.metadata != null ? { toolMetadata: tool.metadata } : {},
		dynamic: true,
		title: tool.title
	} : {
		type: "tool-call",
		toolCallId: toolCall.toolCallId,
		toolName,
		input: parseResult.value,
		providerExecuted: toolCall.providerExecuted,
		providerMetadata: toolCall.providerMetadata,
		...tool.metadata != null ? { toolMetadata: tool.metadata } : {},
		title: tool.title
	}, parseResult.rawValue);
}
//#endregion
//#region src/generate-text/prepare-step-call-settings.ts
/**
* Resolves model call settings for a single step.
*
* Undefined step settings intentionally fall back to the outer call settings,
* while defined falsy values such as `temperature: 0` and `seed: 0` are kept.
*/
function prepareStepCallSettings({ callSettings, stepSettings }) {
	return prepareLanguageModelCallOptions({
		maxOutputTokens: stepSettings?.maxOutputTokens ?? callSettings.maxOutputTokens,
		temperature: stepSettings?.temperature ?? callSettings.temperature,
		topP: stepSettings?.topP ?? callSettings.topP,
		topK: stepSettings?.topK ?? callSettings.topK,
		presencePenalty: stepSettings?.presencePenalty ?? callSettings.presencePenalty,
		frequencyPenalty: stepSettings?.frequencyPenalty ?? callSettings.frequencyPenalty,
		stopSequences: stepSettings?.stopSequences ?? callSettings.stopSequences,
		seed: stepSettings?.seed ?? callSettings.seed,
		reasoning: stepSettings?.reasoning ?? callSettings.reasoning
	});
}
//#endregion
//#region src/generate-text/resolve-tool-approval.ts
/**
* Resolves the approval state for a tool call by checking user-supplied and tool-defined
* approval settings, and normalizes the result to the object status shape.
* User-defined approval settings take precedence over tool-defined settings.
* If no approval settings are provided, the tool call does not require approval.
*/
async function resolveToolApproval({ tools, toolCall, toolApproval, messages, toolsContext, runtimeContext }) {
	if (toolApproval != null && typeof toolApproval === "function") return normalizeToolApprovalStatus(await toolApproval({
		toolCall,
		tools,
		toolsContext,
		messages,
		runtimeContext
	}));
	const toolName = toolCall.toolName;
	const tool = getOwn(tools, toolName);
	const input = toolCall.input;
	const userDefinedToolApprovalStatus = getOwn(toolApproval, toolName);
	if (userDefinedToolApprovalStatus != null) return normalizeToolApprovalStatus(typeof userDefinedToolApprovalStatus === "function" ? await userDefinedToolApprovalStatus(input, {
		toolCallId: toolCall.toolCallId,
		messages,
		toolContext: await validateToolContext({
			toolName,
			context: getOwn(toolsContext, toolName),
			contextSchema: tool?.contextSchema
		}),
		runtimeContext
	}) : userDefinedToolApprovalStatus);
	if (tool?.needsApproval == null) return { type: "not-applicable" };
	return (typeof tool.needsApproval === "function" ? await tool.needsApproval(input, {
		toolCallId: toolCall.toolCallId,
		messages,
		context: await validateToolContext({
			toolName,
			context: getOwn(toolsContext, toolName),
			contextSchema: tool?.contextSchema
		})
	}) : tool.needsApproval) ? { type: "user-approval" } : { type: "not-applicable" };
}
function normalizeToolApprovalStatus(status) {
	return status === void 0 ? { type: "not-applicable" } : typeof status === "string" ? { type: status } : status;
}
//#endregion
//#region src/telemetry/filter-included-context.ts
/**
* Returns a shallow copy of the runtime context with only top-level
* properties marked for telemetry inclusion.
*/
function filterIncludedContext({ context, includeContext }) {
	if (context == null) return {};
	return Object.fromEntries(Object.entries(context).filter(([key]) => includeContext?.[key] === true));
}
function filterToolsContext({ toolsContext, includeToolsContext }) {
	if (includeToolsContext == null) return {};
	return Object.fromEntries(Object.entries(toolsContext).map(([toolName, toolContext]) => [toolName, filterToolContext({
		toolName,
		toolContext,
		includeToolsContext
	})]));
}
function filterToolContext({ toolName, toolContext, includeToolsContext }) {
	const includeToolContext = includeToolsContext?.[toolName];
	return filterIncludedContext({
		context: toolContext,
		includeContext: includeToolContext
	});
}
//#endregion
//#region src/util/merge-callbacks.ts
/**
* Creates an async callback that invokes the provided callbacks in parallel.
* Undefined callbacks are skipped, and thrown or rejected callback errors are
* ignored.
*
* @param callbacks The callbacks to invoke for each event.
* @returns A callback that forwards each event to all callbacks and waits for
* them to settle.
*/
function mergeCallbacks(...callbacks) {
	return async (event) => {
		await Promise.allSettled(callbacks.map(async (callback) => {
			await callback?.(event);
		}));
	};
}
//#endregion
//#region src/telemetry/tracing-channel.ts
const AI_SDK_TELEMETRY_TRACING_CHANNEL = "ai:telemetry";
//#endregion
//#region src/util/is-node-runtime.ts
function isNodeRuntime() {
	return globalThis.process?.release?.name === "node";
}
//#endregion
//#region src/telemetry/redact-telemetry-credentials.ts
/**
* Apply provider-owned credential redaction on telemetry-only copies. Only visit SDK
* metadata containers, never arbitrary prompts, tool outputs, or user context.
*/
function redactTelemetryCredentials(value) {
	return replaceProperties(value, {
		args: redactTelemetryValue,
		tools: redactTools,
		stepTools: redactTools,
		request: redactMetadata,
		response: redactMetadata,
		steps: (steps) => mapArray(steps, redactTelemetryCredentials),
		finalStep: redactTelemetryCredentials,
		error: redactTelemetryCredentials,
		cause: redactTelemetryCredentials,
		errors: (errors) => mapArray(errors, redactTelemetryCredentials),
		lastError: redactTelemetryCredentials,
		requestBodyValues: redactBody
	});
}
function redactMetadata(value) {
	return Array.isArray(value) ? mapArray(value, redactMetadata) : replaceProperties(value, { body: redactBody });
}
function redactBody(value) {
	return replaceProperties(redactTelemetryValue(value), { tools: redactTools });
}
function redactTools(value) {
	if (Array.isArray(value)) return mapArray(value, redactTelemetryCredentials);
	if (!isRecord$2(value)) return value;
	return replaceProperties(value, Object.fromEntries(Object.keys(value).map((key) => [key, redactTelemetryCredentials])));
}
function isRecord$2(value) {
	return value != null && typeof value === "object" && !Array.isArray(value);
}
function mapArray(value, redact) {
	if (!Array.isArray(value)) return value;
	const copy = value.map(redact);
	return copy.some((entry, index) => entry !== value[index]) ? copy : value;
}
/** Preserve result getters, streams, and property descriptors without mutation. */
function replaceProperties(value, redactors) {
	if (!isRecord$2(value)) return value;
	let descriptors;
	for (const [key, redact] of Object.entries(redactors)) {
		const descriptor = Object.getOwnPropertyDescriptor(value, key);
		if (descriptor == null || !("value" in descriptor)) continue;
		const redacted = redact(descriptor.value);
		if (redacted !== descriptor.value) {
			descriptors ??= Object.getOwnPropertyDescriptors(value);
			descriptors[key] = {
				...descriptor,
				value: redacted
			};
		}
	}
	return descriptors == null ? value : Object.create(Object.getPrototypeOf(value), descriptors);
}
//#endregion
//#region src/telemetry/tracing-channel-publisher.ts
let diagnosticsChannelPromise;
/**
* Loads Node's diagnostics channel module only when the current runtime supports
* it. Unsupported runtimes and failed imports intentionally resolve to
* undefined so telemetry tracing never crashes user code.
*/
async function loadDiagnosticsChannel() {
	if (!isNodeRuntime()) return;
	if (diagnosticsChannelPromise == null) diagnosticsChannelPromise = Promise.resolve(loadBuiltinModule("node:diagnostics_channel"));
	return diagnosticsChannelPromise;
}
function loadBuiltinModule(id) {
	const processWithBuiltins = globalThis.process;
	try {
		return processWithBuiltins?.getBuiltinModule?.(id);
	} catch {
		return;
	}
}
/**
* Runs an async operation inside the AI SDK telemetry tracing channel when
* tracing subscribers may exist. Without Node diagnostics-channel support,
* without tracingChannel support, or when the runtime reports no subscribers,
* this is a direct pass-through.
*
* The execution bookkeeping preserves the original model/tool result or error
* if tracing itself throws, and prevents falling back by calling `execute` a
* second time.
*/
async function runWithTracingChannelSpan(message, execute, recordResult = true) {
	const tracingChannel = (await loadDiagnosticsChannel())?.tracingChannel?.(AI_SDK_TELEMETRY_TRACING_CHANNEL);
	if (tracingChannel == null || tracingChannel.hasSubscribers === false) return await execute();
	let executePromise;
	let executionResult;
	let executionError;
	let hasExecutionResult = false;
	let hasExecutionError = false;
	const tracedExecute = () => {
		try {
			executePromise = Promise.resolve(execute());
		} catch (error) {
			executePromise = Promise.reject(error);
		}
		executePromise = executePromise.then((result) => {
			executionResult = result;
			hasExecutionResult = true;
			return result;
		}, (error) => {
			executionError = error;
			hasExecutionError = true;
			throw error;
		});
		return recordResult ? executePromise.then(redactTelemetryCredentials, (error) => {
			throw redactTelemetryCredentials(error);
		}) : executePromise.then(() => void 0, () => {
			throw new Error("AI SDK operation failed");
		});
	};
	try {
		await tracingChannel.tracePromise(tracedExecute, message);
		return executionResult;
	} catch {
		if (hasExecutionError) throw executionError;
		if (hasExecutionResult) return executionResult;
		if (executePromise != null) return await executePromise;
		return await execute();
	}
}
/**
* Opens a long-lived tracing-channel span context and returns a runner that can
* re-enter that context later without changing stream setup timing.
*/
function openTelemetryChannelSpanContext({ message, completion, recordResult = true }) {
	if (!isNodeRuntime()) {
		Promise.resolve(completion).catch(() => {});
		return;
	}
	const diagnosticsChannel = loadBuiltinModule("node:diagnostics_channel");
	const asyncHooks = loadBuiltinModule("node:async_hooks");
	const tracingChannel = diagnosticsChannel?.tracingChannel?.(AI_SDK_TELEMETRY_TRACING_CHANNEL);
	if (tracingChannel == null || tracingChannel.hasSubscribers === false || asyncHooks == null) {
		Promise.resolve(completion).catch(() => {});
		return;
	}
	const context = message;
	let asyncResource;
	let asyncEndPublished = false;
	const safePublish = (publish) => {
		try {
			publish();
		} catch {}
	};
	const publishAsyncEnd = ({ result, error }) => {
		if (asyncEndPublished) return;
		asyncEndPublished = true;
		if (error !== void 0) {
			context.error = recordResult ? redactTelemetryCredentials(error) : /* @__PURE__ */ new Error("AI SDK operation failed");
			safePublish(() => tracingChannel.error.publish(context));
		}
		if (recordResult && result !== void 0) context.result = redactTelemetryCredentials(result);
		safePublish(() => tracingChannel.asyncEnd.publish(context));
	};
	safePublish(() => {
		tracingChannel.start.runStores(context, () => {
			asyncResource = new asyncHooks.AsyncResource("ai.telemetry");
		});
	});
	safePublish(() => tracingChannel.end.publish(context));
	Promise.resolve(completion).then((result) => publishAsyncEnd({ result }), (error) => publishAsyncEnd({ error }));
	return { run: (execute) => asyncResource == null ? execute() : asyncResource.runInAsyncScope(execute) };
}
//#endregion
//#region src/telemetry/telemetry-registry.ts
/**
* Registers one or more telemetry integrations globally.
*/
function registerTelemetry(...integrations) {
	if (!globalThis.AI_SDK_TELEMETRY_INTEGRATIONS) globalThis.AI_SDK_TELEMETRY_INTEGRATIONS = [];
	globalThis.AI_SDK_TELEMETRY_INTEGRATIONS.push(...integrations);
}
function getGlobalTelemetryIntegrations() {
	return globalThis.AI_SDK_TELEMETRY_INTEGRATIONS ?? [];
}
//#endregion
//#region src/telemetry/filter-telemetry-event.ts
/**
* Filters SDK-owned content fields on a copy. Only descend into SDK event
* containers; user context has its own inclusion policy.
*/
function filterTelemetryEvent(event, telemetry) {
	const hideInputs = telemetry.recordInputs === false;
	const hideOutputs = telemetry.recordOutputs === false;
	if (!hideInputs && !hideOutputs || event == null || typeof event !== "object") return event;
	const filtered = Object.assign(Object.create(Object.getPrototypeOf(event)), event);
	const replace = (fields) => {
		for (const [key, value] of Object.entries(fields)) if (Object.hasOwn(event, key)) filtered[key] = value;
	};
	const isSpeech = filtered.operationId === "ai.generateSpeech";
	if (hideInputs) {
		replace({
			instructions: void 0,
			system: void 0,
			prompt: void 0,
			messages: [],
			promptMessages: [],
			experimental_steeringMessages: [],
			tools: void 0,
			stepTools: void 0,
			schema: void 0,
			schemaName: void 0,
			schemaDescription: void 0,
			...typeof filtered.output === "object" ? { output: void 0 } : {},
			providerOptions: {},
			value: "",
			values: [],
			query: "",
			documents: [],
			state: Array.isArray(filtered.state) ? [] : typeof filtered.state === "string" ? "" : {},
			questions: {},
			...isSpeech ? { text: "" } : {}
		});
		if (filtered.toolCall != null) filtered.toolCall = {
			...filtered.toolCall,
			input: void 0
		};
		if (filtered.toolOutput != null) filtered.toolOutput = {
			...filtered.toolOutput,
			input: void 0
		};
		if (Array.isArray(filtered.ranking)) filtered.ranking = filtered.ranking.map((entry) => "document" in entry ? {
			...entry,
			document: typeof entry.document === "string" ? "" : {}
		} : entry);
	}
	if (hideOutputs) {
		replace({
			content: [],
			...!isSpeech ? { text: "" } : {},
			reasoning: Array.isArray(filtered.reasoning) ? [] : void 0,
			reasoningText: void 0,
			files: [],
			sources: [],
			toolCalls: [],
			staticToolCalls: [],
			dynamicToolCalls: [],
			toolResults: [],
			staticToolResults: [],
			dynamicToolResults: [],
			responseMessages: [],
			object: void 0,
			objectText: "",
			embedding: [],
			embeddings: [],
			ranking: [],
			answers: {},
			segments: [],
			words: []
		});
		if (filtered.toolOutput != null) filtered.toolOutput = {
			...filtered.toolOutput,
			output: void 0,
			error: void 0
		};
	}
	replace({
		providerMetadata: void 0,
		error: filtered.error == null ? filtered.error : /* @__PURE__ */ new Error("AI SDK operation failed")
	});
	for (const key of ["toolCall", "toolOutput"]) {
		const toolEvent = filtered[key];
		if (toolEvent != null && typeof toolEvent === "object") filtered[key] = {
			...toolEvent,
			providerMetadata: void 0,
			..."error" in toolEvent ? { error: toolEvent.error == null ? toolEvent.error : /* @__PURE__ */ new Error("AI SDK operation failed") } : {}
		};
	}
	for (const key of ["request", "response"]) {
		const filterMetadata = (metadata) => {
			if (metadata == null || typeof metadata !== "object") return metadata;
			const filteredMetadata = { ...metadata };
			delete filteredMetadata.body;
			if (key === "request" ? hideInputs : hideOutputs) {
				if ("messages" in metadata) filteredMetadata.messages = [];
				if ("instructions" in metadata) filteredMetadata.instructions = void 0;
			}
			return filteredMetadata;
		};
		const metadata = filtered[key];
		if (metadata != null) filtered[key] = Array.isArray(metadata) ? metadata.map(filterMetadata) : filterMetadata(metadata);
	}
	if (Array.isArray(filtered.steps)) filtered.steps = filtered.steps.map((step) => filterTelemetryEvent(step, telemetry));
	if (Object.hasOwn(event, "finalStep")) filtered.finalStep = filterTelemetryEvent(filtered.finalStep, telemetry);
	return filtered;
}
//#endregion
//#region src/telemetry/create-telemetry-dispatcher.ts
function augmentEvent(event, telemetry, filterContext = false) {
	const augmentedEvent = Object.assign(Object.create(Object.getPrototypeOf(event)), event, {
		recordInputs: telemetry.recordInputs,
		recordOutputs: telemetry.recordOutputs,
		functionId: telemetry.functionId,
		aiVersion: VERSION
	});
	if (filterContext && event != null && typeof event === "object" && "runtimeContext" in event) augmentedEvent.runtimeContext = filterIncludedContext({
		context: event.runtimeContext,
		includeContext: telemetry.includeRuntimeContext
	});
	if (filterContext && event != null && typeof event === "object") {
		if ("toolsContext" in event) augmentedEvent.toolsContext = filterToolsContext({
			toolsContext: event.toolsContext,
			includeToolsContext: telemetry.includeToolsContext
		});
		else if ("toolContext" in event && event.toolContext != null && "toolCall" in event && event.toolCall != null && typeof event.toolCall === "object" && "toolName" in event.toolCall) augmentedEvent.toolContext = filterToolContext({
			toolName: event.toolCall.toolName,
			toolContext: event.toolContext,
			includeToolsContext: telemetry.includeToolsContext
		});
	}
	return redactTelemetryCredentials(filterTelemetryEvent(augmentedEvent, telemetry));
}
/**
* Creates a telemetry dispatcher that sends telemetry events
* to the resolved set of integrations.
*
* When per-call integrations are provided, they take precedence over the globally
* registered integrations for that call. When no per-call integrations are
* provided, the globally registered integrations are used.
*
* @param args.telemetry - Optional per-call telemetry settings and integrations.
*
* @returns A telemetry dispatcher that fans out lifecycle events to the
* resolved set of integrations.
*/
function createTelemetryDispatcher({ telemetry }) {
	if (telemetry?.isEnabled === false) return {};
	const localIntegrations = telemetry?.integrations;
	const integrations = localIntegrations != null ? asArray(localIntegrations) : getGlobalTelemetryIntegrations();
	const telemetryMetadata = {
		recordInputs: telemetry?.recordInputs,
		recordOutputs: telemetry?.recordOutputs,
		functionId: telemetry?.functionId,
		includeRuntimeContext: telemetry?.includeRuntimeContext,
		includeToolsContext: telemetry?.includeToolsContext
	};
	const recordResult = telemetry?.recordInputs !== false && telemetry?.recordOutputs !== false;
	const mergeTelemetryCallback = (key, deprecatedKey) => {
		const integrationCallbacks = integrations.map((integration) => {
			const callback = integration[key] ?? (deprecatedKey == null ? void 0 : integration[deprecatedKey]);
			return typeof callback === "function" ? callback.bind(integration) : void 0;
		}).filter(Boolean).map((callback) => ((event) => callback(augmentEvent(event, telemetryMetadata))));
		if (integrationCallbacks.length === 0) return;
		const mergedIntegrationCallback = mergeCallbacks(...integrationCallbacks);
		return async (event) => {
			await mergedIntegrationCallback(event);
		};
	};
	const onStepEnd = mergeTelemetryCallback("onStepEnd");
	const onStepFinish = mergeTelemetryCallback("onStepFinish");
	const executeLanguageModelCallWrappers = integrations.map((integration) => integration.executeLanguageModelCall?.bind(integration)).filter(Boolean);
	const executeToolWrappers = integrations.map((integration) => integration.executeTool?.bind(integration)).filter(Boolean);
	return {
		runInTracingChannelSpan: async ({ type, event, execute }) => await runWithTracingChannelSpan({
			type,
			event: augmentEvent(event, telemetryMetadata, true)
		}, execute, recordResult),
		startTracingChannelContext: ({ type, event, completion }) => openTelemetryChannelSpanContext({
			message: {
				type,
				event: augmentEvent(event, telemetryMetadata, true)
			},
			completion,
			recordResult
		}),
		onStart: mergeTelemetryCallback("onStart"),
		onStepStart: mergeTelemetryCallback("onStepStart"),
		onLanguageModelCallStart: mergeTelemetryCallback("onLanguageModelCallStart"),
		onLanguageModelCallEnd: mergeTelemetryCallback("onLanguageModelCallEnd"),
		onToolExecutionStart: mergeTelemetryCallback("onToolExecutionStart"),
		onToolExecutionEnd: mergeTelemetryCallback("onToolExecutionEnd"),
		onStepEnd: onStepEnd == null && onStepFinish == null ? void 0 : mergeCallbacks(onStepEnd, onStepFinish),
		onStepError: mergeTelemetryCallback("onStepError"),
		onObjectStepStart: mergeTelemetryCallback("onObjectStepStart"),
		onObjectStepEnd: mergeTelemetryCallback("onObjectStepEnd"),
		onEmbedStart: mergeTelemetryCallback("onEmbedStart"),
		onEmbedEnd: mergeTelemetryCallback("onEmbedEnd"),
		onRerankStart: mergeTelemetryCallback("onRerankStart"),
		onRerankEnd: mergeTelemetryCallback("onRerankEnd"),
		experimental_onDecideStart: mergeTelemetryCallback("experimental_onDecideStart", "experimental_onEvaluateStart"),
		experimental_onDecisionModelCallStart: mergeTelemetryCallback("experimental_onDecisionModelCallStart", "experimental_onEvaluationModelCallStart"),
		experimental_onDecisionModelCallEnd: mergeTelemetryCallback("experimental_onDecisionModelCallEnd", "experimental_onEvaluationModelCallEnd"),
		experimental_onDecideEnd: mergeTelemetryCallback("experimental_onDecideEnd", "experimental_onEvaluateEnd"),
		experimental_onStreamTranscriptionStart: mergeTelemetryCallback("experimental_onStreamTranscriptionStart"),
		experimental_onStreamTranscriptionEnd: mergeTelemetryCallback("experimental_onStreamTranscriptionEnd"),
		onEnd: mergeTelemetryCallback("onEnd"),
		onAbort: mergeTelemetryCallback("onAbort"),
		onError: mergeTelemetryCallback("onError"),
		/**
		* Runs provider calls inside integration-specific context so
		* auto-instrumented provider requests can be associated with model work.
		*/
		executeLanguageModelCall: async ({ execute, ...event }) => {
			const augmentedEvent = augmentEvent(event, telemetryMetadata);
			let wrappedExecute = execute;
			for (const executeWrapper of executeLanguageModelCallWrappers) {
				const innerExecute = wrappedExecute;
				wrappedExecute = async () => {
					const originals = /* @__PURE__ */ new Map();
					const redact = (original) => {
						const redacted = redactTelemetryCredentials(original);
						if (redacted !== original) originals.set(redacted, original);
						return redacted;
					};
					const restore = (value) => originals.has(value) ? originals.get(value) : value;
					try {
						return restore(await executeWrapper({
							...augmentedEvent,
							execute: async () => {
								try {
									return redact(await innerExecute());
								} catch (error) {
									throw redact(error);
								}
							}
						}));
					} catch (error) {
						throw restore(error);
					}
				};
			}
			return await runWithTracingChannelSpan({
				type: "languageModelCall",
				event: augmentedEvent
			}, wrappedExecute, recordResult);
		},
		/**
		* Composes all `executeTool` wrappers around the original tool execution.
		* Each wrapper receives an `execute` function that calls the next wrapper in
		* the chain, so integrations can establish nested telemetry context before
		* delegating to the underlying tool.
		*/
		executeTool: async ({ execute, ...event }) => {
			const augmentedEvent = augmentEvent(event, telemetryMetadata);
			let wrappedExecute = execute;
			for (const executeWrapper of executeToolWrappers) {
				const innerExecute = wrappedExecute;
				wrappedExecute = () => executeWrapper({
					...augmentedEvent,
					execute: innerExecute
				});
			}
			return await wrappedExecute();
		}
	};
}
//#endregion
//#region src/generate-text/reasoning.ts
function asReasoningText(reasoningParts) {
	const reasoningText = reasoningParts.map((part) => "text" in part ? part.text : "").join("");
	return reasoningText.length > 0 ? reasoningText : void 0;
}
//#endregion
//#region src/generate-text/step-result.ts
var DefaultStepResult = class {
	constructor({ callId, stepNumber, provider, modelId, runtimeContext, toolsContext, content, finishReason, rawFinishReason, usage, performance, warnings, request, response, providerMetadata, steeringMessages }) {
		this.callId = callId;
		this.stepNumber = stepNumber;
		this.model = {
			provider,
			modelId
		};
		this.runtimeContext = runtimeContext;
		this.toolsContext = toolsContext;
		this.content = content;
		this.finishReason = finishReason;
		this.rawFinishReason = rawFinishReason;
		this.usage = usage;
		this.performance = performance;
		this.warnings = warnings;
		this.request = request;
		this.response = response;
		this.providerMetadata = providerMetadata;
		if (steeringMessages != null && steeringMessages.length > 0) this.experimental_steeringMessages = steeringMessages;
	}
	get text() {
		return this.content.filter((part) => part.type === "text").map((part) => part.text).join("");
	}
	get reasoning() {
		return convertFromReasoningOutputs(this.content.filter((part) => part.type === "reasoning" || part.type === "reasoning-file"));
	}
	get reasoningText() {
		return asReasoningText(this.reasoning);
	}
	get files() {
		return this.content.filter((part) => part.type === "file").map((part) => part.file);
	}
	get sources() {
		return this.content.filter((part) => part.type === "source");
	}
	get toolCalls() {
		return this.content.filter((part) => part.type === "tool-call");
	}
	get staticToolCalls() {
		return this.toolCalls.filter((toolCall) => toolCall.dynamic !== true);
	}
	get dynamicToolCalls() {
		return this.toolCalls.filter((toolCall) => toolCall.dynamic === true);
	}
	get toolResults() {
		return this.content.filter((part) => part.type === "tool-result");
	}
	get staticToolResults() {
		return this.toolResults.filter((toolResult) => toolResult.dynamic !== true);
	}
	get dynamicToolResults() {
		return this.toolResults.filter((toolResult) => toolResult.dynamic === true);
	}
};
//#endregion
//#region src/generate-text/restricted-telemetry-dispatcher.ts
/**
* Creates a copy of a step result whose runtime context only contains
* top-level properties marked for telemetry inclusion.
*/
function restrictStepResult({ step, includeRuntimeContext, includeToolsContext }) {
	return new DefaultStepResult({
		callId: step.callId,
		stepNumber: step.stepNumber,
		provider: step.model.provider,
		modelId: step.model.modelId,
		runtimeContext: filterIncludedContext({
			context: step.runtimeContext,
			includeContext: includeRuntimeContext
		}),
		toolsContext: filterToolsContext({
			toolsContext: step.toolsContext,
			includeToolsContext
		}),
		content: step.content,
		finishReason: step.finishReason,
		rawFinishReason: step.rawFinishReason,
		usage: step.usage,
		performance: step.performance,
		warnings: step.warnings,
		request: step.request,
		response: step.response,
		providerMetadata: step.providerMetadata,
		steeringMessages: step.experimental_steeringMessages
	});
}
/**
* Creates a telemetry dispatcher that only includes configured runtime context
* properties in text-generation lifecycle events before dispatching them.
*/
function createRestrictedTelemetryDispatcher$3({ telemetry, includeRuntimeContext, includeToolsContext }) {
	const telemetryDispatcher = createTelemetryDispatcher({ telemetry });
	const restrictStepStartEvent = (event) => ({
		...event,
		runtimeContext: filterIncludedContext({
			context: event.runtimeContext,
			includeContext: includeRuntimeContext
		}),
		steps: event.steps.map((step) => restrictStepResult({
			step,
			includeRuntimeContext,
			includeToolsContext
		})),
		toolsContext: filterToolsContext({
			toolsContext: event.toolsContext,
			includeToolsContext
		})
	});
	return {
		...telemetryDispatcher,
		onStart: (event) => telemetryDispatcher.onStart?.({
			...event,
			runtimeContext: filterIncludedContext({
				context: event.runtimeContext,
				includeContext: includeRuntimeContext
			}),
			toolsContext: filterToolsContext({
				toolsContext: event.toolsContext,
				includeToolsContext
			})
		}),
		onStepStart: (event) => telemetryDispatcher.onStepStart?.(restrictStepStartEvent(event)),
		onStepEnd: (event) => telemetryDispatcher.onStepEnd?.(restrictStepResult({
			step: event,
			includeRuntimeContext,
			includeToolsContext
		})),
		onStepFinish: (event) => telemetryDispatcher.onStepEnd?.(restrictStepResult({
			step: event,
			includeRuntimeContext,
			includeToolsContext
		})),
		onStepError: (event) => telemetryDispatcher.onStepError?.(restrictStepStartEvent(event)),
		onEnd: (event) => telemetryDispatcher.onEnd?.(((restrictedSteps) => {
			return {
				...event,
				runtimeContext: filterIncludedContext({
					context: event.runtimeContext,
					includeContext: includeRuntimeContext
				}),
				steps: restrictedSteps,
				finalStep: restrictedSteps.at(-1),
				toolsContext: filterToolsContext({
					toolsContext: event.toolsContext,
					includeToolsContext
				})
			};
		})(event.steps.map((step) => restrictStepResult({
			step,
			includeRuntimeContext,
			includeToolsContext
		})))),
		onAbort: (event) => telemetryDispatcher.onAbort?.({
			...event,
			steps: event.steps.map((step) => restrictStepResult({
				step,
				includeRuntimeContext,
				includeToolsContext
			}))
		}),
		onToolExecutionStart: (event) => telemetryDispatcher.onToolExecutionStart?.({
			...event,
			toolContext: filterToolContext({
				toolName: event.toolCall.toolName,
				toolContext: event.toolContext,
				includeToolsContext
			})
		}),
		onToolExecutionEnd: (event) => telemetryDispatcher.onToolExecutionEnd?.({
			...event,
			toolContext: filterToolContext({
				toolName: event.toolCall.toolName,
				toolContext: event.toolContext,
				includeToolsContext
			})
		})
	};
}
//#endregion
//#region src/generate-text/steering.ts
const generateSteeringId = createIdGenerator$1({
	prefix: "steer",
	size: 24
});
const steeringRunStarter = Symbol.for("vercel.ai.steering.start");
var DefaultSteering = class {
	constructor() {
		this.state = "idle";
		this.pending = [];
		this.queued = [];
		this.taken = [];
		this.outcomes = /* @__PURE__ */ new Map();
	}
	steer(message, options) {
		return this.add({
			message,
			id: options?.id,
			target: this.pending
		});
	}
	queue(message, options) {
		return this.add({
			message,
			id: options?.id,
			target: this.queued
		});
	}
	add({ message, id = generateSteeringId(), target }) {
		const existingOutcome = this.outcomes.get(id);
		if (existingOutcome != null) return existingOutcome;
		const userMessage = typeof message === "string" ? {
			role: "user",
			content: message
		} : message;
		const outcome = this.state === "ended" ? Promise.resolve({
			type: "not-delivered",
			id,
			message: userMessage,
			reason: "finished"
		}) : new Promise((resolve) => {
			target.push({
				id,
				message: userMessage,
				resolve
			});
		});
		this.outcomes.set(id, outcome);
		return outcome;
	}
	[steeringRunStarter]() {
		if (this.state !== "idle") throw new InvalidArgumentError({
			parameter: "experimental_steering",
			value: this,
			message: "The steering object was already used by a generation. Create a new one with experimental_createSteering() for each call."
		});
		this.state = "running";
		return {
			hasPendingMessages: () => this.state === "running" && this.pending.length > 0,
			promoteQueuedMessage: () => {
				const next = this.state === "running" ? this.queued.shift() : void 0;
				if (next == null) return false;
				this.pending.push(next);
				return true;
			},
			takeMessages: () => {
				if (this.state !== "running") return [];
				this.taken = [...this.taken, ...this.pending];
				this.pending = [];
				return this.taken.map(({ message }) => message);
			},
			resolveTakenMessages: ({ stepNumber, sentMessages }) => {
				const taken = this.taken;
				this.taken = [];
				const delivered = [];
				for (const { id, message, resolve } of taken) if (isSent({
					message,
					sentMessages
				})) {
					delivered.push({
						id,
						message
					});
					resolve({
						type: "delivered",
						id,
						message,
						stepNumber
					});
				} else resolve({
					type: "not-delivered",
					id,
					message,
					reason: "removed-by-prepare-step"
				});
				return delivered;
			},
			end: (reason) => {
				if (this.state !== "running") return;
				const notDelivered = [
					...this.taken,
					...this.pending,
					...this.queued
				];
				this.taken = [];
				this.pending = [];
				this.queued = [];
				this.state = "ended";
				for (const { id, message, resolve } of notDelivered) resolve({
					type: "not-delivered",
					id,
					message,
					reason
				});
			}
		};
	}
};
function isSent({ message, sentMessages }) {
	const content = JSON.stringify(message.content);
	return sentMessages.some((sentMessage) => sentMessage === message || sentMessage.role === "user" && JSON.stringify(sentMessage.content) === content);
}
/**
* Creates a steering object that sends user messages to a running generation.
*
* @example
* ```ts
* const steering = experimental_createSteering();
*
* const result = streamText({
*   model,
*   tools,
*   stopWhen: isStepCount(20),
*   experimental_steering: steering,
* });
*
* const outcome = await steering.steer('Use Paris, Texas instead.');
* ```
*/
function createSteering() {
	return new DefaultSteering();
}
/**
* Starts a run for a steering object that was passed to a generation.
*/
function startSteeringRun(steering) {
	if (steering == null) return;
	const start = steering[steeringRunStarter];
	if (typeof start !== "function") throw new InvalidArgumentError({
		parameter: "experimental_steering",
		value: steering,
		message: "The steering object must be created with experimental_createSteering()."
	});
	return start.call(steering);
}
//#endregion
//#region src/generate-text/stop-condition.ts
/**
* Creates a stop condition that returns `true` when the number of completed
* steps equals `stepCount`.
*
* @param stepCount - The number of steps to allow before stopping.
*/
function isStepCount(stepCount) {
	return ({ steps }) => steps.length === stepCount;
}
/**
* Creates a stop condition that never returns `true`.
*
* This lets the tool-calling loop continue until it reaches one of its
* natural termination conditions.
*/
function isLoopFinished() {
	return () => false;
}
/**
* Creates a stop condition that returns `true` when the most recent step
* contains a tool call with any of the specified names.
*
* @param toolName - The names of the tools that should stop the loop.
*/
function hasToolCall(...toolName) {
	return ({ steps }) => steps[steps.length - 1]?.toolCalls?.some((toolCall) => toolName.includes(toolCall.toolName)) ?? false;
}
/**
* Evaluates the provided stop conditions for the current list of steps.
*
* Returns `true` as soon as any stop condition is met.
*
* @param stopConditions - The stop conditions to evaluate.
* @param steps - The completed steps accumulated so far.
*/
async function isStopConditionMet({ stopConditions, steps }) {
	return (await Promise.all(stopConditions.map((condition) => condition({ steps })))).some((result) => result);
}
//#endregion
//#region src/generate-text/sum-token-counts.ts
/**
* Adds token counts while preserving an unknown total when both counts are
* unknown.
*/
function sumTokenCounts(tokenCount1, tokenCount2) {
	return tokenCount1 == null && tokenCount2 == null ? void 0 : (tokenCount1 ?? 0) + (tokenCount2 ?? 0);
}
//#endregion
//#region src/util/is-deep-equal-data.ts
/**
* Performs a deep-equal comparison of two parsed JSON objects.
*
* @param {any} obj1 - The first object to compare.
* @param {any} obj2 - The second object to compare.
* @returns {boolean} - Returns true if the two objects are deeply equal, false otherwise.
*/
function isDeepEqualData(obj1, obj2) {
	if (obj1 === obj2) return true;
	if (obj1 == null || obj2 == null) return false;
	if (typeof obj1 !== "object" && typeof obj2 !== "object") return obj1 === obj2;
	if (obj1.constructor !== obj2.constructor) return false;
	if (obj1 instanceof Date && obj2 instanceof Date) return obj1.getTime() === obj2.getTime();
	if (Array.isArray(obj1)) {
		if (obj1.length !== obj2.length) return false;
		for (let i = 0; i < obj1.length; i++) if (!isDeepEqualData(obj1[i], obj2[i])) return false;
		return true;
	}
	const keys1 = Object.keys(obj1);
	const keys2 = Object.keys(obj2);
	if (keys1.length !== keys2.length) return false;
	for (const key of keys1) {
		if (!keys2.includes(key)) return false;
		if (!isDeepEqualData(obj1[key], obj2[key])) return false;
	}
	return true;
}
//#endregion
//#region src/generate-text/to-response-messages.ts
/**
* Converts the result of a `generateText` or `streamText` call to a list of response messages.
*/
async function toResponseMessages({ content: inputContent, tools }) {
	const responseMessages = [];
	const toolCallOrder = /* @__PURE__ */ new Map();
	const content = [];
	for (const part of inputContent) {
		if (part.type === "source") continue;
		if ((part.type === "tool-result" || part.type === "tool-error") && !part.providerExecuted) continue;
		if (part.type === "text" && part.text.length === 0 && part.providerMetadata == null) continue;
		switch (part.type) {
			case "text":
				content.push({
					type: "text",
					text: part.text,
					providerOptions: part.providerMetadata
				});
				break;
			case "custom":
				content.push({
					type: "custom",
					kind: part.kind,
					providerOptions: part.providerMetadata
				});
				break;
			case "reasoning":
				content.push({
					type: "reasoning",
					text: part.text,
					providerOptions: part.providerMetadata
				});
				break;
			case "file":
				content.push({
					type: "file",
					data: part.file.base64,
					mediaType: part.file.mediaType,
					providerOptions: part.providerMetadata
				});
				break;
			case "reasoning-file":
				content.push({
					type: "reasoning-file",
					data: part.file.base64,
					mediaType: part.file.mediaType,
					providerOptions: part.providerMetadata
				});
				break;
			case "tool-call":
				if (!toolCallOrder.has(part.toolCallId)) toolCallOrder.set(part.toolCallId, toolCallOrder.size);
				content.push({
					type: "tool-call",
					toolCallId: part.toolCallId,
					toolName: part.toolName,
					input: part.invalid && typeof part.input !== "object" ? {} : part.input,
					providerExecuted: part.providerExecuted,
					providerOptions: part.providerMetadata
				});
				break;
			case "tool-result": {
				const output = await createToolModelOutput({
					toolCallId: part.toolCallId,
					input: part.input,
					tool: getOwn(tools, part.toolName),
					output: part.output,
					errorMode: "none"
				});
				content.push({
					type: "tool-result",
					toolCallId: part.toolCallId,
					toolName: part.toolName,
					output,
					providerOptions: part.providerMetadata
				});
				break;
			}
			case "tool-error": {
				const output = await createToolModelOutput({
					toolCallId: part.toolCallId,
					input: part.input,
					tool: getOwn(tools, part.toolName),
					output: part.error,
					errorMode: "json"
				});
				content.push({
					type: "tool-result",
					toolCallId: part.toolCallId,
					toolName: part.toolName,
					output,
					providerOptions: part.providerMetadata
				});
				break;
			}
			case "tool-approval-request":
				const inputSchemaInput = getToolCallInputSchemaInput(part.toolCall);
				content.push({
					type: "tool-approval-request",
					approvalId: part.approvalId,
					toolCallId: part.toolCall.toolCallId,
					...part.reason != null ? { reason: part.reason } : {},
					isAutomatic: part.isAutomatic,
					...part.signature != null ? { signature: part.signature } : {},
					...inputSchemaInput != null && !isDeepEqualData(inputSchemaInput.value, part.toolCall.input) ? { inputSchemaInput: inputSchemaInput.value } : {}
				});
		}
	}
	if (content.length > 0) responseMessages.push({
		role: "assistant",
		content
	});
	const toolResultContent = [];
	for (const part of inputContent) {
		if (part.type !== "tool-approval-response" && part.type !== "tool-result" && part.type !== "tool-error") continue;
		if (part.type === "tool-approval-response") {
			toolResultContent.push({
				type: "tool-approval-response",
				approvalId: part.approvalId,
				approved: part.approved,
				reason: part.reason,
				providerExecuted: part.providerExecuted
			});
			if (part.approved === false) toolResultContent.push({
				type: "tool-result",
				toolCallId: part.toolCall.toolCallId,
				toolName: part.toolCall.toolName,
				output: {
					type: "execution-denied",
					reason: part.reason
				}
			});
			continue;
		}
		if (part.providerExecuted) continue;
		const output = await createToolModelOutput({
			toolCallId: part.toolCallId,
			input: part.input,
			tool: getOwn(tools, part.toolName),
			output: part.type === "tool-result" ? part.output : part.error,
			errorMode: part.type === "tool-error" ? "text" : "none"
		});
		toolResultContent.push({
			type: "tool-result",
			toolCallId: part.toolCallId,
			toolName: part.toolName,
			output,
			...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
		});
	}
	if (toolResultContent.length > 0) responseMessages.push({
		role: "tool",
		content: sortToolResultContentByToolCallOrder({
			toolResultContent,
			toolCallOrder
		})
	});
	return responseMessages;
}
function sortToolResultContentByToolCallOrder({ toolResultContent, toolCallOrder }) {
	const sortedToolResults = toolResultContent.filter((part) => part.type === "tool-result").map((part, index) => ({
		part,
		index
	})).sort((a, b) => {
		const aOrder = toolCallOrder.get(a.part.toolCallId);
		const bOrder = toolCallOrder.get(b.part.toolCallId);
		if (aOrder == null && bOrder == null) return a.index - b.index;
		if (aOrder == null) return 1;
		if (bOrder == null) return -1;
		return aOrder - bOrder || a.index - b.index;
	}).map(({ part }) => part);
	let toolResultIndex = 0;
	return toolResultContent.map((part) => part.type === "tool-result" ? sortedToolResults[toolResultIndex++] : part);
}
//#endregion
//#region src/util/canonical-hash.ts
const encoder$1 = new TextEncoder();
/**
* Deterministic JSON serialization: object keys are sorted so that two
* structurally-equal values always produce the same string regardless of key
* insertion order. Used as the input to content hashing.
*/
function canonicalJSON(value) {
	if (value === null || value === void 0) return JSON.stringify(value);
	if (typeof value !== "object") return JSON.stringify(value);
	if (Array.isArray(value)) return `[${value.map((element) => element === void 0 ? "null" : canonicalJSON(element)).join(",")}]`;
	return `{${Object.keys(value).sort().map((k) => `${JSON.stringify(k)}:${canonicalJSON(value[k])}`).join(",")}}`;
}
function toBase64url(bytes) {
	return convertUint8ArrayToBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
}
/**
* Canonical SHA-256 digest (base64url) of an arbitrary JSON-serializable value.
*/
async function hashCanonical(value) {
	const digest = await crypto.subtle.digest("SHA-256", encoder$1.encode(canonicalJSON(value)));
	return toBase64url(new Uint8Array(digest));
}
//#endregion
//#region src/generate-text/tool-approval-signature.ts
const encoder = new TextEncoder();
function fromBase64url(str) {
	return convertBase64ToUint8Array(str);
}
async function importKey(secret) {
	const keyData = typeof secret === "string" ? encoder.encode(secret) : secret;
	return crypto.subtle.importKey("raw", keyData, {
		name: "HMAC",
		hash: "SHA-256"
	}, false, ["sign", "verify"]);
}
function buildPayload(approvalId, toolCallId, toolName, inputDigest) {
	return encoder.encode(JSON.stringify([
		"ai-sdk-tool-approval-v1",
		approvalId,
		toolCallId,
		toolName,
		inputDigest
	]));
}
function buildLegacyPayload(approvalId, toolCallId, toolName, inputDigest) {
	return encoder.encode(`${approvalId}\n${toolCallId}\n${toolName}\n${inputDigest}`);
}
async function signToolApproval({ secret, approvalId, toolCallId, toolName, input }) {
	const key = await importKey(secret);
	const payload = buildPayload(approvalId, toolCallId, toolName, await hashCanonical(input));
	const sig = await crypto.subtle.sign("HMAC", key, payload);
	return toBase64url(new Uint8Array(sig));
}
async function verifyToolApprovalSignature({ secret, signature, approvalId, toolCallId, toolName, input }) {
	const key = await importKey(secret);
	const inputDigest = await hashCanonical(input);
	const sigBytes = fromBase64url(signature);
	const payload = buildPayload(approvalId, toolCallId, toolName, inputDigest);
	if (await crypto.subtle.verify("HMAC", key, sigBytes, payload)) return true;
	if (!approvalId.includes("\n") && !toolCallId.includes("\n") && !toolName.includes("\n")) {
		const legacyPayload = buildLegacyPayload(approvalId, toolCallId, toolName, inputDigest);
		return crypto.subtle.verify("HMAC", key, sigBytes, legacyPayload);
	}
	return false;
}
async function maybeSignApproval({ secret, approvalId, toolCallId, toolName, input }) {
	if (secret == null) return void 0;
	return signToolApproval({
		secret,
		approvalId,
		toolCallId,
		toolName,
		input
	});
}
//#endregion
//#region src/generate-text/validate-tool-approvals.ts
/**
* Re-validates approved tool approvals reconstructed from client-supplied
* message history before they are executed. Checks HMAC signature (when
* configured), input schema, and approval policy.
*/
async function validateApprovedToolApprovals({ approvedToolApprovals, tools, toolApproval, messages, toolsContext, runtimeContext, toolApprovalSecret, refineToolInput }) {
	const approved = [];
	const denied = [];
	const invalid = [];
	for (const collectedApproval of approvedToolApprovals) {
		const tool = getOwn(tools, collectedApproval.toolCall.toolName);
		const { toolMetadata: _toolMetadata, dynamic: _dynamic, ...toolCallFromHistory } = collectedApproval.toolCall;
		const approval = {
			...collectedApproval,
			toolCall: {
				...toolCallFromHistory,
				...tool?.metadata != null ? { toolMetadata: tool.metadata } : {},
				...tool?.type === "dynamic" ? { dynamic: true } : {},
				title: tool?.title
			}
		};
		const { approvalRequest, toolCall } = approval;
		if (toolApprovalSecret != null) {
			if (approvalRequest.signature == null) throw new InvalidToolApprovalSignatureError({
				approvalId: approvalRequest.approvalId,
				toolCallId: toolCall.toolCallId,
				reason: "missing signature"
			});
			if (!await verifyToolApprovalSignature({
				secret: toolApprovalSecret,
				signature: approvalRequest.signature,
				approvalId: approvalRequest.approvalId,
				toolCallId: toolCall.toolCallId,
				toolName: toolCall.toolName,
				input: toolCall.input
			})) throw new InvalidToolApprovalSignatureError({
				approvalId: approvalRequest.approvalId,
				toolCallId: toolCall.toolCallId,
				reason: "invalid signature"
			});
		}
		if (isExecutableTool(tool) && tool.inputSchema != null) {
			let validationError;
			try {
				const approvedInput = structuredClone(toolCall.input);
				const hasInputSchemaInput = Object.prototype.hasOwnProperty.call(approvalRequest, "inputSchemaInput");
				const validation = await safeValidateTypes({
					value: structuredClone(hasInputSchemaInput ? approvalRequest.inputSchemaInput : toolCall.input),
					schema: asSchema$1(tool.inputSchema)
				});
				if (!validation.success) validationError = validation.error;
				else {
					const revalidatedToolCall = await refineParsedToolCallInput({
						toolCall: {
							...toolCall,
							input: validation.value
						},
						refineToolInput
					});
					if (!isDeepEqualData(structuredClone(revalidatedToolCall.input), approvedInput)) validationError = /* @__PURE__ */ new Error("Approved tool input does not match the validated schema output.");
				}
			} catch (error) {
				validationError = error;
			}
			if (validationError != null) {
				invalid.push({
					...approval,
					error: new InvalidToolInputError({
						toolName: toolCall.toolName,
						toolInput: JSON.stringify(toolCall.input),
						cause: validationError
					})
				});
				continue;
			}
		}
		const approvalStatus = await resolveToolApproval({
			tools,
			toolApproval,
			toolCall,
			messages,
			toolsContext,
			runtimeContext
		});
		if (approvalStatus.type === "denied") denied.push({
			...approval,
			approvalResponse: {
				...approval.approvalResponse,
				approved: false,
				reason: approvalStatus.reason ?? approval.approvalResponse.reason
			}
		});
		else approved.push(approval);
	}
	return {
		approvedToolApprovals: approved,
		deniedToolApprovals: denied,
		invalidToolApprovals: invalid
	};
}
//#endregion
//#region src/generate-text/tool-call-concurrency.ts
/**
* Validates the maximum number of tool calls that may execute concurrently.
*/
function prepareToolCallConcurrency(toolCallConcurrency) {
	if (toolCallConcurrency == null) return;
	if (!Number.isInteger(toolCallConcurrency)) throw new InvalidArgumentError({
		parameter: "toolCallConcurrency",
		value: toolCallConcurrency,
		message: "toolCallConcurrency must be an integer"
	});
	if (toolCallConcurrency < 1) throw new InvalidArgumentError({
		parameter: "toolCallConcurrency",
		value: toolCallConcurrency,
		message: "toolCallConcurrency must be >= 1"
	});
	return toolCallConcurrency;
}
/**
* Maps items with an optional concurrency limit while preserving result order.
*
* Workers claim items in input order. When the signal is aborted or an
* execution rejects, no additional queued items are started.
*/
async function mapWithConcurrency({ items, concurrency, abortSignal, execute }) {
	if (concurrency == null || concurrency >= items.length) return Promise.all(items.map(execute));
	const results = new Array(items.length);
	let nextIndex = 0;
	let stopped = false;
	const worker = async () => {
		while (!stopped) {
			abortSignal?.throwIfAborted();
			const index = nextIndex++;
			if (index >= items.length) return;
			try {
				results[index] = await execute(items[index], index);
			} catch (error) {
				stopped = true;
				throw error;
			}
		}
	};
	await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, worker));
	return results;
}
//#endregion
//#region src/generate-text/generate-text.ts
const originalGenerateId$4 = createIdGenerator$1({
	prefix: "aitxt",
	size: 24
});
const originalGenerateCallId$9 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Generate a text and call tools for a given prompt using a language model.
*
* This function does not stream the output. If you want to stream the output, use `streamText` instead.
*
* @param model - The language model to use.
*
* @param tools - Tools that are accessible to and can be called by the model. The model needs to support calling tools.
* @param toolChoice - The tool choice strategy. Default: 'auto'.
* @param toolOrder - Controls the order in which tools are sent to the provider. Tools not listed are appended alphabetically.
* @param toolCallConcurrency - Maximum number of tool calls that may execute concurrently within a step. Set to 1 for sequential execution. Default: unlimited.
*
* @param system - A system message that will be part of the prompt.
* @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
* @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
* @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. Default: false.
*
* @param maxOutputTokens - Maximum number of tokens to generate.
* @param temperature - Temperature setting.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topP - Nucleus sampling.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topK - Only sample from the top K options for each subsequent token.
* Used to remove "long tail" low probability responses.
* Recommended for advanced use cases only. You usually only need to use temperature.
* @param presencePenalty - Presence penalty setting.
* It affects the likelihood of the model to repeat information that is already in the prompt.
* The value is passed through to the provider. The range depends on the provider and model.
* @param frequencyPenalty - Frequency penalty setting.
* It affects the likelihood of the model to repeatedly use the same words or phrases.
* The value is passed through to the provider. The range depends on the provider and model.
* @param stopSequences - Stop sequences.
* If set, the model will stop generating text when one of the stop sequences is generated.
* @param seed - The seed (integer) to use for random sampling.
* If set and supported by the model, calls will generate deterministic results.
*
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param timeout - An optional timeout in milliseconds. The call will be aborted if it takes longer than the specified timeout.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
*
* @param experimental_sandbox - The sandbox environment that is passed through to tool execution.
* @param experimental_steering - A steering object that adds user messages to the generation at the next step boundary.
* @param runtimeContext - User-defined runtime context that flows through the entire generation lifecycle.
* @param experimental_refineToolInput - Optional mapping of tool names to functions that refine parsed tool inputs before tools are executed and before outputs, callbacks, and telemetry are recorded.
* @param onStart - Callback invoked when generation begins, before any LLM calls.
* @param experimental_onStart - Deprecated alias for `onStart`.
* @param onStepStart - Callback invoked when each step begins, before the provider is called.
* @param experimental_onStepStart - Deprecated alias for `onStepStart`.
* Receives step number, messages (in ModelMessage format), tools, and runtimeContext.
* @param onLanguageModelCallStart - Callback invoked immediately before each provider model call begins.
* @param experimental_onLanguageModelCallStart - Deprecated alias for `onLanguageModelCallStart`.
* @param onLanguageModelCallEnd - Callback invoked after each provider model call response is normalized and parsed.
* @param experimental_onLanguageModelCallEnd - Deprecated alias for `onLanguageModelCallEnd`.
* @param onToolExecutionStart - Callback invoked before each tool execution begins.
* Receives tool name, call ID, input, and context.
* @param experimental_onToolCallStart - Deprecated alias for `onToolExecutionStart`.
* @param onToolExecutionEnd - Callback invoked after each tool execution completes.
* Uses a discriminated union: check `success` to determine if `output` or `error` is present.
* @param experimental_onToolCallFinish - Deprecated alias for `onToolExecutionEnd`.
* @param onStepFinish - Callback that is called when each step (LLM call) is finished, including intermediate steps.
* @param onStepError - Callback that is called when a step that started fails before it produces a step result, i.e. when the provider call throws or rejects, or when the call is aborted or times out.
* @param onEnd - Callback that is called when all steps are finished and the response is complete.
* @param onFinish - Deprecated alias for `onEnd`.
*
* @returns
* A result object that contains the generated text, the results of the tool calls, and additional information.
*/
async function generateText(options) {
	const steeringRun = startSteeringRun(options.experimental_steering);
	try {
		return await generateTextInternal(options, steeringRun);
	} catch (error) {
		steeringRun?.end(options.abortSignal?.aborted ? "aborted" : "error");
		throw error;
	}
}
async function generateTextInternal({ model: modelArg, tools, toolChoice, instructions, system, prompt, messages, allowSystemInMessages, maxRetries: maxRetriesArg, abortSignal, timeout, headers, stopWhen = isStepCount(1), experimental_sandbox: sandbox, output, toolApproval, experimental_toolCallers, experimental_toolApprovalSecret, experimental_telemetry, telemetry = experimental_telemetry, providerOptions, activeTools, toolOrder, toolCallConcurrency, prepareStep, experimental_repairToolCall, repairToolCall = experimental_repairToolCall, experimental_refineToolInput: refineToolInput, experimental_download: download, runtimeContext = {}, toolsContext = {}, experimental_include, include = experimental_include, _internal: { generateId = originalGenerateId$4, generateCallId = originalGenerateCallId$9, now: now$4 = now } = {}, onStart, experimental_onStart, onStepStart, experimental_onStepStart, onLanguageModelCallStart, experimental_onLanguageModelCallStart, onLanguageModelCallEnd, experimental_onLanguageModelCallEnd, onToolExecutionStart, onToolExecutionEnd, experimental_onToolCallStart, experimental_onToolCallFinish, onStepEnd, onStepError, onStepFinish, onFinish, onEnd = onFinish, ...settings }, steeringRun) {
	include = {
		requestBody: include?.requestBody ?? false,
		requestMessages: include?.requestMessages ?? false,
		responseBody: include?.responseBody ?? false
	};
	const resolvedToolCallConcurrency = prepareToolCallConcurrency(toolCallConcurrency);
	const model = resolveLanguageModel(modelArg);
	const resolvedToolCallers = resolveToolCallerConfiguration({
		tools,
		toolCallers: experimental_toolCallers
	});
	const prepareToolSearch = createToolSearchState({
		tools,
		toolCallers: resolvedToolCallers
	});
	const stopConditions = asArray(stopWhen);
	const resolvedOnStart = onStart ?? experimental_onStart;
	const resolvedOnStepStart = onStepStart ?? experimental_onStepStart;
	const resolvedOnLanguageModelCallStart = onLanguageModelCallStart ?? experimental_onLanguageModelCallStart;
	const resolvedOnLanguageModelCallEnd = onLanguageModelCallEnd ?? experimental_onLanguageModelCallEnd;
	const resolvedOnToolExecutionStart = onToolExecutionStart ?? experimental_onToolCallStart;
	const resolvedOnToolExecutionEnd = onToolExecutionEnd ?? experimental_onToolCallFinish;
	const resolvedOnStepEnd = onStepEnd ?? onStepFinish;
	const unsupportedTimeoutWarnings = [];
	if (getFirstChunkTimeoutMs(timeout) != null) unsupportedTimeoutWarnings.push({
		type: "unsupported",
		feature: "timeout.firstChunkMs",
		details: "The firstChunkMs timeout is only supported by streaming functions."
	});
	if (getChunkTimeoutMs(timeout) != null) unsupportedTimeoutWarnings.push({
		type: "unsupported",
		feature: "timeout.chunkMs",
		details: "The chunkMs timeout is only supported by streaming functions."
	});
	if (unsupportedTimeoutWarnings.length > 0) logWarnings({
		warnings: unsupportedTimeoutWarnings,
		provider: model.provider,
		model: model.modelId
	});
	const totalTimeoutMs = getTotalTimeoutMs(timeout);
	const stepTimeoutMs = getStepTimeoutMs(timeout);
	const stepAbortController = stepTimeoutMs != null ? new AbortController() : void 0;
	const mergedAbortSignal = mergeAbortSignals(abortSignal, totalTimeoutMs, stepAbortController?.signal);
	const { maxRetries, retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal: mergedAbortSignal
	});
	const callSettings = prepareLanguageModelCallOptions(settings);
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const initialPrompt = await standardizePrompt({
		instructions,
		system,
		prompt,
		messages,
		allowSystemInMessages
	});
	const callId = generateCallId();
	const telemetryDispatcher = createRestrictedTelemetryDispatcher$3({
		telemetry,
		includeRuntimeContext: telemetry?.includeRuntimeContext,
		includeToolsContext: telemetry?.includeToolsContext
	});
	const runInTracingChannelSpan = telemetryDispatcher.runInTracingChannelSpan ?? (async ({ execute }) => await execute());
	const generateTextStartEvent = {
		callId,
		operationId: "ai.generateText",
		provider: model.provider,
		modelId: model.modelId,
		instructions: initialPrompt.instructions,
		messages: initialPrompt.messages,
		tools,
		toolChoice,
		activeTools,
		toolOrder,
		maxOutputTokens: callSettings.maxOutputTokens,
		temperature: callSettings.temperature,
		topP: callSettings.topP,
		topK: callSettings.topK,
		presencePenalty: callSettings.presencePenalty,
		frequencyPenalty: callSettings.frequencyPenalty,
		stopSequences: callSettings.stopSequences,
		seed: callSettings.seed,
		reasoning: callSettings.reasoning,
		maxRetries,
		timeout,
		headers: headersWithUserAgent,
		providerOptions,
		output,
		runtimeContext,
		toolsContext
	};
	const executeGenerateText = async () => {
		await notify({
			event: generateTextStartEvent,
			callbacks: [resolvedOnStart, telemetryDispatcher.onStart]
		});
		let openStep;
		try {
			const initialMessages = initialPrompt.messages;
			const initialResponseMessages = [];
			const { approvedToolApprovals, deniedToolApprovals: collectedDeniedToolApprovals } = collectToolApprovals({ messages: initialMessages });
			const { approvedToolApprovals: localApprovedToolApprovals, deniedToolApprovals: revalidationDeniedToolApprovals, invalidToolApprovals } = await validateApprovedToolApprovals({
				approvedToolApprovals: approvedToolApprovals.filter((toolApproval) => !toolApproval.toolCall.providerExecuted),
				tools,
				toolApproval,
				messages: initialMessages,
				toolsContext,
				runtimeContext,
				toolApprovalSecret: experimental_toolApprovalSecret,
				refineToolInput
			});
			const deniedToolApprovalsWithoutResults = [...collectedDeniedToolApprovals, ...revalidationDeniedToolApprovals].filter((toolApproval) => toolApproval.existingToolResult == null);
			if (deniedToolApprovalsWithoutResults.length > 0 || localApprovedToolApprovals.length > 0 || invalidToolApprovals.length > 0) {
				const toolResults = await executeTools({
					toolCalls: localApprovedToolApprovals.map((toolApproval) => toolApproval.toolCall),
					tools,
					callId,
					messages: initialMessages,
					abortSignal: mergedAbortSignal,
					timeout,
					experimental_sandbox: sandbox,
					toolsContext,
					onToolExecutionStart: (event) => notify({
						event,
						callbacks: [resolvedOnToolExecutionStart, telemetryDispatcher.onToolExecutionStart]
					}),
					onToolExecutionEnd: (event) => notify({
						event,
						callbacks: [resolvedOnToolExecutionEnd, telemetryDispatcher.onToolExecutionEnd]
					}),
					executeToolInTelemetryContext: telemetryDispatcher.executeTool,
					runInTracingChannelSpan,
					toolCallConcurrency: resolvedToolCallConcurrency
				});
				const toolContent = [];
				for (const result of toolResults) {
					const output = result.output;
					const modelOutput = await createToolModelOutput({
						toolCallId: output.toolCallId,
						input: output.input,
						tool: getOwn(tools, output.toolName),
						output: output.type === "tool-result" ? output.output : output.error,
						errorMode: output.type === "tool-error" ? "text" : "none"
					});
					toolContent.push({
						type: "tool-result",
						toolCallId: output.toolCallId,
						toolName: output.toolName,
						output: modelOutput
					});
				}
				for (const toolApproval of invalidToolApprovals) toolContent.push({
					type: "tool-result",
					toolCallId: toolApproval.toolCall.toolCallId,
					toolName: toolApproval.toolCall.toolName,
					output: await createToolModelOutput({
						toolCallId: toolApproval.toolCall.toolCallId,
						input: toolApproval.toolCall.input,
						tool: getOwn(tools, toolApproval.toolCall.toolName),
						output: toolApproval.error,
						errorMode: "text"
					})
				});
				for (const toolApproval of deniedToolApprovalsWithoutResults) toolContent.push({
					type: "tool-result",
					toolCallId: toolApproval.toolCall.toolCallId,
					toolName: toolApproval.toolCall.toolName,
					output: {
						type: "execution-denied",
						reason: toolApproval.approvalResponse.reason,
						...toolApproval.toolCall.providerExecuted && { providerOptions: { openai: { approvalId: toolApproval.approvalResponse.approvalId } } }
					}
				});
				initialResponseMessages.push({
					role: "tool",
					content: toolContent
				});
			}
			const callSettings = prepareLanguageModelCallOptions(settings);
			let currentModelResponse;
			let clientToolCalls = [];
			let clientToolOutputs = [];
			let toolApprovalResponses = [];
			let deniedToolApprovalResponses = [];
			const steps = [];
			let instructionsForNextStep = initialPrompt.instructions;
			let messagesForNextStep = [...initialMessages, ...initialResponseMessages];
			const pendingDeferredToolCalls = /* @__PURE__ */ new Map();
			let steeringEndReason = "finished";
			const shouldStartNextStep = async () => {
				if (steps[steps.length - 1].finishReason === "interrupted") return false;
				if (clientToolOutputs.length + deniedToolApprovalResponses.length !== clientToolCalls.length) {
					steeringEndReason = "waiting-for-tool-results";
					return false;
				}
				if (clientToolCalls.length === 0 && pendingDeferredToolCalls.size === 0) {
					const isTruncated = steps[steps.length - 1].finishReason === "length" || steps[steps.length - 1].finishReason === "content-filter";
					if (!steeringRun?.hasPendingMessages() && (isTruncated || !steeringRun?.promoteQueuedMessage())) return false;
					if (steps[steps.length - 1].finishReason === "error") {
						steeringEndReason = "error";
						return false;
					}
				}
				if (await isStopConditionMet({
					stopConditions,
					steps
				})) {
					steeringEndReason = "stop-condition";
					return false;
				}
				return true;
			};
			do {
				if (steps.length > 0) mergedAbortSignal?.throwIfAborted();
				const stepTimeoutId = setAbortTimeout({
					abortController: stepAbortController,
					label: "Step",
					timeoutMs: stepTimeoutMs
				});
				const stepNumber = steps.length;
				const steeringMessages = steeringRun?.takeMessages() ?? [];
				if (steeringMessages.length > 0) messagesForNextStep = [...messagesForNextStep, ...steeringMessages];
				try {
					await runInTracingChannelSpan({
						type: "step",
						event: {
							callId,
							stepNumber
						},
						execute: async () => {
							const accumulatedResponseMessages = [...initialResponseMessages, ...steps.flatMap((step) => step.response.messages)];
							const stepInputMessages = messagesForNextStep;
							const prepareStepResult = await prepareStep?.({
								model,
								steps,
								stepNumber: steps.length,
								instructions: instructionsForNextStep,
								initialInstructions: initialPrompt.instructions,
								messages: stepInputMessages,
								initialMessages,
								responseMessages: accumulatedResponseMessages,
								...steeringMessages.length > 0 ? { experimental_steeringMessages: steeringMessages } : {},
								runtimeContext,
								toolsContext,
								experimental_sandbox: sandbox
							});
							const stepSandbox = prepareStepResult?.experimental_sandbox ?? sandbox;
							const stepModel = resolveLanguageModel(prepareStepResult?.model ?? model);
							const stepInstructions = prepareStepResult?.instructions ?? prepareStepResult?.system ?? instructionsForNextStep;
							runtimeContext = prepareStepResult?.runtimeContext ?? runtimeContext;
							toolsContext = prepareStepResult?.toolsContext ?? toolsContext;
							const stepActiveTools = filterActiveTools({
								tools,
								activeTools: prepareStepResult?.activeTools ?? activeTools
							});
							const { executionTools, modelTools: stepModelTools, toolCallerMessages } = prepareToolsForToolCallers({
								tools: prepareToolSearch(stepActiveTools, {
									toolsContext,
									experimental_sandbox: stepSandbox
								}),
								toolCallers: resolvedToolCallers
							});
							const stepToolOrder = prepareStepResult?.toolOrder ?? toolOrder;
							const stepTools = await prepareTools({
								tools: stepModelTools,
								toolOrder: stepToolOrder,
								toolsContext,
								experimental_sandbox: stepSandbox
							});
							const stepToolChoice = prepareToolChoice({ toolChoice: prepareStepResult?.toolChoice ?? toolChoice });
							const stepExecutionTools = stepToolChoice.type === "none" ? void 0 : executionTools;
							const stepMessages = appendToolCallerMessages({
								messages: prepareStepResult?.messages ?? stepInputMessages,
								toolCallerMessages
							});
							const deliveredSteeringMessages = (steeringRun?.resolveTakenMessages({
								stepNumber,
								sentMessages: stepMessages
							}) ?? []).map(({ message }) => message);
							const promptMessages = await convertToLanguageModelPrompt({
								prompt: {
									instructions: stepInstructions,
									messages: stepMessages
								},
								supportedUrls: await stepModel.supportedUrls,
								download,
								abortSignal: mergedAbortSignal,
								provider: stepModel.provider.split(".")[0]
							});
							const stepProviderOptions = mergeObjects(providerOptions, prepareStepResult?.providerOptions);
							const stepCallSettings = prepareStepCallSettings({
								callSettings,
								stepSettings: prepareStepResult
							});
							const stepStartEvent = {
								callId,
								provider: stepModel.provider,
								modelId: stepModel.modelId,
								stepNumber,
								instructions: stepInstructions,
								messages: stepMessages,
								tools,
								toolChoice: prepareStepResult?.toolChoice ?? toolChoice,
								activeTools: prepareStepResult?.activeTools ?? activeTools,
								toolOrder: stepToolOrder,
								steps: [...steps],
								providerOptions: stepProviderOptions,
								output,
								runtimeContext,
								promptMessages,
								stepTools,
								stepToolChoice,
								toolsContext
							};
							await notify({
								event: stepStartEvent,
								callbacks: [resolvedOnStepStart, telemetryDispatcher.onStepStart]
							});
							openStep = stepStartEvent;
							const languageModelCallContext = {
								provider: stepModel.provider,
								modelId: stepModel.modelId,
								instructions: stepInstructions,
								messages: stepMessages,
								tools: stepTools,
								...stepCallSettings
							};
							const languageModelCallStartEvent = {
								callId,
								...languageModelCallContext
							};
							const stepStartTimestampMs = now$4();
							await notify({
								event: languageModelCallStartEvent,
								callbacks: [resolvedOnLanguageModelCallStart, telemetryDispatcher.onLanguageModelCallStart]
							});
							const executeLanguageModelCallInTelemetryContext = telemetryDispatcher.executeLanguageModelCall ?? (async ({ execute }) => await execute());
							currentModelResponse = await retry(async () => {
								const result = await executeLanguageModelCallInTelemetryContext({
									...languageModelCallStartEvent,
									execute: async () => {
										const result = await stepModel.doGenerate({
											...stepCallSettings,
											tools: stepTools,
											toolChoice: stepToolChoice,
											responseFormat: await output?.responseFormat,
											prompt: promptMessages,
											providerOptions: stepProviderOptions,
											abortSignal: mergedAbortSignal,
											headers: headersWithUserAgent
										});
										return {
											...result,
											...result.request && { request: sanitizeRequestMetadata(result.request) }
										};
									}
								});
								return {
									...result,
									response: {
										id: result.response?.id ?? generateId(),
										timestamp: result.response?.timestamp ?? /* @__PURE__ */ new Date(),
										modelId: result.response?.modelId ?? stepModel.modelId,
										headers: result.response?.headers,
										body: result.response?.body
									}
								};
							});
							const responseTimeMs = now$4() - stepStartTimestampMs;
							const stepUsage = asLanguageModelUsage(currentModelResponse.usage);
							const stepToolCalls = await Promise.all(currentModelResponse.content.filter((part) => part.type === "tool-call").map((toolCall) => parseToolCall({
								toolCall,
								tools: stepModelTools,
								repairToolCall: stepToolChoice.type === "none" ? void 0 : repairToolCall,
								refineToolInput: stepToolChoice.type === "none" ? void 0 : refineToolInput,
								instructions: stepInstructions,
								messages: stepMessages,
								abortSignal: mergedAbortSignal
							})));
							const toolApprovalRequests = {};
							const stepToolApprovalResponses = {};
							const blockedToolCallIds = /* @__PURE__ */ new Set();
							const generatedFileDataCache = /* @__PURE__ */ new WeakMap();
							const modelCallContent = await convertLanguageModelContent({
								content: currentModelResponse.content,
								toolCalls: stepToolCalls,
								toolOutputs: [],
								toolApprovalRequests: [],
								toolApprovalResponses: [],
								tools,
								download,
								abortSignal: mergedAbortSignal,
								generatedFileDataCache
							});
							await notify({
								event: {
									callId,
									provider: stepModel.provider,
									modelId: currentModelResponse.response.modelId,
									finishReason: currentModelResponse.finishReason.unified,
									usage: stepUsage,
									content: modelCallContent,
									responseId: currentModelResponse.response.id,
									...currentModelResponse.request?.url != null ? { request: { url: getRequestOrigin(currentModelResponse.request.url) } } : {},
									...currentModelResponse.providerMetadata != null ? { providerMetadata: currentModelResponse.providerMetadata } : {},
									performance: {
										responseTimeMs,
										effectiveOutputTokensPerSecond: calculateTokensPerSecond({
											tokens: stepUsage.outputTokens,
											durationMs: responseTimeMs
										}),
										outputTokensPerSecond: void 0,
										inputTokensPerSecond: void 0,
										effectiveTotalTokensPerSecond: calculateTokensPerSecond({
											tokens: sumTokenCounts(stepUsage.inputTokens, stepUsage.outputTokens),
											durationMs: responseTimeMs
										}),
										timeToFirstOutputMs: void 0
									}
								},
								callbacks: [resolvedOnLanguageModelCallEnd, telemetryDispatcher.onLanguageModelCallEnd]
							});
							const enforcedToolChoice = stepToolChoice.type === "auto" ? void 0 : stepToolChoice;
							if (enforcedToolChoice != null && (enforcedToolChoice.type === "none" ? stepToolCalls.length > 0 : currentModelResponse.finishReason.unified !== "interrupted" && !stepToolCalls.some((toolCall) => enforcedToolChoice.type === "required" || toolCall.toolName === enforcedToolChoice.toolName))) throw new ToolChoiceViolationError({
								toolChoice: enforcedToolChoice,
								finishReason: currentModelResponse.finishReason.unified,
								provider: stepModel.provider,
								modelId: stepModel.modelId,
								content: currentModelResponse.content
							});
							for (const toolCall of stepToolCalls) {
								if (toolCall.invalid) continue;
								const tool = getOwn(stepExecutionTools, toolCall.toolName);
								if (tool == null) continue;
								if (tool.onInputStart != null || tool.onInputAvailable != null) {
									const context = await validateToolContext({
										toolName: toolCall.toolName,
										context: getOwn(toolsContext, toolCall.toolName),
										contextSchema: tool.contextSchema
									});
									if (tool.onInputStart != null) await tool.onInputStart({
										toolCallId: toolCall.toolCallId,
										messages: stepMessages,
										abortSignal: mergedAbortSignal,
										context
									});
									if (tool.onInputAvailable != null) await tool.onInputAvailable({
										input: toolCall.input,
										toolCallId: toolCall.toolCallId,
										messages: stepMessages,
										abortSignal: mergedAbortSignal,
										context
									});
								}
								const toolApprovalStatus = await resolveToolApproval({
									tools: stepExecutionTools,
									toolApproval,
									toolCall,
									messages: stepMessages,
									toolsContext,
									runtimeContext
								});
								if (toolApprovalStatus.type === "not-applicable") continue;
								const approvalId = generateId();
								const signature = await maybeSignApproval({
									secret: experimental_toolApprovalSecret,
									approvalId,
									toolCallId: toolCall.toolCallId,
									toolName: toolCall.toolName,
									input: toolCall.input
								});
								switch (toolApprovalStatus.type) {
									case "user-approval":
										toolApprovalRequests[toolCall.toolCallId] = {
											type: "tool-approval-request",
											approvalId,
											toolCall,
											...toolApprovalStatus.reason != null ? { reason: toolApprovalStatus.reason } : {},
											...signature != null ? { signature } : {}
										};
										blockedToolCallIds.add(toolCall.toolCallId);
										break;
									case "approved":
										toolApprovalRequests[toolCall.toolCallId] = {
											type: "tool-approval-request",
											approvalId,
											toolCall,
											isAutomatic: true,
											...signature != null ? { signature } : {}
										};
										stepToolApprovalResponses[toolCall.toolCallId] = {
											type: "tool-approval-response",
											approvalId,
											toolCall,
											approved: true,
											reason: toolApprovalStatus.reason,
											providerExecuted: toolCall.providerExecuted
										};
										break;
									case "denied":
										toolApprovalRequests[toolCall.toolCallId] = {
											type: "tool-approval-request",
											approvalId,
											toolCall,
											isAutomatic: true,
											...signature != null ? { signature } : {}
										};
										stepToolApprovalResponses[toolCall.toolCallId] = {
											type: "tool-approval-response",
											approvalId,
											toolCall,
											approved: false,
											reason: toolApprovalStatus.reason,
											providerExecuted: toolCall.providerExecuted
										};
										blockedToolCallIds.add(toolCall.toolCallId);
								}
							}
							const invalidToolCalls = stepToolCalls.filter((toolCall) => toolCall.invalid && toolCall.dynamic && !toolCall.providerExecuted);
							clientToolOutputs = [];
							for (const toolCall of invalidToolCalls) clientToolOutputs.push({
								type: "tool-error",
								toolCallId: toolCall.toolCallId,
								toolName: toolCall.toolName,
								input: toolCall.input,
								error: getErrorMessage(toolCall.error),
								dynamic: true
							});
							clientToolCalls = stepToolCalls.filter((toolCall) => !toolCall.providerExecuted);
							toolApprovalResponses = Object.values(stepToolApprovalResponses);
							deniedToolApprovalResponses = toolApprovalResponses.filter((toolApprovalResponse) => toolApprovalResponse.approved === false);
							const toolExecutionMs = {};
							if (stepExecutionTools != null && isToolExecutionAllowedFinishReason(currentModelResponse.finishReason.unified)) {
								const toolExecutionResults = await executeTools({
									toolCalls: clientToolCalls.filter((toolCall) => !toolCall.invalid && !blockedToolCallIds.has(toolCall.toolCallId)),
									tools: stepExecutionTools,
									callId,
									messages: stepMessages,
									abortSignal: mergedAbortSignal,
									timeout,
									experimental_sandbox: stepSandbox,
									toolsContext,
									onToolExecutionStart: (event) => notify({
										event,
										callbacks: [resolvedOnToolExecutionStart, telemetryDispatcher.onToolExecutionStart]
									}),
									onToolExecutionEnd: (event) => notify({
										event,
										callbacks: [resolvedOnToolExecutionEnd, telemetryDispatcher.onToolExecutionEnd]
									}),
									executeToolInTelemetryContext: telemetryDispatcher.executeTool,
									runInTracingChannelSpan,
									toolCallConcurrency: resolvedToolCallConcurrency
								});
								for (const result of toolExecutionResults) {
									toolExecutionMs[result.output.toolCallId] = result.toolExecutionMs;
									clientToolOutputs.push(result.output);
								}
							}
							const stepTimeMs = now$4() - stepStartTimestampMs;
							const stepPerformance = {
								effectiveOutputTokensPerSecond: calculateTokensPerSecond({
									tokens: stepUsage.outputTokens,
									durationMs: responseTimeMs
								}),
								outputTokensPerSecond: void 0,
								inputTokensPerSecond: void 0,
								effectiveTotalTokensPerSecond: calculateTokensPerSecond({
									tokens: sumTokenCounts(stepUsage.inputTokens, stepUsage.outputTokens),
									durationMs: responseTimeMs
								}),
								stepTimeMs,
								responseTimeMs,
								toolExecutionMs,
								timeToFirstOutputMs: void 0
							};
							for (const toolCall of stepToolCalls) {
								if (!toolCall.providerExecuted) continue;
								const tool = getOwn(stepExecutionTools, toolCall.toolName);
								if (tool?.type === "provider" && tool.supportsDeferredResults) {
									if (!currentModelResponse.content.some((part) => part.type === "tool-result" && part.toolCallId === toolCall.toolCallId)) pendingDeferredToolCalls.set(toolCall.toolCallId, { toolName: toolCall.toolName });
								}
							}
							for (const part of currentModelResponse.content) if (part.type === "tool-result") pendingDeferredToolCalls.delete(part.toolCallId);
							const stepContent = await convertLanguageModelContent({
								content: currentModelResponse.content,
								toolCalls: stepToolCalls,
								toolOutputs: clientToolOutputs,
								toolApprovalRequests: Object.values(toolApprovalRequests),
								toolApprovalResponses,
								tools,
								download,
								abortSignal: mergedAbortSignal,
								generatedFileDataCache
							});
							const stepResponseMessages = await toResponseMessages({
								content: stepContent,
								tools
							});
							const stepRequest = {
								...currentModelResponse.request,
								body: include.requestBody ? currentModelResponse.request?.body : void 0,
								messages: include.requestMessages ? cloneModelMessages(stepMessages) : void 0
							};
							const stepResponse = {
								...currentModelResponse.response,
								messages: cloneModelMessages(stepResponseMessages),
								body: include.responseBody ? currentModelResponse.response?.body : void 0
							};
							const currentStepResult = new DefaultStepResult({
								callId,
								stepNumber,
								provider: stepModel.provider,
								modelId: stepModel.modelId,
								runtimeContext,
								content: stepContent,
								finishReason: currentModelResponse.finishReason.unified,
								rawFinishReason: currentModelResponse.finishReason.raw,
								usage: stepUsage,
								performance: stepPerformance,
								warnings: currentModelResponse.warnings,
								providerMetadata: currentModelResponse.providerMetadata,
								request: stepRequest,
								response: stepResponse,
								toolsContext,
								steeringMessages: deliveredSteeringMessages
							});
							logWarnings({
								warnings: currentModelResponse.warnings ?? [],
								provider: stepModel.provider,
								model: stepModel.modelId
							});
							steps.push(currentStepResult);
							instructionsForNextStep = stepInstructions;
							messagesForNextStep = [...stepMessages, ...stepResponseMessages];
							openStep = void 0;
							await notify({
								event: currentStepResult,
								callbacks: [resolvedOnStepEnd, telemetryDispatcher.onStepEnd]
							});
							return currentStepResult;
						}
					});
				} finally {
					if (stepTimeoutId != null) clearTimeout(stepTimeoutId);
				}
			} while (await shouldStartNextStep());
			steeringRun?.end(steeringEndReason);
			const lastStep = steps[steps.length - 1];
			const totalUsage = steps.reduce((totalUsage, step) => {
				return addLanguageModelUsage(totalUsage, step.usage);
			}, {
				inputTokens: void 0,
				inputTokenDetails: {
					noCacheTokens: void 0,
					cacheReadTokens: void 0,
					cacheWriteTokens: void 0
				},
				outputTokens: void 0,
				outputTokenDetails: {
					textTokens: void 0,
					reasoningTokens: void 0
				},
				totalTokens: void 0
			});
			const files = steps.flatMap((step) => step.files);
			const sources = steps.flatMap((step) => step.sources);
			const toolCalls = steps.flatMap((step) => step.toolCalls);
			const staticToolCalls = steps.flatMap((step) => step.staticToolCalls);
			const dynamicToolCalls = steps.flatMap((step) => step.dynamicToolCalls);
			const toolResults = steps.flatMap((step) => step.toolResults);
			const staticToolResults = steps.flatMap((step) => step.staticToolResults);
			const dynamicToolResults = steps.flatMap((step) => step.dynamicToolResults);
			const warnings = steps.flatMap((step) => step.warnings ?? []);
			await notify({
				event: {
					callId,
					stepNumber: lastStep.stepNumber,
					model: lastStep.model,
					runtimeContext: lastStep.runtimeContext,
					finishReason: lastStep.finishReason,
					rawFinishReason: lastStep.rawFinishReason,
					usage: totalUsage,
					totalUsage,
					content: steps.flatMap((step) => step.content),
					text: lastStep.text,
					reasoning: lastStep.reasoning,
					reasoningText: lastStep.reasoningText,
					files,
					sources,
					toolCalls,
					staticToolCalls,
					dynamicToolCalls,
					toolResults,
					staticToolResults,
					dynamicToolResults,
					responseMessages: [...initialResponseMessages, ...steps.flatMap((step) => step.response.messages)],
					warnings,
					request: lastStep.request,
					response: lastStep.response,
					providerMetadata: lastStep.providerMetadata,
					steps,
					finalStep: lastStep,
					toolsContext
				},
				callbacks: [onEnd, telemetryDispatcher.onEnd]
			});
			let resolvedOutput;
			if (lastStep.finishReason === "stop" || lastStep.finishReason !== "tool-calls" && lastStep.text.length > 0) {
				const outputSpecification = output ?? text();
				const textForOutput = (await outputSpecification.responseFormat)?.type === "json" ? currentModelResponse.structuredOutputText ?? lastStep.text : lastStep.text;
				resolvedOutput = await outputSpecification.parseCompleteOutput({ text: textForOutput }, {
					response: lastStep.response,
					usage: lastStep.usage,
					finishReason: lastStep.finishReason
				});
			}
			return new DefaultGenerateTextResult({
				initialResponseMessages,
				steps,
				totalUsage,
				output: resolvedOutput
			});
		} catch (error) {
			const wrappedError = wrapGatewayError(error);
			steeringRun?.end(mergedAbortSignal?.aborted ? "aborted" : "error");
			if (openStep != null) await notify({
				event: {
					...openStep,
					error: wrappedError
				},
				callbacks: [onStepError, telemetryDispatcher.onStepError]
			});
			await telemetryDispatcher.onError?.({
				callId,
				error
			});
			throw wrappedError;
		}
	};
	return await runInTracingChannelSpan({
		type: "generateText",
		event: generateTextStartEvent,
		execute: executeGenerateText
	});
}
async function executeTools({ toolCalls, tools, callId, messages, abortSignal, timeout, experimental_sandbox: sandbox, toolsContext, onToolExecutionStart, onToolExecutionEnd, executeToolInTelemetryContext, runInTracingChannelSpan, toolCallConcurrency }) {
	return (await mapWithConcurrency({
		items: toolCalls,
		concurrency: toolCallConcurrency,
		abortSignal,
		execute: async (toolCall) => await executeToolCall({
			toolCall,
			tools,
			callId,
			messages,
			abortSignal,
			timeout,
			experimental_sandbox: sandbox,
			toolsContext,
			onToolExecutionStart,
			onToolExecutionEnd,
			executeToolInTelemetryContext,
			runInTracingChannelSpan
		})
	})).filter((result) => result != null);
}
//#endregion
//#region src/util/prepare-headers.ts
function prepareHeaders(headers, defaultHeaders) {
	const responseHeaders = new Headers(headers ?? {});
	for (const [key, value] of Object.entries(defaultHeaders)) if (!responseHeaders.has(key)) responseHeaders.set(key, value);
	return responseHeaders;
}
//#endregion
//#region src/text-stream/create-text-stream-response.ts
/**
* Creates a Response object from a text stream.
* Each text chunk is encoded as UTF-8 and sent as a separate chunk.
* Sets a `Content-Type` header to `text/plain; charset=utf-8`.
*
* @param options - The options for creating the response.
* @param options.status - Optional HTTP status code (default: 200).
* @param options.statusText - Optional HTTP status text.
* @param options.headers - Optional response headers.
* @param options.stream - The text stream to send.
* @returns A Response object with the text stream body.
*/
function createTextStreamResponse({ status, statusText, headers, stream }) {
	return new Response(stream.pipeThrough(new TextEncoderStream()), {
		status: status ?? 200,
		statusText,
		headers: prepareHeaders(headers, { "content-type": "text/plain; charset=utf-8" })
	});
}
//#endregion
//#region src/util/write-to-server-response.ts
/**
* Writes the content of a stream to a server response.
*
* When the client disconnects before the stream has been fully written
* (premature `close`), the stream is cancelled so that upstream resources
* can be released, and no further chunks are written.
*/
function writeToServerResponse({ response, status, statusText, headers, stream }) {
	const statusCode = status ?? 200;
	if (headers != null) response.setHeaders(headers);
	if (statusText !== void 0) response.writeHead(statusCode, statusText);
	else response.writeHead(statusCode);
	const reader = stream.getReader();
	let clientDisconnected = false;
	let onDisconnect;
	const handleClose = () => {
		if (response.writableFinished) return;
		clientDisconnected = true;
		onDisconnect?.();
		reader.cancel(/* @__PURE__ */ new Error("Client disconnected.")).catch(() => {});
	};
	response.once("close", handleClose);
	if (response.destroyed) handleClose();
	const read = async () => {
		try {
			while (true) {
				const { done, value } = await reader.read();
				if (done || clientDisconnected || response.destroyed) break;
				const canContinue = response.write(value);
				const flush = response.flush;
				if (typeof flush === "function") flush.call(response);
				if (!canContinue) {
					await new Promise((resolve) => {
						onDisconnect = resolve;
						response.once("drain", resolve);
					});
					onDisconnect = void 0;
				}
			}
		} finally {
			response.off("close", handleClose);
			if (clientDisconnected || response.destroyed) reader.cancel().catch(() => {});
			else response.end();
		}
	};
	return read();
}
//#endregion
//#region src/text-stream/pipe-text-stream-to-response.ts
/**
* Writes a text stream to a Node.js ServerResponse object.
* Each text chunk is encoded as UTF-8 and written as a separate chunk.
* Sets a `Content-Type` header to `text/plain; charset=utf-8`.
*
* @param options - The options for piping the stream.
* @param options.response - The Node.js ServerResponse to write to.
* @param options.status - Optional HTTP status code.
* @param options.statusText - Optional HTTP status text.
* @param options.headers - Optional response headers.
* @param options.stream - The text stream to pipe.
* @returns A promise that resolves when the stream has been written.
*/
function pipeTextStreamToResponse({ response, status, statusText, headers, stream }) {
	return writeToServerResponse({
		response,
		status,
		statusText,
		headers: prepareHeaders(headers, { "content-type": "text/plain; charset=utf-8" }),
		stream: stream.pipeThrough(new TextEncoderStream())
	});
}
//#endregion
//#region src/text-stream/to-text-stream.ts
/**
* Converts a stream of `TextStreamPart` chunks into a stream of text deltas.
*/
function toTextStream({ stream }) {
	return stream.pipeThrough(new TransformStream({ transform(part, controller) {
		if (part.type === "text-delta") controller.enqueue(part.text);
	} }));
}
//#endregion
//#region src/ui-message-stream/create-sse-stream-with-keep-alive.ts
const STREAM_OPEN_COMMENT = ": stream-open\n\n";
const KEEP_ALIVE_COMMENT = ": keep-alive\n\n";
function createSseStreamWithKeepAlive({ stream, keepAliveMs }) {
	if (keepAliveMs == null) return stream;
	if (!Number.isFinite(keepAliveMs) || keepAliveMs <= 0 || keepAliveMs > 2147483647) throw new Error("keepAliveMs must be a positive finite timer duration no greater than 2147483647");
	const reader = stream.getReader();
	let keepAliveTimeout;
	let isCancelled = false;
	const clearKeepAliveTimeout = () => {
		clearTimeout(keepAliveTimeout);
		keepAliveTimeout = void 0;
	};
	const scheduleKeepAlive = (controller) => {
		clearKeepAliveTimeout();
		keepAliveTimeout = setTimeout(() => {
			if (isCancelled) return;
			if (controller.desiredSize != null && controller.desiredSize > 0) controller.enqueue(KEEP_ALIVE_COMMENT);
			scheduleKeepAlive(controller);
		}, keepAliveMs);
	};
	return new ReadableStream({
		start(controller) {
			controller.enqueue(STREAM_OPEN_COMMENT);
			scheduleKeepAlive(controller);
		},
		pull(controller) {
			return reader.read().then((result) => {
				clearKeepAliveTimeout();
				if (isCancelled) return;
				if (result.done) controller.close();
				else {
					controller.enqueue(result.value);
					scheduleKeepAlive(controller);
				}
			}, (error) => {
				clearKeepAliveTimeout();
				if (!isCancelled) throw error;
			});
		},
		async cancel(reason) {
			isCancelled = true;
			clearKeepAliveTimeout();
			await reader.cancel(reason);
		}
	});
}
//#endregion
//#region src/ui-message-stream/json-to-sse-transform-stream.ts
/**
* A TransformStream that converts JSON objects to Server-Sent Events (SSE) format.
* Each object is serialized to JSON and wrapped in `data: ...\n\n` format.
* When the stream ends, a `data: [DONE]\n\n` message is sent.
*/
var JsonToSseTransformStream = class extends TransformStream {
	constructor() {
		super({
			transform(part, controller) {
				controller.enqueue(`data: ${JSON.stringify(part)}\n\n`);
			},
			flush(controller) {
				controller.enqueue("data: [DONE]\n\n");
			}
		});
	}
};
//#endregion
//#region src/ui-message-stream/ui-message-stream-headers.ts
const UI_MESSAGE_STREAM_HEADERS = {
	"content-type": "text/event-stream",
	"cache-control": "no-cache",
	connection: "keep-alive",
	"x-vercel-ai-ui-message-stream": "v1",
	"x-accel-buffering": "no"
};
//#endregion
//#region src/ui-message-stream/create-ui-message-stream-response.ts
/**
* Creates a Response object from a UI message stream.
* The stream is transformed to Server-Sent Events (SSE) format.
*
* @param options.status - The HTTP status code for the response.
* @param options.statusText - The HTTP status text for the response.
* @param options.headers - Additional HTTP headers to include in the response.
* @param options.stream - The UI message chunk stream to send.
* @param options.keepAliveMs - Optional interval for sending SSE keep-alive comments.
* @param options.consumeSseStream - Optional callback to consume a copy of the SSE stream independently.
*
* @returns A `Response` object with the UI message stream as the body.
*/
function createUIMessageStreamResponse({ status, statusText, headers, stream, keepAliveMs, consumeSseStream }) {
	let sseStream = createSseStreamWithKeepAlive({
		stream: stream.pipeThrough(new JsonToSseTransformStream()),
		keepAliveMs
	});
	if (consumeSseStream) {
		const [stream1, stream2] = sseStream.tee();
		sseStream = stream1;
		consumeSseStream({ stream: stream2 });
	}
	return new Response(sseStream.pipeThrough(new TextEncoderStream()), {
		status,
		statusText,
		headers: prepareHeaders(headers, UI_MESSAGE_STREAM_HEADERS)
	});
}
//#endregion
//#region src/ui-message-stream/pipe-ui-message-stream-to-response.ts
/**
* Pipes a UI message stream to a Node.js ServerResponse object.
* The stream is transformed to Server-Sent Events (SSE) format.
*
* @param options.response - The Node.js ServerResponse object to write to.
* @param options.status - The HTTP status code for the response.
* @param options.statusText - The HTTP status text for the response.
* @param options.headers - Additional HTTP headers to include in the response.
* @param options.stream - The UI message chunk stream to send.
* @param options.keepAliveMs - Optional interval for sending SSE keep-alive comments.
* @param options.consumeSseStream - Optional callback to consume a copy of the SSE stream independently.
* @returns A promise that resolves when the stream has been written.
*/
function pipeUIMessageStreamToResponse({ response, status, statusText, headers, stream, keepAliveMs, consumeSseStream }) {
	let sseStream = createSseStreamWithKeepAlive({
		stream: stream.pipeThrough(new JsonToSseTransformStream()),
		keepAliveMs
	});
	if (consumeSseStream) {
		const [stream1, stream2] = sseStream.tee();
		sseStream = stream1;
		consumeSseStream({ stream: stream2 });
	}
	return writeToServerResponse({
		response,
		status,
		statusText,
		headers: prepareHeaders(headers, UI_MESSAGE_STREAM_HEADERS),
		stream: sseStream.pipeThrough(new TextEncoderStream())
	});
}
//#endregion
//#region src/ui-message-stream/get-model-tool-error-text.ts
/**
* Returns the error text that the model receives for a failed tool call (see
* `createToolModelOutput` with `errorMode: 'text'`), or `undefined` when the
* error cannot be serialized. In that case the model did not receive an error
* text either, because creating the tool result fails the same way.
*/
function getModelToolErrorText(error) {
	try {
		return getErrorMessage$1(error);
	} catch {
		return;
	}
}
//#endregion
//#region src/ui-message-stream/get-response-ui-message-id.ts
/**
* Determines the message ID to use for a response message.
* If the last message is an assistant message, its ID is reused (continuation).
* Otherwise, a new ID is generated or the provided ID is used.
*
* @param options.originalMessages - The original messages. If not provided, returns `undefined`
*   since client-side ID generation is used in non-persistence mode.
* @param options.responseMessageId - The response message ID or an ID generator function.
*
* @returns The message ID to use, or `undefined` if no persistence mode.
*/
function getResponseUIMessageId({ originalMessages, responseMessageId }) {
	if (originalMessages == null) return;
	const lastMessage = originalMessages[originalMessages.length - 1];
	return lastMessage?.role === "assistant" ? lastMessage.id : typeof responseMessageId === "function" ? responseMessageId() : responseMessageId;
}
//#endregion
//#region src/util/zod.ts
const z$1 = {
	NEVER,
	array,
	boolean,
	custom,
	discriminatedUnion,
	enum: enum$1,
	extend,
	int,
	literal,
	looseObject,
	maximum,
	minLength,
	never,
	nonnegative,
	number,
	object,
	optional,
	pipe,
	positive,
	record,
	refine,
	safeParse,
	startsWith,
	string,
	transform,
	union,
	unknown
};
//#endregion
//#region src/util/classic-zod.ts
const z = {
	array: array$1,
	boolean: boolean$1,
	custom: custom$1,
	discriminatedUnion: discriminatedUnion$1,
	instanceof: instanceof$1,
	lazy,
	literal: literal$1,
	null: null$1,
	number: number$1,
	object: object$1,
	record: record$1,
	string: string$1,
	union: union$1,
	unknown: unknown$1
};
//#endregion
//#region src/types/json-value.ts
const jsonValueSchema = z.lazy(() => z.union([
	z.null(),
	z.string(),
	z.number(),
	z.boolean(),
	z.record(z.string(), jsonValueSchema.optional()),
	z.array(jsonValueSchema)
]));
//#endregion
//#region src/types/provider-metadata.ts
const providerMetadataSchema$1 = z.record(z.string(), z.record(z.string(), jsonValueSchema.optional()));
//#endregion
//#region src/types/citation.ts
const citationSchema = z$1.object({
	source: z$1.discriminatedUnion("sourceType", [z$1.object({
		type: z$1.literal("source"),
		sourceType: z$1.literal("url"),
		id: z$1.string(),
		url: z$1.string(),
		title: z$1.optional(z$1.string()),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}), z$1.object({
		type: z$1.literal("source"),
		sourceType: z$1.literal("document"),
		id: z$1.string(),
		mediaType: z$1.string(),
		title: z$1.string(),
		filename: z$1.optional(z$1.string()),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	})]),
	startIndex: z$1.optional(z$1.number().check(z$1.int()).check(z$1.nonnegative())),
	endIndex: z$1.optional(z$1.number().check(z$1.int()).check(z$1.nonnegative())),
	citedText: z$1.optional(z$1.string())
});
//#endregion
//#region src/ui-message-stream/ui-message-chunks.ts
const toolMetadataSchema$1 = z$1.record(z$1.string(), z$1.optional(jsonValueSchema));
const uiMessageChunkSchema = lazySchema(() => zodSchema$1(z$1.union([
	z$1.looseObject({
		type: z$1.literal("text-start"),
		id: z$1.string(),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("text-delta"),
		id: z$1.string(),
		delta: z$1.string(),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("text-end"),
		id: z$1.string(),
		citations: z$1.optional(z$1.array(citationSchema)),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("error"),
		errorText: z$1.string()
	}),
	z$1.looseObject({
		type: z$1.literal("tool-input-start"),
		toolCallId: z$1.string(),
		toolName: z$1.string(),
		inputEncoding: z$1.optional(z$1.enum(["json", "text"])),
		providerExecuted: z$1.optional(z$1.boolean()),
		providerMetadata: z$1.optional(providerMetadataSchema$1),
		toolMetadata: z$1.optional(toolMetadataSchema$1),
		dynamic: z$1.optional(z$1.boolean()),
		title: z$1.optional(z$1.string())
	}),
	z$1.looseObject({
		type: z$1.literal("tool-input-delta"),
		toolCallId: z$1.string(),
		inputTextDelta: z$1.string()
	}),
	z$1.looseObject({
		type: z$1.literal("tool-input-available"),
		toolCallId: z$1.string(),
		toolName: z$1.string(),
		input: z$1.unknown(),
		providerExecuted: z$1.optional(z$1.boolean()),
		providerMetadata: z$1.optional(providerMetadataSchema$1),
		toolMetadata: z$1.optional(toolMetadataSchema$1),
		dynamic: z$1.optional(z$1.boolean()),
		title: z$1.optional(z$1.string())
	}),
	z$1.looseObject({
		type: z$1.literal("tool-input-error"),
		toolCallId: z$1.string(),
		toolName: z$1.string(),
		input: z$1.unknown(),
		providerExecuted: z$1.optional(z$1.boolean()),
		providerMetadata: z$1.optional(providerMetadataSchema$1),
		toolMetadata: z$1.optional(toolMetadataSchema$1),
		dynamic: z$1.optional(z$1.boolean()),
		errorText: z$1.string(),
		title: z$1.optional(z$1.string())
	}),
	z$1.looseObject({
		type: z$1.literal("tool-approval-request"),
		approvalId: z$1.string(),
		toolCallId: z$1.string(),
		approvalDescriptor: z$1.optional(z$1.unknown()),
		inputSchemaInput: z$1.optional(z$1.unknown()),
		reason: z$1.optional(z$1.string()),
		isAutomatic: z$1.optional(z$1.boolean()),
		signature: z$1.optional(z$1.string())
	}),
	z$1.looseObject({
		type: z$1.literal("tool-approval-response"),
		approvalId: z$1.string(),
		approved: z$1.boolean(),
		reason: z$1.optional(z$1.string()),
		providerExecuted: z$1.optional(z$1.boolean()),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("tool-output-available"),
		toolCallId: z$1.string(),
		output: z$1.unknown(),
		providerExecuted: z$1.optional(z$1.boolean()),
		providerMetadata: z$1.optional(providerMetadataSchema$1),
		toolMetadata: z$1.optional(toolMetadataSchema$1),
		dynamic: z$1.optional(z$1.boolean()),
		preliminary: z$1.optional(z$1.boolean())
	}),
	z$1.looseObject({
		type: z$1.literal("tool-output-error"),
		toolCallId: z$1.string(),
		errorText: z$1.string(),
		providerExecuted: z$1.optional(z$1.boolean()),
		providerMetadata: z$1.optional(providerMetadataSchema$1),
		toolMetadata: z$1.optional(toolMetadataSchema$1),
		dynamic: z$1.optional(z$1.boolean())
	}),
	z$1.looseObject({
		type: z$1.literal("tool-output-denied"),
		toolCallId: z$1.string()
	}),
	z$1.looseObject({
		type: z$1.literal("reasoning-start"),
		id: z$1.string(),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("reasoning-delta"),
		id: z$1.string(),
		delta: z$1.string(),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("reasoning-end"),
		id: z$1.string(),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("custom"),
		kind: z$1.pipe(z$1.string(), z$1.transform((value) => value)),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("source-url"),
		sourceId: z$1.string(),
		url: z$1.string(),
		title: z$1.optional(z$1.string()),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("source-document"),
		sourceId: z$1.string(),
		mediaType: z$1.string(),
		title: z$1.string(),
		filename: z$1.optional(z$1.string()),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("file"),
		url: z$1.string(),
		mediaType: z$1.string(),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("reasoning-file"),
		url: z$1.string(),
		mediaType: z$1.string(),
		providerMetadata: z$1.optional(providerMetadataSchema$1)
	}),
	z$1.looseObject({
		type: z$1.literal("steering-message"),
		id: z$1.string(),
		parts: z$1.array(z$1.union([z$1.looseObject({
			type: z$1.literal("text"),
			text: z$1.string(),
			providerMetadata: z$1.optional(providerMetadataSchema$1)
		}), z$1.looseObject({
			type: z$1.literal("file"),
			mediaType: z$1.string(),
			url: z$1.string(),
			filename: z$1.optional(z$1.string()),
			providerReference: z$1.optional(z$1.record(z$1.string(), z$1.string())),
			providerMetadata: z$1.optional(providerMetadataSchema$1)
		})]))
	}),
	z$1.looseObject({
		type: z$1.custom((value) => typeof value === "string" && value.startsWith("data-"), { message: "Type must start with \"data-\"" }),
		id: z$1.optional(z$1.string()),
		data: z$1.unknown(),
		transient: z$1.optional(z$1.boolean())
	}),
	z$1.looseObject({ type: z$1.literal("start-step") }),
	z$1.looseObject({ type: z$1.literal("finish-step") }),
	z$1.looseObject({ type: z$1.literal("reset-step") }),
	z$1.looseObject({
		type: z$1.literal("start"),
		messageId: z$1.optional(z$1.string()),
		messageMetadata: z$1.optional(z$1.unknown())
	}),
	z$1.looseObject({
		type: z$1.literal("finish"),
		finishReason: z$1.optional(z$1.enum([
			"stop",
			"length",
			"content-filter",
			"tool-calls",
			"error",
			"interrupted",
			"other"
		])),
		messageMetadata: z$1.optional(z$1.unknown())
	}),
	z$1.looseObject({
		type: z$1.literal("abort"),
		reason: z$1.optional(z$1.string())
	}),
	z$1.looseObject({
		type: z$1.literal("message-metadata"),
		messageMetadata: z$1.unknown()
	})
])));
function isDataUIMessageChunk(chunk) {
	return chunk.type.startsWith("data-");
}
//#endregion
//#region src/util/create-id-map.ts
/**
* Creates a string-keyed map without an object prototype.
*
* Use this for lookup tables keyed by IDs or names that may come from outside
* the SDK, such as streamed chunk IDs or tool call IDs. Unlike `{}`, these maps
* do not inherit `__proto__`, `constructor`, or other Object prototype members,
* so a missing untrusted key cannot resolve to a shared prototype object.
*/
function createIdMap() {
	return Object.create(null);
}
//#endregion
//#region src/ui/ui-messages.ts
/**
* Check if a message part is a data part.
*/
function isDataUIPart(part) {
	return part.type.startsWith("data-");
}
/**
* Type guard to check if a message part is a text part.
*/
function isTextUIPart(part) {
	return part.type === "text";
}
/**
* Type guard to check if a message part is a custom part.
*/
function isCustomContentUIPart(part) {
	return part.type === "custom";
}
/**
* Type guard to check if a message part is a file part.
*/
function isFileUIPart(part) {
	return part.type === "file";
}
/**
* Type guard to check if a message part is a reasoning file part.
*/
function isReasoningFileUIPart(part) {
	return part.type === "reasoning-file";
}
/**
* Type guard to check if a message part is a reasoning part.
*/
function isReasoningUIPart(part) {
	return part.type === "reasoning";
}
/**
* Check if a message part is a static tool part.
*
* Static tools are tools for which the types are known at development time.
*/
function isStaticToolUIPart(part) {
	return part.type.startsWith("tool-");
}
/**
* Check if a message part is a dynamic tool part.
*
* Dynamic tools are tools for which the input and output types are unknown.
*/
function isDynamicToolUIPart(part) {
	return part.type === "dynamic-tool";
}
/**
* Check if a message part is a tool part.
*
* Tool parts are either static or dynamic tools.
*
* Use `isStaticToolUIPart` or `isDynamicToolUIPart` to check the type of the tool.
*/
function isToolUIPart(part) {
	return isStaticToolUIPart(part) || isDynamicToolUIPart(part);
}
/**
* Check if a message part is a tool output error part.
*
* This works for both static and dynamic tools.
*/
function isToolOutputErrorUIPart(part) {
	return isToolUIPart(part) && part.state === "output-error";
}
/**
* Returns the name of the static tool.
*
* The possible values are the keys of the tool set.
*/
function getStaticToolName(part) {
	return part.type.split("-").slice(1).join("-");
}
/**
* Returns the name of the tool (static or dynamic).
*
* This function will not restrict the name to the keys of the tool set.
* If you need to restrict the name to the keys of the tool set, use `getStaticToolName` instead.
*/
function getToolName(part) {
	return isDynamicToolUIPart(part) ? part.toolName : getStaticToolName(part);
}
/**
* @deprecated Use getToolName instead.
*/
const getToolOrDynamicToolName = getToolName;
//#endregion
//#region src/ui/process-ui-message-stream.ts
function createStreamingUIMessageState({ lastMessage, messageId }) {
	const message = lastMessage?.role === "assistant" ? lastMessage : {
		id: messageId,
		metadata: void 0,
		role: "assistant",
		parts: []
	};
	const partialToolCalls = createIdMap();
	const lastStepStartIndex = message.parts.findLastIndex((part) => part.type === "step-start");
	let staticToolIndex = 0;
	for (const part of message.parts.slice(lastStepStartIndex + 1)) {
		if (!isToolUIPart(part)) continue;
		const index = staticToolIndex;
		if (isStaticToolUIPart(part)) staticToolIndex++;
		if (part.state !== "input-streaming") continue;
		partialToolCalls[part.toolCallId] = {
			text: part.rawInput ?? "",
			inputEncoding: part.inputEncoding,
			index,
			toolName: part.type === "dynamic-tool" ? part.toolName : getStaticToolName(part),
			dynamic: part.type === "dynamic-tool",
			title: part.title,
			toolMetadata: part.toolMetadata
		};
	}
	return {
		message,
		activeTextParts: createIdMap(),
		activeReasoningParts: createIdMap(),
		partialToolCalls
	};
}
function processUIMessageStream({ stream, messageMetadataSchema, dataPartSchemas, runUpdateMessageJob, onError, onToolCall, onData, resetStateOnMessageIdChange = false, resetStateOnFirstMessageStart = false }) {
	let isFirstMessageStart = true;
	return stream.pipeThrough(new TransformStream({ async transform(chunk, controller) {
		await runUpdateMessageJob(async ({ state, write }) => {
			function getCurrentStepParts() {
				const parts = state.message.parts;
				let currentStepStartIndex = parts.length - 1;
				while (currentStepStartIndex >= 0 && parts[currentStepStartIndex].type !== "step-start") currentStepStartIndex--;
				return parts.slice(currentStepStartIndex + 1);
			}
			function getCurrentStepToolInvocations() {
				return getCurrentStepParts().filter(isToolUIPart);
			}
			function getToolInvocation(toolCallId) {
				let toolInvocation = getCurrentStepToolInvocations().find((invocation) => invocation.toolCallId === toolCallId);
				if (toolInvocation == null) {
					const parts = state.message.parts;
					for (let i = parts.length - 1; i >= 0; i--) {
						const part = parts[i];
						if (isToolUIPart(part) && part.toolCallId === toolCallId) {
							toolInvocation = part;
							break;
						}
					}
				}
				if (toolInvocation == null) throw new UIMessageStreamError({
					chunkType: "tool-invocation",
					chunkId: toolCallId,
					message: `No tool invocation found for tool call ID "${toolCallId}".`
				});
				return toolInvocation;
			}
			function getToolInvocationByApprovalId(approvalId) {
				const toolInvocation = state.message.parts.filter(isToolUIPart).find((invocation) => invocation.approval?.id === approvalId);
				if (toolInvocation == null) throw new UIMessageStreamError({
					chunkType: "tool-approval-response",
					chunkId: approvalId,
					message: `No tool invocation found for approval ID "${approvalId}".`
				});
				return toolInvocation;
			}
			function updateToolPart(options, existingPart) {
				const part = existingPart ?? getCurrentStepParts().find((part) => isStaticToolUIPart(part) && part.toolCallId === options.toolCallId);
				const anyOptions = options;
				const anyPart = part;
				if (part != null) {
					part.state = options.state;
					anyPart.type = `tool-${options.toolName}`;
					anyPart.input = anyOptions.input;
					anyPart.output = anyOptions.output;
					anyPart.errorText = anyOptions.errorText;
					anyPart.rawInput = anyOptions.rawInput;
					if (anyOptions.inputEncoding != null) anyPart.inputEncoding = anyOptions.inputEncoding;
					else delete anyPart.inputEncoding;
					anyPart.preliminary = anyOptions.preliminary;
					if (options.title !== void 0) anyPart.title = options.title;
					if (options.toolMetadata !== void 0) anyPart.toolMetadata = options.toolMetadata;
					anyPart.providerExecuted = anyOptions.providerExecuted ?? part.providerExecuted;
					const providerMetadata = anyOptions.providerMetadata;
					if (providerMetadata != null) {
						if (options.state === "output-available" || options.state === "output-error") {
							const resultPart = part;
							resultPart.resultProviderMetadata = providerMetadata;
						} else part.callProviderMetadata = providerMetadata;
					}
				} else state.message.parts.push({
					type: `tool-${options.toolName}`,
					toolCallId: options.toolCallId,
					state: options.state,
					title: options.title,
					...options.toolMetadata !== void 0 ? { toolMetadata: options.toolMetadata } : {},
					input: anyOptions.input,
					...anyOptions.inputEncoding != null ? { inputEncoding: anyOptions.inputEncoding } : {},
					output: anyOptions.output,
					rawInput: anyOptions.rawInput,
					errorText: anyOptions.errorText,
					providerExecuted: anyOptions.providerExecuted,
					preliminary: anyOptions.preliminary,
					...anyOptions.providerMetadata != null && (options.state === "output-available" || options.state === "output-error") ? { resultProviderMetadata: anyOptions.providerMetadata } : {},
					...anyOptions.providerMetadata != null && !(options.state === "output-available" || options.state === "output-error") ? { callProviderMetadata: anyOptions.providerMetadata } : {}
				});
			}
			function updateDynamicToolPart(options, existingPart) {
				const part = existingPart ?? getCurrentStepParts().find((part) => part.type === "dynamic-tool" && part.toolCallId === options.toolCallId);
				const anyOptions = options;
				const anyPart = part;
				if (part != null) {
					part.state = options.state;
					anyPart.toolName = options.toolName;
					anyPart.input = anyOptions.input;
					anyPart.output = anyOptions.output;
					anyPart.errorText = anyOptions.errorText;
					anyPart.rawInput = anyOptions.rawInput;
					if (anyOptions.inputEncoding != null) anyPart.inputEncoding = anyOptions.inputEncoding;
					else delete anyPart.inputEncoding;
					anyPart.preliminary = anyOptions.preliminary;
					if (options.title !== void 0) anyPart.title = options.title;
					if (options.toolMetadata !== void 0) anyPart.toolMetadata = options.toolMetadata;
					anyPart.providerExecuted = anyOptions.providerExecuted ?? part.providerExecuted;
					const providerMetadata = anyOptions.providerMetadata;
					if (providerMetadata != null) {
						if (options.state === "output-available" || options.state === "output-error") {
							const resultPart = part;
							resultPart.resultProviderMetadata = providerMetadata;
						} else part.callProviderMetadata = providerMetadata;
					}
				} else state.message.parts.push({
					type: "dynamic-tool",
					toolName: options.toolName,
					toolCallId: options.toolCallId,
					state: options.state,
					input: anyOptions.input,
					...anyOptions.inputEncoding != null ? { inputEncoding: anyOptions.inputEncoding } : {},
					output: anyOptions.output,
					errorText: anyOptions.errorText,
					preliminary: anyOptions.preliminary,
					providerExecuted: anyOptions.providerExecuted,
					title: options.title,
					...options.toolMetadata !== void 0 ? { toolMetadata: options.toolMetadata } : {},
					...anyOptions.providerMetadata != null && (options.state === "output-available" || options.state === "output-error") ? { resultProviderMetadata: anyOptions.providerMetadata } : {},
					...anyOptions.providerMetadata != null && !(options.state === "output-available" || options.state === "output-error") ? { callProviderMetadata: anyOptions.providerMetadata } : {}
				});
			}
			async function updateMessageMetadata(metadata) {
				if (metadata != null) {
					const mergedMetadata = state.message.metadata != null ? mergeObjects(state.message.metadata, metadata) : metadata;
					if (messageMetadataSchema != null) await validateTypes({
						value: mergedMetadata,
						schema: messageMetadataSchema,
						context: {
							field: "message.metadata",
							entityId: state.message.id
						}
					});
					state.message.metadata = mergedMetadata;
				}
			}
			switch (chunk.type) {
				case "text-start": {
					const textPart = {
						type: "text",
						text: "",
						providerMetadata: chunk.providerMetadata,
						state: "streaming"
					};
					state.activeTextParts[chunk.id] = textPart;
					state.message.parts.push(textPart);
					write();
					break;
				}
				case "text-delta": {
					const textPart = state.activeTextParts[chunk.id];
					if (textPart == null) throw new UIMessageStreamError({
						chunkType: "text-delta",
						chunkId: chunk.id,
						message: `Received text-delta for missing text part with ID "${chunk.id}". Ensure a "text-start" chunk is sent before any "text-delta" chunks.`
					});
					textPart.text += chunk.delta;
					textPart.providerMetadata = chunk.providerMetadata ?? textPart.providerMetadata;
					write();
					break;
				}
				case "text-end": {
					const textPart = state.activeTextParts[chunk.id];
					if (textPart == null) throw new UIMessageStreamError({
						chunkType: "text-end",
						chunkId: chunk.id,
						message: `Received text-end for missing text part with ID "${chunk.id}". Ensure a "text-start" chunk is sent before any "text-end" chunks.`
					});
					textPart.state = "done";
					if (chunk.citations != null) textPart.citations = chunk.citations;
					textPart.providerMetadata = chunk.providerMetadata ?? textPart.providerMetadata;
					delete state.activeTextParts[chunk.id];
					write();
					break;
				}
				case "custom": {
					const customPart = {
						type: "custom",
						kind: chunk.kind,
						providerMetadata: chunk.providerMetadata
					};
					state.message.parts.push(customPart);
					write();
					break;
				}
				case "reasoning-start": {
					const reasoningPart = {
						type: "reasoning",
						id: chunk.id,
						text: "",
						providerMetadata: chunk.providerMetadata,
						state: "streaming"
					};
					state.activeReasoningParts[chunk.id] = reasoningPart;
					state.message.parts.push(reasoningPart);
					write();
					break;
				}
				case "reasoning-delta": {
					const reasoningPart = state.activeReasoningParts[chunk.id];
					if (reasoningPart == null) throw new UIMessageStreamError({
						chunkType: "reasoning-delta",
						chunkId: chunk.id,
						message: `Received reasoning-delta for missing reasoning part with ID "${chunk.id}". Ensure a "reasoning-start" chunk is sent before any "reasoning-delta" chunks.`
					});
					reasoningPart.text += chunk.delta;
					reasoningPart.providerMetadata = chunk.providerMetadata ?? reasoningPart.providerMetadata;
					write();
					break;
				}
				case "reasoning-end": {
					const reasoningPart = state.activeReasoningParts[chunk.id];
					if (reasoningPart == null) throw new UIMessageStreamError({
						chunkType: "reasoning-end",
						chunkId: chunk.id,
						message: `Received reasoning-end for missing reasoning part with ID "${chunk.id}". Ensure a "reasoning-start" chunk is sent before any "reasoning-end" chunks.`
					});
					reasoningPart.providerMetadata = chunk.providerMetadata ?? reasoningPart.providerMetadata;
					reasoningPart.state = "done";
					delete state.activeReasoningParts[chunk.id];
					write();
					break;
				}
				case "file":
				case "reasoning-file":
					state.message.parts.push({
						type: chunk.type,
						mediaType: chunk.mediaType,
						url: chunk.url,
						...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {}
					});
					write();
					break;
				case "source-url":
					state.message.parts.push({
						type: "source-url",
						sourceId: chunk.sourceId,
						url: chunk.url,
						title: chunk.title,
						providerMetadata: chunk.providerMetadata
					});
					write();
					break;
				case "source-document":
					state.message.parts.push({
						type: "source-document",
						sourceId: chunk.sourceId,
						mediaType: chunk.mediaType,
						title: chunk.title,
						filename: chunk.filename,
						providerMetadata: chunk.providerMetadata
					});
					write();
					break;
				case "tool-input-start": {
					const toolInvocations = getCurrentStepParts().filter(isStaticToolUIPart);
					state.partialToolCalls[chunk.toolCallId] = {
						text: "",
						inputEncoding: chunk.inputEncoding,
						toolName: chunk.toolName,
						index: toolInvocations.length,
						dynamic: chunk.dynamic,
						title: chunk.title,
						toolMetadata: chunk.toolMetadata
					};
					if (chunk.dynamic) updateDynamicToolPart({
						toolCallId: chunk.toolCallId,
						toolName: chunk.toolName,
						state: "input-streaming",
						inputEncoding: chunk.inputEncoding,
						input: void 0,
						providerExecuted: chunk.providerExecuted,
						title: chunk.title,
						toolMetadata: chunk.toolMetadata,
						providerMetadata: chunk.providerMetadata
					});
					else updateToolPart({
						toolCallId: chunk.toolCallId,
						toolName: chunk.toolName,
						state: "input-streaming",
						inputEncoding: chunk.inputEncoding,
						input: void 0,
						providerExecuted: chunk.providerExecuted,
						title: chunk.title,
						toolMetadata: chunk.toolMetadata,
						providerMetadata: chunk.providerMetadata
					});
					write();
					break;
				}
				case "tool-input-delta": {
					const partialToolCall = state.partialToolCalls[chunk.toolCallId];
					if (partialToolCall == null) throw new UIMessageStreamError({
						chunkType: "tool-input-delta",
						chunkId: chunk.toolCallId,
						message: `Received tool-input-delta for missing tool call with ID "${chunk.toolCallId}". Ensure a "tool-input-start" chunk is sent before any "tool-input-delta" chunks.`
					});
					partialToolCall.text += chunk.inputTextDelta;
					const partialArgs = partialToolCall.inputEncoding === "text" ? partialToolCall.text : (await parsePartialJson(partialToolCall.text)).value;
					if (partialToolCall.dynamic) updateDynamicToolPart({
						toolCallId: chunk.toolCallId,
						toolName: partialToolCall.toolName,
						state: "input-streaming",
						inputEncoding: partialToolCall.inputEncoding,
						input: partialArgs,
						rawInput: partialToolCall.text,
						title: partialToolCall.title,
						toolMetadata: partialToolCall.toolMetadata
					});
					else updateToolPart({
						toolCallId: chunk.toolCallId,
						toolName: partialToolCall.toolName,
						state: "input-streaming",
						inputEncoding: partialToolCall.inputEncoding,
						input: partialArgs,
						rawInput: partialToolCall.text,
						title: partialToolCall.title,
						toolMetadata: partialToolCall.toolMetadata
					});
					write();
					break;
				}
				case "tool-input-available":
					if (chunk.dynamic) updateDynamicToolPart({
						toolCallId: chunk.toolCallId,
						toolName: chunk.toolName,
						state: "input-available",
						input: chunk.input,
						providerExecuted: chunk.providerExecuted,
						providerMetadata: chunk.providerMetadata,
						title: chunk.title,
						toolMetadata: chunk.toolMetadata
					});
					else updateToolPart({
						toolCallId: chunk.toolCallId,
						toolName: chunk.toolName,
						state: "input-available",
						input: chunk.input,
						providerExecuted: chunk.providerExecuted,
						providerMetadata: chunk.providerMetadata,
						title: chunk.title,
						toolMetadata: chunk.toolMetadata
					});
					write();
					if (onToolCall && !chunk.providerExecuted) await onToolCall({ toolCall: chunk });
					break;
				case "tool-input-error": {
					const existingPart = getCurrentStepParts().filter(isToolUIPart).find((p) => p.toolCallId === chunk.toolCallId);
					if (existingPart != null ? existingPart.type === "dynamic-tool" : !!chunk.dynamic) updateDynamicToolPart({
						toolCallId: chunk.toolCallId,
						toolName: chunk.toolName,
						state: "output-error",
						input: chunk.input,
						errorText: chunk.errorText,
						providerExecuted: chunk.providerExecuted,
						providerMetadata: chunk.providerMetadata,
						toolMetadata: chunk.toolMetadata
					});
					else updateToolPart({
						toolCallId: chunk.toolCallId,
						toolName: chunk.toolName,
						state: "output-error",
						input: chunk.input,
						errorText: chunk.errorText,
						providerExecuted: chunk.providerExecuted,
						providerMetadata: chunk.providerMetadata,
						toolMetadata: chunk.toolMetadata
					});
					write();
					break;
				}
				case "tool-approval-request": {
					const toolInvocation = getToolInvocation(chunk.toolCallId);
					toolInvocation.state = "approval-requested";
					toolInvocation.approval = {
						id: chunk.approvalId,
						...chunk.approvalDescriptor != null ? { descriptor: chunk.approvalDescriptor } : {},
						...Object.prototype.hasOwnProperty.call(chunk, "inputSchemaInput") ? { inputSchemaInput: chunk.inputSchemaInput } : {},
						...chunk.reason != null ? { requestReason: chunk.reason } : {},
						...chunk.isAutomatic === true ? { isAutomatic: true } : {},
						...chunk.signature != null ? { signature: chunk.signature } : {}
					};
					write();
					break;
				}
				case "tool-approval-response": {
					const toolInvocation = getToolInvocationByApprovalId(chunk.approvalId);
					const approval = toolInvocation.approval == null ? { id: chunk.approvalId } : toolInvocation.approval;
					toolInvocation.state = "approval-responded";
					toolInvocation.approval = {
						...approval,
						id: chunk.approvalId,
						approved: chunk.approved,
						...chunk.reason != null ? { reason: chunk.reason } : {}
					};
					if (chunk.providerExecuted != null) toolInvocation.providerExecuted = chunk.providerExecuted;
					if (chunk.providerMetadata != null) toolInvocation.callProviderMetadata = chunk.providerMetadata;
					write();
					break;
				}
				case "tool-output-denied": {
					const toolInvocation = getToolInvocation(chunk.toolCallId);
					toolInvocation.state = "output-denied";
					write();
					break;
				}
				case "tool-output-available": {
					const toolInvocation = getToolInvocation(chunk.toolCallId);
					if (toolInvocation.type === "dynamic-tool") updateDynamicToolPart({
						toolCallId: chunk.toolCallId,
						toolName: toolInvocation.toolName,
						state: "output-available",
						input: toolInvocation.input,
						output: chunk.output,
						preliminary: chunk.preliminary,
						providerExecuted: chunk.providerExecuted,
						providerMetadata: chunk.providerMetadata,
						title: toolInvocation.title,
						toolMetadata: chunk.toolMetadata ?? toolInvocation.toolMetadata
					}, toolInvocation);
					else updateToolPart({
						toolCallId: chunk.toolCallId,
						toolName: getStaticToolName(toolInvocation),
						state: "output-available",
						input: toolInvocation.input,
						output: chunk.output,
						providerExecuted: chunk.providerExecuted,
						preliminary: chunk.preliminary,
						providerMetadata: chunk.providerMetadata,
						title: toolInvocation.title,
						toolMetadata: chunk.toolMetadata ?? toolInvocation.toolMetadata
					}, toolInvocation);
					write();
					break;
				}
				case "tool-output-error": {
					const toolInvocation = getToolInvocation(chunk.toolCallId);
					if (toolInvocation.type === "dynamic-tool") updateDynamicToolPart({
						toolCallId: chunk.toolCallId,
						toolName: toolInvocation.toolName,
						state: "output-error",
						input: toolInvocation.input,
						errorText: chunk.errorText,
						providerExecuted: chunk.providerExecuted,
						providerMetadata: chunk.providerMetadata,
						title: toolInvocation.title,
						toolMetadata: chunk.toolMetadata ?? toolInvocation.toolMetadata
					}, toolInvocation);
					else updateToolPart({
						toolCallId: chunk.toolCallId,
						toolName: getStaticToolName(toolInvocation),
						state: "output-error",
						input: toolInvocation.input,
						rawInput: toolInvocation.rawInput,
						errorText: chunk.errorText,
						providerExecuted: chunk.providerExecuted,
						providerMetadata: chunk.providerMetadata,
						title: toolInvocation.title,
						toolMetadata: chunk.toolMetadata ?? toolInvocation.toolMetadata
					}, toolInvocation);
					write();
					break;
				}
				case "steering-message":
					state.message.parts.push({
						type: "steering-message",
						id: chunk.id,
						parts: chunk.parts
					});
					write();
					break;
				case "start-step":
					state.message.parts.push({ type: "step-start" });
					break;
				case "finish-step": break;
				case "reset-step": {
					const currentStepParts = getCurrentStepParts();
					state.activeTextParts = createIdMap();
					state.activeReasoningParts = createIdMap();
					state.partialToolCalls = createIdMap();
					if (currentStepParts.length > 0) {
						state.message.parts.splice(state.message.parts.length - currentStepParts.length, currentStepParts.length);
						write();
					}
					break;
				}
				case "start": {
					const shouldReset = resetStateOnFirstMessageStart && isFirstMessageStart || resetStateOnMessageIdChange && chunk.messageId != null && chunk.messageId !== state.message.id;
					isFirstMessageStart = false;
					if (shouldReset) Object.assign(state, createStreamingUIMessageState({
						lastMessage: void 0,
						messageId: chunk.messageId ?? state.message.id
					}), { finishReason: void 0 });
					if (chunk.messageId != null) state.message.id = chunk.messageId;
					await updateMessageMetadata(chunk.messageMetadata);
					if (shouldReset || chunk.messageId != null || chunk.messageMetadata != null) write({ updateStatus: false });
					break;
				}
				case "finish":
					if (chunk.finishReason != null) state.finishReason = chunk.finishReason;
					await updateMessageMetadata(chunk.messageMetadata);
					if (chunk.messageMetadata != null) write();
					break;
				case "message-metadata":
					await updateMessageMetadata(chunk.messageMetadata);
					if (chunk.messageMetadata != null) write();
					break;
				case "error":
					onError?.(new Error(chunk.errorText));
					break;
				default: if (isDataUIMessageChunk(chunk)) {
					const dataPartSchema = dataPartSchemas?.[chunk.type.slice(5)];
					if (dataPartSchema != null) {
						const partIdx = state.message.parts.findIndex((p) => "id" in p && "data" in p && p.id === chunk.id && p.type === chunk.type);
						const actualPartIdx = partIdx >= 0 ? partIdx : state.message.parts.length;
						await validateTypes({
							value: chunk.data,
							schema: dataPartSchema,
							context: {
								field: `message.parts[${actualPartIdx}].data`,
								entityName: chunk.type,
								entityId: chunk.id
							}
						});
					}
					const dataChunk = chunk;
					if (dataChunk.transient) {
						onData?.(dataChunk);
						break;
					}
					const existingUIPart = dataChunk.id != null ? state.message.parts.find((chunkArg) => dataChunk.type === chunkArg.type && dataChunk.id === chunkArg.id) : void 0;
					if (existingUIPart != null) existingUIPart.data = dataChunk.data;
					else state.message.parts.push(dataChunk);
					onData?.(dataChunk);
					write();
				}
			}
			controller.enqueue(chunk);
		});
	} }));
}
//#endregion
//#region src/ui-message-stream/handle-ui-message-stream-finish.ts
function handleUIMessageStreamFinish({ messageId, originalMessages = [], onStepEnd, onStepFinish, onEnd, onFinish, onError, stream, getOutcome }) {
	let lastMessage = originalMessages?.[originalMessages.length - 1];
	if (lastMessage?.role !== "assistant") lastMessage = void 0;
	else messageId = lastMessage.id;
	let isAborted = false;
	let hasProcessingFailure = false;
	let processingError;
	const recordProcessingFailure = (error) => {
		hasProcessingFailure = true;
		processingError = error;
	};
	const idInjectedStream = stream.pipeThrough(new TransformStream({ transform(chunk, controller) {
		try {
			let outputChunk = chunk;
			if (chunk.type === "start") {
				const startChunk = chunk;
				if (startChunk.messageId == null && messageId != null) outputChunk = {
					...startChunk,
					messageId
				};
			}
			if (chunk.type === "abort") isAborted = true;
			controller.enqueue(outputChunk);
		} catch (error) {
			recordProcessingFailure(error);
			throw error;
		}
	} }));
	const resolvedOnStepEnd = onStepEnd ?? onStepFinish;
	const resolvedOnEnd = onEnd ?? onFinish;
	if (resolvedOnEnd == null && resolvedOnStepEnd == null) return idInjectedStream;
	const state = createStreamingUIMessageState({
		lastMessage: lastMessage ? structuredClone(lastMessage) : void 0,
		messageId: messageId ?? ""
	});
	const runUpdateMessageJob = async (job) => {
		try {
			await job({
				state,
				write: () => {}
			});
		} catch (error) {
			recordProcessingFailure(error);
			throw error;
		}
	};
	let finishCalled = false;
	const callOnEnd = async ({ isCancelled }) => {
		if (finishCalled || !resolvedOnEnd) return;
		finishCalled = true;
		const isContinuation = state.message.id === lastMessage?.id;
		const declaredOutcome = getOutcome?.() ?? { status: "unknown" };
		const outcome = hasProcessingFailure ? {
			status: "failed",
			error: processingError
		} : declaredOutcome.status === "unknown" && isAborted ? { status: "aborted" } : declaredOutcome;
		const isConsumerCancellation = isCancelled && outcome.status === "unknown";
		await resolvedOnEnd({
			isAborted: isAborted || outcome.status === "aborted",
			...isConsumerCancellation ? { isCancelled: true } : {},
			isContinuation,
			outcome,
			responseMessage: state.message,
			messages: [...isContinuation ? originalMessages.slice(0, -1) : originalMessages, state.message],
			finishReason: state.finishReason
		});
	};
	const callOnStepFinish = async () => {
		if (!resolvedOnStepEnd) return;
		const isContinuation = state.message.id === lastMessage?.id;
		try {
			await resolvedOnStepEnd({
				isContinuation,
				responseMessage: structuredClone(state.message),
				messages: [...isContinuation ? originalMessages.slice(0, -1) : originalMessages, structuredClone(state.message)]
			});
		} catch (error) {
			onError(error);
		}
	};
	return processUIMessageStream({
		stream: idInjectedStream,
		runUpdateMessageJob,
		onError
	}).pipeThrough(new TransformStream({
		async transform(chunk, controller) {
			if (chunk.type === "finish-step") await callOnStepFinish();
			controller.enqueue(chunk);
		},
		async cancel() {
			await callOnEnd({ isCancelled: true });
		},
		async flush() {
			await callOnEnd({ isCancelled: false });
		}
	}));
}
//#endregion
//#region src/ui-message-stream/to-ui-message-chunk.ts
/**
* Converts a single `TextStreamPart` (as emitted by `streamText`'s
* `stream`) into a `UIMessageChunk`.
*
* Returns `undefined` for stream parts that do not produce UI message chunks.
*/
function toUIMessageChunk(part, { tools, sendReasoning = true, sendSources = false, sendStart = true, sendFinish = true, onError: onErrorOption, redactToolErrors = onErrorOption != null, messageMetadata, responseMessageId } = {}) {
	const onError = onErrorOption ?? (() => "An error occurred.");
	const getToolErrorText = (error) => redactToolErrors ? onError(error) : getModelToolErrorText(error) ?? onError(error);
	const isDynamic = (toolPart) => {
		const tool = tools?.[toolPart.toolName];
		if (tool == null) return toolPart.dynamic;
		return tool?.type === "dynamic" ? true : void 0;
	};
	const partType = part.type;
	switch (partType) {
		case "text-start": return {
			type: "text-start",
			id: part.id,
			...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
		};
		case "text-delta": return {
			type: "text-delta",
			id: part.id,
			delta: part.text,
			...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
		};
		case "text-end": return {
			type: "text-end",
			id: part.id,
			...part.citations != null ? { citations: part.citations } : {},
			...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
		};
		case "reasoning-start":
		case "reasoning-end":
			if (!sendReasoning) return;
			return {
				type: partType,
				id: part.id,
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
			};
		case "reasoning-delta":
			if (!sendReasoning) return;
			return {
				type: "reasoning-delta",
				id: part.id,
				delta: part.text,
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
			};
		case "file":
		case "reasoning-file":
			if (partType === "reasoning-file" && !sendReasoning) return;
			return {
				type: part.type,
				mediaType: part.file.mediaType,
				url: `data:${part.file.mediaType};base64,${part.file.base64}`,
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
			};
		case "source":
			if (!sendSources) return;
			if (part.sourceType === "url") return {
				type: "source-url",
				sourceId: part.id,
				url: part.url,
				title: part.title,
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
			};
			if (part.sourceType === "document") return {
				type: "source-document",
				sourceId: part.id,
				mediaType: part.mediaType,
				title: part.title,
				filename: part.filename,
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
			};
			return;
		case "custom": return {
			type: "custom",
			kind: part.kind,
			...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
		};
		case "tool-input-start": {
			const dynamic = isDynamic(part);
			return {
				type: "tool-input-start",
				toolCallId: part.id,
				toolName: part.toolName,
				...part.inputEncoding != null ? { inputEncoding: part.inputEncoding } : {},
				...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
				...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
				...dynamic != null ? { dynamic } : {},
				...part.title != null ? { title: part.title } : {}
			};
		}
		case "tool-input-delta": return {
			type: "tool-input-delta",
			toolCallId: part.id,
			inputTextDelta: part.delta
		};
		case "tool-call": {
			const dynamic = isDynamic(part);
			if (part.invalid) return {
				type: "tool-input-error",
				toolCallId: part.toolCallId,
				toolName: part.toolName,
				input: part.input,
				...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
				...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
				...dynamic != null ? { dynamic } : {},
				errorText: part.providerExecuted ? onError(part.error) : getToolErrorText(part.error),
				...part.title != null ? { title: part.title } : {}
			};
			return {
				type: "tool-input-available",
				toolCallId: part.toolCallId,
				toolName: part.toolName,
				input: part.input,
				...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
				...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
				...dynamic != null ? { dynamic } : {},
				...part.title != null ? { title: part.title } : {}
			};
		}
		case "tool-approval-request": {
			const inputSchemaInput = getToolCallInputSchemaInput(part.toolCall);
			return {
				type: "tool-approval-request",
				approvalId: part.approvalId,
				toolCallId: part.toolCall.toolCallId,
				...inputSchemaInput != null && !isDeepEqualData(inputSchemaInput.value, part.toolCall.input) ? { inputSchemaInput: inputSchemaInput.value } : {},
				...part.reason != null ? { reason: part.reason } : {},
				...part.isAutomatic != null ? { isAutomatic: part.isAutomatic } : {},
				...part.signature != null ? { signature: part.signature } : {}
			};
		}
		case "tool-approval-response": return {
			type: "tool-approval-response",
			approvalId: part.approvalId,
			approved: part.approved,
			...part.reason != null ? { reason: part.reason } : {},
			...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {}
		};
		case "tool-result": {
			const dynamic = isDynamic(part);
			return {
				type: "tool-output-available",
				toolCallId: part.toolCallId,
				output: part.output === void 0 ? null : part.output,
				...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
				...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
				...part.preliminary != null ? { preliminary: part.preliminary } : {},
				...dynamic != null ? { dynamic } : {}
			};
		}
		case "tool-error": {
			const dynamic = isDynamic(part);
			return {
				type: "tool-output-error",
				toolCallId: part.toolCallId,
				errorText: part.providerExecuted ? typeof part.error === "string" ? part.error : JSON.stringify(part.error) : getToolErrorText(part.error),
				...part.providerExecuted != null ? { providerExecuted: part.providerExecuted } : {},
				...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {},
				...part.toolMetadata != null ? { toolMetadata: part.toolMetadata } : {},
				...dynamic != null ? { dynamic } : {}
			};
		}
		case "tool-output-denied": return {
			type: "tool-output-denied",
			toolCallId: part.toolCallId
		};
		case "error": return {
			type: "error",
			errorText: onError(part.error)
		};
		case "steering-message": return {
			type: "steering-message",
			id: part.id,
			parts: convertUserMessageToUIParts(part.message)
		};
		case "start-step": return { type: "start-step" };
		case "finish-step": return { type: "finish-step" };
		case "start":
			if (!sendStart) return;
			return {
				type: "start",
				...messageMetadata != null ? { messageMetadata } : {},
				...responseMessageId != null ? { messageId: responseMessageId } : {}
			};
		case "finish":
			if (!sendFinish) return;
			return {
				type: "finish",
				finishReason: part.finishReason,
				...messageMetadata != null ? { messageMetadata } : {}
			};
		case "abort": return part;
		case "tool-input-end":
		case "ping":
		case "raw": return;
		default: throw new Error(`Unknown chunk type: ${partType}`);
	}
}
function convertUserMessageToUIParts(message) {
	if (typeof message.content === "string") return [{
		type: "text",
		text: message.content
	}];
	return message.content.map((part) => {
		const providerMetadata = part.providerOptions != null ? { providerMetadata: part.providerOptions } : {};
		if (part.type === "text") return {
			type: "text",
			text: part.text,
			...providerMetadata
		};
		const { data, mediaType: dataUrlMediaType } = convertToLanguageModelV4FilePart(part.type === "image" ? part.image : part.data);
		const mediaType = dataUrlMediaType ?? part.mediaType ?? "image";
		const filename = part.type === "file" ? part.filename : void 0;
		const file = {
			type: "file",
			mediaType,
			...filename != null ? { filename } : {},
			...providerMetadata
		};
		switch (data.type) {
			case "url": return {
				...file,
				url: data.url.toString()
			};
			case "data": return {
				...file,
				url: `data:${mediaType};base64,${convertDataContentToBase64String(data.data)}`
			};
			case "text": return {
				...file,
				url: `data:${mediaType};base64,${convertUint8ArrayToBase64(new TextEncoder().encode(data.text))}`
			};
			case "reference": return {
				...file,
				url: "",
				providerReference: data.reference
			};
		}
	});
}
//#endregion
//#region src/ui-message-stream/to-ui-message-stream.ts
/**
* Converts a stream of `TextStreamPart<TOOLS>` chunks (as emitted by
* `streamText`'s `stream`) into a stream of `UIMessageChunk`s suitable for
* UI message streaming, including response message ID injection and
* step and stream end callbacks.
*/
function toUIMessageStream({ stream, tools, sendReasoning = true, sendSources = false, sendStart = true, sendFinish = true, onError, redactToolErrors, messageMetadata, originalMessages, generateMessageId, onStepEnd, onStepFinish, onEnd, onFinish }) {
	let outcome = { status: "unknown" };
	let hasFatalFailure = false;
	const invalidToolCallIds = /* @__PURE__ */ new Set();
	let mismatchedToolCallIdInCurrentStep;
	let mismatchedToolCallIdInEarlierStep;
	let hasWarnedAboutToolErrorMismatch = false;
	const setSourceOutcome = (newOutcome) => {
		if (!hasFatalFailure && outcome.status !== "completed" && outcome.status !== "aborted" && newOutcome.status !== "unknown" && (outcome.status === "unknown" || newOutcome.status !== "failed")) outcome = newOutcome;
	};
	const failOutcome = (error) => {
		hasFatalFailure = true;
		outcome = {
			status: "failed",
			error
		};
	};
	const responseMessageId = generateMessageId != null ? getResponseUIMessageId({
		originalMessages,
		responseMessageId: generateMessageId
	}) : void 0;
	const sourceReader = stream.getReader();
	let sourceReaderReleased = false;
	let sourceStreamCancelled = false;
	const releaseSourceReader = () => {
		if (!sourceReaderReleased) {
			sourceReader.releaseLock();
			sourceReaderReleased = true;
		}
	};
	return handleUIMessageStreamFinish({
		stream: new ReadableStream({
			async pull(controller) {
				try {
					const { done, value } = await sourceReader.read();
					if (done) {
						releaseSourceReader();
						if (!sourceStreamCancelled) controller.close();
					} else controller.enqueue(value);
				} catch (error) {
					releaseSourceReader();
					if (!sourceStreamCancelled) {
						failOutcome(error);
						controller.error(error);
					}
				}
			},
			async cancel(reason) {
				sourceStreamCancelled = true;
				if (sourceReaderReleased) return;
				try {
					await sourceReader.cancel(reason);
				} finally {
					releaseSourceReader();
				}
			}
		}).pipeThrough(new TransformStream({ transform: async (part, controller) => {
			try {
				if (part.type === "tool-call" && part.invalid) invalidToolCallIds.add(part.toolCallId);
				const isInvalidToolCallError = part.type === "tool-error" && !part.providerExecuted && invalidToolCallIds.delete(part.toolCallId);
				const messageMetadataValue = messageMetadata?.({ part });
				const uiMessageChunk = isInvalidToolCallError ? void 0 : toUIMessageChunk(part, {
					tools,
					sendReasoning,
					sendSources,
					sendStart,
					sendFinish,
					onError,
					redactToolErrors,
					messageMetadata: messageMetadataValue,
					responseMessageId
				});
				if (part.type === "start-step") {
					mismatchedToolCallIdInEarlierStep ??= mismatchedToolCallIdInCurrentStep;
					mismatchedToolCallIdInCurrentStep = void 0;
				} else if ((part.type === "tool-error" || part.type === "tool-call") && !part.providerExecuted && (uiMessageChunk?.type === "tool-output-error" || uiMessageChunk?.type === "tool-input-error")) {
					const { errorText } = uiMessageChunk;
					const modelErrorText = getModelToolErrorText(part.error);
					if (modelErrorText != null && errorText !== modelErrorText) mismatchedToolCallIdInCurrentStep ??= part.toolCallId;
				} else if (uiMessageChunk?.type === "reasoning-start" && mismatchedToolCallIdInEarlierStep != null && !hasWarnedAboutToolErrorMismatch) {
					hasWarnedAboutToolErrorMismatch = true;
					logWarnings({ warnings: [{
						type: "other",
						message: `The error text sent to the UI for tool call "${mismatchedToolCallIdInEarlierStep}" differs from the error text the model received, and reasoning from a later step was sent to the UI. Converting these UI messages back to model messages changes the tool result. Models that bind reasoning to the preceding messages (for example Anthropic models with preserved thinking) reject that history. See https://ai-sdk.dev/docs/ai-sdk-ui/chatbot-tool-usage#tool-error-text-and-message-history`
					}] });
				}
				if (uiMessageChunk != null && part.type !== "finish-step") controller.enqueue(uiMessageChunk);
				if (messageMetadataValue != null && part.type !== "start" && part.type !== "finish") controller.enqueue({
					type: "message-metadata",
					messageMetadata: messageMetadataValue
				});
				if (uiMessageChunk != null && part.type === "finish-step") controller.enqueue(uiMessageChunk);
				if (part.type === "finish") setSourceOutcome({ status: "completed" });
				else if (part.type === "abort") setSourceOutcome({ status: "aborted" });
				else if (part.type === "error") setSourceOutcome({
					status: "failed",
					error: part.error
				});
			} catch (error) {
				failOutcome(error);
				throw error;
			}
		} })),
		messageId: responseMessageId ?? generateMessageId?.(),
		originalMessages,
		onStepEnd: onStepEnd ?? onStepFinish,
		onEnd: onEnd ?? onFinish,
		onError: onError ?? (() => "An error occurred."),
		getOutcome: () => outcome
	});
}
//#endregion
//#region src/util/async-iterable-stream.ts
/**
* Wraps a ReadableStream and returns an object that is both a ReadableStream and an AsyncIterable.
* This enables consumption of the stream using for-await-of, with proper resource cleanup on early exit or error.
*
* @template T The type of the stream's chunks.
* @param source The source ReadableStream to wrap.
* @returns An AsyncIterableStream that can be used as both a ReadableStream and an AsyncIterable.
*/
function createAsyncIterableStream(source) {
	return asAsyncIterableStream(source.pipeThrough(new TransformStream()));
}
/**
* Attaches the async iterator protocol to an existing ReadableStream in place,
* turning it into an AsyncIterableStream without piping through an additional
* TransformStream.
*
* Use this when the stream is already known to be fresh and exclusively owned
* (e.g. the readable side of a TransformStream created for this consumer).
* Adding an extra `pipeThrough` in that situation creates a chain of two
* transforms fed by an active upstream pipe, which can surface a spurious
* unhandled `undefined` rejection when the consumer cancels early (observed on
* Node.js 26). {@link createAsyncIterableStream} wraps this after adding a
* fresh transform for callers that may pass shared or locked streams.
*
* @template T The type of the stream's chunks.
* @param stream The ReadableStream to augment. It must be fresh and unlocked.
* @returns The same stream, augmented with the async iterator protocol.
*/
function asAsyncIterableStream(stream) {
	/**
	* Implements the async iterator protocol for the stream.
	* Ensures proper cleanup (cancelling and releasing the reader) on completion, early exit, or error.
	*/
	stream[Symbol.asyncIterator] = function() {
		const reader = this.getReader();
		let finished = false;
		/**
		* Cleans up the reader by cancelling and releasing the lock.
		*/
		async function cleanup(cancelStream) {
			if (finished) return;
			finished = true;
			try {
				if (cancelStream) await reader.cancel?.();
			} finally {
				try {
					reader.releaseLock();
				} catch {}
			}
		}
		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
				};
				let result;
				try {
					result = await reader.read();
				} catch (error) {
					await cleanup(false);
					throw error;
				}
				const { done, value } = result;
				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;
}
//#endregion
//#region src/util/consume-stream.ts
/**
* Consumes a ReadableStream until it's fully read.
*
* This function reads the stream chunk by chunk until the stream is exhausted.
* It doesn't process or return the data from the stream; it simply ensures
* that the entire stream is read.
*
* @param options - The options for consuming the stream.
* @param options.stream - The ReadableStream to be consumed.
* @param options.onError - Optional callback to handle errors that occur during consumption.
* @returns A promise that resolves when the stream is fully consumed.
*/
async function consumeStream({ stream, onError, abortSignal }) {
	const reader = stream.getReader();
	const cancelOnAbort = () => {
		reader.cancel().catch(() => {});
	};
	if (abortSignal?.aborted) cancelOnAbort();
	else abortSignal?.addEventListener("abort", cancelOnAbort, { once: true });
	try {
		while (true) {
			const { done } = await reader.read();
			if (done) break;
		}
	} catch (error) {
		onError?.(error);
	} finally {
		abortSignal?.removeEventListener("abort", cancelOnAbort);
		reader.releaseLock();
	}
}
//#endregion
//#region src/util/create-resolvable-promise.ts
/**
* Creates a Promise with externally accessible resolve and reject functions.
*
* @template T - The type of the value that the Promise will resolve to.
* @returns An object containing:
*   - promise: A Promise that can be resolved or rejected externally.
*   - resolve: A function to resolve the Promise with a value of type T.
*   - reject: A function to reject the Promise with an error.
*/
function createResolvablePromise() {
	let resolve;
	let reject;
	return {
		promise: new Promise((res, rej) => {
			resolve = res;
			reject = rej;
		}),
		resolve,
		reject
	};
}
//#endregion
//#region src/util/create-stitchable-stream.ts
/**
* Creates a stitchable stream that can pipe one stream at a time.
*
* @template T - The type of values emitted by the streams.
* @returns {Object} An object containing the stitchable stream and control methods.
*/
function createStitchableStream() {
	let innerStreams = [];
	let controller = null;
	let isClosed = false;
	let isCancelled = false;
	let waitForNewStream = createResolvablePromise();
	const terminate = () => {
		if (isCancelled) return;
		isClosed = true;
		waitForNewStream.resolve();
		innerStreams.forEach(({ reader, onCancel }) => {
			onCancel?.();
			reader.cancel();
		});
		innerStreams = [];
		controller?.close();
	};
	const processPull = async () => {
		if (isCancelled) return;
		if (isClosed && innerStreams.length === 0) {
			controller?.close();
			return;
		}
		if (innerStreams.length === 0) {
			waitForNewStream = createResolvablePromise();
			await waitForNewStream.promise;
			return await processPull();
		}
		const currentStream = innerStreams[0];
		try {
			const { value, done } = await currentStream.reader.read();
			if (isCancelled) return;
			if (done) {
				innerStreams.shift();
				if (innerStreams.length === 0 && isClosed) controller?.close();
				else await processPull();
			} else controller?.enqueue(value);
		} catch (error) {
			if (isCancelled) return;
			currentStream.onError?.(error);
			controller?.error(error);
			innerStreams.shift();
			terminate();
		}
	};
	return {
		stream: new ReadableStream({
			start(controllerParam) {
				controller = controllerParam;
			},
			pull: processPull,
			async cancel() {
				isCancelled = true;
				isClosed = true;
				waitForNewStream.resolve();
				for (const { reader, onCancel } of innerStreams) {
					onCancel?.();
					await reader.cancel();
				}
				innerStreams = [];
			}
		}),
		addStream: (innerStream, callbacks) => {
			if (isCancelled) {
				callbacks?.onCancel?.();
				innerStream.cancel().catch(() => {});
				return;
			}
			if (isClosed) throw new Error("Cannot add inner stream: outer stream is closed");
			innerStreams.push({
				reader: innerStream.getReader(),
				...callbacks
			});
			waitForNewStream.resolve();
		},
		/**
		* Gracefully close the outer stream. This will let the inner streams
		* finish processing and then close the outer stream.
		*/
		close: () => {
			if (isCancelled) return;
			isClosed = true;
			waitForNewStream.resolve();
			if (innerStreams.length === 0) controller?.close();
		},
		/**
		* Immediately close the outer stream. This will cancel all inner streams
		* and close the outer stream.
		*/
		terminate
	};
}
//#endregion
//#region src/generate-text/stream-retry-attempt-boundary.ts
const streamRetryAttemptBoundarySymbol = Symbol("streamRetryAttemptBoundary");
function createStreamRetryAttemptBoundaryPart({ warnings }) {
	return {
		[streamRetryAttemptBoundarySymbol]: true,
		warnings
	};
}
function isStreamRetryAttemptBoundaryPart(part) {
	return typeof part === "object" && part != null && streamRetryAttemptBoundarySymbol in part;
}
//#endregion
//#region src/generate-text/execute-tools-from-stream.ts
function executeToolsFromStream({ stream, tools, callId, messages, abortSignal, timeout, experimental_sandbox: sandbox, toolsContext, toolApproval, runtimeContext, toolApprovalSecret, generateId, onToolExecutionStart, onToolExecutionEnd, executeToolInTelemetryContext, runInTracingChannelSpan, toolCallConcurrency }) {
	const toolCallsToExecute = [];
	return stream.pipeThrough(new TransformStream({ async transform(chunk, controller) {
		controller.enqueue(chunk);
		if (isStreamRetryAttemptBoundaryPart(chunk)) {
			toolCallsToExecute.length = 0;
			return;
		}
		switch (chunk.type) {
			case "tool-call": {
				if (chunk.invalid) return;
				const tool = getOwn(tools, chunk.toolName);
				if (tool == null) return;
				const toolApprovalStatus = await resolveToolApproval({
					tools,
					toolCall: chunk,
					toolApproval,
					messages,
					toolsContext,
					runtimeContext
				});
				if (toolApprovalStatus.type === "not-applicable") {
					if (tool.execute != null && chunk.providerExecuted !== true) toolCallsToExecute.push(chunk);
					return;
				}
				const approvalId = generateId();
				const signature = await maybeSignApproval({
					secret: toolApprovalSecret,
					approvalId,
					toolCallId: chunk.toolCallId,
					toolName: chunk.toolName,
					input: chunk.input
				});
				switch (toolApprovalStatus.type) {
					case "user-approval":
						controller.enqueue({
							type: "tool-approval-request",
							approvalId,
							toolCall: chunk,
							...toolApprovalStatus.reason != null ? { reason: toolApprovalStatus.reason } : {},
							...signature != null ? { signature } : {}
						});
						return;
					case "denied":
						controller.enqueue({
							type: "tool-approval-request",
							approvalId,
							toolCall: chunk,
							isAutomatic: true,
							...signature != null ? { signature } : {}
						});
						controller.enqueue({
							type: "tool-approval-response",
							approvalId,
							approved: false,
							toolCall: chunk,
							reason: toolApprovalStatus.reason,
							providerExecuted: chunk.providerExecuted
						});
						controller.enqueue({
							type: "tool-output-denied",
							toolCallId: chunk.toolCallId,
							toolName: chunk.toolName
						});
						return;
					case "approved":
						controller.enqueue({
							type: "tool-approval-request",
							approvalId,
							toolCall: chunk,
							isAutomatic: true,
							...signature != null ? { signature } : {}
						});
						controller.enqueue({
							type: "tool-approval-response",
							approvalId,
							approved: true,
							toolCall: chunk,
							reason: toolApprovalStatus.reason,
							providerExecuted: chunk.providerExecuted
						});
				}
				if (tool.execute != null && chunk.providerExecuted !== true) toolCallsToExecute.push(chunk);
				return;
			}
			case "model-call-end":
				if (!isToolExecutionAllowedFinishReason(chunk.finishReason)) return;
				await mapWithConcurrency({
					items: toolCallsToExecute,
					concurrency: toolCallConcurrency,
					abortSignal,
					execute: async (toolCall) => {
						try {
							const result = await executeToolCall({
								toolCall,
								tools,
								callId,
								messages,
								abortSignal,
								timeout,
								experimental_sandbox: sandbox,
								toolsContext,
								onToolExecutionStart,
								onToolExecutionEnd,
								executeToolInTelemetryContext,
								runInTracingChannelSpan,
								onPreliminaryToolResult: (result) => {
									controller.enqueue(result);
								}
							});
							if (result != null) {
								controller.enqueue({
									type: "tool-execution-end",
									toolCallId: result.output.toolCallId,
									toolExecutionMs: result.toolExecutionMs
								});
								controller.enqueue(result.output);
							}
						} catch (error) {
							controller.enqueue({
								type: "error",
								error
							});
						}
					}
				});
		}
	} }));
}
//#endregion
//#region src/generate-text/is-output-chunk.ts
const isOutputChunkType = {
	file: true,
	custom: false,
	source: false,
	"text-start": false,
	"text-end": false,
	"text-delta": true,
	"reasoning-start": false,
	"reasoning-end": false,
	"reasoning-delta": true,
	"reasoning-file": true,
	"tool-input-start": false,
	"tool-input-end": false,
	"tool-input-delta": true,
	"tool-approval-request": false,
	"tool-approval-response": false,
	"tool-call": true,
	"tool-result": false,
	"tool-error": false,
	"tool-output-denied": false,
	"tool-execution-end": false,
	"model-call-start": false,
	"model-call-response-metadata": false,
	"model-call-end": false,
	error: false,
	ping: false,
	raw: false
};
function isOutputChunk$1(chunk) {
	if (!isOutputChunkType[chunk.type]) return false;
	switch (chunk.type) {
		case "text-delta":
		case "reasoning-delta": return chunk.text.length > 0;
		case "tool-input-delta": return chunk.delta.length > 0;
		case "file":
		case "reasoning-file":
		case "tool-call": return true;
		default: return false;
	}
}
//#endregion
//#region src/generate-text/invoke-tool-callbacks-from-stream.ts
function invokeToolCallbacksFromStream({ stream, tools, stepInputMessages, abortSignal, toolsContext }) {
	if (tools == null) return stream;
	let ongoingToolCalls = createIdMap();
	const getValidatedContext = ({ toolCallId, toolName }) => {
		const ongoingToolCall = ongoingToolCalls[toolCallId];
		const validatedContext = ongoingToolCall?.validatedContexts[toolName];
		if (validatedContext != null) return validatedContext;
		const tool = getOwn(tools, toolName);
		const newValidatedContext = validateToolContext({
			toolName,
			context: getOwn(toolsContext, toolName),
			contextSchema: tool?.contextSchema
		});
		if (ongoingToolCall != null) ongoingToolCall.validatedContexts[toolName] = newValidatedContext;
		return newValidatedContext;
	};
	return stream.pipeThrough(new TransformStream({ async transform(chunk, controller) {
		controller.enqueue(chunk);
		if (isStreamRetryAttemptBoundaryPart(chunk)) {
			ongoingToolCalls = createIdMap();
			return;
		}
		switch (chunk.type) {
			case "tool-input-start": {
				ongoingToolCalls[chunk.id] = {
					toolName: chunk.toolName,
					validatedContexts: createIdMap()
				};
				const tool = getOwn(tools, chunk.toolName);
				if (tool?.onInputStart != null) await tool.onInputStart({
					toolCallId: chunk.id,
					messages: stepInputMessages,
					abortSignal,
					context: await getValidatedContext({
						toolCallId: chunk.id,
						toolName: chunk.toolName
					})
				});
				break;
			}
			case "tool-input-delta": {
				const toolName = ongoingToolCalls[chunk.id]?.toolName;
				const tool = getOwn(tools, toolName);
				if (tool?.onInputDelta != null) await tool.onInputDelta({
					inputTextDelta: chunk.delta,
					toolCallId: chunk.id,
					messages: stepInputMessages,
					abortSignal,
					context: await getValidatedContext({
						toolCallId: chunk.id,
						toolName
					})
				});
				break;
			}
			case "tool-call": {
				const toolName = chunk.toolName;
				const tool = getOwn(tools, toolName);
				if (!chunk.invalid && tool?.onInputAvailable != null) {
					const validatedContext = getValidatedContext({
						toolCallId: chunk.toolCallId,
						toolName
					});
					delete ongoingToolCalls[chunk.toolCallId];
					await tool.onInputAvailable({
						input: chunk.input,
						toolCallId: chunk.toolCallId,
						messages: stepInputMessages,
						abortSignal,
						context: await validatedContext
					});
				} else delete ongoingToolCalls[chunk.toolCallId];
			}
		}
	} }));
}
//#endregion
//#region src/generate-text/stream-text-single-consumer-result.ts
/** Expose only the stream and completion metadata for a single consumer. */
function createSingleConsumerStreamTextResult(result) {
	return {
		get textStream() {
			return result.textStream;
		},
		get stream() {
			return result.stream;
		},
		get fullStream() {
			return result.fullStream;
		},
		get partialOutputStream() {
			return result.partialOutputStream;
		},
		get elementStream() {
			return result.elementStream;
		},
		get totalUsage() {
			return result.totalUsage;
		},
		get usage() {
			return result.usage;
		},
		get finishReason() {
			return result.finishReason;
		},
		get rawFinishReason() {
			return result.rawFinishReason;
		},
		consumeStream: result.consumeStream.bind(result),
		toUIMessageStream: result.toUIMessageStream.bind(result),
		toUIMessageStreamResponse: result.toUIMessageStreamResponse.bind(result),
		toTextStreamResponse: result.toTextStreamResponse.bind(result),
		pipeUIMessageStreamToResponse: result.pipeUIMessageStreamToResponse.bind(result),
		pipeTextStreamToResponse: result.pipeTextStreamToResponse.bind(result)
	};
}
//#endregion
//#region src/prompt/normalize-stream-provider-error.ts
/**
* Normalizes well-formed provider error payloads without changing existing
* Error instances or malformed/unknown values.
*/
function normalizeStreamProviderError(error) {
	if (isError(error) || AISDKError$1.isInstance(error) || StreamProviderError.isInstance(error)) return error;
	const outer = asRecord(error);
	if (outer == null) return error;
	const providerStreamError = isProviderStreamError(error);
	const details = providerStreamError ? outer : asRecord(asRecord(outer.response)?.error) ?? asRecord(outer.error) ?? outer;
	if (typeof details.message !== "string") return error;
	const type = getString(details.type) ?? getString(outer.type);
	const code = getStringOrNumber(details.code) ?? getStringOrNumber(outer.code);
	const explicitStatusCode = getHttpStatusCode(details.statusCode) ?? getHttpStatusCode(outer.statusCode) ?? getHttpStatusCode(details.status_code) ?? getHttpStatusCode(outer.status_code) ?? getHttpStatusCode(details.status) ?? getHttpStatusCode(outer.status) ?? getHttpStatusCode(details.code) ?? getHttpStatusCode(outer.code);
	const messageMetadata = inferExactMessageMetadata(details.message);
	const statusCode = explicitStatusCode ?? messageMetadata?.statusCode;
	const explicitRetryability = getBoolean(details.isRetryable) ?? getBoolean(outer.isRetryable) ?? getBoolean(details.is_retryable) ?? getBoolean(outer.is_retryable);
	return new StreamProviderError({
		message: details.message,
		type,
		code,
		statusCode,
		isRetryable: explicitRetryability ?? messageMetadata?.isRetryable ?? isRetryableStatusCode(statusCode),
		data: providerStreamError ? error.data : error
	});
}
function inferExactMessageMetadata(message) {
	switch (message.trim().toLowerCase()) {
		case "overloaded":
		case "overloaded error":
		case "model overloaded": return {
			statusCode: 503,
			isRetryable: true
		};
		case "internal server error": return {
			statusCode: 500,
			isRetryable: true
		};
		case "service unavailable": return {
			statusCode: 503,
			isRetryable: true
		};
		default: return;
	}
}
function isRetryableStatusCode(statusCode) {
	return statusCode != null && (statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500);
}
function asRecord(value) {
	return typeof value === "object" && value != null ? value : void 0;
}
function isError(value) {
	return value instanceof Error || Object.prototype.toString.call(value) === "[object Error]";
}
function getString(value) {
	return typeof value === "string" ? value : void 0;
}
function getStringOrNumber(value) {
	return typeof value === "string" || typeof value === "number" ? value : void 0;
}
function getBoolean(value) {
	return typeof value === "boolean" ? value : void 0;
}
function getHttpStatusCode(value) {
	const statusCode = typeof value === "string" && /^\d{3}$/.test(value) ? Number(value) : value;
	return typeof statusCode === "number" && Number.isInteger(statusCode) && statusCode >= 400 && statusCode <= 599 ? statusCode : void 0;
}
//#endregion
//#region src/generate-text/stream-language-model-call.ts
const originalGenerateId$3 = createIdGenerator$1({
	prefix: "aitxt",
	size: 24
});
const originalGenerateCallId$8 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Streams a single language model call after standardizing the prompt and tools.
*
* The returned stream emits model call parts together with request and response
* metadata when available.
*
* @param model - The language model to use.
* @param tools - Tools that are accessible to and can be called by the model. The model needs to support calling tools.
* @param output - Output configuration that controls the response format requested from the model.
* @param toolChoice - The tool choice strategy for the model call.
*
* @param system - A system message that will be part of the prompt.
* @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
* @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
* @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. Default: false.
*
* @param maxOutputTokens - Maximum number of tokens to generate.
* @param temperature - Temperature setting.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topP - Nucleus sampling.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topK - Only sample from the top K options for each subsequent token.
* Used to remove "long tail" low probability responses.
* Recommended for advanced use cases only. You usually only need to use temperature.
* @param presencePenalty - Presence penalty setting.
* It affects the likelihood of the model to repeat information that is already in the prompt.
* The value is passed through to the provider. The range depends on the provider and model.
* @param frequencyPenalty - Frequency penalty setting.
* It affects the likelihood of the model to repeatedly use the same words or phrases.
* The value is passed through to the provider. The range depends on the provider and model.
* @param stopSequences - Stop sequences.
* If set, the model will stop generating text when one of the stop sequences is generated.
* @param seed - The seed (integer) to use for random sampling.
* If set and supported by the model, calls will generate deterministic results.
* @param reasoning - Reasoning configuration for the model call.
*
* @param download - A function that downloads URLs as part of prompt conversion and generated file URLs.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request.
* @param includeRawChunks - Whether to include raw provider stream chunks in the model stream.
* @param providerOptions - Additional provider-specific options.
* @param repairToolCall - A function that can repair invalid tool calls before they are emitted.
* @param refineToolInput - Optional mapping of tool names to functions that refine parsed tool inputs before they are emitted, used for telemetry, or executed.
* @param onStart - A callback that receives the fully converted prompt before the model call starts.
*
* @returns A stream of model call parts together with request and response metadata when available.
*/
async function streamLanguageModelCall({ model, tools, toolOrder, output, toolChoice, prompt, system, instructions, messages, allowSystemInMessages, download, abortSignal, headers, includeRawChunks, providerOptions, repairToolCall, refineToolInput, executeLanguageModelCallInTelemetryContext = async ({ execute }) => await execute(), callId, toolsContext, experimental_sandbox: sandbox, _internal: { generateId = originalGenerateId$3, generateCallId = originalGenerateCallId$8, now: now$3 = now, collectContent = true } = {}, onStart, onLanguageModelCallStart, onLanguageModelCallEnd, ...callSettings }) {
	const resolvedModel = resolveLanguageModel(model);
	const effectiveCallId = callId ?? generateCallId();
	const standardizedPrompt = await standardizePrompt({
		instructions,
		system,
		prompt,
		messages,
		allowSystemInMessages
	});
	const promptMessages = await convertToLanguageModelPrompt({
		prompt: {
			instructions: standardizedPrompt.instructions,
			messages: standardizedPrompt.messages
		},
		supportedUrls: await resolvedModel.supportedUrls,
		download,
		abortSignal,
		provider: resolvedModel.provider.split(".")[0]
	});
	const stepTools = await prepareTools({
		tools,
		toolOrder,
		toolsContext,
		experimental_sandbox: sandbox
	});
	const stepToolChoice = prepareToolChoice({ toolChoice });
	await notify({
		event: { promptMessages },
		callbacks: onStart
	});
	const languageModelCallStartEvent = {
		callId: effectiveCallId,
		provider: resolvedModel.provider,
		modelId: resolvedModel.modelId,
		instructions: standardizedPrompt.instructions,
		messages: standardizedPrompt.messages,
		tools: stepTools,
		...callSettings
	};
	await notify({
		event: languageModelCallStartEvent,
		callbacks: onLanguageModelCallStart
	});
	const callStartTimestampMs = now$3();
	const { stream: languageModelStream, response, request } = await executeLanguageModelCallInTelemetryContext({
		...languageModelCallStartEvent,
		execute: async () => {
			const result = await resolvedModel.doStream({
				...callSettings,
				tools: stepTools,
				toolChoice: stepToolChoice,
				responseFormat: await output?.responseFormat,
				prompt: promptMessages,
				providerOptions,
				abortSignal,
				headers,
				includeRawChunks
			});
			return {
				...result,
				...result.request && { request: sanitizeRequestMetadata(result.request) }
			};
		}
	});
	return {
		stream: createAsyncIterableStream(languageModelStream.pipeThrough(createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({
			tools,
			instructions: standardizedPrompt.instructions,
			messages: standardizedPrompt.messages,
			repairToolCall,
			refineToolInput,
			download,
			abortSignal,
			callId: effectiveCallId,
			provider: resolvedModel.provider,
			modelId: resolvedModel.modelId,
			toolChoice: stepToolChoice,
			generateId,
			now: now$3,
			callStartTimestampMs,
			request,
			onLanguageModelCallEnd,
			collectContent
		}))),
		response,
		request
	};
}
function createLanguageModelV4StreamPartToLanguageModelStreamPartTransform({ tools, instructions, messages, repairToolCall, refineToolInput, download, abortSignal, callId, provider, modelId, toolChoice, generateId, now, callStartTimestampMs, request, onLanguageModelCallEnd, collectContent }) {
	const toolCallsByToolCallId = /* @__PURE__ */ new Map();
	const modelCallContent = [];
	const rawModelCallContent = [];
	const textPartIndexes = /* @__PURE__ */ new Map();
	const reasoningPartIndexes = /* @__PURE__ */ new Map();
	const rawTextPartIndexes = /* @__PURE__ */ new Map();
	const rawReasoningPartIndexes = /* @__PURE__ */ new Map();
	let responseId = generateId();
	let responseModelId = modelId;
	let timeToFirstOutputMs;
	let previousOutputChunkTimestampMs;
	const timeBetweenOutputChunksMs = [];
	const withholdToolParts = toolChoice.type === "none";
	return new TransformStream({ async transform(chunk, controller) {
		if (isOutputChunk(chunk)) {
			const outputChunkTimestampMs = now();
			if (timeToFirstOutputMs == null) timeToFirstOutputMs = outputChunkTimestampMs - callStartTimestampMs;
			else if (previousOutputChunkTimestampMs != null) timeBetweenOutputChunksMs.push(outputChunkTimestampMs - previousOutputChunkTimestampMs);
			previousOutputChunkTimestampMs = outputChunkTimestampMs;
		}
		if (withholdToolParts && (chunk.type === "tool-input-start" || chunk.type === "tool-input-delta" || chunk.type === "tool-input-end")) return;
		switch (chunk.type) {
			case "error":
				controller.enqueue({
					type: "error",
					error: normalizeStreamProviderError(chunk.error)
				});
				break;
			case "text-start":
				upsertTextContentPart({
					enabled: collectContent,
					content: modelCallContent,
					rawContent: rawModelCallContent,
					partIndexes: textPartIndexes,
					rawPartIndexes: rawTextPartIndexes,
					id: chunk.id,
					type: "text",
					providerMetadata: chunk.providerMetadata
				});
				controller.enqueue(chunk);
				break;
			case "text-delta":
				upsertTextContentPart({
					enabled: collectContent,
					content: modelCallContent,
					rawContent: rawModelCallContent,
					partIndexes: textPartIndexes,
					rawPartIndexes: rawTextPartIndexes,
					id: chunk.id,
					type: "text",
					textDelta: chunk.delta,
					providerMetadata: chunk.providerMetadata
				});
				controller.enqueue({
					type: "text-delta",
					id: chunk.id,
					text: chunk.delta,
					providerMetadata: chunk.providerMetadata
				});
				break;
			case "text-end":
				upsertTextContentPart({
					enabled: collectContent,
					content: modelCallContent,
					rawContent: rawModelCallContent,
					partIndexes: textPartIndexes,
					rawPartIndexes: rawTextPartIndexes,
					id: chunk.id,
					type: "text",
					providerMetadata: chunk.providerMetadata
				});
				textPartIndexes.delete(chunk.id);
				rawTextPartIndexes.delete(chunk.id);
				controller.enqueue(chunk);
				break;
			case "reasoning-start":
				upsertTextContentPart({
					enabled: collectContent,
					content: modelCallContent,
					rawContent: rawModelCallContent,
					partIndexes: reasoningPartIndexes,
					rawPartIndexes: rawReasoningPartIndexes,
					id: chunk.id,
					type: "reasoning",
					providerMetadata: chunk.providerMetadata
				});
				controller.enqueue(chunk);
				break;
			case "reasoning-delta":
				upsertTextContentPart({
					enabled: collectContent,
					content: modelCallContent,
					rawContent: rawModelCallContent,
					partIndexes: reasoningPartIndexes,
					rawPartIndexes: rawReasoningPartIndexes,
					id: chunk.id,
					type: "reasoning",
					textDelta: chunk.delta,
					providerMetadata: chunk.providerMetadata
				});
				controller.enqueue({
					type: "reasoning-delta",
					id: chunk.id,
					text: chunk.delta,
					providerMetadata: chunk.providerMetadata
				});
				break;
			case "reasoning-end":
				upsertTextContentPart({
					enabled: collectContent,
					content: modelCallContent,
					rawContent: rawModelCallContent,
					partIndexes: reasoningPartIndexes,
					rawPartIndexes: rawReasoningPartIndexes,
					id: chunk.id,
					type: "reasoning",
					providerMetadata: chunk.providerMetadata
				});
				reasoningPartIndexes.delete(chunk.id);
				rawReasoningPartIndexes.delete(chunk.id);
				controller.enqueue(chunk);
				break;
			case "file":
			case "reasoning-file": {
				const file = new DefaultGeneratedFileWithType({
					data: await resolveGeneratedFileData({
						data: chunk.data,
						download,
						abortSignal
					}),
					mediaType: chunk.mediaType
				});
				if (collectContent) modelCallContent.push({
					type: chunk.type,
					file,
					...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {}
				});
				if (collectContent) rawModelCallContent.push(chunk);
				controller.enqueue({
					type: chunk.type,
					file,
					providerMetadata: chunk.providerMetadata
				});
				break;
			}
			case "finish": {
				const usage = asLanguageModelUsage(chunk.usage);
				const responseTimeMs = now() - callStartTimestampMs;
				const performance = {
					responseTimeMs,
					effectiveOutputTokensPerSecond: calculateTokensPerSecond({
						tokens: usage.outputTokens,
						durationMs: responseTimeMs
					}),
					outputTokensPerSecond: timeToFirstOutputMs == null ? void 0 : calculateTokensPerSecond({
						tokens: usage.outputTokens,
						durationMs: responseTimeMs - timeToFirstOutputMs
					}),
					inputTokensPerSecond: timeToFirstOutputMs == null ? void 0 : calculateTokensPerSecond({
						tokens: usage.inputTokens,
						durationMs: timeToFirstOutputMs
					}),
					effectiveTotalTokensPerSecond: calculateTokensPerSecond({
						tokens: sumTokenCounts(usage.inputTokens, usage.outputTokens),
						durationMs: responseTimeMs
					}),
					timeToFirstOutputMs,
					timeBetweenOutputChunksMs: timeBetweenOutputChunksMs.length > 0 ? calculateOutputChunkTimingStats(timeBetweenOutputChunksMs) : void 0
				};
				await notify({
					event: {
						callId,
						provider,
						modelId: responseModelId,
						finishReason: chunk.finishReason.unified,
						usage,
						content: modelCallContent,
						responseId,
						...request?.url != null ? { request: { url: getRequestOrigin(request.url) } } : {},
						...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
						performance
					},
					callbacks: onLanguageModelCallEnd
				});
				const enforcedToolChoice = toolChoice.type === "auto" ? void 0 : toolChoice;
				const toolChoiceViolationError = enforcedToolChoice != null && (enforcedToolChoice.type === "none" ? toolCallsByToolCallId.size > 0 : chunk.finishReason.unified !== "interrupted" && ![...toolCallsByToolCallId.values()].some((toolCall) => enforcedToolChoice.type === "required" || toolCall.toolName === enforcedToolChoice.toolName)) ? new ToolChoiceViolationError({
					toolChoice: enforcedToolChoice,
					finishReason: chunk.finishReason.unified,
					provider,
					modelId,
					content: rawModelCallContent
				}) : void 0;
				controller.enqueue({
					type: "model-call-end",
					finishReason: toolChoiceViolationError == null ? chunk.finishReason.unified : "error",
					rawFinishReason: chunk.finishReason.raw,
					usage,
					providerMetadata: chunk.providerMetadata,
					performance
				});
				if (toolChoiceViolationError != null) {
					controller.enqueue({
						type: "error",
						error: toolChoiceViolationError
					});
					break;
				}
				break;
			}
			case "tool-call":
				if (collectContent) rawModelCallContent.push(chunk);
				try {
					const toolCall = await parseToolCall({
						toolCall: chunk,
						tools,
						repairToolCall: withholdToolParts ? void 0 : repairToolCall,
						refineToolInput: withholdToolParts ? void 0 : refineToolInput,
						instructions,
						messages,
						abortSignal
					});
					toolCallsByToolCallId.set(toolCall.toolCallId, toolCall);
					if (collectContent) modelCallContent.push(toolCall);
					if (withholdToolParts) break;
					controller.enqueue(toolCall);
					if (toolCall.invalid) {
						if (!toolCall.providerExecuted) controller.enqueue({
							type: "tool-error",
							toolCallId: toolCall.toolCallId,
							toolName: toolCall.toolName,
							input: toolCall.input,
							error: getErrorMessage$1(toolCall.error),
							dynamic: true,
							title: toolCall.title,
							...toolCall.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
						});
						break;
					}
				} catch (error) {
					controller.enqueue({
						type: "error",
						error
					});
				}
				break;
			case "tool-approval-request": {
				if (collectContent) rawModelCallContent.push(chunk);
				if (withholdToolParts) break;
				const toolCall = toolCallsByToolCallId.get(chunk.toolCallId);
				if (toolCall == null) {
					controller.enqueue({
						type: "error",
						error: new ToolCallNotFoundForApprovalError({
							toolCallId: chunk.toolCallId,
							approvalId: chunk.approvalId
						})
					});
					break;
				}
				const toolApprovalRequest = {
					type: "tool-approval-request",
					approvalId: chunk.approvalId,
					toolCall
				};
				controller.enqueue(toolApprovalRequest);
				if (collectContent) modelCallContent.push(toolApprovalRequest);
				break;
			}
			case "tool-result": {
				if (collectContent) rawModelCallContent.push(chunk);
				const toolName = chunk.toolName;
				const toolCall = toolCallsByToolCallId.get(chunk.toolCallId);
				const toolResultPart = chunk.isError ? {
					type: "tool-error",
					toolCallId: chunk.toolCallId,
					toolName,
					input: toolCall?.input,
					providerExecuted: true,
					error: chunk.result,
					dynamic: chunk.dynamic,
					...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
					...toolCall?.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
				} : {
					type: "tool-result",
					toolCallId: chunk.toolCallId,
					toolName,
					input: toolCall?.input,
					output: chunk.result,
					providerExecuted: true,
					dynamic: chunk.dynamic,
					...chunk.providerMetadata != null ? { providerMetadata: chunk.providerMetadata } : {},
					...toolCall?.toolMetadata != null ? { toolMetadata: toolCall.toolMetadata } : {}
				};
				if (!withholdToolParts) controller.enqueue(toolResultPart);
				if (collectContent) modelCallContent.push(toolResultPart);
				break;
			}
			case "tool-input-start": {
				const tool = getOwn(tools, chunk.toolName);
				controller.enqueue({
					...chunk,
					dynamic: chunk.dynamic ?? tool?.type === "dynamic",
					title: tool?.title,
					...tool?.metadata != null ? { toolMetadata: tool.metadata } : {}
				});
				break;
			}
			case "stream-start":
				controller.enqueue({
					type: "model-call-start",
					warnings: chunk.warnings
				});
				break;
			case "response-metadata":
				responseId = chunk.id ?? responseId;
				responseModelId = chunk.modelId ?? responseModelId;
				controller.enqueue({
					type: "model-call-response-metadata",
					id: chunk.id,
					timestamp: chunk.timestamp,
					modelId: chunk.modelId
				});
				break;
			default:
				if (chunk.type === "custom" || chunk.type === "source") {
					if (collectContent) modelCallContent.push(chunk);
					if (collectContent) rawModelCallContent.push(chunk);
				}
				controller.enqueue(chunk);
		}
	} });
}
/**
* Returns true for chunks that contain generated model output.
* Used to measure time-to-first-output for text, reasoning, generated files,
* and tool calls.
*/
function isOutputChunk(chunk) {
	return chunk.type === "text-delta" && chunk.delta.length > 0 || chunk.type === "reasoning-delta" && chunk.delta.length > 0 || chunk.type === "tool-input-delta" && chunk.delta.length > 0 || chunk.type === "file" || chunk.type === "reasoning-file" || chunk.type === "tool-call";
}
function calculateOutputChunkTimingStats(timingsMs) {
	const sortedTimingsMs = [...timingsMs].sort((a, b) => a - b);
	const sum = timingsMs.reduce((sum, timingMs) => sum + timingMs, 0);
	return {
		min: sortedTimingsMs[0],
		p10: calculateNearestRankPercentile(sortedTimingsMs, .1),
		median: calculateNearestRankPercentile(sortedTimingsMs, .5),
		avg: sum / timingsMs.length,
		p90: calculateNearestRankPercentile(sortedTimingsMs, .9),
		max: sortedTimingsMs[sortedTimingsMs.length - 1]
	};
}
function calculateNearestRankPercentile(sortedValues, percentile) {
	return sortedValues[Math.ceil(percentile * sortedValues.length) - 1];
}
/**
* Appends a text or reasoning content part into the content array and updates the part indexes.
*/
function upsertTextContentPart({ enabled, content, rawContent, partIndexes, rawPartIndexes, id, type, textDelta, providerMetadata }) {
	if (!enabled) return;
	let partIndex = partIndexes.get(id);
	if (partIndex == null) {
		partIndex = content.push({
			type,
			text: "",
			...providerMetadata != null ? { providerMetadata } : {}
		}) - 1;
		partIndexes.set(id, partIndex);
	}
	let rawPartIndex = rawPartIndexes.get(id);
	if (rawPartIndex == null) {
		rawPartIndex = rawContent.push({
			type,
			text: "",
			...providerMetadata != null ? { providerMetadata } : {}
		}) - 1;
		rawPartIndexes.set(id, rawPartIndex);
	}
	const part = content[partIndex];
	const rawPart = rawContent[rawPartIndex];
	if (textDelta != null) {
		part.text += textDelta;
		rawPart.text += textDelta;
	}
	if (providerMetadata != null) {
		part.providerMetadata = providerMetadata;
		rawPart.providerMetadata = providerMetadata;
	}
}
//#endregion
//#region src/generate-text/stream-text.ts
const originalGenerateId$2 = createIdGenerator$1({
	prefix: "aitxt",
	size: 24
});
const originalGenerateCallId$7 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Generate a text and call tools for a given prompt using a language model.
*
* This function streams the output. If you do not want to stream the output, use `generateText` instead.
*
* @param model - The language model to use.
* @param tools - Tools that are accessible to and can be called by the model. The model needs to support calling tools.
* @param toolOrder - Controls the order in which tools are sent to the provider. Tools not listed are appended alphabetically.
* @param toolCallConcurrency - Maximum number of tool calls that may execute concurrently within a step. Set to 1 for sequential execution. Default: unlimited.
*
* @param system - A system message that will be part of the prompt.
* @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
* @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
* @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. Default: false.
*
* @param maxOutputTokens - Maximum number of tokens to generate.
* @param temperature - Temperature setting.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topP - Nucleus sampling.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topK - Only sample from the top K options for each subsequent token.
* Used to remove "long tail" low probability responses.
* Recommended for advanced use cases only. You usually only need to use temperature.
* @param presencePenalty - Presence penalty setting.
* It affects the likelihood of the model to repeat information that is already in the prompt.
* The value is passed through to the provider. The range depends on the provider and model.
* @param frequencyPenalty - Frequency penalty setting.
* It affects the likelihood of the model to repeatedly use the same words or phrases.
* The value is passed through to the provider. The range depends on the provider and model.
* @param stopSequences - Stop sequences.
* If set, the model will stop generating text when one of the stop sequences is generated.
* @param seed - The seed (integer) to use for random sampling.
* If set and supported by the model, calls will generate deterministic results.
*
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param streamRetries - Maximum number of retries for provider errors received after streaming starts. Set to 0 to disable automatic stream retries while allowing `onError` to request retries. Omit to disable all stream retry behavior. Default: 0.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param timeout - An optional timeout in milliseconds. The call will be aborted if it takes longer than the specified timeout.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
*
* @param experimental_sandbox - The sandbox environment that is passed through to tool execution.
* @param experimental_steering - A steering object that adds user messages to the generation at the next step boundary.
* @param runtimeContext - User-defined runtime context that flows through the entire generation lifecycle.
* @param experimental_refineToolInput - Optional mapping of tool names to functions that refine parsed tool inputs before tools are executed and before outputs, callbacks, and telemetry are recorded.
*
* @param onChunk - Callback that is called for each chunk of the stream. The stream processing will pause until the callback promise is resolved.
* @param onError - Callback that is called when an error occurs during streaming. You can use it to log errors.
* @param onStart - Callback invoked when generation begins, before any LLM calls.
* @param experimental_onStart - Deprecated alias for `onStart`.
* @param onStepStart - Callback invoked when each step begins, before the provider is called.
* @param experimental_onStepStart - Deprecated alias for `onStepStart`.
* @param onLanguageModelCallStart - Callback invoked immediately before each provider model call begins.
* @param experimental_onLanguageModelCallStart - Deprecated alias for `onLanguageModelCallStart`.
* @param onLanguageModelCallEnd - Callback invoked after each provider model call response is normalized and parsed.
* @param experimental_onLanguageModelCallEnd - Deprecated alias for `onLanguageModelCallEnd`.
* @param onToolExecutionStart - Callback invoked before each tool execution begins.
* @param experimental_onToolCallStart - Deprecated alias for `onToolExecutionStart`.
* @param onToolExecutionEnd - Callback invoked after each tool execution completes.
* @param experimental_onToolCallFinish - Deprecated alias for `onToolExecutionEnd`.
* @param onStepEnd - Callback that is called when each step (LLM call) ends, including intermediate steps.
* @param onStepError - Callback that is called when a step that started fails before it produces a step result, i.e. when the provider call throws or rejects, or when the model stream ends without output. A provider `error` chunk still ends the step with `onStepEnd`, and an abort or timeout ends it with `onAbort`.
* @param onStepFinish - Deprecated alias for `onStepEnd`.
* @param onEnd - Callback that is called when all steps are finished and the response is complete.
* @param onFinish - Deprecated alias for `onEnd`.
*
* @returns
* A result object for accessing different stream types and additional information.
*/
function streamText(options) {
	return startStreamText(options);
}
/**
* Stream text with a single consumer, without replay or final-content getters.
* Accepts the same options as streamText and uses the same execution engine.
*/
function streamTextLowMemory(options) {
	const telemetry = options.telemetry ?? options.experimental_telemetry;
	const integrations = telemetry?.integrations != null ? asArray(telemetry.integrations) : getGlobalTelemetryIntegrations();
	const collectContent = options.tools != null && Object.keys(options.tools).length > 0 || options.toolChoice != null || options.output != null || options.prepareStep != null || options.stopWhen != null || options.onEnd != null || options.onFinish != null || options.onStepEnd != null || options.onStepFinish != null || options.onAbort != null || options.onLanguageModelCallEnd != null || options.experimental_onLanguageModelCallEnd != null || telemetry?.isEnabled !== false && integrations.length > 0;
	return createSingleConsumerStreamTextResult(startStreamText({
		...options,
		_internal: {
			...options._internal,
			retention: {
				replay: false,
				collectContent
			}
		}
	}));
}
function startStreamText(options) {
	const steeringRun = startSteeringRun(options.experimental_steering);
	try {
		return streamTextInternal(options, steeringRun);
	} catch (error) {
		steeringRun?.end("error");
		throw error;
	}
}
function streamTextInternal({ model, tools, toolChoice, instructions, system, prompt, messages, allowSystemInMessages, maxRetries, streamRetries, abortSignal, timeout, headers, stopWhen = isStepCount(1), experimental_sandbox: sandbox, output, toolApproval, experimental_toolCallers, experimental_toolApprovalSecret, experimental_telemetry, telemetry = experimental_telemetry, prepareStep, providerOptions, activeTools, toolOrder, toolCallConcurrency, experimental_repairToolCall, repairToolCall = experimental_repairToolCall, experimental_refineToolInput: refineToolInput, experimental_transform: transform, experimental_download: download, includeRawChunks, onChunk, onError: onErrorArg, onFinish, onEnd = onFinish, onAbort, onStepEnd, onStepError, onStepFinish, onStart, experimental_onStart, onStepStart, experimental_onStepStart, onLanguageModelCallStart, experimental_onLanguageModelCallStart, onLanguageModelCallEnd, experimental_onLanguageModelCallEnd, onToolExecutionStart, onToolExecutionEnd, experimental_onToolCallStart, experimental_onToolCallFinish, runtimeContext = {}, toolsContext = {}, experimental_include, include = experimental_include, _internal: { now: now$2 = now, generateId = originalGenerateId$2, generateCallId = originalGenerateCallId$7, retention = {
	replay: true,
	collectContent: true
} } = {}, ...settings }, steeringRun) {
	const resolvedToolCallConcurrency = prepareToolCallConcurrency(toolCallConcurrency);
	const totalTimeoutMs = getTotalTimeoutMs(timeout);
	const stepTimeoutMs = getStepTimeoutMs(timeout);
	const firstChunkTimeoutMs = getFirstChunkTimeoutMs(timeout);
	const chunkTimeoutMs = getChunkTimeoutMs(timeout);
	const stepAbortController = stepTimeoutMs != null ? new AbortController() : void 0;
	const firstChunkAbortController = firstChunkTimeoutMs != null ? new AbortController() : void 0;
	const chunkAbortController = chunkTimeoutMs != null ? new AbortController() : void 0;
	const onError = onErrorArg ?? (({ error }) => {
		console.error(error);
	});
	const resolvedOnStart = onStart ?? experimental_onStart;
	const resolvedOnStepStart = onStepStart ?? experimental_onStepStart;
	const resolvedOnLanguageModelCallStart = onLanguageModelCallStart ?? experimental_onLanguageModelCallStart;
	const resolvedOnLanguageModelCallEnd = onLanguageModelCallEnd ?? experimental_onLanguageModelCallEnd;
	const resolvedOnToolExecutionStart = onToolExecutionStart ?? experimental_onToolCallStart;
	const resolvedOnToolExecutionEnd = onToolExecutionEnd ?? experimental_onToolCallFinish;
	const resolvedOnStepEnd = onStepEnd ?? onStepFinish;
	return new DefaultStreamTextResult({
		retention,
		model: resolveLanguageModel(model),
		telemetry,
		headers,
		settings,
		maxRetries,
		streamRetries,
		abortSignal: mergeAbortSignals(abortSignal, totalTimeoutMs, stepAbortController?.signal, firstChunkAbortController?.signal, chunkAbortController?.signal),
		stepTimeoutMs,
		stepAbortController,
		firstChunkTimeoutMs,
		firstChunkAbortController,
		chunkTimeoutMs,
		chunkAbortController,
		instructions,
		system,
		prompt,
		messages,
		allowSystemInMessages,
		experimental_sandbox: sandbox,
		steeringRun,
		tools,
		toolsContext,
		runtimeContext,
		toolChoice,
		transforms: asArray(transform),
		activeTools,
		toolOrder,
		toolCallConcurrency: resolvedToolCallConcurrency,
		repairToolCall,
		refineToolInput,
		stopConditions: asArray(stopWhen),
		output,
		toolApproval,
		experimental_toolCallers,
		experimental_toolApprovalSecret,
		providerOptions,
		prepareStep,
		timeout,
		onChunk,
		onError,
		canRetryStreamViaOnError: streamRetries !== void 0 && onErrorArg != null,
		onEnd,
		onAbort,
		onStepFinish: resolvedOnStepEnd,
		onStepError,
		onStart: resolvedOnStart,
		onStepStart: resolvedOnStepStart,
		onLanguageModelCallStart: resolvedOnLanguageModelCallStart,
		onLanguageModelCallEnd: resolvedOnLanguageModelCallEnd,
		onToolExecutionStart: resolvedOnToolExecutionStart,
		onToolExecutionEnd: resolvedOnToolExecutionEnd,
		now: now$2,
		generateId,
		generateCallId,
		download,
		include: {
			requestBody: include?.requestBody ?? false,
			requestMessages: include?.requestMessages ?? false,
			rawChunks: include?.rawChunks ?? includeRawChunks ?? false
		}
	});
}
const streamRetryBoundarySymbol = Symbol("streamRetryBoundary");
function isStreamRetryBoundaryPart(part) {
	return streamRetryBoundarySymbol in part;
}
async function markPromiseAsHandled$1(promise) {
	try {
		await promise;
	} catch {}
}
function createOutputTransformStream(output, collectOutput = true) {
	let firstTextChunkId = void 0;
	let text = "";
	let textChunk = "";
	let textProviderMetadata = void 0;
	let arrayStreamParser = createArrayStreamParser(output);
	let lastArrayPartial;
	let lastPublishedValue = void 0;
	let hasPublishedValue = false;
	function resetOutputState() {
		arrayStreamParser = createArrayStreamParser(output);
		lastArrayPartial = void 0;
		firstTextChunkId = void 0;
		text = "";
		textChunk = "";
		textProviderMetadata = void 0;
		lastPublishedValue = void 0;
		hasPublishedValue = false;
	}
	function enqueueChunk({ controller, chunk }) {
		controller.enqueue(chunk);
	}
	function publishTextChunk({ controller, partialOutput = void 0 }) {
		enqueueChunk({
			controller,
			chunk: {
				part: {
					type: "text-delta",
					id: firstTextChunkId,
					text: textChunk,
					providerMetadata: textProviderMetadata
				},
				partialOutput
			}
		});
		textChunk = "";
	}
	return new TransformStream({ async transform(chunk, controller) {
		if (!collectOutput) {
			controller.enqueue(isStreamRetryBoundaryPart(chunk) ? chunk : {
				part: chunk,
				partialOutput: void 0
			});
			return;
		}
		if (isStreamRetryBoundaryPart(chunk)) {
			resetOutputState();
			controller.enqueue(chunk);
			return;
		}
		if (chunk.type === "start-step") resetOutputState();
		if (chunk.type === "finish-step" && textChunk.length > 0) publishTextChunk({ controller });
		if (chunk.type !== "text-delta" && chunk.type !== "text-start" && chunk.type !== "text-end") {
			enqueueChunk({
				controller,
				chunk: {
					part: chunk,
					partialOutput: void 0
				}
			});
			return;
		}
		if (firstTextChunkId == null) firstTextChunkId = chunk.id;
		else if (chunk.id !== firstTextChunkId) {
			enqueueChunk({
				controller,
				chunk: {
					part: chunk,
					partialOutput: void 0
				}
			});
			return;
		}
		if (chunk.type === "text-start") {
			enqueueChunk({
				controller,
				chunk: {
					part: chunk,
					partialOutput: void 0
				}
			});
			return;
		}
		if (chunk.type === "text-end") {
			if (textChunk.length > 0) publishTextChunk({ controller });
			enqueueChunk({
				controller,
				chunk: {
					part: chunk,
					partialOutput: void 0
				}
			});
			return;
		}
		text += chunk.text;
		textChunk += chunk.text;
		textProviderMetadata = chunk.providerMetadata ?? textProviderMetadata;
		if (chunk.text.length === 0 && chunk.providerMetadata != null) {
			enqueueChunk({
				controller,
				chunk: {
					part: chunk,
					partialOutput: void 0
				}
			});
			return;
		}
		if (arrayStreamParser != null) {
			const result = await arrayStreamParser(chunk.text);
			if (result !== "fallback") {
				if (result != null) {
					lastArrayPartial = result.partial;
					publishTextChunk({
						controller,
						partialOutput: lastArrayPartial
					});
				}
				return;
			}
			arrayStreamParser = void 0;
			if (lastArrayPartial != null) {
				lastPublishedValue = JSON.stringify(lastArrayPartial);
				hasPublishedValue = true;
			}
		}
		const result = await output.parsePartialOutput({ text });
		if (result !== void 0) {
			const currentValue = typeof result.partial === "string" ? result.partial : JSON.stringify(result.partial);
			if (!hasPublishedValue || currentValue !== lastPublishedValue) {
				publishTextChunk({
					controller,
					partialOutput: result.partial
				});
				lastPublishedValue = currentValue;
				hasPublishedValue = true;
			}
		}
	} });
}
function applyStreamTextTransforms({ stream, transforms, tools, stopStream }) {
	const sourceReader = stream.getReader();
	let sourceDone = false;
	let pendingBoundary;
	let transformedSegmentReader;
	const createTransformedSegmentReader = () => {
		let segment = new ReadableStream({
			async pull(controller) {
				const { done, value } = await sourceReader.read();
				if (done) {
					sourceDone = true;
					controller.close();
					return;
				}
				if (isStreamRetryBoundaryPart(value)) {
					pendingBoundary = value;
					controller.close();
					return;
				}
				controller.enqueue(value);
			},
			cancel(reason) {
				return sourceReader.cancel(reason);
			}
		}, { highWaterMark: 0 });
		for (const transform of transforms) segment = segment.pipeThrough(transform({
			tools,
			stopStream
		}));
		return segment.getReader();
	};
	return new ReadableStream({
		async pull(controller) {
			transformedSegmentReader ??= createTransformedSegmentReader();
			const { done, value } = await transformedSegmentReader.read();
			if (!done) {
				controller.enqueue(value);
				return;
			}
			transformedSegmentReader = void 0;
			if (pendingBoundary != null) {
				controller.enqueue(pendingBoundary);
				pendingBoundary = void 0;
				return;
			}
			if (sourceDone) controller.close();
		},
		async cancel(reason) {
			await transformedSegmentReader?.cancel(reason);
			await sourceReader.cancel(reason);
		}
	});
}
var DefaultStreamTextResult = class {
	constructor({ retention, model, telemetry, headers, settings, maxRetries: maxRetriesArg, streamRetries: streamRetriesArg, abortSignal, stepTimeoutMs, stepAbortController, firstChunkTimeoutMs, firstChunkAbortController, chunkTimeoutMs, chunkAbortController, instructions, system, prompt, messages, allowSystemInMessages, experimental_sandbox: sandbox, steeringRun, tools, toolChoice, transforms, activeTools, toolOrder, toolCallConcurrency, repairToolCall, refineToolInput, stopConditions, output, toolApproval, experimental_toolCallers, experimental_toolApprovalSecret, providerOptions, prepareStep, now, generateId, generateCallId, timeout, onChunk, onError, canRetryStreamViaOnError, onEnd, onAbort, onStepFinish, onStepError, onStart, onStepStart, onLanguageModelCallStart, onLanguageModelCallEnd, onToolExecutionStart, onToolExecutionEnd, runtimeContext, toolsContext, download, include }) {
		this._totalUsage = new DelayedPromise();
		this._finishReason = new DelayedPromise();
		this._rawFinishReason = new DelayedPromise();
		this._steps = new DelayedPromise();
		this._initialResponseMessages = new DelayedPromise();
		this.streamClaimed = false;
		this.retention = retention;
		this.outputSpecification = output;
		this.tools = tools;
		const resolvedToolCallers = resolveToolCallerConfiguration({
			tools,
			toolCallers: experimental_toolCallers
		});
		const prepareToolSearch = createToolSearchState({
			tools,
			toolCallers: resolvedToolCallers
		});
		const telemetryDispatcher = createRestrictedTelemetryDispatcher$3({
			telemetry,
			includeRuntimeContext: telemetry?.includeRuntimeContext,
			includeToolsContext: telemetry?.includeToolsContext
		});
		let stepFinish;
		let recordedContent = [];
		let recordedFinishReason = void 0;
		let recordedRawFinishReason = void 0;
		let recordedTotalUsage = void 0;
		let recordedRequest = {};
		let recordedRequestMessages = [];
		let recordedWarnings = [];
		let recordedSteps = [];
		const initialResponseMessages = [];
		let stepMessagesForNextStep;
		let currentStepMessages = [];
		let currentStepSteeringMessages = [];
		let isAborted = false;
		let currentStepModel = model;
		const createPartIdReserver = () => {
			const usedIds = /* @__PURE__ */ new Set();
			return (id) => {
				if (!usedIds.has(id)) {
					usedIds.add(id);
					return id;
				}
				const generatedId = generateId();
				let uniqueId = generatedId;
				let suffix = 0;
				while (usedIds.has(uniqueId)) uniqueId = `${generatedId}-${++suffix}`;
				usedIds.add(uniqueId);
				return uniqueId;
			};
		};
		const reserveTextPartId = createPartIdReserver();
		const reserveReasoningPartId = createPartIdReserver();
		const pendingDeferredToolCalls = /* @__PURE__ */ new Map();
		let activeTextContent = createIdMap();
		let activeReasoningContent = createIdMap();
		let recordedNoOutputError;
		const errorsHandledForStreamRetry = /* @__PURE__ */ new Set();
		let openStep;
		const notifyStepError = async (error) => {
			if (openStep == null || abortSignal?.aborted) return;
			const { event } = openStep;
			openStep = void 0;
			await notify({
				event: {
					...event,
					error
				},
				callbacks: [onStepError, telemetryDispatcher.onStepError]
			});
		};
		const eventProcessor = new TransformStream({
			async transform(chunk, controller) {
				if (isStreamRetryBoundaryPart(chunk)) {
					const retryBoundary = chunk[streamRetryBoundarySymbol];
					recordedContent = [];
					activeReasoningContent = createIdMap();
					activeTextContent = createIdMap();
					recordedRequest = retryBoundary.request;
					recordedRequestMessages = retryBoundary.request.messages ?? [];
					recordedWarnings = retryBoundary.warnings;
					return;
				}
				const { part } = chunk;
				controller.enqueue(chunk);
				const callbacksHandledForStreamRetry = part.type === "error" && errorsHandledForStreamRetry.has(part.error);
				if (!callbacksHandledForStreamRetry) await notify({
					event: { chunk: part },
					callbacks: onChunk
				});
				if (part.type === "error") {
					const error = wrapGatewayError(part.error);
					if (NoOutputGeneratedError.isInstance(error)) recordedNoOutputError = error;
					if (callbacksHandledForStreamRetry) errorsHandledForStreamRetry.delete(part.error);
					else {
						if (openStep != null) openStep.error = error;
						await notify({
							event: { error },
							callbacks: async (event) => {
								await onError(event);
							}
						});
					}
				}
				if (part.type === "custom" || part.type === "source" || part.type === "tool-call" || part.type === "tool-approval-request" || part.type === "tool-approval-response" || part.type === "tool-error") {
					if (retention.collectContent) recordedContent.push(part);
				}
				if (part.type === "text-start") {
					activeTextContent[part.id] = {
						type: "text",
						text: "",
						providerMetadata: part.providerMetadata
					};
					if (retention.collectContent) recordedContent.push(activeTextContent[part.id]);
				}
				if (part.type === "text-delta") {
					const activeText = activeTextContent[part.id];
					if (activeText == null) {
						controller.enqueue({
							part: {
								type: "error",
								error: `text part ${part.id} not found`
							},
							partialOutput: void 0
						});
						return;
					}
					if (retention.collectContent) activeText.text += part.text;
					activeText.providerMetadata = part.providerMetadata ?? activeText.providerMetadata;
				}
				if (part.type === "text-end") {
					const activeText = activeTextContent[part.id];
					if (activeText == null) {
						controller.enqueue({
							part: {
								type: "error",
								error: `text part ${part.id} not found`
							},
							partialOutput: void 0
						});
						return;
					}
					activeText.providerMetadata = part.providerMetadata ?? activeText.providerMetadata;
					if (part.citations != null) activeText.citations = part.citations;
					delete activeTextContent[part.id];
				}
				if (part.type === "reasoning-start") {
					activeReasoningContent[part.id] = {
						type: "reasoning",
						text: "",
						providerMetadata: part.providerMetadata
					};
					if (retention.collectContent) recordedContent.push(activeReasoningContent[part.id]);
				}
				if (part.type === "reasoning-delta") {
					const activeReasoning = activeReasoningContent[part.id];
					if (activeReasoning == null) {
						controller.enqueue({
							part: {
								type: "error",
								error: `reasoning part ${part.id} not found`
							},
							partialOutput: void 0
						});
						return;
					}
					if (retention.collectContent) activeReasoning.text += part.text;
					activeReasoning.providerMetadata = part.providerMetadata ?? activeReasoning.providerMetadata;
				}
				if (part.type === "reasoning-end") {
					const activeReasoning = activeReasoningContent[part.id];
					if (activeReasoning == null) {
						controller.enqueue({
							part: {
								type: "error",
								error: `reasoning part ${part.id} not found`
							},
							partialOutput: void 0
						});
						return;
					}
					activeReasoning.providerMetadata = part.providerMetadata ?? activeReasoning.providerMetadata;
					delete activeReasoningContent[part.id];
				}
				if (part.type === "file" || part.type === "reasoning-file") {
					if (retention.collectContent) recordedContent.push({
						type: part.type,
						file: part.file,
						...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
					});
				}
				if (part.type === "tool-result" && !part.preliminary) {
					if (retention.collectContent) recordedContent.push(part);
				}
				if (part.type === "start-step") {
					recordedContent = [];
					activeReasoningContent = createIdMap();
					activeTextContent = createIdMap();
					recordedRequest = part.request;
					recordedWarnings = part.warnings;
				}
				if (part.type === "finish-step") {
					const stepResponseMessages = await toResponseMessages({
						content: recordedContent,
						tools
					});
					const currentStepResult = new DefaultStepResult({
						callId,
						stepNumber: recordedSteps.length,
						provider: currentStepModel.provider,
						modelId: currentStepModel.modelId,
						runtimeContext,
						toolsContext,
						content: recordedContent,
						finishReason: part.finishReason,
						rawFinishReason: part.rawFinishReason,
						usage: part.usage,
						performance: part.performance,
						warnings: recordedWarnings,
						request: {
							...recordedRequest,
							messages: include.requestMessages ? cloneModelMessages(recordedRequestMessages) : void 0
						},
						response: {
							...part.response,
							messages: cloneModelMessages(stepResponseMessages)
						},
						providerMetadata: part.providerMetadata,
						steeringMessages: currentStepSteeringMessages
					});
					openStep = void 0;
					await notify({
						event: currentStepResult,
						callbacks: [onStepFinish, telemetryDispatcher.onStepEnd]
					});
					logWarnings({
						warnings: recordedWarnings,
						provider: currentStepModel.provider,
						model: currentStepModel.modelId
					});
					recordedSteps.push(currentStepResult);
					stepMessagesForNextStep = [...currentStepMessages, ...stepResponseMessages];
					stepFinish.resolve();
				}
				if (part.type === "finish") {
					recordedTotalUsage = part.totalUsage;
					recordedFinishReason = part.finishReason;
					recordedRawFinishReason = part.rawFinishReason;
				}
			},
			async flush(controller) {
				steeringRun?.end(recordedSteps.length === 0 || recordedNoOutputError != null ? "error" : "finished");
				try {
					const noOutputError = new NoOutputGeneratedError({ message: "No output generated. Check the stream for errors." });
					await notifyStepError(openStep?.error ?? noOutputError);
					if (recordedSteps.length === 0 || recordedNoOutputError != null) {
						const error = abortSignal?.aborted ? abortSignal.reason : recordedNoOutputError ?? noOutputError;
						if (recordedNoOutputError != null && !abortSignal?.aborted) await telemetryDispatcher.onError?.({
							callId,
							error: recordedNoOutputError
						});
						self.rejectResultPromises(error);
						return;
					}
					const finishReason = recordedFinishReason ?? "other";
					const totalUsage = recordedTotalUsage ?? createNullLanguageModelUsage();
					self._finishReason.resolve(finishReason);
					self._rawFinishReason.resolve(recordedRawFinishReason);
					self._totalUsage.resolve(totalUsage);
					self._steps.resolve(retention.replay ? recordedSteps : []);
					if (isAborted) return;
					const finalStep = recordedSteps[recordedSteps.length - 1];
					const content = recordedSteps.flatMap((step) => step.content);
					const files = recordedSteps.flatMap((step) => step.files);
					const sources = recordedSteps.flatMap((step) => step.sources);
					const toolCalls = recordedSteps.flatMap((step) => step.toolCalls);
					const staticToolCalls = recordedSteps.flatMap((step) => step.staticToolCalls);
					const dynamicToolCalls = recordedSteps.flatMap((step) => step.dynamicToolCalls);
					const toolResults = recordedSteps.flatMap((step) => step.toolResults);
					const staticToolResults = recordedSteps.flatMap((step) => step.staticToolResults);
					const dynamicToolResults = recordedSteps.flatMap((step) => step.dynamicToolResults);
					const warnings = recordedSteps.flatMap((step) => step.warnings ?? []);
					const onEndWithOutput = onEnd == null ? void 0 : async (event) => {
						const parsedOutput = output == null ? void 0 : await (retention.replay ? self.getOutputPromise() : self.parseOutput(finalStep)).catch(() => void 0);
						await onEnd({
							...event,
							...output != null ? { output: parsedOutput } : {}
						});
					};
					const onEndEvent = {
						callId,
						toolsContext: finalStep.toolsContext,
						stepNumber: finalStep.stepNumber,
						model: finalStep.model,
						runtimeContext: finalStep.runtimeContext,
						finishReason: finalStep.finishReason,
						rawFinishReason: finalStep.rawFinishReason,
						usage: totalUsage,
						totalUsage,
						content,
						text: finalStep.text,
						reasoning: finalStep.reasoning,
						reasoningText: finalStep.reasoningText,
						files,
						sources,
						toolCalls,
						staticToolCalls,
						dynamicToolCalls,
						toolResults,
						staticToolResults,
						dynamicToolResults,
						responseMessages: [...initialResponseMessages, ...recordedSteps.flatMap((step) => step.response.messages)],
						warnings,
						request: finalStep.request,
						response: finalStep.response,
						providerMetadata: finalStep.providerMetadata,
						steps: recordedSteps,
						finalStep
					};
					await Promise.all([notify({
						event: onEndEvent,
						callbacks: onEndWithOutput
					}), notify({
						event: onEndEvent,
						callbacks: telemetryDispatcher.onEnd
					})]);
				} catch (error) {
					controller.error(error);
				} finally {
					if (!retention.replay) {
						recordedSteps = [];
						recordedContent = [];
						recordedRequestMessages = [];
						currentStepMessages = [];
						stepMessagesForNextStep = void 0;
						activeTextContent = createIdMap();
						activeReasoningContent = createIdMap();
					}
				}
			}
		});
		const stitchableStream = createStitchableStream();
		this.addStream = stitchableStream.addStream;
		this.closeStream = stitchableStream.close;
		const reader = stitchableStream.stream.getReader();
		const cancelOnAbort = () => {
			this.rejectResultPromises(abortSignal?.reason);
			reader.cancel(abortSignal?.reason).catch(() => {});
		};
		const removeAbortListener = () => abortSignal?.removeEventListener("abort", cancelOnAbort);
		let stream = new ReadableStream({
			async start(controller) {
				controller.enqueue({ type: "start" });
				abortSignal?.addEventListener("abort", cancelOnAbort, { once: true });
				if (abortSignal?.aborted) cancelOnAbort();
			},
			async pull(controller) {
				async function abort() {
					isAborted = true;
					removeAbortListener();
					steeringRun?.end("aborted");
					await notify({
						event: {
							callId,
							steps: recordedSteps,
							...abortSignal?.reason !== void 0 ? { reason: abortSignal.reason } : {}
						},
						callbacks: [onAbort, telemetryDispatcher.onAbort]
					});
					controller.enqueue({
						type: "abort",
						...abortSignal?.reason !== void 0 ? { reason: getErrorMessage$1(abortSignal.reason) } : {}
					});
					controller.close();
				}
				try {
					const { done, value } = await reader.read();
					if (abortSignal?.aborted) {
						await abort();
						return;
					}
					if (done) {
						removeAbortListener();
						controller.close();
						return;
					}
					controller.enqueue(value);
				} catch (error) {
					removeAbortListener();
					if (isAbortError(error) && abortSignal?.aborted) await abort();
					else {
						steeringRun?.end("error");
						await notifyStepError(wrapGatewayError(error));
						await telemetryDispatcher.onError?.({
							callId,
							error
						});
						controller.error(error);
					}
				}
			},
			cancel(reason) {
				removeAbortListener();
				steeringRun?.end("aborted");
				return reader.cancel(reason);
			}
		});
		let isRunning = true;
		stream = stream.pipeThrough(new TransformStream({ async transform(chunk, controller) {
			if (isRunning) controller.enqueue(chunk);
		} }));
		stream = applyStreamTextTransforms({
			stream,
			transforms,
			tools,
			stopStream() {
				stitchableStream.terminate();
				isRunning = false;
			}
		});
		this.baseStream = stream.pipeThrough(createOutputTransformStream(output ?? text(), retention.replay || output != null)).pipeThrough(eventProcessor);
		const { maxRetries } = prepareRetries({
			maxRetries: maxRetriesArg,
			abortSignal
		});
		const { maxRetries: streamRetries } = prepareRetries({
			maxRetries: streamRetriesArg,
			abortSignal,
			parameter: "streamRetries",
			defaultMaxRetries: 0
		});
		const callSettings = prepareLanguageModelCallOptions(settings);
		const self = this;
		const callId = generateCallId();
		(async () => {
			const initialPrompt = await standardizePrompt({
				instructions,
				system,
				prompt,
				messages,
				allowSystemInMessages
			});
			const startEvent = {
				callId,
				operationId: "ai.streamText",
				provider: model.provider,
				modelId: model.modelId,
				instructions: initialPrompt.instructions,
				messages: initialPrompt.messages,
				tools,
				toolChoice,
				activeTools,
				toolOrder,
				maxOutputTokens: callSettings.maxOutputTokens,
				temperature: callSettings.temperature,
				topP: callSettings.topP,
				topK: callSettings.topK,
				presencePenalty: callSettings.presencePenalty,
				frequencyPenalty: callSettings.frequencyPenalty,
				stopSequences: callSettings.stopSequences,
				seed: callSettings.seed,
				reasoning: callSettings.reasoning,
				maxRetries,
				timeout,
				headers,
				providerOptions,
				output,
				runtimeContext,
				toolsContext
			};
			const streamTextTracingChannelContext = telemetryDispatcher.startTracingChannelContext?.({
				type: "streamText",
				event: startEvent,
				completion: self._totalUsage.promise.then(() => void 0)
			});
			const runInStreamTextTracingChannelContext = (execute) => streamTextTracingChannelContext?.run(execute) ?? execute();
			const runInTracingChannelSpanInStreamText = telemetryDispatcher.runInTracingChannelSpan == null ? void 0 : (options) => runInStreamTextTracingChannelContext(() => telemetryDispatcher.runInTracingChannelSpan(options));
			await notify({
				event: startEvent,
				callbacks: [onStart, telemetryDispatcher.onStart]
			});
			const initialMessages = initialPrompt.messages;
			let instructionsForNextStep = initialPrompt.instructions;
			const { approvedToolApprovals, deniedToolApprovals } = collectToolApprovals({ messages: initialMessages });
			if (deniedToolApprovals.length > 0 || approvedToolApprovals.length > 0) {
				const { approvedToolApprovals: localApprovedToolApprovals, deniedToolApprovals: revalidationDeniedToolApprovals, invalidToolApprovals } = await validateApprovedToolApprovals({
					approvedToolApprovals: approvedToolApprovals.filter((toolApproval) => !toolApproval.toolCall.providerExecuted),
					tools,
					toolApproval,
					messages: initialMessages,
					toolsContext,
					runtimeContext,
					toolApprovalSecret: experimental_toolApprovalSecret,
					refineToolInput
				});
				const localDeniedToolApprovals = [...deniedToolApprovals.filter((toolApproval) => !toolApproval.toolCall.providerExecuted), ...revalidationDeniedToolApprovals];
				const localDeniedToolApprovalsWithoutResults = localDeniedToolApprovals.filter((toolApproval) => toolApproval.existingToolResult == null);
				const deniedProviderExecutedToolApprovals = deniedToolApprovals.filter((toolApproval) => toolApproval.toolCall.providerExecuted);
				let toolExecutionStepStreamController;
				const toolExecutionStepStream = new ReadableStream({ start(controller) {
					toolExecutionStepStreamController = controller;
				} });
				self.addStream(toolExecutionStepStream);
				try {
					for (const toolApproval of [...localDeniedToolApprovals, ...deniedProviderExecutedToolApprovals]) toolExecutionStepStreamController?.enqueue({
						type: "tool-output-denied",
						toolCallId: toolApproval.toolCall.toolCallId,
						toolName: toolApproval.toolCall.toolName
					});
					for (const toolApproval of invalidToolApprovals) toolExecutionStepStreamController?.enqueue({
						type: "tool-error",
						toolCallId: toolApproval.toolCall.toolCallId,
						toolName: toolApproval.toolCall.toolName,
						input: toolApproval.toolCall.input,
						error: getErrorMessage$1(toolApproval.error),
						title: toolApproval.toolCall.title,
						...toolApproval.toolCall.dynamic === true ? { dynamic: true } : {},
						...toolApproval.toolCall.toolMetadata != null ? { toolMetadata: toolApproval.toolCall.toolMetadata } : {}
					});
					const toolOutputs = [];
					await mapWithConcurrency({
						items: localApprovedToolApprovals,
						concurrency: toolCallConcurrency,
						abortSignal,
						execute: async (toolApproval) => {
							const result = await executeToolCall({
								toolCall: toolApproval.toolCall,
								tools,
								callId,
								messages: initialMessages,
								abortSignal,
								timeout,
								experimental_sandbox: sandbox,
								toolsContext,
								onToolExecutionStart: filterNullable(onToolExecutionStart, telemetryDispatcher.onToolExecutionStart),
								onToolExecutionEnd: filterNullable(onToolExecutionEnd, telemetryDispatcher.onToolExecutionEnd),
								executeToolInTelemetryContext: telemetryDispatcher.executeTool,
								runInTracingChannelSpan: runInTracingChannelSpanInStreamText,
								onPreliminaryToolResult: (result) => {
									toolExecutionStepStreamController?.enqueue(result);
								}
							});
							if (result != null) {
								toolExecutionStepStreamController?.enqueue(result.output);
								toolOutputs.push(result.output);
							}
						}
					});
					if (toolOutputs.length > 0 || localDeniedToolApprovalsWithoutResults.length > 0 || invalidToolApprovals.length > 0) {
						const localToolContent = [];
						for (const output of toolOutputs) localToolContent.push({
							type: "tool-result",
							toolCallId: output.toolCallId,
							toolName: output.toolName,
							output: await createToolModelOutput({
								toolCallId: output.toolCallId,
								input: output.input,
								tool: getOwn(tools, output.toolName),
								output: output.type === "tool-result" ? output.output : output.error,
								errorMode: output.type === "tool-error" ? "text" : "none"
							})
						});
						for (const toolApproval of invalidToolApprovals) localToolContent.push({
							type: "tool-result",
							toolCallId: toolApproval.toolCall.toolCallId,
							toolName: toolApproval.toolCall.toolName,
							output: await createToolModelOutput({
								toolCallId: toolApproval.toolCall.toolCallId,
								input: toolApproval.toolCall.input,
								tool: getOwn(tools, toolApproval.toolCall.toolName),
								output: toolApproval.error,
								errorMode: "text"
							})
						});
						for (const toolApproval of localDeniedToolApprovalsWithoutResults) localToolContent.push({
							type: "tool-result",
							toolCallId: toolApproval.toolCall.toolCallId,
							toolName: toolApproval.toolCall.toolName,
							output: {
								type: "execution-denied",
								reason: toolApproval.approvalResponse.reason
							}
						});
						initialResponseMessages.push({
							role: "tool",
							content: localToolContent
						});
					}
				} finally {
					toolExecutionStepStreamController?.close();
				}
			}
			self._initialResponseMessages.resolve(initialResponseMessages);
			async function streamStep({ currentStep, usage }) {
				const stepTimeoutId = setAbortTimeout({
					abortController: stepAbortController,
					label: "Step",
					timeoutMs: stepTimeoutMs
				});
				let firstChunkTimeoutId = void 0;
				function startFirstChunkTimeout() {
					if (abortSignal?.aborted) return;
					firstChunkTimeoutId = setAbortTimeout({
						abortController: firstChunkAbortController,
						label: "First chunk",
						timeoutMs: firstChunkTimeoutMs
					});
				}
				function clearFirstChunkTimeout() {
					if (firstChunkTimeoutId != null) {
						clearTimeout(firstChunkTimeoutId);
						firstChunkTimeoutId = void 0;
					}
				}
				let chunkTimeoutId = void 0;
				function resetChunkTimeout() {
					if (chunkTimeoutId != null) clearTimeout(chunkTimeoutId);
					if (abortSignal?.aborted) return;
					chunkTimeoutId = setAbortTimeout({
						abortController: chunkAbortController,
						label: "Chunk",
						timeoutMs: chunkTimeoutMs
					});
				}
				function clearChunkTimeout() {
					if (chunkTimeoutId != null) {
						clearTimeout(chunkTimeoutId);
						chunkTimeoutId = void 0;
					}
				}
				function clearModelOutputTimeouts() {
					clearFirstChunkTimeout();
					clearChunkTimeout();
				}
				function clearStepTimeout() {
					if (stepTimeoutId != null) clearTimeout(stepTimeoutId);
				}
				function clearStepTimeouts() {
					clearStepTimeout();
					clearModelOutputTimeouts();
				}
				function cleanupStepTimeouts() {
					abortSignal?.removeEventListener("abort", cleanupStepTimeouts);
					clearStepTimeouts();
				}
				abortSignal?.addEventListener("abort", cleanupStepTimeouts, { once: true });
				try {
					stepFinish = new DelayedPromise();
					const stepTracingChannelContext = telemetryDispatcher.startTracingChannelContext?.({
						type: "step",
						event: {
							callId,
							stepNumber: currentStep
						},
						completion: stepFinish.promise
					});
					const runInStepTracingChannelContext = (execute) => stepTracingChannelContext?.run(execute) ?? execute();
					const responseMessagesFromPreviousSteps = recordedSteps.flatMap((step) => step.response.messages);
					const accumulatedResponseMessages = [...initialResponseMessages, ...responseMessagesFromPreviousSteps];
					const steeringMessages = steeringRun?.takeMessages() ?? [];
					const stepInputMessages = [...stepMessagesForNextStep ?? [...initialMessages, ...initialResponseMessages], ...steeringMessages];
					const prepareStepResult = await prepareStep?.({
						model,
						steps: recordedSteps,
						stepNumber: recordedSteps.length,
						instructions: instructionsForNextStep,
						initialInstructions: initialPrompt.instructions,
						messages: stepInputMessages,
						initialMessages,
						responseMessages: accumulatedResponseMessages,
						...steeringMessages.length > 0 ? { experimental_steeringMessages: steeringMessages } : {},
						toolsContext,
						runtimeContext,
						experimental_sandbox: sandbox
					});
					const stepSandbox = prepareStepResult?.experimental_sandbox ?? sandbox;
					runtimeContext = prepareStepResult?.runtimeContext ?? runtimeContext;
					toolsContext = prepareStepResult?.toolsContext ?? toolsContext;
					const stepModel = resolveLanguageModel(prepareStepResult?.model ?? model);
					currentStepModel = stepModel;
					const stepActiveTools = filterActiveTools({
						tools,
						activeTools: prepareStepResult?.activeTools ?? activeTools
					});
					const { executionTools, modelTools: stepModelTools, toolCallerMessages } = prepareToolsForToolCallers({
						tools: prepareToolSearch(stepActiveTools, {
							toolsContext,
							experimental_sandbox: stepSandbox
						}),
						toolCallers: resolvedToolCallers
					});
					const stepToolOrder = prepareStepResult?.toolOrder ?? toolOrder;
					const stepTools = await prepareTools({
						tools: stepModelTools,
						toolOrder: stepToolOrder,
						toolsContext,
						experimental_sandbox: stepSandbox
					});
					const stepToolChoice = prepareToolChoice({ toolChoice: prepareStepResult?.toolChoice ?? toolChoice });
					const stepExecutionTools = stepToolChoice.type === "none" ? void 0 : executionTools;
					const stepMessages = appendToolCallerMessages({
						messages: prepareStepResult?.messages ?? stepInputMessages,
						toolCallerMessages
					});
					currentStepMessages = stepMessages;
					const deliveredSteeringMessages = steeringRun?.resolveTakenMessages({
						stepNumber: currentStep,
						sentMessages: stepMessages
					}) ?? [];
					currentStepSteeringMessages = deliveredSteeringMessages.map(({ message }) => message);
					if (deliveredSteeringMessages.length > 0) self.addStream(new ReadableStream({ start(controller) {
						for (const { id, message } of deliveredSteeringMessages) controller.enqueue({
							type: "steering-message",
							id,
							message,
							stepNumber: currentStep
						});
						controller.close();
					} }));
					const stepInstructions = prepareStepResult?.instructions ?? prepareStepResult?.system ?? instructionsForNextStep;
					instructionsForNextStep = stepInstructions;
					const stepProviderOptions = mergeObjects(providerOptions, prepareStepResult?.providerOptions);
					const stepCallSettings = prepareStepCallSettings({
						callSettings,
						stepSettings: prepareStepResult
					});
					const stepStartTimestampMs = now();
					const { retry } = prepareRetries({
						maxRetries,
						abortSignal
					});
					let hasNotifiedStepStart = false;
					const callLanguageModel = () => runInStepTracingChannelContext(() => retry(async () => streamLanguageModelCall({
						model: prepareStepResult?.model ?? model,
						tools: stepModelTools,
						toolOrder: stepToolOrder,
						toolChoice: prepareStepResult?.toolChoice ?? toolChoice,
						instructions: stepInstructions,
						messages: stepMessages,
						allowSystemInMessages,
						repairToolCall,
						refineToolInput,
						abortSignal,
						headers,
						includeRawChunks: include.rawChunks,
						providerOptions: stepProviderOptions,
						download,
						output,
						callId,
						executeLanguageModelCallInTelemetryContext: telemetryDispatcher.executeLanguageModelCall,
						toolsContext,
						experimental_sandbox: stepSandbox,
						onLanguageModelCallStart: filterNullable(onLanguageModelCallStart, telemetryDispatcher.onLanguageModelCallStart),
						onLanguageModelCallEnd: filterNullable(onLanguageModelCallEnd, telemetryDispatcher.onLanguageModelCallEnd),
						onStart: async ({ promptMessages }) => {
							if (hasNotifiedStepStart) return;
							hasNotifiedStepStart = true;
							const stepStartEvent = {
								callId,
								provider: stepModel.provider,
								modelId: stepModel.modelId,
								stepNumber: recordedSteps.length,
								instructions: stepInstructions,
								messages: stepMessages,
								tools,
								toolChoice: prepareStepResult?.toolChoice ?? toolChoice,
								activeTools: prepareStepResult?.activeTools ?? activeTools,
								toolOrder: stepToolOrder,
								steps: [...recordedSteps],
								providerOptions: stepProviderOptions,
								runtimeContext,
								toolsContext,
								output,
								promptMessages,
								stepTools,
								stepToolChoice
							};
							await notify({
								event: stepStartEvent,
								callbacks: [onStepStart, telemetryDispatcher.onStepStart]
							});
							openStep = { event: stepStartEvent };
						},
						_internal: {
							now,
							collectContent: retention.collectContent
						},
						...stepCallSettings
					})));
					const initialLanguageModelCall = await callLanguageModel();
					let request = initialLanguageModelCall.request;
					let response = initialLanguageModelCall.response;
					let languageModelStreamReader = initialLanguageModelCall.stream.getReader();
					let automaticStreamRetryCount = 0;
					let callbackStreamRetryCount = 0;
					let bufferedAttemptParts = [];
					const openTextParts = /* @__PURE__ */ new Set();
					const openReasoningParts = /* @__PURE__ */ new Set();
					let enqueueStreamRetryAttemptBoundary = false;
					const shouldBufferToolParts = streamRetries > 0 || canRetryStreamViaOnError;
					const languageModelStream = new ReadableStream({
						async pull(controller) {
							const enqueueAttemptPart = (part) => {
								switch (part.type) {
									case "text-start":
										openTextParts.add(part.id);
										break;
									case "text-end":
										openTextParts.delete(part.id);
										break;
									case "reasoning-start":
										openReasoningParts.add(part.id);
										break;
									case "reasoning-end": openReasoningParts.delete(part.id);
								}
								controller.enqueue(part);
							};
							const flushBufferedAttemptParts = () => {
								for (const part of bufferedAttemptParts) enqueueAttemptPart(part);
								bufferedAttemptParts = [];
							};
							const closeOpenAttemptParts = () => {
								for (const id of openTextParts) controller.enqueue({
									type: "text-end",
									id
								});
								openTextParts.clear();
								for (const id of openReasoningParts) controller.enqueue({
									type: "reasoning-end",
									id
								});
								openReasoningParts.clear();
							};
							while (true) {
								let result;
								try {
									result = await languageModelStreamReader.read();
								} catch (error) {
									clearModelOutputTimeouts();
									throw error;
								}
								const { done, value } = result;
								if (enqueueStreamRetryAttemptBoundary) {
									controller.enqueue(createStreamRetryAttemptBoundaryPart({ warnings: !done && value.type === "model-call-start" ? value.warnings : [] }));
									enqueueStreamRetryAttemptBoundary = false;
								}
								if (done) {
									clearModelOutputTimeouts();
									flushBufferedAttemptParts();
									controller.close();
									return;
								}
								const isToolPart = value.type === "tool-input-start" || value.type === "tool-input-delta" || value.type === "tool-input-end" || value.type === "tool-call" || value.type === "tool-approval-request" || value.type === "tool-approval-response" || value.type === "tool-result" || value.type === "tool-error";
								if (value.type === "model-call-end") {
									clearModelOutputTimeouts();
									flushBufferedAttemptParts();
									enqueueAttemptPart(value);
									return;
								}
								if (isOutputChunk$1(value)) {
									clearFirstChunkTimeout();
									resetChunkTimeout();
								}
								if (shouldBufferToolParts && value.type !== "error" && value.type !== "ping" && (isToolPart || bufferedAttemptParts.length > 0)) {
									bufferedAttemptParts.push(value);
									continue;
								}
								if (value.type !== "error") {
									enqueueAttemptPart(value);
									return;
								}
								clearModelOutputTimeouts();
								await notify({
									event: { chunk: value },
									callbacks: onChunk
								});
								const error = wrapGatewayError(value.error);
								const isToolChoiceViolation = ToolChoiceViolationError.isInstance(error);
								let onErrorResult;
								try {
									onErrorResult = await onError({ error });
								} catch {}
								const callbackRequestedRetry = canRetryStreamViaOnError && typeof onErrorResult === "object" && onErrorResult != null && "retry" in onErrorResult && onErrorResult.retry === true;
								const automaticRetry = !isToolChoiceViolation && automaticStreamRetryCount < streamRetries;
								if (!automaticRetry && !(!isToolChoiceViolation && !automaticRetry && callbackRequestedRetry && callbackStreamRetryCount < 1)) {
									flushBufferedAttemptParts();
									errorsHandledForStreamRetry.add(value.error);
									controller.enqueue(value);
									return;
								}
								if (automaticRetry) automaticStreamRetryCount++;
								else callbackStreamRetryCount++;
								await languageModelStreamReader.cancel(error);
								bufferedAttemptParts = [];
								closeOpenAttemptParts();
								let retryLanguageModelCall;
								try {
									retryLanguageModelCall = await callLanguageModel();
								} catch (retryError) {
									controller.enqueue({
										type: "error",
										error: retryError
									});
									controller.close();
									return;
								}
								request = retryLanguageModelCall.request;
								response = retryLanguageModelCall.response;
								languageModelStreamReader = retryLanguageModelCall.stream.getReader();
								startFirstChunkTimeout();
								enqueueStreamRetryAttemptBoundary = true;
							}
						},
						cancel(reason) {
							clearModelOutputTimeouts();
							return languageModelStreamReader.cancel(reason);
						}
					});
					startFirstChunkTimeout();
					const streamAfterToolCallbackInvocation = invokeToolCallbacksFromStream({
						stream: languageModelStream,
						tools: stepExecutionTools,
						stepInputMessages: stepMessages,
						abortSignal,
						toolsContext
					});
					const runInTracingChannelSpanInStep = telemetryDispatcher.runInTracingChannelSpan == null ? void 0 : (options) => runInStepTracingChannelContext(() => telemetryDispatcher.runInTracingChannelSpan(options));
					const streamWithToolResults = executeToolsFromStream({
						stream: streamAfterToolCallbackInvocation,
						tools: stepExecutionTools,
						callId,
						messages: stepMessages,
						abortSignal,
						timeout,
						experimental_sandbox: stepSandbox,
						toolsContext,
						toolApproval,
						runtimeContext,
						toolApprovalSecret: experimental_toolApprovalSecret,
						generateId,
						onToolExecutionStart: filterNullable(onToolExecutionStart, telemetryDispatcher.onToolExecutionStart),
						onToolExecutionEnd: filterNullable(onToolExecutionEnd, telemetryDispatcher.onToolExecutionEnd),
						executeToolInTelemetryContext: telemetryDispatcher.executeTool,
						runInTracingChannelSpan: runInTracingChannelSpanInStep,
						toolCallConcurrency
					});
					const getStepRequest = () => ({
						...request,
						body: include.requestBody ? request?.body : void 0,
						messages: include.requestMessages ? cloneModelMessages(stepMessages) : void 0
					});
					recordedRequestMessages = getStepRequest().messages ?? [];
					const stepToolCalls = [];
					const stepToolOutputs = [];
					const stepToolApprovalResponses = [];
					let warnings;
					let stepFinishReason = "other";
					let stepRawFinishReason = void 0;
					let hasReceivedTerminalChunk = false;
					let hasReceivedOutputChunk = false;
					let stepUsage = createNullLanguageModelUsage();
					let stepProviderMetadata;
					let stepFirstChunk = true;
					const createModelCallPerformance = () => ({
						responseTimeMs: 0,
						effectiveOutputTokensPerSecond: 0,
						outputTokensPerSecond: void 0,
						inputTokensPerSecond: void 0,
						effectiveTotalTokensPerSecond: 0,
						timeToFirstOutputMs: void 0,
						timeBetweenOutputChunksMs: void 0
					});
					let modelCallPerformance = createModelCallPerformance();
					const toolExecutionMs = {};
					const createStepResponse = () => ({
						id: generateId(),
						timestamp: /* @__PURE__ */ new Date(),
						modelId: stepModel.modelId
					});
					let stepResponse = createStepResponse();
					const textPartIds = /* @__PURE__ */ new Map();
					const reasoningPartIds = /* @__PURE__ */ new Map();
					const enqueueStepPart = (controller, part) => {
						controller.enqueue(part);
					};
					self.addStream(streamWithToolResults.pipeThrough(new TransformStream({
						async transform(chunk, controller) {
							if (isStreamRetryAttemptBoundaryPart(chunk)) {
								warnings = chunk.warnings;
								stepFinishReason = "other";
								stepRawFinishReason = void 0;
								hasReceivedTerminalChunk = false;
								hasReceivedOutputChunk = false;
								stepUsage = createNullLanguageModelUsage();
								stepProviderMetadata = void 0;
								modelCallPerformance = createModelCallPerformance();
								stepResponse = createStepResponse();
								textPartIds.clear();
								reasoningPartIds.clear();
								controller.enqueue({ [streamRetryBoundarySymbol]: {
									request: getStepRequest(),
									warnings
								} });
								return;
							}
							if (chunk.type === "model-call-start") {
								warnings = chunk.warnings;
								return;
							}
							if (stepFirstChunk) {
								stepFirstChunk = false;
								enqueueStepPart(controller, {
									type: "start-step",
									request: getStepRequest(),
									warnings: warnings ?? []
								});
							}
							const chunkType = chunk.type;
							if (isOutputChunk$1(chunk)) hasReceivedOutputChunk = true;
							switch (chunkType) {
								case "file":
								case "custom":
								case "source":
								case "reasoning-file":
								case "tool-input-start":
								case "tool-input-end":
								case "tool-input-delta":
								case "tool-approval-request":
								case "ping":
								case "tool-output-denied":
									enqueueStepPart(controller, chunk);
									break;
								case "text-start": {
									const id = reserveTextPartId(chunk.id);
									textPartIds.set(chunk.id, id);
									enqueueStepPart(controller, {
										...chunk,
										id
									});
									break;
								}
								case "text-delta":
									if (chunk.text.length > 0 || chunk.providerMetadata != null) enqueueStepPart(controller, {
										...chunk,
										id: textPartIds.get(chunk.id) ?? chunk.id
									});
									break;
								case "text-end":
									enqueueStepPart(controller, {
										...chunk,
										id: textPartIds.get(chunk.id) ?? chunk.id
									});
									textPartIds.delete(chunk.id);
									break;
								case "reasoning-start": {
									const id = reserveReasoningPartId(chunk.id);
									reasoningPartIds.set(chunk.id, id);
									enqueueStepPart(controller, {
										...chunk,
										id
									});
									break;
								}
								case "reasoning-delta":
									enqueueStepPart(controller, {
										...chunk,
										id: reasoningPartIds.get(chunk.id) ?? chunk.id
									});
									break;
								case "reasoning-end":
									enqueueStepPart(controller, {
										...chunk,
										id: reasoningPartIds.get(chunk.id) ?? chunk.id
									});
									reasoningPartIds.delete(chunk.id);
									break;
								case "tool-call":
									enqueueStepPart(controller, chunk);
									stepToolCalls.push(chunk);
									break;
								case "tool-approval-response":
									enqueueStepPart(controller, chunk);
									stepToolApprovalResponses.push(chunk);
									break;
								case "tool-result":
									enqueueStepPart(controller, chunk);
									if (!chunk.preliminary) stepToolOutputs.push(chunk);
									break;
								case "tool-error":
									enqueueStepPart(controller, chunk);
									stepToolOutputs.push(chunk);
									break;
								case "tool-execution-end":
									toolExecutionMs[chunk.toolCallId] = chunk.toolExecutionMs;
									break;
								case "model-call-response-metadata":
									stepResponse = {
										id: chunk.id ?? stepResponse.id,
										timestamp: chunk.timestamp ?? stepResponse.timestamp,
										modelId: chunk.modelId ?? stepResponse.modelId
									};
									break;
								case "model-call-end":
									hasReceivedTerminalChunk = true;
									stepUsage = chunk.usage;
									stepFinishReason = chunk.finishReason;
									stepRawFinishReason = chunk.rawFinishReason;
									stepProviderMetadata = chunk.providerMetadata;
									modelCallPerformance = chunk.performance;
									break;
								case "error":
									hasReceivedTerminalChunk = true;
									enqueueStepPart(controller, chunk);
									stepFinishReason = "error";
									break;
								case "raw":
									if (include.rawChunks) enqueueStepPart(controller, chunk);
									break;
								default: throw new Error(`Unknown chunk type: ${chunkType}`);
							}
						},
						async flush(controller) {
							if (!hasReceivedTerminalChunk && !hasReceivedOutputChunk) {
								enqueueStepPart(controller, {
									type: "error",
									error: new NoOutputGeneratedError({ message: "No output generated. The model stream ended without a finish chunk." })
								});
								cleanupStepTimeouts();
								self.closeStream();
								return;
							}
							const stepTimeMs = now() - stepStartTimestampMs;
							const finishStepPart = {
								type: "finish-step",
								finishReason: stepFinishReason,
								rawFinishReason: stepRawFinishReason,
								usage: stepUsage,
								performance: {
									stepTimeMs,
									toolExecutionMs,
									...modelCallPerformance
								},
								providerMetadata: stepProviderMetadata,
								response: {
									...stepResponse,
									headers: response?.headers
								}
							};
							enqueueStepPart(controller, finishStepPart);
							const combinedUsage = addLanguageModelUsage(usage, stepUsage);
							await stepFinish.promise;
							const clientToolCalls = stepToolCalls.filter((toolCall) => toolCall.providerExecuted !== true);
							const clientToolOutputs = stepToolOutputs.filter((toolOutput) => toolOutput.providerExecuted !== true);
							const deniedToolApprovalResponses = stepToolApprovalResponses.filter((toolApprovalResponse) => toolApprovalResponse.approved === false);
							for (const toolCall of stepToolCalls) {
								if (toolCall.providerExecuted !== true) continue;
								const tool = getOwn(stepExecutionTools, toolCall.toolName);
								if (tool?.type === "provider" && tool.supportsDeferredResults) {
									if (!stepToolOutputs.some((output) => (output.type === "tool-result" || output.type === "tool-error") && output.toolCallId === toolCall.toolCallId)) pendingDeferredToolCalls.set(toolCall.toolCallId, { toolName: toolCall.toolName });
								}
							}
							for (const output of stepToolOutputs) if (output.type === "tool-result" || output.type === "tool-error") pendingDeferredToolCalls.delete(output.toolCallId);
							cleanupStepTimeouts();
							let steeringEndReason = "finished";
							const shouldStartNextStep = async () => {
								if (stepFinishReason === "interrupted") return false;
								if (clientToolCalls.length !== clientToolOutputs.length + deniedToolApprovalResponses.length) {
									steeringEndReason = "waiting-for-tool-results";
									return false;
								}
								if (clientToolCalls.length === 0 && pendingDeferredToolCalls.size === 0) {
									const isTruncated = stepFinishReason === "length" || stepFinishReason === "content-filter";
									if (!steeringRun?.hasPendingMessages() && (isTruncated || !steeringRun?.promoteQueuedMessage())) return false;
									if (stepFinishReason === "error") {
										steeringEndReason = "error";
										return false;
									}
								}
								if (await isStopConditionMet({
									stopConditions,
									steps: recordedSteps
								})) {
									steeringEndReason = "stop-condition";
									return false;
								}
								return true;
							};
							if (await shouldStartNextStep()) try {
								await runInStreamTextTracingChannelContext(() => streamStep({
									currentStep: currentStep + 1,
									usage: combinedUsage
								}));
							} catch (error) {
								steeringRun?.end("error");
								enqueueStepPart(controller, {
									type: "error",
									error
								});
								self.closeStream();
							}
							else {
								steeringRun?.end(steeringEndReason);
								enqueueStepPart(controller, {
									type: "finish",
									finishReason: stepFinishReason,
									rawFinishReason: stepRawFinishReason,
									totalUsage: combinedUsage
								});
								self.closeStream();
							}
						}
					})), {
						onError: cleanupStepTimeouts,
						onCancel: cleanupStepTimeouts
					});
				} catch (error) {
					cleanupStepTimeouts();
					throw error;
				}
			}
			await runInStreamTextTracingChannelContext(() => streamStep({
				currentStep: 0,
				usage: createNullLanguageModelUsage()
			}));
		})().catch(async (error) => {
			steeringRun?.end(abortSignal?.aborted ? "aborted" : "error");
			await notifyStepError(wrapGatewayError(error));
			await telemetryDispatcher.onError?.({
				callId,
				error
			});
			self._initialResponseMessages.reject(error);
			markPromiseAsHandled$1(self._initialResponseMessages.promise);
			self.addStream(new ReadableStream({ start(controller) {
				controller.enqueue({
					type: "error",
					error
				});
				controller.close();
			} }));
			self.closeStream();
		});
	}
	get steps() {
		if (this.retention.replay) this.consumeStream();
		return this._steps.promise;
	}
	get finalStep() {
		return this.steps.then((steps) => steps.at(-1));
	}
	get content() {
		return this.steps.then((steps) => steps.flatMap((step) => step.content));
	}
	get warnings() {
		return this.steps.then((steps) => steps.flatMap((step) => step.warnings ?? []));
	}
	get providerMetadata() {
		return this.finalStep.then((step) => step.providerMetadata);
	}
	get text() {
		return this.finalStep.then((step) => step.text);
	}
	get reasoningText() {
		return this.finalStep.then((step) => step.reasoningText);
	}
	get reasoning() {
		return this.finalStep.then((step) => convertToReasoningOutputs(step.reasoning));
	}
	get sources() {
		return this.steps.then((steps) => steps.flatMap((step) => step.sources));
	}
	get files() {
		return this.steps.then((steps) => steps.flatMap((step) => step.files));
	}
	get toolCalls() {
		return this.steps.then((steps) => steps.flatMap((step) => step.toolCalls));
	}
	get staticToolCalls() {
		return this.steps.then((steps) => steps.flatMap((step) => step.staticToolCalls));
	}
	get dynamicToolCalls() {
		return this.steps.then((steps) => steps.flatMap((step) => step.dynamicToolCalls));
	}
	get toolResults() {
		return this.steps.then((steps) => steps.flatMap((step) => step.toolResults));
	}
	get staticToolResults() {
		return this.steps.then((steps) => steps.flatMap((step) => step.staticToolResults));
	}
	get dynamicToolResults() {
		return this.steps.then((steps) => steps.flatMap((step) => step.dynamicToolResults));
	}
	get usage() {
		return this.totalUsage;
	}
	get request() {
		return this.finalStep.then((step) => step.request);
	}
	get response() {
		return this.finalStep.then((step) => step.response);
	}
	get responseMessages() {
		return Promise.all([this._initialResponseMessages.promise, this.steps]).then(([initialResponseMessages, steps]) => [...initialResponseMessages, ...steps.flatMap((step) => step.response.messages)]);
	}
	get totalUsage() {
		if (this.retention.replay) this.consumeStream();
		return this._totalUsage.promise;
	}
	get finishReason() {
		if (this.retention.replay) this.consumeStream();
		return this._finishReason.promise;
	}
	get rawFinishReason() {
		if (this.retention.replay) this.consumeStream();
		return this._rawFinishReason.promise;
	}
	/**
	* Split out a new stream from the original stream.
	* The original stream is replaced to allow for further splitting,
	* since we do not know how many times the stream will be split.
	*
	* Note: this leads to buffering the stream content on the server.
	* However, the LLM results are expected to be small enough to not cause issues.
	*/
	teeStream() {
		if (!this.retention.replay) {
			if (this.streamClaimed) throw new AISDKError$1({
				name: "AI_StreamAlreadyConsumedError",
				message: "This result supports one stream consumer. Choose one stream projection or response helper."
			});
			this.streamClaimed = true;
			const reader = this.baseStream.getReader();
			const rejectResults = (error) => this.rejectResultPromises(error);
			return new ReadableStream({
				async pull(controller) {
					try {
						const { done, value } = await reader.read();
						if (done) {
							reader.releaseLock();
							controller.close();
						} else controller.enqueue(value);
					} catch (error) {
						rejectResults(error);
						reader.releaseLock();
						controller.error(error);
					}
				},
				async cancel(reason) {
					rejectResults(reason ?? new DOMException("The stream was cancelled.", "AbortError"));
					try {
						await reader.cancel(reason);
					} finally {
						reader.releaseLock();
					}
				}
			}, { highWaterMark: 0 });
		}
		const [stream1, stream2] = this.baseStream.tee();
		this.baseStream = stream2;
		return stream1;
	}
	get textStream() {
		return this.asIterableStream(toTextStream({ stream: this.stream }));
	}
	asIterableStream(stream) {
		return this.retention.replay ? createAsyncIterableStream(stream) : asAsyncIterableStream(stream);
	}
	get stream() {
		return this.asIterableStream(this.teeStream().pipeThrough(new TransformStream({ transform({ part }, controller) {
			controller.enqueue(part);
		} })));
	}
	get fullStream() {
		return this.stream;
	}
	rejectResultPromises(error) {
		this.rejectResultPromise({
			delayedPromise: this._finishReason,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._rawFinishReason,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._totalUsage,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._steps,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._initialResponseMessages,
			error
		});
	}
	rejectResultPromise({ delayedPromise, error }) {
		if (delayedPromise.isPending()) {
			delayedPromise.reject(error);
			markPromiseAsHandled$1(delayedPromise.promise);
		}
	}
	async consumeStream(options) {
		const stream = this.stream;
		try {
			await consumeStream({
				stream,
				onError: (error) => {
					this.rejectResultPromises(error);
					options?.onError?.(error);
				}
			});
		} catch (error) {
			this.rejectResultPromises(error);
			options?.onError?.(error);
		}
	}
	get experimental_partialOutputStream() {
		return this.partialOutputStream;
	}
	get partialOutputStream() {
		if (!this.retention.replay && this.outputSpecification == null) throw new UnsupportedFunctionalityError$1({ functionality: "partialOutputStream without an explicit output specification with experimental_streamTextLowMemory" });
		return this.asIterableStream(this.teeStream().pipeThrough(new TransformStream({ transform({ partialOutput }, controller) {
			if (partialOutput !== void 0) controller.enqueue(partialOutput);
		} })));
	}
	get elementStream() {
		const transform = this.outputSpecification?.createElementStreamTransform();
		if (transform == null) throw new UnsupportedFunctionalityError$1({ functionality: `element streams in ${this.outputSpecification?.name ?? "text"} mode` });
		return this.asIterableStream(this.teeStream().pipeThrough(transform));
	}
	getOutputPromise() {
		if (this.outputPromise == null) this.outputPromise = this.finalStep.then((step) => this.parseOutput(step));
		return this.outputPromise;
	}
	parseOutput(step) {
		return (this.outputSpecification ?? text()).parseCompleteOutput({ text: step.text }, {
			response: step.response,
			usage: step.usage,
			finishReason: step.finishReason
		});
	}
	get output() {
		return this.getOutputPromise();
	}
	toUIMessageStream({ originalMessages, generateMessageId, onStepEnd, onStepFinish, onEnd, onFinish, messageMetadata, sendReasoning, sendSources, sendStart, sendFinish, onError, redactToolErrors } = {}) {
		return createAsyncIterableStream(toUIMessageStream({
			stream: this.stream,
			tools: this.tools,
			originalMessages,
			generateMessageId,
			onStepEnd: onStepEnd ?? onStepFinish,
			onEnd: onEnd ?? onFinish,
			messageMetadata,
			sendReasoning,
			sendSources,
			sendStart,
			sendFinish,
			onError,
			redactToolErrors
		}));
	}
	pipeUIMessageStreamToResponse(response, { originalMessages, generateMessageId, onStepEnd, onStepFinish, onEnd, onFinish, messageMetadata, sendReasoning, sendSources, sendFinish, sendStart, onError, redactToolErrors, ...init } = {}) {
		return pipeUIMessageStreamToResponse({
			response,
			stream: this.toUIMessageStream({
				originalMessages,
				generateMessageId,
				onStepEnd: onStepEnd ?? onStepFinish,
				onEnd: onEnd ?? onFinish,
				messageMetadata,
				sendReasoning,
				sendSources,
				sendFinish,
				sendStart,
				onError,
				redactToolErrors
			}),
			...init
		});
	}
	pipeTextStreamToResponse(response, init) {
		return pipeTextStreamToResponse({
			response,
			stream: this.textStream,
			...init
		});
	}
	toUIMessageStreamResponse({ originalMessages, generateMessageId, onStepEnd, onStepFinish, onEnd, onFinish, messageMetadata, sendReasoning, sendSources, sendFinish, sendStart, onError, redactToolErrors, ...init } = {}) {
		return createUIMessageStreamResponse({
			stream: this.toUIMessageStream({
				originalMessages,
				generateMessageId,
				onStepEnd: onStepEnd ?? onStepFinish,
				onEnd: onEnd ?? onFinish,
				messageMetadata,
				sendReasoning,
				sendSources,
				sendFinish,
				sendStart,
				onError,
				redactToolErrors
			}),
			...init
		});
	}
	toTextStreamResponse(init) {
		return createTextStreamResponse({
			stream: this.textStream,
			...init
		});
	}
};
//#endregion
//#region src/util/is-caused-by-abort.ts
/**
* Checks if the error is an abort or timeout error, or is caused by one.
* Providers can wrap the abort or timeout error, e.g. as the cause of an
* API call error.
*/
function isCausedByAbort(error) {
	let current = error;
	for (let depth = 0; current != null && depth < 5; depth++) {
		if (isAbortError(current)) return true;
		current = current.cause;
	}
	return false;
}
//#endregion
//#region src/agent/default-stop-condition.ts
/**
* Logs the warning for the default stopWhen condition.
*/
function logDefaultStopConditionWarning({ stepCount, provider, modelId }) {
	logWarnings({
		provider,
		model: modelId,
		warnings: [{
			type: "other",
			message: `The tool loop stopped because it reached the default stopWhen condition, isStepCount(${stepCount}). To allow more steps, set stopWhen to isStepCount(...) with a higher limit or provide a custom stop condition. Learn more: https://ai-sdk.dev/docs/agents/loop-control`
		}]
	});
}
/**
* Stop conditions are only evaluated when the tool loop can otherwise continue,
* so logging here avoids warning when a call finishes naturally at the limit.
*/
function createDefaultStopCondition(stepCount) {
	return ({ steps }) => {
		if (steps.length !== stepCount) return false;
		const { provider, modelId } = steps[steps.length - 1].model;
		logDefaultStopConditionWarning({
			stepCount,
			provider,
			modelId
		});
		return true;
	};
}
//#endregion
//#region src/agent/tool-loop-agent.ts
/**
* A tool loop agent is an agent that runs tools in a loop. In each step,
* it calls the LLM, and if there are tool calls, it executes the tools
* and calls the LLM again in a new step with the tool results.
*
* The loop continues until:
* - A finish reasoning other than tool-calls is returned, or
* - A tool that is invoked does not have an execute function, or
* - A tool call needs approval via `toolApproval` or tool-level `needsApproval`, or
* - A stop condition is met (default stop condition is isStepCount(20))
*/
var ToolLoopAgent = class {
	constructor(settings) {
		this.version = "agent-v1";
		const { onFinish, onEnd = onFinish } = settings;
		this.settings = {
			...settings,
			onEnd
		};
	}
	/**
	* The id of the agent.
	*/
	get id() {
		return this.settings.id;
	}
	/**
	* The tools that the agent can use.
	*/
	get tools() {
		return this.settings.tools;
	}
	async prepareCall(options) {
		if (this.settings.callOptionsSchema != null && options.options !== void 0) {
			const validatedOptions = await validateTypes({
				value: options.options,
				schema: this.settings.callOptionsSchema,
				context: { field: "options" }
			});
			options = {
				...options,
				options: validatedOptions
			};
		}
		const { onStart: _settingsStableOnStart, experimental_onStart: _settingsExperimentalOnStart, onStepStart: _settingsStableOnStepStart, experimental_onStepStart: _settingsExperimentalOnStepStart, onToolExecutionStart: _settingsOnToolExecutionStart, onToolExecutionEnd: _settingsOnToolExecutionEnd, onStepEnd: _settingsOnStepEnd, onStepFinish: _settingsOnStepFinish, onError: _settingsOnError, onAbort: _settingsOnAbort, onFinish: _settingsOnFinish, onEnd: _settingsOnEnd, ...settingsWithoutCallbacks } = this.settings;
		const baseCallArgs = {
			...settingsWithoutCallbacks,
			stopWhen: this.settings.stopWhen ?? createDefaultStopCondition(20),
			...options
		};
		const { instructions, allowSystemInMessages, messages, prompt, runtimeContext, ...callArgs } = await this.settings.prepareCall?.(baseCallArgs) ?? baseCallArgs;
		const promptArgs = {
			instructions,
			allowSystemInMessages,
			messages,
			prompt
		};
		if (runtimeContext === void 0) return {
			...callArgs,
			...promptArgs
		};
		return {
			...callArgs,
			runtimeContext,
			...promptArgs
		};
	}
	/**
	* Tags outgoing requests so usage can be attributed to ToolLoopAgent. Chains
	* with the `ai/<version>` and `ai-sdk/<provider>/<version>` suffixes added
	* downstream by generateText/streamText and the provider.
	*/
	agentHeaders(preparedCall) {
		return withUserAgentSuffix(preparedCall.headers ?? {}, "ai-sdk-agent/tool-loop");
	}
	/**
	* Generates an output from the agent (non-streaming).
	*/
	async generate({ abortSignal, timeout, experimental_sandbox: sandbox, experimental_steering: steering, onStart, experimental_onStart, onStepStart, experimental_onStepStart, onToolExecutionStart, onToolExecutionEnd, onStepEnd, onStepFinish, onFinish, onEnd = onFinish, ...options }) {
		const generate = generateText;
		const preparedCall = await this.prepareCall({
			...options,
			experimental_sandbox: sandbox
		});
		const callbackArgs = {
			abortSignal,
			timeout: timeout ?? preparedCall.timeout,
			experimental_sandbox: sandbox,
			experimental_steering: steering,
			onStart: mergeCallbacks(this.settings.onStart ?? this.settings.experimental_onStart, onStart ?? experimental_onStart),
			onStepStart: mergeCallbacks(this.settings.onStepStart ?? this.settings.experimental_onStepStart, onStepStart ?? experimental_onStepStart),
			onToolExecutionStart: mergeCallbacks(this.settings.onToolExecutionStart, onToolExecutionStart),
			onToolExecutionEnd: mergeCallbacks(this.settings.onToolExecutionEnd, onToolExecutionEnd),
			onStepEnd: mergeCallbacks(this.settings.onStepEnd ?? this.settings.onStepFinish, onStepEnd ?? onStepFinish),
			onEnd: mergeCallbacks(this.settings.onEnd, onEnd)
		};
		try {
			return await generate({
				...preparedCall,
				...callbackArgs,
				headers: this.agentHeaders(preparedCall)
			});
		} catch (error) {
			if (!isCausedByAbort(error) && !abortSignal?.aborted) await notify({
				event: { error },
				callbacks: this.settings.onError
			});
			throw error;
		}
	}
	/**
	* Streams an output from the agent (streaming).
	*/
	async stream({ abortSignal, timeout, experimental_sandbox: sandbox, experimental_steering: steering, experimental_transform, onStart, experimental_onStart, onStepStart, experimental_onStepStart, onToolExecutionStart, onToolExecutionEnd, onStepEnd, onStepFinish, onFinish, onEnd = onFinish, ...options }) {
		const stream = streamText;
		const preparedCall = await this.prepareCall({
			...options,
			experimental_sandbox: sandbox
		});
		const callbackArgs = {
			abortSignal,
			timeout: timeout ?? preparedCall.timeout,
			experimental_sandbox: sandbox,
			experimental_steering: steering,
			experimental_transform,
			onStart: mergeCallbacks(this.settings.onStart ?? this.settings.experimental_onStart, onStart ?? experimental_onStart),
			onStepStart: mergeCallbacks(this.settings.onStepStart ?? this.settings.experimental_onStepStart, onStepStart ?? experimental_onStepStart),
			onToolExecutionStart: mergeCallbacks(this.settings.onToolExecutionStart, onToolExecutionStart),
			onToolExecutionEnd: mergeCallbacks(this.settings.onToolExecutionEnd, onToolExecutionEnd),
			onStepEnd: mergeCallbacks(this.settings.onStepEnd ?? this.settings.onStepFinish, onStepEnd ?? onStepFinish),
			onEnd: mergeCallbacks(this.settings.onEnd, onEnd),
			onError: this.settings.onError,
			onAbort: this.settings.onAbort
		};
		return await stream({
			...preparedCall,
			...callbackArgs,
			headers: this.agentHeaders(preparedCall)
		});
	}
};
//#endregion
//#region src/ui-message-stream/create-ui-message-stream.ts
/**
* Creates a UI message stream that can be used to send messages to the client.
*
* @param options.execute - A function that is called with a writer to write UI message chunks to the stream.
* @param options.onError - A function that extracts an error message from an error. Defaults to `() => 'An error occurred.'` so server-side error details are not leaked to the client; supply your own to surface richer messages.
* @param options.originalMessages - The original messages. If provided, persistence mode is assumed
*   and a message ID is provided for the response message.
* @param options.onStepEnd - A callback that is called when each step ends. Useful for persisting intermediate messages.
* @param options.onStepFinish - Deprecated alias for `onStepEnd`.
* @param options.onEnd - A callback that is called when the stream ends.
* @param options.onFinish - Deprecated alias for `onEnd`.
* @param options.generateId - A function that generates a unique ID. Defaults to the built-in ID generator.
*
* @returns A `ReadableStream` of UI message chunks.
*/
function createUIMessageStream({ execute, onError = () => "An error occurred.", originalMessages, onStepEnd, onStepFinish, onEnd, onFinish, generateId = generateId$1 }) {
	let controller;
	const ongoingStreamPromises = [];
	const activeReaders = /* @__PURE__ */ new Set();
	let isCancelled = false;
	let cancelReason;
	let outcome = { status: "unknown" };
	const stream = new ReadableStream({
		start(controllerArg) {
			controller = controllerArg;
		},
		async cancel(reason) {
			isCancelled = true;
			cancelReason = reason;
			await Promise.all(Array.from(activeReaders, (reader) => reader.cancel(reason)));
		}
	});
	function safeEnqueue(data) {
		try {
			controller.enqueue(data);
		} catch {}
	}
	function setOutcome(newOutcome) {
		if (outcome.status === "unknown" && newOutcome.status !== "unknown") outcome = newOutcome;
	}
	function failOutcome(error) {
		outcome = {
			status: "failed",
			error
		};
	}
	function safeError(error) {
		try {
			controller.error(error);
		} catch {}
	}
	function handleError(error) {
		failOutcome(error);
		let errorText;
		try {
			errorText = onError(error);
		} catch (onErrorError) {
			failOutcome(onErrorError);
			safeError(onErrorError);
			return;
		}
		safeEnqueue({
			type: "error",
			errorText
		});
	}
	try {
		const result = execute({ writer: {
			write(part) {
				safeEnqueue(part);
			},
			merge(streamArg) {
				if (isCancelled) {
					streamArg.cancel(cancelReason).catch(() => {});
					return;
				}
				ongoingStreamPromises.push((async () => {
					const reader = streamArg.getReader();
					activeReaders.add(reader);
					try {
						while (true) {
							const { done, value } = await reader.read();
							if (done) break;
							safeEnqueue(value);
						}
					} finally {
						activeReaders.delete(reader);
						reader.releaseLock();
					}
				})().catch((error) => {
					handleError(error);
				}));
			},
			setOutcome,
			onError
		} });
		if (result) ongoingStreamPromises.push(result.catch((error) => {
			handleError(error);
		}));
	} catch (error) {
		handleError(error);
	}
	(async () => {
		while (ongoingStreamPromises.length > 0) await ongoingStreamPromises.shift();
	})().finally(() => {
		try {
			controller.close();
		} catch {}
	});
	return handleUIMessageStreamFinish({
		stream,
		messageId: generateId(),
		originalMessages,
		onStepEnd: onStepEnd ?? onStepFinish,
		onEnd: onEnd ?? onFinish,
		onError,
		getOutcome: () => outcome
	});
}
//#endregion
//#region src/ui-message-stream/read-ui-message-stream.ts
function createUIMessageSnapshot(message) {
	const textByPartIndex = /* @__PURE__ */ new Map();
	const messageWithoutText = {
		...message,
		parts: message.parts.map((part, index) => {
			if (part.type === "text" || part.type === "reasoning") {
				textByPartIndex.set(index, part.text);
				return {
					...part,
					text: ""
				};
			}
			return part;
		})
	};
	const snapshot = structuredClone(messageWithoutText);
	for (const [index, text] of textByPartIndex) {
		const part = snapshot.parts[index];
		if (part.type === "text" || part.type === "reasoning") part.text = text;
	}
	return snapshot;
}
/**
* Transforms a stream of `UIMessageChunk`s into an `AsyncIterableStream` of `UIMessage`s.
*
* @param options.message - The last assistant message to use as a starting point when the conversation is resumed. Otherwise undefined.
* @param options.stream - The stream of `UIMessageChunk`s to read.
* @param options.terminateOnError - Whether to terminate the stream if an error occurs.
* @param options.onError - A function that is called when an error occurs.
*
* @returns An `AsyncIterableStream` of `UIMessage`s. Each stream part is a different state of the same message
* as it is being completed.
*/
function readUIMessageStream({ message, stream, onError, terminateOnError = false }) {
	let controller;
	let hasErrored = false;
	let isCancelled = false;
	const abortController = new AbortController();
	const outputStream = new ReadableStream({
		start(controllerParam) {
			controller = controllerParam;
		},
		cancel() {
			isCancelled = true;
			abortController.abort();
		}
	});
	const state = createStreamingUIMessageState({
		messageId: message?.id ?? "",
		lastMessage: message
	});
	const handleError = (error) => {
		onError?.(error);
		if (!hasErrored && terminateOnError) {
			hasErrored = true;
			controller?.error(error);
		}
	};
	consumeStream({
		stream: processUIMessageStream({
			stream,
			resetStateOnMessageIdChange: true,
			runUpdateMessageJob(job) {
				return job({
					state,
					write: () => {
						if (!isCancelled) controller?.enqueue(createUIMessageSnapshot(state.message));
					}
				});
			},
			onError: handleError
		}),
		onError: handleError,
		abortSignal: abortController.signal
	}).finally(() => {
		if (!hasErrored && !isCancelled) controller?.close();
	});
	return createAsyncIterableStream(outputStream);
}
//#endregion
//#region src/ui/unavailable-tool.ts
function markToolPartAsUnavailable(part) {
	part.dynamic = false;
	return part;
}
function isToolPartFromUnavailableTool(part) {
	return part.type === "dynamic-tool" && part.dynamic === false;
}
//#endregion
//#region src/ui/warn-if-ui-message-has-deprecated-raw-input.ts
const rawInputDeprecationWarning = {
	type: "deprecated",
	setting: "rawInput in output-error UI message parts",
	message: "Use the \"input\" field instead. The \"rawInput\" field will be removed in the next major version."
};
function warnIfUIMessageHasDeprecatedRawInput(messages) {
	if (messages.some((message) => message.parts.some((part) => part != null && typeof part === "object" && "type" in part && typeof part.type === "string" && (part.type === "dynamic-tool" || part.type.startsWith("tool-")) && "state" in part && part.state === "output-error" && Object.prototype.hasOwnProperty.call(part, "rawInput") && "rawInput" in part && part.rawInput !== void 0))) logWarnings({ warnings: [rawInputDeprecationWarning] });
}
//#endregion
//#region src/ui/convert-to-model-messages.ts
/**
* Converts an array of UI messages from useChat into an array of ModelMessages that can be used
* with the AI functions (e.g. `streamText`, `generateText`).
*
* @param messages - The UI messages to convert.
* @param options.tools - The tools to use.
* @param options.ignoreIncompleteToolCalls - Whether to ignore incomplete tool calls. Default is `false`.
* @param options.convertDataPart - Optional function to convert data parts to text or file model message parts. Returns `undefined` if the part should be ignored.
*
* @returns An array of ModelMessages.
*/
async function convertToModelMessages(messages, options) {
	const modelMessages = [];
	warnIfUIMessageHasDeprecatedRawInput(messages);
	const lastUserMessageIndex = messages.reduce((lastIndex, message, index) => message.role === "user" ? index : lastIndex, -1);
	if (options?.ignoreIncompleteToolCalls || lastUserMessageIndex > 0) messages = messages.map((message, messageIndex) => ({
		...message,
		parts: message.parts.filter((part) => !isToolUIPart(part) || (part.state !== "approval-requested" || messageIndex >= lastUserMessageIndex) && (!options?.ignoreIncompleteToolCalls || part.state === "approval-responded" || part.state === "output-available" && part.preliminary !== true || part.state === "output-error" || part.state === "output-denied"))
	}));
	async function createModelOutput({ toolPart, toolName, output, errorMode }) {
		const tool = getOwn(options?.tools, toolName);
		if (errorMode === "none" && tool == null && isToolPartFromUnavailableTool(toolPart)) return {
			type: "text",
			value: "Tool output omitted because the tool is no longer available."
		};
		return createToolModelOutput({
			toolCallId: toolPart.toolCallId,
			input: toolPart.input,
			output,
			tool,
			errorMode
		});
	}
	for (const message of messages) switch (message.role) {
		case "system": {
			const textParts = message.parts.filter((part) => part.type === "text");
			const providerMetadata = textParts.reduce((acc, part) => {
				if (part.providerMetadata != null) return {
					...acc,
					...part.providerMetadata
				};
				return acc;
			}, {});
			modelMessages.push({
				role: "system",
				content: textParts.map((part) => part.text).join(""),
				...Object.keys(providerMetadata).length > 0 ? { providerOptions: providerMetadata } : {}
			});
			break;
		}
		case "user":
			modelMessages.push({
				role: "user",
				content: message.parts.map((part) => {
					if (isTextUIPart(part) || isFileUIPart(part)) return convertUserContentUIPart(part);
					if (isDataUIPart(part)) return options?.convertDataPart?.(part);
				}).filter(isNonNullable)
			});
			break;
		case "assistant":
			if (message.parts != null) {
				let block = [];
				async function processBlock() {
					if (block.length === 0) return;
					const content = [];
					for (const part of block) if (isTextUIPart(part)) content.push({
						type: "text",
						text: part.text,
						...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
					});
					else if (isCustomContentUIPart(part)) content.push({
						type: "custom",
						kind: part.kind,
						...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
					});
					else if (isFileUIPart(part)) content.push({
						type: "file",
						mediaType: part.mediaType,
						filename: part.filename,
						data: part.providerReference != null ? {
							type: "reference",
							reference: part.providerReference
						} : {
							type: "url",
							url: new URL(part.url)
						},
						...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
					});
					else if (isReasoningFileUIPart(part)) content.push({
						type: "reasoning-file",
						data: {
							type: "url",
							url: new URL(part.url)
						},
						mediaType: part.mediaType,
						providerOptions: part.providerMetadata
					});
					else if (isReasoningUIPart(part)) content.push({
						type: "reasoning",
						text: part.text,
						providerOptions: part.providerMetadata
					});
					else if (isToolUIPart(part)) {
						const toolName = getToolName(part);
						if (part.state !== "input-streaming") {
							const callProviderMetadata = part.callProviderMetadata ?? (part.state === "output-error" ? part.resultProviderMetadata : void 0);
							content.push({
								type: "tool-call",
								toolCallId: part.toolCallId,
								toolName,
								input: part.state === "output-error" ? part.input ?? ("rawInput" in part ? part.rawInput : void 0) : part.input,
								providerExecuted: part.providerExecuted,
								...callProviderMetadata != null ? { providerOptions: callProviderMetadata } : {}
							});
							if (part.approval != null) content.push({
								type: "tool-approval-request",
								approvalId: part.approval.id,
								toolCallId: part.toolCallId,
								isAutomatic: part.approval.isAutomatic,
								...part.approval.requestReason != null ? { reason: part.approval.requestReason } : {},
								...Object.prototype.hasOwnProperty.call(part.approval, "inputSchemaInput") ? { inputSchemaInput: part.approval.inputSchemaInput } : {},
								...part.approval.signature != null ? { signature: part.approval.signature } : {}
							});
							if (part.providerExecuted === true && part.state !== "approval-responded" && (part.state === "output-available" || part.state === "output-error")) {
								const resultProviderMetadata = part.resultProviderMetadata ?? part.callProviderMetadata;
								content.push({
									type: "tool-result",
									toolCallId: part.toolCallId,
									toolName,
									output: await createModelOutput({
										toolPart: part,
										toolName,
										output: part.state === "output-error" ? part.errorText : part.output,
										errorMode: part.state === "output-error" ? "json" : "none"
									}),
									...resultProviderMetadata != null ? { providerOptions: resultProviderMetadata } : {}
								});
							}
						}
					} else if (isDataUIPart(part)) {
						const dataPart = options?.convertDataPart?.(part);
						if (dataPart != null) content.push(dataPart);
					} else throw new Error(`Unsupported part: ${part}`);
					if (content.length > 0) modelMessages.push({
						role: "assistant",
						content
					});
					const toolParts = block.filter((part) => isToolUIPart(part) && (part.providerExecuted !== true || part.approval?.approved != null));
					if (toolParts.length > 0) {
						const content = [];
						for (const toolPart of toolParts) {
							if (toolPart.approval?.approved != null) content.push({
								type: "tool-approval-response",
								approvalId: toolPart.approval.id,
								approved: toolPart.approval.approved,
								reason: toolPart.approval.reason,
								providerExecuted: toolPart.providerExecuted
							});
							if (toolPart.state === "approval-responded" && toolPart.approval?.approved === false) content.push({
								type: "tool-result",
								toolCallId: toolPart.toolCallId,
								toolName: getToolName(toolPart),
								output: {
									type: "execution-denied",
									reason: toolPart.approval.reason
								},
								...toolPart.callProviderMetadata != null ? { providerOptions: toolPart.callProviderMetadata } : {}
							});
							if (toolPart.providerExecuted === true) continue;
							switch (toolPart.state) {
								case "output-denied":
									content.push({
										type: "tool-result",
										toolCallId: toolPart.toolCallId,
										toolName: getToolName(toolPart),
										output: {
											type: "error-text",
											value: toolPart.approval?.reason ?? "Tool call execution denied."
										},
										...toolPart.callProviderMetadata != null ? { providerOptions: toolPart.callProviderMetadata } : {}
									});
									break;
								case "output-error":
								case "output-available": {
									const toolName = getToolName(toolPart);
									content.push({
										type: "tool-result",
										toolCallId: toolPart.toolCallId,
										toolName,
										output: await createModelOutput({
											toolPart,
											toolName,
											output: toolPart.state === "output-error" ? toolPart.errorText : toolPart.output,
											errorMode: toolPart.state === "output-error" ? "text" : "none"
										}),
										...toolPart.callProviderMetadata != null ? { providerOptions: toolPart.callProviderMetadata } : {}
									});
									break;
								}
							}
						}
						if (content.length > 0) modelMessages.push({
							role: "tool",
							content
						});
					}
					block = [];
				}
				for (const part of message.parts) if (isCustomContentUIPart(part) || isTextUIPart(part) || isReasoningUIPart(part) || isReasoningFileUIPart(part) || isFileUIPart(part) || isToolUIPart(part) || isDataUIPart(part)) block.push(part);
				else if (part.type === "step-start") await processBlock();
				else if (part.type === "steering-message") {
					await processBlock();
					modelMessages.push({
						role: "user",
						content: part.parts.map(convertUserContentUIPart)
					});
				}
				await processBlock();
				break;
			}
			break;
		default: {
			const _exhaustiveCheck = message.role;
			throw new MessageConversionError({
				originalMessage: message,
				message: `Unsupported role: ${_exhaustiveCheck}`
			});
		}
	}
	return modelMessages;
}
function convertUserContentUIPart(part) {
	if (part.type === "text") return {
		type: "text",
		text: part.text,
		...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
	};
	return {
		type: "file",
		mediaType: part.mediaType,
		filename: part.filename,
		data: part.providerReference != null ? {
			type: "reference",
			reference: part.providerReference
		} : {
			type: "url",
			url: new URL(part.url)
		},
		...part.providerMetadata != null ? { providerOptions: part.providerMetadata } : {}
	};
}
//#endregion
//#region src/ui/validate-ui-messages.ts
/**
* Returns the path to the first value that can never be part of a JSON value
* (a non-finite number, bigint, symbol, or function), if there is one.
*/
function findInvalidJsonValuePath(value, path = [], visited = /* @__PURE__ */ new WeakSet()) {
	switch (typeof value) {
		case "number": return Number.isFinite(value) ? void 0 : [...path];
		case "bigint":
		case "symbol":
		case "function": return [...path];
		case "object": {
			if (value === null || visited.has(value)) return;
			visited.add(value);
			const keys = Array.isArray(value) ? value.keys() : Object.keys(value);
			for (const key of keys) {
				if (key === "__proto__") continue;
				path.push(key);
				const invalidPath = findInvalidJsonValuePath(value[key], path, visited);
				if (invalidPath != null) return invalidPath;
				path.pop();
			}
			return;
		}
		default: return;
	}
}
/**
* Rejects values that contain an invalid JSON value with a single issue before
* `schema` validates them.
*
* The JSON value schema is a recursive union. It reports the issues of every
* alternative at every nesting level around an invalid value, so the size of a
* validation error would grow much faster than the (untrusted) input.
*
* @param jsonValuePath - Path from the validated value to the JSON value.
*/
function withJsonValueCheck(schema, jsonValuePath = []) {
	return z$1.pipe(z$1.unknown().check((context) => {
		let jsonValue = context.value;
		for (const key of jsonValuePath) jsonValue = jsonValue != null && typeof jsonValue === "object" ? jsonValue[key] : void 0;
		const invalidPath = findInvalidJsonValuePath(jsonValue);
		if (invalidPath != null) context.issues.push({
			code: "custom",
			message: "Invalid JSON value. Expected null, a string, a finite number, a boolean, an array, or an object.",
			input: context.value,
			path: [...jsonValuePath, ...invalidPath]
		});
	}), schema);
}
const toolMetadataSchema = withJsonValueCheck(z$1.record(z$1.string(), z$1.optional(jsonValueSchema)));
const providerMetadataSchema = withJsonValueCheck(providerMetadataSchema$1);
const providerReferenceSchema$1 = z$1.record(z$1.string(), z$1.string());
const uiCitationSchema = withJsonValueCheck(citationSchema, ["source", "providerMetadata"]);
function isEmptyObject(value) {
	return value != null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === 0;
}
function asDynamicToolPart(toolPart) {
	const { type, ...part } = toolPart;
	return markToolPartAsUnavailable({
		...part,
		type: "dynamic-tool",
		toolName: type.slice(5)
	});
}
function getToolPartInputSchemaInput(toolPart) {
	return toolPart.approval != null && Object.prototype.hasOwnProperty.call(toolPart.approval, "inputSchemaInput") ? { value: toolPart.approval.inputSchemaInput } : void 0;
}
/**
* Creates an array schema that validates its elements in order and stops at
* the first invalid element.
*
* UI messages are untrusted input. `z.array` validates every element and
* reports the issues of all invalid elements, so the memory and time needed to
* reject an input would grow with the number of invalid elements in it.
*/
function arrayUntilFirstInvalidElement(selectElementSchema) {
	return z$1.pipe(z$1.array(z$1.unknown()), z$1.transform((elements, context) => {
		const validatedElements = [];
		for (const [index, element] of elements.entries()) {
			const result = z$1.safeParse(selectElementSchema(element), element);
			if (!result.success) {
				for (const issue of result.error.issues) context.issues.push({
					...issue,
					path: [index, ...issue.path]
				});
				return z$1.NEVER;
			}
			validatedElements.push(result.data);
		}
		return validatedElements;
	}));
}
const uiMessagesSchema = lazySchema(() => {
	const approvalRequestedSchema = z$1.object({
		id: z$1.string(),
		approved: z$1.optional(z$1.never()),
		descriptor: z$1.optional(z$1.unknown()),
		requestReason: z$1.optional(z$1.string()),
		reason: z$1.optional(z$1.never()),
		isAutomatic: z$1.optional(z$1.boolean()),
		signature: z$1.optional(z$1.string()),
		inputSchemaInput: z$1.optional(z$1.unknown())
	});
	const approvalRespondedSchema = z$1.extend(approvalRequestedSchema, {
		approved: z$1.boolean(),
		reason: z$1.optional(z$1.string())
	});
	const approvalGrantedSchema = z$1.extend(approvalRespondedSchema, { approved: z$1.literal(true) });
	const approvalDeniedSchema = z$1.extend(approvalRespondedSchema, { approved: z$1.literal(false) });
	const steeringMessagePartSchema = z$1.discriminatedUnion("type", [z$1.object({
		type: z$1.literal("text"),
		text: z$1.string(),
		providerMetadata: z$1.optional(providerMetadataSchema)
	}), z$1.object({
		type: z$1.literal("file"),
		mediaType: z$1.string(),
		filename: z$1.optional(z$1.string()),
		url: z$1.string(),
		providerReference: z$1.optional(providerReferenceSchema$1),
		providerMetadata: z$1.optional(providerMetadataSchema)
	})]);
	const invalidPartTypeMessage = "Invalid UI message part type. Expected a known part type (for example \"text\" or \"dynamic-tool\") or a type starting with \"data-\" or \"tool-\".";
	const staticPartSchema = z$1.discriminatedUnion("type", [
		z$1.object({
			type: z$1.literal("text"),
			text: z$1.string(),
			citations: z$1.optional(arrayUntilFirstInvalidElement(() => uiCitationSchema)),
			state: z$1.optional(z$1.enum(["streaming", "done"])),
			providerMetadata: z$1.optional(providerMetadataSchema)
		}),
		z$1.object({
			type: z$1.literal("reasoning"),
			id: z$1.optional(z$1.string()),
			text: z$1.string(),
			state: z$1.optional(z$1.enum(["streaming", "done"])),
			providerMetadata: z$1.optional(providerMetadataSchema)
		}),
		z$1.object({
			type: z$1.literal("custom"),
			kind: z$1.string(),
			providerMetadata: z$1.optional(providerMetadataSchema)
		}),
		z$1.object({
			type: z$1.literal("source-url"),
			sourceId: z$1.string(),
			url: z$1.string(),
			title: z$1.optional(z$1.string()),
			providerMetadata: z$1.optional(providerMetadataSchema)
		}),
		z$1.object({
			type: z$1.literal("source-document"),
			sourceId: z$1.string(),
			mediaType: z$1.string(),
			title: z$1.string(),
			filename: z$1.optional(z$1.string()),
			providerMetadata: z$1.optional(providerMetadataSchema)
		}),
		z$1.object({
			type: z$1.literal("file"),
			mediaType: z$1.string(),
			filename: z$1.optional(z$1.string()),
			url: z$1.string(),
			providerReference: z$1.optional(providerReferenceSchema$1),
			providerMetadata: z$1.optional(providerMetadataSchema)
		}),
		z$1.object({
			type: z$1.literal("reasoning-file"),
			mediaType: z$1.string(),
			url: z$1.string(),
			providerMetadata: z$1.optional(providerMetadataSchema)
		}),
		z$1.object({
			type: z$1.literal("steering-message"),
			id: z$1.string(),
			parts: arrayUntilFirstInvalidElement(() => steeringMessagePartSchema)
		}),
		z$1.object({ type: z$1.literal("step-start") })
	], { error: (issue) => issue.code === "invalid_union" ? invalidPartTypeMessage : void 0 });
	const dataPartSchema = z$1.object({
		type: z$1.string().check(z$1.startsWith("data-")),
		id: z$1.optional(z$1.string()),
		data: z$1.unknown()
	});
	const dynamicToolPartSchema = z$1.discriminatedUnion("state", [
		z$1.object({
			type: z$1.literal("dynamic-tool"),
			dynamic: z$1.optional(z$1.literal(false)),
			toolName: z$1.string(),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("input-streaming"),
			input: z$1.optional(z$1.unknown()),
			rawInput: z$1.optional(z$1.string()),
			inputEncoding: z$1.optional(z$1.enum(["json", "text"])),
			providerExecuted: z$1.optional(z$1.boolean()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			approval: z$1.optional(z$1.never())
		}),
		z$1.object({
			type: z$1.literal("dynamic-tool"),
			dynamic: z$1.optional(z$1.literal(false)),
			toolName: z$1.string(),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("input-available"),
			input: z$1.unknown(),
			providerExecuted: z$1.optional(z$1.boolean()),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: z$1.optional(z$1.never())
		}),
		z$1.object({
			type: z$1.literal("dynamic-tool"),
			dynamic: z$1.optional(z$1.literal(false)),
			toolName: z$1.string(),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("approval-requested"),
			input: z$1.unknown(),
			providerExecuted: z$1.optional(z$1.boolean()),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: approvalRequestedSchema
		}),
		z$1.object({
			type: z$1.literal("dynamic-tool"),
			dynamic: z$1.optional(z$1.literal(false)),
			toolName: z$1.string(),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("approval-responded"),
			input: z$1.unknown(),
			providerExecuted: z$1.optional(z$1.boolean()),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: approvalRespondedSchema
		}),
		z$1.object({
			type: z$1.literal("dynamic-tool"),
			dynamic: z$1.optional(z$1.literal(false)),
			toolName: z$1.string(),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("output-available"),
			input: z$1.unknown(),
			providerExecuted: z$1.optional(z$1.boolean()),
			output: z$1.unknown(),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			resultProviderMetadata: z$1.optional(providerMetadataSchema),
			preliminary: z$1.optional(z$1.boolean()),
			approval: z$1.optional(approvalGrantedSchema)
		}),
		z$1.object({
			type: z$1.literal("dynamic-tool"),
			dynamic: z$1.optional(z$1.literal(false)),
			toolName: z$1.string(),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("output-error"),
			input: z$1.optional(z$1.unknown()),
			rawInput: z$1.optional(z$1.unknown()),
			providerExecuted: z$1.optional(z$1.boolean()),
			output: z$1.optional(z$1.never()),
			errorText: z$1.string(),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			resultProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: z$1.optional(approvalGrantedSchema)
		}),
		z$1.object({
			type: z$1.literal("dynamic-tool"),
			dynamic: z$1.optional(z$1.literal(false)),
			toolName: z$1.string(),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("output-denied"),
			input: z$1.unknown(),
			providerExecuted: z$1.optional(z$1.boolean()),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: approvalDeniedSchema
		})
	]);
	const toolPartSchema = z$1.discriminatedUnion("state", [
		z$1.object({
			type: z$1.string().check(z$1.startsWith("tool-")),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("input-streaming"),
			providerExecuted: z$1.optional(z$1.boolean()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			input: z$1.optional(z$1.unknown()),
			rawInput: z$1.optional(z$1.string()),
			inputEncoding: z$1.optional(z$1.enum(["json", "text"])),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			approval: z$1.optional(z$1.never())
		}),
		z$1.object({
			type: z$1.string().check(z$1.startsWith("tool-")),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("input-available"),
			providerExecuted: z$1.optional(z$1.boolean()),
			input: z$1.unknown(),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: z$1.optional(z$1.never())
		}),
		z$1.object({
			type: z$1.string().check(z$1.startsWith("tool-")),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("approval-requested"),
			input: z$1.unknown(),
			providerExecuted: z$1.optional(z$1.boolean()),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: approvalRequestedSchema
		}),
		z$1.object({
			type: z$1.string().check(z$1.startsWith("tool-")),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("approval-responded"),
			input: z$1.unknown(),
			providerExecuted: z$1.optional(z$1.boolean()),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: approvalRespondedSchema
		}),
		z$1.object({
			type: z$1.string().check(z$1.startsWith("tool-")),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("output-available"),
			providerExecuted: z$1.optional(z$1.boolean()),
			input: z$1.unknown(),
			output: z$1.unknown(),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			resultProviderMetadata: z$1.optional(providerMetadataSchema),
			preliminary: z$1.optional(z$1.boolean()),
			approval: z$1.optional(approvalGrantedSchema)
		}),
		z$1.object({
			type: z$1.string().check(z$1.startsWith("tool-")),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("output-error"),
			providerExecuted: z$1.optional(z$1.boolean()),
			input: z$1.optional(z$1.unknown()),
			rawInput: z$1.optional(z$1.unknown()),
			output: z$1.optional(z$1.never()),
			errorText: z$1.string(),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			resultProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: z$1.optional(approvalGrantedSchema)
		}),
		z$1.object({
			type: z$1.string().check(z$1.startsWith("tool-")),
			toolCallId: z$1.string(),
			title: z$1.optional(z$1.string()),
			toolMetadata: z$1.optional(toolMetadataSchema),
			state: z$1.literal("output-denied"),
			providerExecuted: z$1.optional(z$1.boolean()),
			input: z$1.unknown(),
			output: z$1.optional(z$1.never()),
			errorText: z$1.optional(z$1.never()),
			callProviderMetadata: z$1.optional(providerMetadataSchema),
			approval: approvalDeniedSchema
		})
	]);
	const messageSchema = z$1.object({
		id: z$1.string(),
		role: z$1.enum([
			"system",
			"user",
			"assistant"
		]),
		metadata: z$1.optional(z$1.unknown()),
		parts: arrayUntilFirstInvalidElement((part) => {
			const type = part?.type;
			if (typeof type === "string") {
				if (type.startsWith("data-")) return dataPartSchema;
				if (type.startsWith("tool-")) return toolPartSchema;
				if (type === "dynamic-tool") return dynamicToolPartSchema;
			}
			return staticPartSchema;
		})
	}).check((context) => {
		const message = context.value;
		if (message.role !== "assistant" && message.parts.length === 0) context.issues.push({
			continue: true,
			origin: "array",
			code: "too_small",
			minimum: 1,
			inclusive: true,
			input: message.parts,
			path: ["parts"],
			message: "Message must contain at least one part"
		});
	});
	return zodSchema$1(arrayUntilFirstInvalidElement(() => messageSchema).check(z$1.minLength(1, "Messages array must not be empty")));
});
async function safeValidateUIMessagesInternal({ messages, metadataSchema, dataSchemas, tools, experimental_refineToolInput }, { convertMissingTerminalToolsToDynamic }) {
	try {
		if (messages == null) return {
			success: false,
			error: new InvalidArgumentError({
				parameter: "messages",
				value: messages,
				message: "messages parameter must be provided"
			})
		};
		const validatedMessages = await validateTypes({
			value: messages,
			schema: uiMessagesSchema
		});
		warnIfUIMessageHasDeprecatedRawInput(validatedMessages);
		if (metadataSchema) for (const [msgIdx, message] of validatedMessages.entries()) message.metadata = await validateTypes({
			value: message.metadata,
			schema: metadataSchema,
			context: {
				field: `messages[${msgIdx}].metadata`,
				entityId: message.id
			}
		});
		const shouldValidateToolParts = tools != null || convertMissingTerminalToolsToDynamic;
		if (dataSchemas || shouldValidateToolParts) for (const [msgIdx, message] of validatedMessages.entries()) for (const [partIdx, part] of message.parts.entries()) {
			if (dataSchemas && part.type.startsWith("data-")) {
				const dataPart = part;
				const dataName = dataPart.type.slice(5);
				const dataSchema = dataSchemas[dataName];
				if (!dataSchema) return {
					success: false,
					error: new TypeValidationError$1({
						value: dataPart.data,
						cause: `No data schema found for data part ${dataName}`,
						context: {
							field: `messages[${msgIdx}].parts[${partIdx}].data`,
							entityName: dataName,
							entityId: dataPart.id
						}
					})
				};
				dataPart.data = await validateTypes({
					value: dataPart.data,
					schema: dataSchema,
					context: {
						field: `messages[${msgIdx}].parts[${partIdx}].data`,
						entityName: dataName,
						entityId: dataPart.id
					}
				});
			}
			if (shouldValidateToolParts && part.type.startsWith("tool-")) {
				const toolPart = part;
				const toolName = toolPart.type.slice(5);
				const tool = tools == null ? void 0 : getOwn(tools, toolName);
				const isTerminal = toolPart.state === "output-available" || toolPart.state === "output-error" || toolPart.state === "output-denied";
				if (!tool && isTerminal) {
					if (tools != null || convertMissingTerminalToolsToDynamic) message.parts[partIdx] = asDynamicToolPart(toolPart);
					continue;
				}
				if (!tool) return {
					success: false,
					error: new TypeValidationError$1({
						value: toolPart.input,
						cause: `No tool schema found for tool part ${toolName}`,
						context: {
							field: `messages[${msgIdx}].parts[${partIdx}].input`,
							entityName: toolName,
							entityId: toolPart.toolCallId
						}
					})
				};
				const inputValidationContext = {
					field: `messages[${msgIdx}].parts[${partIdx}].input`,
					entityName: toolName,
					entityId: toolPart.toolCallId
				};
				const inputSchemaInput = getToolPartInputSchemaInput(toolPart);
				const inputToValidate = inputSchemaInput == null ? toolPart.input : inputSchemaInput.value;
				let convertToDynamic = false;
				if (toolPart.state !== "input-streaming" && (toolPart.state !== "output-error" || inputSchemaInput != null || toolPart.input !== void 0)) {
					const result = await safeValidateTypes({
						value: inputToValidate,
						schema: tool.inputSchema,
						context: inputValidationContext
					});
					let inputError;
					if (!result.success) inputError = result.error;
					else if (inputSchemaInput != null) try {
						const refine = getOwn(experimental_refineToolInput, toolName);
						if (!isDeepEqualData(refine == null ? result.value : await refine(result.value), toolPart.input)) inputError = new TypeValidationError$1({
							value: toolPart.input,
							cause: "Tool input does not match the output reconstructed from inputSchemaInput.",
							context: inputValidationContext
						});
					} catch (error) {
						inputError = new TypeValidationError$1({
							value: inputToValidate,
							cause: error,
							context: inputValidationContext
						});
					}
					if (inputError != null) {
						if (toolPart.state === "output-error" || toolPart.state === "output-available" && isEmptyObject(toolPart.input)) convertToDynamic = true;
						else throw inputError;
					}
				}
				if (toolPart.state === "output-available" && tool.outputSchema) await validateTypes({
					value: toolPart.output,
					schema: tool.outputSchema,
					context: {
						field: `messages[${msgIdx}].parts[${partIdx}].output`,
						entityName: toolName,
						entityId: toolPart.toolCallId
					}
				});
				if (convertToDynamic) message.parts[partIdx] = asDynamicToolPart(toolPart);
			}
		}
		return {
			success: true,
			data: validatedMessages
		};
	} catch (error) {
		return {
			success: false,
			error
		};
	}
}
/**
* Validates a list of UI messages like `validateUIMessages`,
* but instead of throwing it returns `{ success: true, data }`
* or `{ success: false, error }`.
*/
async function safeValidateUIMessages(options) {
	return safeValidateUIMessagesInternal(options, { convertMissingTerminalToolsToDynamic: false });
}
/**
* Validates a list of UI messages.
*
* Metadata, data parts, and generic tool call structures are only validated if
* the corresponding schemas are provided. Otherwise, they are assumed to be
* valid.
*/
async function validateUIMessages(options) {
	const response = await safeValidateUIMessages(options);
	if (!response.success) throw response.error;
	return response.data;
}
async function validateUIMessagesForAgent(options) {
	const response = await safeValidateUIMessagesInternal(options, { convertMissingTerminalToolsToDynamic: true });
	if (!response.success) throw response.error;
	return response.data;
}
//#endregion
//#region src/agent/create-agent-ui-stream.ts
/**
* Runs the agent and stream the output as a UI message stream.
*
* @param agent - The agent to run.
* @param uiMessages - The input UI messages.
* @param convertDataPart - Optional function to convert custom data parts to text or file model message parts.
* @param abortSignal - The abort signal. Optional.
* @param timeout - Timeout in milliseconds. Optional.
* @param experimental_sandbox - The sandbox environment that is passed through to tool execution. Optional.
* @param experimental_steering - A steering object that adds user messages to the run at the next step boundary. Only supported by `ToolLoopAgent`. Optional.
* @param options - The options for the agent.
* @param experimental_transform - The stream transformations. Optional.
* @param onStepEnd - Callback that is called when each step ends. Optional.
* @param onStepFinish - Deprecated alias for `onStepEnd`. Optional.
* @param onUIMessageStepEnd - Callback with the accumulated UI message after each step. Optional.
*
* @returns The UI message stream.
*/
async function createAgentUIStream({ agent, uiMessages, convertDataPart, options, abortSignal, timeout, experimental_sandbox: sandbox, experimental_steering: steering, experimental_transform, onStepEnd, onStepFinish, onUIMessageStepEnd, ...uiMessageStreamOptions }) {
	if (steering != null && !(agent instanceof ToolLoopAgent)) throw new InvalidArgumentError({
		parameter: "experimental_steering",
		value: steering,
		message: "Steering is only supported by ToolLoopAgent."
	});
	const validatedMessages = await validateUIMessagesForAgent({
		messages: uiMessages,
		tools: agent.tools
	});
	const modelMessages = await convertToModelMessages(validatedMessages, {
		tools: agent.tools,
		convertDataPart
	});
	const result = await agent.stream({
		prompt: modelMessages,
		options,
		abortSignal,
		timeout,
		experimental_sandbox: sandbox,
		experimental_steering: steering,
		experimental_transform,
		onStepEnd: onStepEnd ?? onStepFinish
	});
	const originalMessages = uiMessageStreamOptions.originalMessages ?? validatedMessages;
	return createAsyncIterableStream(toUIMessageStream({
		...uiMessageStreamOptions,
		originalMessages,
		onStepEnd: onUIMessageStepEnd,
		stream: result.stream,
		tools: agent.tools
	}));
}
//#endregion
//#region src/agent/create-agent-ui-stream-response.ts
/**
* Runs the agent and returns a response object with a UI message stream.
*
* @param agent - The agent to run.
* @param uiMessages - The input UI messages.
* @param convertDataPart - Optional function to convert custom data parts to text or file model message parts.
* @param abortSignal - Abort signal. Optional.
* @param timeout - Timeout in milliseconds. Optional.
* @param experimental_sandbox - The sandbox environment that is passed through to tool execution. Optional.
* @param experimental_steering - A steering object that adds user messages to the run at the next step boundary. Only supported by `ToolLoopAgent`. Optional.
* @param options - The options for the agent. Optional.
* @param experimental_transform - Stream transformations. Optional.
* @param onStepEnd - Callback that is called when each step ends. Optional.
* @param onStepFinish - Deprecated alias for `onStepEnd`. Optional.
* @param onUIMessageStepEnd - Callback with the accumulated UI message after each step. Optional.
* @param headers - Additional headers for the response. Optional.
* @param status - The status code for the response. Optional.
* @param statusText - The status text for the response. Optional.
* @param keepAliveMs - Optional interval for sending SSE keep-alive comments.
* @param consumeSseStream - Whether to consume the SSE stream. Optional.
*
* @returns The response object.
*/
async function createAgentUIStreamResponse({ headers, status, statusText, keepAliveMs, consumeSseStream, ...options }) {
	return createUIMessageStreamResponse({
		headers,
		status,
		statusText,
		keepAliveMs,
		consumeSseStream,
		stream: await createAgentUIStream(options)
	});
}
//#endregion
//#region src/agent/pipe-agent-ui-stream-to-response.ts
/**
* Pipes the agent UI message stream to a Node.js ServerResponse object.
*
* @param response - The Node.js ServerResponse object to pipe to.
* @param agent - The agent to run.
* @param uiMessages - The input UI messages.
* @param convertDataPart - Optional function to convert custom data parts to text or file model message parts.
* @param abortSignal - Abort signal. Optional.
* @param timeout - Timeout in milliseconds. Optional.
* @param experimental_sandbox - The sandbox environment that is passed through to tool execution. Optional.
* @param experimental_steering - A steering object that adds user messages to the run at the next step boundary. Only supported by `ToolLoopAgent`. Optional.
* @param options - The options for the agent. Optional.
* @param experimental_transform - Stream transformations. Optional.
* @param onStepEnd - Callback that is called when each step ends. Optional.
* @param onStepFinish - Deprecated alias for `onStepEnd`. Optional.
* @param onUIMessageStepEnd - Callback with the accumulated UI message after each step. Optional.
* @param headers - Additional headers for the response. Optional.
* @param status - The status code for the response. Optional.
* @param statusText - The status text for the response. Optional.
* @param keepAliveMs - Optional interval for sending SSE keep-alive comments.
* @param consumeSseStream - Whether to consume the SSE stream. Optional.
*/
async function pipeAgentUIStreamToResponse({ response, headers, status, statusText, keepAliveMs, consumeSseStream, ...options }) {
	return pipeUIMessageStreamToResponse({
		response,
		headers,
		status,
		statusText,
		keepAliveMs,
		consumeSseStream,
		stream: await createAgentUIStream(options)
	});
}
//#endregion
//#region src/util/set-own.ts
/**
* Writes an enumerable own property without invoking inherited setters such as
* `Object.prototype.__proto__`. Keeps the target object's prototype unchanged.
*/
function setOwn(object, key, value) {
	Object.defineProperty(object, key, {
		value,
		enumerable: true,
		configurable: true,
		writable: true
	});
}
//#endregion
//#region src/generate-image/generate-image.ts
const gatewayCostMetadataKeys = [
	"cost",
	"gatewayCost",
	"inferenceCost",
	"inputInferenceCost",
	"marketCost",
	"outputInferenceCost",
	"surchargeCost"
];
var RetryableNoImageResultError = class extends Error {
	constructor() {
		super("No image generated.");
		this.name = "RetryableNoImageResultError";
	}
};
/**
* Generates images using an image model.
*
* @param model - The image model to use.
* @param prompt - The prompt that should be used to generate the image.
* @param n - Number of images to generate. Default: 1.
* @param maxImagesPerCall - Maximum number of images to generate in a single API call.
* @param size - Size of the images to generate. Must have the format `{width}x{height}`.
* @param aspectRatio - Aspect ratio of the images to generate. Must have the format `{width}:{height}`.
* @param seed - Seed for the image generation.
* @param providerOptions - Additional provider-specific options that are passed through to the provider
* as body parameters.
* @param maxRetries - Maximum number of retries per image model call, including retries after unclassified empty responses. Empty responses marked as not retryable by the provider are not retried. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
*
* @returns A result object that contains the generated images.
*/
async function generateImage({ model: modelArg, prompt: promptArg, n = 1, maxImagesPerCall, size, aspectRatio, seed, providerOptions, maxRetries: maxRetriesArg, abortSignal, headers }) {
	const model = resolveImageModel(modelArg);
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const { retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal,
		additionalRetryableError: (error) => error instanceof RetryableNoImageResultError
	});
	const maxImagesPerCallWithDefault = maxImagesPerCall ?? await invokeModelMaxImagesPerCall(model) ?? 1;
	const callCount = Math.ceil(n / maxImagesPerCallWithDefault);
	const callImageCounts = Array.from({ length: callCount }, (_, i) => {
		if (i < callCount - 1) return maxImagesPerCallWithDefault;
		const remainder = n % maxImagesPerCallWithDefault;
		return remainder === 0 ? maxImagesPerCallWithDefault : remainder;
	});
	const results = (await Promise.all(callImageCounts.map(async (callImageCount) => {
		const callResults = [];
		try {
			await retry(async () => {
				const { prompt, files, mask } = normalizePrompt$1(promptArg);
				const result = await model.doGenerate({
					prompt,
					files,
					mask,
					n: callImageCount,
					abortSignal,
					headers: headersWithUserAgent,
					size,
					aspectRatio,
					seed,
					providerOptions: providerOptions ?? {}
				});
				callResults.push(result);
				if (result.images.length === 0 && result.isRetryable !== false) throw new RetryableNoImageResultError();
				return result;
			});
			return callResults;
		} catch (error) {
			if ((error instanceof RetryableNoImageResultError ? error : RetryError.isInstance(error) && error.lastError instanceof RetryableNoImageResultError ? error.lastError : void 0) != null) return callResults;
			throw error;
		}
	}))).flat();
	const images = [];
	const calls = [];
	const warnings = [];
	const responses = [];
	const providerMetadata = {};
	let totalUsage = {
		inputTokens: void 0,
		outputTokens: void 0,
		totalTokens: void 0
	};
	for (const result of results) {
		const callImages = result.images.map((image, index) => new DefaultGeneratedFile({
			data: image,
			mediaType: detectMediaType({
				data: image,
				topLevelType: "image"
			}) ?? "image/png",
			providerMetadata: getImageProviderMetadata(result.providerMetadata, index)
		}));
		images.push(...callImages);
		calls.push({
			images: callImages,
			providerMetadata: result.providerMetadata,
			response: result.response,
			warnings: result.warnings,
			usage: result.usage
		});
		warnings.push(...result.warnings);
		if (result.usage != null) totalUsage = addImageModelUsage(totalUsage, result.usage);
		if (result.providerMetadata) for (const [providerName, metadata] of Object.entries(result.providerMetadata)) if (providerName === "gateway") {
			const currentEntry = providerMetadata[providerName];
			if (currentEntry != null && typeof currentEntry === "object") {
				const currentGatewayMetadata = currentEntry;
				const newGatewayMetadata = metadata;
				providerMetadata[providerName] = {
					...currentEntry,
					...metadata,
					...Object.fromEntries(gatewayCostMetadataKeys.flatMap((key) => {
						const total = addDecimalStrings(currentGatewayMetadata[key], newGatewayMetadata[key]);
						return total == null ? [] : [[key, total]];
					}))
				};
			} else providerMetadata[providerName] = { ...metadata };
			const imagesValue = providerMetadata[providerName].images;
			if (Array.isArray(imagesValue) && imagesValue.length === 0) delete providerMetadata[providerName].images;
		} else {
			const currentEntry = getOwn(providerMetadata, providerName) ?? { images: [] };
			currentEntry.images.push(...metadata.images);
			setOwn(providerMetadata, providerName, currentEntry);
		}
		responses.push(result.response);
	}
	logWarnings({
		warnings,
		provider: model.provider,
		model: model.modelId
	});
	if (!images.length) throw new NoImageGeneratedError({
		calls,
		responses
	});
	return new DefaultGenerateImageResult({
		images,
		calls,
		warnings,
		responses,
		providerMetadata,
		usage: totalUsage
	});
}
var DefaultGenerateImageResult = class {
	constructor(options) {
		this.images = options.images;
		this.calls = options.calls;
		this.warnings = options.warnings;
		this.responses = options.responses;
		this.providerMetadata = options.providerMetadata;
		this.usage = options.usage;
	}
	get image() {
		return this.images[0];
	}
};
/**
* Extracts per-image metadata from the legacy `providerMetadata.<provider>.images` result shape.
*/
function getImageProviderMetadata(providerMetadata, imageIndex) {
	if (providerMetadata == null) return;
	let imageMetadata;
	for (const [providerName, metadata] of Object.entries(providerMetadata)) {
		const value = metadata.images?.[imageIndex];
		if (isJSONObject(value) && !Array.isArray(value)) setOwn(imageMetadata ??= {}, providerName, value);
	}
	return imageMetadata;
}
async function invokeModelMaxImagesPerCall(model) {
	if (!(model.maxImagesPerCall instanceof Function)) return model.maxImagesPerCall;
	return model.maxImagesPerCall({ modelId: model.modelId });
}
function addDecimalStrings(value1, value2) {
	if (typeof value1 !== "string" || typeof value2 !== "string" || !/^\d+(?:\.\d+)?$/.test(value1) || !/^\d+(?:\.\d+)?$/.test(value2)) return;
	const [integer1, fraction1 = ""] = value1.split(".");
	const [integer2, fraction2 = ""] = value2.split(".");
	const precision = Math.max(fraction1.length, fraction2.length);
	const sumString = (BigInt(integer1 + fraction1.padEnd(precision, "0")) + BigInt(integer2 + fraction2.padEnd(precision, "0"))).toString().padStart(precision + 1, "0");
	return precision === 0 ? sumString : `${sumString.slice(0, -precision)}.${sumString.slice(-precision)}`.replace(/\.?0+$/, "");
}
function normalizePrompt$1(prompt) {
	if (typeof prompt === "string") return {
		prompt,
		files: void 0,
		mask: void 0
	};
	return {
		prompt: prompt.text,
		files: prompt.images.map(toImageModelV4File),
		mask: prompt.mask ? toImageModelV4File(prompt.mask) : void 0
	};
}
function toImageModelV4File(dataContent) {
	if (typeof dataContent === "string" && dataContent.startsWith("http")) return {
		type: "url",
		url: dataContent
	};
	if (typeof dataContent === "string" && dataContent.startsWith("data:")) {
		const { mediaType: dataUrlMediaType, base64Content } = splitDataUrl(dataContent);
		if (base64Content != null) {
			const uint8Data = convertBase64ToUint8Array(base64Content);
			return {
				type: "file",
				data: uint8Data,
				mediaType: dataUrlMediaType || detectMediaType({
					data: uint8Data,
					topLevelType: "image"
				}) || "image/png"
			};
		}
	}
	const uint8Data = convertDataContentToUint8Array(dataContent);
	return {
		type: "file",
		data: uint8Data,
		mediaType: detectMediaType({
			data: uint8Data,
			topLevelType: "image"
		}) || "image/png"
	};
}
//#endregion
//#region src/batch/batch.ts
/**
* Requests cancellation of a batch.
*/
async function cancelBatch({ provider, batch, providerOptions, abortSignal, headers, timeout }) {
	const batchApi = resolveBatchApi(provider);
	validateBatchReference({
		batchApi,
		batch
	});
	if (batchApi.doCancelBatch == null) throw new UnsupportedFunctionalityError$1({
		functionality: "batch cancellation",
		message: "The provider does not support batch cancellation."
	});
	const operationAbortSignal = mergeAbortSignals(abortSignal, getTotalTimeoutMs(timeout));
	try {
		return await batchApi.doCancelBatch({
			batchId: batch.id,
			providerOptions,
			abortSignal: operationAbortSignal,
			headers: withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`)
		});
	} catch (error) {
		throw wrapGatewayError(error);
	}
}
/**
* Lists a page of batches.
*/
async function listBatches({ provider, providerOptions, limit, cursor, maxRetries, abortSignal, headers, timeout } = {}) {
	const batchApi = resolveBatchApi(provider);
	const doListBatches = batchApi.doListBatches?.bind(batchApi);
	if (doListBatches == null) throw new UnsupportedFunctionalityError$1({
		functionality: "batch listing",
		message: "The provider does not support listing batches."
	});
	const operationAbortSignal = mergeAbortSignals(abortSignal, getTotalTimeoutMs(timeout));
	const { retry } = prepareRetries({
		maxRetries,
		abortSignal: operationAbortSignal
	});
	try {
		const { batches, nextCursor, providerMetadata } = await retry(() => doListBatches({
			providerOptions,
			abortSignal: operationAbortSignal,
			headers: withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`),
			...limit != null && { limit },
			...cursor != null && { cursor }
		}));
		return {
			batches: batches.map(({ batchId, ...status }) => ({
				version: 2,
				id: batchId,
				provider: batchApi.provider,
				...status
			})),
			...nextCursor != null && { nextCursor },
			...providerMetadata != null && { providerMetadata }
		};
	} catch (error) {
		throw wrapGatewayError(error);
	}
}
/**
* Starts a batch.
*/
async function startBatch({ provider, requests, providerOptions, webhookUrl, abortSignal, headers, timeout }) {
	validateRequests(requests);
	const batchApi = resolveBatchApi(provider);
	const operationAbortSignal = mergeAbortSignals(abortSignal, getTotalTimeoutMs(timeout));
	const supportedUrls = await batchApi.supportedUrls;
	operationAbortSignal?.throwIfAborted();
	const normalizedRequests = [];
	const toolsByName = /* @__PURE__ */ new Map();
	for (const request of requests) {
		const requestType = request.type;
		switch (requestType) {
			case "text": {
				const standardizedPrompt = await standardizePrompt(request);
				const preparedTools = await prepareTools({
					tools: request.tools,
					toolOrder: request.toolOrder,
					toolsContext: request.toolsContext
				});
				validateCompatibleTools({
					requestId: request.id,
					tools: preparedTools,
					toolsByName
				});
				normalizedRequests.push({
					id: request.id,
					type: request.type,
					modelId: request.model,
					options: {
						...prepareLanguageModelCallOptions(request),
						prompt: await convertToLanguageModelPrompt({
							prompt: standardizedPrompt,
							supportedUrls,
							download: void 0,
							abortSignal: operationAbortSignal,
							provider: batchApi.provider.split(".")[0]
						}),
						tools: preparedTools,
						toolChoice: prepareToolChoice({ toolChoice: request.toolChoice }),
						providerOptions: request.providerOptions
					}
				});
				break;
			}
			case "image": {
				const { prompt, files, mask } = normalizePrompt$1(request.prompt);
				normalizedRequests.push({
					id: request.id,
					type: request.type,
					modelId: request.model,
					options: {
						prompt,
						n: request.n ?? 1,
						size: request.size,
						aspectRatio: request.aspectRatio,
						seed: request.seed,
						files,
						mask,
						providerOptions: request.providerOptions ?? {}
					}
				});
				break;
			}
			default: {
				const _exhaustiveCheck = requestType;
				throw new InvalidArgumentError({
					parameter: "requests",
					value: _exhaustiveCheck,
					message: `Unsupported batch request type "${_exhaustiveCheck}".`
				});
			}
		}
		operationAbortSignal?.throwIfAborted();
	}
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	try {
		const { batchId, warnings, ...status } = await batchApi.doStartBatch({
			requests: normalizedRequests,
			providerOptions,
			abortSignal: operationAbortSignal,
			headers: headersWithUserAgent,
			...webhookUrl != null && { webhookUrl }
		});
		const modelByRequestId = new Map(normalizedRequests.map((request) => [request.id, request.modelId]));
		for (const { requestId, warning } of warnings) logWarnings({
			warnings: [warning],
			provider: batchApi.provider,
			model: requestId == null ? void 0 : modelByRequestId.get(requestId)
		});
		return {
			version: 2,
			id: batchId,
			provider: batchApi.provider,
			...status,
			warnings
		};
	} catch (error) {
		throw wrapGatewayError(error);
	}
}
function validateCompatibleTools({ requestId, tools, toolsByName }) {
	for (const tool of tools ?? []) {
		const previousTool = toolsByName.get(tool.name);
		if (previousTool != null && !isDeepEqualData(previousTool, tool)) throw new InvalidArgumentError({
			parameter: "requests",
			value: requestId,
			message: `tool "${tool.name}" must have the same definition in every batch request`
		});
		toolsByName.set(tool.name, tool);
	}
}
/**
* Retrieves the latest normalized status for a batch.
*/
async function getBatchStatus({ provider, batch, providerOptions, maxRetries, abortSignal, headers, timeout }) {
	const batchApi = resolveBatchApi(provider);
	validateBatchReference({
		batchApi,
		batch
	});
	const operationAbortSignal = mergeAbortSignals(abortSignal, getTotalTimeoutMs(timeout));
	const { retry } = prepareRetries({
		maxRetries,
		abortSignal: operationAbortSignal
	});
	try {
		return await retry(() => batchApi.doGetBatchStatus({
			batchId: batch.id,
			providerOptions,
			abortSignal: operationAbortSignal,
			headers: withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`)
		}));
	} catch (error) {
		throw wrapGatewayError(error);
	}
}
/**
* Streams complete terminal results for the requests in a batch.
*/
function getBatchResults({ provider, batch, tools, providerOptions, maxRetries, abortSignal, headers, timeout }) {
	const batchApi = resolveBatchApi(provider);
	validateBatchReference({
		batchApi,
		batch
	});
	const streamAbortController = new AbortController();
	const operationAbortSignal = mergeAbortSignals(abortSignal, getTotalTimeoutMs(timeout), streamAbortController.signal);
	const { retry } = prepareRetries({
		maxRetries,
		abortSignal: operationAbortSignal
	});
	const transform = new TransformStream({
		async transform(item, controller) {
			controller.enqueue(await convertBatchItemResult({
				item,
				tools,
				abortSignal: operationAbortSignal
			}));
		},
		cancel(reason) {
			streamAbortController.abort(reason ?? /* @__PURE__ */ new Error("Batch results stream was cancelled."));
		}
	});
	(async () => {
		try {
			await (await retry(() => batchApi.doGetBatchResults({
				batchId: batch.id,
				providerOptions,
				abortSignal: operationAbortSignal,
				headers: withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`)
			}))).pipeTo(transform.writable, { signal: operationAbortSignal });
		} catch (error) {
			await transform.writable.abort(wrapGatewayError(error)).catch(() => {});
		}
	})();
	return asAsyncIterableStream(transform.readable);
}
function resolveBatchApi(provider) {
	provider ??= asProviderV4(globalThis.AI_SDK_DEFAULT_PROVIDER ?? gateway$1);
	if (isBatchApi(provider)) return provider;
	if (!hasBatchFactory(provider)) throw new UnsupportedFunctionalityError$1({
		functionality: "batch processing",
		message: "The provider does not support batch processing. Make sure it exposes an experimental_batch() method."
	});
	return provider.experimental_batch();
}
function hasBatchFactory(provider) {
	return typeof provider.experimental_batch === "function";
}
function isBatchApi(provider) {
	const candidate = provider;
	return typeof candidate.doStartBatch === "function" && typeof candidate.doGetBatchStatus === "function" && typeof candidate.doGetBatchResults === "function";
}
function validateRequests(requests) {
	if (requests.length === 0) throw new InvalidArgumentError({
		parameter: "requests",
		value: requests,
		message: "requests must not be empty"
	});
	const ids = /* @__PURE__ */ new Set();
	for (const request of requests) {
		if (request.id.trim().length === 0) throw new InvalidArgumentError({
			parameter: "requests",
			value: requests,
			message: "request IDs must not be empty"
		});
		if (ids.has(request.id)) throw new InvalidArgumentError({
			parameter: "requests",
			value: requests,
			message: `request IDs must be unique; duplicate ID "${request.id}"`
		});
		ids.add(request.id);
	}
}
function validateBatchReference({ batchApi, batch }) {
	if (batch.provider !== batchApi.provider) throw new InvalidArgumentError({
		parameter: "provider",
		value: batchApi,
		message: `provider ${batchApi.provider} is not compatible with batch provider ${batch.provider}`
	});
}
async function convertBatchItemResult({ item, tools, abortSignal }) {
	switch (item.type) {
		case "text": switch (item.status) {
			case "succeeded": return {
				type: item.type,
				id: item.id,
				status: item.status,
				...await convertGenerateResult({
					result: item.result,
					tools,
					abortSignal
				})
			};
			case "failed": return {
				type: item.type,
				id: item.id,
				status: item.status,
				error: item.error,
				providerMetadata: item.providerMetadata
			};
			case "cancelled":
			case "expired": return {
				type: item.type,
				id: item.id,
				status: item.status,
				error: item.error,
				providerMetadata: item.providerMetadata
			};
		}
		case "image": switch (item.status) {
			case "succeeded": return {
				type: item.type,
				id: item.id,
				status: item.status,
				...convertImageResult(item.result)
			};
			case "failed": return {
				type: item.type,
				id: item.id,
				status: item.status,
				error: item.error,
				providerMetadata: item.providerMetadata
			};
			case "cancelled":
			case "expired": return {
				type: item.type,
				id: item.id,
				status: item.status,
				error: item.error,
				providerMetadata: item.providerMetadata
			};
		}
	}
}
function convertImageResult(result) {
	return {
		images: result.images.map((image, index) => new DefaultGeneratedFile({
			data: image,
			mediaType: detectMediaType({
				data: image,
				topLevelType: "image"
			}) ?? "image/png",
			providerMetadata: getImageProviderMetadata(result.providerMetadata, index)
		})),
		warnings: result.warnings,
		response: {
			timestamp: result.response.timestamp,
			modelId: result.response.modelId,
			headers: result.response.headers
		},
		providerMetadata: result.providerMetadata,
		usage: result.usage
	};
}
async function convertGenerateResult({ result, tools, abortSignal }) {
	const toolCalls = await Promise.all(result.content.filter((part) => part.type === "tool-call").map((toolCall) => parseToolCall({
		toolCall,
		tools,
		repairToolCall: void 0,
		refineToolInput: void 0,
		instructions: void 0,
		messages: []
	})));
	return {
		content: await convertLanguageModelContent({
			content: result.content,
			toolCalls,
			toolOutputs: [],
			toolApprovalRequests: [],
			toolApprovalResponses: [],
			tools,
			abortSignal
		}),
		text: result.content.filter((part) => part.type === "text").map((part) => part.text).join(""),
		finishReason: result.finishReason.unified,
		rawFinishReason: result.finishReason.raw,
		usage: asLanguageModelUsage(result.usage),
		...result.response != null ? { response: {
			id: result.response.id,
			timestamp: result.response.timestamp?.toISOString(),
			modelId: result.response.modelId
		} } : {},
		providerMetadata: result.providerMetadata
	};
}
//#endregion
//#region src/embed/restricted-telemetry-dispatcher.ts
/**
* Filters runtime context before sending operation events to telemetry integrations.
* User callbacks continue to receive the original context.
*/
function createRestrictedTelemetryDispatcher$2({ telemetry }) {
	const dispatcher = createTelemetryDispatcher({ telemetry });
	return {
		...dispatcher,
		onStart: (event) => dispatcher.onStart?.({
			...event,
			runtimeContext: filterIncludedContext({
				context: event.runtimeContext,
				includeContext: telemetry?.includeRuntimeContext
			})
		}),
		onEnd: (event) => dispatcher.onEnd?.({
			...event,
			runtimeContext: filterIncludedContext({
				context: event.runtimeContext,
				includeContext: telemetry?.includeRuntimeContext
			})
		})
	};
}
//#endregion
//#region src/embed/validate-embedding-dimensions.ts
function validateEmbeddingDimensions(dimensions) {
	if (dimensions !== void 0 && (!Number.isInteger(dimensions) || dimensions <= 0)) throw new InvalidArgumentError({
		parameter: "dimensions",
		value: dimensions,
		message: "dimensions must be a positive integer"
	});
}
//#endregion
//#region src/embed/embed.ts
const originalGenerateCallId$6 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Embed a value using an embedding model. The type of the value is defined by the embedding model.
*
* @param model - The embedding model to use.
* @param value - The value that should be embedded.
*
* @param dimensions - Requested output dimensions. Must be a positive integer. Requires provider support.
*
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
*
* @param telemetry - Optional telemetry configuration.
* @param runtimeContext - User-defined runtime context passed to callbacks and, when explicitly included, telemetry.
*
* @param providerOptions - Additional provider-specific options. They are passed through
* to the provider from the AI SDK and enable provider-specific
* functionality that can be fully encapsulated in the provider.
*
* @returns A result object that contains the embedding, the value, and additional information.
*/
async function embed({ model: modelArg, value, dimensions, providerOptions, maxRetries: maxRetriesArg, abortSignal, headers, experimental_telemetry, telemetry = experimental_telemetry, runtimeContext = {}, onStart, experimental_onStart, onEnd, experimental_onEnd, _internal: { generateCallId = originalGenerateCallId$6 } = {} }) {
	validateEmbeddingDimensions(dimensions);
	const model = resolveEmbeddingModel(modelArg);
	const { maxRetries, retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	const resolvedOnStart = onStart ?? experimental_onStart;
	const resolvedOnEnd = onEnd ?? experimental_onEnd;
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const callId = generateCallId();
	const telemetryDispatcher = createRestrictedTelemetryDispatcher$2({ telemetry });
	const runInTracingChannelSpan = telemetryDispatcher.runInTracingChannelSpan ?? (async ({ execute }) => await execute());
	const startEvent = {
		callId,
		operationId: "ai.embed",
		runtimeContext,
		provider: model.provider,
		modelId: model.modelId,
		value,
		dimensions,
		maxRetries,
		headers: headersWithUserAgent,
		providerOptions
	};
	return await runInTracingChannelSpan({
		type: "embed",
		event: startEvent,
		execute: async () => {
			await notify({
				event: startEvent,
				callbacks: [resolvedOnStart, telemetryDispatcher.onStart]
			});
			try {
				const { embedding, usage, warnings, response, providerMetadata } = await retry(async () => {
					const embedCallId = generateCallId();
					await notify({
						event: {
							callId,
							embedCallId,
							operationId: "ai.embed.doEmbed",
							provider: model.provider,
							modelId: model.modelId,
							values: [value],
							dimensions
						},
						callbacks: [telemetryDispatcher.onEmbedStart]
					});
					const modelResponse = await model.doEmbed({
						values: [value],
						dimensions,
						abortSignal,
						headers: headersWithUserAgent,
						providerOptions
					});
					const embedding = modelResponse.embeddings[0];
					const usage = modelResponse.usage ?? { tokens: NaN };
					await notify({
						event: {
							callId,
							embedCallId,
							operationId: "ai.embed.doEmbed",
							provider: model.provider,
							modelId: model.modelId,
							values: [value],
							embeddings: modelResponse.embeddings,
							usage
						},
						callbacks: [telemetryDispatcher.onEmbedEnd]
					});
					if (embedding == null) throw new InvalidResponseDataError({
						data: modelResponse.embeddings,
						message: "No embedding generated."
					});
					return {
						embedding,
						usage,
						warnings: modelResponse.warnings ?? [],
						providerMetadata: modelResponse.providerMetadata,
						response: modelResponse.response
					};
				});
				logWarnings({
					warnings,
					provider: model.provider,
					model: model.modelId
				});
				await notify({
					event: {
						callId,
						operationId: "ai.embed",
						runtimeContext,
						provider: model.provider,
						modelId: model.modelId,
						value,
						embedding,
						usage,
						warnings,
						providerMetadata,
						response
					},
					callbacks: [resolvedOnEnd, telemetryDispatcher.onEnd]
				});
				return new DefaultEmbedResult({
					value,
					embedding,
					usage,
					warnings,
					providerMetadata,
					response
				});
			} catch (error) {
				await telemetryDispatcher.onError?.({
					callId,
					error
				});
				throw error;
			}
		}
	});
}
var DefaultEmbedResult = class {
	constructor(options) {
		this.value = options.value;
		this.embedding = options.embedding;
		this.usage = options.usage;
		this.warnings = options.warnings;
		this.providerMetadata = options.providerMetadata;
		this.response = options.response;
	}
};
//#endregion
//#region src/model/get-embedding-model-max-input-bytes-per-call.ts
function getEmbeddingModelMaxInputBytesPerCall(model) {
	return model[EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL];
}
//#endregion
//#region src/model/get-embedding-model-provider-options-transformer.ts
function getEmbeddingModelProviderOptionsTransformer(model) {
	return model[EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER];
}
//#endregion
//#region src/util/split-array.ts
/**
* Splits an array into chunks of a specified size.
*
* @template T - The type of elements in the array.
* @param {T[]} array - The array to split.
* @param {number} chunkSize - The size of each chunk.
* @returns {T[][]} - A new array containing the chunks.
* @throws {InvalidArgumentError} If the chunk size is not greater than 0.
*/
function splitArray(array, chunkSize) {
	if (chunkSize <= 0) throw new InvalidArgumentError({
		parameter: "chunkSize",
		value: chunkSize,
		message: "chunkSize must be greater than 0"
	});
	const result = [];
	for (let i = 0; i < array.length; i += chunkSize) result.push(array.slice(i, i + chunkSize));
	return result;
}
//#endregion
//#region src/embed/embed-many.ts
const originalGenerateCallId$5 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Embed several values using an embedding model. The type of the value is defined
* by the embedding model.
*
* `embedMany` automatically splits large requests into smaller chunks when the
* model has a limit on either the number of embeddings or the UTF-8 input bytes
* that can be processed in a single call.
*
* @param model - The embedding model to use.
* @param values - The values that should be embedded.
*
* @param dimensions - Requested output dimensions. Must be a positive integer. Requires provider support.
*
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
*
* @param maxParallelCalls - Maximum number of concurrent requests when a request is split into
* multiple model calls. Must be greater than 0 when the model supports parallel calls.
* Default: Infinity.
*
* @param telemetry - Optional telemetry configuration.
* @param runtimeContext - User-defined runtime context passed to callbacks and, when explicitly included, telemetry.
*
* @param providerOptions - Additional provider-specific options. They are passed through
* to the provider from the AI SDK and enable provider-specific
* functionality that can be fully encapsulated in the provider.
*
* @returns A result object that contains the embeddings, the value, and additional information.
*/
async function embedMany({ model: modelArg, values, dimensions, maxParallelCalls = Infinity, maxRetries: maxRetriesArg, abortSignal, headers, providerOptions, experimental_telemetry, telemetry = experimental_telemetry, runtimeContext = {}, onStart, experimental_onStart, onEnd, experimental_onEnd, _internal: { generateCallId = originalGenerateCallId$5 } = {} }) {
	validateEmbeddingDimensions(dimensions);
	const model = resolveEmbeddingModel(modelArg);
	const { maxRetries, retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	const resolvedOnStart = onStart ?? experimental_onStart;
	const resolvedOnEnd = onEnd ?? experimental_onEnd;
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const callId = generateCallId();
	const telemetryDispatcher = createRestrictedTelemetryDispatcher$2({ telemetry });
	const runInTracingChannelSpan = telemetryDispatcher.runInTracingChannelSpan ?? (async ({ execute }) => await execute());
	const startEvent = {
		callId,
		operationId: "ai.embedMany",
		runtimeContext,
		provider: model.provider,
		modelId: model.modelId,
		value: values,
		dimensions,
		maxRetries,
		headers: headersWithUserAgent,
		providerOptions
	};
	return await runInTracingChannelSpan({
		type: "embedMany",
		event: startEvent,
		execute: async () => {
			await notify({
				event: startEvent,
				callbacks: [resolvedOnStart, telemetryDispatcher.onStart]
			});
			try {
				const [maxEmbeddingsPerCall, maxInputBytesPerCall, supportsParallelCalls] = await Promise.all([
					model.maxEmbeddingsPerCall,
					getEmbeddingModelMaxInputBytesPerCall(model),
					model.supportsParallelCalls
				]);
				const hasEmbeddingLimit = maxEmbeddingsPerCall != null && maxEmbeddingsPerCall !== Infinity;
				const hasInputByteLimit = maxInputBytesPerCall != null && maxInputBytesPerCall !== Infinity;
				if (!hasEmbeddingLimit && !hasInputByteLimit) {
					const { embeddings, usage, warnings, response, providerMetadata } = await retry(async () => {
						const embedCallId = generateCallId();
						await notify({
							event: {
								callId,
								embedCallId,
								operationId: "ai.embedMany.doEmbed",
								provider: model.provider,
								modelId: model.modelId,
								values,
								dimensions
							},
							callbacks: [telemetryDispatcher.onEmbedStart]
						});
						const modelResponse = await model.doEmbed({
							values,
							dimensions,
							abortSignal,
							headers: headersWithUserAgent,
							providerOptions
						});
						const embeddings = modelResponse.embeddings;
						const usage = modelResponse.usage ?? { tokens: NaN };
						await notify({
							event: {
								callId,
								embedCallId,
								operationId: "ai.embedMany.doEmbed",
								provider: model.provider,
								modelId: model.modelId,
								values,
								embeddings,
								usage
							},
							callbacks: [telemetryDispatcher.onEmbedEnd]
						});
						return {
							embeddings,
							usage,
							warnings: modelResponse.warnings ?? [],
							providerMetadata: modelResponse.providerMetadata,
							response: modelResponse.response
						};
					});
					validateEmbeddingCount({
						embeddings,
						values
					});
					logWarnings({
						warnings,
						provider: model.provider,
						model: model.modelId
					});
					await notify({
						event: {
							callId,
							operationId: "ai.embedMany",
							runtimeContext,
							provider: model.provider,
							modelId: model.modelId,
							value: values,
							embedding: embeddings,
							usage,
							warnings,
							providerMetadata,
							response: [response]
						},
						callbacks: [resolvedOnEnd, telemetryDispatcher.onEnd]
					});
					return new DefaultEmbedManyResult({
						values,
						embeddings,
						usage,
						warnings,
						providerMetadata,
						responses: [response]
					});
				}
				const valueChunks = splitByEmbeddingLimits({
					values,
					maxEmbeddingsPerCall: hasEmbeddingLimit ? maxEmbeddingsPerCall : Infinity,
					maxInputBytesPerCall: hasInputByteLimit ? maxInputBytesPerCall : Infinity
				});
				const providerOptionsTransformer = getEmbeddingModelProviderOptionsTransformer(model);
				const embeddings = [];
				const warnings = [];
				const responses = [];
				let tokens = 0;
				let providerMetadata;
				const parallelChunks = splitArray(valueChunks, supportsParallelCalls ? maxParallelCalls : 1);
				let nextChunkStartIndex = 0;
				for (const parallelChunk of parallelChunks) {
					const results = await Promise.all(parallelChunk.map(async (chunk) => {
						const startIndex = nextChunkStartIndex;
						nextChunkStartIndex += chunk.length;
						const chunkProviderOptions = providerOptionsTransformer ? await providerOptionsTransformer({
							providerOptions,
							values,
							startIndex,
							endIndex: startIndex + chunk.length
						}) : providerOptions;
						const result = await retry(async () => {
							const embedCallId = generateCallId();
							await notify({
								event: {
									callId,
									embedCallId,
									operationId: "ai.embedMany.doEmbed",
									provider: model.provider,
									modelId: model.modelId,
									values: chunk,
									dimensions
								},
								callbacks: [telemetryDispatcher.onEmbedStart]
							});
							const modelResponse = await model.doEmbed({
								values: chunk,
								dimensions,
								abortSignal,
								headers: headersWithUserAgent,
								providerOptions: chunkProviderOptions
							});
							const chunkEmbeddings = modelResponse.embeddings;
							const usage = modelResponse.usage ?? { tokens: NaN };
							await notify({
								event: {
									callId,
									embedCallId,
									operationId: "ai.embedMany.doEmbed",
									provider: model.provider,
									modelId: model.modelId,
									values: chunk,
									embeddings: chunkEmbeddings,
									usage
								},
								callbacks: [telemetryDispatcher.onEmbedEnd]
							});
							return {
								embeddings: chunkEmbeddings,
								usage,
								warnings: modelResponse.warnings ?? [],
								providerMetadata: modelResponse.providerMetadata,
								response: modelResponse.response
							};
						});
						validateEmbeddingCount({
							embeddings: result.embeddings,
							values: chunk
						});
						return result;
					}));
					for (const result of results) {
						embeddings.push(...result.embeddings);
						warnings.push(...result.warnings);
						responses.push(result.response);
						tokens += result.usage.tokens;
						if (result.providerMetadata) {
							if (!providerMetadata) providerMetadata = { ...result.providerMetadata };
							else for (const [providerName, metadata] of Object.entries(result.providerMetadata)) setOwn(providerMetadata, providerName, {
								...getOwn(providerMetadata, providerName),
								...metadata
							});
						}
					}
				}
				logWarnings({
					warnings,
					provider: model.provider,
					model: model.modelId
				});
				await notify({
					event: {
						callId,
						operationId: "ai.embedMany",
						runtimeContext,
						provider: model.provider,
						modelId: model.modelId,
						value: values,
						embedding: embeddings,
						usage: { tokens },
						warnings,
						providerMetadata,
						response: responses
					},
					callbacks: [resolvedOnEnd, telemetryDispatcher.onEnd]
				});
				return new DefaultEmbedManyResult({
					values,
					embeddings,
					usage: { tokens },
					warnings,
					providerMetadata,
					responses
				});
			} catch (error) {
				await telemetryDispatcher.onError?.({
					callId,
					error
				});
				throw error;
			}
		}
	});
}
function validateEmbeddingCount({ embeddings, values }) {
	if (embeddings.length !== values.length) throw new InvalidResponseDataError$1({
		data: embeddings,
		message: `Expected ${values.length} embeddings, but received ${embeddings.length}.`
	});
}
const textEncoder = new TextEncoder();
function splitByEmbeddingLimits({ values, maxEmbeddingsPerCall, maxInputBytesPerCall }) {
	if (maxEmbeddingsPerCall <= 0) throw new Error("maxEmbeddingsPerCall must be greater than 0");
	if (maxInputBytesPerCall <= 0) throw new Error("maxInputBytesPerCall must be greater than 0");
	if (values.length === 0) return [];
	const chunks = [];
	let currentChunk = [];
	let currentInputBytes = 0;
	for (const value of values) {
		const inputBytes = textEncoder.encode(value).length;
		if (currentChunk.length > 0 && (currentChunk.length >= maxEmbeddingsPerCall || currentInputBytes + inputBytes > maxInputBytesPerCall)) {
			chunks.push(currentChunk);
			currentChunk = [];
			currentInputBytes = 0;
		}
		currentChunk.push(value);
		currentInputBytes += inputBytes;
	}
	chunks.push(currentChunk);
	return chunks;
}
var DefaultEmbedManyResult = class {
	constructor(options) {
		this.values = options.values;
		this.embeddings = options.embeddings;
		this.usage = options.usage;
		this.warnings = options.warnings;
		this.providerMetadata = options.providerMetadata;
		this.responses = options.responses;
	}
};
//#endregion
//#region src/decide/decision-state.ts
function isDecisionStateParts(state) {
	return Array.isArray(state);
}
async function prepareDecisionState({ state, abortSignal, download }) {
	if (typeof state === "string") return [{
		type: "text",
		text: state
	}];
	if (!isDecisionStateParts(state)) return [{
		type: "json",
		value: state
	}];
	if (state.every((part) => part.type !== "file")) return state;
	const message = (await convertToLanguageModelPrompt({
		prompt: {
			instructions: void 0,
			messages: [{
				role: "user",
				content: state.filter((part) => part.type === "file")
			}]
		},
		supportedUrls: {},
		download: download ?? (async (requests) => {
			if (requests.length > 0) throw new DownloadError$1({
				url: requests[0].url.toString(),
				message: "URL file state requires experimental_download. For untrusted URLs, use createDownload({ fetch }) with a transport that validates DNS at connection time."
			});
			return [];
		}),
		abortSignal
	}))[0];
	if (message.role !== "user") throw new Error("Expected user message.");
	let fileIndex = 0;
	return state.map((part) => part.type === "file" ? message.content[fileIndex++] : part);
}
//#endregion
//#region src/decide/restricted-telemetry-dispatcher.ts
function createRestrictedTelemetryDispatcher$1({ telemetry }) {
	const dispatcher = createTelemetryDispatcher({ telemetry });
	return {
		...dispatcher,
		onStart: (event) => dispatcher.experimental_onDecideStart?.({
			...event,
			runtimeContext: filterIncludedContext({
				context: event.runtimeContext,
				includeContext: telemetry?.includeRuntimeContext
			})
		}),
		onEnd: (event) => dispatcher.experimental_onDecideEnd?.({
			...event,
			runtimeContext: filterIncludedContext({
				context: event.runtimeContext,
				includeContext: telemetry?.includeRuntimeContext
			})
		})
	};
}
//#endregion
//#region src/decide/validate-decision.ts
const tolerance = 1e-6;
function isRecord$1(value) {
	if (value == null || typeof value !== "object" || Array.isArray(value)) return false;
	const prototype = Object.getPrototypeOf(value);
	return prototype === Object.prototype || prototype === null;
}
/**
* Checks the JSON constraints that types cannot express: finite numbers, no
* cycles, and no array holes. These would otherwise be silently changed by
* `JSON.stringify` or make it throw.
*/
function isSerializableJSON(value, ancestors = /* @__PURE__ */ new Set()) {
	if (typeof value === "number") return Number.isFinite(value);
	if (value == null || typeof value !== "object") return true;
	if (ancestors.has(value)) return false;
	ancestors.add(value);
	const valid = Array.isArray(value) ? Array.from(value.keys()).every((index) => index in value && isSerializableJSON(value[index], ancestors)) : Object.values(value).every((item) => isSerializableJSON(item, ancestors));
	ancestors.delete(value);
	return valid;
}
function invalidInput(parameter, value, message) {
	throw new InvalidArgumentError({
		parameter,
		value,
		message
	});
}
function validateDecisionState(state) {
	if (Array.isArray(state) && Array.from(state.keys()).some((index) => !(index in state))) invalidInput("state", state, "state parts must not contain array holes");
	if (!isSerializableJSON(Array.isArray(state) ? state.flatMap((part) => part.type === "json" ? [part.value] : []) : state)) invalidInput("state", state, "JSON content must not contain non-finite numbers, cycles, or array holes");
}
function validateDecisionInput({ state, questions }) {
	validateDecisionState(state);
	if (Object.keys(questions).length === 0) invalidInput("questions", questions, "must be a nonempty question map");
	for (const [id, question] of Object.entries(questions)) {
		const parameter = `questions.${id}`;
		if (!isSerializableJSON(question.instructions) || "criteria" in question && !isSerializableJSON(question.criteria)) invalidInput(parameter, question, "instructions and criteria must not contain non-finite numbers, cycles, or array holes");
		switch (question.type) {
			case "choice":
				if (Object.keys(question.criteria).length === 0) invalidInput(parameter, question, "choice criteria must be a nonempty option map");
				break;
			case "score":
				if (question.criteria.length === 0) invalidInput(parameter, question, "score criteria must contain at least one ordered level");
				break;
			case "boolean": {
				const criteria = question.criteria;
				if (question.instructions == null && (criteria == null || !Object.values(criteria).some((value) => value != null))) invalidInput(parameter, question, "boolean questions require instructions or at least one non-null criterion");
				if (criteria != null && Object.keys(criteria).some((key) => key !== "true" && key !== "false")) invalidInput(parameter, question, "boolean criteria may only describe true and false");
				break;
			}
		}
	}
}
function invalidAnswer$1(answers, message) {
	throw new InvalidResponseDataError$1({
		data: answers,
		message
	});
}
function isProbability(value) {
	return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
}
function hasExactKeys(value, keys) {
	return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
}
function validateDistribution(value, keys, answers, id, roundingError) {
	if (!isRecord$1(value) || !hasExactKeys(value, keys) || !Object.values(value).every(isProbability)) invalidAnswer$1(answers, `Question "${id}" must have a complete distribution of finite probabilities in [0, 1].`);
	const sum = Object.values(value).reduce((total, probability) => total + probability, 0);
	if (Math.abs(sum - 1) > tolerance + keys.length * roundingError) invalidAnswer$1(answers, `Question "${id}" probabilities must sum to 1 within the declared rounding precision.`);
}
function validateDecisionAnswers({ questions, answers, rounding }) {
	function roundingError(decimals) {
		if (decimals === void 0) return 0;
		if (!Number.isInteger(decimals) || decimals < 0 || decimals > 15) invalidAnswer$1(answers, "Decision rounding decimals must be integers between 0 and 15.");
		return .5 * 10 ** -decimals;
	}
	const probabilityError = roundingError(rounding?.probabilityDecimals);
	const scoreError = roundingError(rounding?.scoreDecimals);
	if (!isRecord$1(answers) || !hasExactKeys(answers, Object.keys(questions))) invalidAnswer$1(answers, "Decision must return exactly one answer for every question.");
	for (const [id, question] of Object.entries(questions)) {
		const answer = answers[id];
		if (isRecord$1(answer) && answer.type === "refusal") continue;
		if (!isRecord$1(answer) || answer.type !== question.type) invalidAnswer$1(answers, `Question "${id}" returned an answer with the wrong type.`);
		switch (question.type) {
			case "choice":
				if (typeof answer.choice !== "string" || !Object.hasOwn(question.criteria, answer.choice)) invalidAnswer$1(answers, `Question "${id}" selected an unknown option.`);
				if (answer.probabilities !== void 0) {
					validateDistribution(answer.probabilities, Object.keys(question.criteria), answers, id, probabilityError);
					const selected = answer.probabilities[answer.choice];
					if (Object.values(answer.probabilities).some((probability) => probability > selected + tolerance + 2 * probabilityError)) invalidAnswer$1(answers, `Question "${id}" did not select a highest-probability option.`);
				}
				break;
			case "score":
				if (typeof answer.score !== "number" || !Number.isFinite(answer.score) || answer.score < 0 || answer.score > question.criteria.length - 1) invalidAnswer$1(answers, `Question "${id}" score must be in [0, ${question.criteria.length - 1}].`);
				if (answer.probabilities !== void 0) {
					const keys = question.criteria.map((_, index) => String(index));
					validateDistribution(answer.probabilities, keys, answers, id, probabilityError);
					const mean = Object.entries(answer.probabilities).reduce((total, [index, probability]) => total + Number(index) * probability, 0);
					const meanRoundingError = keys.reduce((total, index) => total + Number(index) * probabilityError, 0);
					if (Math.abs(mean - answer.score) > tolerance + meanRoundingError + scoreError) invalidAnswer$1(answers, `Question "${id}" score must equal the probability-weighted mean within the declared rounding precision.`);
				}
				break;
			case "box": {
				const box = answer.box;
				if (!isRecord$1(box) || !hasExactKeys(box, [
					"top",
					"bottom",
					"left",
					"right"
				]) || !isProbability(box.left) || !isProbability(box.right) || !isProbability(box.top) || !isProbability(box.bottom) || !(box.left < box.right) || !(box.top < box.bottom)) invalidAnswer$1(answers, `Question "${id}" must return box edges in [0, 1] with left < right and top < bottom.`);
				break;
			}
			case "boolean": if (!isProbability(answer.probability)) invalidAnswer$1(answers, `Question "${id}" must return P(true) as a finite probability in [0, 1].`);
		}
	}
}
//#endregion
//#region src/decide/decide.ts
const originalGenerateCallId$4 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/** Decide answers to typed questions against one shared state. Experimental. */
async function decide({ model: modelArg, state, questions, maxOutputTokens, reasoning, maxRetries, abortSignal, experimental_download: download, headers, providerOptions = {}, telemetry, runtimeContext = {}, onStart, onEnd, _internal: { generateCallId = originalGenerateCallId$4 } = {} }) {
	const model = resolveDecisionModel(modelArg);
	prepareLanguageModelCallOptions({ maxOutputTokens });
	validateDecisionInput({
		state,
		questions
	});
	for (const [questionId, question] of Object.entries(questions)) if (!model.supportedQuestionTypes.includes(question.type)) throw new Experimental_DecisionUnsupportedQuestionTypeError$1({
		questionId,
		questionType: question.type,
		provider: model.provider,
		modelId: model.modelId
	});
	const callId = generateCallId();
	const { maxRetries: resolvedMaxRetries, retry } = prepareRetries({
		maxRetries,
		abortSignal
	});
	const telemetryDispatcher = createRestrictedTelemetryDispatcher$1({ telemetry });
	const runInTracingChannelSpan = telemetryDispatcher.runInTracingChannelSpan ?? (async ({ execute }) => await execute());
	const startEvent = {
		callId,
		operationId: "ai.decide",
		runtimeContext,
		provider: model.provider,
		modelId: model.modelId,
		state,
		questions,
		maxOutputTokens,
		reasoning,
		maxRetries: resolvedMaxRetries,
		headers,
		providerOptions
	};
	return await runInTracingChannelSpan({
		type: "experimental_decide",
		event: startEvent,
		execute: async () => {
			await notify({
				event: startEvent,
				callbacks: [onStart, telemetryDispatcher.onStart]
			});
			try {
				const preparedState = await prepareDecisionState({
					state,
					abortSignal,
					download
				});
				const modelCallEvent = {
					callId,
					operationId: "ai.decide.doDecide",
					provider: model.provider,
					modelId: model.modelId,
					state: preparedState,
					questions
				};
				await notify({
					event: modelCallEvent,
					callbacks: [telemetryDispatcher.experimental_onDecisionModelCallStart]
				});
				const result = await retry(async () => {
					abortSignal?.throwIfAborted();
					return await model.doDecide({
						state: preparedState,
						questions,
						maxOutputTokens,
						reasoning,
						abortSignal,
						headers: withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`),
						providerOptions
					});
				});
				abortSignal?.throwIfAborted();
				validateDecisionAnswers({
					questions,
					answers: result.answers,
					rounding: result.rounding
				});
				const refusedQuestionIds = Object.keys(questions).filter((id) => result.answers[id]?.type === "refusal");
				if (refusedQuestionIds.length > 0) throw new Experimental_DecisionRefusalError$1({
					questionIds: refusedQuestionIds,
					provider: model.provider,
					modelId: model.modelId
				});
				await notify({
					event: {
						...modelCallEvent,
						...result
					},
					callbacks: [telemetryDispatcher.experimental_onDecisionModelCallEnd]
				});
				logWarnings({
					warnings: result.warnings,
					provider: model.provider,
					model: model.modelId
				});
				const inputTokens = result.usage?.inputTokens;
				const outputTokens = result.usage?.outputTokens;
				const decisionResult = {
					answers: result.answers,
					usage: {
						inputTokens,
						outputTokens,
						totalTokens: inputTokens != null && outputTokens != null ? inputTokens + outputTokens : void 0
					},
					warnings: result.warnings,
					rounding: result.rounding,
					providerMetadata: result.providerMetadata,
					response: {
						...result.response,
						timestamp: result.response?.timestamp ?? /* @__PURE__ */ new Date(),
						modelId: result.response?.modelId ?? model.modelId
					}
				};
				await notify({
					event: {
						...startEvent,
						...decisionResult
					},
					callbacks: [onEnd, telemetryDispatcher.onEnd]
				});
				return decisionResult;
			} catch (error) {
				await telemetryDispatcher.onError?.({
					callId,
					error
				});
				throw error;
			}
		}
	});
}
//#endregion
//#region src/decide/index.ts
/** @deprecated Use `experimental_decide` instead. */
const experimental_evaluate = decide;
//#endregion
//#region src/extract/validate-extraction.ts
const durationUnits = [
	"seconds",
	"minutes",
	"hours",
	"days",
	"weeks",
	"months",
	"years"
];
const listItems = [
	"text",
	"number",
	"date"
];
const time = /^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$/;
const datetime = /^\d{4}-\d{2}-\d{2}T([01]\d|2[0-3]):[0-5]\d(:[0-5]\d(\.\d{1,9})?)?(Z|[+-]([01]\d|2[0-3]):[0-5]\d)?$/;
function isDate(value) {
	if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(value)) return false;
	const date = /* @__PURE__ */ new Date(`${value}T00:00:00Z`);
	return !Number.isNaN(date.getTime()) && date.toISOString().slice(0, 10) === value;
}
function isNumber(value, { integer, decimals }) {
	return typeof value === "number" && Number.isFinite(value) && (!integer || Number.isInteger(value)) && (decimals === void 0 || Number(value.toFixed(decimals)) === value);
}
function isDenseArray(value) {
	if (!Array.isArray(value) || Object.keys(value).length !== value.length) return false;
	for (let index = 0; index < value.length; index++) if (!Object.hasOwn(value, index)) return false;
	return true;
}
function isValue(field, value) {
	switch (field.type) {
		case "text": return typeof value === "string";
		case "number": return isNumber(value, field);
		case "duration": return isNumber(value, field) && value >= 0;
		case "date": return isDate(value);
		case "time": return typeof value === "string" && time.test(value);
		case "datetime": return typeof value === "string" && datetime.test(value) && isDate(value.slice(0, 10));
	}
}
function isSource(source, state) {
	if (!isRecord$1(source) || typeof source.part !== "number" || !Number.isInteger(source.part) || source.part < 0 || source.part >= state.length) return false;
	const part = state[source.part];
	switch (source.type) {
		case "text": return part.type === "text" && typeof source.start === "number" && typeof source.end === "number" && Number.isInteger(source.start) && Number.isInteger(source.end) && source.start >= 0 && source.start < source.end && source.end <= part.text.length;
		case "file": return part.type === "file";
		default: return false;
	}
}
function validateExtractionInput({ state, fields, referenceDate }) {
	validateDecisionState(state);
	if (referenceDate !== void 0 && !isDate(referenceDate)) invalidInput("referenceDate", referenceDate, "must be a YYYY-MM-DD calendar date");
	if (Object.keys(fields).length === 0) invalidInput("fields", fields, "must be a nonempty field map");
	for (const [id, field] of Object.entries(fields)) {
		const parameter = `fields.${id}`;
		if (!isSerializableJSON(field.instructions)) invalidInput(parameter, field, "instructions must not contain non-finite numbers, cycles, or array holes");
		if ("decimals" in field && field.decimals !== void 0 && !(Number.isInteger(field.decimals) && field.decimals >= 0 && field.decimals <= 6)) invalidInput(parameter, field, "decimals must be an integer from 0 to 6");
		if (field.type === "duration" && field.unit !== void 0 && !durationUnits.includes(field.unit)) invalidInput(parameter, field, `duration unit must be one of ${durationUnits.join(", ")}`);
		if (field.type === "list" && !listItems.includes(field.items)) invalidInput(parameter, field, `list items must be one of ${listItems.join(", ")}`);
	}
}
function invalidAnswer(answers, message) {
	throw new InvalidResponseDataError$1({
		data: answers,
		message
	});
}
function validateExtractionAnswers({ fields, state, answers }) {
	if (!isRecord$1(answers) || !hasExactKeys(answers, Object.keys(fields))) invalidAnswer(answers, "Extraction must return exactly one answer for every field.");
	for (const [id, field] of Object.entries(fields)) {
		const answer = answers[id];
		if (isRecord$1(answer) && answer.type === "refusal") continue;
		if (!isRecord$1(answer) || answer.type !== field.type) invalidAnswer(answers, `Field "${id}" returned an answer with the wrong type.`);
		if (answer.pNull !== void 0 && !isProbability(answer.pNull) || answer.confidence !== void 0 && !isProbability(answer.confidence)) invalidAnswer(answers, `Field "${id}" must return pNull and confidence as finite probabilities in [0, 1].`);
		if (field.type === "list") {
			const item = field.items === "number" ? {
				type: "number",
				integer: field.integer,
				decimals: field.decimals
			} : { type: field.items };
			const value = answer.value;
			if (value !== null && !(isDenseArray(value) && value.every((entry) => isValue(item, entry)))) invalidAnswer(answers, `Field "${id}" must return null or a list of ${field.items} values.`);
			const items = answer.items;
			if (items !== void 0 && !(isDenseArray(items) && Array.isArray(value) && items.length === value.length && items.every((entry) => isRecord$1(entry) && (entry.confidence === void 0 || isProbability(entry.confidence)) && (entry.source === void 0 || isSource(entry.source, state))))) invalidAnswer(answers, `Field "${id}" must return one item entry per list value, with confidences in [0, 1] and sources inside the state.`);
			continue;
		}
		if (answer.value !== null && !isValue(field, answer.value)) invalidAnswer(answers, `Field "${id}" must return null or a valid ${field.type} value.`);
		if (answer.guess !== void 0 && !isValue(field, answer.guess)) invalidAnswer(answers, `Field "${id}" must return a valid ${field.type} guess.`);
		if (answer.source !== void 0 && !isSource(answer.source, state)) invalidAnswer(answers, `Field "${id}" returned a source outside the state.`);
	}
}
//#endregion
//#region src/extract/extract.ts
/** Extract typed field values from one shared state. Experimental. */
async function extract({ model: modelArg, state, fields, referenceDate, maxOutputTokens, reasoning, maxRetries, abortSignal, experimental_download: download, headers, providerOptions = {} }) {
	const model = resolveExtractionModel(modelArg);
	prepareLanguageModelCallOptions({ maxOutputTokens });
	validateExtractionInput({
		state,
		fields,
		referenceDate
	});
	for (const [fieldId, field] of Object.entries(fields)) if (!model.supportedFieldTypes.includes(field.type)) throw new Experimental_ExtractionUnsupportedFieldTypeError$1({
		fieldId,
		fieldType: field.type,
		provider: model.provider,
		modelId: model.modelId
	});
	const { retry } = prepareRetries({
		maxRetries,
		abortSignal
	});
	const preparedState = await prepareDecisionState({
		state,
		abortSignal,
		download
	});
	const result = await retry(async () => {
		abortSignal?.throwIfAborted();
		return await model.doExtract({
			state: preparedState,
			fields,
			referenceDate,
			maxOutputTokens,
			reasoning,
			abortSignal,
			headers: withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`),
			providerOptions
		});
	});
	abortSignal?.throwIfAborted();
	validateExtractionAnswers({
		fields,
		state: preparedState,
		answers: result.answers
	});
	const refusedFieldIds = Object.keys(fields).filter((id) => result.answers[id]?.type === "refusal");
	if (refusedFieldIds.length > 0) throw new Experimental_ExtractionRefusalError$1({
		fieldIds: refusedFieldIds,
		provider: model.provider,
		modelId: model.modelId
	});
	logWarnings({
		warnings: result.warnings,
		provider: model.provider,
		model: model.modelId
	});
	const inputTokens = result.usage?.inputTokens;
	const outputTokens = result.usage?.outputTokens;
	return {
		answers: result.answers,
		usage: {
			inputTokens,
			outputTokens,
			totalTokens: inputTokens != null && outputTokens != null ? inputTokens + outputTokens : void 0
		},
		warnings: result.warnings,
		providerMetadata: result.providerMetadata,
		response: {
			...result.response,
			timestamp: result.response?.timestamp ?? /* @__PURE__ */ new Date(),
			modelId: result.response?.modelId ?? model.modelId
		}
	};
}
//#endregion
//#region src/generate-text/extract-reasoning-content.ts
function extractReasoningContent(content) {
	const parts = content.filter((content) => content.type === "reasoning");
	return parts.length === 0 ? void 0 : parts.map((content) => content.text).join("\n");
}
//#endregion
//#region src/generate-text/extract-text-content.ts
function extractTextContent(content) {
	const parts = content.filter((content) => content.type === "text");
	if (parts.length === 0) return;
	return parts.map((content) => content.text).join("");
}
//#endregion
//#region src/generate-object/output-strategy.ts
const noSchemaOutputStrategy = {
	type: "no-schema",
	jsonSchema: async () => void 0,
	async validatePartialResult({ value, textDelta }) {
		return {
			success: true,
			value: {
				partial: value,
				textDelta
			}
		};
	},
	async validateFinalResult(value, context) {
		return value === void 0 ? {
			success: false,
			error: new NoObjectGeneratedError({
				message: "No object generated: response did not match schema.",
				text: context.text,
				response: context.response,
				usage: context.usage,
				finishReason: context.finishReason
			})
		} : {
			success: true,
			value
		};
	},
	createElementStream() {
		throw new UnsupportedFunctionalityError$1({ functionality: "element streams in no-schema mode" });
	}
};
const objectOutputStrategy = (schema) => ({
	type: "object",
	jsonSchema: async () => await schema.jsonSchema,
	async validatePartialResult({ value, textDelta }) {
		return {
			success: true,
			value: {
				partial: value,
				textDelta
			}
		};
	},
	async validateFinalResult(value) {
		return safeValidateTypes({
			value,
			schema
		});
	},
	createElementStream() {
		throw new UnsupportedFunctionalityError$1({ functionality: "element streams in object mode" });
	}
});
const arrayOutputStrategy = (schema) => {
	return {
		type: "array",
		createArrayStreamParser: () => createArrayOutputStreamParser(schema, false),
		jsonSchema: async () => {
			const { $schema: _$schema, definitions, $defs, ...itemSchema } = await schema.jsonSchema;
			return {
				$schema: "http://json-schema.org/draft-07/schema#",
				...definitions != null && { definitions },
				...$defs != null && { $defs },
				type: "object",
				properties: { elements: {
					type: "array",
					items: itemSchema
				} },
				required: ["elements"],
				additionalProperties: false
			};
		},
		async validatePartialResult({ value, latestObject, isFirstDelta, isFinalDelta }) {
			if (!isJSONObject(value) || !isJSONArray(value.elements)) return {
				success: false,
				error: new TypeValidationError$1({
					value,
					cause: "value must be an object that contains an array of elements"
				})
			};
			const inputArray = value.elements;
			const resultArray = [];
			for (let i = 0; i < inputArray.length; i++) {
				const element = inputArray[i];
				const result = await safeValidateTypes({
					value: element,
					schema
				});
				if (i === inputArray.length - 1 && !isFinalDelta) continue;
				if (!result.success) return result;
				resultArray.push(result.value);
			}
			const publishedElementCount = latestObject?.length ?? 0;
			let textDelta = "";
			if (isFirstDelta) textDelta += "[";
			if (publishedElementCount > 0) textDelta += ",";
			textDelta += resultArray.slice(publishedElementCount).map((element) => JSON.stringify(element)).join(",");
			if (isFinalDelta) textDelta += "]";
			return {
				success: true,
				value: {
					partial: resultArray,
					textDelta
				}
			};
		},
		async validateFinalResult(value) {
			if (!isJSONObject(value) || !isJSONArray(value.elements)) return {
				success: false,
				error: new TypeValidationError$1({
					value,
					cause: "value must be an object that contains an array of elements"
				})
			};
			const inputArray = value.elements;
			const resultArray = [];
			for (const element of inputArray) {
				const result = await safeValidateTypes({
					value: element,
					schema
				});
				if (!result.success) return result;
				resultArray.push(result.value);
			}
			return {
				success: true,
				value: resultArray
			};
		},
		createElementStream(originalStream) {
			let publishedElements = 0;
			return createAsyncIterableStream(originalStream.pipeThrough(new TransformStream({ transform(chunk, controller) {
				switch (chunk.type) {
					case "object": {
						const array = chunk.object;
						for (; publishedElements < array.length; publishedElements++) controller.enqueue(array[publishedElements]);
						break;
					}
					case "text-delta":
					case "finish":
					case "error": break;
					default: throw new Error(`Unsupported chunk type: ${chunk}`);
				}
			} })));
		}
	};
};
const enumOutputStrategy = (enumValues) => {
	return {
		type: "enum",
		jsonSchema: async () => ({
			$schema: "http://json-schema.org/draft-07/schema#",
			type: "object",
			properties: { result: {
				type: "string",
				enum: enumValues
			} },
			required: ["result"],
			additionalProperties: false
		}),
		async validateFinalResult(value) {
			if (!isJSONObject(value) || typeof value.result !== "string") return {
				success: false,
				error: new TypeValidationError$1({
					value,
					cause: "value must be an object that contains a string in the \"result\" property."
				})
			};
			const result = value.result;
			return enumValues.includes(result) ? {
				success: true,
				value: result
			} : {
				success: false,
				error: new TypeValidationError$1({
					value,
					cause: "value must be a string in the enum"
				})
			};
		},
		async validatePartialResult({ value, textDelta }) {
			if (!isJSONObject(value) || typeof value.result !== "string") return {
				success: false,
				error: new TypeValidationError$1({
					value,
					cause: "value must be an object that contains a string in the \"result\" property."
				})
			};
			const result = value.result;
			const possibleEnumValues = enumValues.filter((enumValue) => enumValue.startsWith(result));
			if (value.result.length === 0 || possibleEnumValues.length === 0) return {
				success: false,
				error: new TypeValidationError$1({
					value,
					cause: "value must be a string in the enum"
				})
			};
			return {
				success: true,
				value: {
					partial: possibleEnumValues.length > 1 ? result : possibleEnumValues[0],
					textDelta
				}
			};
		},
		createElementStream() {
			throw new UnsupportedFunctionalityError$1({ functionality: "element streams in enum mode" });
		}
	};
};
function getOutputStrategy({ output, schema, enumValues }) {
	switch (output) {
		case "object": return objectOutputStrategy(asSchema$1(schema));
		case "array": return arrayOutputStrategy(asSchema$1(schema));
		case "enum": return enumOutputStrategy(enumValues);
		case "no-schema": return noSchemaOutputStrategy;
		default: throw new Error(`Unsupported output: ${output}`);
	}
}
//#endregion
//#region src/generate-object/parse-and-validate-object-result.ts
/**
* Parses and validates a result string by parsing it as JSON and validating against the output strategy.
*
* @param result - The result string to parse and validate
* @param outputStrategy - The output strategy containing validation logic
* @param context - Additional context for error reporting
* @returns The validated result
* @throws NoObjectGeneratedError if parsing or validation fails
*/
async function parseAndValidateObjectResult(result, outputStrategy, context) {
	const parseResult = await safeParseJSON({ text: result });
	if (!parseResult.success) throw new NoObjectGeneratedError({
		message: "No object generated: could not parse the response.",
		cause: parseResult.error,
		text: result,
		response: context.response,
		usage: context.usage,
		finishReason: context.finishReason
	});
	const validationResult = await outputStrategy.validateFinalResult(parseResult.value, {
		text: result,
		response: context.response,
		usage: context.usage
	});
	if (!validationResult.success) throw new NoObjectGeneratedError({
		message: "No object generated: response did not match schema.",
		cause: validationResult.error,
		text: result,
		response: context.response,
		usage: context.usage,
		finishReason: context.finishReason
	});
	return validationResult.value;
}
/**
* Parses and validates a result string by parsing it as JSON and validating against the output strategy.
* If the result cannot be parsed, it attempts to repair the result using the repairText function.
*
* @param result - The result string to parse and validate
* @param outputStrategy - The output strategy containing validation logic
* @param repairText - A function that attempts to repair the result string
* @param context - Additional context for error reporting
* @returns The validated result
* @throws NoObjectGeneratedError if parsing or validation fails
*/
async function parseAndValidateObjectResultWithRepair(result, outputStrategy, repairText, context) {
	try {
		return await parseAndValidateObjectResult(result, outputStrategy, context);
	} catch (error) {
		if (repairText != null && NoObjectGeneratedError.isInstance(error) && (JSONParseError$1.isInstance(error.cause) || TypeValidationError$1.isInstance(error.cause))) {
			const repairedText = await repairText({
				text: result,
				error: error.cause
			});
			if (repairedText === null) throw error;
			return await parseAndValidateObjectResult(repairedText, outputStrategy, context);
		}
		throw error;
	}
}
//#endregion
//#region src/generate-object/validate-object-generation-input.ts
function validateObjectGenerationInput({ output, schema, schemaName, schemaDescription, enumValues }) {
	if (output === "no-schema") {
		if (schema != null) throw new InvalidArgumentError({
			parameter: "schema",
			value: schema,
			message: "Schema is not supported for no-schema output."
		});
		if (schemaDescription != null) throw new InvalidArgumentError({
			parameter: "schemaDescription",
			value: schemaDescription,
			message: "Schema description is not supported for no-schema output."
		});
		if (schemaName != null) throw new InvalidArgumentError({
			parameter: "schemaName",
			value: schemaName,
			message: "Schema name is not supported for no-schema output."
		});
		if (enumValues != null) throw new InvalidArgumentError({
			parameter: "enumValues",
			value: enumValues,
			message: "Enum values are not supported for no-schema output."
		});
	}
	if (output === "object") {
		if (enumValues != null) throw new InvalidArgumentError({
			parameter: "enumValues",
			value: enumValues,
			message: "Enum values are not supported for object output."
		});
	}
	if (output === "array") {
		if (enumValues != null) throw new InvalidArgumentError({
			parameter: "enumValues",
			value: enumValues,
			message: "Enum values are not supported for array output."
		});
	}
	if (output === "enum") {
		if (schema != null) throw new InvalidArgumentError({
			parameter: "schema",
			value: schema,
			message: "Schema is not supported for enum output."
		});
		if (schemaDescription != null) throw new InvalidArgumentError({
			parameter: "schemaDescription",
			value: schemaDescription,
			message: "Schema description is not supported for enum output."
		});
		if (schemaName != null) throw new InvalidArgumentError({
			parameter: "schemaName",
			value: schemaName,
			message: "Schema name is not supported for enum output."
		});
		for (const value of enumValues ?? []) if (typeof value !== "string") throw new InvalidArgumentError({
			parameter: "enumValues",
			value,
			message: "Enum values must be strings."
		});
	}
}
//#endregion
//#region src/generate-object/generate-object.ts
const originalGenerateId$1 = createIdGenerator$1({
	prefix: "aiobj",
	size: 24
});
/**
* Generate a structured, typed object for a given prompt and schema using a language model.
*
* This function does not stream the output. If you want to stream the output, use `streamObject` instead.
*
* @param model - The language model to use.
*
* @param system - A system message that will be part of the prompt.
* @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
* @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
* @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. Default: false.
*
* @param maxOutputTokens - Maximum number of tokens to generate.
* @param temperature - Temperature setting.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topP - Nucleus sampling.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topK - Only sample from the top K options for each subsequent token.
* Used to remove "long tail" low probability responses.
* Recommended for advanced use cases only. You usually only need to use temperature.
* @param presencePenalty - Presence penalty setting.
* It affects the likelihood of the model to repeat information that is already in the prompt.
* The value is passed through to the provider. The range depends on the provider and model.
* @param frequencyPenalty - Frequency penalty setting.
* It affects the likelihood of the model to repeatedly use the same words or phrases.
* The value is passed through to the provider. The range depends on the provider and model.
* @param stopSequences - Stop sequences.
* If set, the model will stop generating text when one of the stop sequences is generated.
* @param seed - The seed (integer) to use for random sampling.
* If set and supported by the model, calls will generate deterministic results.
*
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
*
* @param schema - The schema of the object that the model should generate.
* @param schemaName - Optional name of the output that should be generated.
* Used by some providers for additional LLM guidance, e.g.
* via tool or schema name.
* @param schemaDescription - Optional description of the output that should be generated.
* Used by some providers for additional LLM guidance, e.g.
* via tool or schema description.
*
* @param output - The type of the output.
*
* - 'object': The output is an object.
* - 'array': The output is an array.
* - 'enum': The output is an enum.
* - 'no-schema': The output is not a schema.
*
* @param repairText - A function that attempts to repair the raw output of the model
* to enable JSON parsing.
* @param experimental_repairText - Deprecated alias for `repairText`.
*
* @param telemetry - Optional telemetry configuration.
*
* @param providerOptions - Additional provider-specific options. They are passed through
* to the provider from the AI SDK and enable provider-specific
* functionality that can be fully encapsulated in the provider.
*
* @param onStart - Callback invoked when generation begins, before the LLM call.
* @param experimental_onStart - Deprecated alias for `onStart`.
* @param onStepStart - Callback invoked when the model call begins.
* @param experimental_onStepStart - Deprecated alias for `onStepStart`.
* @param onStepEnd - Callback invoked when the model call completes with the raw result.
* @param onStepFinish - Deprecated alias for `onStepEnd`.
* @param onFinish - Callback invoked when the entire operation completes with the parsed object.
*
* @returns
* A result object that contains the generated object, the finish reason, the token usage, and additional information.
*
* @deprecated Use `generateText` with an `output` setting instead.
*/
async function generateObject(options) {
	logWarnings({ warnings: [{
		type: "deprecated",
		setting: "generateObject",
		message: "Use generateText with an output setting instead."
	}] });
	const { model: modelArg, output = "object", instructions, system, prompt, messages, allowSystemInMessages, maxRetries: maxRetriesArg, abortSignal, headers, experimental_repairText, repairText = experimental_repairText, experimental_telemetry, telemetry = experimental_telemetry, experimental_download: download, providerOptions, onStart, experimental_onStart, onStepStart, experimental_onStepStart, onStepEnd, onStepFinish, onFinish, _internal: { generateId = originalGenerateId$1, currentDate = () => /* @__PURE__ */ new Date() } = {}, ...settings } = options;
	const model = resolveLanguageModel(modelArg);
	const enumValues = "enum" in options ? options.enum : void 0;
	const { schema: inputSchema, schemaDescription, schemaName } = "schema" in options ? options : {};
	validateObjectGenerationInput({
		output,
		schema: inputSchema,
		schemaName,
		schemaDescription,
		enumValues
	});
	const { maxRetries, retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	const outputStrategy = getOutputStrategy({
		output,
		schema: inputSchema,
		enumValues
	});
	const callSettings = prepareLanguageModelCallOptions(settings);
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const telemetryDispatcher = createTelemetryDispatcher({ telemetry });
	const resolvedOnStart = onStart ?? experimental_onStart;
	const resolvedOnStepStart = onStepStart ?? experimental_onStepStart;
	const resolvedOnStepEnd = onStepEnd ?? onStepFinish;
	const jsonSchema = await outputStrategy.jsonSchema();
	const callId = generateId();
	await notify({
		event: {
			callId,
			operationId: "ai.generateObject",
			provider: model.provider,
			modelId: model.modelId,
			system: instructions ?? system,
			prompt,
			messages,
			maxOutputTokens: callSettings.maxOutputTokens,
			temperature: callSettings.temperature,
			topP: callSettings.topP,
			topK: callSettings.topK,
			presencePenalty: callSettings.presencePenalty,
			frequencyPenalty: callSettings.frequencyPenalty,
			seed: callSettings.seed,
			maxRetries,
			headers: headersWithUserAgent,
			providerOptions,
			output: outputStrategy.type,
			schema: jsonSchema,
			schemaName,
			schemaDescription
		},
		callbacks: [resolvedOnStart, telemetryDispatcher.onStart]
	});
	try {
		const promptMessages = await convertToLanguageModelPrompt({
			prompt: await standardizePrompt({
				instructions,
				system,
				prompt,
				messages,
				allowSystemInMessages
			}),
			supportedUrls: await model.supportedUrls,
			download,
			abortSignal,
			provider: model.provider.split(".")[0]
		});
		await notify({
			event: {
				callId,
				stepNumber: 0,
				provider: model.provider,
				modelId: model.modelId,
				providerOptions,
				headers: headersWithUserAgent,
				promptMessages
			},
			callbacks: [resolvedOnStepStart, telemetryDispatcher.onObjectStepStart]
		});
		const generateResult = await retry(() => model.doGenerate({
			responseFormat: {
				type: "json",
				schema: jsonSchema,
				name: schemaName,
				description: schemaDescription
			},
			...prepareLanguageModelCallOptions(settings),
			prompt: promptMessages,
			providerOptions,
			abortSignal,
			headers: headersWithUserAgent
		}));
		const responseData = {
			id: generateResult.response?.id ?? generateId(),
			timestamp: generateResult.response?.timestamp ?? currentDate(),
			modelId: generateResult.response?.modelId ?? model.modelId,
			headers: generateResult.response?.headers,
			body: generateResult.response?.body
		};
		const text = extractTextContent(generateResult.content);
		const reasoning = extractReasoningContent(generateResult.content);
		if (text === void 0) throw new NoObjectGeneratedError({
			message: "No object generated: the model did not return a response.",
			response: responseData,
			usage: asLanguageModelUsage(generateResult.usage),
			finishReason: generateResult.finishReason.unified
		});
		const finishReason = generateResult.finishReason.unified;
		const usage = asLanguageModelUsage(generateResult.usage);
		const warnings = generateResult.warnings;
		const resultProviderMetadata = generateResult.providerMetadata;
		const request = sanitizeRequestMetadata(generateResult.request) ?? {};
		const response = responseData;
		logWarnings({
			warnings,
			provider: model.provider,
			model: model.modelId
		});
		await notify({
			event: {
				callId,
				stepNumber: 0,
				provider: model.provider,
				modelId: model.modelId,
				finishReason,
				usage,
				objectText: text,
				msToFirstChunk: void 0,
				reasoning,
				warnings,
				request,
				response,
				providerMetadata: resultProviderMetadata
			},
			callbacks: [resolvedOnStepEnd, telemetryDispatcher.onObjectStepEnd]
		});
		const object = await parseAndValidateObjectResultWithRepair(generateResult.structuredOutputText ?? text, outputStrategy, repairText, {
			response,
			usage,
			finishReason
		});
		await notify({
			event: {
				callId,
				object,
				error: void 0,
				reasoning,
				finishReason,
				usage,
				warnings,
				request,
				response,
				providerMetadata: resultProviderMetadata
			},
			callbacks: [onFinish, telemetryDispatcher.onEnd]
		});
		return new DefaultGenerateObjectResult({
			object,
			reasoning,
			finishReason,
			usage,
			warnings,
			request,
			response,
			providerMetadata: resultProviderMetadata
		});
	} catch (error) {
		await telemetryDispatcher.onError?.({
			callId,
			error
		});
		throw wrapGatewayError(error);
	}
}
var DefaultGenerateObjectResult = class {
	constructor(options) {
		this.object = options.object;
		this.finishReason = options.finishReason;
		this.usage = options.usage;
		this.warnings = options.warnings;
		this.providerMetadata = options.providerMetadata;
		this.response = options.response;
		this.request = options.request;
		this.reasoning = options.reasoning;
	}
	toJsonResponse(init) {
		return new Response(JSON.stringify(this.object), {
			status: init?.status ?? 200,
			headers: prepareHeaders(init?.headers, { "content-type": "application/json; charset=utf-8" })
		});
	}
};
//#endregion
//#region src/util/cosine-similarity.ts
/**
* Calculates the cosine similarity between two vectors. This is a useful metric for
* comparing the similarity of two vectors such as embeddings.
*
* @param vector1 - The first vector.
* @param vector2 - The second vector.
*
* @returns The cosine similarity between vector1 and vector2, or 0 if either vector is the zero vector.
*
* @throws {InvalidArgumentError} If the vectors do not have the same length.
*/
function cosineSimilarity(vector1, vector2) {
	if (vector1.length !== vector2.length) throw new InvalidArgumentError({
		parameter: "vector1,vector2",
		value: {
			vector1Length: vector1.length,
			vector2Length: vector2.length
		},
		message: `Vectors must have the same length`
	});
	const n = vector1.length;
	if (n === 0) return 0;
	let magnitudeSquared1 = 0;
	let magnitudeSquared2 = 0;
	let dotProduct = 0;
	for (let i = 0; i < n; i++) {
		const value1 = vector1[i];
		const value2 = vector2[i];
		magnitudeSquared1 += value1 * value1;
		magnitudeSquared2 += value2 * value2;
		dotProduct += value1 * value2;
	}
	return magnitudeSquared1 === 0 || magnitudeSquared2 === 0 ? 0 : dotProduct / (Math.sqrt(magnitudeSquared1) * Math.sqrt(magnitudeSquared2));
}
//#endregion
//#region src/util/download/create-download.ts
/**
* Creates a download function with configurable options.
*
* @param options - Configuration options for the download function.
* @param options.maxBytes - Maximum allowed download size in bytes. Default: 2 GiB.
* @param options.fetch - Fetch transport, e.g. guarded-fetch for DNS validation on Node.js.
* @returns A download function that can be passed to `transcribe()`,
* `experimental_generateVideo()`, or as `experimental_download` to
* `generateText()` and `streamText()`.
*/
function createDownload(options) {
	const download$1 = ({ url, abortSignal }) => download({
		url,
		maxBytes: options?.maxBytes,
		abortSignal,
		fetch: options?.fetch
	});
	return ((requests) => Array.isArray(requests) ? Promise.all(requests.map((request) => request.isUrlSupportedByModel ? null : download$1(request))) : download$1(requests));
}
//#endregion
//#region src/util/data-url.ts
const { atob: atob$1 } = globalThis;
/**
* Converts a data URL of type text/* to a text string.
*
* @throws {InvalidArgumentError} If the data URL is malformed or cannot be decoded.
*/
function getTextFromDataUrl(dataUrl) {
	const [header, base64Content] = dataUrl.split(",");
	const mediaType = header.split(";")[0].split(":")[1];
	const charsetMatch = /(?:^|;)\s*charset\s*=\s*(?:"([^"]+)"|([^;\s]+))/i.exec(header);
	const charset = charsetMatch?.[1] ?? charsetMatch?.[2];
	if (mediaType == null || base64Content == null) throw new InvalidArgumentError({
		parameter: "dataUrl",
		value: dataUrl,
		message: "Invalid data URL format"
	});
	try {
		const byteString = atob$1(base64Content);
		if (charset == null) return byteString;
		return new TextDecoder(charset).decode(Uint8Array.from(byteString, (byte) => byte.codePointAt(0)));
	} catch {
		throw new InvalidArgumentError({
			parameter: "dataUrl",
			value: dataUrl,
			message: "Error decoding data URL"
		});
	}
}
//#endregion
//#region src/util/serial-job-executor.ts
var SerialJobExecutor = class {
	constructor() {
		this.queue = [];
		this.isProcessing = false;
		this.idleWaiters = [];
	}
	async processQueue() {
		if (this.isProcessing) return;
		this.isProcessing = true;
		try {
			while (this.queue.length > 0) {
				await this.queue[0]();
				this.queue.shift();
			}
		} finally {
			this.isProcessing = false;
			for (const resolve of this.idleWaiters.splice(0)) resolve();
		}
	}
	async run(job) {
		return new Promise((resolve, reject) => {
			this.queue.push(async () => {
				try {
					await job();
					resolve();
				} catch (error) {
					reject(error);
				}
			});
			this.processQueue();
		});
	}
	async waitForIdle() {
		if (!this.isProcessing && this.queue.length === 0) return;
		await new Promise((resolve) => {
			this.idleWaiters.push(resolve);
		});
	}
};
//#endregion
//#region src/util/simulate-readable-stream.ts
/**
* Creates a ReadableStream that emits the provided values with an optional delay between each value.
*
* @param options - The configuration options
* @param options.chunks - Array of values to be emitted by the stream
* @param options.initialDelayInMs - Optional initial delay in milliseconds before emitting the first value (default: 0). Can be set to `null` to skip the initial delay. The difference between `initialDelayInMs: null` and `initialDelayInMs: 0` is that `initialDelayInMs: null` will emit the values without any delay, while `initialDelayInMs: 0` will emit the values with a delay of 0 milliseconds.
* @param options.chunkDelayInMs - Optional delay in milliseconds between emitting each value (default: 0). Can be set to `null` to skip the delay. The difference between `chunkDelayInMs: null` and `chunkDelayInMs: 0` is that `chunkDelayInMs: null` will emit the values without any delay, while `chunkDelayInMs: 0` will emit the values with a delay of 0 milliseconds.
* @returns A ReadableStream that emits the provided values
*/
function simulateReadableStream({ chunks, initialDelayInMs = 0, chunkDelayInMs = 0, _internal }) {
	const delay$3 = _internal?.delay ?? delay;
	let index = 0;
	return new ReadableStream({ async pull(controller) {
		if (index < chunks.length) {
			await delay$3(index === 0 ? initialDelayInMs : chunkDelayInMs);
			controller.enqueue(chunks[index++]);
		} else controller.close();
	} });
}
//#endregion
//#region src/generate-object/stream-object.ts
const originalGenerateId = createIdGenerator$1({
	prefix: "aiobj",
	size: 24
});
async function markPromiseAsHandled(promise) {
	try {
		await promise;
	} catch {}
}
/**
* Generate a structured, typed object for a given prompt and schema using a language model.
*
* This function streams the output. If you do not want to stream the output, use `generateObject` instead.
*
* @param model - The language model to use.
*
* @param system - A system message that will be part of the prompt.
* @param prompt - A simple text prompt. You can either use `prompt` or `messages` but not both.
* @param messages - A list of messages. You can either use `prompt` or `messages` but not both.
* @param allowSystemInMessages - Whether system messages are allowed in the `prompt` or `messages` fields. Default: false.
*
* @param maxOutputTokens - Maximum number of tokens to generate.
* @param temperature - Temperature setting.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topP - Nucleus sampling.
* The value is passed through to the provider. The range depends on the provider and model.
* It is recommended to set either `temperature` or `topP`, but not both.
* @param topK - Only sample from the top K options for each subsequent token.
* Used to remove "long tail" low probability responses.
* Recommended for advanced use cases only. You usually only need to use temperature.
* @param presencePenalty - Presence penalty setting.
* It affects the likelihood of the model to repeat information that is already in the prompt.
* The value is passed through to the provider. The range depends on the provider and model.
* @param frequencyPenalty - Frequency penalty setting.
* It affects the likelihood of the model to repeatedly use the same words or phrases.
* The value is passed through to the provider. The range depends on the provider and model.
* @param stopSequences - Stop sequences.
* If set, the model will stop generating text when one of the stop sequences is generated.
* @param seed - The seed (integer) to use for random sampling.
* If set and supported by the model, calls will generate deterministic results.
*
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
*
* @param schema - The schema of the object that the model should generate.
* @param schemaName - Optional name of the output that should be generated.
* Used by some providers for additional LLM guidance, e.g.
* via tool or schema name.
* @param schemaDescription - Optional description of the output that should be generated.
* Used by some providers for additional LLM guidance, e.g.
* via tool or schema description.
*
* @param output - The type of the output.
*
* - 'object': The output is an object.
* - 'array': The output is an array.
* - 'enum': The output is an enum.
* - 'no-schema': The output is not a schema.
*
* @param repairText - A function that attempts to repair the raw output of the model
* to enable JSON parsing.
* @param experimental_repairText - Deprecated alias for `repairText`.
*
* @param telemetry - Optional telemetry configuration.
*
* @param providerOptions - Additional provider-specific options. They are passed through
* to the provider from the AI SDK and enable provider-specific
* functionality that can be fully encapsulated in the provider.
*
* @returns
* A result object for accessing the partial object stream and additional information.
*
* @deprecated Use `streamText` with an `output` setting instead.
*/
function streamObject(options) {
	logWarnings({ warnings: [{
		type: "deprecated",
		setting: "streamObject",
		message: "Use streamText with an output setting instead."
	}] });
	const { model, output = "object", instructions, system, prompt, messages, allowSystemInMessages, maxRetries, abortSignal, headers, experimental_repairText, repairText = experimental_repairText, experimental_telemetry, telemetry = experimental_telemetry, experimental_download: download, providerOptions, onStart, experimental_onStart, onStepStart, experimental_onStepStart, onStepEnd, onStepFinish, onError = ({ error }) => {
		console.error(error);
	}, onFinish, _internal: { generateId = originalGenerateId, currentDate = () => /* @__PURE__ */ new Date(), now: now$1 = now } = {}, ...settings } = options;
	const enumValues = "enum" in options && options.enum ? options.enum : void 0;
	const { schema: inputSchema, schemaDescription, schemaName } = "schema" in options ? options : {};
	validateObjectGenerationInput({
		output,
		schema: inputSchema,
		schemaName,
		schemaDescription,
		enumValues
	});
	return new DefaultStreamObjectResult({
		model,
		telemetry,
		headers,
		settings,
		maxRetries,
		abortSignal,
		outputStrategy: getOutputStrategy({
			output,
			schema: inputSchema,
			enumValues
		}),
		instructions,
		system,
		prompt,
		messages,
		allowSystemInMessages,
		schemaName,
		schemaDescription,
		providerOptions,
		repairText,
		onStart: onStart ?? experimental_onStart,
		onStepStart: onStepStart ?? experimental_onStepStart,
		onStepFinish: onStepEnd ?? onStepFinish,
		onError,
		onFinish,
		download,
		generateId,
		currentDate,
		now: now$1
	});
}
var DefaultStreamObjectResult = class {
	constructor({ model: modelArg, headers, telemetry, settings, maxRetries: maxRetriesArg, abortSignal, outputStrategy, instructions, system, prompt, messages, allowSystemInMessages, schemaName, schemaDescription, providerOptions, repairText, onStart, onStepStart, onStepFinish, onError, onFinish, download, generateId, currentDate, now }) {
		this._object = new DelayedPromise();
		this._usage = new DelayedPromise();
		this._providerMetadata = new DelayedPromise();
		this._warnings = new DelayedPromise();
		this._request = new DelayedPromise();
		this._response = new DelayedPromise();
		this._finishReason = new DelayedPromise();
		const model = resolveLanguageModel(modelArg);
		const { maxRetries, retry } = prepareRetries({
			maxRetries: maxRetriesArg,
			abortSignal
		});
		const callSettings = prepareLanguageModelCallOptions(settings);
		const telemetryDispatcher = createTelemetryDispatcher({ telemetry });
		const self = this;
		const stitchableStream = createStitchableStream();
		const eventProcessor = new TransformStream({ transform(chunk, controller) {
			controller.enqueue(chunk);
			if (chunk.type === "error") notify({
				event: { error: wrapGatewayError(chunk.error) },
				callbacks: onError
			});
		} });
		this.baseStream = stitchableStream.stream.pipeThrough(eventProcessor);
		const callId = generateId();
		(async () => {
			const jsonSchema = await outputStrategy.jsonSchema();
			await notify({
				event: {
					callId,
					operationId: "ai.streamObject",
					provider: model.provider,
					modelId: model.modelId,
					system: instructions ?? system,
					prompt,
					messages,
					maxOutputTokens: callSettings.maxOutputTokens,
					temperature: callSettings.temperature,
					topP: callSettings.topP,
					topK: callSettings.topK,
					presencePenalty: callSettings.presencePenalty,
					frequencyPenalty: callSettings.frequencyPenalty,
					seed: callSettings.seed,
					maxRetries,
					headers,
					providerOptions,
					output: outputStrategy.type,
					schema: jsonSchema,
					schemaName,
					schemaDescription
				},
				callbacks: [onStart, telemetryDispatcher.onStart]
			});
			const standardizedPrompt = await standardizePrompt({
				instructions,
				system,
				prompt,
				messages,
				allowSystemInMessages
			});
			const callOptions = {
				responseFormat: {
					type: "json",
					schema: jsonSchema,
					name: schemaName,
					description: schemaDescription
				},
				...prepareLanguageModelCallOptions(settings),
				prompt: await convertToLanguageModelPrompt({
					prompt: standardizedPrompt,
					supportedUrls: await model.supportedUrls,
					download,
					abortSignal,
					provider: model.provider.split(".")[0]
				}),
				providerOptions,
				abortSignal,
				headers,
				includeRawChunks: false
			};
			await notify({
				event: {
					callId,
					stepNumber: 0,
					provider: model.provider,
					modelId: model.modelId,
					providerOptions,
					headers,
					promptMessages: callOptions.prompt
				},
				callbacks: [onStepStart, telemetryDispatcher.onObjectStepStart]
			});
			const transformer = { transform: (chunk, controller) => {
				switch (chunk.type) {
					case "text-delta":
						controller.enqueue(chunk.delta);
						break;
					case "response-metadata":
					case "finish":
					case "error":
					case "stream-start": controller.enqueue(chunk);
				}
			} };
			const startTimestampMs = now();
			const { stream, response, request: rawRequest } = await retry(() => model.doStream(callOptions));
			const request = sanitizeRequestMetadata(rawRequest);
			self._request.resolve(request ?? {});
			let warnings;
			let usage = createNullLanguageModelUsage();
			let finishReason;
			let providerMetadata;
			let object;
			let error;
			let terminalError;
			let msToFirstChunk = void 0;
			let arrayStreamParser = outputStrategy.createArrayStreamParser?.();
			let accumulatedText = "";
			let textDelta = "";
			let fullResponse = {
				id: generateId(),
				timestamp: currentDate(),
				modelId: model.modelId
			};
			let latestObjectJson = void 0;
			let latestObject = void 0;
			let isFirstChunk = true;
			let isFirstDelta = true;
			const transformedStream = stream.pipeThrough(new TransformStream(transformer)).pipeThrough(new TransformStream({
				async transform(chunk, controller) {
					if (typeof chunk === "object" && chunk.type === "stream-start") {
						warnings = chunk.warnings;
						return;
					}
					if (isFirstChunk) {
						msToFirstChunk = now() - startTimestampMs;
						isFirstChunk = false;
					}
					if (typeof chunk === "string") {
						accumulatedText += chunk;
						textDelta += chunk;
						if (arrayStreamParser != null) {
							const result = await arrayStreamParser(chunk);
							if (result !== "fallback") {
								if (result != null) {
									latestObject = result.partial;
									controller.enqueue({
										type: "object",
										object: latestObject
									});
									controller.enqueue({
										type: "text-delta",
										textDelta: result.textDelta
									});
									textDelta = "";
									isFirstDelta = false;
								}
								return;
							}
							arrayStreamParser = void 0;
						}
						const { value: currentObjectJson, state: parseState } = await parsePartialJson(accumulatedText);
						if (currentObjectJson !== void 0 && !isDeepEqualData(latestObjectJson, currentObjectJson)) {
							const validationResult = await outputStrategy.validatePartialResult({
								value: currentObjectJson,
								textDelta,
								latestObject,
								isFirstDelta,
								isFinalDelta: parseState === "successful-parse"
							});
							if (validationResult.success && !isDeepEqualData(latestObject, validationResult.value.partial)) {
								latestObjectJson = currentObjectJson;
								latestObject = validationResult.value.partial;
								controller.enqueue({
									type: "object",
									object: latestObject
								});
								controller.enqueue({
									type: "text-delta",
									textDelta: validationResult.value.textDelta
								});
								textDelta = "";
								isFirstDelta = false;
							}
						}
						return;
					}
					switch (chunk.type) {
						case "response-metadata":
							fullResponse = {
								id: chunk.id ?? fullResponse.id,
								timestamp: chunk.timestamp ?? fullResponse.timestamp,
								modelId: chunk.modelId ?? fullResponse.modelId
							};
							break;
						case "error":
							if (terminalError === void 0) {
								const wrappedError = wrapGatewayError(chunk.error);
								terminalError = { error: wrappedError };
								error = wrappedError;
								finishReason = "error";
								self.rejectResultPromises(wrappedError);
							}
							controller.enqueue(chunk);
							break;
						case "finish":
							if (textDelta !== "") controller.enqueue({
								type: "text-delta",
								textDelta
							});
							finishReason = terminalError === void 0 ? chunk.finishReason.unified : "error";
							usage = asLanguageModelUsage(chunk.usage);
							providerMetadata = chunk.providerMetadata;
							controller.enqueue({
								...chunk,
								finishReason,
								usage,
								response: fullResponse
							});
							logWarnings({
								warnings: warnings ?? [],
								provider: model.provider,
								model: model.modelId
							});
							if (terminalError !== void 0) break;
							self._usage.resolve(usage);
							self._providerMetadata.resolve(providerMetadata);
							self._warnings.resolve(warnings);
							self._response.resolve({
								...fullResponse,
								headers: response?.headers
							});
							self._finishReason.resolve(finishReason ?? "other");
							try {
								object = await parseAndValidateObjectResultWithRepair(accumulatedText, outputStrategy, repairText, {
									response: fullResponse,
									usage,
									finishReason
								});
								self._object.resolve(object);
							} catch (e) {
								error = e;
								self._object.reject(e);
							}
							break;
						default: controller.enqueue(chunk);
					}
				},
				async flush(controller) {
					try {
						const finalUsage = usage ?? {
							promptTokens: NaN,
							completionTokens: NaN,
							totalTokens: NaN
						};
						await notify({
							event: {
								callId,
								stepNumber: 0,
								provider: model.provider,
								modelId: model.modelId,
								finishReason: finishReason ?? "other",
								usage: finalUsage,
								objectText: accumulatedText,
								msToFirstChunk,
								reasoning: void 0,
								warnings,
								request: request ?? {},
								response: {
									...fullResponse,
									headers: response?.headers
								},
								providerMetadata
							},
							callbacks: [onStepFinish, telemetryDispatcher.onObjectStepEnd]
						});
						await notify({
							event: {
								callId,
								object,
								error,
								reasoning: void 0,
								finishReason: finishReason ?? "other",
								usage: finalUsage,
								warnings,
								request: request ?? {},
								response: {
									...fullResponse,
									headers: response?.headers
								},
								providerMetadata
							},
							callbacks: [onFinish, telemetryDispatcher.onEnd]
						});
					} catch (error) {
						controller.enqueue({
							type: "error",
							error
						});
					}
				}
			}));
			stitchableStream.addStream(transformedStream, { onError(error) {
				const wrappedError = wrapGatewayError(error);
				self.rejectResultPromises(wrappedError);
				notify({
					event: { error: wrappedError },
					callbacks: onError
				});
			} });
		})().catch(async (error) => {
			self.rejectResultPromises(error);
			await telemetryDispatcher.onError?.({
				callId,
				error
			});
			stitchableStream.addStream(new ReadableStream({ start(controller) {
				controller.enqueue({
					type: "error",
					error
				});
				controller.close();
			} }));
		}).finally(() => {
			stitchableStream.close();
		});
		this.outputStrategy = outputStrategy;
	}
	rejectResultPromises(error) {
		this.rejectResultPromise({
			delayedPromise: this._object,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._usage,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._providerMetadata,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._warnings,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._request,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._response,
			error
		});
		this.rejectResultPromise({
			delayedPromise: this._finishReason,
			error
		});
	}
	rejectResultPromise({ delayedPromise, error }) {
		if (delayedPromise.isPending()) {
			delayedPromise.reject(error);
			markPromiseAsHandled(delayedPromise.promise);
		}
	}
	get object() {
		return this._object.promise;
	}
	get usage() {
		return this._usage.promise;
	}
	get providerMetadata() {
		return this._providerMetadata.promise;
	}
	get warnings() {
		return this._warnings.promise;
	}
	get request() {
		return this._request.promise;
	}
	get response() {
		return this._response.promise;
	}
	get finishReason() {
		return this._finishReason.promise;
	}
	get partialObjectStream() {
		return createAsyncIterableStream(this.baseStream.pipeThrough(new TransformStream({ transform(chunk, controller) {
			switch (chunk.type) {
				case "object":
					controller.enqueue(chunk.object);
					break;
				case "text-delta":
				case "finish":
				case "error": break;
				default: throw new Error(`Unsupported chunk type: ${chunk}`);
			}
		} })));
	}
	get elementStream() {
		return this.outputStrategy.createElementStream(this.baseStream);
	}
	get textStream() {
		return createAsyncIterableStream(this.baseStream.pipeThrough(new TransformStream({ transform(chunk, controller) {
			switch (chunk.type) {
				case "text-delta":
					controller.enqueue(chunk.textDelta);
					break;
				case "object":
				case "finish":
				case "error": break;
				default: throw new Error(`Unsupported chunk type: ${chunk}`);
			}
		} })));
	}
	get fullStream() {
		return createAsyncIterableStream(this.baseStream);
	}
	pipeTextStreamToResponse(response, init) {
		return pipeTextStreamToResponse({
			response,
			stream: this.textStream,
			...init
		});
	}
	toTextStreamResponse(init) {
		return createTextStreamResponse({
			stream: this.textStream,
			...init
		});
	}
};
//#endregion
//#region src/generate-speech/generated-audio-file.ts
var DefaultGeneratedAudioFile = class extends DefaultGeneratedFile {
	constructor({ data, mediaType }) {
		super({
			data,
			mediaType
		});
		let format = "mp3";
		if (mediaType) {
			const mediaTypeParts = mediaType.split("/");
			if (mediaTypeParts.length === 2) {
				if (mediaType !== "audio/mpeg") format = mediaTypeParts[1];
			}
		}
		if (!format) throw new InvalidResponseDataError$1({
			data: mediaType,
			message: `Could not determine audio format from media type: ${mediaType}`
		});
		this.format = format;
	}
};
//#endregion
//#region src/generate-speech/generate-speech.ts
const originalGenerateCallId$3 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Generates speech audio using a speech model.
*
* @param model - The speech model to use.
* @param text - The text to convert to speech.
* @param voice - The voice to use for speech generation.
* @param outputFormat - The output format to use for speech generation e.g. "mp3", "wav", etc.
* @param instructions - Instructions for the speech generation e.g. "Speak in a slow and steady tone".
* @param speed - The speed of the speech generation.
* @param language - The language for speech generation (ISO 639-1 code e.g. "en", "es", "fr") or "auto" for automatic detection.
* @param providerOptions - Additional provider-specific options that are passed through to the provider
* as body parameters.
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
* @param telemetry - Optional telemetry configuration.
*
* @returns A result object that contains the generated audio data.
*/
async function generateSpeech({ model, text, voice, outputFormat, instructions, speed, language, providerOptions = {}, maxRetries: maxRetriesArg, abortSignal, headers, telemetry, _internal: { generateCallId = originalGenerateCallId$3 } = {} }) {
	const resolvedModel = resolveSpeechModel(model);
	if (!resolvedModel) throw new Error("Model could not be resolved");
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const { maxRetries, retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	const callId = generateCallId();
	const telemetryDispatcher = createTelemetryDispatcher({ telemetry });
	const runInTracingChannelSpan = telemetryDispatcher.runInTracingChannelSpan ?? (async ({ execute }) => await execute());
	const startEvent = {
		callId,
		operationId: "ai.generateSpeech",
		provider: resolvedModel.provider,
		modelId: resolvedModel.modelId,
		text,
		voice,
		outputFormat,
		instructions,
		speed,
		language,
		maxRetries,
		headers,
		providerOptions
	};
	return await runInTracingChannelSpan({
		type: "generateSpeech",
		event: startEvent,
		execute: async () => {
			await notify({
				event: startEvent,
				callbacks: [telemetryDispatcher.onStart]
			});
			try {
				const result = await retry(() => resolvedModel.doGenerate({
					text,
					voice,
					outputFormat,
					instructions,
					speed,
					language,
					abortSignal,
					headers: headersWithUserAgent,
					providerOptions
				}));
				if (!result.audio || result.audio.length === 0) throw new NoSpeechGeneratedError({ responses: [result.response] });
				logWarnings({
					warnings: result.warnings,
					provider: resolvedModel.provider,
					model: resolvedModel.modelId
				});
				const detectedMediaType = detectMediaType({
					data: result.audio,
					topLevelType: "audio"
				});
				const audio = new DefaultGeneratedAudioFile({
					data: result.audio,
					mediaType: detectedMediaType ?? getResponseAudioMediaType(result.response.headers) ?? getOutputFormatMediaType(outputFormat) ?? "audio/mp3"
				});
				if (telemetryDispatcher.onEnd != null) await notify({
					event: {
						callId,
						operationId: "ai.generateSpeech",
						provider: resolvedModel.provider,
						modelId: resolvedModel.modelId,
						text,
						audio: {
							byteLength: getBase64OrBinaryByteLength(result.audio),
							mediaType: audio.mediaType,
							format: audio.format
						},
						usage: result.usage,
						warnings: result.warnings,
						providerMetadata: result.providerMetadata,
						response: getTelemetryResponseMetadata(result.response)
					},
					callbacks: [telemetryDispatcher.onEnd]
				});
				return new DefaultSpeechResult({
					audio,
					warnings: result.warnings,
					responses: [result.response],
					providerMetadata: result.providerMetadata
				});
			} catch (error) {
				await telemetryDispatcher.onError?.({
					callId,
					error
				});
				throw error;
			}
		}
	});
}
function getBase64OrBinaryByteLength(audio) {
	if (audio instanceof Uint8Array) return audio.byteLength;
	let characterCount = 0;
	let lastCharacter = "";
	let secondLastCharacter = "";
	for (const character of audio) {
		if (/\s/.test(character)) continue;
		characterCount++;
		secondLastCharacter = lastCharacter;
		lastCharacter = character;
	}
	const padding = lastCharacter === "=" ? secondLastCharacter === "=" ? 2 : 1 : 0;
	return Math.floor(characterCount * 3 / 4) - padding;
}
function getTelemetryResponseMetadata(response) {
	return {
		timestamp: response.timestamp,
		modelId: response.modelId,
		headers: response.headers
	};
}
function getResponseAudioMediaType(headers) {
	const mediaType = Object.entries(headers ?? {}).find(([name]) => name.toLowerCase() === "content-type")?.[1];
	if (mediaType == null) return;
	const normalizedMediaType = mediaType.split(";", 1)[0].trim().toLowerCase();
	if (normalizedMediaType.length === 0) return;
	return normalizedMediaType.startsWith("audio/") ? normalizedMediaType : void 0;
}
function getOutputFormatMediaType(outputFormat) {
	if (outputFormat == null) return;
	switch (outputFormat.trim().toLowerCase()) {
		case "pcm":
		case "audio/pcm": return "audio/pcm";
		case "audio/l16": return "audio/l16";
		case "mulaw":
		case "audio/mulaw": return "audio/mulaw";
		case "alaw":
		case "audio/alaw": return "audio/alaw";
		default: return;
	}
}
var DefaultSpeechResult = class {
	constructor(options) {
		this.audio = options.audio;
		this.warnings = options.warnings;
		this.responses = options.responses;
		this.providerMetadata = options.providerMetadata ?? {};
	}
};
//#endregion
//#region src/generate-speech/is-streaming-speech-model.ts
/**
* Whether a resolved speech model implements the experimental streaming
* speech extension (`Experimental_StreamingSpeechModelV4`).
*/
function isStreamingSpeechModel(model) {
	return typeof model.doStream === "function";
}
//#endregion
//#region src/generate-speech/stream-speech.ts
/**
* Streams speech audio using a speech model.
*
* @param model - The speech model to use. It must support streaming speech.
* @param text - The text to convert to speech: a complete string, or a stream of text deltas
* (e.g. the text stream of `streamText`) or text parts that is synthesized as it arrives.
* A text part can set its own `voice` on providers that support several voices per stream.
* @param voice - The voice to use for speech generation.
* @param outputFormat - The format of the output audio chunks, e.g. `{ type: 'audio/pcm', rate: 24000 }`.
* @param instructions - Instructions for the speech generation e.g. "Speak in a slow and steady tone".
* @param speed - The speed of the speech generation.
* @param language - The language for speech generation (ISO 639-1 code e.g. "en", "es", "fr") or "auto" for automatic detection.
* @param providerOptions - Additional provider-specific options.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP/WebSocket headers to send when supported by the provider.
* @param includeRawChunks - When true, raw provider chunks are included in `fullStream`.
* @param onError - Called for each provider error part; defaults to `console.error`.
*
* @returns A result object with the audio stream and the final usage and metadata.
*/
function streamSpeech({ model, text, voice, outputFormat, instructions, speed, language, providerOptions = {}, abortSignal, headers, includeRawChunks, onError = ({ error }) => {
	console.error(error);
}, _internal: { currentDate = () => /* @__PURE__ */ new Date() } = {} }) {
	const resolvedModel = resolveSpeechModel(model);
	if (!resolvedModel) throw new Error("Model could not be resolved");
	if (!isStreamingSpeechModel(resolvedModel)) throw new UnsupportedFunctionalityError$1({
		functionality: "streaming speech",
		message: `The ${resolvedModel.provider} model "${resolvedModel.modelId}" does not support streaming speech.` + (typeof model === "string" ? " String model IDs resolve through the global provider (AI Gateway by default). If that provider does not support streaming speech, pass a provider model instance instead (e.g. elevenLabs.speech('eleven_flash_v2_5')) or upgrade @ai-sdk/gateway to a version with streaming speech support." : "")
	});
	const textStream = toTextStream$1(text);
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const usagePromise = new DelayedPromise();
	const warningsPromise = new DelayedPromise();
	const responsesPromise = new DelayedPromise();
	const providerMetadataPromise = new DelayedPromise();
	const rejectPendingPromises = (error) => {
		for (const promise of [
			usagePromise,
			warningsPromise,
			responsesPromise,
			providerMetadataPromise
		]) if (promise.isPending()) promise.reject(error);
	};
	const startedAt = currentDate();
	let response;
	const currentResponseMetadata = () => response ?? {
		timestamp: startedAt,
		modelId: resolvedModel.modelId
	};
	const resolveWarnings = (warnings) => {
		warningsPromise.resolve(warnings);
		logWarnings({
			warnings,
			provider: resolvedModel.provider,
			model: resolvedModel.modelId
		});
	};
	const pipeAbortController = new AbortController();
	let hasAudio = false;
	let finished = false;
	let lastError;
	const incompleteStreamError = () => hasAudio ? lastError ?? new StreamProviderError({ message: "The speech stream ended before it finished." }) : new NoSpeechGeneratedError({
		responses: [currentResponseMetadata()],
		cause: lastError
	});
	const transform = new TransformStream({
		transform(value, controller) {
			switch (value.type) {
				case "stream-start":
					resolveWarnings(value.warnings);
					break;
				case "response-metadata":
					response = {
						timestamp: value.timestamp ?? currentResponseMetadata().timestamp,
						modelId: value.modelId ?? currentResponseMetadata().modelId,
						headers: value.headers ?? response?.headers,
						body: value.body ?? response?.body
					};
					break;
				case "audio": {
					const audio = typeof value.audio === "string" ? convertBase64ToUint8Array(value.audio) : value.audio;
					if (audio.length === 0 && value.providerMetadata == null) break;
					hasAudio ||= audio.length > 0;
					controller.enqueue({
						type: "audio",
						...value.id != null && { id: value.id },
						audio,
						audioFormat: value.audioFormat,
						...value.providerMetadata != null && { providerMetadata: value.providerMetadata }
					});
					break;
				}
				case "raw":
					controller.enqueue(value);
					break;
				case "error":
					lastError = value.error;
					Promise.resolve().then(() => onError({ error: value.error })).catch(() => {});
					controller.enqueue(value);
					break;
				case "finish":
					if (!warningsPromise.isResolved()) resolveWarnings([]);
					if (!hasAudio) throw new NoSpeechGeneratedError({
						responses: [currentResponseMetadata()],
						cause: lastError
					});
					finished = true;
					usagePromise.resolve(value.usage ?? {});
					responsesPromise.resolve([currentResponseMetadata()]);
					providerMetadataPromise.resolve(value.providerMetadata ?? {});
			}
		},
		flush() {
			if (!finished) throw incompleteStreamError();
		},
		cancel(reason) {
			const cancelReason = reason ?? /* @__PURE__ */ new Error("Speech stream was cancelled.");
			rejectPendingPromises(cancelReason);
			pipeAbortController.abort(cancelReason);
		}
	});
	if (abortSignal != null) {
		const onAbort = () => {
			const reason = abortSignal.reason;
			rejectPendingPromises(reason);
			pipeAbortController.abort(reason);
			transform.writable.abort(reason).catch(() => {});
		};
		if (abortSignal.aborted) onAbort();
		else abortSignal.addEventListener("abort", onAbort, { once: true });
	}
	(async () => {
		const result = await resolvedModel.doStream({
			text: textStream,
			voice,
			outputFormat,
			instructions,
			speed,
			language,
			providerOptions,
			abortSignal: mergeAbortSignals(abortSignal, pipeAbortController.signal),
			headers: headersWithUserAgent,
			includeRawChunks
		});
		response = {
			timestamp: result.response?.timestamp ?? startedAt,
			modelId: result.response?.modelId ?? resolvedModel.modelId,
			headers: result.response?.headers,
			body: result.response?.body
		};
		await result.stream.pipeTo(transform.writable, { signal: pipeAbortController.signal });
	})().catch((error) => {
		const reason = error ?? /* @__PURE__ */ new Error("Speech stream was cancelled or errored.");
		rejectPendingPromises(reason);
		textStream.cancel(reason).catch(() => {});
		transform.writable.abort(reason).catch(() => {});
	});
	let streamOwner = "unclaimed";
	function consumeStream() {
		if (streamOwner !== "unclaimed") return;
		streamOwner = "result-promises";
		const reader = transform.readable.getReader();
		(async () => {
			while (!(await reader.read()).done);
		})().catch(() => {});
	}
	function claimStream(owner) {
		if (streamOwner !== "unclaimed") throw new Error(streamOwner === "result-promises" ? `${owner === "full-stream" ? "fullStream" : "audioStream"} cannot be accessed after a result promise.` : "Only one of audioStream or fullStream can be accessed, and only once.");
		streamOwner = owner;
		return transform.readable;
	}
	return {
		get usage() {
			consumeStream();
			return usagePromise.promise;
		},
		get warnings() {
			consumeStream();
			return warningsPromise.promise;
		},
		get responses() {
			consumeStream();
			return responsesPromise.promise;
		},
		get providerMetadata() {
			consumeStream();
			return providerMetadataPromise.promise;
		},
		get fullStream() {
			return asAsyncIterableStream(claimStream("full-stream"));
		},
		get audioStream() {
			return asAsyncIterableStream(createAudioByteStream(claimStream("audio-stream")));
		}
	};
}
/**
* Projects speech parts to audio bytes with a pull-based stream rather than a
* second `pipeThrough`, so an early consumer cancel cancels the part stream
* directly instead of surfacing an unhandled rejection from a chained pipe.
*/
function createAudioByteStream(parts) {
	let reader;
	return new ReadableStream({
		async pull(controller) {
			reader ??= parts.getReader();
			for (;;) {
				const { done, value } = await reader.read();
				if (done) {
					controller.close();
					return;
				}
				if (value.type === "audio" && value.audio.length > 0) {
					controller.enqueue(value.audio);
					return;
				}
			}
		},
		async cancel(reason) {
			if (reader != null) await reader.cancel(reason).catch(() => {});
			else await parts.cancel(reason).catch(() => {});
		}
	});
}
function toTextStream$1(text) {
	if (typeof text === "string") return new ReadableStream({ start(controller) {
		controller.enqueue({
			type: "text",
			text
		});
		controller.close();
	} });
	return toSourceStream(text).pipeThrough(new TransformStream({ transform(value, controller) {
		controller.enqueue(toTextPart(value));
	} }));
}
function toSourceStream(text) {
	if (text instanceof ReadableStream) return text;
	if (typeof text?.[Symbol.asyncIterator] === "function") return convertAsyncIteratorToReadableStream(text[Symbol.asyncIterator]());
	const iterable = text;
	return convertAsyncIteratorToReadableStream((async function* () {
		yield* iterable;
	})());
}
function toTextPart(value) {
	if (typeof value === "string") return {
		type: "text",
		text: value
	};
	return {
		type: "text",
		text: value.text,
		...value.voice != null && { voice: value.voice },
		...value.providerOptions != null && { providerOptions: value.providerOptions }
	};
}
//#endregion
//#region src/generate-speech/index.ts
/**
* @deprecated Use `generateSpeech` instead.
*/
const experimental_generateSpeech = (options) => {
	logWarnings({ warnings: [{
		type: "deprecated",
		setting: "experimental_generateSpeech",
		message: "Use generateSpeech instead."
	}] });
	return generateSpeech(options);
};
//#endregion
//#region src/generate-text/prune-messages.ts
/**
* Prunes model messages from a list of model messages.
*
* @param messages - The list of model messages to prune.
* @param reasoning - How to remove reasoning content from assistant messages. Default is `'none'`.
* @param toolCalls - How to prune tool call/results/approval content. Default is `[]`.
* @param emptyMessages - Whether to keep or remove messages whose content is empty after pruning. Default is `'remove'`.
*
* @returns The pruned list of model messages.
*/
function pruneMessages({ messages, reasoning = "none", toolCalls = [], emptyMessages = "remove" }) {
	if (reasoning === "all" || reasoning === "before-last-message") messages = messages.map((message, messageIndex) => {
		if (message.role !== "assistant" || typeof message.content === "string" || reasoning === "before-last-message" && messageIndex === messages.length - 1) return message;
		return {
			...message,
			content: message.content.filter((part) => part.type !== "reasoning" && part.type !== "reasoning-file")
		};
	});
	if (toolCalls === "none") toolCalls = [];
	else if (toolCalls === "all") toolCalls = [{ type: "all" }];
	else if (toolCalls === "before-last-message") toolCalls = [{ type: "before-last-message" }];
	else if (typeof toolCalls === "string") toolCalls = [{ type: toolCalls }];
	for (const toolCall of toolCalls) {
		const keepLastMessagesCount = toolCall.type === "all" ? void 0 : toolCall.type === "before-last-message" ? 1 : Number(toolCall.type.slice(12).slice(0, -9));
		const keptToolCallIds = /* @__PURE__ */ new Set();
		const keptApprovalIds = /* @__PURE__ */ new Set();
		if (keepLastMessagesCount != null && keepLastMessagesCount !== 0) {
			for (const message of messages.slice(-keepLastMessagesCount)) if ((message.role === "assistant" || message.role === "tool") && typeof message.content !== "string") {
				for (const part of message.content) if (part.type === "tool-call" || part.type === "tool-result") keptToolCallIds.add(part.toolCallId);
				else if (part.type === "tool-approval-request" || part.type === "tool-approval-response") keptApprovalIds.add(part.approvalId);
			}
		}
		const toolCallIdToToolName = /* @__PURE__ */ new Map();
		for (const message of messages) if ((message.role === "assistant" || message.role === "tool") && typeof message.content !== "string") {
			for (const part of message.content) if (part.type === "tool-call" || part.type === "tool-result") toolCallIdToToolName.set(part.toolCallId, part.toolName);
		}
		const approvalIdToToolCallId = /* @__PURE__ */ new Map();
		const approvalIdToToolName = /* @__PURE__ */ new Map();
		for (const message of messages) if ((message.role === "assistant" || message.role === "tool") && typeof message.content !== "string") {
			for (const part of message.content) if (part.type === "tool-approval-request") {
				approvalIdToToolCallId.set(part.approvalId, part.toolCallId);
				const toolName = toolCallIdToToolName.get(part.toolCallId);
				if (toolName != null) approvalIdToToolName.set(part.approvalId, toolName);
			}
		}
		for (const approvalId of keptApprovalIds) {
			const toolCallId = approvalIdToToolCallId.get(approvalId);
			if (toolCallId != null) keptToolCallIds.add(toolCallId);
		}
		messages = messages.map((message, messageIndex) => {
			if (message.role !== "assistant" && message.role !== "tool" || typeof message.content === "string" || keepLastMessagesCount && messageIndex >= messages.length - keepLastMessagesCount) return message;
			const keepParts = message.content.map((part) => {
				if (part.type !== "tool-call" && part.type !== "tool-result" && part.type !== "tool-approval-request" && part.type !== "tool-approval-response") return true;
				if ((part.type === "tool-call" || part.type === "tool-result") && keptToolCallIds.has(part.toolCallId) || (part.type === "tool-approval-request" || part.type === "tool-approval-response") && keptApprovalIds.has(part.approvalId)) return true;
				const partToolName = part.type === "tool-call" || part.type === "tool-result" ? part.toolName : approvalIdToToolName.get(part.approvalId);
				return toolCall.tools != null && partToolName != null && !toolCall.tools.includes(partToolName);
			});
			if (message.role === "assistant") for (let reasoningIndex = 0; reasoningIndex < message.content.length; reasoningIndex++) {
				const part = message.content[reasoningIndex];
				if (part.type !== "reasoning" && part.type !== "reasoning-file") continue;
				let reasoningEndIndex = reasoningIndex + 1;
				while (reasoningEndIndex < message.content.length) {
					const nextPart = message.content[reasoningEndIndex];
					if (nextPart.type !== "reasoning" && nextPart.type !== "reasoning-file") break;
					reasoningEndIndex++;
				}
				let followingPartIndex = reasoningEndIndex;
				let hasFollowingPart = false;
				let hasKeptFollowingPart = false;
				while (followingPartIndex < message.content.length) {
					const followingPart = message.content[followingPartIndex];
					if (followingPart.type === "reasoning" || followingPart.type === "reasoning-file") break;
					hasFollowingPart = true;
					hasKeptFollowingPart ||= keepParts[followingPartIndex];
					followingPartIndex++;
				}
				if (hasFollowingPart && !hasKeptFollowingPart) for (let index = reasoningIndex; index < reasoningEndIndex; index++) keepParts[index] = false;
				reasoningIndex = followingPartIndex - 1;
			}
			return {
				...message,
				content: message.content.filter((_, index) => keepParts[index])
			};
		});
	}
	if (emptyMessages === "remove") messages = messages.filter((message) => message.content.length > 0);
	return messages;
}
//#endregion
//#region src/generate-text/smooth-stream.ts
const CHUNKING_REGEXPS = {
	word: /\S+\s+/m,
	line: /\n+/m
};
function isDocumentHidden() {
	return typeof document !== "undefined" && document.visibilityState === "hidden";
}
/**
* Smooths text and reasoning streaming output.
*
* @param delayInMs - The delay in milliseconds between each chunk. Defaults to 10ms. Can be set to `null` to skip the delay. The delay is skipped while the document is hidden (e.g. browser background tabs), where timer throttling would otherwise stall the stream.
* @param chunking - Controls how the text is chunked for streaming. Use "word" to stream word by word (default), "line" to stream line by line, provide a custom RegExp pattern that does not match the empty string for custom chunking, provide an Intl.Segmenter for locale-aware word segmentation (recommended for CJK languages), or provide a custom ChunkDetector function.
*
* @returns A transform stream that smooths text streaming output.
*/
function smoothStream({ delayInMs = 10, chunking = "word", _internal: { delay: delay$2 = delay } = {} } = {}) {
	let detectChunk;
	if (chunking != null && typeof chunking === "object" && "segment" in chunking && typeof chunking.segment === "function") {
		const segmenter = chunking;
		detectChunk = (buffer) => {
			if (buffer.length === 0) return null;
			return segmenter.segment(buffer)[Symbol.iterator]().next().value?.segment || null;
		};
	} else if (typeof chunking === "function") detectChunk = (buffer) => {
		const match = chunking(buffer);
		if (match == null) return null;
		if (!match.length) throw new Error(`Chunking function must return a non-empty string.`);
		if (!buffer.startsWith(match)) throw new Error(`Chunking function must return a match that is a prefix of the buffer. Received: "${match}" which is not a prefix of buffer "${buffer}"`);
		return match;
	};
	else {
		const chunkingRegex = typeof chunking === "string" ? CHUNKING_REGEXPS[chunking] : chunking;
		detectChunk = (buffer) => {
			const lastIndex = chunkingRegex.lastIndex;
			chunkingRegex.lastIndex = 0;
			let match;
			try {
				match = chunkingRegex.exec(buffer);
			} finally {
				chunkingRegex.lastIndex = lastIndex;
			}
			if (!match) return null;
			if (!match[0].length) throw new Error(`Chunking RegExp must not match an empty string.`);
			return buffer.slice(0, match.index) + match[0];
		};
	}
	return () => {
		let buffer = "";
		let id = "";
		let type = void 0;
		let providerMetadata = void 0;
		function flushBuffer(controller) {
			if (type !== void 0 && (buffer.length > 0 || providerMetadata != null)) {
				controller.enqueue({
					type,
					text: buffer,
					id,
					...providerMetadata != null ? { providerMetadata } : {}
				});
				buffer = "";
				providerMetadata = void 0;
			}
		}
		return new TransformStream({ async transform(chunk, controller) {
			if (chunk.type === "ping") {
				controller.enqueue(chunk);
				return;
			}
			if (chunk.type !== "text-delta" && chunk.type !== "reasoning-delta") {
				flushBuffer(controller);
				controller.enqueue(chunk);
				return;
			}
			if (chunk.text.length === 0 && chunk.providerMetadata != null) {
				flushBuffer(controller);
				controller.enqueue(chunk);
				return;
			}
			if (buffer.length > 0 && (chunk.type !== type || chunk.id !== id || providerMetadata != null || chunk.providerMetadata != null)) flushBuffer(controller);
			buffer += chunk.text;
			id = chunk.id;
			type = chunk.type;
			providerMetadata = chunk.providerMetadata;
			let match;
			while ((match = detectChunk(buffer)) != null) {
				controller.enqueue({
					type,
					text: match,
					id,
					...providerMetadata != null ? { providerMetadata } : {}
				});
				buffer = buffer.slice(match.length);
				await delay$2(isDocumentHidden() ? null : delayInMs);
			}
			if (buffer.length === 0) providerMetadata = void 0;
		} });
	};
}
//#endregion
//#region src/generate-text/tool-fingerprint.ts
/**
* Tag a tool description for hashing. A function description is developer-owned
* (evaluated per call from local context), not a server-controlled "rug pull"
* vector, so only its presence is pinned, not its identity. The tagged shape
* keeps a literal string equal to some placeholder from ever hashing like a
* function.
*/
function tagDescription(description) {
	if (typeof description === "string") return {
		type: "string",
		value: description
	};
	if (description == null) return { type: "none" };
	return { type: "function" };
}
/**
* Fingerprint the server-controlled, security-relevant fields of each tool in a
* `ToolSet`: `description` (string form only), the resolved input JSON schema,
* and `title`. Returns a map of tool name to a stable digest.
*
* Capture a baseline at trust time (first connect, human-reviewed) and compare
* later fetches with {@link detectToolDrift} to catch MCP tool-definition drift
* ("rug pull"). Baseline storage and the drift response are the app's concern.
*/
async function fingerprintTools(tools) {
	const entries = await Promise.all(Object.keys(tools).map(async (name) => {
		const tool = tools[name];
		return [name, await hashCanonical({
			description: tagDescription(tool.description),
			inputSchema: await asSchema$1(tool.inputSchema).jsonSchema,
			title: tool.title
		})];
	}));
	return Object.fromEntries(entries);
}
/**
* Pure diff of two fingerprint maps produced by {@link fingerprintTools}.
* `added`/`removed` are tools present in only one map; `changed` are tools whose
* pinned definition differs. Uses own-property lookups so a tool literally named
* `constructor` or `toString` diffs correctly.
*/
function detectToolDrift(current, baseline) {
	const added = [];
	const removed = [];
	const changed = [];
	for (const name of Object.keys(current)) if (!Object.hasOwn(baseline, name)) added.push(name);
	else if (current[name] !== baseline[name]) changed.push(name);
	for (const name of Object.keys(baseline)) if (!Object.hasOwn(current, name)) removed.push(name);
	return {
		added,
		removed,
		changed
	};
}
//#endregion
//#region src/generate-video/generate-video.ts
/**
* Generates videos using a video model.
*
* @param model - The video model to use.
* @param prompt - The prompt that should be used to generate the video.
* @param n - Number of videos to generate. Default: 1.
* @param aspectRatio - Aspect ratio of the videos to generate. Must have the format `{width}:{height}`, or `'adaptive'`.
* @param resolution - Resolution of the videos to generate. Must have the format `{width}x{height}`.
* @param duration - Duration of the video in seconds.
* @param fps - Frames per second for the video.
* @param seed - Seed for the video generation.
* @param frameImages - Role-tagged image inputs for image-to-video and first-last-frame generation.
* @param inputReferences - Reference image or video inputs for reference-to-video generation.
* @param generateAudio - Whether the model should generate audio alongside the video.
* @param providerOptions - Additional provider-specific options that are passed through to the provider
* as body parameters.
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
* @param poll - Polling configuration for models that support the start/status flow.
* @param webhook - Webhook factory for models that support the start/status flow.
*
* @returns A result object that contains the generated videos.
*/
const defaultDownload$1 = createDownload();
async function experimental_generateVideo({ model: modelArg, prompt: promptArg, n = 1, maxVideosPerCall, aspectRatio, resolution, duration, fps, seed, frameImages, inputReferences, generateAudio, providerOptions, maxRetries: maxRetriesArg, abortSignal, headers, download: downloadFn = defaultDownload$1, poll, webhook }) {
	const model = resolveVideoModel(modelArg);
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const { maxRetries, retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	const { prompt, resolvedImage, normalizedFrameImages, effectiveInputReferences, warnings } = normalizeVideoCallInputs({
		promptArg,
		frameImages,
		inputReferences
	});
	const maxVideosPerCallWithDefault = maxVideosPerCall ?? await invokeModelMaxVideosPerCall(model) ?? 1;
	const hasStartStatus = model.doStart != null && model.doStatus != null;
	const useStartStatus = hasStartStatus && (poll != null || webhook != null || model.doGenerate == null);
	if (model.doGenerate == null && !hasStartStatus) throw new Error(`Video model ${model.modelId} does not implement doGenerate or doStart/doStatus.`);
	if ((poll != null || webhook != null) && !hasStartStatus) logWarnings({
		warnings: [{
			type: "other",
			message: "poll/webhook options were provided but the model does not support doStart/doStatus. Falling back to doGenerate."
		}],
		provider: model.provider,
		model: model.modelId
	});
	const callCount = Math.ceil(n / maxVideosPerCallWithDefault);
	const callVideoCounts = Array.from({ length: callCount }, (_, index) => {
		const remaining = n - index * maxVideosPerCallWithDefault;
		return Math.min(remaining, maxVideosPerCallWithDefault);
	});
	const results = await Promise.all(callVideoCounts.map(async (callVideoCount) => {
		const callOptions = {
			prompt,
			n: callVideoCount,
			aspectRatio,
			resolution,
			duration,
			fps,
			seed,
			image: resolvedImage,
			frameImages: normalizedFrameImages,
			inputReferences: effectiveInputReferences,
			generateAudio,
			providerOptions: providerOptions ?? {},
			headers: headersWithUserAgent,
			abortSignal
		};
		if (useStartStatus) return executeStartStatusFlow({
			model,
			callOptions,
			poll,
			webhook,
			maxRetries,
			retry
		});
		return retry(() => model.doGenerate(callOptions));
	}));
	const videos = [];
	let uploadedVideos = 0;
	const responses = [];
	const providerMetadata = {};
	for (const result of results) {
		for (const videoData of result.videos) switch (videoData.type) {
			case "uploaded":
				uploadedVideos++;
				break;
			case "url": {
				const { data, mediaType: downloadedMediaType } = await downloadFn({
					url: new URL(videoData.url),
					abortSignal
				});
				const isUsableMediaType = (type) => !!type && type !== "application/octet-stream";
				const mediaType = isUsableMediaType(videoData.mediaType) && videoData.mediaType || isUsableMediaType(downloadedMediaType) && downloadedMediaType || detectMediaType({
					data,
					topLevelType: "video"
				}) || "video/mp4";
				videos.push(new DefaultGeneratedFile({
					data,
					mediaType
				}));
				break;
			}
			case "base64":
				videos.push(new DefaultGeneratedFile({
					data: videoData.data,
					mediaType: videoData.mediaType || "video/mp4"
				}));
				break;
			case "binary": {
				const mediaType = videoData.mediaType || detectMediaType({
					data: videoData.data,
					topLevelType: "video"
				}) || "video/mp4";
				videos.push(new DefaultGeneratedFile({
					data: videoData.data,
					mediaType
				}));
				break;
			}
		}
		warnings.push(...result.warnings);
		responses.push({
			timestamp: result.response.timestamp,
			modelId: result.response.modelId,
			headers: result.response.headers,
			providerMetadata: result.providerMetadata
		});
		if (result.providerMetadata != null) mergeProviderMetadata(providerMetadata, result.providerMetadata);
	}
	if (videos.length === 0 && uploadedVideos === 0) throw new NoVideoGeneratedError({ responses });
	if (warnings.length > 0) logWarnings({
		warnings,
		provider: model.provider,
		model: model.modelId
	});
	const result = {
		video: videos[0],
		videos,
		uploadedVideos,
		warnings,
		responses,
		providerMetadata
	};
	if (videos.length === 0) Object.defineProperty(result, "video", {
		enumerable: false,
		get() {
			throw new NoVideoGeneratedError({
				message: "Videos were delivered to the upload destination. Use uploadedVideos instead of video.",
				responses
			});
		}
	});
	return result;
}
async function executeStartStatusFlow({ model, callOptions, poll: pollConfig, webhook: webhookFactory, maxRetries, retry }) {
	const earlyWarnings = [];
	let webhookUrl;
	let webhookReceived;
	if (webhookFactory != null) {
		if (model.handleWebhookOption != null) {
			const result = await model.handleWebhookOption({ webhook: webhookFactory });
			webhookReceived = Promise.resolve(result.received);
			webhookReceived.catch(() => {});
			webhookUrl = result.webhookUrl;
		} else earlyWarnings.push({
			type: "unsupported",
			feature: "webhook",
			details: "This model does not support webhooks. Falling back to polling."
		});
	}
	const callerIdempotencyKey = Object.entries(callOptions.headers ?? {}).find(([key, value]) => key.toLowerCase() === "idempotency-key" && value !== void 0);
	const startCallOptions = {
		...callOptions,
		headers: {
			...callOptions.headers,
			...callerIdempotencyKey ? {} : { "idempotency-key": `aisdk_vid_${generateId$1()}` }
		},
		webhookUrl
	};
	const startResult = await retry(() => model.doStart(startCallOptions));
	const allWarnings = [...earlyWarnings, ...startResult.warnings];
	let operationProviderMetadata = startResult.providerMetadata == null ? void 0 : { ...startResult.providerMetadata };
	const intervalMs = pollConfig?.intervalMs ?? 5e3;
	const timeoutMs = pollConfig?.timeoutMs ?? 6e5;
	const delay$1 = pollConfig?.delay ?? delay;
	const startTime = Date.now();
	const pollingTimeoutError = /* @__PURE__ */ new Error(`Video generation timed out after ${timeoutMs}ms.`);
	if (webhookReceived != null) await waitForWebhook({
		received: webhookReceived,
		timeoutMs,
		abortSignal: callOptions.abortSignal,
		delay: delay$1
	});
	while (true) {
		if (webhookReceived == null) {
			const elapsedMs = Date.now() - startTime;
			if (elapsedMs >= timeoutMs) throw pollingTimeoutError;
			await delay$1(Math.min(intervalMs, timeoutMs - elapsedMs), { abortSignal: callOptions.abortSignal });
			if (Date.now() - startTime >= timeoutMs) throw pollingTimeoutError;
		}
		let statusResult;
		if (webhookReceived != null) statusResult = await retry(() => model.doStatus({
			operation: startResult.operation,
			abortSignal: callOptions.abortSignal,
			headers: callOptions.headers
		}));
		else {
			const statusTimeoutController = new AbortController();
			const statusAbortSignal = mergeAbortSignals(callOptions.abortSignal, statusTimeoutController.signal);
			const statusTimeoutId = setTimeout(() => statusTimeoutController.abort(pollingTimeoutError), timeoutMs - (Date.now() - startTime));
			const statusTimeoutPromise = new Promise((_, reject) => {
				statusTimeoutController.signal.addEventListener("abort", () => reject(pollingTimeoutError), { once: true });
			});
			const { retry: statusRetry } = prepareRetries({
				maxRetries,
				abortSignal: statusAbortSignal
			});
			try {
				statusResult = await Promise.race([statusRetry(() => model.doStatus({
					operation: startResult.operation,
					abortSignal: statusAbortSignal,
					headers: callOptions.headers
				})), statusTimeoutPromise]);
			} catch (error) {
				if (statusTimeoutController.signal.aborted) throw pollingTimeoutError;
				throw error;
			} finally {
				clearTimeout(statusTimeoutId);
			}
		}
		if (statusResult.status === "error") throw new Error(statusResult.error);
		if (statusResult.warnings != null) allWarnings.push(...statusResult.warnings);
		if (statusResult.providerMetadata != null) {
			operationProviderMetadata ??= {};
			mergeProviderMetadata(operationProviderMetadata, statusResult.providerMetadata);
		}
		if (statusResult.status === "completed") return {
			videos: statusResult.videos,
			warnings: allWarnings,
			providerMetadata: operationProviderMetadata,
			response: statusResult.response
		};
		if (webhookReceived != null) throw new Error("Video generation did not complete after webhook notification.");
	}
}
async function waitForWebhook({ received, timeoutMs, abortSignal, delay }) {
	const timeoutController = typeof globalThis.AbortController === "function" ? new globalThis.AbortController() : void 0;
	try {
		await Promise.race([received, delay(timeoutMs, { abortSignal: timeoutController == null ? abortSignal : mergeAbortSignals(abortSignal, timeoutController.signal) }).then(() => {
			throw new Error(`Video generation timed out after ${timeoutMs}ms.`);
		})]);
	} finally {
		timeoutController?.abort();
	}
}
function mergeProviderMetadata(target, source) {
	for (const [providerName, metadataValue] of Object.entries(source)) {
		const existingMetadata = getOwn(target, providerName);
		if (existingMetadata != null && typeof existingMetadata === "object" && metadataValue != null && typeof metadataValue === "object") {
			setOwn(target, providerName, {
				...existingMetadata,
				...metadataValue
			});
			if ("videos" in existingMetadata && Array.isArray(existingMetadata.videos) && "videos" in metadataValue && Array.isArray(metadataValue.videos)) target[providerName].videos = [...existingMetadata.videos, ...metadataValue.videos];
		} else setOwn(target, providerName, metadataValue);
	}
}
function normalizePrompt(promptArg) {
	if (typeof promptArg === "string") return {
		prompt: promptArg,
		image: void 0
	};
	return {
		prompt: promptArg.text,
		image: promptArg.image != null ? normalizeImageData(promptArg.image) : void 0
	};
}
/**
* Shared input normalization for `experimental_generateVideo` and
* `experimental_startVideo`: prompt/image plus the frameImages /
* inputReferences precedence rules and their warnings.
*/
function normalizeVideoCallInputs({ promptArg, frameImages, inputReferences }) {
	const { prompt, image } = normalizePrompt(promptArg);
	const normalizedFrameImages = frameImages?.flatMap((frame) => {
		const normalizedImage = normalizeImageData(frame.image);
		return normalizedImage != null ? [{
			image: normalizedImage,
			frameType: frame.frameType
		}] : [];
	});
	const normalizedInputReferences = inputReferences?.flatMap((reference) => {
		const normalized = normalizeReferenceData(reference);
		return normalized != null ? [normalized] : [];
	});
	const effectiveInputReferences = normalizedFrameImages != null && normalizedFrameImages.length > 0 ? void 0 : normalizedInputReferences;
	const warnings = [];
	if (normalizedFrameImages != null && normalizedFrameImages.length > 0 && normalizedInputReferences != null && normalizedInputReferences.length > 0) warnings.push({
		type: "other",
		message: "inputReferences were ignored because frameImages were provided; frameImages and inputReferences cannot be combined."
	});
	const firstFrameImage = normalizedFrameImages?.find((frame) => frame.frameType === "first_frame")?.image;
	if (image != null && firstFrameImage != null) warnings.push({
		type: "other",
		message: "prompt.image was ignored because a first_frame frameImage was provided; the first_frame frameImage takes precedence as the start image."
	});
	return {
		prompt,
		resolvedImage: firstFrameImage ?? image,
		normalizedFrameImages,
		effectiveInputReferences,
		warnings
	};
}
function detectFileMediaType(data, restrictToImages) {
	return (restrictToImages ? detectMediaType({
		data,
		topLevelType: "image"
	}) : detectMediaType({ data })) ?? "image/png";
}
/**
* Normalizes a {@link DataContent} image into a {@link Experimental_VideoModelV4File}.
* Accepts a URL string, a data URL, a base64 string, or binary image data.
*/
function normalizeImageData(dataContent, { restrictToImages = true } = {}) {
	if (typeof dataContent === "string") {
		if (dataContent.startsWith("http://") || dataContent.startsWith("https://")) return {
			type: "url",
			url: dataContent
		};
		if (dataContent.startsWith("data:")) {
			const { mediaType, base64Content } = splitDataUrl(dataContent);
			const data = convertBase64ToUint8Array(base64Content ?? "");
			return {
				type: "file",
				mediaType: mediaType ?? detectFileMediaType(data, restrictToImages),
				data
			};
		}
		const bytes = convertBase64ToUint8Array(dataContent);
		return {
			type: "file",
			mediaType: detectFileMediaType(bytes, restrictToImages),
			data: bytes
		};
	}
	if (dataContent instanceof Uint8Array || dataContent instanceof ArrayBuffer) {
		const bytes = dataContent instanceof Uint8Array ? dataContent : new Uint8Array(dataContent);
		return {
			type: "file",
			mediaType: detectFileMediaType(bytes, restrictToImages),
			data: bytes
		};
	}
}
/**
* Normalizes a reference input into a {@link Experimental_VideoModelV4File},
* accepting either a plain {@link DataContent} or the object form that carries
* an explicit `mediaType`.
*/
function normalizeReferenceData(reference) {
	if (!(typeof reference === "object" && reference != null && !(reference instanceof Uint8Array) && !(reference instanceof ArrayBuffer) && "data" in reference)) return normalizeImageData(reference, { restrictToImages: false });
	const normalized = normalizeImageData(reference.data, { restrictToImages: false });
	if (normalized == null) return normalized;
	return {
		...normalized,
		...reference.mediaType != null ? { mediaType: reference.mediaType } : {}
	};
}
async function invokeModelMaxVideosPerCall(model) {
	if (typeof model.maxVideosPerCall === "function") return await model.maxVideosPerCall({ modelId: model.modelId });
	return model.maxVideosPerCall;
}
//#endregion
//#region src/generate-video/start-video.ts
/**
* Starts an asynchronous video generation and returns immediately with an
* opaque `operation` reference — without waiting for the video to finish.
*
* This is the fire-and-forget counterpart to `experimental_generateVideo`:
* use it to fan out many jobs, to submit from a process that will not stay
* alive, or together with `webhookUrl` so the provider notifies your endpoint
* at the terminal state. Check the outcome with `experimental_getVideoStatus`,
* or let your webhook receiver fetch the result.
*
* @param model - The video model to use. Must implement `doStart`.
* @param prompt - The prompt that should be used to generate the video.
* @param n - Number of videos to generate. Default: 1. Must not exceed the
* model's `maxVideosPerCall` — fan out with multiple `startVideo` calls.
* @param aspectRatio - Aspect ratio of the videos to generate. Must have the format `{width}:{height}`, or `'adaptive'`.
* @param resolution - Resolution of the videos to generate. Must have the format `{width}x${height}`.
* @param duration - Duration of the video in seconds.
* @param fps - Frames per second for the video.
* @param seed - Seed for the video generation.
* @param frameImages - Role-tagged image inputs for image-to-video and first-last-frame generation.
* @param inputReferences - Reference image or video inputs for reference-to-video generation.
* @param generateAudio - Whether the model should generate audio alongside the video.
* @param providerOptions - Additional provider-specific options that are passed through to the provider
* as body parameters.
* @param maxRetries - Maximum number of retries for the start call. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
* @param webhookUrl - A URL the provider should notify when the generation
* reaches a terminal state.
*
* @returns A result object that contains the opaque `operation` reference,
* warnings, provider metadata (including the provider's job id), and response
* metadata.
*/
async function experimental_startVideo({ model: modelArg, prompt: promptArg, n = 1, maxVideosPerCall, aspectRatio, resolution, duration, fps, seed, frameImages, inputReferences, generateAudio, providerOptions, maxRetries: maxRetriesArg, abortSignal, headers, webhookUrl }) {
	const model = resolveVideoModel(modelArg);
	if (model.doStart == null) throw new Error(`Video model ${model.modelId} does not implement doStart. Use generateVideo for models without an asynchronous start/status flow.`);
	if (!Number.isInteger(n) || n < 1) throw new Error(`Invalid n: expected a positive integer, received ${JSON.stringify(n)}.`);
	const knownMaxVideosPerCall = maxVideosPerCall ?? (typeof model.maxVideosPerCall === "function" ? await model.maxVideosPerCall({ modelId: model.modelId }) : model.maxVideosPerCall);
	if (knownMaxVideosPerCall != null && n > knownMaxVideosPerCall) throw new Error(`Video model ${model.modelId} supports at most ${knownMaxVideosPerCall} video(s) per call, but ${n} were requested. Split the batch across multiple startVideo calls.`);
	const { prompt, resolvedImage, normalizedFrameImages, effectiveInputReferences, warnings } = normalizeVideoCallInputs({
		promptArg,
		frameImages,
		inputReferences
	});
	const { retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	const callerIdempotencyKey = Object.entries(headers ?? {}).find(([key, value]) => key.toLowerCase() === "idempotency-key" && value !== void 0);
	const callOptions = {
		prompt,
		n,
		aspectRatio,
		resolution,
		duration,
		fps,
		seed,
		image: resolvedImage,
		frameImages: normalizedFrameImages,
		inputReferences: effectiveInputReferences,
		generateAudio,
		providerOptions: providerOptions ?? {},
		headers: {
			...withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`),
			...callerIdempotencyKey ? {} : { "idempotency-key": `aisdk_vid_${generateId$1()}` }
		},
		abortSignal,
		webhookUrl
	};
	const startResult = await retry(() => model.doStart(callOptions));
	return {
		operation: startResult.operation,
		warnings: [...warnings, ...startResult.warnings],
		providerMetadata: startResult.providerMetadata,
		response: startResult.response
	};
}
//#endregion
//#region src/generate-video/get-video-status.ts
/**
* Checks the status of an asynchronous video generation started with
* `experimental_startVideo`.
*
* A single check — no polling loop. Poll by calling this on your own
* schedule, or skip polling entirely when the start used `webhookUrl` and
* your receiver fetches the result after the terminal notification arrives.
*
* @param model - The video model the operation was started on.
* @param operation - The opaque reference returned by `experimental_startVideo`.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param maxRetries - Maximum number of retries for the status call. Set to 0 to disable retries. Default: 2.
*/
async function experimental_getVideoStatus(modelArg, { operation, headers, abortSignal, maxRetries: maxRetriesArg }) {
	const model = resolveVideoModel(modelArg);
	if (model.doStatus == null) throw new Error(`Video model ${model.modelId} does not implement doStatus.`);
	const { retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	return retry(() => model.doStatus({
		operation,
		headers: withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`),
		abortSignal
	}));
}
//#endregion
//#region src/middleware/default-embedding-settings-middleware.ts
/**
* Applies default settings for an embedding model.
*/
function defaultEmbeddingSettingsMiddleware({ settings }) {
	return {
		specificationVersion: "v4",
		transformParams: async ({ params }) => {
			return mergeObjects(settings, params);
		}
	};
}
//#endregion
//#region src/middleware/default-instructions-middleware.ts
/**
* Applies default instructions to a language model when a call does not
* already contain a system message.
*/
function defaultInstructionsMiddleware({ instructions }) {
	const defaultSystemMessages = typeof instructions === "string" ? [{
		role: "system",
		content: instructions
	}] : asArray(instructions).map((message) => ({
		role: "system",
		content: message.content,
		providerOptions: message.providerOptions
	}));
	return {
		specificationVersion: "v4",
		transformParams: async ({ params }) => {
			if (defaultSystemMessages.length === 0 || params.prompt.some((message) => message.role === "system")) return params;
			return {
				...params,
				prompt: [...defaultSystemMessages, ...params.prompt]
			};
		}
	};
}
//#endregion
//#region src/middleware/default-settings-middleware.ts
/**
* Applies default settings for a language model.
*/
function defaultSettingsMiddleware({ settings }) {
	return {
		specificationVersion: "v4",
		transformParams: async ({ params }) => {
			return mergeObjects(settings, params);
		}
	};
}
//#endregion
//#region src/middleware/extract-json-middleware.ts
/**
* Default transform function that strips markdown code fences from text.
*/
function defaultTransform(text) {
	return text.replace(/^```(?:json)?\s*\n?/, "").replace(/\n?```\s*$/, "").trim();
}
function stripMarkdownCodeFenceSuffix(text) {
	return text.replace(/\n?```\s*$/, "").trimEnd();
}
function getPotentialSuffixStart(text) {
	let index = text.length;
	while (index > 0 && /\s/.test(text[index - 1])) index--;
	let backtickCount = 0;
	while (index > 0 && backtickCount < 3 && text[index - 1] === "`") {
		index--;
		backtickCount++;
	}
	if (backtickCount > 0) while (index > 0 && /\s/.test(text[index - 1])) index--;
	return index;
}
/**
* Middleware that extracts JSON from text content by stripping
* markdown code fences and other formatting.
*
* This is useful when using Output.object() with models that wrap
* JSON responses in markdown code blocks.
*
* @param options - Configuration options for the middleware.
* @param options.transform - Custom transform function. If provided, this will be
* used instead of the default markdown fence stripping.
*/
function extractJsonMiddleware(options) {
	const transform = options?.transform ?? defaultTransform;
	const hasCustomTransform = options?.transform !== void 0;
	return {
		specificationVersion: "v4",
		wrapGenerate: async ({ doGenerate }) => {
			const { content, structuredOutputText, ...rest } = await doGenerate();
			const transformedContent = [];
			for (const part of content) {
				if (part.type !== "text") {
					transformedContent.push(part);
					continue;
				}
				transformedContent.push({
					...part,
					text: transform(part.text)
				});
			}
			return {
				content: transformedContent,
				...rest,
				...structuredOutputText != null && { structuredOutputText: transform(structuredOutputText) }
			};
		},
		wrapStream: async ({ doStream }) => {
			const { stream, ...rest } = await doStream();
			const textBlocks = createIdMap();
			return {
				stream: stream.pipeThrough(new TransformStream({ transform: (chunk, controller) => {
					if (chunk.type === "text-start") {
						textBlocks[chunk.id] = {
							startEvent: chunk,
							phase: hasCustomTransform ? "buffering" : "prefix",
							buffer: "",
							prefixStripped: false
						};
						return;
					}
					if (chunk.type === "text-delta") {
						const block = textBlocks[chunk.id];
						if (!block) {
							controller.enqueue(chunk);
							return;
						}
						block.buffer += chunk.delta;
						if (block.phase === "buffering") return;
						if (block.phase === "prefix") {
							if (block.buffer.length > 0 && !block.buffer.startsWith("`")) {
								block.phase = "streaming";
								controller.enqueue(block.startEvent);
							} else if (block.buffer.startsWith("```")) {
								if (block.buffer.includes("\n")) {
									const prefixMatch = block.buffer.match(/^```(?:json)?\s*\n/);
									if (prefixMatch) {
										block.buffer = block.buffer.slice(prefixMatch[0].length);
										block.prefixStripped = true;
										block.phase = "streaming";
										controller.enqueue(block.startEvent);
									} else {
										block.phase = "streaming";
										controller.enqueue(block.startEvent);
									}
								}
							} else if (block.buffer.length >= 3 && !block.buffer.startsWith("```")) {
								block.phase = "streaming";
								controller.enqueue(block.startEvent);
							}
						}
						if (block.phase === "streaming") {
							const potentialSuffixStart = getPotentialSuffixStart(block.buffer);
							const toStream = block.buffer.slice(0, potentialSuffixStart);
							block.buffer = block.buffer.slice(potentialSuffixStart);
							if (toStream.length === 0) return;
							controller.enqueue({
								type: "text-delta",
								id: chunk.id,
								delta: toStream
							});
						}
						return;
					}
					if (chunk.type === "text-end") {
						const block = textBlocks[chunk.id];
						if (block) {
							if (block.phase === "prefix" || block.phase === "buffering") controller.enqueue(block.startEvent);
							let remaining = block.buffer;
							if (block.phase === "buffering") remaining = transform(remaining);
							else if (block.prefixStripped) remaining = stripMarkdownCodeFenceSuffix(remaining);
							else if (block.phase === "prefix") remaining = transform(remaining);
							else remaining = stripMarkdownCodeFenceSuffix(remaining);
							if (remaining.length > 0) controller.enqueue({
								type: "text-delta",
								id: chunk.id,
								delta: remaining
							});
							controller.enqueue(chunk);
							delete textBlocks[chunk.id];
							return;
						}
					}
					controller.enqueue(chunk);
				} })),
				...rest
			};
		}
	};
}
//#endregion
//#region src/util/get-potential-start-index.ts
/**
* Finds the potential starting index where searchedText could begin in text.
*
* This function checks for both complete and partial matches:
* - If searchedText is found as a complete substring, returns the index of the first occurrence.
* - If the end of text matches the beginning of searchedText (partial match),
*   returns the index where that partial match starts.
*
* @param text - The text to search within.
* @param searchedText - The text to search for.
* @returns The starting index of the match (complete or partial), or null if
*          searchedText is empty or no match is found.
*/
function getPotentialStartIndex(text, searchedText) {
	if (searchedText.length === 0) return null;
	const directIndex = text.indexOf(searchedText);
	if (directIndex !== -1) return directIndex;
	for (let i = text.length - 1; i >= 0; i--) {
		const suffix = text.substring(i);
		if (searchedText.startsWith(suffix)) return i;
	}
	return null;
}
//#endregion
//#region src/middleware/extract-reasoning-middleware.ts
/**
* Extracts a delimited reasoning section from the generated text and exposes it
* as a `reasoning` property on the result.
*
* @param tagName - An XML tag name (without angle brackets), or literal opening
* and closing delimiters for formats such as Gemma's thought channel.
* @param separator - The separator to use between reasoning and text sections.
* @param startWithReasoning - Whether to start with reasoning tokens.
*/
function extractReasoningMiddleware({ tagName, separator = "\n", startWithReasoning = false }) {
	const openingTag = typeof tagName === "string" ? `<${tagName}>` : tagName.opening;
	const closingTag = typeof tagName === "string" ? `</${tagName}>` : tagName.closing;
	if (openingTag.length === 0 || closingTag.length === 0) throw new InvalidArgumentError({
		parameter: "tagName",
		value: tagName,
		message: "Reasoning delimiters must not be empty."
	});
	const escapedOpeningTag = openingTag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
	const escapedClosingTag = closingTag.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
	function extractReasoning(input) {
		const text = startWithReasoning ? openingTag + input : input;
		const regexp = new RegExp(`${escapedOpeningTag}(.*?)${escapedClosingTag}`, "gs");
		const matches = Array.from(text.matchAll(regexp));
		if (!matches.length) return {
			text: input,
			reasoning: void 0
		};
		const reasoning = matches.map((match) => match[1]).join(separator);
		let textWithoutReasoning = text;
		for (let i = matches.length - 1; i >= 0; i--) {
			const match = matches[i];
			const beforeMatch = textWithoutReasoning.slice(0, match.index);
			const afterMatch = textWithoutReasoning.slice(match.index + match[0].length);
			textWithoutReasoning = beforeMatch + (beforeMatch.length > 0 && afterMatch.length > 0 ? separator : "") + afterMatch;
		}
		return {
			text: textWithoutReasoning,
			reasoning
		};
	}
	return {
		specificationVersion: "v4",
		wrapGenerate: async ({ doGenerate }) => {
			const { content, structuredOutputText, ...rest } = await doGenerate();
			const transformedContent = [];
			for (const part of content) {
				if (part.type !== "text") {
					transformedContent.push(part);
					continue;
				}
				const { text, reasoning } = extractReasoning(part.text);
				if (reasoning === void 0) {
					transformedContent.push(part);
					continue;
				}
				transformedContent.push({
					type: "reasoning",
					text: reasoning
				});
				transformedContent.push({
					type: "text",
					text
				});
			}
			return {
				content: transformedContent,
				...rest,
				...structuredOutputText != null && { structuredOutputText: extractReasoning(structuredOutputText).text }
			};
		},
		wrapStream: async ({ doStream }) => {
			const { stream, ...rest } = await doStream();
			const reasoningExtractions = createIdMap();
			let reasoningIdCounter = 0;
			const delayedTextStarts = createIdMap();
			return {
				stream: stream.pipeThrough(new TransformStream({ transform: (chunk, controller) => {
					if (chunk.type === "text-start") {
						delayedTextStarts[chunk.id] = chunk;
						return;
					}
					if (chunk.type !== "text-delta" && chunk.type !== "text-end") {
						controller.enqueue(chunk);
						return;
					}
					if (chunk.type === "text-delta" && reasoningExtractions[chunk.id] == null) reasoningExtractions[chunk.id] = {
						isFirstReasoning: true,
						isFirstText: true,
						afterSwitch: false,
						isReasoning: startWithReasoning,
						buffer: "",
						reasoningId: void 0,
						textId: chunk.id
					};
					const activeExtraction = reasoningExtractions[chunk.id];
					if (activeExtraction == null) {
						if (delayedTextStarts[chunk.id] != null) {
							controller.enqueue(delayedTextStarts[chunk.id]);
							delete delayedTextStarts[chunk.id];
						}
						controller.enqueue(chunk);
						return;
					}
					function getReasoningId() {
						return activeExtraction.reasoningId ??= `reasoning-${reasoningIdCounter++}`;
					}
					function publish(text) {
						if (text.length > 0) {
							const prefix = activeExtraction.afterSwitch && (activeExtraction.isReasoning ? !activeExtraction.isFirstReasoning : !activeExtraction.isFirstText) ? separator : "";
							if (activeExtraction.isReasoning && (activeExtraction.afterSwitch || activeExtraction.isFirstReasoning)) controller.enqueue({
								type: "reasoning-start",
								id: getReasoningId()
							});
							if (activeExtraction.isReasoning) controller.enqueue({
								type: "reasoning-delta",
								delta: prefix + text,
								id: getReasoningId()
							});
							else {
								if (delayedTextStarts[activeExtraction.textId] != null) {
									controller.enqueue(delayedTextStarts[activeExtraction.textId]);
									delete delayedTextStarts[activeExtraction.textId];
								}
								controller.enqueue({
									type: "text-delta",
									delta: prefix + text,
									id: activeExtraction.textId
								});
							}
							activeExtraction.afterSwitch = false;
							if (activeExtraction.isReasoning) activeExtraction.isFirstReasoning = false;
							else activeExtraction.isFirstText = false;
						}
					}
					if (chunk.type === "text-end") {
						publish(activeExtraction.buffer);
						activeExtraction.buffer = "";
						if (delayedTextStarts[chunk.id] != null) {
							controller.enqueue(delayedTextStarts[chunk.id]);
							delete delayedTextStarts[chunk.id];
						}
						controller.enqueue(chunk);
						return;
					}
					activeExtraction.buffer += chunk.delta;
					do {
						const nextTag = activeExtraction.isReasoning ? closingTag : openingTag;
						const startIndex = getPotentialStartIndex(activeExtraction.buffer, nextTag);
						if (startIndex == null) {
							publish(activeExtraction.buffer);
							activeExtraction.buffer = "";
							break;
						}
						publish(activeExtraction.buffer.slice(0, startIndex));
						if (startIndex + nextTag.length <= activeExtraction.buffer.length) {
							activeExtraction.buffer = activeExtraction.buffer.slice(startIndex + nextTag.length);
							if (activeExtraction.isReasoning) {
								if (activeExtraction.isFirstReasoning) controller.enqueue({
									type: "reasoning-start",
									id: getReasoningId()
								});
								controller.enqueue({
									type: "reasoning-end",
									id: getReasoningId()
								});
								activeExtraction.reasoningId = void 0;
							}
							activeExtraction.isReasoning = !activeExtraction.isReasoning;
							activeExtraction.afterSwitch = true;
						} else {
							activeExtraction.buffer = activeExtraction.buffer.slice(startIndex);
							break;
						}
					} while (true);
				} })),
				...rest
			};
		}
	};
}
//#endregion
//#region src/middleware/simulate-streaming-middleware.ts
/**
* Simulates streaming chunks with the response from a generate call.
*/
function simulateStreamingMiddleware() {
	return {
		specificationVersion: "v4",
		wrapStream: async ({ doGenerate }) => {
			const result = await doGenerate();
			let id = 0;
			return {
				stream: new ReadableStream({ start(controller) {
					controller.enqueue({
						type: "stream-start",
						warnings: result.warnings
					});
					controller.enqueue({
						type: "response-metadata",
						...result.response
					});
					for (const part of result.content) switch (part.type) {
						case "text":
							if (part.text.length > 0 || (part.citations?.length ?? 0) > 0) {
								controller.enqueue({
									type: "text-start",
									id: String(id),
									...part.providerMetadata != null ? { providerMetadata: part.providerMetadata } : {}
								});
								controller.enqueue({
									type: "text-delta",
									id: String(id),
									delta: part.text
								});
								controller.enqueue({
									type: "text-end",
									id: String(id),
									...part.citations != null ? { citations: part.citations } : {}
								});
								id++;
							}
							break;
						case "reasoning":
							controller.enqueue({
								type: "reasoning-start",
								id: String(id),
								providerMetadata: part.providerMetadata
							});
							controller.enqueue({
								type: "reasoning-delta",
								id: String(id),
								delta: part.text
							});
							controller.enqueue({
								type: "reasoning-end",
								id: String(id)
							});
							id++;
							break;
						default: controller.enqueue(part);
					}
					controller.enqueue({
						type: "finish",
						finishReason: result.finishReason,
						usage: result.usage,
						providerMetadata: result.providerMetadata
					});
					controller.close();
				} }),
				request: result.request,
				response: result.response
			};
		}
	};
}
//#endregion
//#region src/middleware/add-tool-input-examples-middleware.ts
function defaultFormatExample(example) {
	return JSON.stringify(example.input);
}
/**
* Middleware that appends input examples to tool descriptions.
*
* This is useful for providers that don't natively support the `inputExamples`
* property. The middleware serializes examples into the tool's description text.
*
* @param options - Configuration options for the middleware.
* @param options.prefix - A prefix to prepend before the examples. Default: 'Input Examples:'
* @param options.format - Optional custom formatter for each example.
*   Receives the example object and its index. Default: JSON.stringify(example.input)
* @param options.remove - Whether to remove the inputExamples property
*   after adding them to the description. Default: true
*
* @example
* ```ts
* import { wrapLanguageModel, addToolInputExamplesMiddleware } from 'ai';
*
* const model = wrapLanguageModel({
*   model: yourModel,
*   middleware: addToolInputExamplesMiddleware(),
* });
* ```
*/
function addToolInputExamplesMiddleware({ prefix = "Input Examples:", format = defaultFormatExample, remove = true } = {}) {
	return {
		specificationVersion: "v4",
		transformParams: async ({ params }) => {
			if (!params.tools?.length) return params;
			const transformedTools = params.tools.map((tool) => {
				if (tool.type !== "function" || !tool.inputExamples?.length) return tool;
				const examplesSection = `${prefix}\n${tool.inputExamples.map((example, index) => format(example, index)).join("\n")}`;
				const toolDescription = tool.description ? `${tool.description}\n\n${examplesSection}` : examplesSection;
				return {
					...tool,
					description: toolDescription,
					inputExamples: remove ? void 0 : tool.inputExamples
				};
			});
			return {
				...params,
				tools: transformedTools
			};
		}
	};
}
//#endregion
//#region src/middleware/wrap-language-model.ts
/**
* Wraps a LanguageModelV4 instance with middleware functionality.
* This function allows you to apply middleware to transform parameters,
* wrap generate operations, and wrap stream operations of a language model.
*
* @param options - Configuration options for wrapping the language model.
* @param options.model - The original LanguageModelV4 instance to be wrapped.
* @param options.middleware - The middleware to be applied to the language model. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
* @param options.modelId - Optional custom model ID to override the original model's ID.
* @param options.providerId - Optional custom provider ID to override the original model's provider ID.
* @returns A new LanguageModelV4 instance with middleware applied.
*/
const wrapLanguageModel = ({ model: inputModel, middleware: middlewareArg, modelId, providerId }) => {
	const model = asLanguageModelV4(inputModel);
	return [...asArray(middlewareArg)].reverse().reduce((wrappedModel, middleware) => {
		return doWrap$2({
			model: wrappedModel,
			middleware,
			modelId,
			providerId
		});
	}, model);
};
const doWrap$2 = ({ model, middleware: { transformParams, wrapGenerate, wrapStream, overrideProvider, overrideModelId, overrideSupportedUrls }, modelId, providerId }) => {
	async function doTransform({ params, type }) {
		return transformParams ? await transformParams({
			params,
			type,
			model
		}) : params;
	}
	return {
		specificationVersion: "v4",
		provider: providerId ?? overrideProvider?.({ model }) ?? model.provider,
		modelId: modelId ?? overrideModelId?.({ model }) ?? model.modelId,
		supportedUrls: overrideSupportedUrls?.({ model }) ?? model.supportedUrls,
		async doGenerate(params) {
			const transformedParams = await doTransform({
				params,
				type: "generate"
			});
			const doGenerate = async () => await model.doGenerate(transformedParams);
			const doStream = async () => await model.doStream(transformedParams);
			return wrapGenerate ? await wrapGenerate({
				doGenerate,
				doStream,
				params: transformedParams,
				model
			}) : await doGenerate();
		},
		async doStream(params) {
			const transformedParams = await doTransform({
				params,
				type: "stream"
			});
			const doGenerate = async () => await model.doGenerate(transformedParams);
			const doStream = async () => await model.doStream(transformedParams);
			return wrapStream ? await wrapStream({
				doGenerate,
				doStream,
				params: transformedParams,
				model
			}) : await doStream();
		}
	};
};
//#endregion
//#region src/middleware/wrap-embedding-model.ts
/**
* Wraps an EmbeddingModelV4 instance with middleware functionality.
* This function allows you to apply middleware to transform parameters,
* wrap embed operations of an embedding model.
*
* @param options - Configuration options for wrapping the embedding model.
* @param options.model - The original EmbeddingModelV4 instance to be wrapped.
* @param options.middleware - The middleware to be applied to the embedding model. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
* @param options.modelId - Optional custom model ID to override the original model's ID.
* @param options.providerId - Optional custom provider ID to override the original model's provider ID.
* @returns A new EmbeddingModelV4 instance with middleware applied.
*/
const wrapEmbeddingModel = ({ model: inputModel, middleware: middlewareArg, modelId, providerId }) => {
	const model = asEmbeddingModelV4(inputModel);
	return [...asArray(middlewareArg)].reverse().reduce((wrappedModel, middleware) => {
		return doWrap$1({
			model: wrappedModel,
			middleware,
			modelId,
			providerId
		});
	}, model);
};
const doWrap$1 = ({ model, middleware: { transformParams, wrapEmbed, overrideProvider, overrideModelId, overrideMaxEmbeddingsPerCall, overrideSupportsParallelCalls }, modelId, providerId }) => {
	async function doTransform({ params }) {
		return transformParams ? await transformParams({
			params,
			model
		}) : params;
	}
	return {
		specificationVersion: "v4",
		provider: providerId ?? overrideProvider?.({ model }) ?? model.provider,
		modelId: modelId ?? overrideModelId?.({ model }) ?? model.modelId,
		maxEmbeddingsPerCall: overrideMaxEmbeddingsPerCall?.({ model }) ?? model.maxEmbeddingsPerCall,
		[EXPERIMENTAL_EMBEDDING_MODEL_MAX_INPUT_BYTES_PER_CALL]: getEmbeddingModelMaxInputBytesPerCall(model),
		[EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER]: getEmbeddingModelProviderOptionsTransformer(model),
		supportsParallelCalls: overrideSupportsParallelCalls?.({ model }) ?? model.supportsParallelCalls,
		async doEmbed(params) {
			const transformedParams = await doTransform({ params });
			const doEmbed = async () => await model.doEmbed(transformedParams);
			return wrapEmbed ? await wrapEmbed({
				doEmbed,
				params: transformedParams,
				model
			}) : await doEmbed();
		}
	};
};
//#endregion
//#region src/middleware/wrap-image-model.ts
/**
* Wraps an ImageModelV4 instance with middleware functionality.
* This function allows you to apply middleware to transform parameters
* and wrap generate operations of an image model.
*
* @param options - Configuration options for wrapping the image model.
* @param options.model - The original ImageModelV4 instance to be wrapped.
* @param options.middleware - The middleware to be applied to the image model. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
* @param options.modelId - Optional custom model ID to override the original model's ID.
* @param options.providerId - Optional custom provider ID to override the original model's provider ID.
* @returns A new ImageModelV4 instance with middleware applied.
*/
const wrapImageModel = ({ model: inputModel, middleware: middlewareArg, modelId, providerId }) => {
	const model = asImageModelV4(inputModel);
	return [...asArray(middlewareArg)].reverse().reduce((wrappedModel, middleware) => {
		return doWrap({
			model: wrappedModel,
			middleware,
			modelId,
			providerId
		});
	}, model);
};
const doWrap = ({ model, middleware: { transformParams, wrapGenerate, overrideProvider, overrideModelId, overrideMaxImagesPerCall, overrideSupportsFileInputs, overrideSupportsMaskInputs }, modelId, providerId }) => {
	async function doTransform({ params }) {
		return transformParams ? await transformParams({
			params,
			model
		}) : params;
	}
	const maxImagesPerCallRaw = overrideMaxImagesPerCall?.({ model }) ?? model.maxImagesPerCall;
	const maxImagesPerCall = maxImagesPerCallRaw instanceof Function ? maxImagesPerCallRaw.bind(model) : maxImagesPerCallRaw;
	const supportsFileInputs = overrideSupportsFileInputs !== void 0 ? overrideSupportsFileInputs({ model }) : model.supportsFileInputs;
	const supportsMaskInputs = overrideSupportsMaskInputs !== void 0 ? overrideSupportsMaskInputs({ model }) : model.supportsMaskInputs;
	return {
		specificationVersion: "v4",
		provider: providerId ?? overrideProvider?.({ model }) ?? model.provider,
		modelId: modelId ?? overrideModelId?.({ model }) ?? model.modelId,
		maxImagesPerCall,
		supportsFileInputs,
		supportsMaskInputs,
		async doGenerate(params) {
			const transformedParams = await doTransform({ params });
			const doGenerate = async () => await model.doGenerate(transformedParams);
			return wrapGenerate ? await wrapGenerate({
				doGenerate,
				params: transformedParams,
				model
			}) : await doGenerate();
		}
	};
};
//#endregion
//#region src/middleware/wrap-provider.ts
/**
* Wraps a ProviderV4 instance with middleware functionality.
* This function allows you to apply middleware to all language models
* from the provider, enabling you to transform parameters, wrap generate
* operations, and wrap stream operations for every language model.
*
* @param options - Configuration options for wrapping the provider.
* @param options.provider - The original ProviderV4 instance to be wrapped.
* @param options.languageModelMiddleware - The middleware to be applied to all language models from the provider. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
* @param options.imageModelMiddleware - Optional middleware to be applied to all image models from the provider. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
* @returns A new ProviderV4 instance with middleware applied to all language models.
*/
function wrapProvider({ provider, languageModelMiddleware, imageModelMiddleware }) {
	const providerV4 = asProviderV4(provider);
	return {
		specificationVersion: "v4",
		languageModel: (modelId) => wrapLanguageModel({
			model: providerV4.languageModel(modelId),
			middleware: languageModelMiddleware
		}),
		embeddingModel: providerV4.embeddingModel,
		imageModel: (modelId) => {
			let model = providerV4.imageModel(modelId);
			if (imageModelMiddleware != null) model = wrapImageModel({
				model,
				middleware: imageModelMiddleware
			});
			return model;
		},
		transcriptionModel: providerV4.transcriptionModel,
		speechModel: providerV4.speechModel,
		rerankingModel: providerV4.rerankingModel,
		...providerV4.files != null ? { files: providerV4.files } : {},
		...providerV4.skills != null ? { skills: providerV4.skills } : {}
	};
}
//#endregion
//#region src/prompt/content-part.ts
const fileInlineDataSchema = z.union([
	z.string(),
	z.custom(isUint8Array, { message: "Must be a Uint8Array" }),
	z.custom(isArrayBuffer, { message: "Must be an ArrayBuffer" }),
	z.custom(isBuffer, { message: "Must be a Buffer" })
]);
const providerReferenceSchema = z.record(z.string(), z.string());
/**
* @internal
*/
const textPartSchema = z.object({
	type: z.literal("text"),
	text: z.string(),
	providerOptions: providerMetadataSchema$1.optional()
});
/**
* @internal
* @deprecated Use `filePartSchema` with `mediaType: 'image'` instead:
* `{ type: 'file', mediaType: 'image', data: { type: 'data', data } }`.
*/
const imagePartSchema = z.object({
	type: z.literal("image"),
	image: z.union([
		fileInlineDataSchema,
		z.instanceof(URL),
		providerReferenceSchema
	]),
	mediaType: z.string().optional(),
	providerOptions: providerMetadataSchema$1.optional()
});
const taggedFileDataSchema = z.discriminatedUnion("type", [
	z.object({
		type: z.literal("data"),
		data: fileInlineDataSchema
	}),
	z.object({
		type: z.literal("url"),
		url: z.instanceof(URL)
	}),
	z.object({
		type: z.literal("reference"),
		reference: providerReferenceSchema
	}),
	z.object({
		type: z.literal("text"),
		text: z.string()
	})
]);
const taggedReasoningFileDataSchema = z.discriminatedUnion("type", [z.object({
	type: z.literal("data"),
	data: fileInlineDataSchema
}), z.object({
	type: z.literal("url"),
	url: z.instanceof(URL)
})]);
/**
* @internal
*/
const filePartSchema = z.object({
	type: z.literal("file"),
	data: z.union([
		taggedFileDataSchema,
		fileInlineDataSchema,
		z.instanceof(URL),
		providerReferenceSchema
	]),
	filename: z.string().optional(),
	mediaType: z.string(),
	providerOptions: providerMetadataSchema$1.optional()
});
/**
* @internal
*/
const reasoningPartSchema = z.object({
	type: z.literal("reasoning"),
	text: z.string(),
	providerOptions: providerMetadataSchema$1.optional()
});
/**
* @internal
*/
const customPartSchema = z.object({
	type: z.literal("custom"),
	kind: z.string().transform((value) => value),
	providerOptions: providerMetadataSchema$1.optional()
});
/**
* @internal
*/
const reasoningFilePartSchema = z.object({
	type: z.literal("reasoning-file"),
	data: z.union([
		taggedReasoningFileDataSchema,
		fileInlineDataSchema,
		z.instanceof(URL)
	]),
	mediaType: z.string(),
	providerOptions: providerMetadataSchema$1.optional()
});
/**
* @internal
*/
const toolCallPartSchema = z.object({
	type: z.literal("tool-call"),
	toolCallId: z.string(),
	toolName: z.string(),
	input: z.unknown(),
	providerOptions: providerMetadataSchema$1.optional(),
	providerExecuted: z.boolean().optional()
});
/**
* @internal
*/
const outputSchema = z.discriminatedUnion("type", [
	z.object({
		type: z.literal("text"),
		value: z.string(),
		providerOptions: providerMetadataSchema$1.optional()
	}),
	z.object({
		type: z.literal("json"),
		value: jsonValueSchema,
		providerOptions: providerMetadataSchema$1.optional()
	}),
	z.object({
		type: z.literal("execution-denied"),
		reason: z.string().optional(),
		providerOptions: providerMetadataSchema$1.optional()
	}),
	z.object({
		type: z.literal("error-text"),
		value: z.string(),
		providerOptions: providerMetadataSchema$1.optional()
	}),
	z.object({
		type: z.literal("error-json"),
		value: jsonValueSchema,
		providerOptions: providerMetadataSchema$1.optional()
	}),
	z.object({
		type: z.literal("content"),
		value: z.array(z.union([
			z.object({
				type: z.literal("text"),
				text: z.string(),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("file"),
				data: taggedFileDataSchema,
				mediaType: z.string(),
				filename: z.string().optional(),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("file-data"),
				data: z.string(),
				mediaType: z.string(),
				filename: z.string().optional(),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("file-url"),
				url: z.string(),
				mediaType: z.string().optional(),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("file-id"),
				fileId: z.union([z.string(), z.record(z.string(), z.string())]),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("file-reference"),
				providerReference: z.record(z.string(), z.string()),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("image-data"),
				data: z.string(),
				mediaType: z.string(),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("image-url"),
				url: z.string(),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("image-file-id"),
				fileId: z.union([z.string(), z.record(z.string(), z.string())]),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("image-file-reference"),
				providerReference: z.record(z.string(), z.string()),
				providerOptions: providerMetadataSchema$1.optional()
			}),
			z.object({
				type: z.literal("custom"),
				providerOptions: providerMetadataSchema$1.optional()
			})
		]))
	})
]);
/**
* @internal
*/
const toolResultPartSchema = z.object({
	type: z.literal("tool-result"),
	toolCallId: z.string(),
	toolName: z.string(),
	output: outputSchema,
	providerOptions: providerMetadataSchema$1.optional()
});
/**
* @internal
*/
const toolApprovalRequestSchema = z.object({
	type: z.literal("tool-approval-request"),
	approvalId: z.string(),
	toolCallId: z.string(),
	reason: z.string().optional(),
	isAutomatic: z.boolean().optional(),
	signature: z.string().optional(),
	inputSchemaInput: z.unknown().optional()
});
/**
* @internal
*/
const toolApprovalResponseSchema = z.object({
	type: z.literal("tool-approval-response"),
	approvalId: z.string(),
	approved: z.boolean(),
	reason: z.string().optional()
});
//#endregion
//#region src/prompt/message.ts
const systemModelMessageSchema = z.object({
	role: z.literal("system"),
	content: z.string(),
	providerOptions: providerMetadataSchema$1.optional()
});
const userModelMessageSchema = z.object({
	role: z.literal("user"),
	content: z.union([z.string(), z.array(z.union([
		textPartSchema,
		imagePartSchema,
		filePartSchema
	]))]),
	providerOptions: providerMetadataSchema$1.optional()
});
const assistantModelMessageSchema = z.object({
	role: z.literal("assistant"),
	content: z.union([z.string(), z.array(z.union([
		textPartSchema,
		customPartSchema,
		filePartSchema,
		reasoningPartSchema,
		reasoningFilePartSchema,
		toolCallPartSchema,
		toolResultPartSchema,
		toolApprovalRequestSchema
	]))]),
	providerOptions: providerMetadataSchema$1.optional()
});
const toolModelMessageSchema = z.object({
	role: z.literal("tool"),
	content: z.array(z.union([toolResultPartSchema, toolApprovalResponseSchema])),
	providerOptions: providerMetadataSchema$1.optional()
});
const modelMessageSchema = z.union([
	systemModelMessageSchema,
	userModelMessageSchema,
	assistantModelMessageSchema,
	toolModelMessageSchema
]);
//#endregion
//#region src/realtime/audio-utils.ts
/**
* Converts Float32 audio samples to a base64-encoded PCM16 string
* for sending to a realtime model via input_audio_buffer.append.
*
* Samples are expected to be in the range [-1.0, 1.0].
* Output is 16-bit signed integer, little-endian, base64-encoded.
*/
function encodeRealtimeAudio(float32Array) {
	const buffer = /* @__PURE__ */ new ArrayBuffer(float32Array.length * 2);
	const view = new DataView(buffer);
	for (let i = 0; i < float32Array.length; i++) {
		const s = Math.max(-1, Math.min(1, float32Array[i]));
		view.setInt16(i * 2, s < 0 ? s * 32768 : s * 32767, true);
	}
	const bytes = new Uint8Array(buffer);
	const chunkSize = 32768;
	let binary = "";
	for (let i = 0; i < bytes.length; i += chunkSize) {
		const chunk = bytes.subarray(i, i + chunkSize);
		binary += String.fromCharCode(...chunk);
	}
	return btoa(binary);
}
/**
* Converts a base64-encoded PCM16 string (from a realtime model's
* audio-delta event) back to Float32 audio samples.
*
* Input is expected to be 16-bit signed integer, little-endian, base64-encoded.
* Output samples are in the range [-1.0, 1.0].
*/
function decodeRealtimeAudio(base64Audio) {
	const binaryString = atob(base64Audio);
	const bytes = new Uint8Array(binaryString.length);
	for (let i = 0; i < binaryString.length; i++) bytes[i] = binaryString.charCodeAt(i);
	const pcm16 = new Int16Array(bytes.buffer);
	const float32 = new Float32Array(pcm16.length);
	for (let i = 0; i < pcm16.length; i++) float32[i] = pcm16[i] / 32768;
	return float32;
}
/**
* Resamples audio from one sample rate to another using linear
* interpolation. Suitable for voice audio.
*
* @param input - Float32 audio samples at the input sample rate.
* @param inputRate - The sample rate of the input audio (e.g. 48000).
* @param outputRate - The desired output sample rate (e.g. 24000).
* @returns Float32 audio samples at the output sample rate.
*/
function resampleAudio(input, inputRate, outputRate) {
	if (inputRate === outputRate) return input;
	const ratio = inputRate / outputRate;
	const outputLength = Math.round(input.length / ratio);
	const output = new Float32Array(outputLength);
	for (let i = 0; i < outputLength; i++) {
		const srcIndex = i * ratio;
		const srcIndexFloor = Math.floor(srcIndex);
		const srcIndexCeil = Math.min(srcIndexFloor + 1, input.length - 1);
		const fraction = srcIndex - srcIndexFloor;
		output[i] = input[srcIndexFloor] * (1 - fraction) + input[srcIndexCeil] * fraction;
	}
	return output;
}
//#endregion
//#region src/realtime/get-realtime-tool-definitions.ts
async function getRealtimeToolDefinitions({ tools, toolsContext = {} }) {
	const definitions = [];
	for (const [name, tool] of Object.entries(tools)) {
		const toolType = tool.type;
		switch (toolType) {
			case void 0:
			case "function":
			case "dynamic": {
				const description = resolveRealtimeToolDescription({
					tool,
					toolName: name,
					toolsContext
				});
				definitions.push({
					type: "function",
					name,
					description,
					parameters: await asSchema$1(tool.inputSchema).jsonSchema
				});
				break;
			}
			case "provider": break;
			default: throw new Error(`Unsupported tool type: ${toolType}`);
		}
	}
	return definitions;
}
function resolveRealtimeToolDescription({ tool, toolName, toolsContext }) {
	return tool.description === void 0 ? void 0 : typeof tool.description === "string" ? tool.description : tool.description({ context: toolsContext[toolName] });
}
//#endregion
//#region src/realtime/browser-realtime-audio.ts
var BrowserRealtimeAudio = class {
	constructor(options) {
		this.captureContext = null;
		this.captureProcessor = null;
		this.captureSource = null;
		this.captureStream = null;
		this.ownsCaptureStream = true;
		this.captureCleanup = [];
		this.captureGeneration = 0;
		this.playbackContext = null;
		this.playbackQueue = [];
		this.playbackTime = 0;
		this.playbackStartTime = 0;
		this.activeSources = /* @__PURE__ */ new Set();
		this.isPlaying = false;
		this.playbackPaused = false;
		this.captureSampleRate = options.captureSampleRate;
		this.playbackSampleRate = options.playbackSampleRate;
		this.onAudio = options.onAudio;
		this.onPlayingChange = options.onPlayingChange;
		this.maxPlaybackSeconds = options.maxPlaybackSeconds ?? Infinity;
		this.onError = options.onError;
		this.onCapturingChange = options.onCapturingChange;
	}
	ensurePlaybackContext() {
		if (this.playbackContext == null) {
			this.playbackContext = new AudioContext({ sampleRate: this.playbackSampleRate });
			const context = this.playbackContext;
			context.onstatechange = () => {
				if (this.playbackContext === context) this.setPlaying(context.state === "running" && this.activeSources.size > 0);
			};
		}
	}
	async resumePlayback() {
		this.ensurePlaybackContext();
		const context = this.playbackContext;
		if (this.playbackPaused) this.stopPlayback();
		if (this.playbackContext !== context) return;
		await context?.resume();
		if (this.playbackContext !== context) return;
		this.playbackPaused = false;
		this.setPlaying(this.playbackContext?.state === "running" && this.activeSources.size > 0);
	}
	startCapture(stream, options) {
		const generation = this.captureGeneration + 1;
		this.stopCapture();
		if (generation !== this.captureGeneration) {
			if (options?.ownsStream ?? true) stream.getTracks().forEach((track) => track.stop());
			return;
		}
		this.captureStream = stream;
		this.ownsCaptureStream = options?.ownsStream ?? true;
		const ctx = new AudioContext({ sampleRate: this.captureSampleRate });
		this.captureContext = ctx;
		ctx.resume().catch((error) => {
			if (this.captureContext === ctx) this.onError?.(error);
		});
		const source = ctx.createMediaStreamSource(stream);
		this.captureSource = source;
		const processor = ctx.createScriptProcessor(1024, 1, 1);
		this.captureProcessor = processor;
		processor.onaudioprocess = (event) => {
			if (this.captureContext !== ctx) return;
			const inputData = event.inputBuffer.getChannelData(0);
			const samples = resampleAudio(new Float32Array(inputData), ctx.sampleRate, this.captureSampleRate);
			try {
				this.onAudio(encodeRealtimeAudio(samples));
			} catch (error) {
				this.onError?.(error instanceof Error ? error : new Error(String(error)));
			}
		};
		source.connect(processor);
		processor.connect(ctx.destination);
		const updateCapturing = () => this.onCapturingChange(stream.getAudioTracks().some((track) => track.enabled && !track.muted && track.readyState === "live"));
		for (const track of stream.getAudioTracks()) for (const event of [
			"ended",
			"mute",
			"unmute"
		]) {
			track.addEventListener(event, updateCapturing);
			this.captureCleanup.push(() => track.removeEventListener(event, updateCapturing));
		}
		updateCapturing();
	}
	stopCapture() {
		this.captureGeneration++;
		if (this.captureProcessor != null) this.captureProcessor.onaudioprocess = null;
		for (const cleanup of this.captureCleanup) cleanup();
		this.captureCleanup = [];
		this.captureProcessor?.disconnect();
		this.captureSource?.disconnect();
		this.captureContext?.close().catch(() => {});
		if (this.ownsCaptureStream) this.captureStream?.getTracks().forEach((track) => track.stop());
		this.captureProcessor = null;
		this.captureSource = null;
		this.captureContext = null;
		this.captureStream = null;
		this.onCapturingChange(false);
	}
	playAudio(base64Audio) {
		if (this.playbackPaused) return;
		this.ensurePlaybackContext();
		const samples = decodeRealtimeAudio(base64Audio);
		if (Math.max(0, this.playbackTime - (this.playbackContext?.currentTime ?? 0)) + samples.length / this.playbackSampleRate > this.maxPlaybackSeconds) {
			this.playbackPaused = true;
			this.stopPlayback();
			this.onError?.(/* @__PURE__ */ new Error("Realtime audio playback buffer is full; playback paused, call resumePlayback() to resume at the live edge"));
			return;
		}
		this.playbackQueue.push(samples);
		this.schedulePlayback();
	}
	stopPlayback() {
		this.playbackQueue = [];
		for (const source of this.activeSources) try {
			source.onended = null;
			source.stop();
			source.disconnect();
		} catch {}
		this.activeSources.clear();
		if (this.playbackContext != null) this.playbackTime = this.playbackContext.currentTime;
		this.setPlaying(false);
	}
	getPlaybackOffsetMs() {
		const ctx = this.playbackContext;
		if (ctx == null) return 0;
		return (ctx.currentTime - this.playbackStartTime) * 1e3;
	}
	dispose() {
		this.stopCapture();
		this.stopPlayback();
		if (this.playbackContext != null) this.playbackContext.onstatechange = null;
		this.playbackContext?.close().catch(() => {});
		this.playbackContext = null;
		this.playbackTime = 0;
		this.playbackPaused = false;
	}
	setPlaying(isPlaying) {
		if (isPlaying && !this.isPlaying) this.playbackStartTime = this.playbackContext?.currentTime ?? 0;
		if (this.isPlaying !== isPlaying) {
			this.isPlaying = isPlaying;
			this.onPlayingChange(isPlaying);
		}
	}
	schedulePlayback() {
		const ctx = this.playbackContext;
		if (ctx == null || this.playbackQueue.length === 0) return;
		while (this.playbackQueue.length > 0) {
			const samples = this.playbackQueue.shift();
			const buffer = ctx.createBuffer(1, samples.length, this.playbackSampleRate);
			buffer.getChannelData(0).set(samples);
			const source = ctx.createBufferSource();
			source.buffer = buffer;
			source.connect(ctx.destination);
			const startTime = Math.max(this.playbackTime, ctx.currentTime);
			source.start(startTime);
			this.playbackTime = startTime + buffer.duration;
			this.activeSources.add(source);
			this.setPlaying(ctx.state === "running");
			if (this.playbackContext !== ctx) return;
			source.onended = () => {
				source.disconnect();
				this.activeSources.delete(source);
				if (this.playbackQueue.length === 0 && this.activeSources.size === 0) this.setPlaying(false);
			};
		}
	}
};
//#endregion
//#region src/realtime/realtime-event-channel.ts
/** One codec queue per connection; retired connections cannot deliver late work. */
var RealtimeEventChannel = class {
	constructor(options) {
		this.options = options;
		this.active = true;
		this.finishing = false;
		this.incoming = Promise.resolve();
		this.outgoing = Promise.resolve();
		this.incomingCount = 0;
		this.incomingBytes = 0;
		this.outgoingCount = 0;
		this.parse = options.model.createServerEventParser?.() ?? options.model.parseServerEvent.bind(options.model);
	}
	get hasPendingIncoming() {
		return this.incomingCount > 0;
	}
	dispose() {
		this.active = false;
	}
	/** Stop accepting messages, but deliver already received terminal events. */
	async finish() {
		this.stopWriting();
		await this.incoming;
		this.dispose();
	}
	stopWriting() {
		this.finishing = true;
	}
	send(event, shouldSend) {
		if (!this.active || this.finishing) throw new Error("Realtime connection is closed");
		if (this.outgoingCount >= (this.options.maxPending ?? 512)) throw new Error("Realtime outgoing queue is full");
		this.outgoingCount++;
		const operation = this.outgoing.then(async () => {
			if (!this.active || this.finishing) throw new Error("Realtime connection is closed");
			if (shouldSend?.() === false) return;
			if (!this.active || this.finishing) throw new Error("Realtime connection is closed");
			const data = await this.options.model.serializeClientEvent(event);
			if (!this.active || this.finishing) throw new Error("Realtime connection is closed");
			if (shouldSend?.() === false) return;
			if (!this.active || this.finishing) throw new Error("Realtime connection is closed");
			if (data != null) this.options.send(data);
		});
		this.outgoing = operation.catch((error) => {
			if (!this.finishing) {
				if (event.type !== "input-audio-append" && event.type !== "session-close") this.report(error);
			}
		}).finally(() => {
			this.outgoingCount--;
		});
		return operation;
	}
	receive(data) {
		if (!this.active || this.finishing) return;
		const bytes = typeof data === "string" ? data.length * 2 : data instanceof Blob ? data.size : data.byteLength ?? 0;
		if (this.incomingCount >= (this.options.maxPending ?? 512) || this.incomingBytes + bytes > (this.options.maxPendingBytes ?? 8388608)) {
			this.finishing = true;
			this.fatal(/* @__PURE__ */ new Error("Realtime incoming queue is full; input protocol continuity was lost"));
			return;
		}
		this.incomingCount++;
		this.incomingBytes += bytes;
		this.incoming = this.incoming.then(async () => {
			if (!this.active) return;
			const text = typeof data === "string" ? data : data instanceof Blob ? await data.text() : new TextDecoder().decode(data);
			const parsed = await safeParseJSON({ text });
			if (!this.active) return;
			if (!parsed.success) throw new Error("Invalid JSON in realtime server message", { cause: parsed.error });
			const health = this.options.model.getHealthCheckResponse?.(parsed.value);
			if (!this.active) return;
			if (health != null && !this.finishing) this.options.send(health);
			if (!this.active) return;
			const result = this.parse(parsed.value);
			for (const event of Array.isArray(result) ? result : [result]) {
				if (!this.active) return;
				try {
					await this.options.onEvent(event);
				} catch (error) {
					this.report(error);
				}
			}
		}).catch((error) => {
			this.finishing = true;
			this.fatal(error instanceof Error ? error : new Error(String(error)));
		}).finally(() => {
			this.incomingCount--;
			this.incomingBytes -= bytes;
		});
	}
	fatal(error) {
		if (!this.active) return;
		if (this.options.onFatalError != null) this.options.onFatalError(error);
		else this.report(error);
	}
	report(error) {
		if (!this.active) return;
		try {
			this.options.onError(error instanceof Error ? error : new Error(String(error)));
		} catch {}
	}
};
//#endregion
//#region src/realtime/encode-realtime-frame.ts
/** Private Live continuous wire budgets; legacy transports do not enforce them. */
const REALTIME_MAX_FRAME_BYTES = 131072;
const REALTIME_MAX_BUFFERED_BYTES = 131072;
/** Serialize once, measuring the exact payload passed to the browser. */
function encodeRealtimeFrame(value) {
	if (value instanceof ArrayBuffer) return {
		data: value,
		byteLength: value.byteLength
	};
	if (ArrayBuffer.isView(value)) return {
		data: value,
		byteLength: value.byteLength
	};
	if (value instanceof Blob) return {
		data: value,
		byteLength: value.size
	};
	const data = typeof value === "string" ? value : JSON.stringify(value);
	if (data === void 0) throw new Error("Realtime event could not be encoded as JSON");
	return {
		data,
		byteLength: new TextEncoder().encode(data).byteLength
	};
}
function assertRealtimeFrameBudget(frame, bufferedAmount) {
	if (frame.byteLength > 131072) throw new Error(`Realtime frame exceeds the ${REALTIME_MAX_FRAME_BYTES}-byte limit; reduce the event payload`);
	if (bufferedAmount + frame.byteLength > 131072) throw new Error(`Realtime send buffer is full (${REALTIME_MAX_BUFFERED_BYTES}-byte limit); wait before retrying`);
}
//#endregion
//#region src/realtime/browser-realtime-transport.ts
function getCloseError(event) {
	if (event.code === 1e3 && event.wasClean) return void 0;
	return /* @__PURE__ */ new Error(`Realtime WebSocket closed unexpectedly (code ${event.code}${event.reason === "" ? "" : `: ${event.reason}`})`);
}
var BrowserRealtimeTransport = class {
	constructor(options) {
		this.options = options;
		this.ws = null;
		this.epoch = 0;
		this.failing = false;
		this.closing = false;
		this.model = options.model;
		this.continuous = options.model.capabilities?.conversation === "continuous";
		this.onServerEvent = options.onServerEvent;
		this.onError = options.onError;
		this.onClose = options.onClose;
	}
	get isOpen() {
		return !this.closing && !this.failing && this.ws?.readyState === WebSocket.OPEN;
	}
	connect({ mode, token, url, onOpen, protocols }) {
		this.disconnect();
		const epoch = this.epoch;
		if (mode !== "relay" && (mode !== "client-secret" || typeof token !== "string" || token.trim() === "")) throw new Error("Realtime client-secret connection requires a nonempty token");
		const wsConfig = mode === "relay" ? {
			url,
			protocols
		} : this.model.getWebSocketConfig?.({
			token,
			url
		});
		if (this.epoch !== epoch) return;
		if (wsConfig == null) throw new Error("Model does not support client-secret WebSockets");
		const finalUrl = wsConfig.url;
		const finalProtocols = wsConfig.protocols;
		if (this.epoch !== epoch) return;
		try {
			if (typeof finalUrl !== "string" || !/^wss?:\/\//i.test(finalUrl)) throw new Error("Invalid realtime WebSocket URL");
			const parsed = new URL(finalUrl);
			if (!["ws:", "wss:"].includes(parsed.protocol) || parsed.hostname === "" || finalUrl.includes("#")) throw new Error("Invalid realtime WebSocket URL");
		} catch {
			throw new Error("Invalid realtime WebSocket URL; expected an absolute ws:// or wss:// URL with a host and no fragment");
		}
		if (this.epoch !== epoch) return;
		const ws = new WebSocket(finalUrl, finalProtocols);
		this.ws = ws;
		let starting = false;
		let connectionError;
		const codec = new RealtimeEventChannel({
			model: this.model,
			send: (data) => {
				if (this.epoch !== epoch || this.ws !== ws || !this.isOpen) throw new Error("Realtime WebSocket is not open");
				this.sendRaw(data);
			},
			onEvent: this.onServerEvent,
			onError: (error) => {
				if (!starting) this.onError(error);
			},
			onFatalError: (error) => this.fail(error)
		});
		if (this.epoch !== epoch) {
			codec.dispose();
			return;
		}
		this.codec = codec;
		ws.onopen = () => {
			if (this.ws !== ws) return;
			starting = true;
			try {
				Promise.resolve(onOpen()).catch((error) => {
					if (this.ws === ws) this.fail(error instanceof Error ? error : new Error(String(error)));
				}).finally(() => {
					starting = false;
				});
			} catch (error) {
				if (this.epoch === epoch) this.fail(error instanceof Error ? error : new Error(String(error)));
			}
		};
		ws.onmessage = (messageEvent) => {
			if (this.ws === ws) this.codec?.receive(messageEvent.data);
		};
		ws.onerror = () => {
			if (this.ws === ws) {
				connectionError = /* @__PURE__ */ new Error("WebSocket connection error");
				this.failing = true;
			}
		};
		ws.onclose = (event) => {
			if (this.ws === ws) {
				this.ws = null;
				const closeError = getCloseError(event) ?? connectionError;
				const reportCloseErrorImmediately = closeError != null && !codec.hasPendingIncoming;
				codec.stopWriting();
				this.notifyClosing();
				if (this.epoch !== epoch) return;
				const drain = codec.finish();
				if (reportCloseErrorImmediately) {
					try {
						this.onError(closeError);
					} catch {}
					if (this.epoch !== epoch) return;
				}
				const complete = () => {
					if (this.epoch !== epoch) return;
					clearTimeout(this.drainTimer);
					this.epoch++;
					codec.dispose();
					try {
						this.onClose(closeError);
					} catch (error) {
						this.reportCallbackError(error);
					}
				};
				this.drainTimer = setTimeout(complete, 1e3);
				this.awaitDrain(drain, complete);
			}
		};
	}
	disconnect() {
		this.epoch++;
		clearTimeout(this.drainTimer);
		const ws = this.ws;
		this.ws = null;
		this.codec?.dispose();
		this.codec = void 0;
		this.failing = false;
		this.closing = false;
		ws?.close();
	}
	sendEvent(event, shouldSend, automaticAudio = false) {
		if (this.failing || this.closing) throw new Error("Realtime connection is closed");
		if (this.codec == null) return Promise.resolve();
		const epoch = this.epoch;
		const failed = (error) => {
			if (automaticAudio && this.epoch === epoch && this.isOpen) this.fail(error instanceof Error ? error : new Error(String(error)));
		};
		try {
			const sent = this.codec.send(event, shouldSend);
			sent.catch(failed);
			return sent;
		} catch (error) {
			failed(error);
			throw error;
		}
	}
	finish() {
		return this.codec?.finish() ?? Promise.resolve();
	}
	/** Drain accepted events when media or protocol continuity is lost. */
	fail(error) {
		if (this.failing) return;
		this.failing = true;
		const epoch = this.epoch;
		const ws = this.ws;
		this.ws = null;
		this.codec?.stopWriting();
		ws?.close();
		this.notifyClosing();
		if (this.epoch !== epoch) return;
		const drain = this.finish();
		if (this.options.onFatalError != null) this.options.onFatalError(error, drain);
		else {
			const complete = () => {
				if (epoch !== this.epoch) return;
				this.disconnect();
				try {
					this.onClose();
				} catch (cause) {
					this.reportCallbackError(cause);
				}
			};
			this.drainTimer = setTimeout(complete, 1e3);
			this.awaitDrain(drain, complete);
			this.reportCallbackError(error);
		}
	}
	notifyClosing() {
		if (this.closing) return;
		this.closing = true;
		try {
			this.options.onClosing?.();
		} catch (error) {
			this.reportCallbackError(error);
		}
	}
	async awaitDrain(drain, complete) {
		try {
			await drain;
		} catch {}
		try {
			complete();
		} catch (error) {
			this.reportCallbackError(error);
		}
	}
	reportCallbackError(error) {
		try {
			this.onError(error instanceof Error ? error : new Error(String(error)));
		} catch {}
	}
	sendRaw(data) {
		const ws = this.ws;
		const epoch = this.epoch;
		if (ws == null || !this.isOpen) return;
		const frame = encodeRealtimeFrame(data);
		if (this.epoch !== epoch || this.ws !== ws || !this.isOpen) throw new Error("Realtime connection is closed");
		if (this.continuous) assertRealtimeFrameBudget(frame, ws.bufferedAmount);
		ws.send(frame.data);
	}
	dispose() {
		this.disconnect();
	}
};
//#endregion
//#region src/realtime/browser-realtime-live-websocket.ts
/** Continuous PCM16 audio-chunk media for an application-owned WebSocket relay. */
var BrowserRealtimeLiveWebSocket = class {
	constructor(options) {
		this.options = options;
		this.generation = 0;
		this.ready = false;
		this.capturingStarted = false;
		this.pendingAudio = 0;
		this.captureGeneration = 0;
		this.captureEnabled = true;
		const input = options.sessionConfig?.inputAudioFormat;
		const output = options.sessionConfig?.outputAudioFormat;
		const sampleRate = input?.rate ?? output?.rate ?? options.sampleRate ?? 24e3;
		const format = {
			type: input?.type ?? output?.type ?? "audio/pcm",
			rate: sampleRate
		};
		this.config = {
			...options.sessionConfig,
			inputAudioFormat: {
				...format,
				...input
			},
			outputAudioFormat: {
				...format,
				...output
			}
		};
		this.transport = new BrowserRealtimeTransport({
			model: options.model,
			onServerEvent: options.onEvent,
			onError: options.onError,
			onFatalError: options.onFatalError,
			onClosing: () => {
				const generation = this.generation;
				options.onClosing?.();
				if (generation === this.generation) this.stopCapture();
			},
			onClose: options.onClose
		});
		this.audio = new BrowserRealtimeAudio({
			captureSampleRate: this.config.inputAudioFormat?.rate ?? sampleRate,
			playbackSampleRate: this.config.outputAudioFormat?.rate ?? sampleRate,
			maxPlaybackSeconds: options.maxPlaybackBufferSeconds ?? 2,
			onAudio: (audio) => this.sendAudio(audio),
			onError: options.onError,
			onCapturingChange: options.onCapturing,
			onPlayingChange: options.onPlaying
		});
	}
	connect(options) {
		const generation = this.generation + 1;
		this.dispose();
		if (generation !== this.generation) return;
		for (const format of [this.config.inputAudioFormat, this.config.outputAudioFormat]) {
			if (format?.type !== "audio/pcm") throw new UnsupportedFunctionalityError$1({ functionality: "Continuous browser WebSocket audio supports PCM16 only" });
			if (format.rate == null || !Number.isFinite(format.rate) || format.rate < 8e3 || format.rate > 96e3) throw new Error("Invalid realtime PCM sample rate");
		}
		this.stream = options.stream;
		this.captureEnabled = options.capture !== false;
		this.audio.ensurePlaybackContext();
		this.audio.resumePlayback().catch((error) => {
			if (generation === this.generation) this.options.onError(error);
		});
		this.transport.connect({
			mode: "relay",
			url: options.url,
			protocols: options.protocols,
			onOpen: () => {
				return this.transport.sendEvent({
					type: this.options.model.capabilities?.startup ?? "session-update",
					config: this.config
				});
			}
		});
	}
	startCapture() {
		this.ready = true;
		if (!this.captureEnabled || this.capturingStarted) return;
		this.resumeCapture().catch((error) => this.options.onError(error));
	}
	async resumeCapture(suppliedStream) {
		const generation = this.captureGeneration + 1;
		this.stopCapture();
		if (generation !== this.captureGeneration) return;
		this.ready = true;
		this.capturingStarted = true;
		this.captureEnabled = true;
		if (suppliedStream != null) this.stream = suppliedStream;
		const supplied = this.stream;
		const stream = supplied ?? await navigator.mediaDevices.getUserMedia({ audio: true });
		if (generation !== this.captureGeneration || !this.ready) {
			if (supplied == null) stream.getTracks().forEach((track) => track.stop());
			return;
		}
		if (!stream.getAudioTracks().some((track) => track.readyState === "live")) {
			if (supplied == null) stream.getTracks().forEach((track) => track.stop());
			throw new Error("Realtime requires a live audio track");
		}
		this.audio.startCapture(stream, { ownsStream: supplied == null });
	}
	sendAudio(audio) {
		if (!this.ready || !this.transport.isOpen) return;
		if (this.pendingAudio >= 8) {
			this.transport.fail(/* @__PURE__ */ new Error("Realtime audio send queue is full"));
			return;
		}
		const generation = this.generation;
		let sent;
		try {
			sent = this.transport.sendEvent({
				type: "input-audio-append",
				audio
			}, void 0, true);
		} catch (error) {
			if (!this.ready || !this.transport.isOpen) return;
			throw error;
		}
		this.pendingAudio++;
		sent.then(() => {
			if (generation === this.generation) this.pendingAudio--;
		}, (error) => {
			if (generation === this.generation && this.ready && this.transport.isOpen) this.options.onFatalError(error);
		});
	}
	sendEvent(event, shouldSend) {
		if (event.type === "session-update") for (const key of ["inputAudioFormat", "outputAudioFormat"]) {
			const update = event.config[key];
			if (update != null && (update.type !== this.config[key]?.type || update.rate != null && update.rate !== this.config[key]?.rate)) throw new Error("Changing Live WebSocket audio format requires reconnecting");
		}
		return this.transport.sendEvent(event, shouldSend);
	}
	playAudio(audio) {
		try {
			this.audio.playAudio(audio);
		} catch (error) {
			this.options.onError(error instanceof Error ? error : new Error(String(error)));
		}
	}
	stopPlayback() {
		this.audio.stopPlayback();
	}
	resumePlayback() {
		return this.audio.resumePlayback();
	}
	stopCapture() {
		this.captureGeneration++;
		this.ready = false;
		this.capturingStarted = false;
		this.captureEnabled = false;
		this.audio.stopCapture();
	}
	finish() {
		return this.transport.finish();
	}
	dispose() {
		this.generation++;
		this.stopCapture();
		this.ready = false;
		this.capturingStarted = false;
		this.pendingAudio = 0;
		this.stream = void 0;
		this.transport.disconnect();
		this.audio.dispose();
	}
};
//#endregion
//#region src/realtime/browser-realtime-webrtc.ts
const MAX_SESSION_ANSWER_BYTES = 1048576;
async function readSessionAnswer(response) {
	const reader = response.body?.getReader();
	if (reader == null) throw new Error("Invalid realtime session answer");
	const decoder = new TextDecoder();
	let bytes = 0;
	let text = "";
	try {
		if (Number(response.headers.get("content-length")) > MAX_SESSION_ANSWER_BYTES) throw new Error("Realtime session answer exceeds the 1 MiB limit");
		while (true) {
			const { done, value } = await reader.read();
			if (done) return text + decoder.decode();
			bytes += value.byteLength;
			if (bytes > MAX_SESSION_ANSWER_BYTES) throw new Error("Realtime session answer exceeds the 1 MiB limit");
			text += decoder.decode(value, { stream: true });
		}
	} catch (error) {
		reader.cancel(error).catch(() => {});
		throw error;
	} finally {
		reader.releaseLock();
	}
}
function selectAudioTrack(stream) {
	const live = stream.getAudioTracks().filter((track) => track.readyState === "live");
	return live.find((track) => track.enabled && !track.muted) ?? live[0];
}
var BrowserRealtimeWebRTC = class {
	constructor(options) {
		this.options = options;
		this.ownsStream = false;
		this.generation = 0;
		this.closingNotified = false;
		this.captureGeneration = 0;
		this.senderOperations = Promise.resolve();
		this.trackCleanups = [];
	}
	async connect({ api, sessionConfig, stream, timeoutMs, capture = true }) {
		const generation = this.generation + 1;
		this.dispose();
		const current = () => generation === this.generation;
		if (!current()) return;
		const config = this.options.model.getWebRTCConfig?.();
		if (!current()) return;
		if (config == null) throw new Error("This model does not support WebRTC configuration");
		const abort = new AbortController();
		this.abort = abort;
		const timeout = setTimeout(() => abort.abort(/* @__PURE__ */ new Error("Realtime startup timed out")), timeoutMs);
		const cancelled = new Promise((_, reject) => {
			abort.signal.addEventListener("abort", () => reject(abort.signal.reason), { once: true });
		});
		const start = async () => {
			const captureGeneration = this.captureGeneration;
			let media = capture ? stream ?? await navigator.mediaDevices.getUserMedia({ audio: true }) : void 0;
			if (!current() || abort.signal.aborted) {
				if (stream == null) media?.getTracks().forEach((track) => track.stop());
				throw new Error("Realtime connection cancelled");
			}
			if (captureGeneration !== this.captureGeneration) {
				if (stream == null) media?.getTracks().forEach((track) => track.stop());
				media = void 0;
			}
			this.stream = media;
			this.ownsStream = stream == null;
			const track = media == null ? void 0 : selectAudioTrack(media);
			if (media != null && track == null) throw new Error("Realtime requires a live audio track");
			const pc = new RTCPeerConnection();
			this.pc = pc;
			const audio = document.createElement("audio");
			audio.autoplay = true;
			this.audio = audio;
			audio.onplaying = () => {
				if (current()) this.options.onPlaying(true);
			};
			const stopped = () => {
				if (current()) this.options.onPlaying(false);
			};
			audio.onpause = stopped;
			audio.onended = stopped;
			audio.onwaiting = stopped;
			pc.ontrack = (event) => {
				if (!current()) return;
				audio.srcObject = event.streams[0] ?? new MediaStream([event.track]);
				audio.play().catch((error) => {
					if (current()) this.options.onError(error);
				});
			};
			pc.onconnectionstatechange = () => {
				if (!current()) return;
				if (pc.connectionState === "connected") clearTimeout(this.disconnectTimer);
				else if (pc.connectionState === "disconnected") {
					clearTimeout(this.disconnectTimer);
					this.disconnectTimer = setTimeout(() => {
						if (current() && pc.connectionState === "disconnected") this.fail(/* @__PURE__ */ new Error("Realtime peer disconnected beyond recovery grace period"));
					}, this.options.disconnectTimeoutMs ?? 5e3);
				} else if (pc.connectionState === "closed") this.drainClose(/* @__PURE__ */ new Error("Realtime peer connection closed"));
				else if (pc.connectionState === "failed") this.fail(/* @__PURE__ */ new Error(`Realtime peer connection ${pc.connectionState}`));
			};
			pc.oniceconnectionstatechange = () => {
				if (current() && pc.iceConnectionState === "failed") this.fail(/* @__PURE__ */ new Error("Realtime ICE connection failed"));
			};
			const dc = pc.createDataChannel(config.dataChannelLabel);
			this.dc = dc;
			const codec = new RealtimeEventChannel({
				model: this.options.model,
				onEvent: this.options.onEvent,
				onError: this.options.onError,
				onFatalError: (error) => {
					if (current()) this.fail(error);
				},
				send: (data) => {
					if (!current() || this.finishing || dc.readyState !== "open") throw new Error("Realtime data channel is not open");
					if (dc.bufferedAmount > 1048576) throw new Error("Realtime data channel buffer is full");
					const encoded = typeof data === "string" ? data : JSON.stringify(data);
					if (!current() || this.finishing || dc.readyState !== "open") throw new Error("Realtime data channel is not open");
					dc.send(encoded);
				}
			});
			if (!current()) {
				codec.dispose();
				return;
			}
			this.codec = codec;
			dc.onmessage = (event) => {
				if (current()) this.codec?.receive(event.data);
			};
			dc.onclose = () => {
				if (current()) this.drainClose(/* @__PURE__ */ new Error("Realtime data channel closed"));
			};
			dc.onerror = () => {
				if (current()) this.fail(/* @__PURE__ */ new Error("Realtime data channel error"));
			};
			const opened = new Promise((resolve, reject) => {
				this.rejectStartup = reject;
				dc.onopen = () => {
					this.rejectStartup = void 0;
					resolve();
				};
			});
			opened.catch(() => {});
			const gathered = new Promise((resolve) => {
				pc.onicegatheringstatechange = () => {
					if (pc.iceGatheringState === "complete") resolve();
				};
			});
			this.sender = media != null && track != null ? pc.addTrack(track, media) : pc.addTransceiver("audio", { direction: "sendrecv" }).sender;
			this.observeCapture();
			if (!current() || abort.signal.aborted) return;
			const offer = await pc.createOffer();
			if (!current() || abort.signal.aborted) return;
			await pc.setLocalDescription(offer);
			if (pc.iceGatheringState !== "complete") await Promise.race([gathered, cancelled]);
			if (!current() || abort.signal.aborted) return;
			const sdp = pc.localDescription?.sdp;
			if (sdp == null) throw new Error("Realtime offer has no SDP");
			const response = await fetch(api, {
				method: "POST",
				headers: { "Content-Type": "application/json" },
				body: JSON.stringify({
					sdp,
					sessionConfig
				}),
				signal: abort.signal
			});
			if (!response.ok) throw new Error(`Failed to create realtime session: ${response.status}`);
			const parsed = await safeParseJSON({ text: await readSessionAnswer(response) });
			if (!current() || abort.signal.aborted) return;
			if (!parsed.success || typeof parsed.value !== "object" || parsed.value == null || !("sdp" in parsed.value) || typeof parsed.value.sdp !== "string" || parsed.value.sdp.trim().length === 0 || !("sessionId" in parsed.value) || typeof parsed.value.sessionId !== "string" || parsed.value.sessionId.trim().length === 0) throw new Error("Invalid realtime session answer");
			await pc.setRemoteDescription({
				type: "answer",
				sdp: parsed.value.sdp
			});
			await Promise.race([opened, cancelled]);
		};
		try {
			await Promise.race([start(), cancelled]);
		} catch (error) {
			if (current()) this.dispose();
			throw error;
		} finally {
			clearTimeout(timeout);
			this.rejectStartup = void 0;
		}
	}
	sendEvent(event, shouldSend) {
		if (this.finishing || this.dc?.readyState !== "open") throw new Error("Realtime data channel is not open");
		return this.codec?.send(event, shouldSend) ?? Promise.resolve();
	}
	async resumePlayback() {
		if (this.audio == null) throw new Error("Realtime playback is not connected");
		await this.audio.play();
	}
	stopPlayback() {
		this.audio?.pause();
	}
	finish() {
		return this.codec?.finish() ?? Promise.resolve();
	}
	fail(error) {
		if (this.finishing === "failure") return;
		this.finishing = "failure";
		clearTimeout(this.finishTimer);
		if (this.rejectStartup != null) {
			this.rejectStartup(error);
			this.abort?.abort(error);
			return;
		}
		const generation = this.generation;
		const drain = this.finish();
		this.notifyClosing();
		if (generation !== this.generation) return;
		this.stopCaptureForShutdown(generation);
		if (generation !== this.generation) return;
		if (this.options.onFatalError != null) {
			this.options.onFatalError(error, drain);
			return;
		}
		const complete = () => {
			if (generation !== this.generation) return;
			this.dispose();
			try {
				this.options.onClose();
			} catch (cause) {
				this.reportCallbackError(cause);
			}
		};
		this.finishTimer = setTimeout(complete, 1e3);
		this.awaitDrain(drain, complete);
		try {
			this.options.onError(error);
		} catch {}
	}
	drainClose(error) {
		if (this.finishing) return;
		if (this.rejectStartup != null) {
			this.fail(error);
			return;
		}
		this.finishing = "close";
		const generation = this.generation;
		const complete = () => {
			if (generation !== this.generation || this.finishing !== "close") return;
			clearTimeout(this.finishTimer);
			try {
				this.options.onClose(error);
			} catch (cause) {
				this.reportCallbackError(cause);
			} finally {
				if (generation === this.generation) this.dispose();
			}
		};
		this.finishTimer = setTimeout(complete, 1e3);
		this.awaitDrain(this.finish(), complete);
		this.notifyClosing();
		if (generation !== this.generation) return;
		this.stopCaptureForShutdown(generation);
	}
	notifyClosing() {
		if (this.closingNotified) return;
		this.closingNotified = true;
		try {
			this.options.onClosing?.();
		} catch (error) {
			this.reportCallbackError(error);
		}
	}
	async stopCaptureForShutdown(generation) {
		try {
			await this.stopCapture();
		} catch (cause) {
			if (generation !== this.generation || this.finishing !== "close") return;
			try {
				this.fail(cause instanceof Error ? cause : new Error(String(cause)));
			} catch (error) {
				this.reportCallbackError(error);
			}
		}
	}
	async awaitDrain(drain, complete) {
		try {
			await drain;
		} catch {}
		try {
			complete();
		} catch (error) {
			this.reportCallbackError(error);
		}
	}
	reportCallbackError(error) {
		try {
			this.options.onError(error instanceof Error ? error : new Error(String(error)));
		} catch {}
	}
	async stopCapture() {
		const generation = ++this.captureGeneration;
		for (const cleanup of this.trackCleanups) cleanup();
		this.trackCleanups = [];
		if (this.ownsStream) this.stream?.getTracks().forEach((track) => track.stop());
		this.stream = void 0;
		const pc = this.pc;
		const sender = this.sender;
		await this.queueSenderOperation(async () => {
			if (pc !== this.pc || sender !== this.sender) return;
			if (pc != null && sender != null) await this.detachSender(pc, sender);
			if (generation === this.captureGeneration && pc === this.pc) this.options.onCapturing(false);
		});
	}
	async startCapture(supplied) {
		const generation = this.captureGeneration + 1;
		await this.stopCapture();
		if (generation !== this.captureGeneration || this.pc == null || this.finishing) return;
		const media = supplied ?? await navigator.mediaDevices.getUserMedia({ audio: true });
		if (generation !== this.captureGeneration || this.pc == null || this.finishing) {
			if (supplied == null) media.getTracks().forEach((track) => track.stop());
			return;
		}
		const track = selectAudioTrack(media);
		if (track == null) {
			if (supplied == null) media.getTracks().forEach((track) => track.stop());
			throw new Error("Realtime requires a live audio track");
		}
		const pc = this.pc;
		const sender = this.sender;
		await this.queueSenderOperation(async () => {
			const current = () => generation === this.captureGeneration && pc === this.pc && sender === this.sender && pc.connectionState !== "closed" && !this.finishing;
			let attached = false;
			try {
				if (!current() || sender == null) return;
				await sender.replaceTrack(track);
				if (!current()) {
					if (pc === this.pc) await this.detachSender(pc, sender);
					return;
				}
				this.stream = media;
				this.ownsStream = supplied == null;
				attached = true;
				this.observeCapture();
			} finally {
				if (!attached && supplied == null) media.getTracks().forEach((track) => track.stop());
			}
		});
	}
	queueSenderOperation(operation) {
		const pending = this.senderOperations.then(operation);
		this.senderOperations = pending.catch(() => {});
		return pending;
	}
	async detachSender(pc, sender) {
		if (pc.connectionState === "closed") return;
		try {
			await sender.replaceTrack(null);
		} catch (error) {
			if (pc !== this.pc) return;
			this.closePeer(pc);
			this.fail(error instanceof Error ? error : new Error(String(error)));
		}
	}
	closePeer(pc) {
		pc.ontrack = null;
		pc.onconnectionstatechange = null;
		pc.oniceconnectionstatechange = null;
		pc.onicegatheringstatechange = null;
		if (pc.connectionState !== "closed") pc.close();
	}
	observeCapture() {
		const generation = this.captureGeneration;
		const sender = this.sender;
		const track = sender?.track;
		const update = () => {
			if (generation === this.captureGeneration && this.sender === sender) this.options.onCapturing(sender?.track != null && sender.track.readyState === "live" && sender.track.enabled && !sender.track.muted);
		};
		if (track != null) for (const event of [
			"ended",
			"mute",
			"unmute"
		]) {
			track.addEventListener(event, update);
			this.trackCleanups.push(() => track.removeEventListener(event, update));
		}
		update();
	}
	dispose() {
		this.generation++;
		this.captureGeneration++;
		clearTimeout(this.finishTimer);
		clearTimeout(this.disconnectTimer);
		this.finishing = void 0;
		this.closingNotified = false;
		this.senderOperations = Promise.resolve();
		this.abort?.abort(/* @__PURE__ */ new Error("Realtime connection cancelled"));
		this.abort = void 0;
		this.codec?.dispose();
		this.codec = void 0;
		if (this.dc != null) {
			this.dc.onopen = null;
			this.dc.onclose = null;
			this.dc.onerror = null;
			this.dc.onmessage = null;
			this.dc.close();
			this.dc = void 0;
		}
		if (this.pc != null) {
			this.closePeer(this.pc);
			this.pc = void 0;
		}
		for (const cleanup of this.trackCleanups) cleanup();
		this.trackCleanups = [];
		if (this.ownsStream) this.stream?.getTracks().forEach((track) => track.stop());
		this.stream = void 0;
		this.sender = void 0;
		if (this.audio != null) {
			this.audio.onplaying = null;
			this.audio.onpause = null;
			this.audio.onended = null;
			this.audio.onwaiting = null;
			this.audio.pause();
			this.audio.srcObject = null;
			this.audio = void 0;
		}
		this.options.onCapturing(false);
		this.options.onPlaying(false);
	}
};
//#endregion
//#region src/realtime/realtime-attempt.ts
/** Cancellation and settlement belong to one connection attempt. */
var RealtimeAttempt = class {
	constructor() {
		this.abort = new AbortController();
		this.reportedTransportErrors = /* @__PURE__ */ new WeakSet();
		this.timers = /* @__PURE__ */ new Map();
		this.active = true;
		this.ready = false;
		this.closing = false;
		this.transportClosing = false;
	}
	timer(name, duration, callback) {
		this.clearTimer(name);
		this.timers.set(name, setTimeout(() => {
			this.timers.delete(name);
			if (this.active) callback();
		}, duration));
	}
	clearTimer(name) {
		clearTimeout(this.timers.get(name));
		this.timers.delete(name);
	}
	beginClose() {
		this.closing = true;
		return this.closePromise ??= new Promise((resolve) => {
			this.settleClose = resolve;
		});
	}
	retire() {
		if (!this.active) return;
		this.active = false;
		this.abort.abort();
		for (const timer of this.timers.values()) clearTimeout(timer);
		this.timers.clear();
		this.settleClose?.();
		this.settleClose = void 0;
	}
};
//#endregion
//#region src/realtime/realtime-command-tracker.ts
/** Attempt-local ACK correlation; unresolved commands are never evicted. */
var RealtimeCommandTracker = class {
	constructor(sendCommand) {
		this.sendCommand = sendCommand;
		this.pending = /* @__PURE__ */ new Map();
		this.recent = /* @__PURE__ */ new Set();
	}
	validateId(id) {
		if (this.pending.has(id) || this.recent.has(id)) throw new Error("Realtime command ID was already used; retry with a fresh eventId");
		if (this.pending.size >= 512) throw new Error("Too many pending realtime commands");
	}
	complete(id) {
		const command = this.pending.get(id);
		if (command == null) return;
		this.pending.delete(id);
		this.recent.add(id);
		if (this.recent.size > 4096) {
			const oldest = this.recent.values().next().value;
			if (oldest != null) this.recent.delete(oldest);
		}
		return command;
	}
	send(event) {
		const muted = event.type === "input-audio-mute" ? true : event.type === "input-audio-unmute" ? false : void 0;
		if (event.type === "input-audio-mute" || event.type === "input-audio-unmute") event = {
			...event,
			eventId: event.eventId ?? generateId$1()
		};
		const id = "eventId" in event ? event.eventId : void 0;
		if (id != null) {
			this.validateId(id);
			this.pending.set(id, { muted });
		}
		const awaitsAcknowledgement = event.type === "context-append" || event.type === "session-update" || muted != null;
		try {
			const sent = this.sendCommand(event);
			sent.then(() => {
				if (id != null && !awaitsAcknowledgement) this.complete(id);
			}, () => {
				if (id != null) this.complete(id);
			});
			return sent;
		} catch (error) {
			if (id != null) this.complete(id);
			throw error;
		}
	}
	receive(event) {
		if (event.type === "command-acknowledged" && event.clientEventId != null) return this.complete(event.clientEventId);
		if (event.type === "error" && event.clientEventId != null) this.complete(event.clientEventId);
	}
};
//#endregion
//#region src/realtime/validate-realtime-setup.ts
const setupSchema = z$1.object({
	token: z$1.string().check(z$1.refine((value) => value.trim().length > 0)),
	url: z$1.string().check(z$1.refine((value) => {
		try {
			const url = new URL(value);
			return (url.protocol === "ws:" || url.protocol === "wss:") && url.hostname !== "";
		} catch {
			return false;
		}
	})),
	expiresAt: z$1.optional(z$1.number().check(z$1.positive()).check(z$1.maximum(Number.MAX_SAFE_INTEGER))),
	tools: z$1.optional(z$1.array(z$1.object({
		type: z$1.literal("function"),
		name: z$1.string().check(z$1.minLength(1)),
		description: z$1.optional(z$1.string()),
		parameters: z$1.record(z$1.string(), z$1.unknown())
	})))
});
function validateRealtimeSetup(payload) {
	const result = setupSchema.safeParse(payload);
	if (!result.success) throw new Error("Invalid realtime setup: expected a nonempty token, a ws(s) URL, and valid optional expiresAt/tools");
	return result.data;
}
//#endregion
//#region src/realtime/realtime-session-state.ts
function createSessionState() {
	return {
		transcripts: [],
		delegations: [],
		isInputMuted: false,
		finalization: "pending"
	};
}
function reduceSessionState(state, event, limit, muted) {
	switch (event.type) {
		case "session-started": return {
			...state,
			sessionId: event.sessionId,
			delegationMode: event.delegationMode
		};
		case "session-usage": return {
			...state,
			usage: event.usage
		};
		case "session-closed": return {
			...state,
			sessionId: event.sessionId ?? state.sessionId,
			usage: event.usage,
			terminationReason: event.reason,
			finalization: "confirmed"
		};
		case "transcript-fragment": return {
			...state,
			transcripts: [...state.transcripts, event].slice(-limit)
		};
		case "delegation-created": return state.delegations.some((item) => item.delegationId === event.delegationId) ? state : {
			...state,
			delegations: [...state.delegations, event].slice(-limit)
		};
		case "command-acknowledged": return muted == null ? state : {
			...state,
			isInputMuted: muted
		};
		default: return state;
	}
}
//#endregion
//#region src/realtime/realtime-event-reducer.ts
function createInitialRealtimeState() {
	return {
		status: "disconnected",
		messages: [],
		events: [],
		isCapturing: false,
		isPlaying: false
	};
}
var RealtimeEventReducer = class {
	constructor(maxEvents = 500) {
		this.maxEvents = maxEvents;
		this.currentAssistantMessageId = null;
		this.textAccumulators = /* @__PURE__ */ new Map();
		this.toolArgAccumulators = /* @__PURE__ */ new Map();
		this.toolCallIdToMessageId = /* @__PURE__ */ new Map();
		this.toolCallIdToName = /* @__PURE__ */ new Map();
		this.inputAudioMessageInsertIndex = /* @__PURE__ */ new Map();
		this.itemIdToPartLocation = /* @__PURE__ */ new Map();
	}
	setStatus(state, status) {
		return {
			...state,
			status
		};
	}
	setCapturing(state, isCapturing) {
		return {
			...state,
			isCapturing
		};
	}
	setPlaying(state, isPlaying) {
		return {
			...state,
			isPlaying
		};
	}
	addUserTextMessage(state, text) {
		return {
			...state,
			messages: [...state.messages, {
				id: `user-${Date.now()}`,
				role: "user",
				parts: [{
					type: "text",
					text,
					state: "done"
				}]
			}]
		};
	}
	addToolOutput(state, callId, result) {
		return {
			state: this.updateToolPartState(state, callId, result),
			output: {
				callId,
				name: this.toolCallIdToName.get(callId),
				output: JSON.stringify(result)
			}
		};
	}
	async reduceServerEvent(state, event) {
		let nextState = this.pushEvent(state, event);
		const effects = [];
		switch (event.type) {
			case "session-created":
			case "session-updated":
				if (nextState.status === "connecting") nextState = this.setStatus(nextState, "connected");
				break;
			case "audio-delta":
				effects.push({
					type: "play-audio",
					itemId: event.itemId,
					delta: event.delta
				});
				break;
			case "audio-committed":
				if (event.itemId != null) this.inputAudioMessageInsertIndex.set(event.itemId, nextState.messages.length);
				break;
			case "audio-transcript-delta":
			case "text-delta":
				nextState = this.appendTextDelta(nextState, event.itemId, event.delta);
				break;
			case "audio-transcript-done":
				nextState = this.finalizeText(nextState, event.itemId, event.transcript);
				break;
			case "text-done":
				nextState = this.finalizeText(nextState, event.itemId, event.text);
				break;
			case "input-transcription-completed":
				nextState = this.addInputTranscriptionMessage(nextState, event.itemId, event.transcript);
				break;
			case "response-created":
			case "response-done":
				this.currentAssistantMessageId = null;
				break;
			case "speech-started":
				this.currentAssistantMessageId = null;
				effects.push({ type: "speech-started" });
				break;
			case "function-call-arguments-delta": {
				const { state: updatedState, messageId } = this.getOrCreateAssistantMessage(nextState);
				nextState = updatedState;
				this.toolCallIdToMessageId.set(event.callId, messageId);
				const acc = this.toolArgAccumulators.get(event.callId) ?? "";
				this.toolArgAccumulators.set(event.callId, acc + event.delta);
				nextState = this.ensureToolPart(nextState, messageId, event.callId);
				break;
			}
			case "function-call-arguments-done": {
				this.toolArgAccumulators.delete(event.callId);
				this.toolCallIdToName.set(event.callId, event.name);
				const parseResult = await safeParseJSON({ text: event.arguments });
				const parsedInput = parseResult.success ? parseResult.value : {};
				const messageId = this.toolCallIdToMessageId.get(event.callId);
				if (messageId != null) nextState = this.markToolInputAvailable(nextState, messageId, event.callId, event.name, parsedInput);
				if (!parseResult.success) effects.push({
					type: "error",
					error: /* @__PURE__ */ new Error(`Failed to parse tool arguments: ${event.arguments}`)
				});
				else effects.push({
					type: "tool-call",
					callId: event.callId,
					name: event.name,
					args: parsedInput,
					rawArguments: event.arguments
				});
				break;
			}
			case "error": effects.push({
				type: "error",
				error: new Error(event.message)
			});
		}
		return {
			state: nextState,
			effects
		};
	}
	pushEvent(state, event) {
		const events = [...state.events, event];
		return {
			...state,
			events: events.length > this.maxEvents ? events.slice(-this.maxEvents) : events
		};
	}
	getOrCreateAssistantMessage(state) {
		if (this.currentAssistantMessageId != null) return {
			state,
			messageId: this.currentAssistantMessageId
		};
		const messageId = `assistant-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
		this.currentAssistantMessageId = messageId;
		return {
			state: {
				...state,
				messages: [...state.messages, {
					id: messageId,
					role: "assistant",
					parts: []
				}]
			},
			messageId
		};
	}
	addInputTranscriptionMessage(state, itemId, transcript) {
		const messageId = `user-${itemId}`;
		if (state.messages.find((message) => message.id === messageId) != null) return {
			...state,
			messages: state.messages.map((message) => message.id === messageId ? {
				...message,
				parts: [{
					type: "text",
					text: transcript,
					state: "done"
				}]
			} : message)
		};
		const insertIndex = Math.min(this.inputAudioMessageInsertIndex.get(itemId) ?? state.messages.length, state.messages.length);
		const messages = [...state.messages];
		messages.splice(insertIndex, 0, {
			id: messageId,
			role: "user",
			parts: [{
				type: "text",
				text: transcript,
				state: "done"
			}]
		});
		return {
			...state,
			messages
		};
	}
	appendTextDelta(state, itemId, delta) {
		const { state: stateWithMessage, messageId } = this.getOrCreateAssistantMessage(state);
		const text = (this.textAccumulators.get(itemId) ?? "") + delta;
		this.textAccumulators.set(itemId, text);
		const location = this.itemIdToPartLocation.get(itemId);
		if (location != null) return this.updateMessagePart(stateWithMessage, location.messageId, location.partIndex, {
			type: "text",
			text,
			state: "streaming"
		});
		return {
			...stateWithMessage,
			messages: stateWithMessage.messages.map((message) => {
				if (message.id !== messageId) return message;
				const partIndex = message.parts.length;
				this.itemIdToPartLocation.set(itemId, {
					messageId,
					partIndex
				});
				return {
					...message,
					parts: [...message.parts, {
						type: "text",
						text,
						state: "streaming"
					}]
				};
			})
		};
	}
	finalizeText(state, itemId, finalText) {
		const text = finalText ?? this.textAccumulators.get(itemId) ?? "";
		this.textAccumulators.delete(itemId);
		const location = this.itemIdToPartLocation.get(itemId);
		if (location == null) return state;
		this.itemIdToPartLocation.delete(itemId);
		return this.updateMessagePart(state, location.messageId, location.partIndex, {
			type: "text",
			text,
			state: "done"
		});
	}
	ensureToolPart(state, messageId, callId) {
		return {
			...state,
			messages: state.messages.map((message) => {
				if (message.id !== messageId) return message;
				if (message.parts.find((part) => part.type === "dynamic-tool" && part.toolCallId === callId) != null) return message;
				return {
					...message,
					parts: [...message.parts, {
						type: "dynamic-tool",
						toolName: "",
						toolCallId: callId,
						state: "input-streaming",
						input: void 0
					}]
				};
			})
		};
	}
	markToolInputAvailable(state, messageId, callId, name, input) {
		return {
			...state,
			messages: state.messages.map((message) => {
				if (message.id !== messageId) return message;
				return {
					...message,
					parts: message.parts.map((part) => {
						if (part.type !== "dynamic-tool") return part;
						const toolPart = part;
						if (toolPart.toolCallId !== callId) return part;
						return {
							...toolPart,
							toolName: name,
							state: "input-available",
							input
						};
					})
				};
			})
		};
	}
	updateToolPartState(state, callId, result) {
		const messageId = this.toolCallIdToMessageId.get(callId);
		if (messageId == null) return state;
		return {
			...state,
			messages: state.messages.map((message) => {
				if (message.id !== messageId) return message;
				return {
					...message,
					parts: message.parts.map((part) => {
						if (part.type !== "dynamic-tool") return part;
						const toolPart = part;
						if (toolPart.toolCallId !== callId) return part;
						return {
							...toolPart,
							state: "output-available",
							output: result
						};
					})
				};
			})
		};
	}
	updateMessagePart(state, messageId, partIndex, part) {
		return {
			...state,
			messages: state.messages.map((message) => {
				if (message.id !== messageId) return message;
				const parts = [...message.parts];
				parts[partIndex] = part;
				return {
					...message,
					parts
				};
			})
		};
	}
};
//#endregion
//#region src/realtime/realtime-session.ts
var AbstractRealtimeSession = class {
	constructor(options) {
		this.options = options;
		this.state = createInitialRealtimeState();
		this.publication = 0;
		this.captureGeneration = 0;
		this.captureRequested = false;
		this.currentResponseItemId = null;
		this.toolCallsInResponse = /* @__PURE__ */ new Set();
		this.submittedToolOutputs = /* @__PURE__ */ new Set();
		this.responseToolCallsClosed = false;
		const capabilities = options.model.capabilities;
		this.sessionLifecycle = capabilities?.startup === "session-start" || capabilities?.finalization === "session-close";
		this.continuous = capabilities?.conversation === "continuous";
		this.maxEvents = options.maxEvents ?? 500;
		if (!Number.isSafeInteger(this.maxEvents) || this.maxEvents < 1) throw new Error("maxEvents must be a positive integer");
		for (const timeout of [
			options.startupTimeoutMs ?? 3e4,
			options.closeTimeoutMs ?? 15e3,
			options.rtcDisconnectTimeoutMs ?? 5e3
		]) if (!Number.isFinite(timeout) || timeout <= 0 || timeout > 2147483647) throw new Error("Realtime timeouts must be positive finite timer durations");
		const budget = options.maxPlaybackBufferSeconds ?? 2;
		if (!Number.isFinite(budget) || budget <= 0) throw new Error("maxPlaybackBufferSeconds must be positive and finite");
		this.reducer = new RealtimeEventReducer(this.maxEvents);
		this.onToolCall = options.onToolCall;
		this.onEvent = options.onEvent;
		this.onError = options.onError;
	}
	validateConnection() {
		const { model, api } = this.options;
		if ((!this.continuous || api.session != null || api.provider != null) && this.options.maxPlaybackBufferSeconds != null) throw new Error("maxPlaybackBufferSeconds is supported only for continuous PCM sessions");
		const connection = api.provider != null ? "provider" : api.session != null ? "webrtc" : api.token != null ? "client-secret-websocket" : "server-websocket";
		if (!(model.capabilities?.connections ?? ["client-secret-websocket"]).includes(connection) || api.provider == null && model.capabilities?.transports != null && !model.capabilities.transports.includes(api.session != null ? "webrtc" : "websocket")) throw new Error(`Realtime model does not support ${connection}`);
		if (api.provider != null) {
			if (model.createTransport == null) throw new Error("Realtime model does not support a provider transport");
			return;
		}
		if (api.session != null) {
			if (model.getWebRTCConfig == null) throw new Error("Realtime model does not support WebRTC configuration");
			return;
		}
		if (this.continuous && api.websocket == null) throw new Error("Continuous PCM sessions require an application WebSocket relay");
		if (api.token != null && model.getWebSocketConfig == null) throw new Error("Realtime model does not support client-secret WebSocket configuration");
	}
	async connect(connectOptions) {
		if (this.attempt?.active) throw new Error("Realtime session is already active");
		const attempt = new RealtimeAttempt();
		this.attempt = attempt;
		const current = () => this.attempt === attempt && attempt.active;
		try {
			this.applyState({
				...this.state,
				status: "connecting"
			});
			if (!current()) return;
			this.validateConnection();
			const { model, api, sessionConfig } = this.options;
			if (connectOptions?.capture === false) this.stopAudioCapture();
			if (!current()) return;
			if (connectOptions?.stream != null && connectOptions.stream !== this.suppliedStream) {
				if (this.captureRequested && !this.sessionLifecycle && !this.continuous && api.session == null && api.provider == null) this.startAudioCapture(connectOptions.stream);
				else this.suppliedStream = connectOptions.stream;
			}
			if (!current()) return;
			this.reducer = new RealtimeEventReducer(this.maxEvents);
			this.currentResponseItemId = null;
			this.toolCallsInResponse.clear();
			this.submittedToolOutputs.clear();
			this.responseToolCallsClosed = false;
			if (this.sessionLifecycle) this.applyState({
				...this.state,
				session: createSessionState()
			});
			if (!current()) return;
			this.commands = new RealtimeCommandTracker((event) => {
				const writable = () => current() && !attempt.transportClosing && attempt.cause == null && (!attempt.closing || event.type === "session-close");
				if (!writable()) throw new Error("Realtime connection is closed");
				return this.sendTransport(event, writable);
			});
			attempt.timer("startup", this.options.startupTimeoutMs ?? 3e4, () => {
				if (current()) this.fail(/* @__PURE__ */ new Error("Realtime session startup timed out"));
			});
			const reportedTransportErrors = attempt.reportedTransportErrors;
			const callbacks = {
				model,
				onEvent: async (event) => {
					if (!current()) return;
					try {
						await this.handleServerEvent(event, attempt);
					} catch (error) {
						if (current()) this.fail(error, (this.providerTransport ?? this.rtc ?? this.pcm ?? this.transport)?.finish());
					}
				},
				onError: (error) => {
					if (current()) {
						reportedTransportErrors.add(error);
						this.reportError(error, attempt);
					}
				},
				onFatalError: (error, drain) => {
					if (current()) this.fail(error, drain);
				},
				onClosing: () => {
					if (!current()) return;
					attempt.beginClose();
					attempt.transportClosing = true;
					attempt.clearTimer("startup");
					attempt.clearTimer("close");
					this.stopAudioCapture();
					if (!current()) return;
					this.applyState({
						...this.state,
						status: attempt.cause == null ? "closing" : "error"
					});
				},
				onClose: (error) => {
					if (!current()) return;
					const finalizationConfirmed = model.capabilities?.finalization === "session-close" && this.state.session?.finalization === "confirmed";
					if (api.provider != null && attempt.closing) {
						if (error != null && !finalizationConfirmed && !reportedTransportErrors.has(error)) {
							reportedTransportErrors.add(error);
							this.reportError(error, attempt);
						}
						return;
					}
					if (error != null && !finalizationConfirmed) this.fail(error, void 0, !reportedTransportErrors.has(error));
					else if (!attempt.ready && !finalizationConfirmed) this.fail(/* @__PURE__ */ new Error("Realtime connection closed before becoming ready"));
					else this.disconnect();
				},
				onCapturing: (isCapturing) => {
					if (current()) this.applyState({
						...this.state,
						isCapturing
					});
				},
				onPlaying: (isPlaying) => {
					if (current()) this.applyState({
						...this.state,
						isPlaying
					});
				}
			};
			if (api.provider != null) {
				const transport = model.createTransport(callbacks);
				if (!current()) {
					transport.dispose();
					return;
				}
				this.providerTransport = transport;
				await transport.connect({
					api: api.provider,
					sessionConfig,
					stream: connectOptions?.stream,
					capture: connectOptions?.capture,
					abortSignal: attempt.abort.signal
				});
			} else if (api.session != null) {
				this.rtc = new BrowserRealtimeWebRTC({
					...callbacks,
					disconnectTimeoutMs: this.options.rtcDisconnectTimeoutMs
				});
				await this.rtc.connect({
					api: api.session,
					sessionConfig,
					stream: connectOptions?.stream,
					capture: connectOptions?.capture,
					timeoutMs: this.options.startupTimeoutMs ?? 3e4
				});
			} else if (api.websocket != null && model.capabilities?.conversation === "continuous") {
				this.pcm = new BrowserRealtimeLiveWebSocket({
					...callbacks,
					sessionConfig,
					sampleRate: this.options.sampleRate,
					maxPlaybackBufferSeconds: this.options.maxPlaybackBufferSeconds
				});
				this.pcm.connect({
					url: api.websocket,
					protocols: api.protocols,
					stream: connectOptions?.stream,
					capture: connectOptions?.capture
				});
			} else {
				this.ensureAudio();
				let config = sessionConfig ?? {};
				let token;
				let url = api.websocket;
				if (api.token != null) {
					const response = await fetch(api.token, {
						method: "POST",
						headers: { "Content-Type": "application/json" },
						body: JSON.stringify({ sessionConfig }),
						signal: attempt.abort.signal
					});
					if (!current()) return;
					if (!response.ok) throw new Error(`Failed to fetch realtime setup: ${response.status}`);
					const payload = await response.json().catch(() => {
						throw new Error("Invalid realtime setup response");
					});
					if (!current() || attempt.closing) return;
					const setup = validateRealtimeSetup(payload);
					token = setup.token;
					url = setup.url;
					config = {
						...sessionConfig,
						...setup.tools == null ? {} : { tools: setup.tools }
					};
				}
				if (url == null) throw new Error("Realtime WebSocket URL is missing");
				if (api.token != null && token == null) throw new Error("Realtime client-secret connection requires a token");
				this.ensureAudio().ensurePlaybackContext();
				if (!current()) return;
				this.transport = new BrowserRealtimeTransport({
					...callbacks,
					onServerEvent: callbacks.onEvent
				});
				this.transport.connect({
					...token != null ? {
						mode: "client-secret",
						token
					} : {
						mode: "relay",
						protocols: api.protocols
					},
					url,
					onOpen: () => {
						const writable = () => current() && !attempt.closing && attempt.cause == null;
						if (!writable()) return;
						return this.sendTransport({
							type: model.capabilities?.startup ?? "session-update",
							config
						}, writable);
					}
				});
			}
		} catch (error) {
			if (current()) this.fail(error);
		}
	}
	fail(error, drain, report = true) {
		const attempt = this.attempt;
		if (attempt == null || !attempt.active || attempt.cause != null) return;
		attempt.cause = error instanceof Error ? error : new Error(String(error));
		if (drain != null) attempt.beginClose();
		this.applyState({
			...this.state,
			status: "error"
		});
		if (this.attempt !== attempt || !attempt.active) return;
		this.stopAudioCapture();
		if (this.attempt !== attempt || !attempt.active) return;
		if (drain == null) this.disconnect();
		else this.drainAttempt(attempt, drain);
		if (report) this.reportError(attempt.cause, attempt);
	}
	async drainAttempt(attempt, drain) {
		if (this.attempt === attempt && attempt.active) attempt.timer("drain", 1e3, () => this.finishAttempt(attempt));
		try {
			await drain;
		} catch {}
		this.finishAttempt(attempt);
	}
	finishAttempt(attempt) {
		if (this.attempt !== attempt || !attempt.active) return;
		try {
			this.disconnect();
		} catch (error) {
			this.reportError(error, attempt);
		}
	}
	closeFailed(attempt, error) {
		if (this.attempt !== attempt || !attempt.active || attempt.transportClosing) return;
		attempt.clearTimer("close");
		const transport = this.providerTransport ?? this.rtc ?? this.pcm ?? this.transport;
		this.drainAttempt(attempt, transport?.finish());
		if (error instanceof Error) {
			if (attempt.reportedTransportErrors.has(error)) return;
			attempt.reportedTransportErrors.add(error);
		}
		this.reportError(error, attempt);
	}
	disconnect() {
		const attempt = this.attempt;
		this.captureGeneration++;
		this.captureRequested = false;
		this.suppliedStream = void 0;
		const transport = this.transport;
		const audio = this.audio;
		const pcm = this.pcm;
		const rtc = this.rtc;
		const providerTransport = this.providerTransport;
		this.transport = void 0;
		this.audio = void 0;
		this.pcm = void 0;
		this.rtc = void 0;
		this.providerTransport = void 0;
		this.commands = void 0;
		attempt?.retire();
		transport?.dispose();
		audio?.dispose();
		pcm?.dispose();
		rtc?.dispose();
		providerTransport?.dispose();
		if (this.attempt !== attempt) return;
		const session = this.state.session;
		this.applyState({
			...this.state,
			status: attempt?.cause != null ? "error" : "disconnected",
			isCapturing: false,
			isPlaying: false,
			...session != null ? { session: session.finalization === "confirmed" ? session : {
				...session,
				finalization: "unconfirmed"
			} } : {}
		});
	}
	/** Wait for provider cleanup or supported session-close finalization. */
	close(options) {
		const attempt = this.attempt;
		if (attempt?.closePromise != null) return attempt.closePromise;
		const providerTransport = this.providerTransport;
		if (providerTransport != null && attempt?.active) {
			const promise = attempt.beginClose();
			attempt.clearTimer("startup");
			this.applyState({
				...this.state,
				status: "closing"
			});
			if (this.attempt !== attempt || !attempt.active) return promise;
			this.stopAudioCapture();
			if (this.attempt !== attempt || !attempt.active) return promise;
			attempt.timer("close", this.options.closeTimeoutMs ?? 15e3, () => {
				if (this.attempt === attempt && attempt.active) this.fail(/* @__PURE__ */ new Error("Realtime provider session cleanup timed out"));
			});
			providerTransport.close().then(() => this.finishAttempt(attempt), (error) => this.closeFailed(attempt, error));
			return promise;
		}
		if (this.state.status !== "connected" || this.options.model.capabilities?.finalization !== "session-close" || attempt == null) {
			this.disconnect();
			return Promise.resolve();
		}
		if (options?.eventId != null) this.commands?.validateId(options.eventId);
		const promise = attempt.beginClose();
		this.applyState({
			...this.state,
			status: "closing"
		});
		if (this.attempt !== attempt || !attempt.active || attempt.transportClosing) return promise;
		this.stopAudioCapture();
		if (this.attempt !== attempt || !attempt.active || attempt.transportClosing) return promise;
		attempt.timer("close", this.options.closeTimeoutMs ?? 15e3, () => this.finishAttempt(attempt));
		const failed = (error) => this.closeFailed(attempt, error);
		try {
			this.commands?.send({
				type: "session-close",
				eventId: options?.eventId
			}).catch(failed);
		} catch (error) {
			failed(error);
		}
		return promise;
	}
	sendTransport(event, guard, automaticAudio = false) {
		const transport = this.providerTransport ?? this.rtc ?? this.pcm ?? this.transport;
		if (transport == null) throw new Error("Realtime connection is not open");
		if (transport === this.providerTransport) {
			const attempt = this.attempt;
			const sent = transport.sendEvent(event, guard);
			sent.catch((error) => {
				if (attempt?.active && this.attempt === attempt) this.reportError(error, attempt);
			});
			return sent;
		}
		if (transport === this.transport) return this.transport.sendEvent(event, guard, automaticAudio);
		return transport.sendEvent(event, guard);
	}
	sendEvent(event) {
		if (this.state.status === "error" || this.state.status === "closing" || this.attempt?.closing || !this.attempt?.active) throw new Error("Realtime session is not accepting submissions");
		if (this.sessionLifecycle && this.state.status !== "connected") throw new Error("Realtime session is not accepting submissions");
		if (this.rtc != null && event.type === "input-audio-append" || (this.continuous || this.rtc != null) && (event.type === "input-audio-commit" || event.type === "input-audio-clear")) throw new UnsupportedFunctionalityError$1({ functionality: "JSON audio commands unsupported for this session transport" });
		if (event.type === "session-close") return this.close({ eventId: event.eventId });
		if (event.type === "session-start" && this.sessionLifecycle) throw new Error("Realtime session has already started");
		if (!this.sessionLifecycle && this.state.session == null) {
			const attempt = this.attempt;
			return this.sendTransport(event, () => this.attempt === attempt && attempt.active && !attempt.closing && attempt.cause == null);
		}
		return this.commands?.send(event) ?? this.sendTransport(event);
	}
	sendTextMessage(text) {
		if (this.continuous) throw new UnsupportedFunctionalityError$1({ functionality: "sendTextMessage for continuous sessions; client-delegation text is application-owned, use context-append for context" });
		this.sendEvent({
			type: "conversation-item-create",
			item: {
				type: "text-message",
				role: "user",
				text
			}
		});
		this.sendEvent({ type: "response-create" });
		this.applyState(this.reducer.addUserTextMessage(this.state, text));
	}
	sendAudio(audio) {
		const attempt = this.attempt;
		this.sendEvent({
			type: "input-audio-append",
			audio
		}).catch((error) => {
			if (attempt?.active && this.attempt === attempt) this.reportError(error, attempt);
		});
	}
	commitAudio() {
		this.sendEvent({ type: "input-audio-commit" });
	}
	clearAudioBuffer() {
		this.sendEvent({ type: "input-audio-clear" });
	}
	requestResponse(options) {
		this.sendEvent({
			type: "response-create",
			...options != null ? { options } : {}
		});
	}
	cancelResponse() {
		this.sendEvent({ type: "response-cancel" });
	}
	sendAutomaticAudio(audio) {
		if (this.state.status !== "connected" || !this.attempt?.active || this.attempt.closing) return;
		const attempt = this.attempt;
		const failed = (error) => {
			if (attempt?.active && this.attempt === attempt && !attempt.closing) this.fail(error);
		};
		try {
			this.sendTransport({
				type: "input-audio-append",
				audio
			}, () => this.attempt === attempt && attempt.active && !attempt.closing, true).catch(failed);
		} catch (error) {
			failed(error);
		}
	}
	addToolOutput(callId, result) {
		if (this.continuous) throw new UnsupportedFunctionalityError$1({ functionality: "addToolOutput for continuous sessions; client delegation is application-owned" });
		const attempt = this.attempt;
		if (!attempt?.active || attempt.closing || attempt.cause != null) throw new Error("Realtime session is not accepting submissions");
		const { state, output } = this.reducer.addToolOutput(this.state, callId, result);
		this.applyState(state);
		if (this.attempt !== attempt || !attempt?.active) return;
		this.sendEvent({
			type: "conversation-item-create",
			item: {
				type: "function-call-output",
				...output
			}
		});
		this.submittedToolOutputs.add(callId);
		this.maybeRequestToolResponse();
	}
	maybeRequestToolResponse() {
		if (this.providerTransport != null || this.state.status !== "connected" || this.attempt?.closing || !this.responseToolCallsClosed || this.toolCallsInResponse.size === 0 || [...this.toolCallsInResponse].some((id) => !this.submittedToolOutputs.has(id))) return;
		this.sendEvent({ type: "response-create" });
		this.toolCallsInResponse.clear();
		this.submittedToolOutputs.clear();
		this.responseToolCallsClosed = false;
	}
	startAudioCapture(stream) {
		const legacy = !this.sessionLifecycle && !this.continuous && this.options.api.session == null && this.options.api.provider == null;
		if (!legacy && this.state.status !== "connected") throw new Error("Realtime session is not accepting capture");
		if (this.attempt?.active && (this.attempt.closing || this.attempt.cause != null)) throw new Error("Realtime session is not accepting capture");
		this.suppliedStream = stream;
		if (legacy) {
			this.captureGeneration++;
			this.captureRequested = true;
			this.ensureAudio().startCapture(stream);
			return;
		}
		const attempt = this.attempt;
		this.resumeAudioCapture().catch((error) => {
			if (attempt?.active) this.reportError(error, attempt);
		});
	}
	async resumeAudioCapture() {
		const accepting = () => !this.attempt?.closing && this.attempt?.cause == null && (this.state.status === "connected" || !this.sessionLifecycle && this.state.status === "connecting");
		if (!accepting()) throw new Error("Realtime session is not accepting capture");
		this.captureRequested = true;
		if (this.providerTransport != null) return this.providerTransport.startCapture(this.suppliedStream);
		if (this.rtc != null) return this.rtc.startCapture(this.suppliedStream);
		if (this.pcm != null) return this.pcm.resumeCapture(this.suppliedStream);
		const audio = this.audio;
		if (audio == null) throw new Error("Realtime capture transport is not ready");
		const captureGeneration = ++this.captureGeneration;
		const attempt = this.attempt;
		const supplied = this.suppliedStream;
		const stream = supplied ?? await navigator.mediaDevices.getUserMedia({ audio: true });
		if (!attempt?.active || this.attempt !== attempt || this.audio !== audio || !accepting() || captureGeneration !== this.captureGeneration) {
			if (supplied == null) stream.getTracks().forEach((track) => track.stop());
			return;
		}
		audio.startCapture(stream, { ownsStream: supplied == null || !this.sessionLifecycle || this.options.api.token != null });
	}
	stopAudioCapture() {
		this.captureGeneration++;
		this.captureRequested = false;
		if (this.audio != null && (!this.sessionLifecycle || this.options.api.token != null)) this.suppliedStream = void 0;
		const pcm = this.pcm;
		const audio = this.audio;
		const rtc = this.rtc;
		const providerTransport = this.providerTransport;
		const attempt = this.attempt;
		if (providerTransport != null) providerTransport.stopCapture().catch((error) => {
			if (attempt?.active && this.attempt === attempt) this.reportError(error, attempt);
		});
		if (rtc != null) rtc.stopCapture().catch((error) => {
			if (attempt?.active && this.attempt === attempt) this.reportError(error, attempt);
		});
		pcm?.stopCapture();
		audio?.stopCapture();
	}
	stopPlayback() {
		(this.providerTransport ?? this.rtc ?? this.pcm ?? this.audio)?.stopPlayback();
	}
	async resumePlayback() {
		await (this.providerTransport ?? this.rtc ?? this.pcm ?? this.audio)?.resumePlayback();
	}
	dispose() {
		this.disconnect();
	}
	ensureAudio() {
		if (this.audio != null) return this.audio;
		const { sessionConfig, sampleRate } = this.options;
		const audio = new BrowserRealtimeAudio({
			captureSampleRate: sessionConfig?.inputAudioFormat?.rate ?? sampleRate ?? 24e3,
			playbackSampleRate: sessionConfig?.outputAudioFormat?.rate ?? sampleRate ?? 24e3,
			onAudio: (value) => {
				if (this.audio === audio) this.sendAutomaticAudio(value);
			},
			onError: (error) => {
				if (this.audio !== audio) return;
				this.reportError(error, this.attempt);
			},
			onCapturingChange: (isCapturing) => {
				if (this.audio === audio) this.applyState({
					...this.state,
					isCapturing
				});
			},
			onPlayingChange: (isPlaying) => {
				if (this.audio === audio) this.applyState({
					...this.state,
					isPlaying
				});
			}
		});
		this.audio = audio;
		return audio;
	}
	applyState(nextState) {
		const publication = ++this.publication;
		const previous = this.state;
		this.state = nextState;
		const update = (key) => {
			if (publication === this.publication && previous[key] !== nextState[key]) this.setState(key, nextState[key]);
		};
		update("status");
		update("messages");
		update("events");
		update("isCapturing");
		update("isPlaying");
		update("session");
	}
	async executeTool(callId, name, args, attempt) {
		if (this.continuous || this.attempt !== attempt || !attempt.active || attempt.closing || attempt.cause != null) return;
		try {
			if (this.onToolCall == null) {
				this.reportError(/* @__PURE__ */ new Error(`No handler provided for tool "${name}"`), attempt);
				return;
			}
			const result = await this.onToolCall({ toolCall: {
				toolCallId: callId,
				toolName: name,
				args
			} });
			if (result !== void 0 && this.attempt === attempt && attempt?.active && this.state.status === "connected") this.addToolOutput(callId, result);
		} catch (error) {
			if (attempt.active) this.reportError(error, attempt);
		}
	}
	async handleServerEvent(event, attempt) {
		const current = () => this.attempt === attempt && attempt.active;
		if (!current()) return;
		if (event.type === "session-started" && event.delegationMode === "provider") throw new UnsupportedFunctionalityError$1({ functionality: "Provider delegation mode; this realtime runtime supports client delegation only" });
		if (this.continuous && event.type === "audio-delta") throw new UnsupportedFunctionalityError$1({ functionality: "Turn-based audio-delta in a continuous PCM session; use audio-chunk" });
		const command = this.commands?.receive(event);
		const result = await this.reducer.reduceServerEvent(this.state, event);
		if (!current()) return;
		const session = this.state.session ?? (event.type === "session-started" ? createSessionState() : void 0);
		this.applyState({
			...result.state,
			status: this.state.status,
			...session == null ? {} : { session: reduceSessionState(session, event, this.maxEvents, command?.muted) }
		});
		if (!current()) return;
		for (const effect of result.effects) {
			this.handleReducerEffect(effect, attempt);
			if (!current()) return;
		}
		if (event.type === "audio-chunk") (this.pcm ?? this.audio)?.playAudio(event.delta);
		if (!current()) return;
		if (event.type === "response-done" && this.toolCallsInResponse.size > 0) {
			this.responseToolCallsClosed = true;
			this.maybeRequestToolResponse();
		}
		if (!current()) return;
		if (event.type === "session-closed" && session != null) {
			this.disconnect();
			this.notifyEvent(event, attempt, true);
			return;
		}
		if ((event.type === "session-started" || event.type === "session-created" || event.type === "session-updated") && attempt.active && !attempt.closing && attempt.cause == null) {
			if (this.options.model.capabilities?.startup === "session-start" ? event.type === "session-started" : event.type !== "session-started") {
				attempt.ready = true;
				attempt.clearTimer("startup");
				this.applyState({
					...this.state,
					status: "connected"
				});
				if (!current() || attempt.closing) return;
				this.pcm?.startCapture();
			}
		}
		if (current()) this.notifyEvent(event, attempt);
	}
	handleReducerEffect(effect, attempt) {
		switch (effect.type) {
			case "play-audio":
				this.currentResponseItemId = effect.itemId;
				this.audio?.playAudio(effect.delta);
				break;
			case "speech-started":
				if (!this.continuous && this.state.isPlaying) {
					const playedMs = this.audio?.getPlaybackOffsetMs() ?? 0;
					const itemId = this.currentResponseItemId;
					this.audio?.stopPlayback();
					if (this.attempt !== attempt || !attempt.active) return;
					if (itemId != null && !attempt.closing && attempt.cause == null) this.sendEvent({
						type: "conversation-item-truncate",
						itemId,
						contentIndex: 0,
						audioEndMs: Math.round(playedMs)
					});
				}
				break;
			case "tool-call":
				if (this.continuous) break;
				this.toolCallsInResponse.add(effect.callId);
				this.executeTool(effect.callId, effect.name, effect.args, attempt);
				break;
			case "error": this.reportError(effect.error, attempt);
		}
	}
	async reportError(error, attempt) {
		if (this.attempt !== attempt) return;
		try {
			await this.onError?.(error instanceof Error ? error : new Error(String(error)));
		} catch {}
	}
	notifyEvent(event, attempt, terminal = false) {
		if (this.attempt !== attempt || !attempt.active && !terminal) return;
		const report = (error) => {
			if (attempt.active || terminal) this.reportError(error, attempt);
		};
		try {
			Promise.resolve(this.onEvent?.(event)).catch(report);
		} catch (error) {
			report(error);
		}
	}
};
//#endregion
//#region src/registry/custom-provider.ts
/**
* Creates a custom provider with specified language models, text embedding models, image models, transcription models, speech models, file APIs, skill APIs, and an optional fallback provider.
*
* @param {Object} options - The options for creating the custom provider.
* @param {Record<string, LanguageModel>} [options.languageModels] - A record of language models, where keys are model IDs and values are language model instances.
* @param {Record<string, EmbeddingModel>} [options.embeddingModels] - A record of text embedding models, where keys are model IDs and values are embedding model instances.
* @param {Record<string, ImageModel>} [options.imageModels] - A record of image models, where keys are model IDs and values are image model instances.
* @param {Record<string, TranscriptionModel>} [options.transcriptionModels] - A record of transcription models, where keys are model IDs and values are transcription model instances.
* @param {Record<string, SpeechModel>} [options.speechModels] - A record of speech models, where keys are model IDs and values are speech model instances.
* @param {Record<string, RerankingModel>} [options.rerankingModels] - A record of reranking models, where keys are model IDs and values are reranking model instances.
* @param {Record<string, VideoModel>} [options.videoModels] - A record of video models, where keys are model IDs and values are video model instances.
* @param {Record<string, DecisionModel>} [options.decisionModels] - Experimental decision models or default-provider model IDs, keyed by alias.
* @param {FilesV4} [options.files] - A files interface for uploading files.
* @param {SkillsV4} [options.skills] - A skills interface for uploading skills.
* @param {ProviderV2 | ProviderV3 | ProviderV4} [options.fallbackProvider] - An optional fallback provider to use when a requested model is not found in the custom provider.
* @returns {ProviderV4} A ProviderV4 object with languageModel, embeddingModel, imageModel, transcriptionModel, speechModel, rerankingModel, and videoModel methods.
*
* @throws {NoSuchModelError} Throws when a requested model is not found and no fallback provider is available.
*/
function customProvider({ languageModels, embeddingModels, imageModels, transcriptionModels, speechModels, rerankingModels, videoModels, decisionModels: decisionModelsArg, evaluationModels, files, skills, fallbackProvider: fallbackProviderArg }) {
	const decisionModels = decisionModelsArg ?? evaluationModels;
	const fallbackProvider = fallbackProviderArg == null ? void 0 : asProviderV4(fallbackProviderArg);
	const baseProvider = {
		specificationVersion: "v4",
		languageModel(modelId) {
			if (languageModels != null && modelId in languageModels) return resolveLanguageModel(languageModels[modelId]);
			if (fallbackProvider) return fallbackProvider.languageModel(modelId);
			throw new NoSuchModelError$1({
				modelId,
				modelType: "languageModel"
			});
		},
		embeddingModel(modelId) {
			if (embeddingModels != null && modelId in embeddingModels) return resolveEmbeddingModel(embeddingModels[modelId]);
			if (fallbackProvider) return fallbackProvider.embeddingModel(modelId);
			throw new NoSuchModelError$1({
				modelId,
				modelType: "embeddingModel"
			});
		},
		imageModel(modelId) {
			if (imageModels != null && modelId in imageModels) return resolveImageModel(imageModels[modelId]);
			if (fallbackProvider?.imageModel) return fallbackProvider.imageModel(modelId);
			throw new NoSuchModelError$1({
				modelId,
				modelType: "imageModel"
			});
		},
		transcriptionModel(modelId) {
			if (transcriptionModels != null && modelId in transcriptionModels) {
				const model = resolveTranscriptionModel(transcriptionModels[modelId]);
				if (model != null) return model;
			}
			if (fallbackProvider?.transcriptionModel) return fallbackProvider.transcriptionModel(modelId);
			throw new NoSuchModelError$1({
				modelId,
				modelType: "transcriptionModel"
			});
		},
		speechModel(modelId) {
			if (speechModels != null && modelId in speechModels) {
				const model = resolveSpeechModel(speechModels[modelId]);
				if (model != null) return model;
			}
			if (fallbackProvider?.speechModel) return fallbackProvider.speechModel(modelId);
			throw new NoSuchModelError$1({
				modelId,
				modelType: "speechModel"
			});
		},
		rerankingModel(modelId) {
			if (rerankingModels != null && modelId in rerankingModels) return resolveRerankingModel(rerankingModels[modelId]);
			if (fallbackProvider?.rerankingModel) return fallbackProvider.rerankingModel(modelId);
			throw new NoSuchModelError$1({
				modelId,
				modelType: "rerankingModel"
			});
		},
		decisionModel(modelId) {
			if (decisionModels != null && Object.hasOwn(decisionModels, modelId)) return resolveDecisionModel(decisionModels[modelId]);
			const provider = fallbackProviderArg;
			const factory = provider?.decisionModel ?? provider?.evaluationModel;
			if (typeof factory === "function") {
				const model = factory.call(provider, modelId);
				if (model != null) return resolveDecisionModel(model);
			}
			throw new NoSuchModelError$1({
				modelId,
				modelType: "decisionModel"
			});
		},
		evaluationModel(modelId) {
			return asEvaluationModel(this.decisionModel(modelId));
		},
		videoModel(modelId) {
			if (videoModels != null && modelId in videoModels) return resolveVideoModel(videoModels[modelId]);
			const provider = fallbackProviderArg;
			if (provider?.videoModel) return resolveVideoModel(provider.videoModel(modelId));
			throw new NoSuchModelError$1({
				modelId,
				modelType: "videoModel"
			});
		}
	};
	const filesAndSkills = {
		...files != null || fallbackProvider?.files != null ? { files() {
			return files ?? fallbackProvider.files();
		} } : {},
		...skills != null || fallbackProvider?.skills != null ? { skills() {
			return skills ?? fallbackProvider.skills();
		} } : {}
	};
	return Object.assign(baseProvider, filesAndSkills);
}
//#endregion
//#region src/registry/no-such-provider-error.ts
const name = "AI_NoSuchProviderError";
const marker = `vercel.ai.error.${name}`;
const symbol = Symbol.for(marker);
var NoSuchProviderError = class extends NoSuchModelError$1 {
	constructor({ modelId, modelType, providerId, availableProviders, message = `No such provider: ${providerId} (available providers: ${availableProviders.join()})` }) {
		super({
			errorName: name,
			modelId,
			modelType,
			message
		});
		this[symbol] = true;
		this.providerId = providerId;
		this.availableProviders = availableProviders;
	}
	static isInstance(error) {
		return AISDKError$1.hasMarker(error, marker);
	}
};
//#endregion
//#region src/registry/provider-registry.ts
/**
* Creates a registry for the given providers with optional middleware functionality.
* This function allows you to register multiple providers and optionally apply middleware
* to all language models from the registry, enabling you to transform parameters, wrap generate
* operations, and wrap stream operations for every language model accessed through the registry.
*
* @param providers - A record of provider instances to be registered in the registry.
* @param options - Configuration options for the provider registry.
* @param options.separator - The separator used between provider ID and model ID in the combined identifier. Defaults to ':'.
* @param options.languageModelMiddleware - Optional middleware to be applied to all language models from the registry. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
* @param options.imageModelMiddleware - Optional middleware to be applied to all image models from the registry. When multiple middlewares are provided, the first middleware will transform the input first, and the last middleware will be wrapped directly around the model.
* @returns A new ProviderRegistryProvider instance that provides access to all registered providers with optional middleware applied to language and image models.
*/
function createProviderRegistry(providers, { separator = ":", languageModelMiddleware, imageModelMiddleware } = {}) {
	const registry = new DefaultProviderRegistry({
		separator,
		languageModelMiddleware,
		imageModelMiddleware
	});
	for (const [id, provider] of Object.entries(providers)) registry.registerProvider({
		id,
		provider
	});
	return registry;
}
/**
* @deprecated Use `createProviderRegistry` instead.
*/
const experimental_createProviderRegistry = createProviderRegistry;
var DefaultProviderRegistry = class {
	constructor({ separator, languageModelMiddleware, imageModelMiddleware }) {
		this.providers = Object.create(null);
		this.separator = separator;
		this.languageModelMiddleware = languageModelMiddleware;
		this.imageModelMiddleware = imageModelMiddleware;
	}
	registerProvider({ id, provider }) {
		const providerV4 = asProviderV4(provider);
		const videoModel = provider.videoModel?.bind(provider);
		const decisionProvider = provider;
		const decisionModel = (decisionProvider.decisionModel ?? decisionProvider.evaluationModel)?.bind(provider);
		const registeredProvider = videoModel == null ? providerV4 : Object.assign(Object.create(Object.getPrototypeOf(providerV4)), {
			...providerV4,
			videoModel: (modelId) => asVideoModelV4(videoModel(modelId))
		});
		if (registeredProvider !== provider && decisionModel != null) Object.assign(registeredProvider, { decisionModel });
		this.providers[id] = registeredProvider;
	}
	getProvider(id, modelType) {
		const provider = this.providers[id];
		if (provider == null) throw new NoSuchProviderError({
			modelId: id,
			modelType,
			providerId: id,
			availableProviders: Object.keys(this.providers)
		});
		return provider;
	}
	splitId(id, modelType) {
		const index = id.indexOf(this.separator);
		if (index === -1) throw new NoSuchModelError$1({
			modelId: id,
			modelType,
			message: `Invalid ${modelType} id for registry: ${id} (must be in the format "providerId${this.separator}modelId")`
		});
		return [id.slice(0, index), id.slice(index + this.separator.length)];
	}
	languageModel(id) {
		const [providerId, modelId] = this.splitId(id, "languageModel");
		let model = this.getProvider(providerId, "languageModel").languageModel?.(modelId);
		if (model == null) throw new NoSuchModelError$1({
			modelId: id,
			modelType: "languageModel"
		});
		if (this.languageModelMiddleware != null) model = wrapLanguageModel({
			model,
			middleware: this.languageModelMiddleware
		});
		return model;
	}
	embeddingModel(id) {
		const [providerId, modelId] = this.splitId(id, "embeddingModel");
		const model = this.getProvider(providerId, "embeddingModel").embeddingModel?.(modelId);
		if (model == null) throw new NoSuchModelError$1({
			modelId: id,
			modelType: "embeddingModel"
		});
		return model;
	}
	imageModel(id) {
		const [providerId, modelId] = this.splitId(id, "imageModel");
		let model = this.getProvider(providerId, "imageModel").imageModel?.(modelId);
		if (model == null) throw new NoSuchModelError$1({
			modelId: id,
			modelType: "imageModel"
		});
		if (this.imageModelMiddleware != null) model = wrapImageModel({
			model,
			middleware: this.imageModelMiddleware
		});
		return model;
	}
	transcriptionModel(id) {
		const [providerId, modelId] = this.splitId(id, "transcriptionModel");
		const model = this.getProvider(providerId, "transcriptionModel").transcriptionModel?.(modelId);
		if (model == null) throw new NoSuchModelError$1({
			modelId: id,
			modelType: "transcriptionModel"
		});
		return model;
	}
	speechModel(id) {
		const [providerId, modelId] = this.splitId(id, "speechModel");
		const model = this.getProvider(providerId, "speechModel").speechModel?.(modelId);
		if (model == null) throw new NoSuchModelError$1({
			modelId: id,
			modelType: "speechModel"
		});
		return model;
	}
	rerankingModel(id) {
		const [providerId, modelId] = this.splitId(id, "rerankingModel");
		const model = this.getProvider(providerId, "rerankingModel").rerankingModel?.(modelId);
		if (model == null) throw new NoSuchModelError$1({
			modelId: id,
			modelType: "rerankingModel"
		});
		return model;
	}
	videoModel(id) {
		const [providerId, modelId] = this.splitId(id, "videoModel");
		const model = this.getProvider(providerId, "videoModel").videoModel?.(modelId);
		if (model == null) throw new NoSuchModelError$1({
			modelId: id,
			modelType: "videoModel"
		});
		return asVideoModelV4(model);
	}
	decisionModel(id) {
		const [providerId, modelId] = this.splitId(id, "decisionModel");
		const provider = this.getProvider(providerId, "decisionModel");
		const model = (provider.decisionModel ?? provider.evaluationModel)?.call(provider, modelId);
		if (model == null) throw new NoSuchModelError$1({
			modelId: id,
			modelType: "decisionModel"
		});
		return resolveDecisionModel(model);
	}
	/** @deprecated Use `decisionModel` instead. */
	evaluationModel(id) {
		return asEvaluationModel(this.decisionModel(id));
	}
	files(id) {
		const files = this.getProvider(id, "languageModel").files?.();
		if (files == null) throw new Error(`The provider "${id}" does not support file uploads. Make sure it exposes a files() method.`);
		return files;
	}
	skills(id) {
		const skills = this.getProvider(id, "languageModel").skills?.();
		if (skills == null) throw new Error(`The provider "${id}" does not support skills. Make sure it exposes a skills() method.`);
		return skills;
	}
};
//#endregion
//#region src/rerank/restricted-telemetry-dispatcher.ts
/**
* Filters runtime context before sending operation events to telemetry integrations.
* User callbacks continue to receive the original context.
*/
function createRestrictedTelemetryDispatcher({ telemetry }) {
	const dispatcher = createTelemetryDispatcher({ telemetry });
	return {
		...dispatcher,
		onStart: (event) => dispatcher.onStart?.({
			...event,
			runtimeContext: filterIncludedContext({
				context: event.runtimeContext,
				includeContext: telemetry?.includeRuntimeContext
			})
		}),
		onEnd: (event) => dispatcher.onEnd?.({
			...event,
			runtimeContext: filterIncludedContext({
				context: event.runtimeContext,
				includeContext: telemetry?.includeRuntimeContext
			})
		})
	};
}
//#endregion
//#region src/rerank/rerank.ts
const originalGenerateCallId$2 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Rerank documents using a reranking model. The type of the value is defined by the reranking model.
*
* @param model - The reranking model to use.
* @param documents - The documents that should be reranked.
* @param query - The query to rerank the documents against.
* @param topN - Number of top documents to return.
*
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
* @param providerOptions - Additional provider-specific options.
* @param telemetry - Optional telemetry configuration.
* @param runtimeContext - User-defined runtime context passed to callbacks and, when explicitly included, telemetry.
*
* @returns A result object that contains the reranked documents, the reranked indices, and additional information.
*/
async function rerank({ model: modelArg, documents, query, topN, maxRetries: maxRetriesArg, abortSignal, headers, providerOptions, experimental_telemetry, telemetry = experimental_telemetry, runtimeContext = {}, onStart, experimental_onStart, onEnd, experimental_onEnd, _internal: { generateCallId = originalGenerateCallId$2 } = {} }) {
	const model = resolveRerankingModel(modelArg);
	const callId = generateCallId();
	const resolvedOnStart = onStart ?? experimental_onStart;
	const resolvedOnEnd = onEnd ?? experimental_onEnd;
	const telemetryDispatcher = createRestrictedTelemetryDispatcher({ telemetry });
	const runInTracingChannelSpan = telemetryDispatcher.runInTracingChannelSpan ?? (async ({ execute }) => await execute());
	if (documents.length === 0) {
		await notify({
			event: {
				callId,
				operationId: "ai.rerank",
				runtimeContext,
				provider: model.provider,
				modelId: model.modelId,
				documents,
				query,
				topN,
				maxRetries: maxRetriesArg ?? 2,
				headers,
				providerOptions
			},
			callbacks: [resolvedOnStart, telemetryDispatcher.onStart]
		});
		await notify({
			event: {
				callId,
				operationId: "ai.rerank",
				runtimeContext,
				provider: model.provider,
				modelId: model.modelId,
				documents,
				query,
				ranking: [],
				warnings: [],
				providerMetadata: void 0,
				response: {
					timestamp: /* @__PURE__ */ new Date(),
					modelId: model.modelId
				}
			},
			callbacks: [resolvedOnEnd, telemetryDispatcher.onEnd]
		});
		return new DefaultRerankResult({
			originalDocuments: [],
			ranking: [],
			providerMetadata: void 0,
			response: {
				timestamp: /* @__PURE__ */ new Date(),
				modelId: model.modelId
			}
		});
	}
	const { maxRetries, retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	const documentsToSend = typeof documents[0] === "string" ? {
		type: "text",
		values: documents
	} : {
		type: "object",
		values: documents
	};
	const startEvent = {
		callId,
		operationId: "ai.rerank",
		runtimeContext,
		provider: model.provider,
		modelId: model.modelId,
		documents,
		query,
		topN,
		maxRetries,
		headers,
		providerOptions
	};
	return await runInTracingChannelSpan({
		type: "rerank",
		event: startEvent,
		execute: async () => {
			await notify({
				event: startEvent,
				callbacks: [resolvedOnStart, telemetryDispatcher.onStart]
			});
			try {
				const { ranking, response, providerMetadata, warnings } = await retry(async () => {
					await notify({
						event: {
							callId,
							operationId: "ai.rerank.doRerank",
							provider: model.provider,
							modelId: model.modelId,
							documents,
							documentsType: documentsToSend.type,
							query,
							topN
						},
						callbacks: [telemetryDispatcher.onRerankStart]
					});
					const modelResponse = await model.doRerank({
						documents: documentsToSend,
						query,
						topN,
						providerOptions,
						abortSignal,
						headers
					});
					const ranking = modelResponse.ranking;
					await notify({
						event: {
							callId,
							operationId: "ai.rerank.doRerank",
							provider: model.provider,
							modelId: model.modelId,
							documentsType: documentsToSend.type,
							ranking
						},
						callbacks: [telemetryDispatcher.onRerankEnd]
					});
					return {
						ranking,
						providerMetadata: modelResponse.providerMetadata,
						response: modelResponse.response,
						warnings: modelResponse.warnings
					};
				});
				validateRankingIndices({
					ranking,
					documents
				});
				logWarnings({
					warnings: warnings ?? [],
					provider: model.provider,
					model: model.modelId
				});
				await notify({
					event: {
						callId,
						operationId: "ai.rerank",
						runtimeContext,
						provider: model.provider,
						modelId: model.modelId,
						documents,
						query,
						ranking: ranking.map((ranking) => ({
							originalIndex: ranking.index,
							score: ranking.relevanceScore,
							document: documents[ranking.index]
						})),
						warnings: warnings ?? [],
						providerMetadata,
						response: {
							id: response?.id,
							timestamp: response?.timestamp ?? /* @__PURE__ */ new Date(),
							modelId: response?.modelId ?? model.modelId,
							headers: response?.headers,
							body: response?.body
						}
					},
					callbacks: [resolvedOnEnd, telemetryDispatcher.onEnd]
				});
				return new DefaultRerankResult({
					originalDocuments: documents,
					ranking: ranking.map((ranking) => ({
						originalIndex: ranking.index,
						score: ranking.relevanceScore,
						document: documents[ranking.index]
					})),
					providerMetadata,
					response: {
						id: response?.id,
						timestamp: response?.timestamp ?? /* @__PURE__ */ new Date(),
						modelId: response?.modelId ?? model.modelId,
						headers: response?.headers,
						body: response?.body
					}
				});
			} catch (error) {
				await telemetryDispatcher.onError?.({
					callId,
					error
				});
				throw error;
			}
		}
	});
}
function validateRankingIndices({ ranking, documents }) {
	for (const { index } of ranking) if (!Number.isInteger(index) || index < 0 || index >= documents.length) throw new InvalidResponseDataError$1({
		data: ranking,
		message: `Invalid ranking index ${index}. Expected an integer between 0 and ${documents.length - 1}.`
	});
}
var DefaultRerankResult = class {
	constructor(options) {
		this.originalDocuments = options.originalDocuments;
		this.ranking = options.ranking;
		this.response = options.response;
		this.providerMetadata = options.providerMetadata;
	}
	get rerankedDocuments() {
		return this.ranking.map((ranking) => ranking.document);
	}
};
//#endregion
//#region src/transcribe/transcribe.ts
const originalGenerateCallId$1 = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Generates transcripts using a transcription model.
*
* @param model - The transcription model to use.
* @param audio - The audio data to transcribe as DataContent (string | Uint8Array | ArrayBuffer | Buffer) or a URL.
* @param providerOptions - Additional provider-specific options that are passed through to the provider
* as body parameters.
* @param maxRetries - Maximum number of retries. Set to 0 to disable retries. Default: 2.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP headers to be sent with the request. Only applicable for HTTP-based providers.
* @param telemetry - Optional telemetry configuration.
*
* @returns A result object that contains the generated transcript.
*/
const defaultDownload = createDownload();
async function transcribe({ model, audio, providerOptions = {}, timestampGranularities, maxRetries: maxRetriesArg, abortSignal, headers, telemetry, download: downloadFn = defaultDownload, _internal: { generateCallId = originalGenerateCallId$1 } = {} }) {
	const resolvedModel = resolveTranscriptionModel(model);
	if (!resolvedModel) throw new Error("Model could not be resolved");
	const { maxRetries, retry } = prepareRetries({
		maxRetries: maxRetriesArg,
		abortSignal
	});
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const callId = generateCallId();
	const telemetryDispatcher = createTelemetryDispatcher({ telemetry });
	const runInTracingChannelSpan = telemetryDispatcher.runInTracingChannelSpan ?? (async ({ execute }) => await execute());
	const createStartEvent = ({ byteLength, mediaType }) => ({
		callId,
		operationId: "ai.transcribe",
		provider: resolvedModel.provider,
		modelId: resolvedModel.modelId,
		audio: {
			byteLength,
			mediaType
		},
		inputAudioFormat: void 0,
		maxRetries,
		headers,
		providerOptions,
		timestampGranularities
	});
	const executeWithStartEvent = async ({ startEvent, execute }) => await runInTracingChannelSpan({
		type: "transcribe",
		event: startEvent,
		execute: async () => {
			await notify({
				event: startEvent,
				callbacks: [telemetryDispatcher.onStart]
			});
			return await execute();
		}
	});
	let preparationError;
	let preparationFailed = false;
	let audioData;
	let downloadedMediaType;
	try {
		if (audio instanceof URL) {
			if (resolvedModel.doGenerateFromUrl != null && downloadFn === defaultDownload && (audio.protocol === "https:" || audio.protocol === "http:")) audioData = audio;
			else {
				const downloadResult = await downloadFn({
					url: audio,
					abortSignal
				});
				audioData = downloadResult.data;
				downloadedMediaType = downloadResult.mediaType;
			}
		} else audioData = convertDataContentToUint8Array(audio);
	} catch (error) {
		preparationFailed = true;
		preparationError = error;
		audioData = /* @__PURE__ */ new Uint8Array();
	}
	if (preparationFailed) {
		const startEvent = createStartEvent({
			byteLength: void 0,
			mediaType: void 0
		});
		try {
			return await executeWithStartEvent({
				startEvent,
				execute: () => {
					throw preparationError;
				}
			});
		} catch (error) {
			await telemetryDispatcher.onError?.({
				callId,
				error
			});
			throw error;
		}
	}
	let mediaType = audioData instanceof URL ? void 0 : getAudioMediaType(downloadedMediaType) ?? detectMediaType({
		data: audioData,
		topLevelType: "audio"
	}) ?? "audio/wav";
	let byteLength = audioData instanceof URL ? void 0 : audioData.byteLength;
	const startEvent = createStartEvent({
		byteLength,
		mediaType
	});
	try {
		return await executeWithStartEvent({
			startEvent,
			execute: async () => {
				const result = await retry(async () => {
					const callOptions = {
						abortSignal,
						headers: headersWithUserAgent,
						providerOptions,
						...timestampGranularities != null ? { timestampGranularities } : {}
					};
					if (audioData instanceof URL) {
						const nativeResult = await resolvedModel.doGenerateFromUrl?.({
							...callOptions,
							audio: audioData
						});
						if (nativeResult != null) return nativeResult;
						const downloaded = await downloadFn({
							url: audioData,
							abortSignal
						});
						audioData = downloaded.data;
						mediaType = getAudioMediaType(downloaded.mediaType) ?? detectMediaType({
							data: audioData,
							topLevelType: "audio"
						}) ?? "audio/wav";
						byteLength = audioData.byteLength;
					}
					return resolvedModel.doGenerate({
						...callOptions,
						audio: audioData,
						mediaType: mediaType ?? "audio/wav"
					});
				});
				logWarnings({
					warnings: result.warnings,
					provider: resolvedModel.provider,
					model: resolvedModel.modelId
				});
				if (result.text == null) throw new NoTranscriptGeneratedError({ responses: [result.response] });
				await notify({
					event: {
						callId,
						operationId: "ai.transcribe",
						provider: resolvedModel.provider,
						modelId: resolvedModel.modelId,
						audio: {
							byteLength,
							mediaType
						},
						text: result.text,
						segments: result.segments,
						words: result.words,
						language: result.language,
						durationInSeconds: result.durationInSeconds,
						usage: result.usage,
						warnings: result.warnings,
						providerMetadata: result.providerMetadata,
						response: result.response
					},
					callbacks: [telemetryDispatcher.onEnd]
				});
				return new DefaultTranscriptionResult({
					text: result.text,
					segments: result.segments,
					words: result.words,
					language: result.language,
					durationInSeconds: result.durationInSeconds,
					warnings: result.warnings,
					responses: [result.response],
					providerMetadata: result.providerMetadata
				});
			}
		});
	} catch (error) {
		await telemetryDispatcher.onError?.({
			callId,
			error
		});
		throw error;
	}
}
/**
* Normalizes a downloaded `Content-Type` header value and returns it only
* when it is a full `audio/<subtype>` media type. Generic or mislabeled types
* (e.g. `application/octet-stream`, `binary/octet-stream`, `text/plain`)
* return `undefined` so that the media type is detected from the audio bytes
* instead.
*/
function getAudioMediaType(contentType) {
	const mediaType = contentType?.split(";")[0].trim().toLowerCase();
	return mediaType != null && getTopLevelMediaType(mediaType) === "audio" && isFullMediaType(mediaType) ? mediaType : void 0;
}
var DefaultTranscriptionResult = class {
	constructor(options) {
		this.text = options.text;
		this.segments = options.segments;
		this.words = options.words;
		this.language = options.language;
		this.durationInSeconds = options.durationInSeconds;
		this.warnings = options.warnings;
		this.responses = options.responses;
		this.providerMetadata = options.providerMetadata ?? {};
	}
};
//#endregion
//#region src/transcribe/stream-transcribe.ts
const originalGenerateCallId = createIdGenerator$1({
	prefix: "call",
	size: 24
});
/**
* Streams transcripts using a transcription model.
*
* @param model - The transcription model to use.
* @param audio - Raw audio chunks to transcribe.
* @param inputAudioFormat - The input audio format for the raw audio chunks.
* @param providerOptions - Additional provider-specific options.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP/WebSocket headers to send when supported by the provider.
* @param telemetry - Optional telemetry configuration.
*
* @returns A result object that contains the streaming transcript and final transcript metadata.
*/
function streamTranscribe({ model, audio, inputAudioFormat, providerOptions = {}, abortSignal, headers, includeRawChunks, telemetry, _internal: { currentDate = () => /* @__PURE__ */ new Date(), generateCallId = originalGenerateCallId } = {} }) {
	const resolvedModel = resolveTranscriptionModel(model);
	if (!resolvedModel) throw new Error("Model could not be resolved");
	const doStream = resolvedModel.doStream?.bind(resolvedModel);
	if (doStream == null) throw new UnsupportedFunctionalityError$1({
		functionality: "streaming transcription",
		message: `The ${resolvedModel.provider} model "${resolvedModel.modelId}" does not support streaming transcription.` + (typeof model === "string" ? " String model IDs resolve through the global provider (AI Gateway by default). If that provider does not support streaming transcription, pass a provider model instance instead (e.g. openai.transcription('gpt-realtime-whisper')) or upgrade @ai-sdk/gateway to a version with streaming transcription support." : "")
	});
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const callId = generateCallId();
	const telemetryDispatcher = createTelemetryDispatcher({ telemetry });
	const runInTracingChannelSpan = telemetryDispatcher.runInTracingChannelSpan ?? (async ({ execute }) => await execute());
	let audioByteLength = 0;
	const countedAudio = telemetryDispatcher.experimental_onStreamTranscriptionEnd != null ? createByteCountingStream(audio, (byteLength) => {
		audioByteLength += byteLength;
	}) : audio;
	const startEvent = {
		callId,
		operationId: "ai.streamTranscribe",
		provider: resolvedModel.provider,
		modelId: resolvedModel.modelId,
		audio: {
			byteLength: void 0,
			mediaType: inputAudioFormat.type
		},
		inputAudioFormat,
		maxRetries: void 0,
		headers,
		providerOptions
	};
	const textPromise = new DelayedPromise();
	const segmentsPromise = new DelayedPromise();
	const languagePromise = new DelayedPromise();
	const durationInSecondsPromise = new DelayedPromise();
	const warningsPromise = new DelayedPromise();
	const responsesPromise = new DelayedPromise();
	const providerMetadataPromise = new DelayedPromise();
	let warnings = [];
	let telemetrySettled = false;
	const rejectPendingPromises = (error) => {
		for (const promise of [
			textPromise,
			segmentsPromise,
			languagePromise,
			durationInSecondsPromise,
			warningsPromise,
			responsesPromise,
			providerMetadataPromise
		]) if (promise.isPending()) promise.reject(error);
	};
	const startedAt = currentDate();
	let response;
	const currentResponseMetadata = () => response ?? {
		timestamp: startedAt,
		modelId: resolvedModel.modelId
	};
	const resolveWarnings = (resolvedWarnings) => {
		warnings = resolvedWarnings;
		warningsPromise.resolve(resolvedWarnings);
		logWarnings({
			warnings: resolvedWarnings,
			provider: resolvedModel.provider,
			model: resolvedModel.modelId
		});
	};
	const pipeAbortController = new AbortController();
	const transform = new TransformStream({
		async transform(value, controller) {
			switch (value.type) {
				case "stream-start":
					resolveWarnings(value.warnings);
					break;
				case "response-metadata":
					response = {
						timestamp: value.timestamp ?? currentResponseMetadata().timestamp,
						modelId: value.modelId ?? currentResponseMetadata().modelId,
						headers: value.headers ?? response?.headers
					};
					break;
				case "transcript-delta":
				case "transcript-partial":
				case "transcript-final":
				case "raw":
				case "error":
					controller.enqueue(value);
					break;
				case "finish":
					if (!warningsPromise.isResolved()) resolveWarnings([]);
					if (!value.text) throw new NoTranscriptGeneratedError({ responses: [currentResponseMetadata()] });
					textPromise.resolve(value.text);
					segmentsPromise.resolve(value.segments);
					languagePromise.resolve(value.language);
					durationInSecondsPromise.resolve(value.durationInSeconds);
					responsesPromise.resolve([currentResponseMetadata()]);
					providerMetadataPromise.resolve(value.providerMetadata ?? {});
					telemetrySettled = true;
					if (telemetryDispatcher.experimental_onStreamTranscriptionEnd != null) await notify({
						event: {
							callId,
							operationId: "ai.streamTranscribe",
							provider: resolvedModel.provider,
							modelId: resolvedModel.modelId,
							audio: {
								byteLength: audioByteLength,
								mediaType: inputAudioFormat.type
							},
							text: value.text,
							segments: value.segments,
							language: value.language,
							durationInSeconds: value.durationInSeconds,
							usage: value.usage,
							warnings,
							providerMetadata: value.providerMetadata,
							response: currentResponseMetadata()
						},
						callbacks: [telemetryDispatcher.experimental_onStreamTranscriptionEnd]
					});
			}
		},
		flush() {
			if (textPromise.isPending()) throw new NoTranscriptGeneratedError({ responses: [currentResponseMetadata()] });
		},
		cancel(reason) {
			pipeAbortController.abort(reason ?? /* @__PURE__ */ new Error("Transcription stream was cancelled."));
		}
	});
	runInTracingChannelSpan({
		type: "streamTranscribe",
		event: startEvent,
		execute: async () => {
			await notify({
				event: startEvent,
				callbacks: [telemetryDispatcher.experimental_onStreamTranscriptionStart]
			});
			const result = await doStream({
				audio: countedAudio,
				inputAudioFormat,
				providerOptions,
				abortSignal: mergeAbortSignals(abortSignal, pipeAbortController.signal),
				headers: headersWithUserAgent,
				includeRawChunks
			});
			response = {
				timestamp: result.response?.timestamp ?? startedAt,
				modelId: result.response?.modelId ?? resolvedModel.modelId,
				headers: result.response?.headers
			};
			await result.stream.pipeTo(transform.writable, { signal: pipeAbortController.signal });
		}
	}).catch(async (error) => {
		const reason = error ?? /* @__PURE__ */ new Error("Transcription stream was cancelled or errored.");
		rejectPendingPromises(reason);
		if (!telemetrySettled) {
			telemetrySettled = true;
			await telemetryDispatcher.onError?.({
				callId,
				error: reason
			});
		}
		countedAudio.cancel(reason).catch(() => {});
		transform.writable.abort(reason).catch(() => {});
	});
	let streamOwner = "unclaimed";
	function consumeStream() {
		if (streamOwner === "full-stream" || streamOwner === "result-promises") return;
		streamOwner = "result-promises";
		const reader = transform.readable.getReader();
		(async () => {
			while (!(await reader.read()).done);
		})().catch(() => {});
	}
	function getFullStream() {
		if (streamOwner !== "unclaimed") throw new Error(streamOwner === "full-stream" ? "fullStream can only be accessed once." : "fullStream cannot be accessed after a result promise.");
		streamOwner = "full-stream";
		return asAsyncIterableStream(transform.readable);
	}
	return {
		get text() {
			consumeStream();
			return textPromise.promise;
		},
		get segments() {
			consumeStream();
			return segmentsPromise.promise;
		},
		get language() {
			consumeStream();
			return languagePromise.promise;
		},
		get durationInSeconds() {
			consumeStream();
			return durationInSecondsPromise.promise;
		},
		get warnings() {
			consumeStream();
			return warningsPromise.promise;
		},
		get responses() {
			consumeStream();
			return responsesPromise.promise;
		},
		get providerMetadata() {
			consumeStream();
			return providerMetadataPromise.promise;
		},
		get fullStream() {
			return getFullStream();
		}
	};
}
function createByteCountingStream(audio, onChunk) {
	let audioReader;
	return new ReadableStream({
		async pull(controller) {
			audioReader ??= audio.getReader();
			const { done, value } = await audioReader.read();
			if (done) {
				controller.close();
				return;
			}
			onChunk(typeof value === "string" ? getBase64ByteLength(value) : value.byteLength);
			controller.enqueue(value);
		},
		async cancel(reason) {
			if (audioReader != null) await audioReader.cancel(reason);
			else await audio.cancel(reason);
		}
	});
}
function getBase64ByteLength(value) {
	let characterCount = 0;
	let lastCharacter = "";
	let secondLastCharacter = "";
	for (const character of value) {
		if (/\s/.test(character)) continue;
		characterCount++;
		secondLastCharacter = lastCharacter;
		lastCharacter = character;
	}
	const padding = lastCharacter === "=" ? secondLastCharacter === "=" ? 2 : 1 : 0;
	return Math.floor(characterCount * 3 / 4) - padding;
}
//#endregion
//#region src/transcribe/index.ts
/**
* @deprecated Use `transcribe` instead.
*/
const experimental_transcribe = (options) => {
	logWarnings({ warnings: [{
		type: "deprecated",
		setting: "experimental_transcribe",
		message: "Use transcribe instead."
	}] });
	return transcribe(options);
};
//#endregion
//#region src/translate/stream-translate.ts
/**
* Streams speech-to-speech translations using a speech translation model.
*
* @param model - The speech translation model to use.
* @param audio - Raw audio chunks to translate.
* @param inputAudioFormat - The input audio format for the raw audio chunks.
* @param targetLanguage - The language to translate the audio into.
* @param sourceLanguage - The language of the source audio. Auto-detected when absent.
* @param outputAudioFormat - The desired audio format for translated audio chunks.
* @param providerOptions - Additional provider-specific options.
* @param abortSignal - An optional abort signal that can be used to cancel the call.
* @param headers - Additional HTTP/WebSocket headers to send when supported by the provider.
* @param includeRawChunks - When true, providers include raw provider chunks in the stream as `raw` parts.
*
* @returns A result object that contains the streaming translation and final translation metadata.
*/
function streamTranslate({ model, audio, inputAudioFormat, targetLanguage, sourceLanguage, outputAudioFormat, providerOptions = {}, abortSignal, headers, includeRawChunks, _internal: { currentDate = () => /* @__PURE__ */ new Date() } = {} }) {
	const resolvedModel = resolveSpeechTranslationModel(model);
	const doStream = resolvedModel.doStream.bind(resolvedModel);
	const headersWithUserAgent = withUserAgentSuffix(headers ?? {}, `ai/${VERSION}`);
	const sourceTextPromise = new DelayedPromise();
	const translationTextPromise = new DelayedPromise();
	const durationInSecondsPromise = new DelayedPromise();
	const usagePromise = new DelayedPromise();
	const warningsPromise = new DelayedPromise();
	const responsePromise = new DelayedPromise();
	const providerMetadataPromise = new DelayedPromise();
	const rejectPendingPromises = (error) => {
		for (const promise of [
			sourceTextPromise,
			translationTextPromise,
			durationInSecondsPromise,
			usagePromise,
			warningsPromise,
			responsePromise,
			providerMetadataPromise
		]) if (promise.isPending()) promise.reject(error);
	};
	const startedAt = currentDate();
	let response;
	const currentResponseMetadata = () => response ?? {
		timestamp: startedAt,
		modelId: resolvedModel.modelId
	};
	const resolveWarnings = (warnings) => {
		warningsPromise.resolve(warnings);
		logWarnings({
			warnings,
			provider: resolvedModel.provider,
			model: resolvedModel.modelId
		});
	};
	const pipeAbortController = new AbortController();
	let hasAudioOutput = false;
	const transform = new TransformStream({
		transform(value, controller) {
			switch (value.type) {
				case "stream-start":
					resolveWarnings(value.warnings);
					break;
				case "response-metadata":
					response = {
						timestamp: value.timestamp ?? currentResponseMetadata().timestamp,
						modelId: value.modelId ?? currentResponseMetadata().modelId,
						headers: value.headers ?? response?.headers
					};
					break;
				case "audio":
					hasAudioOutput = true;
					controller.enqueue(value);
					break;
				case "output-text-delta":
				case "output-text-final":
				case "source-transcript-delta":
				case "source-transcript-partial":
				case "source-transcript-final":
				case "raw":
				case "error":
					controller.enqueue(value);
					break;
				case "finish":
					if (!warningsPromise.isResolved()) resolveWarnings([]);
					if (!hasAudioOutput && !value.outputText) throw new NoTranslationGeneratedError({ response: currentResponseMetadata() });
					sourceTextPromise.resolve(value.sourceText);
					translationTextPromise.resolve(value.outputText);
					durationInSecondsPromise.resolve(value.durationInSeconds);
					usagePromise.resolve(value.usage);
					responsePromise.resolve(currentResponseMetadata());
					providerMetadataPromise.resolve(value.providerMetadata ?? {});
					break;
				default: throw new Error(`Unsupported part type: ${value}`);
			}
		},
		flush() {
			if (translationTextPromise.isPending()) throw new NoTranslationGeneratedError({ response: currentResponseMetadata() });
		},
		cancel(reason) {
			pipeAbortController.abort(reason ?? /* @__PURE__ */ new Error("Translation stream was cancelled."));
		}
	});
	(async () => {
		const result = await doStream({
			audio,
			inputAudioFormat,
			targetLanguage,
			sourceLanguage,
			outputAudioFormat,
			providerOptions,
			abortSignal: mergeAbortSignals(abortSignal, pipeAbortController.signal),
			headers: headersWithUserAgent,
			includeRawChunks
		});
		response = {
			timestamp: result.response?.timestamp ?? startedAt,
			modelId: result.response?.modelId ?? resolvedModel.modelId,
			headers: result.response?.headers
		};
		await result.stream.pipeTo(transform.writable, { signal: pipeAbortController.signal });
	})().catch((error) => {
		const reason = error ?? /* @__PURE__ */ new Error("Translation stream was cancelled or errored.");
		rejectPendingPromises(reason);
		audio.cancel(reason).catch(() => {});
		transform.writable.abort(reason).catch(() => {});
	});
	let streamOwner = "unclaimed";
	function consumeStream() {
		if (streamOwner === "full-stream" || streamOwner === "result-promises") return;
		streamOwner = "result-promises";
		const reader = transform.readable.getReader();
		(async () => {
			while (!(await reader.read()).done);
		})().catch(() => {});
	}
	function getFullStream() {
		if (streamOwner !== "unclaimed") throw new Error(streamOwner === "full-stream" ? "fullStream can only be accessed once." : "fullStream cannot be accessed after a result promise.");
		streamOwner = "full-stream";
		return asAsyncIterableStream(transform.readable);
	}
	return {
		get sourceText() {
			consumeStream();
			return sourceTextPromise.promise;
		},
		get translationText() {
			consumeStream();
			return translationTextPromise.promise;
		},
		get durationInSeconds() {
			consumeStream();
			return durationInSecondsPromise.promise;
		},
		get usage() {
			consumeStream();
			return usagePromise.promise;
		},
		get warnings() {
			consumeStream();
			return warningsPromise.promise;
		},
		get response() {
			consumeStream();
			return responsePromise.promise;
		},
		get providerMetadata() {
			consumeStream();
			return providerMetadataPromise.promise;
		},
		get fullStream() {
			return getFullStream();
		}
	};
}
//#endregion
//#region src/ui/create-ui-api-call-error.ts
async function createUIApiCallError({ response, url, fallbackMessage }) {
	const responseBody = await response.text();
	return new APICallError$1({
		message: responseBody || fallbackMessage,
		url,
		requestBodyValues: void 0,
		statusCode: response.status,
		responseBody
	});
}
//#endregion
//#region src/ui/process-text-stream.ts
async function processTextStream({ stream, onTextPart }) {
	const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
	while (true) {
		const { done, value } = await reader.read();
		if (done) break;
		await onTextPart(value);
	}
}
//#endregion
//#region src/ui/call-completion-api.ts
const getOriginalFetch = () => fetch;
async function callCompletionApi({ api, prompt, credentials, headers, body, streamProtocol = "data", setCompletion, setLoading, setError, setAbortController, getAbortController, onFinish, onError, fetch = getOriginalFetch() }) {
	const abortController = new AbortController();
	const isCurrentRequest = () => getAbortController == null || getAbortController() === abortController;
	try {
		setLoading(true);
		setError(void 0);
		setAbortController(abortController);
		setCompletion("");
		const response = await fetch(api, {
			method: "POST",
			body: JSON.stringify({
				prompt,
				...body
			}),
			credentials,
			headers: withUserAgentSuffix({
				"Content-Type": "application/json",
				...headers
			}, `ai-sdk/${VERSION}`, getRuntimeEnvironmentUserAgent()),
			signal: abortController.signal
		}).catch((err) => {
			throw err;
		});
		if (!response.ok) throw await createUIApiCallError({
			response,
			url: api,
			fallbackMessage: "Failed to fetch the chat response."
		});
		if (!response.body) throw new EmptyResponseBodyError$1({ message: "The response body is empty." });
		let result = "";
		switch (streamProtocol) {
			case "text":
				await processTextStream({
					stream: response.body,
					onTextPart: (chunk) => {
						result += chunk;
						if (isCurrentRequest()) setCompletion(result);
					}
				});
				break;
			case "data":
				await consumeStream({
					stream: parseJsonEventStream$1({
						stream: response.body,
						schema: uiMessageChunkSchema
					}).pipeThrough(new TransformStream({ async transform(part) {
						if (!part.success) throw part.error;
						const streamPart = part.value;
						if (streamPart.type === "text-delta") {
							result += streamPart.delta;
							if (isCurrentRequest()) setCompletion(result);
						} else if (streamPart.type === "error") throw new UIMessageStreamError({
							chunkType: "error",
							chunkId: "",
							message: streamPart.errorText
						});
					} })),
					onError: (error) => {
						throw error;
					}
				});
				break;
			default: {
				const exhaustiveCheck = streamProtocol;
				throw new InvalidArgumentError({
					parameter: "streamProtocol",
					value: exhaustiveCheck,
					message: `Unknown stream protocol: ${exhaustiveCheck}`
				});
			}
		}
		if (onFinish) onFinish(prompt, result);
		return result;
	} catch (err) {
		if (err.name === "AbortError") return null;
		if (err instanceof Error) {
			if (onError) onError(err);
		}
		if (isCurrentRequest()) setError(err);
	} finally {
		if (isCurrentRequest()) {
			setAbortController(null);
			setLoading(false);
		}
	}
}
//#endregion
//#region src/ui/convert-file-list-to-file-ui-parts.ts
async function convertFileListToFileUIParts(files) {
	if (files == null) return [];
	if (!globalThis.FileList || !(files instanceof globalThis.FileList)) throw new UnsupportedFunctionalityError$1({
		functionality: "FileList",
		message: "FileList is not supported in the current environment"
	});
	return Promise.all(Array.from(files).map(async (file) => {
		const { name, type } = file;
		return {
			type: "file",
			mediaType: type,
			filename: name,
			url: await new Promise((resolve, reject) => {
				const reader = new FileReader();
				reader.onload = (readerEvent) => {
					resolve(readerEvent.target?.result);
				};
				reader.onerror = (error) => reject(error);
				reader.readAsDataURL(file);
			})
		};
	}));
}
//#endregion
//#region src/ui/http-chat-transport.ts
function appendPathToUrl(url, path) {
	const queryOrFragmentStart = url.search(/[?#]/);
	const urlPath = queryOrFragmentStart === -1 ? url : url.slice(0, queryOrFragmentStart);
	const suffix = queryOrFragmentStart === -1 ? "" : url.slice(queryOrFragmentStart);
	return `${urlPath.endsWith("/") && path.startsWith("/") ? urlPath.slice(0, -1) : urlPath}${path}${suffix}`;
}
var HttpChatTransport = class {
	constructor({ api = "/api/chat", credentials, headers, body, fetch, prepareSendMessagesRequest, prepareReconnectToStreamRequest }) {
		this.api = api;
		this.credentials = credentials;
		this.headers = headers;
		this.body = body;
		this.fetch = fetch;
		this.prepareSendMessagesRequest = prepareSendMessagesRequest;
		this.prepareReconnectToStreamRequest = prepareReconnectToStreamRequest;
	}
	async sendMessages({ abortSignal, ...options }) {
		const resolvedBody = await resolve(this.body);
		const resolvedHeaders = await resolve(this.headers);
		const resolvedCredentials = await resolve(this.credentials);
		const baseHeaders = {
			...normalizeHeaders(resolvedHeaders),
			...normalizeHeaders(options.headers)
		};
		const preparedRequest = await this.prepareSendMessagesRequest?.({
			api: this.api,
			id: options.chatId,
			messages: options.messages,
			body: {
				...resolvedBody,
				...options.body
			},
			headers: baseHeaders,
			credentials: resolvedCredentials,
			requestMetadata: options.metadata,
			trigger: options.trigger,
			messageId: options.messageId
		});
		const api = preparedRequest?.api ?? this.api;
		const headers = preparedRequest?.headers !== void 0 ? normalizeHeaders(preparedRequest.headers) : baseHeaders;
		const body = preparedRequest?.body !== void 0 ? preparedRequest.body : {
			...resolvedBody,
			...options.body,
			id: options.chatId,
			messages: options.messages,
			trigger: options.trigger,
			messageId: options.messageId
		};
		const credentials = preparedRequest?.credentials ?? resolvedCredentials;
		const response = await (this.fetch ?? globalThis.fetch)(api, {
			method: "POST",
			headers: {
				"content-type": "application/json",
				...headers
			},
			body: JSON.stringify(body),
			credentials,
			signal: abortSignal
		});
		if (!response.ok) throw await createUIApiCallError({
			response,
			url: api,
			fallbackMessage: "Failed to fetch the chat response."
		});
		if (!response.body) throw new EmptyResponseBodyError$1({ message: "The response body is empty." });
		return this.processResponseStream(response.body);
	}
	async reconnectToStream(options) {
		const resolvedBody = await resolve(this.body);
		const resolvedHeaders = await resolve(this.headers);
		const resolvedCredentials = await resolve(this.credentials);
		const baseHeaders = {
			...normalizeHeaders(resolvedHeaders),
			...normalizeHeaders(options.headers)
		};
		const preparedRequest = await this.prepareReconnectToStreamRequest?.({
			api: this.api,
			id: options.chatId,
			body: {
				...resolvedBody,
				...options.body
			},
			headers: baseHeaders,
			credentials: resolvedCredentials,
			requestMetadata: options.metadata
		});
		let api = preparedRequest?.api;
		if (api == null) {
			if (options.chatId === "." || options.chatId === "..") throw new InvalidArgumentError({
				parameter: "chatId",
				value: options.chatId,
				message: "Chat IDs must not be \".\" or \"..\" when using the default reconnect URL."
			});
			api = appendPathToUrl(this.api, `/${encodeURIComponent(options.chatId)}/stream`);
		}
		const headers = preparedRequest?.headers !== void 0 ? normalizeHeaders(preparedRequest.headers) : baseHeaders;
		const credentials = preparedRequest?.credentials ?? resolvedCredentials;
		const response = await (this.fetch ?? globalThis.fetch)(api, {
			method: "GET",
			headers,
			credentials,
			signal: options.abortSignal
		});
		if (response.status === 204) return null;
		if (!response.ok) throw await createUIApiCallError({
			response,
			url: api,
			fallbackMessage: "Failed to fetch the chat response."
		});
		if (!response.body) throw new EmptyResponseBodyError$1({ message: "The response body is empty." });
		return this.processResponseStream(response.body);
	}
};
//#endregion
//#region src/ui/default-chat-transport.ts
var DefaultChatTransport = class extends HttpChatTransport {
	constructor({ resumeStreamIsReplay = true, ...options } = {}) {
		super(options);
		this.resumeStreamIsReplay = resumeStreamIsReplay;
	}
	processResponseStream(stream) {
		return parseJsonEventStream$1({
			stream,
			schema: uiMessageChunkSchema
		}).pipeThrough(new TransformStream({ async transform(chunk, controller) {
			if (!chunk.success) throw chunk.error;
			controller.enqueue(chunk.value);
		} }));
	}
};
//#endregion
//#region src/ui/chat.ts
var AbstractChat = class {
	get id() {
		return this._id ??= this.generateId();
	}
	constructor({ generateId = generateId$1, id, transport = new DefaultChatTransport(), messageMetadataSchema, dataPartSchemas, state, onError, onToolCall, onFinish, onData, sendAutomaticallyWhen, experimental_queue = false }) {
		this.queuedMessagesFallback = [];
		this.queuedMessageOptions = /* @__PURE__ */ new Map();
		this.isQueuePaused = false;
		this.pendingAutomaticDecisions = [];
		this.pendingMessagePreparations = /* @__PURE__ */ new Set();
		this.interruptedMessageIds = /* @__PURE__ */ new Set();
		this.activeResponse = void 0;
		this.activeResumeRequest = void 0;
		this.resumableStreamState = void 0;
		this.jobExecutor = new SerialJobExecutor();
		this.activeStopCount = 0;
		this.stopGeneration = 0;
		this.experimental_removeQueuedMessage = (id) => {
			this.queuedMessageOptions.delete(id);
			this.setQueuedMessages(this.experimental_queuedMessages.filter((message) => message.id !== id));
		};
		this.experimental_sendQueuedMessageNow = async (id) => {
			const message = this.experimental_queuedMessages.find((message) => message.id === id);
			if (message == null) return;
			this.setQueuedMessages([message, ...this.experimental_queuedMessages.filter((queued) => queued.id !== id)]);
			const stopGeneration = this.stopGeneration + 1;
			await this.stop();
			if (stopGeneration !== this.stopGeneration) return;
			await this.resumeQueue({
				skipWaitForUser: true,
				options: this.queuedMessageOptions.get(id)
			});
		};
		this.sendMessage = async (message, options) => {
			if (message == null) {
				let messageId = this.pendingApprovalMessageId;
				if (messageId == null) {
					messageId = this.lastMessage?.id;
					for (let i = this.state.messages.length - 1; i >= 0; i--) {
						const candidate = this.state.messages[i];
						if (candidate.role === "assistant" && candidate.parts.some((part) => isToolUIPart(part) && part.state === "approval-responded")) {
							messageId = candidate.id;
							break;
						}
					}
				}
				const pendingApprovalMessageIndex = messageId != null && messageId === this.pendingApprovalMessageId ? this.state.messages.findIndex((message) => message.id === messageId) : -1;
				await this.makeRequestForToolApproval({
					messageId,
					messageIndex: pendingApprovalMessageIndex,
					...options
				});
				return;
			}
			let uiMessage;
			if ("text" in message || "files" in message) {
				const abortController = new AbortController();
				this.pendingMessagePreparations.add(abortController);
				let fileParts;
				try {
					fileParts = Array.isArray(message.files) ? message.files : await convertFileListToFileUIParts(message.files);
				} finally {
					this.pendingMessagePreparations.delete(abortController);
				}
				if (abortController.signal.aborted) return;
				uiMessage = { parts: [...fileParts, ..."text" in message && message.text != null ? [{
					type: "text",
					text: message.text
				}] : []] };
			} else uiMessage = message;
			if (this.queueEnabled && message.messageId == null && (this.isRequestInProgress() || this.isWaitingForUser() || this.experimental_queuedMessages.length > 0)) {
				const queuedMessage = {
					...uiMessage,
					id: uiMessage.id ?? this.generateId(),
					role: uiMessage.role ?? "user",
					metadata: message.metadata
				};
				if (options != null) this.queuedMessageOptions.set(queuedMessage.id, options);
				this.setQueuedMessages([...this.experimental_queuedMessages, queuedMessage]);
				await this.resumeQueue({
					skipWaitForUser: this.isQueuePaused,
					options
				});
				return;
			}
			if (message.messageId != null) {
				await this.clearQueueForHistoryChange();
				const messageIndex = this.state.messages.findIndex((m) => m.id === message.messageId);
				if (messageIndex === -1) throw new InvalidArgumentError({
					parameter: "message.messageId",
					value: message.messageId,
					message: `message with id ${message.messageId} not found`
				});
				if (this.state.messages[messageIndex].role !== "user") throw new InvalidArgumentError({
					parameter: "message.messageId",
					value: message.messageId,
					message: `message with id ${message.messageId} is not a user message`
				});
				this.state.messages = this.state.messages.slice(0, messageIndex + 1);
				this.state.replaceMessage(messageIndex, {
					id: message.messageId,
					...uiMessage,
					role: uiMessage.role ?? "user",
					metadata: message.metadata
				});
			} else this.state.pushMessage({
				...uiMessage,
				id: uiMessage.id ?? this.generateId(),
				role: uiMessage.role ?? "user",
				metadata: message.metadata
			});
			this.isQueuePaused = false;
			await this.makeRequest({
				trigger: "submit-message",
				messageId: message.messageId,
				...options
			});
		};
		this.regenerate = async ({ messageId, ...options } = {}) => {
			await this.clearQueueForHistoryChange();
			const messageIndex = messageId == null ? this.state.messages.length - 1 : this.state.messages.findIndex((message) => message.id === messageId);
			if (messageIndex === -1) throw new InvalidArgumentError({
				parameter: "messageId",
				value: messageId,
				message: `message ${messageId} not found`
			});
			this.state.messages = this.state.messages.slice(0, this.messages[messageIndex].role === "assistant" ? messageIndex : messageIndex + 1);
			await this.makeRequest({
				trigger: "regenerate-message",
				messageId,
				...options
			});
		};
		this.resumeStream = async (options = {}) => {
			await this.makeRequest({
				trigger: "resume-stream",
				...options
			});
		};
		this["~resumeStreamIfDisconnected"] = async ({ shouldResume = () => true } = {}) => {
			const activeResponse = this.activeResponse;
			if (this.resumableStreamState == null && activeResponse != null) {
				await activeResponse.completionPromise;
				if (this.resumableStreamState !== activeResponse.state) return;
			}
			if (this.resumableStreamState != null && shouldResume()) await this.resumeStream();
		};
		this.clearError = () => {
			if (this.status === "error") {
				this.state.error = void 0;
				this.setStatus({ status: "ready" });
			}
		};
		this.addToolApprovalResponse = async ({ id, approved, reason, options }) => this.jobExecutor.run(async () => {
			const stopGeneration = this.stopGeneration;
			const messages = this.state.messages;
			const updatePart = (part) => isToolUIPart(part) && part.state === "approval-requested" && part.approval.id === id ? {
				...part,
				state: "approval-responded",
				approval: {
					...part.approval,
					id,
					approved,
					reason
				}
			} : part;
			const messageIndex = messages.findIndex((message) => message.parts.some((part) => isToolUIPart(part) && part.state === "approval-requested" && part.approval.id === id));
			if (messageIndex !== -1) {
				const message = messages[messageIndex];
				this.state.replaceMessage(messageIndex, {
					...message,
					parts: message.parts.map(updatePart)
				});
				this.pendingApprovalMessageId = message.id;
			}
			if (this.activeResponse) this.activeResponse.state.message.parts = this.activeResponse.state.message.parts.map(updatePart);
			if (messageIndex !== -1 && this.status !== "streaming" && this.status !== "submitted" && this.sendAutomaticallyWhen) {
				const shouldSend = await this.shouldSendAutomatically(messages[messageIndex].id);
				if (shouldSend) {
					this.runAutomaticRequest(() => {
						const messageId = messageIndex === -1 ? this.lastMessage?.id : messages[messageIndex].id;
						return this.makeRequestForToolApproval({
							messageId,
							messageIndex,
							...options
						});
					}, shouldSend);
					return;
				}
			}
			this.settleQueue({ stopGeneration });
		});
		this.addToolOutput = async ({ state, toolCallId, output, errorText, options }) => this.jobExecutor.run(async () => {
			const stopGeneration = this.stopGeneration;
			const messages = this.state.messages;
			const updatePart = (part) => {
				if (!isToolUIPart(part) || part.toolCallId !== toolCallId) return part;
				const { approval: existingApproval, ...toolPart } = part;
				const approval = existingApproval?.approved === true ? { approval: {
					...existingApproval,
					approved: existingApproval.approved
				} } : {};
				return state === "output-error" ? {
					...toolPart,
					...approval,
					state,
					input: part.input,
					output: void 0,
					errorText
				} : {
					...toolPart,
					...approval,
					state: "output-available",
					input: part.input,
					output,
					errorText: void 0
				};
			};
			const messageIndex = messages.findIndex((message) => message.parts.some((part) => isToolUIPart(part) && part.toolCallId === toolCallId));
			if (messageIndex !== -1) {
				const message = messages[messageIndex];
				this.state.replaceMessage(messageIndex, {
					...message,
					parts: message.parts.map(updatePart)
				});
			}
			if (this.activeResponse) this.activeResponse.state.message.parts = this.activeResponse.state.message.parts.map(updatePart);
			if (messageIndex !== -1 && this.status !== "streaming" && this.status !== "submitted" && this.sendAutomaticallyWhen) {
				const shouldSend = await this.shouldSendAutomatically(messages[messageIndex].id);
				if (shouldSend) {
					this.runAutomaticRequest(() => this.makeRequest({
						trigger: "submit-message",
						messageId: messages[messageIndex].id,
						...options
					}), shouldSend);
					return;
				}
			}
			this.settleQueue({ stopGeneration });
		});
		this.addToolResult = this.addToolOutput;
		this.stop = async () => {
			this.activeStopCount++;
			this.stopGeneration++;
			this.deferredApprovalSend = void 0;
			try {
				const activeResumeRequest = this.activeResumeRequest;
				const activeResponse = this.activeResponse;
				for (const controller of this.pendingMessagePreparations) controller.abort();
				activeResumeRequest?.abortController.abort();
				activeResponse?.abortController.abort();
				await Promise.all([activeResumeRequest?.completionPromise, activeResponse?.completionPromise]);
				await this.jobExecutor.waitForIdle();
				this.isQueuePaused = true;
			} finally {
				this.activeStopCount--;
			}
		};
		this.dispose = async () => {
			await this.stop();
			this.transport.close?.();
		};
		this._id = id;
		this.transport = transport;
		this.generateId = generateId;
		this.messageMetadataSchema = messageMetadataSchema;
		this.dataPartSchemas = dataPartSchemas;
		this.state = state;
		this.onError = onError;
		this.onToolCall = onToolCall;
		this.onFinish = onFinish;
		this.onData = onData;
		this.sendAutomaticallyWhen = sendAutomaticallyWhen;
		this.queueEnabled = experimental_queue;
	}
	/**
	* Hook status:
	*
	* - `submitted`: The message has been sent to the API and we're awaiting the start of the response stream.
	* - `streaming`: The response is actively streaming in from the API, receiving chunks of data.
	* - `ready`: The full response has been received and processed; a new user message can be submitted.
	* - `error`: An error occurred during the API request, preventing successful completion.
	*/
	get status() {
		return this.state.status;
	}
	setStatus({ status, error }) {
		if (this.status === status) {
			if (this.error !== error) this.state.error = error;
			return;
		}
		this.state.status = status;
		this.state.error = error;
	}
	get error() {
		return this.state.error;
	}
	get messages() {
		return this.state.messages;
	}
	get lastMessage() {
		return this.state.messages[this.state.messages.length - 1];
	}
	/**
	* Experimental. Messages that wait to be sent when `experimental_queue` is
	* enabled, in the order they will be sent.
	*/
	get experimental_queuedMessages() {
		return this.state.experimental_queuedMessages ?? this.queuedMessagesFallback;
	}
	setQueuedMessages(experimental_queuedMessages) {
		if ("experimental_queuedMessages" in this.state) this.state.experimental_queuedMessages = experimental_queuedMessages;
		else this.queuedMessagesFallback = experimental_queuedMessages;
	}
	async resumeQueue({ skipWaitForUser, options }) {
		this.isQueuePaused = false;
		if (this.hasUnsentApprovalResponse()) {
			if (!this.isRequestInProgress()) {
				await this.sendMessage(void 0, options);
				return;
			}
			this.deferredApprovalSend = { options };
		}
		await this.settleQueue({ skipWaitForUser });
	}
	async clearQueueForHistoryChange() {
		if (!this.queueEnabled) return;
		this.queuedMessageOptions.clear();
		this.setQueuedMessages([]);
		this.deferredApprovalSend = void 0;
		if (this.isRequestInProgress()) await this.stop();
	}
	isRequestInProgress() {
		return this.pendingAutomaticDecisions.includes(this.stopGeneration) || this.activeResponse != null || this.status === "submitted" || this.status === "streaming";
	}
	isWaitingForUser() {
		const lastMessage = this.lastMessage;
		return lastMessage?.role === "assistant" && lastMessage.parts.some((part) => isToolUIPart(part) && (part.state === "approval-requested" || part.state === "approval-responded" || !part.providerExecuted && (part.state === "input-streaming" || part.state === "input-available")));
	}
	hasUnsentApprovalResponse() {
		const lastMessage = this.lastMessage;
		return lastMessage?.role === "assistant" && lastMessage.parts.some((part) => isToolUIPart(part) && part.state === "approval-responded") && !lastMessage.parts.some((part) => isToolUIPart(part) && (part.state === "approval-requested" || !part.providerExecuted && (part.state === "input-streaming" || part.state === "input-available")));
	}
	async settleQueue({ stopGeneration = this.stopGeneration, skipWaitForUser = false } = {}) {
		if (this.isQueuePaused || this.isRequestInProgress() || this.activeStopCount > 0 || stopGeneration !== this.stopGeneration) return;
		const deferredApprovalSend = this.deferredApprovalSend;
		this.deferredApprovalSend = void 0;
		if (deferredApprovalSend != null && this.hasUnsentApprovalResponse()) {
			await this.sendMessage(void 0, deferredApprovalSend.options);
			return;
		}
		const [message, ...rest] = this.experimental_queuedMessages;
		if (message == null || !skipWaitForUser && this.isWaitingForUser()) return;
		const options = this.queuedMessageOptions.get(message.id);
		this.queuedMessageOptions.delete(message.id);
		this.setQueuedMessages(rest);
		this.state.pushMessage(message);
		await this.makeRequest({
			trigger: "submit-message",
			...options
		});
	}
	set messages(messages) {
		this.state.messages = messages;
	}
	async shouldSendAutomatically(messageId = this.lastMessage?.id) {
		const isInterrupted = (id) => id != null && this.interruptedMessageIds.has(id);
		if (!this.sendAutomaticallyWhen || isInterrupted(messageId) || isInterrupted(this.lastMessage?.id)) return false;
		const stopGeneration = this.stopGeneration;
		this.pendingAutomaticDecisions.push(stopGeneration);
		let result;
		try {
			result = await this.sendAutomaticallyWhen({ messages: this.state.messages });
		} finally {
			this.pendingAutomaticDecisions.splice(this.pendingAutomaticDecisions.indexOf(stopGeneration), 1);
		}
		return result && !isInterrupted(messageId) && !isInterrupted(this.lastMessage?.id);
	}
	async runAutomaticRequest(request, shouldSend) {
		const stopGeneration = this.stopGeneration;
		const startedWhileStopping = this.activeStopCount > 0;
		if (!(shouldSend ?? await this.shouldSendAutomatically())) return false;
		if (startedWhileStopping || stopGeneration !== this.stopGeneration || this.activeStopCount > 0) return false;
		await request();
		return true;
	}
	async makeRequestForToolApproval({ messageId, messageIndex, ...options }) {
		this.deferredApprovalSend = void 0;
		const consumesPendingApproval = messageId != null && messageId === this.pendingApprovalMessageId;
		if (consumesPendingApproval) this.pendingApprovalMessageId = void 0;
		await this.makeRequest({
			trigger: "submit-message",
			messageId,
			...options
		});
		if (consumesPendingApproval && this.status === "error" && this.pendingApprovalMessageId == null) this.pendingApprovalMessageId = this.state.messages[messageIndex]?.id ?? messageId;
	}
	async makeRequest(options) {
		const completion = createResolvablePromise();
		try {
			await this.makeRequestImpl({
				...options,
				completionPromise: completion.promise
			});
		} finally {
			completion.resolve();
		}
	}
	async makeRequestImpl({ trigger, metadata, headers, body, messageId, completionPromise }) {
		if (trigger !== "resume-stream") this.resumableStreamState = void 0;
		const abortController = new AbortController();
		const activeResumeRequest = trigger === "resume-stream" ? {
			abortController,
			completionPromise
		} : void 0;
		if (activeResumeRequest) {
			this.activeResumeRequest?.abortController.abort();
			this.activeResumeRequest = activeResumeRequest;
		}
		const isCurrentRequest = () => activeResumeRequest == null || this.activeResumeRequest === activeResumeRequest;
		const clearActiveResumeRequest = () => {
			if (this.activeResumeRequest === activeResumeRequest) this.activeResumeRequest = void 0;
		};
		let resumeStream;
		if (trigger === "resume-stream") try {
			const reconnect = await this.transport.reconnectToStream({
				chatId: this.id,
				abortSignal: abortController.signal,
				metadata,
				headers,
				body
			});
			if (abortController.signal.aborted || !isCurrentRequest()) {
				await reconnect?.cancel().catch(() => {});
				if (isCurrentRequest()) {
					this.setStatus({ status: "ready" });
					this.resumableStreamState = void 0;
				}
				clearActiveResumeRequest();
				return;
			}
			if (reconnect == null) {
				this.setStatus({ status: "ready" });
				this.resumableStreamState = void 0;
				clearActiveResumeRequest();
				return;
			}
			resumeStream = reconnect;
		} catch (err) {
			if (abortController.signal.aborted || err.name === "AbortError") {
				if (isCurrentRequest()) {
					this.setStatus({ status: "ready" });
					this.resumableStreamState = void 0;
				}
				clearActiveResumeRequest();
				return;
			}
			if (!isCurrentRequest()) return;
			if (this.onError && err instanceof Error) this.onError(err);
			this.setStatus({
				status: "error",
				error: err
			});
			clearActiveResumeRequest();
			return;
		}
		this.setStatus({
			status: "submitted",
			error: void 0
		});
		const lastMessage = this.lastMessage;
		const responseMessageIndex = trigger === "submit-message" && messageId != null ? this.state.messages.findIndex((message) => message.id === messageId) : this.state.messages.length - 1;
		const responseMessage = responseMessageIndex === -1 ? lastMessage : this.state.messages[responseMessageIndex];
		const originalResponseMessageId = responseMessage?.id;
		const resumableResponseMessage = trigger === "resume-stream" && responseMessage?.role === "assistant" && responseMessage.parts.some((part) => isToolUIPart(part) && (part.state === "input-streaming" || part.state === "input-available" && part.providerExecuted || part.state === "approval-responded")) ? this.state.snapshot(responseMessage) : void 0;
		const usesEarlierAssistantMessage = responseMessageIndex !== -1 && responseMessageIndex < this.state.messages.length - 1 && responseMessage?.role === "assistant";
		let isAbort = false;
		let isDisconnect = false;
		let isError = false;
		let activeResponse;
		try {
			const response = {
				state: trigger === "resume-stream" && this.resumableStreamState != null ? this.resumableStreamState : createStreamingUIMessageState({
					lastMessage: trigger === "resume-stream" ? resumableResponseMessage : trigger === "regenerate-message" ? void 0 : this.state.snapshot(responseMessage),
					messageId: this.generateId()
				}),
				abortController,
				completionPromise
			};
			activeResponse = response;
			response.abortController.signal.addEventListener("abort", () => {
				isAbort = true;
			});
			this.activeResponse = response;
			let stream;
			if (trigger === "resume-stream") stream = resumeStream;
			else stream = await this.transport.sendMessages({
				chatId: this.id,
				messages: this.state.messages,
				abortSignal: response.abortController.signal,
				metadata,
				headers,
				body,
				trigger,
				messageId
			});
			const runUpdateMessageJob = (job) => this.jobExecutor.run(() => {
				if (response.abortController.signal.aborted) return Promise.resolve();
				return job({
					state: response.state,
					write: ({ updateStatus = true } = {}) => {
						if (response.abortController.signal.aborted) return;
						if (updateStatus) this.setStatus({ status: "streaming" });
						const existingMessageIndex = this.state.messages.findLastIndex((message) => message.id === response.state.message.id);
						if (existingMessageIndex !== -1) this.state.replaceMessage(existingMessageIndex, response.state.message);
						else if (usesEarlierAssistantMessage) {
							const originalMessageIndex = this.state.messages.findLastIndex((message) => message.id === originalResponseMessageId);
							if (originalMessageIndex !== -1) this.state.replaceMessage(originalMessageIndex, response.state.message);
							else this.state.pushMessage(response.state.message);
						} else this.state.pushMessage(response.state.message);
					}
				});
			});
			await consumeStream({
				stream: processUIMessageStream({
					stream,
					resetStateOnMessageIdChange: trigger === "resume-stream",
					resetStateOnFirstMessageStart: trigger === "resume-stream" && this.transport.resumeStreamIsReplay,
					onToolCall: this.onToolCall,
					onData: this.onData,
					messageMetadataSchema: this.messageMetadataSchema,
					dataPartSchemas: this.dataPartSchemas,
					runUpdateMessageJob,
					onError: (error) => {
						throw error;
					}
				}),
				abortSignal: response.abortController.signal,
				onError: (error) => {
					throw error;
				}
			});
			if (isAbort) {
				if (isCurrentRequest()) {
					this.setStatus({ status: "ready" });
					if (this.resumableStreamState === response.state) this.resumableStreamState = void 0;
				}
				return null;
			}
			if (isCurrentRequest()) {
				this.setStatus({ status: "ready" });
				if (this.resumableStreamState === response.state) this.resumableStreamState = void 0;
			}
		} catch (err) {
			if (isAbort || err.name === "AbortError") {
				isAbort = true;
				if (isCurrentRequest()) {
					this.setStatus({ status: "ready" });
					if (this.resumableStreamState === activeResponse?.state) this.resumableStreamState = void 0;
				}
				return null;
			}
			if (!isCurrentRequest()) return null;
			isError = true;
			if (err instanceof TypeError) {
				const message = err.message.toLowerCase();
				isDisconnect = message.includes("fetch") || message.includes("network") || message === "load failed";
			}
			if (isDisconnect) this.resumableStreamState = activeResponse?.state;
			else if (this.resumableStreamState === activeResponse?.state) this.resumableStreamState = void 0;
			if (this.onError && err instanceof Error) this.onError(err);
			this.setStatus({
				status: "error",
				error: err
			});
		} finally {
			try {
				if (activeResponse) {
					const { message, finishReason } = activeResponse.state;
					if (finishReason === "interrupted") this.interruptedMessageIds.add(message.id);
					else if (!isAbort && !isError) this.interruptedMessageIds.delete(message.id);
					this.onFinish?.({
						message: activeResponse.state.message,
						messages: this.state.messages,
						isAbort,
						isDisconnect,
						isError,
						finishReason: activeResponse.state.finishReason
					});
				}
			} finally {
				if (isAbort || isError || activeResponse?.state.finishReason === "interrupted") this.isQueuePaused = true;
				if (this.activeResponse === activeResponse) this.activeResponse = void 0;
				clearActiveResumeRequest();
			}
		}
		if (!isAbort && !isError && activeResponse?.state.finishReason !== "interrupted") {
			const stopGeneration = this.stopGeneration;
			if (!await this.runAutomaticRequest(() => this.makeRequest({
				trigger: "submit-message",
				messageId: this.lastMessage?.id,
				metadata,
				headers,
				body
			}))) await this.settleQueue({ stopGeneration });
		}
	}
};
//#endregion
//#region src/ui/direct-chat-transport.ts
/**
* A transport that directly communicates with an Agent in-process,
* without going through HTTP. This is useful for:
* - Server-side rendering scenarios
* - Testing without network
* - Single-process applications
*
* @example
* ```tsx
* import { useChat } from '@ai-sdk/react';
* import { DirectChatTransport } from 'ai';
* import { myAgent } from './my-agent';
*
* const { messages, sendMessage } = useChat({
*   transport: new DirectChatTransport({ agent: myAgent }),
* });
* ```
*/
var DirectChatTransport = class {
	constructor({ agent, options, ...uiMessageStreamOptions }) {
		this.agent = agent;
		this.agentOptions = options;
		this.uiMessageStreamOptions = uiMessageStreamOptions;
	}
	async sendMessages({ messages, abortSignal }) {
		const validatedMessages = await validateUIMessagesForAgent({
			messages,
			tools: this.agent.tools
		});
		const modelMessages = await convertToModelMessages(validatedMessages, { tools: this.agent.tools });
		const result = await this.agent.stream({
			prompt: modelMessages,
			abortSignal,
			...this.agentOptions !== void 0 ? { options: this.agentOptions } : {}
		});
		return toUIMessageStream({
			...this.uiMessageStreamOptions,
			originalMessages: this.uiMessageStreamOptions.originalMessages ?? validatedMessages,
			stream: result.stream,
			tools: this.agent.tools
		});
	}
	/**
	* Direct transport does not support reconnection since there is no
	* persistent server-side stream to reconnect to.
	*
	* @returns Always returns `null`
	*/
	async reconnectToStream(_options) {
		return null;
	}
};
//#endregion
//#region src/ui/last-assistant-message-is-complete-with-approval-responses.ts
/**
* Check if the last message is an assistant message with completed tool call approvals.
* The last step of the message must have at least one tool approval response and
* all tool approvals must have a response.
*/
function lastAssistantMessageIsCompleteWithApprovalResponses({ messages }) {
	const message = messages[messages.length - 1];
	if (!message) return false;
	if (message.role !== "assistant") return false;
	const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
		return part.type === "step-start" ? index : lastIndex;
	}, -1);
	const lastStepToolInvocations = message.parts.slice(lastStepStartIndex + 1).filter(isToolUIPart);
	return lastStepToolInvocations.filter((part) => part.state === "approval-responded").length > 0 && lastStepToolInvocations.every((part) => part.state === "output-available" && part.preliminary !== true || part.state === "output-error" || part.state === "output-denied" || part.state === "approval-responded");
}
//#endregion
//#region src/ui/last-assistant-message-is-complete-with-tool-calls.ts
/**
* Check if the last message is an assistant message with completed tool calls.
* The last step of the message must have at least one tool invocation and
* all tool invocations must have a result. Completed model text may follow
* the tool invocation because client-side tool results update parts in place,
* but trailing text without a completed stream state prevents resubmission.
*/
function lastAssistantMessageIsCompleteWithToolCalls({ messages }) {
	const message = messages[messages.length - 1];
	if (!message) return false;
	if (message.role !== "assistant") return false;
	const lastStepStartIndex = message.parts.reduce((lastIndex, part, index) => {
		return part.type === "step-start" ? index : lastIndex;
	}, -1);
	const lastStepParts = message.parts.slice(lastStepStartIndex + 1);
	const lastStepToolInvocations = lastStepParts.filter(isToolUIPart).filter((part) => !part.providerExecuted);
	const lastToolInvocationIndex = lastStepParts.reduce((lastIndex, part, index) => isToolUIPart(part) && !part.providerExecuted ? index : lastIndex, -1);
	return lastStepToolInvocations.length > 0 && !lastStepParts.slice(lastToolInvocationIndex + 1).some((part) => part.type === "text" && part.state !== "done") && lastStepToolInvocations.every((part) => part.state === "output-available" && part.preliminary !== true || part.state === "output-error");
}
//#endregion
//#region src/ui/transform-text-to-ui-message-stream.ts
function transformTextToUiMessageStream({ stream }) {
	return stream.pipeThrough(new TransformStream({
		start(controller) {
			controller.enqueue({ type: "start" });
			controller.enqueue({ type: "start-step" });
			controller.enqueue({
				type: "text-start",
				id: "text-1"
			});
		},
		async transform(part, controller) {
			controller.enqueue({
				type: "text-delta",
				id: "text-1",
				delta: part
			});
		},
		async flush(controller) {
			controller.enqueue({
				type: "text-end",
				id: "text-1"
			});
			controller.enqueue({ type: "finish-step" });
			controller.enqueue({ type: "finish" });
		}
	}));
}
//#endregion
//#region src/ui/text-stream-chat-transport.ts
var TextStreamChatTransport = class extends HttpChatTransport {
	constructor(options = {}) {
		super(options);
	}
	processResponseStream(stream) {
		return transformTextToUiMessageStream({ stream: stream.pipeThrough(new TextDecoderStream()) });
	}
};
//#endregion
//#region src/ui/websocket-chat-transport.ts
const WEBSOCKET_OPEN_STATE = 1;
function createAbortError(signal) {
	const reason = signal?.reason;
	if (reason instanceof Error) return reason;
	const error = /* @__PURE__ */ new Error("The WebSocket chat request was aborted.");
	error.name = "AbortError";
	return error;
}
function asError(error) {
	return error instanceof Error ? error : new Error(String(error));
}
function isRecord(value) {
	return value != null && typeof value === "object" && !Array.isArray(value);
}
function isStringRecord(value) {
	return isRecord(value) && Object.values(value).every((item) => typeof item === "string");
}
function isSequence(value) {
	return Number.isSafeInteger(value) && value >= 0;
}
/**
* Validates an untrusted client-to-server WebSocket chat frame.
*/
async function safeValidateWebSocketChatTransportRequest({ value }) {
	try {
		if (!isRecord(value) || typeof value.type !== "string") throw new Error("Invalid WebSocket chat request frame.");
		if (value.type === "abort") {
			if (typeof value.requestId !== "string") throw new Error("Invalid WebSocket chat abort request.");
			return {
				success: true,
				data: value
			};
		}
		if (typeof value.requestId !== "string" || typeof value.id !== "string" || !isStringRecord(value.headers) || !isRecord(value.body)) throw new Error("Invalid WebSocket chat request frame.");
		if (value.type === "resume") {
			if (value.lastSequence !== void 0 && !isSequence(value.lastSequence)) throw new Error("Invalid WebSocket chat resume sequence.");
			return {
				success: true,
				data: value
			};
		}
		if (value.type !== "send" || !["submit-message", "regenerate-message"].includes(value.trigger) || value.messageId !== void 0 && typeof value.messageId !== "string") throw new Error("Invalid WebSocket chat send request.");
		const messages = await safeValidateUIMessages({ messages: value.messages });
		if (!messages.success) throw new Error("Invalid UI messages in WebSocket chat request.", { cause: messages.error });
		return {
			success: true,
			data: {
				...value,
				messages: messages.data
			}
		};
	} catch (error) {
		return {
			success: false,
			error: asError(error)
		};
	}
}
/**
* A `ChatTransport` that multiplexes correlated UI message streams over one
* persistent WebSocket connection.
*
* The server must implement the protocol represented by
* `WebSocketChatTransportRequest` and `WebSocketChatTransportResponse`.
*/
var WebSocketChatTransport = class {
	constructor(options) {
		this.resumeStreamIsReplay = true;
		this.activeRequests = /* @__PURE__ */ new Map();
		this.sendQueue = Promise.resolve();
		this.url = options.url;
		this.protocols = options.protocols;
		this.params = options.params;
		this.headers = options.headers;
		this.body = options.body;
		this.webSocket = options.webSocket;
		this.prepareSendMessagesRequest = options.prepareSendMessagesRequest;
		this.prepareReconnectToStreamRequest = options.prepareReconnectToStreamRequest;
	}
	async sendMessages({ abortSignal, ...options }) {
		this.throwIfAborted(abortSignal);
		const [resolvedHeaders, resolvedBody] = await Promise.all([resolve(this.headers), resolve(this.body)]);
		this.throwIfAborted(abortSignal);
		const headers = {
			...normalizeHeaders(resolvedHeaders),
			...normalizeHeaders(options.headers)
		};
		const body = {
			...resolvedBody,
			...options.body
		};
		const preparedRequest = await this.prepareSendMessagesRequest?.({
			id: options.chatId,
			messages: options.messages,
			requestMetadata: options.metadata,
			body,
			headers,
			trigger: options.trigger,
			messageId: options.messageId
		});
		this.throwIfAborted(abortSignal);
		const socket = await this.getSocket(abortSignal);
		const requestId = generateId$1();
		const request = this.createActiveRequest({
			requestId,
			kind: "send",
			lastSequence: -1,
			abortSignal
		});
		const frame = {
			type: "send",
			requestId,
			id: options.chatId,
			trigger: options.trigger,
			messageId: options.messageId,
			messages: preparedRequest?.messages ?? options.messages,
			headers: preparedRequest?.headers == null ? headers : normalizeHeaders(preparedRequest.headers),
			body: preparedRequest?.body ?? body,
			metadata: options.metadata
		};
		try {
			await this.sendFrame(socket, frame, abortSignal);
			return request.stream;
		} catch (error) {
			const requestError = asError(error);
			this.failRequest(request, requestError);
			throw requestError;
		}
	}
	async reconnectToStream(options) {
		this.throwIfAborted(options.abortSignal);
		const [resolvedHeaders, resolvedBody] = await Promise.all([resolve(this.headers), resolve(this.body)]);
		this.throwIfAborted(options.abortSignal);
		const headers = {
			...normalizeHeaders(resolvedHeaders),
			...normalizeHeaders(options.headers)
		};
		const body = {
			...resolvedBody,
			...options.body
		};
		const preparedRequest = await this.prepareReconnectToStreamRequest?.({
			id: options.chatId,
			requestMetadata: options.metadata,
			body,
			headers
		});
		this.throwIfAborted(options.abortSignal);
		const socket = await this.getSocket(options.abortSignal);
		const requestId = generateId$1();
		let resolveResponse;
		let rejectResponse;
		const responsePromise = new Promise((resolve, reject) => {
			resolveResponse = resolve;
			rejectResponse = reject;
		});
		responsePromise.catch(() => {});
		const request = this.createActiveRequest({
			requestId,
			kind: "resume",
			lastSequence: -1,
			abortSignal: options.abortSignal,
			resolveResponse,
			rejectResponse
		});
		const frame = {
			type: "resume",
			requestId,
			id: options.chatId,
			lastSequence: void 0,
			headers: preparedRequest?.headers == null ? headers : normalizeHeaders(preparedRequest.headers),
			body: preparedRequest?.body ?? body,
			metadata: options.metadata
		};
		try {
			await this.sendFrame(socket, frame, options.abortSignal);
		} catch (error) {
			const requestError = asError(error);
			request.responseSettled = true;
			this.failRequest(request, requestError);
			throw requestError;
		}
		return responsePromise;
	}
	/**
	* Closes the current connection and errors any active response streams.
	* A later request opens a new connection.
	*/
	close() {
		const error = /* @__PURE__ */ new Error("WebSocket chat transport was closed.");
		const connection = this.connection;
		this.connection = void 0;
		this.failAllRequests(error);
		if (connection != null) {
			this.rejectConnection(connection, error);
			try {
				connection.socket?.close(1e3, "Client closed transport");
			} catch {}
		}
	}
	throwIfAborted(abortSignal) {
		if (abortSignal?.aborted) throw createAbortError(abortSignal);
	}
	async getSocket(abortSignal) {
		const existingSocket = this.connection?.socket;
		if (existingSocket?.readyState === WEBSOCKET_OPEN_STATE) return existingSocket;
		if (this.connection == null) {
			let resolveConnection;
			let rejectConnection;
			const connection = {
				promise: new Promise((resolve, reject) => {
					resolveConnection = resolve;
					rejectConnection = reject;
				}),
				resolve: resolveConnection,
				reject: rejectConnection,
				settled: false
			};
			this.connection = connection;
			this.initializeConnection(connection);
		}
		const connection = this.connection;
		if (connection == null) throw new Error("Failed to initialize WebSocket connection.");
		return this.waitForConnection(connection.promise, abortSignal);
	}
	async initializeConnection(connection) {
		try {
			const params = await resolve(this.params);
			if (this.connection !== connection) return;
			const url = this.buildUrl(params);
			const socket = new (getWebSocketConstructor(this.webSocket))(url, this.protocols);
			connection.socket = socket;
			let messageTail = Promise.resolve();
			socket.onopen = () => {
				if (this.connection !== connection) return;
				this.resolveConnection(connection, socket);
			};
			socket.onmessage = (event) => {
				messageTail = messageTail.then(() => readWebSocketMessageText(event.data)).then((text) => this.handleResponseFrame(connection, text)).catch((error) => {
					this.terminateConnection(connection, asError(error));
				});
			};
			socket.onerror = () => {
				this.terminateConnection(connection, /* @__PURE__ */ new TypeError("WebSocket chat network connection failed."));
			};
			socket.onclose = (event) => {
				messageTail = messageTail.then(() => {
					if (this.connection !== connection) return;
					const closeEvent = event;
					const code = typeof closeEvent?.code === "number" ? closeEvent.code : void 0;
					const reason = typeof closeEvent?.reason === "string" && closeEvent.reason !== "" ? `: ${closeEvent.reason}` : "";
					this.terminateConnection(connection, /* @__PURE__ */ new TypeError(`WebSocket chat network connection closed${code == null ? "" : ` (code ${code}${reason})`}.`), false);
				}).catch((error) => {
					this.terminateConnection(connection, asError(error));
				});
			};
		} catch (error) {
			this.terminateConnection(connection, asError(error), false);
		}
	}
	buildUrl(params) {
		let url;
		try {
			const baseUrl = typeof globalThis.location === "undefined" ? void 0 : globalThis.location.href;
			url = new URL(this.url, baseUrl);
			url = toWebSocketUrl(url);
		} catch {
			throw new Error("Invalid WebSocket chat URL. Use an absolute URL outside the browser.");
		}
		if (!["ws:", "wss:"].includes(url.protocol) || url.hostname === "") throw new Error("Invalid WebSocket chat URL. Expected ws:// or wss://.");
		if (url.hash !== "") throw new Error("Invalid WebSocket chat URL. Fragments are not allowed.");
		for (const [key, value] of Object.entries(params ?? {})) url.searchParams.set(key, value);
		return url;
	}
	waitForConnection(promise, abortSignal) {
		if (abortSignal == null) return promise;
		if (abortSignal.aborted) return Promise.reject(createAbortError(abortSignal));
		return new Promise((resolve, reject) => {
			const onAbort = () => {
				reject(createAbortError(abortSignal));
			};
			abortSignal.addEventListener("abort", onAbort, { once: true });
			promise.then((socket) => {
				abortSignal.removeEventListener("abort", onAbort);
				resolve(socket);
			}, (error) => {
				abortSignal.removeEventListener("abort", onAbort);
				reject(error);
			});
		});
	}
	resolveConnection(connection, socket) {
		if (connection.settled) return;
		connection.settled = true;
		connection.resolve(socket);
	}
	rejectConnection(connection, error) {
		if (connection.settled) return;
		connection.settled = true;
		connection.reject(error);
	}
	terminateConnection(connection, error, closeSocket = true) {
		if (this.connection !== connection) return;
		this.connection = void 0;
		this.rejectConnection(connection, error);
		this.failAllRequests(error);
		if (closeSocket) try {
			connection.socket?.close(1011, "WebSocket chat transport error");
		} catch {}
	}
	createActiveRequest({ requestId, kind, lastSequence, abortSignal, resolveResponse, rejectResponse }) {
		let controller;
		const request = {
			requestId,
			kind,
			lastSequence,
			stream: new ReadableStream({
				start(streamController) {
					controller = streamController;
				},
				cancel: () => {
					this.abortRequest(requestId, false);
				}
			}),
			controller,
			responseSettled: false,
			resolveResponse,
			rejectResponse,
			abortSignal
		};
		this.activeRequests.set(requestId, request);
		if (abortSignal != null) {
			const abortListener = () => {
				this.abortRequest(requestId, true);
			};
			request.abortListener = abortListener;
			abortSignal.addEventListener("abort", abortListener, { once: true });
			if (abortSignal.aborted) abortListener();
		}
		return request;
	}
	abortRequest(requestId, closeStream) {
		const request = this.activeRequests.get(requestId);
		if (request == null) return;
		const error = createAbortError(request.abortSignal);
		if (request.kind === "resume" && !request.responseSettled) {
			request.responseSettled = true;
			request.rejectResponse?.(error);
		}
		this.cleanupRequest(request);
		if (closeStream) try {
			request.controller.close();
		} catch {}
		const socket = this.connection?.socket;
		if (socket?.readyState === WEBSOCKET_OPEN_STATE) this.sendFrame(socket, {
			type: "abort",
			requestId
		}).catch(() => {});
	}
	cleanupRequest(request) {
		this.activeRequests.delete(request.requestId);
		if (request.abortListener != null) {
			request.abortSignal?.removeEventListener("abort", request.abortListener);
			request.abortListener = void 0;
		}
	}
	failRequest(request, error) {
		if (!this.activeRequests.has(request.requestId)) return;
		if (request.kind === "resume" && !request.responseSettled) {
			request.responseSettled = true;
			request.rejectResponse?.(error);
		}
		this.cleanupRequest(request);
		try {
			request.controller.error(error);
		} catch {}
	}
	failAllRequests(error) {
		for (const request of [...this.activeRequests.values()]) this.failRequest(request, error);
	}
	resolveResumeStream(request) {
		if (request.kind !== "resume" || request.responseSettled) return;
		request.responseSettled = true;
		request.resolveResponse?.(request.stream);
	}
	async validateResponseChunk(value) {
		const chunk = await safeValidateTypes({
			value,
			schema: uiMessageChunkSchema
		});
		if (!chunk.success) throw new Error("Invalid UI message chunk in WebSocket response.");
		return chunk.value;
	}
	async handleResponseFrame(connection, text) {
		if (this.connection !== connection) return;
		const parsed = await safeParseJSON({ text });
		if (!parsed.success || !isRecord(parsed.value)) throw new Error("Invalid WebSocket chat response frame.");
		const type = parsed.value.type;
		const requestId = parsed.value.requestId;
		if (typeof type !== "string" || typeof requestId !== "string") throw new Error("Invalid WebSocket chat response frame.");
		const request = this.activeRequests.get(requestId);
		if (request == null) return;
		switch (type) {
			case "start":
				this.resolveResumeStream(request);
				return;
			case "chunk": {
				if (!isSequence(parsed.value.sequence)) throw new Error("Invalid WebSocket chat chunk sequence.");
				if (parsed.value.sequence <= request.lastSequence) return;
				if (parsed.value.sequence !== request.lastSequence + 1) throw new Error("Out-of-order WebSocket chat chunk sequence.");
				const chunk = await this.validateResponseChunk(parsed.value.chunk);
				if (this.activeRequests.get(requestId) !== request) return;
				this.resolveResumeStream(request);
				try {
					request.controller.enqueue(chunk);
				} catch {
					return;
				}
				request.lastSequence = parsed.value.sequence;
				return;
			}
			case "end":
				this.resolveResumeStream(request);
				this.cleanupRequest(request);
				request.controller.close();
				return;
			case "no-active":
				if (request.kind === "resume" && !request.responseSettled) {
					request.responseSettled = true;
					request.resolveResponse?.(null);
				}
				this.cleanupRequest(request);
				request.controller.close();
				return;
			case "error":
				if (parsed.value.errorText !== void 0 && typeof parsed.value.errorText !== "string") throw new Error("Invalid WebSocket chat error response.");
				this.failRequest(request, new Error(parsed.value.errorText ?? "WebSocket chat server returned an error."));
				return;
			default: throw new Error(`Unknown WebSocket chat response type: ${type}.`);
		}
	}
	async sendFrame(socket, frame, abortSignal) {
		const send = this.sendQueue.then(async () => {
			await waitForWebSocketBufferDrain(socket, { abortSignal });
			this.throwIfAborted(abortSignal);
			if (this.connection?.socket !== socket || socket.readyState !== WEBSOCKET_OPEN_STATE) throw new TypeError("WebSocket chat network connection is not open.");
			socket.send(JSON.stringify(frame));
		});
		this.sendQueue = send.catch(() => {});
		return send;
	}
};
//#endregion
//#region src/upload-file/upload-file.ts
/**
* Uploads a file using a files API interface.
*
* @param api - The Files API interface to use for uploading.
* @param data - The file data to upload (tagged `{ type: 'data' | 'text' | 'stream' }`).
* Stream data is sent without buffering by providers that support streaming
* uploads (others reject with `UnsupportedFunctionalityError`); the provider
* consumes the stream — any failed upload, including validation failures
* before a request is made, cancels it. Do not reuse it.
* @param mediaType - Optional IANA media type. Auto-detected from file bytes
* when omitted (falls back to `text/plain` for the `text` variant and
* `application/octet-stream` for the `stream` variant, which cannot be sniffed).
* @param filename - Optional filename for the uploaded file. Multipart-based
* providers default it to `"blob"` when omitted.
* @param abortSignal - Optional signal to cancel the upload.
* @param headers - Optional additional HTTP headers for the request.
* @param providerOptions - Additional provider-specific options.
*
* @returns A result object containing the provider reference, optional
* metadata, and — when reported by the provider — `byteSize`, `createdAt`,
* and `expiresAt` (the provider-applied retention expiry).
*/
async function uploadFile({ api, data: dataArg, mediaType: mediaTypeArg, filename, abortSignal, headers, providerOptions }) {
	const data = dataArg instanceof Uint8Array || typeof dataArg === "string" ? {
		type: "data",
		data: dataArg
	} : dataArg;
	const mediaType = mediaTypeArg ?? (data.type === "text" ? "text/plain" : data.type === "stream" ? "application/octet-stream" : detectMediaType({ data: data.data }) ?? (isLikelyText(data.data) ? "text/plain" : "application/octet-stream"));
	let result;
	try {
		result = await ("uploadFile" in api ? api : typeof api.files === "function" ? api.files() : (() => {
			throw new Error("The provider does not support file uploads. Make sure it exposes a files() method.");
		})()).uploadFile({
			data,
			mediaType,
			filename,
			abortSignal,
			headers,
			providerOptions
		});
	} catch (error) {
		if (data.type === "stream") await data.stream.cancel(error).catch(() => {});
		throw error;
	}
	return new DefaultUploadFileResult({
		providerReference: result.providerReference,
		mediaType: result.mediaType,
		filename: result.filename,
		byteSize: result.byteSize,
		createdAt: result.createdAt,
		expiresAt: result.expiresAt,
		providerMetadata: result.providerMetadata,
		warnings: result.warnings
	});
}
var DefaultUploadFileResult = class {
	constructor(options) {
		this.providerReference = options.providerReference;
		this.mediaType = options.mediaType;
		this.filename = options.filename;
		this.byteSize = options.byteSize;
		this.createdAt = options.createdAt;
		this.expiresAt = options.expiresAt;
		this.providerMetadata = options.providerMetadata;
		this.warnings = options.warnings;
	}
};
function isLikelyText(data) {
	const CHECK_LENGTH = 512;
	const BASE64_CHECK_LENGTH = Math.ceil(172) * 4;
	const bytes = typeof data === "string" ? convertBase64ToUint8Array(data.substring(0, Math.min(data.length, BASE64_CHECK_LENGTH))) : data;
	const checkLength = Math.min(bytes.length, CHECK_LENGTH);
	if (checkLength === 0) return false;
	for (let i = 0; i < checkLength; i++) {
		const byte = bytes[i];
		if (byte === 0 || byte < 32 && byte !== 9 && byte !== 10 && byte !== 13) return false;
	}
	return true;
}
//#endregion
//#region src/upload-skill/upload-skill.ts
async function uploadSkill({ api, files, displayTitle, providerOptions }) {
	const skillsApi = "uploadSkill" in api ? api : typeof api.skills === "function" ? api.skills() : (() => {
		throw new Error("The provider does not support skills. Make sure it exposes a skills() method.");
	})();
	const normalizedFiles = files.map((file) => ({
		...file,
		data: file.data instanceof Uint8Array || typeof file.data === "string" ? {
			type: "data",
			data: file.data
		} : file.data
	}));
	return await skillsApi.uploadSkill({
		files: normalizedFiles,
		displayTitle,
		providerOptions
	});
}
//#endregion
export { AISDKError, AI_SDK_TELEMETRY_TRACING_CHANNEL, APICallError, AbstractChat, DefaultChatTransport, DefaultGeneratedFile, DirectChatTransport, DownloadError, EmptyResponseBodyError, AbstractRealtimeSession as Experimental_AbstractRealtimeSession, ToolLoopAgent as Experimental_Agent, ToolLoopAgent, Experimental_DecisionRefusalError, Experimental_DecisionUnsupportedQuestionTypeError, Experimental_EvaluationUnsupportedQuestionTypeError, Experimental_ExtractionRefusalError, Experimental_ExtractionUnsupportedFieldTypeError, HttpChatTransport, InvalidArgumentError, InvalidDataContentError, InvalidMessageRoleError, InvalidPromptError, InvalidResponseDataError, InvalidStreamPartError, InvalidToolApprovalError, InvalidToolApprovalSignatureError, InvalidToolInputError, JSONParseError, JsonToSseTransformStream, LoadAPIKeyError, LoadSettingError, MessageConversionError, MissingToolResultsError, NoContentGeneratedError, NoImageGeneratedError, NoObjectGeneratedError, NoOutputGeneratedError, NoSpeechGeneratedError, NoSuchModelError, NoSuchProviderError, NoSuchProviderReferenceError, NoSuchToolError, NoTranscriptGeneratedError, NoTranslationGeneratedError, NoVideoGeneratedError, output_exports as Output, RetryError, SerialJobExecutor, StreamProviderError, TextStreamChatTransport, TooManyEmbeddingValuesForCallError, ToolCallNotFoundForApprovalError, ToolCallRepairError, ToolChoiceViolationError, TypeValidationError, UIMessageStreamError, UI_MESSAGE_STREAM_HEADERS, UnsupportedFunctionalityError, UnsupportedModelVersionError, WebSocketChatTransport, addToolInputExamplesMiddleware, asSchema, assistantModelMessageSchema, callCompletionApi, consumeStream, convertDataContentToBase64String, convertFileListToFileUIParts, convertToModelMessages, cosineSimilarity, createAgentUIStream, createAgentUIStreamResponse, createDownload, createGateway, createIdGenerator, createProviderRegistry, createTextStreamResponse, createUIMessageStream, createUIMessageStreamResponse, customProvider, defaultEmbeddingSettingsMiddleware, defaultInstructionsMiddleware, defaultSettingsMiddleware, detectToolDrift, dynamicTool, embed, embedMany, cancelBatch as experimental_cancelBatch, experimental_createProviderRegistry, createSteering as experimental_createSteering, decide as experimental_decide, decodeRealtimeAudio as experimental_decodeRealtimeAudio, encodeRealtimeAudio as experimental_encodeRealtimeAudio, experimental_evaluate, extract as experimental_extract, filterActiveTools as experimental_filterActiveTools, filterActiveTools, experimental_generateSpeech, experimental_generateVideo, getBatchResults as experimental_getBatchResults, getBatchStatus as experimental_getBatchStatus, getRealtimeToolDefinitions as experimental_getRealtimeToolDefinitions, experimental_getVideoStatus, listBatches as experimental_listBatches, resampleAudio as experimental_resampleAudio, startBatch as experimental_startBatch, experimental_startVideo, streamLanguageModelCall as experimental_streamLanguageModelCall, streamSpeech as experimental_streamSpeech, streamTextLowMemory as experimental_streamTextLowMemory, streamTranscribe as experimental_streamTranscribe, streamTranslate as experimental_streamTranslate, experimental_toolCaller, experimental_transcribe, extractJsonMiddleware, extractReasoningMiddleware, fingerprintTools, gateway, generateId, generateImage, generateObject, generateSpeech, generateText, getChunkTimeoutMs, getFirstChunkTimeoutMs, getStaticToolName, getStepTimeoutMs, getTextFromDataUrl, getToolName, getToolOrDynamicToolName, getToolTimeoutMs, getTotalTimeoutMs, hasToolCall, isCustomContentUIPart, isDataUIPart, isDeepEqualData, isDynamicToolUIPart, isFileUIPart, isLoopFinished, isReasoningFileUIPart, isReasoningUIPart, isStaticToolUIPart, isStepCount, isStepCount as stepCountIs, isTextUIPart, isToolOutputErrorUIPart, isToolUIPart, jsonSchema, lastAssistantMessageIsCompleteWithApprovalResponses, lastAssistantMessageIsCompleteWithToolCalls, modelMessageSchema, parseJsonEventStream, parsePartialJson, pipeAgentUIStreamToResponse, pipeTextStreamToResponse, pipeUIMessageStreamToResponse, pruneMessages, readUIMessageStream, registerTelemetry, rerank, safeValidateUIMessages, safeValidateWebSocketChatTransportRequest, simulateReadableStream, simulateStreamingMiddleware, smoothStream, streamObject, streamText, systemModelMessageSchema, toTextStream, toUIMessageChunk, toUIMessageStream, tool, toolModelMessageSchema, toolSearch, transcribe, uiMessageChunkSchema, uploadFile, uploadSkill, userModelMessageSchema, validateUIMessages, wrapEmbeddingModel, wrapImageModel, wrapLanguageModel, wrapProvider, zodSchema };

//# sourceMappingURL=index.js.map