workers-ai-provider 3.3.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/dist/anthropic.d.mts +1 -1
- package/dist/{gateway-delegate-BAALxuBO.d.mts → gateway-delegate-CAX7trdL.d.mts} +21 -10
- package/dist/{gateway-provider-BjPLZLob.mjs → gateway-provider-BIZ2bimW.mjs} +4 -4
- package/dist/gateway-provider-BIZ2bimW.mjs.map +1 -0
- package/dist/gateway-provider.mjs +1 -1
- package/dist/google.d.mts +1 -1
- package/dist/google.mjs +2 -2
- package/dist/google.mjs.map +1 -1
- package/dist/index.d.mts +33 -28
- package/dist/index.mjs +106 -44
- package/dist/index.mjs.map +1 -1
- package/dist/openai.d.mts +4 -3
- package/dist/openai.mjs +3 -2
- package/dist/openai.mjs.map +1 -1
- package/package.json +11 -11
- package/src/aisearch-chat-language-model.ts +10 -10
- package/src/client-fallback.ts +11 -11
- package/src/convert-to-workersai-chat-messages.ts +69 -30
- package/src/gateway-delegate.ts +40 -15
- package/src/google.ts +2 -4
- package/src/index.ts +45 -8
- package/src/map-workersai-finish-reason.ts +2 -2
- package/src/map-workersai-usage.ts +4 -4
- package/src/openai.ts +3 -2
- package/src/streaming.ts +18 -18
- package/src/utils.ts +8 -8
- package/src/workersai-chat-language-model.ts +64 -14
- package/src/workersai-embedding-model.ts +6 -6
- package/src/workersai-image-model.ts +6 -6
- package/src/workersai-reranking-model.ts +9 -9
- package/src/workersai-speech-model.ts +7 -7
- package/src/workersai-transcription-model.ts +11 -11
- package/dist/gateway-provider-BjPLZLob.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as GatewayDelegateError, S as headersToObject, _ as detectProviderByUrl, a as WORKERS_AI_ERROR_CODE_TO_STATUS, b as asText, c as parseWorkersAIErrorCode, d as isForcedToolChoice, f as normalizeMessagesForBinding$1, g as GATEWAY_PROVIDERS, h as createResumableStream, i as WorkersAIGatewayError, l as SSEDecoder, m as processText, n as createGatewayProvider, o as isAbortError, p as parseLeakedToolCalls$1, r as WorkersAIFallbackError, s as messageOf, t as createGatewayFetch, u as getToolNames, v as findProviderBySlug, w as _defineProperty, x as buildGatewayEntry, y as wireableProviders } from "./gateway-provider-
|
|
1
|
+
import { C as GatewayDelegateError, S as headersToObject, _ as detectProviderByUrl, a as WORKERS_AI_ERROR_CODE_TO_STATUS, b as asText, c as parseWorkersAIErrorCode, d as isForcedToolChoice, f as normalizeMessagesForBinding$1, g as GATEWAY_PROVIDERS, h as createResumableStream, i as WorkersAIGatewayError, l as SSEDecoder, m as processText, n as createGatewayProvider, o as isAbortError, p as parseLeakedToolCalls$1, r as WorkersAIFallbackError, s as messageOf, t as createGatewayFetch, u as getToolNames, v as findProviderBySlug, w as _defineProperty, x as buildGatewayEntry, y as wireableProviders } from "./gateway-provider-BIZ2bimW.mjs";
|
|
2
2
|
import { APICallError, TooManyEmbeddingValuesForCallError, UnsupportedFunctionalityError } from "@ai-sdk/provider";
|
|
3
3
|
import { generateId } from "ai";
|
|
4
4
|
//#region src/workersai-error.ts
|
|
@@ -294,7 +294,7 @@ function processToolCalls(output) {
|
|
|
294
294
|
*
|
|
295
295
|
* The recovery logic (which JSON shapes count as a leaked call) lives in
|
|
296
296
|
* `@cloudflare/gateway-core`; this wrapper only layers the framework id on each
|
|
297
|
-
* neutral result so the existing `
|
|
297
|
+
* neutral result so the existing `LanguageModelV4ToolCall` shape is preserved.
|
|
298
298
|
*/
|
|
299
299
|
function parseLeakedToolCalls(text, knownToolNames) {
|
|
300
300
|
return parseLeakedToolCalls$1(text, knownToolNames).map((call) => ({
|
|
@@ -341,28 +341,41 @@ function salvageToolCallsFromText(output, context) {
|
|
|
341
341
|
//#endregion
|
|
342
342
|
//#region src/convert-to-workersai-chat-messages.ts
|
|
343
343
|
/**
|
|
344
|
-
* Normalise
|
|
344
|
+
* Normalise a tagged `SharedV4FileData` value to a Uint8Array.
|
|
345
345
|
*
|
|
346
346
|
* Handles:
|
|
347
|
-
* -
|
|
348
|
-
*
|
|
349
|
-
* -
|
|
347
|
+
* - { type: 'data' } → Uint8Array returned as-is; string decoded from
|
|
348
|
+
* base64 (with or without data-URL prefix)
|
|
349
|
+
* - { type: 'url' } → not supported (Workers AI needs raw bytes, not a reference)
|
|
350
|
+
* - { type: 'reference' } → not supported (Workers AI has no file store to resolve it)
|
|
351
|
+
* - { type: 'text' } → not supported for image parts
|
|
350
352
|
*/
|
|
351
|
-
function toUint8Array$2(
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
if (
|
|
353
|
+
function toUint8Array$2(fileData) {
|
|
354
|
+
switch (fileData.type) {
|
|
355
|
+
case "data": {
|
|
356
|
+
const data = fileData.data;
|
|
357
|
+
if (data instanceof Uint8Array) return data;
|
|
358
|
+
let base64 = data;
|
|
359
|
+
if (base64.startsWith("data:")) {
|
|
360
|
+
const commaIndex = base64.indexOf(",");
|
|
361
|
+
if (commaIndex >= 0) base64 = base64.slice(commaIndex + 1);
|
|
362
|
+
}
|
|
363
|
+
const binaryString = atob(base64);
|
|
364
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
365
|
+
for (let i = 0; i < binaryString.length; i++) bytes[i] = binaryString.charCodeAt(i);
|
|
366
|
+
return bytes;
|
|
358
367
|
}
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
368
|
+
case "url": throw new Error("URL image sources are not supported by Workers AI. Provide image data as a Uint8Array or base64 string instead.");
|
|
369
|
+
case "reference": throw new UnsupportedFunctionalityError({
|
|
370
|
+
functionality: "file-part-provider-reference",
|
|
371
|
+
message: "Provider file references are not supported by Workers AI. Provide image data as a Uint8Array or base64 string instead."
|
|
372
|
+
});
|
|
373
|
+
case "text": throw new UnsupportedFunctionalityError({
|
|
374
|
+
functionality: "file-part-inline-text",
|
|
375
|
+
message: "Inline text file parts are not supported by Workers AI chat. Pass text as a regular text part instead."
|
|
376
|
+
});
|
|
377
|
+
default: throw new Error(`Unsupported file data type: ${fileData.type}`);
|
|
363
378
|
}
|
|
364
|
-
if (data instanceof URL) throw new Error("URL image sources are not supported by Workers AI. Provide image data as a Uint8Array or base64 string instead.");
|
|
365
|
-
return null;
|
|
366
379
|
}
|
|
367
380
|
function assertImageMediaType(mediaType) {
|
|
368
381
|
if (!mediaType) throw new UnsupportedFunctionalityError({
|
|
@@ -445,6 +458,8 @@ function convertToWorkersAIChatMessages(prompt) {
|
|
|
445
458
|
reasoning += part.text;
|
|
446
459
|
break;
|
|
447
460
|
case "file": break;
|
|
461
|
+
case "reasoning-file": break;
|
|
462
|
+
case "custom": break;
|
|
448
463
|
case "tool-call":
|
|
449
464
|
toolCalls.push({
|
|
450
465
|
function: {
|
|
@@ -511,7 +526,7 @@ function convertToWorkersAIChatMessages(prompt) {
|
|
|
511
526
|
//#endregion
|
|
512
527
|
//#region src/map-workersai-usage.ts
|
|
513
528
|
/**
|
|
514
|
-
* Map Workers AI usage data to the AI SDK
|
|
529
|
+
* Map Workers AI usage data to the AI SDK v4 usage format.
|
|
515
530
|
* Accepts any object that may have a `usage` property with token counts.
|
|
516
531
|
*
|
|
517
532
|
* Workers AI mirrors the OpenAI usage shape, including
|
|
@@ -595,7 +610,7 @@ function mapWorkersAIFinishReason(finishReasonOrResponse) {
|
|
|
595
610
|
//#endregion
|
|
596
611
|
//#region src/streaming.ts
|
|
597
612
|
/**
|
|
598
|
-
* Prepend a stream-start event to an existing
|
|
613
|
+
* Prepend a stream-start event to an existing LanguageModelV4 stream.
|
|
599
614
|
* Uses pipeThrough for proper backpressure and error propagation.
|
|
600
615
|
*/
|
|
601
616
|
function prependStreamStart(source, warnings) {
|
|
@@ -629,7 +644,7 @@ function isNullFinalizationChunk(tc) {
|
|
|
629
644
|
return !(tc.id ?? null) && !name && (!args || args === "");
|
|
630
645
|
}
|
|
631
646
|
/**
|
|
632
|
-
* Maps a Workers AI SSE stream into AI SDK
|
|
647
|
+
* Maps a Workers AI SSE stream into AI SDK LanguageModelV4StreamPart events.
|
|
633
648
|
*
|
|
634
649
|
* Uses a TransformStream pipeline for proper backpressure — chunks are emitted
|
|
635
650
|
* one at a time as the downstream consumer pulls, not buffered eagerly.
|
|
@@ -949,7 +964,7 @@ function getMappedStream(response, salvageContext) {
|
|
|
949
964
|
//#region src/aisearch-chat-language-model.ts
|
|
950
965
|
var AISearchChatLanguageModel = class {
|
|
951
966
|
constructor(modelId, settings, config) {
|
|
952
|
-
_defineProperty(this, "specificationVersion", "
|
|
967
|
+
_defineProperty(this, "specificationVersion", "v4");
|
|
953
968
|
_defineProperty(this, "defaultObjectGenerationMode", "json");
|
|
954
969
|
_defineProperty(this, "supportedUrls", {});
|
|
955
970
|
_defineProperty(this, "modelId", void 0);
|
|
@@ -1042,7 +1057,7 @@ var WorkersAIEmbeddingModel = class {
|
|
|
1042
1057
|
return this.settings.supportsParallelCalls ?? true;
|
|
1043
1058
|
}
|
|
1044
1059
|
constructor(modelId, settings, config) {
|
|
1045
|
-
_defineProperty(this, "specificationVersion", "
|
|
1060
|
+
_defineProperty(this, "specificationVersion", "v4");
|
|
1046
1061
|
_defineProperty(this, "modelId", void 0);
|
|
1047
1062
|
_defineProperty(this, "config", void 0);
|
|
1048
1063
|
_defineProperty(this, "settings", void 0);
|
|
@@ -1079,9 +1094,26 @@ var WorkersAIEmbeddingModel = class {
|
|
|
1079
1094
|
};
|
|
1080
1095
|
//#endregion
|
|
1081
1096
|
//#region src/workersai-chat-language-model.ts
|
|
1097
|
+
/**
|
|
1098
|
+
* Map the unified `reasoning` call option (spec v4) to Workers AI's
|
|
1099
|
+
* `reasoning_effort`. Workers AI accepts "low" | "medium" | "high" | null
|
|
1100
|
+
* (null disables reasoning), so `minimal` and `xhigh` are clamped to the
|
|
1101
|
+
* nearest supported effort. `provider-default` (and absence) returns
|
|
1102
|
+
* undefined so the settings-level `reasoning_effort` still applies.
|
|
1103
|
+
*/
|
|
1104
|
+
function mapUnifiedReasoningEffort(reasoning) {
|
|
1105
|
+
switch (reasoning) {
|
|
1106
|
+
case void 0:
|
|
1107
|
+
case "provider-default": return;
|
|
1108
|
+
case "none": return null;
|
|
1109
|
+
case "minimal": return "low";
|
|
1110
|
+
case "xhigh": return "high";
|
|
1111
|
+
default: return reasoning;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1082
1114
|
var WorkersAIChatLanguageModel = class {
|
|
1083
1115
|
constructor(modelId, settings, config) {
|
|
1084
|
-
_defineProperty(this, "specificationVersion", "
|
|
1116
|
+
_defineProperty(this, "specificationVersion", "v4");
|
|
1085
1117
|
_defineProperty(this, "defaultObjectGenerationMode", "json");
|
|
1086
1118
|
_defineProperty(this, "supportedUrls", {});
|
|
1087
1119
|
_defineProperty(this, "modelId", void 0);
|
|
@@ -1094,7 +1126,7 @@ var WorkersAIChatLanguageModel = class {
|
|
|
1094
1126
|
get provider() {
|
|
1095
1127
|
return this.config.provider;
|
|
1096
1128
|
}
|
|
1097
|
-
getArgs({ responseFormat, tools, toolChoice, maxOutputTokens, temperature, topP, frequencyPenalty, presencePenalty, seed }) {
|
|
1129
|
+
getArgs({ responseFormat, tools, toolChoice, maxOutputTokens, temperature, topP, frequencyPenalty, presencePenalty, seed, reasoning }) {
|
|
1098
1130
|
const type = responseFormat?.type ?? "text";
|
|
1099
1131
|
const warnings = [];
|
|
1100
1132
|
if (frequencyPenalty != null) warnings.push({
|
|
@@ -1105,6 +1137,11 @@ var WorkersAIChatLanguageModel = class {
|
|
|
1105
1137
|
feature: "presencePenalty",
|
|
1106
1138
|
type: "unsupported"
|
|
1107
1139
|
});
|
|
1140
|
+
if (reasoning === "minimal" || reasoning === "xhigh") warnings.push({
|
|
1141
|
+
type: "compatibility",
|
|
1142
|
+
feature: "reasoning",
|
|
1143
|
+
details: `Workers AI supports reasoning_effort "low" | "medium" | "high"; "${reasoning}" was mapped to "${reasoning === "minimal" ? "low" : "high"}".`
|
|
1144
|
+
});
|
|
1108
1145
|
const baseArgs = {
|
|
1109
1146
|
max_tokens: maxOutputTokens,
|
|
1110
1147
|
model: this.modelId,
|
|
@@ -1157,11 +1194,17 @@ var WorkersAIChatLanguageModel = class {
|
|
|
1157
1194
|
*
|
|
1158
1195
|
* `reasoning_effort: null` is a valid value ("disable reasoning"), so we
|
|
1159
1196
|
* check `!== undefined` rather than truthiness.
|
|
1197
|
+
*
|
|
1198
|
+
* The unified `reasoning` call option (spec v4) is mapped onto
|
|
1199
|
+
* `reasoning_effort` between the two: an explicit per-call
|
|
1200
|
+
* `providerOptions["workers-ai"].reasoning_effort` wins, then the unified
|
|
1201
|
+
* option, then settings.
|
|
1160
1202
|
*/
|
|
1161
1203
|
buildRunInputs(args, messages, options) {
|
|
1162
1204
|
const rawPerCall = options?.providerOptions?.["workers-ai"];
|
|
1163
1205
|
const perCall = rawPerCall !== null && typeof rawPerCall === "object" && !Array.isArray(rawPerCall) ? rawPerCall : {};
|
|
1164
|
-
const
|
|
1206
|
+
const unifiedReasoningEffort = mapUnifiedReasoningEffort(options?.reasoning);
|
|
1207
|
+
const reasoningEffort = "reasoning_effort" in perCall ? perCall.reasoning_effort : unifiedReasoningEffort !== void 0 ? unifiedReasoningEffort : this.settings.reasoning_effort;
|
|
1165
1208
|
const chatTemplateKwargs = "chat_template_kwargs" in perCall ? perCall.chat_template_kwargs : this.settings.chat_template_kwargs;
|
|
1166
1209
|
return {
|
|
1167
1210
|
max_tokens: args.max_tokens,
|
|
@@ -1230,7 +1273,10 @@ var WorkersAIChatLanguageModel = class {
|
|
|
1230
1273
|
async doGenerate(options) {
|
|
1231
1274
|
const { args, warnings } = this.getArgs(options);
|
|
1232
1275
|
const { messages } = convertToWorkersAIChatMessages(options.prompt);
|
|
1233
|
-
const inputs = this.buildRunInputs(args, messages, {
|
|
1276
|
+
const inputs = this.buildRunInputs(args, messages, {
|
|
1277
|
+
providerOptions: options.providerOptions,
|
|
1278
|
+
reasoning: options.reasoning
|
|
1279
|
+
});
|
|
1234
1280
|
const runOptions = this.getRunOptions();
|
|
1235
1281
|
let output;
|
|
1236
1282
|
try {
|
|
@@ -1269,7 +1315,8 @@ var WorkersAIChatLanguageModel = class {
|
|
|
1269
1315
|
const { messages } = convertToWorkersAIChatMessages(options.prompt);
|
|
1270
1316
|
const inputs = this.buildRunInputs(args, messages, {
|
|
1271
1317
|
stream: true,
|
|
1272
|
-
providerOptions: options.providerOptions
|
|
1318
|
+
providerOptions: options.providerOptions,
|
|
1319
|
+
reasoning: options.reasoning
|
|
1273
1320
|
});
|
|
1274
1321
|
const runOptions = this.getRunOptions();
|
|
1275
1322
|
let response;
|
|
@@ -1352,7 +1399,7 @@ var WorkersAIImageModel = class {
|
|
|
1352
1399
|
this.modelId = modelId;
|
|
1353
1400
|
this.settings = settings;
|
|
1354
1401
|
this.config = config;
|
|
1355
|
-
_defineProperty(this, "specificationVersion", "
|
|
1402
|
+
_defineProperty(this, "specificationVersion", "v4");
|
|
1356
1403
|
}
|
|
1357
1404
|
async doGenerate({ prompt, n, size, aspectRatio, seed, abortSignal }) {
|
|
1358
1405
|
const { width, height } = getDimensionsFromSizeString(size);
|
|
@@ -1448,7 +1495,7 @@ async function toUint8Array$1(output) {
|
|
|
1448
1495
|
//#endregion
|
|
1449
1496
|
//#region src/workersai-transcription-model.ts
|
|
1450
1497
|
/**
|
|
1451
|
-
* Workers AI transcription model implementing the AI SDK's `
|
|
1498
|
+
* Workers AI transcription model implementing the AI SDK's `TranscriptionModelV4` interface.
|
|
1452
1499
|
*
|
|
1453
1500
|
* Supports:
|
|
1454
1501
|
* - Whisper models (`@cf/openai/whisper`, `whisper-tiny-en`, `whisper-large-v3-turbo`)
|
|
@@ -1462,7 +1509,7 @@ var WorkersAITranscriptionModel = class {
|
|
|
1462
1509
|
this.modelId = modelId;
|
|
1463
1510
|
this.settings = settings;
|
|
1464
1511
|
this.config = config;
|
|
1465
|
-
_defineProperty(this, "specificationVersion", "
|
|
1512
|
+
_defineProperty(this, "specificationVersion", "v4");
|
|
1466
1513
|
}
|
|
1467
1514
|
async doGenerate(options) {
|
|
1468
1515
|
const { audio, mediaType, abortSignal } = options;
|
|
@@ -1561,7 +1608,7 @@ function uint8ArrayToBase64(bytes) {
|
|
|
1561
1608
|
//#endregion
|
|
1562
1609
|
//#region src/workersai-speech-model.ts
|
|
1563
1610
|
/**
|
|
1564
|
-
* Workers AI speech (text-to-speech) model implementing the AI SDK's `
|
|
1611
|
+
* Workers AI speech (text-to-speech) model implementing the AI SDK's `SpeechModelV4` interface.
|
|
1565
1612
|
*
|
|
1566
1613
|
* Currently supports Deepgram Aura-1 (`@cf/deepgram/aura-1`).
|
|
1567
1614
|
* The model accepts `{ text, voice?, speed? }` and returns raw audio bytes.
|
|
@@ -1574,7 +1621,7 @@ var WorkersAISpeechModel = class {
|
|
|
1574
1621
|
this.modelId = modelId;
|
|
1575
1622
|
this.settings = settings;
|
|
1576
1623
|
this.config = config;
|
|
1577
|
-
_defineProperty(this, "specificationVersion", "
|
|
1624
|
+
_defineProperty(this, "specificationVersion", "v4");
|
|
1578
1625
|
}
|
|
1579
1626
|
async doGenerate(options) {
|
|
1580
1627
|
const { text, voice, speed, abortSignal } = options;
|
|
@@ -1662,7 +1709,7 @@ async function toUint8Array(output) {
|
|
|
1662
1709
|
//#endregion
|
|
1663
1710
|
//#region src/workersai-reranking-model.ts
|
|
1664
1711
|
/**
|
|
1665
|
-
* Workers AI reranking model implementing the AI SDK's `
|
|
1712
|
+
* Workers AI reranking model implementing the AI SDK's `RerankingModelV4` interface.
|
|
1666
1713
|
*
|
|
1667
1714
|
* Supports BGE reranker models (`@cf/baai/bge-reranker-base`, `bge-reranker-v2-m3`).
|
|
1668
1715
|
*
|
|
@@ -1678,7 +1725,7 @@ var WorkersAIRerankingModel = class {
|
|
|
1678
1725
|
this.modelId = modelId;
|
|
1679
1726
|
this.settings = settings;
|
|
1680
1727
|
this.config = config;
|
|
1681
|
-
_defineProperty(this, "specificationVersion", "
|
|
1728
|
+
_defineProperty(this, "specificationVersion", "v4");
|
|
1682
1729
|
}
|
|
1683
1730
|
async doRerank(options) {
|
|
1684
1731
|
const { documents, query, topN, abortSignal } = options;
|
|
@@ -1773,7 +1820,7 @@ function createClientFallbackModel(legs) {
|
|
|
1773
1820
|
throw new WorkersAIFallbackError(attempts);
|
|
1774
1821
|
}
|
|
1775
1822
|
return {
|
|
1776
|
-
specificationVersion: "
|
|
1823
|
+
specificationVersion: "v4",
|
|
1777
1824
|
provider: primary.provider,
|
|
1778
1825
|
modelId: primary.modelId,
|
|
1779
1826
|
supportedUrls: primary.supportedUrls,
|
|
@@ -1825,7 +1872,7 @@ function selectTransport(opts, resumeExplicitlyTrue, runCatalog = true, gatewayA
|
|
|
1825
1872
|
const wantsCaching = opts.cacheTtl !== void 0 || opts.skipCache === true;
|
|
1826
1873
|
const gatewayOnly = wantsServerFallback || wantsCaching;
|
|
1827
1874
|
const feature = wantsServerFallback ? "fallback.mode:\"server\"" : "caching (cacheTtl/skipCache)";
|
|
1828
|
-
if (runCatalog && !gatewayAvailable && (opts.transport === "gateway" || gatewayOnly)) throw new GatewayDelegateError("config", `${opts.transport === "gateway" ? "transport:\"gateway\"" : feature} is unavailable: this provider is on the unified run catalog but is not a native gateway provider, so it has no gateway path (no caching, server-side fallback, or transport:"gateway"). Use the default run path, or fallback.mode:"client".`);
|
|
1875
|
+
if (runCatalog && !gatewayAvailable && (opts.transport === "gateway" || opts.byok || gatewayOnly)) throw new GatewayDelegateError("config", `${opts.transport === "gateway" ? "transport:\"gateway\"" : opts.byok ? "byok" : feature} is unavailable: this provider is on the unified run catalog but is not a native gateway provider, so it has no gateway path (no caching, server-side fallback, BYOK, or transport:"gateway"). Use the default run path, or fallback.mode:"client".`);
|
|
1829
1876
|
if (!runCatalog) {
|
|
1830
1877
|
if (opts.transport === "run") throw new GatewayDelegateError("config", "transport:\"run\" is unavailable: this provider is not on the unified-billing run catalog, so it can only be reached through the gateway path (BYOK).");
|
|
1831
1878
|
if (resumeExplicitlyTrue) throw new GatewayDelegateError("config", "resume:true is unavailable: this provider is not on the resumable run catalog (cf-aig-run-id requires the unified-billing run path).");
|
|
@@ -1835,6 +1882,15 @@ function selectTransport(opts, resumeExplicitlyTrue, runCatalog = true, gatewayA
|
|
|
1835
1882
|
warnings
|
|
1836
1883
|
};
|
|
1837
1884
|
}
|
|
1885
|
+
if (opts.byok) {
|
|
1886
|
+
if (opts.transport === "run") throw new GatewayDelegateError("config", "transport:\"run\" cannot forward a BYOK key — BYOK is a gateway-path feature. Drop transport:\"run\" (or set transport:\"gateway\").");
|
|
1887
|
+
if (resumeExplicitlyTrue) throw new GatewayDelegateError("config", "byok cannot provide resume — cf-aig-run-id is only on the unified-billing run path.");
|
|
1888
|
+
return {
|
|
1889
|
+
transport: "gateway",
|
|
1890
|
+
resumeEnabled: false,
|
|
1891
|
+
warnings
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1838
1894
|
if (opts.transport === "run" && gatewayOnly) throw new GatewayDelegateError("config", `transport:"run" cannot satisfy ${feature}: those features are only available on the gateway path. Use the gateway transport, or fallback.mode:"client".`);
|
|
1839
1895
|
if (opts.transport === "gateway" && resumeExplicitlyTrue) throw new GatewayDelegateError("config", "transport:\"gateway\" cannot provide resume — cf-aig-run-id is only on the run path.");
|
|
1840
1896
|
if (gatewayOnly) {
|
|
@@ -2146,7 +2202,7 @@ function makeServerFallbackModel(params) {
|
|
|
2146
2202
|
})[method](options);
|
|
2147
2203
|
};
|
|
2148
2204
|
return {
|
|
2149
|
-
specificationVersion: "
|
|
2205
|
+
specificationVersion: "v4",
|
|
2150
2206
|
provider: refModel.provider,
|
|
2151
2207
|
modelId: refModel.modelId,
|
|
2152
2208
|
supportedUrls: refModel.supportedUrls,
|
|
@@ -2189,8 +2245,11 @@ function createWorkersAI(options) {
|
|
|
2189
2245
|
isBinding
|
|
2190
2246
|
});
|
|
2191
2247
|
const toGatewayOptions = (gateway) => typeof gateway === "string" ? { id: gateway } : gateway;
|
|
2192
|
-
const
|
|
2193
|
-
if (settings.fallback || settings.transport === "gateway" || settings.resume === true || settings.onProgress || settings.onResumeExpired || settings.byok)
|
|
2248
|
+
const createRunPathModel = (modelId, settings = {}, kind) => {
|
|
2249
|
+
if (settings.fallback || settings.transport === "gateway" || settings.resume === true || settings.onProgress || settings.onResumeExpired || settings.byok) {
|
|
2250
|
+
const subject = kind === "dynamic" ? `"${modelId}" is an AI Gateway dynamic route` : `"${modelId}" routes through the bare unified-billing run path because no \`providers\` are configured`;
|
|
2251
|
+
throw new Error(`${subject}. It uses AI.run with OpenAI-compatible chat-completions wire format; fallback, gateway transport, resume, BYOK, and resume callbacks are gateway-delegate features — configure provider plugins to use them (createWorkersAI({ binding: env.AI, providers: [openai] })), and for dynamic routes set caching/fallback on the route or gateway instead of per call.`);
|
|
2252
|
+
}
|
|
2194
2253
|
const gateway = { ...toGatewayOptions(settings.gateway) ?? options.gateway ?? { id: DEFAULT_GATEWAY_ID } };
|
|
2195
2254
|
if (settings.metadata) gateway.metadata = {
|
|
2196
2255
|
...gateway.metadata ?? {},
|
|
@@ -2216,7 +2275,7 @@ function createWorkersAI(options) {
|
|
|
2216
2275
|
delete chatSettings.byok;
|
|
2217
2276
|
const plugin = options.providers?.find((p) => p.wireFormat === DYNAMIC_ROUTE_WIRE_FORMAT);
|
|
2218
2277
|
if (!plugin) {
|
|
2219
|
-
if (options.providers?.length) throw new Error(`"${modelId}" is an AI Gateway dynamic route. Dynamic routes return OpenAI-compatible chat-completions wire format on the AI.run path, so configure the OpenAI provider plugin: import { openai } from "workers-ai-provider/openai"; createWorkersAI({ binding: env.AI, providers: [openai] }).`);
|
|
2278
|
+
if (kind === "dynamic" && options.providers?.length) throw new Error(`"${modelId}" is an AI Gateway dynamic route. Dynamic routes return OpenAI-compatible chat-completions wire format on the AI.run path, so configure the OpenAI provider plugin: import { openai } from "workers-ai-provider/openai"; createWorkersAI({ binding: env.AI, providers: [openai] }).`);
|
|
2220
2279
|
return createChatModel(modelId, chatSettings);
|
|
2221
2280
|
}
|
|
2222
2281
|
const fetchImpl = (async (_input, init) => {
|
|
@@ -2263,8 +2322,11 @@ A gateway defaults to "default" but can be set via \`gateway\`. Otherwise use a
|
|
|
2263
2322
|
};
|
|
2264
2323
|
const isGatewaySlug = (id) => typeof id === "string" && !id.startsWith("@") && !id.startsWith("dynamic/") && id.includes("/");
|
|
2265
2324
|
const buildChat = (modelId, settings) => {
|
|
2266
|
-
if (typeof modelId === "string" && modelId.startsWith("dynamic/")) return
|
|
2267
|
-
if (isGatewaySlug(modelId))
|
|
2325
|
+
if (typeof modelId === "string" && modelId.startsWith("dynamic/")) return createRunPathModel(modelId, settings, "dynamic");
|
|
2326
|
+
if (isGatewaySlug(modelId)) {
|
|
2327
|
+
if (!options.providers?.length) return createRunPathModel(modelId, settings, "catalog");
|
|
2328
|
+
return getDelegate(modelId)(modelId, settings);
|
|
2329
|
+
}
|
|
2268
2330
|
return createChatModel(modelId, settings);
|
|
2269
2331
|
};
|
|
2270
2332
|
const createImageModel = (modelId, settings = {}) => new WorkersAIImageModel(modelId, settings, {
|