workers-ai-provider
Version:
Workers AI Provider for the vercel AI SDK
520 lines (518 loc) • 22.7 kB
text/typescript
import { C as createResumableStream, E as wireableProviders, S as WireFormat, T as findProviderBySlug, _ as GATEWAY_PROVIDERS, a as ProviderPlugin, b as ResumableStreamOptions, c as selectTransport, d as FallbackAttempt, f as GatewayErrorCode, g as Billing, h as WorkersAIGatewayError, i as ParsedSlug, l as FallbackLeg, m as WorkersAIFallbackError, n as DispatchInfo, o as Transport, p as GatewayErrorContext, r as FallbackOptions, s as parseSlug, t as DelegateCallOptions, u as createClientFallbackModel, v as GatewayDelegateError, w as detectProviderByUrl, x as ResumeExpiredPolicy, y as GatewayProviderInfo } from "./gateway-delegate-D_zkIp5r.mjs";
import { GatewayFetchConfig, createGatewayFetch, createGatewayProvider } from "./gateway-provider.mjs";
import { EmbeddingModelV3, EmbeddingModelV3CallOptions, EmbeddingModelV3Result, ImageModelV3, LanguageModelV3, RerankingModelV3, SpeechModelV3, TranscriptionModelV3 } from "@ai-sdk/provider";
//#region src/aisearch-chat-settings.d.ts
type AISearchChatSettings = {
/**
* Whether to inject a safety prompt before all conversations.
* Defaults to `false`.
*/
safePrompt?: boolean;
/**
* Passthrough settings that are provided directly to the run function.
*/
[key: string]: unknown;
};
//#endregion
//#region src/workersai-models.d.ts
/**
* The known (typed) BaseAiTextGeneration model ids — the literal union without
* the `(string & {})` escape hatch. Used to drive editor autocomplete while
* still capturing the exact literal a caller passed (see `WorkersAI`).
*/
type KnownTextGenerationModels = Exclude<value2key<AiModels, BaseAiTextGeneration>, value2key<AiModels, BaseAiTextToImage>>;
/**
* The names of the BaseAiTextGeneration models.
*
* Accepts any string at runtime, but provides autocomplete for known models.
*/
type TextGenerationModels = KnownTextGenerationModels | (string & {});
type ImageGenerationModels = value2key<AiModels, BaseAiTextToImage> | (string & {});
/**
* The names of the BaseAiTextToEmbeddings models.
*
* Accepts any string at runtime, but provides autocomplete for known models.
*/
type EmbeddingModels = value2key<AiModels, BaseAiTextEmbeddings> | (string & {});
/**
* Workers AI models that support speech-to-text transcription.
*
* Includes Whisper variants from `@cloudflare/workers-types` plus
* Deepgram partner models that may not be in the typed interface yet.
* Accepts any string at runtime, but provides autocomplete for known models.
*/
type TranscriptionModels = value2key<AiModels, BaseAiAutomaticSpeechRecognition> | "@cf/deepgram/nova-3" | (string & {});
/**
* Workers AI models that support text-to-speech.
*
* Includes models from `@cloudflare/workers-types` plus Deepgram partner
* models that may not be in the typed interface yet.
* Accepts any string at runtime, but provides autocomplete for known models.
*/
type SpeechModels = value2key<AiModels, BaseAiTextToSpeech> | "@cf/deepgram/aura-1" | "@cf/deepgram/aura-2-en" | "@cf/deepgram/aura-2-es" | (string & {});
/**
* Workers AI models that support reranking.
*
* Accepts any string at runtime, but provides autocomplete for known models.
*/
type RerankingModels = "@cf/baai/bge-reranker-base" | "@cf/baai/bge-reranker-v2-m3" | (string & {});
type value2key<T, V> = { [K in keyof T]: T[K] extends V ? K : never }[keyof T];
//#endregion
//#region src/aisearch-chat-language-model.d.ts
type AISearchChatConfig = {
provider: string;
binding: AutoRAG;
gateway?: GatewayOptions;
};
declare class AISearchChatLanguageModel implements LanguageModelV3 {
readonly specificationVersion = "v3";
readonly defaultObjectGenerationMode = "json";
readonly supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>>;
readonly modelId: TextGenerationModels;
readonly settings: AISearchChatSettings;
private readonly config;
constructor(modelId: TextGenerationModels, settings: AISearchChatSettings, config: AISearchChatConfig);
get provider(): string;
private getWarnings;
/**
* Build the search query from messages.
* Flattens the conversation into a single string for aiSearch.
*/
private buildQuery;
doGenerate(options: Parameters<LanguageModelV3["doGenerate"]>[0]): Promise<Awaited<ReturnType<LanguageModelV3["doGenerate"]>>>;
doStream(options: Parameters<LanguageModelV3["doStream"]>[0]): Promise<Awaited<ReturnType<LanguageModelV3["doStream"]>>>;
}
//#endregion
//#region src/workersai-embedding-model.d.ts
type WorkersAIEmbeddingConfig = {
provider: string;
binding: Ai;
gateway?: GatewayOptions;
};
type WorkersAIEmbeddingSettings = {
gateway?: GatewayOptions;
maxEmbeddingsPerCall?: number;
supportsParallelCalls?: boolean;
/**
* Passthrough settings that are provided directly to the run function.
*/
[key: string]: unknown;
};
declare class WorkersAIEmbeddingModel implements EmbeddingModelV3 {
readonly specificationVersion = "v3";
readonly modelId: EmbeddingModels;
private readonly config;
private readonly settings;
get provider(): string;
get maxEmbeddingsPerCall(): number;
get supportsParallelCalls(): boolean;
constructor(modelId: EmbeddingModels, settings: WorkersAIEmbeddingSettings, config: WorkersAIEmbeddingConfig);
doEmbed({
values,
abortSignal
}: EmbeddingModelV3CallOptions): Promise<EmbeddingModelV3Result>;
}
//#endregion
//#region src/workersai-chat-settings.d.ts
type WorkersAIChatSettings = {
/**
* Whether to inject a safety prompt before all conversations.
* Defaults to `false`.
*/
safePrompt?: boolean;
/**
* Optionally set Cloudflare AI Gateway options.
*/
gateway?: GatewayOptions;
/**
* Session affinity key for prefix-cache optimization.
* Routes requests with the same key to the same backend replica.
*/
sessionAffinity?: string;
/**
* Controls the reasoning budget for reasoning-capable Workers AI models
* (e.g. `@cf/zai-org/glm-4.7-flash`, `@cf/moonshotai/kimi-k2.7-code`,
* `@cf/openai/gpt-oss-120b`).
*
* `null` is a valid value and disables reasoning for models that support it.
* Forwarded on the `inputs` object of `binding.run(model, inputs)`.
*/
reasoning_effort?: "low" | "medium" | "high" | null;
/**
* Chat-template overrides for reasoning-capable models that expose
* thinking toggles (e.g. GLM, Kimi).
*
* Forwarded on the `inputs` object of `binding.run(model, inputs)`.
*/
chat_template_kwargs?: {
/** Whether to enable reasoning. Enabled by default on reasoning models. */enable_thinking?: boolean; /** If false, preserves reasoning context between turns. */
clear_thinking?: boolean;
};
/**
* Passthrough settings that are provided directly to the run function.
* Use this for any provider-specific options not covered by the typed fields.
*/
[key: string]: unknown;
};
//#endregion
//#region src/workersai-chat-language-model.d.ts
type WorkersAIChatConfig = {
provider: string;
binding: Ai;
gateway?: GatewayOptions; /** True when using a real Workers AI binding (not the REST shim). */
isBinding: boolean;
};
declare class WorkersAIChatLanguageModel implements LanguageModelV3 {
readonly specificationVersion = "v3";
readonly defaultObjectGenerationMode = "json";
readonly supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>>;
readonly modelId: TextGenerationModels;
readonly settings: WorkersAIChatSettings;
private readonly config;
constructor(modelId: TextGenerationModels, settings: WorkersAIChatSettings, config: WorkersAIChatConfig);
get provider(): string;
private getArgs;
/**
* Build the inputs object for `binding.run()`, shared by doGenerate and doStream.
*
* Images are embedded inline in messages as OpenAI-compatible content
* arrays with `image_url` parts. Both the REST API and the binding
* accept this format at runtime.
*
* The binding path additionally normalises null content to empty strings.
*
* Reasoning controls (`reasoning_effort`, `chat_template_kwargs`) are
* forwarded here from settings. These belong on the INPUTS object, not on
* the 3rd-arg options / REST query string — see
* https://github.com/cloudflare/ai/issues/501. Per-call values from
* `providerOptions["workers-ai"]` override settings.
*
* `reasoning_effort: null` is a valid value ("disable reasoning"), so we
* check `!== undefined` rather than truthiness.
*/
private buildRunInputs;
/**
* Get passthrough options for binding.run() from settings.
*
* `reasoning_effort` and `chat_template_kwargs` are explicitly excluded
* here — they belong on the `inputs` object (see `buildRunInputs`), not on
* the `options` (3rd) arg of binding.run() or the REST query string.
*/
private getRunOptions;
/**
* Extract reasoning, text, and tool calls from a non-streaming response.
*
* Shared by `doGenerate` and `doStream`'s graceful-degradation branch (the
* path gpt-oss falls through, since it doesn't support `/ai/run/` streaming
* and is retried non-streaming). When a forced tool call was leaked into
* text content (gpt-oss harmony quirk), it is salvaged into a structured
* tool call and the leaked JSON text is suppressed. A warning is appended in
* place so callers can observe the reinterpretation.
*/
private extractContent;
doGenerate(options: Parameters<LanguageModelV3["doGenerate"]>[0]): Promise<Awaited<ReturnType<LanguageModelV3["doGenerate"]>>>;
doStream(options: Parameters<LanguageModelV3["doStream"]>[0]): Promise<Awaited<ReturnType<LanguageModelV3["doStream"]>>>;
}
//#endregion
//#region src/workersai-image-settings.d.ts
type WorkersAIImageSettings = {
maxImagesPerCall?: number;
};
//#endregion
//#region src/workersai-image-model.d.ts
type WorkersAIImageConfig = {
provider: string;
binding: Ai;
gateway?: GatewayOptions;
};
declare class WorkersAIImageModel implements ImageModelV3 {
readonly modelId: ImageGenerationModels;
readonly settings: WorkersAIImageSettings;
readonly config: WorkersAIImageConfig;
readonly specificationVersion = "v3";
get maxImagesPerCall(): number;
get provider(): string;
constructor(modelId: ImageGenerationModels, settings: WorkersAIImageSettings, config: WorkersAIImageConfig);
doGenerate({
prompt,
n,
size,
aspectRatio,
seed,
abortSignal
}: Parameters<ImageModelV3["doGenerate"]>[0]): Promise<Awaited<ReturnType<ImageModelV3["doGenerate"]>>>;
}
//#endregion
//#region src/workersai-transcription-settings.d.ts
type WorkersAITranscriptionSettings = {
/**
* Language of the audio, as an ISO-639-1 code (e.g. "en", "fr").
* Only supported by Whisper models. Nova-3 detects language automatically.
*/
language?: string;
/**
* Initial prompt / context to guide the transcription.
* Mapped to `initial_prompt` for Whisper models.
*/
prompt?: string;
};
//#endregion
//#region src/utils.d.ts
/**
* Parameters for configuring the Cloudflare-based AI runner.
*/
interface CreateRunConfig {
/** Your Cloudflare account identifier. */
accountId: string;
/** Cloudflare API token/key with appropriate permissions. */
apiKey: string;
/** Custom fetch implementation for intercepting requests. */
fetch?: typeof globalThis.fetch;
}
//#endregion
//#region src/workersai-transcription-model.d.ts
type WorkersAITranscriptionConfig = {
provider: string;
binding: Ai;
gateway?: GatewayOptions;
/**
* Whether the binding is a real `env.AI` binding (true) or a REST shim (false).
* Nova-3 uses different upload paths depending on this.
*/
isBinding: boolean;
/**
* REST credentials, only set when `isBinding` is false.
* Needed for Nova-3 which requires binary upload, bypassing the JSON-based REST shim.
*/
credentials?: CreateRunConfig;
};
/**
* Workers AI transcription model implementing the AI SDK's `TranscriptionModelV3` interface.
*
* Supports:
* - Whisper models (`@cf/openai/whisper`, `whisper-tiny-en`, `whisper-large-v3-turbo`)
* - Deepgram Nova-3 (`@cf/deepgram/nova-3`) — uses a different input/output format
*/
declare class WorkersAITranscriptionModel implements TranscriptionModelV3 {
readonly modelId: TranscriptionModels;
readonly settings: WorkersAITranscriptionSettings;
readonly config: WorkersAITranscriptionConfig;
readonly specificationVersion = "v3";
get provider(): string;
constructor(modelId: TranscriptionModels, settings: WorkersAITranscriptionSettings, config: WorkersAITranscriptionConfig);
doGenerate(options: Parameters<TranscriptionModelV3["doGenerate"]>[0]): Promise<Awaited<ReturnType<TranscriptionModelV3["doGenerate"]>>>;
private runWhisper;
private normalizeWhisperResponse;
private runNova3;
private normalizeNova3Response;
}
//#endregion
//#region src/workersai-speech-settings.d.ts
type WorkersAISpeechSettings = {};
//#endregion
//#region src/workersai-speech-model.d.ts
type WorkersAISpeechConfig = {
provider: string;
binding: Ai;
gateway?: GatewayOptions;
};
/**
* Workers AI speech (text-to-speech) model implementing the AI SDK's `SpeechModelV3` interface.
*
* Currently supports Deepgram Aura-1 (`@cf/deepgram/aura-1`).
* The model accepts `{ text, voice?, speed? }` and returns raw audio bytes.
*/
declare class WorkersAISpeechModel implements SpeechModelV3 {
readonly modelId: SpeechModels;
readonly settings: WorkersAISpeechSettings;
readonly config: WorkersAISpeechConfig;
readonly specificationVersion = "v3";
get provider(): string;
constructor(modelId: SpeechModels, settings: WorkersAISpeechSettings, config: WorkersAISpeechConfig);
doGenerate(options: Parameters<SpeechModelV3["doGenerate"]>[0]): Promise<Awaited<ReturnType<SpeechModelV3["doGenerate"]>>>;
}
//#endregion
//#region src/workersai-reranking-settings.d.ts
type WorkersAIRerankingSettings = {};
//#endregion
//#region src/workersai-reranking-model.d.ts
type WorkersAIRerankingConfig = {
provider: string;
binding: Ai;
gateway?: GatewayOptions;
};
/**
* Workers AI reranking model implementing the AI SDK's `RerankingModelV3` interface.
*
* Supports BGE reranker models (`@cf/baai/bge-reranker-base`, `bge-reranker-v2-m3`).
*
* Workers AI reranking API:
* - Input: `{ query, contexts: [{ text }], top_k? }`
* - Output: `{ response: [{ id, score }] }`
*/
declare class WorkersAIRerankingModel implements RerankingModelV3 {
readonly modelId: RerankingModels;
readonly settings: WorkersAIRerankingSettings;
readonly config: WorkersAIRerankingConfig;
readonly specificationVersion = "v3";
get provider(): string;
constructor(modelId: RerankingModels, settings: WorkersAIRerankingSettings, config: WorkersAIRerankingConfig);
doRerank(options: Parameters<RerankingModelV3["doRerank"]>[0]): Promise<Awaited<ReturnType<RerankingModelV3["doRerank"]>>>;
}
//#endregion
//#region src/autorag-chat-language-model.d.ts
/**
* @deprecated Use `AISearchChatLanguageModel` instead. AutoRAG has been renamed to AI Search.
* @see https://developers.cloudflare.com/ai-search/
*/
declare class AutoRAGChatLanguageModel extends AISearchChatLanguageModel {}
//#endregion
//#region src/autorag-chat-settings.d.ts
/**
* @deprecated Use `AISearchChatSettings` instead. AutoRAG has been renamed to AI Search.
* @see https://developers.cloudflare.com/ai-search/
*/
type AutoRAGChatSettings = AISearchChatSettings;
//#endregion
//#region src/index.d.ts
type WorkersAISettings = ({
/**
* Provide a Cloudflare AI binding.
*/
binding: Ai;
/**
* Credentials must be absent when a binding is given.
*/
accountId?: never;
apiKey?: never;
} | {
/**
* Provide Cloudflare API credentials directly. Must be used if a binding is not specified.
*/
accountId: string;
apiKey: string;
/**
* Both binding must be absent if credentials are used directly.
*/
binding?: never;
/**
* Custom fetch implementation. You can use it as a middleware to
* intercept requests, or to provide a custom fetch implementation
* for e.g. testing. Only available in credentials mode.
*/
fetch?: typeof globalThis.fetch;
}) & {
/**
* Optionally specify a gateway. For third-party catalog routing (see
* `providers`) this defaults to the account's `"default"` gateway when unset.
*/
gateway?: GatewayOptions;
/**
* Provider plugins that enable routing third-party catalog models
* (e.g. `"openai/gpt-5-mini"`) through AI Gateway. Supply them from the
* sub-path modules, e.g. `import { openai } from "workers-ai-provider/openai"`.
*
* When set, calling the provider with a `"<provider>/<model>"` slug (anything
* that is not a `@cf/...` Workers AI model id) is automatically dispatched
* through the {@link createGatewayDelegate | gateway delegate}. Leaving this
* unset preserves the exact prior behavior — only Workers AI models are built.
*
* @experimental The gateway delegate is an experimental surface.
*/
providers?: ProviderPlugin[];
/**
* Default resume behavior for gateway-routed catalog models. Defaults to
* `true`. Overridable per call. Only relevant when `providers` is set.
*/
resume?: boolean;
/**
* Default resume-expiry policy for gateway-routed catalog models (run path).
* Defaults to `"error"`. Only relevant when `providers` is set.
*/
onResumeExpired?: ResumeExpiredPolicy;
};
/**
* True when a literal model id is a `"<provider>/<model>"` AI Gateway catalog
* slug rather than a `@cf/...` Workers AI id. Bare `string` (a non-literal,
* e.g. a variable) resolves to `false` so the common path keeps chat settings.
*/
type IsCatalogSlug<M extends string> = string extends M ? false : M extends `@${string}` ? false : M extends `dynamic/${string}` ? false : M extends `${string}/${string}` ? true : false;
type IsDynamicRoute<M extends string> = string extends M ? false : M extends `dynamic/${string}` ? true : false;
/**
* Picks the per-model settings type from the (captured) literal model id:
* `DelegateCallOptions` for catalog slugs, `WorkersAIChatSettings` otherwise.
* This is what lets `workersai("openai/gpt-5", { … })` autocomplete delegate
* options while `workersai("@cf/…", { … })` autocompletes chat settings.
*/
type ModelSettings<M extends string> = IsCatalogSlug<M> extends true ? DelegateCallOptions : IsDynamicRoute<M> extends true ? DelegateCallOptions | WorkersAIChatSettings : WorkersAIChatSettings;
interface WorkersAI {
<M extends string>(modelId: M | KnownTextGenerationModels, settings?: ModelSettings<M>): WorkersAIChatLanguageModel;
/**
* Creates a model for text generation. Accepts a `@cf/...` Workers AI id, or
* a `"<provider>/<model>"` catalog slug when `providers` is configured.
**/
chat<M extends string>(modelId: M | KnownTextGenerationModels, settings?: ModelSettings<M>): WorkersAIChatLanguageModel;
embedding(modelId: EmbeddingModels, settings?: WorkersAIEmbeddingSettings): WorkersAIEmbeddingModel;
textEmbedding(modelId: EmbeddingModels, settings?: WorkersAIEmbeddingSettings): WorkersAIEmbeddingModel;
textEmbeddingModel(modelId: EmbeddingModels, settings?: WorkersAIEmbeddingSettings): WorkersAIEmbeddingModel;
/**
* Creates a model for image generation.
**/
image(modelId: ImageGenerationModels, settings?: WorkersAIImageSettings): WorkersAIImageModel;
imageModel(modelId: ImageGenerationModels, settings?: WorkersAIImageSettings): WorkersAIImageModel;
/**
* Creates a model for speech-to-text transcription.
**/
transcription(modelId: TranscriptionModels, settings?: WorkersAITranscriptionSettings): WorkersAITranscriptionModel;
transcriptionModel(modelId: TranscriptionModels, settings?: WorkersAITranscriptionSettings): WorkersAITranscriptionModel;
/**
* Creates a model for text-to-speech synthesis.
**/
speech(modelId: SpeechModels, settings?: WorkersAISpeechSettings): WorkersAISpeechModel;
speechModel(modelId: SpeechModels, settings?: WorkersAISpeechSettings): WorkersAISpeechModel;
/**
* Creates a model for document reranking.
**/
reranking(modelId: RerankingModels, settings?: WorkersAIRerankingSettings): WorkersAIRerankingModel;
rerankingModel(modelId: RerankingModels, settings?: WorkersAIRerankingSettings): WorkersAIRerankingModel;
}
/**
* Create a Workers AI provider instance.
*/
declare function createWorkersAI(options: WorkersAISettings): WorkersAI;
type AISearchSettings = {
binding: AutoRAG;
};
interface AISearchProvider {
(settings?: AISearchChatSettings): AISearchChatLanguageModel;
/**
* Creates a model for text generation.
**/
chat(settings?: AISearchChatSettings): AISearchChatLanguageModel;
}
/**
* Create an AI Search provider instance.
*
* AI Search (formerly AutoRAG) is Cloudflare's managed search service.
* @see https://developers.cloudflare.com/ai-search/
*/
declare function createAISearch(options: AISearchSettings, /** @internal */
providerName?: string): AISearchProvider;
/**
* @deprecated Use `AISearchSettings` instead. AutoRAG has been renamed to AI Search.
* @see https://developers.cloudflare.com/ai-search/
*/
type AutoRAGSettings = AISearchSettings;
/**
* @deprecated Use `AISearchProvider` instead. AutoRAG has been renamed to AI Search.
* @see https://developers.cloudflare.com/ai-search/
*/
type AutoRAGProvider = AISearchProvider;
/**
* @deprecated Use `createAISearch` instead. AutoRAG has been renamed to AI Search.
* @see https://developers.cloudflare.com/ai-search/
*/
declare function createAutoRAG(options: AISearchSettings): AISearchProvider;
//#endregion
export { AISearchChatLanguageModel, type AISearchChatSettings, AISearchProvider, AISearchSettings, AutoRAGChatLanguageModel, type AutoRAGChatSettings, AutoRAGProvider, AutoRAGSettings, type Billing, type DelegateCallOptions, type DispatchInfo, type FallbackAttempt, type FallbackLeg, type FallbackOptions, GATEWAY_PROVIDERS, GatewayDelegateError, type GatewayErrorCode, type GatewayErrorContext, type GatewayFetchConfig, type GatewayProviderInfo, type ParsedSlug, type ProviderPlugin, type ResumableStreamOptions, type ResumeExpiredPolicy, type Transport, type WireFormat, WorkersAI, WorkersAIFallbackError, WorkersAIGatewayError, WorkersAIRerankingModel, type WorkersAIRerankingSettings, WorkersAISettings, WorkersAISpeechModel, type WorkersAISpeechSettings, WorkersAITranscriptionModel, type WorkersAITranscriptionSettings, createAISearch, createAutoRAG, createClientFallbackModel, createGatewayFetch, createGatewayProvider, createResumableStream, createWorkersAI, detectProviderByUrl, findProviderBySlug, parseSlug, selectTransport, wireableProviders };
//# sourceMappingURL=index.d.mts.map