agents 0.28.0 → 0.29.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.
Files changed (121) hide show
  1. package/dist/{agent-routing-QDcchcQP.d.ts → agent-routing-CDbpVjYq.d.ts} +18 -8
  2. package/dist/agent-routing.d.ts +1 -1
  3. package/dist/agent-tool-types.d.ts +1 -1
  4. package/dist/{agent-tools-DHL2XI7u.d.ts → agent-tools-C8DH8Yii.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +1 -1
  6. package/dist/{ai-ahruGw7e.d.ts → ai-iXw0uOGj.d.ts} +3 -3
  7. package/dist/{ai-sdk-Bdsf6mSA.js → ai-sdk-DRPh2rRa.js} +218 -132
  8. package/dist/ai-sdk-DRPh2rRa.js.map +1 -0
  9. package/dist/browser/ai.d.ts +1 -1
  10. package/dist/browser/ai.js +2 -2
  11. package/dist/browser/index.d.ts +8 -8
  12. package/dist/browser/index.js +3 -3
  13. package/dist/browser/tools/ai-sdk.d.ts +2 -2
  14. package/dist/browser/tools/ai-sdk.js +1 -1
  15. package/dist/browser/tools/pi.d.ts +1 -1
  16. package/dist/browser/tools/pi.js +3 -3
  17. package/dist/browser/tools/pi.js.map +1 -1
  18. package/dist/browser/tools/tanstack-ai.d.ts +2 -2
  19. package/dist/browser/tools/tanstack-ai.js +1 -1
  20. package/dist/{browser-CEdNlsaD.js → browser-DccPw_wW.js} +130 -79
  21. package/dist/browser-DccPw_wW.js.map +1 -0
  22. package/dist/{browser-D30VlpcA.d.ts → browser-DlXhSAdf.d.ts} +41 -37
  23. package/dist/{browser-tool-4iomavs_.js → browser-tool-B1mhifin.js} +3 -3
  24. package/dist/{browser-tool-4iomavs_.js.map → browser-tool-B1mhifin.js.map} +1 -1
  25. package/dist/{browser-tool-vtrPOV8e.d.ts → browser-tool-Cxjk5sgG.d.ts} +2 -2
  26. package/dist/chat/index.d.ts +143 -71
  27. package/dist/chat/index.js +269 -110
  28. package/dist/chat/index.js.map +1 -1
  29. package/dist/chat-sdk/index.d.ts +1 -1
  30. package/dist/chat-sdk/index.js +1 -1
  31. package/dist/cli.js +33 -33
  32. package/dist/{client-BGIQKJhX.d.ts → client-C27CtRZr.d.ts} +2 -2
  33. package/dist/client.d.ts +1 -1
  34. package/dist/{connector-DEXzVoaY.d.ts → connector-20DJ6p4k.d.ts} +2 -2
  35. package/dist/{connector-CtZylXdk.js → connector-DAXBOIIi.js} +2 -2
  36. package/dist/{connector-CtZylXdk.js.map → connector-DAXBOIIi.js.map} +1 -1
  37. package/dist/experimental/channels/web/index.js +1 -1
  38. package/dist/{handler-stateless-VvrWSAVA.js → handler-stateless-Bly_nSH3.js} +12 -3
  39. package/dist/handler-stateless-Bly_nSH3.js.map +1 -0
  40. package/dist/harness/container/index.js +1 -1
  41. package/dist/harness/container/index.js.map +1 -1
  42. package/dist/harness/opencode/index.d.ts +182 -6
  43. package/dist/harness/opencode/index.js +354 -23
  44. package/dist/harness/opencode/index.js.map +1 -1
  45. package/dist/harness/pi/index.d.ts +13 -5
  46. package/dist/harness/pi/index.js +8 -214
  47. package/dist/harness/pi/index.js.map +1 -1
  48. package/dist/{images-Ce9SCu3X.js → images-xaDv2Fqe.js} +662 -152
  49. package/dist/images-xaDv2Fqe.js.map +1 -0
  50. package/dist/index-DCxk3OSJ.d.ts +378 -0
  51. package/dist/{index-kbSUIer3.d.ts → index-iv9FTXX9.d.ts} +80 -112
  52. package/dist/index.d.ts +1 -1
  53. package/dist/index.js +1 -1
  54. package/dist/{input-schema-D2QAtHZH.js → input-schema-B0Etuo-o.js} +2 -2
  55. package/dist/{input-schema-D2QAtHZH.js.map → input-schema-B0Etuo-o.js.map} +1 -1
  56. package/dist/lifecycle/index.js +1 -1
  57. package/dist/{lifecycle-DGorpAmA.js → lifecycle-ClT4DmF2.js} +11 -3
  58. package/dist/lifecycle-ClT4DmF2.js.map +1 -0
  59. package/dist/mcp/client/index.d.ts +1 -1
  60. package/dist/mcp/index.d.ts +1 -1
  61. package/dist/mcp/index.js +17 -3
  62. package/dist/mcp/index.js.map +1 -1
  63. package/dist/mcp/server/index.js +1 -1
  64. package/dist/models/ai-sdk/index.d.ts +31 -326
  65. package/dist/models/ai-sdk/index.js +1 -1
  66. package/dist/models/opencode/index.d.ts +25 -13
  67. package/dist/models/opencode/index.js +16 -11
  68. package/dist/models/opencode/index.js.map +1 -1
  69. package/dist/models/pi-ai/index.d.ts +17 -13
  70. package/dist/models/pi-ai/index.js +89 -36
  71. package/dist/models/pi-ai/index.js.map +1 -1
  72. package/dist/react.d.ts +2 -2
  73. package/dist/routing/index.d.ts +1 -1
  74. package/dist/serializable.d.ts +1 -1
  75. package/dist/{session-store-DoPY12xM.d.ts → session-store-_IK6dV-w.d.ts} +14 -2
  76. package/dist/{session-store-Do4xkDcf.js → session-store-yvwq1f9x.js} +55 -2
  77. package/dist/session-store-yvwq1f9x.js.map +1 -0
  78. package/dist/{settings-C45hDliX.js → settings-Dk2il2Hf.js} +10 -4
  79. package/dist/settings-Dk2il2Hf.js.map +1 -0
  80. package/dist/skills/index.d.ts +22 -28
  81. package/dist/skills/index.js +183 -143
  82. package/dist/skills/index.js.map +1 -1
  83. package/dist/{src-CQxJFv4l.js → src-6lr7MtM_.js} +3 -3
  84. package/dist/src-6lr7MtM_.js.map +1 -0
  85. package/dist/sub-routing.d.ts +1 -1
  86. package/dist/{tool-cQRkwSZZ.js → tool-DkT_DJBm.js} +2 -2
  87. package/dist/tool-DkT_DJBm.js.map +1 -0
  88. package/dist/transport-CPh7YGiw.d.ts +623 -0
  89. package/dist/voice/index.d.ts +1 -1
  90. package/dist/web/fetch/tools/pi.js +2 -2
  91. package/dist/web/fetch/tools/pi.js.map +1 -1
  92. package/dist/web/search/index.js +1 -1
  93. package/dist/web/search/tools/ai-sdk.js +2 -2
  94. package/dist/web/search/tools/pi.js +3 -3
  95. package/dist/web/search/tools/pi.js.map +1 -1
  96. package/dist/web/search/tools/tanstack-ai.js +2 -2
  97. package/dist/websockets/index.js +1 -1
  98. package/dist/{websockets-C3zy8YR0.js → websockets-CqxnntmE.js} +2 -2
  99. package/dist/{websockets-C3zy8YR0.js.map → websockets-CqxnntmE.js.map} +1 -1
  100. package/dist/workflow-types.d.ts +1 -1
  101. package/dist/workflows.d.ts +1 -1
  102. package/dist/workflows.js +1 -1
  103. package/docs/browse-the-web.md +1 -1
  104. package/docs/chat-agents.md +19 -18
  105. package/docs/harnesses/pi.md +47 -18
  106. package/docs/mcp-client.md +1 -1
  107. package/docs/mcp-servers.md +1 -1
  108. package/docs/models-pi-ai.md +70 -17
  109. package/docs/models.md +219 -152
  110. package/package.json +14 -14
  111. package/dist/ai-sdk-Bdsf6mSA.js.map +0 -1
  112. package/dist/browser-CEdNlsaD.js.map +0 -1
  113. package/dist/handler-stateless-VvrWSAVA.js.map +0 -1
  114. package/dist/images-Ce9SCu3X.js.map +0 -1
  115. package/dist/lifecycle-DGorpAmA.js.map +0 -1
  116. package/dist/session-store-Do4xkDcf.js.map +0 -1
  117. package/dist/settings-C45hDliX.js.map +0 -1
  118. package/dist/settings-NgGwF7Qt.d.ts +0 -331
  119. package/dist/src-CQxJFv4l.js.map +0 -1
  120. package/dist/tool-cQRkwSZZ.js.map +0 -1
  121. package/dist/transport-k2mFrtL8.d.ts +0 -200
@@ -1,42 +1,40 @@
1
1
  import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
2
2
  import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
3
- import { S as isRetryableStatus, _ as isGatewayErrorEnvelope, a as normalizeChatCompletion, b as classifyStatus, f as createTransport$1, g as headersToObject, h as errorFromResponse$1, i as normalizeChatCompletionsStream, m as errorFromGatewayEnvelope$1, n as imageMediaTypeOf, o as prepareChatCompletionsRequest, p as definedHeaders, r as sseDataStream, t as buildImageInput, u as requireGatewayProvider, v as unwrapEnvelope$1, x as isAbortError, y as CloudflareAIError$1 } from "./images-Ce9SCu3X.js";
4
- import { a as parseModelOptions, i as mergeModelOptions, n as PROVIDER_OPTIONS_KEY, o as resolveOptions, r as gatewayLayerOf } from "./settings-C45hDliX.js";
3
+ import { C as isCatalogModelId, S as isRetryableStatus, T as isRunPathLanguageModelId, _ as isGatewayErrorEnvelope, a as normalizeChatCompletion, b as classifyStatus, f as createTransport$1, g as headersToObject, h as errorFromResponse$1, i as normalizeChatCompletionsStream, m as errorFromGatewayEnvelope$1, n as imageMediaTypeOf, o as prepareChatCompletionsRequest, p as definedHeaders, r as sseDataStream, t as buildImageInput, u as requireGatewayProvider, v as unwrapEnvelope$1, w as isDynamicRouteId, x as isAbortError, y as CloudflareAIError$1 } from "./images-xaDv2Fqe.js";
4
+ import { a as parseModelOptions, i as mergeModelOptions, n as PROVIDER_OPTIONS_KEY, o as resolveOptions, r as gatewayLayerOf } from "./settings-Dk2il2Hf.js";
5
5
  import { APICallError, TooManyEmbeddingValuesForCallError } from "@ai-sdk/provider";
6
6
  //#region src/models/ai-sdk/errors.ts
7
- /** The provider packages worth naming when someone passes a vendor id. */
8
- const VENDOR_PACKAGES = {
9
- anthropic: {
10
- call: "anthropic(\"claude-opus-4-8\")",
11
- package: "@ai-sdk/anthropic"
12
- },
13
- google: {
14
- call: "google(\"gemini-3-flash\")",
15
- package: "@ai-sdk/google"
16
- },
17
- openai: {
18
- call: "openai(\"gpt-5-mini\")",
19
- package: "@ai-sdk/openai"
20
- }
21
- };
22
7
  /**
23
- * The one error a bad model id produces. Workers AI ids are the only strings
24
- * this provider knows; a third-party model is a model object built by that
25
- * vendor's own provider package.
8
+ * The error a string that names no model this provider runs produces.
9
+ * Language models take Workers AI ids, AI Gateway catalog ids and dynamic
10
+ * routes; the modality methods take Workers AI ids only.
26
11
  */
27
- function notAWorkersAIId(modelId) {
28
- const vendor = VENDOR_PACKAGES[modelId.split("/")[0] ?? ""];
29
- const advice = vendor === void 0 ? "install its AI SDK provider package and pass the model object, e.g. ai(anthropic(\"claude-opus-4-8\"))" : `install ${vendor.package} and pass the model object: ai(${vendor.call})`;
30
- return /* @__PURE__ */ new TypeError(`"${modelId}" is not a Workers AI model id. Workers AI ids start with "@cf/", and they are the only ids this provider takes: a third-party model goes through its own provider and is only routed by AI Gateway — ${advice}.`);
12
+ function notAModelId(modelId, accepts) {
13
+ return /* @__PURE__ */ new TypeError(accepts === "language" ? `"${modelId}" is not a model id this provider knows. Use a Workers AI id ("@cf/zai-org/glm-4.7-flash"), an AI Gateway catalog id ("<author>/<model>", e.g. "openai/gpt-5.5" or "anthropic/claude-opus-4.8"), or a dynamic route ("dynamic/<route>").` : `"${modelId}" is not a Workers AI model id. The embedding, image, speech, transcription and reranking methods take Workers AI ids, which start with "@cf/".`);
31
14
  }
32
15
  /**
33
- * The gate every string that names a model passes through, wherever it enters
34
- * the module: `ai("…")`, a per-model fallback leg, or a leg read out of the
35
- * per-call `providerOptions.cloudflare` bag. One rule, one message, thrown at
36
- * the line that supplied the id rather than at the request it would have made.
16
+ * The gate for the modality methods — embedding, image, speech,
17
+ * transcription, reranking — and their fallback legs: a Workers AI id and
18
+ * nothing else. Catalog models and dynamic routes are chat models here.
37
19
  */
38
20
  function requireWorkersAIId(modelId) {
39
- if (!modelId.startsWith("@cf/")) throw notAWorkersAIId(modelId);
21
+ if (isDynamicRouteId(modelId)) throw new TypeError(`"${modelId}" is an AI Gateway dynamic route, and a dynamic route is a chat model: it answers in the chat-completions shape. Use it as ai("${modelId}"); the embedding, image, speech, transcription and reranking methods take "@cf/" ids.`);
22
+ if (!modelId.startsWith("@cf/")) throw notAModelId(modelId, "workers-ai");
23
+ return modelId;
24
+ }
25
+ /** Whether a string names a language model: any of the three id kinds. */
26
+ function isLanguageModelId(modelId) {
27
+ return isRunPathLanguageModelId(modelId) || isCatalogModelId(modelId);
28
+ }
29
+ /**
30
+ * The gate every string that names a language model passes through, wherever
31
+ * it enters the module: `ai("…")`, a per-model fallback leg, or a leg read
32
+ * out of the per-call `providerOptions.cloudflare` bag. All three kinds run on
33
+ * `env.AI.run`. Thrown at the line that supplied the id rather than at the
34
+ * request it would have made.
35
+ */
36
+ function requireLanguageModelId(modelId) {
37
+ if (!isLanguageModelId(modelId)) throw notAModelId(modelId, "language");
40
38
  return modelId;
41
39
  }
42
40
  /**
@@ -117,6 +115,19 @@ function fallbackLegs(model, call) {
117
115
  * @experimental This surface is experimental and may change.
118
116
  */
119
117
  function parseCallOptions(providerOptions) {
118
+ const options = parseModelOptions(providerOptions?.[PROVIDER_OPTIONS_KEY]);
119
+ for (const leg of options?.fallback ?? []) requireLanguageModelId(leg);
120
+ return options;
121
+ }
122
+ /**
123
+ * Per-call options for the modality models — embedding, image, speech,
124
+ * transcription, reranking. The same bag as {@link parseCallOptions}, but a
125
+ * fallback leg must be a Workers AI id: a dynamic route answers in the
126
+ * chat-completions shape, which none of those models can read.
127
+ *
128
+ * @experimental This surface is experimental and may change.
129
+ */
130
+ function parseModalityCallOptions(providerOptions) {
120
131
  const options = parseModelOptions(providerOptions?.[PROVIDER_OPTIONS_KEY]);
121
132
  for (const leg of options?.fallback ?? []) requireWorkersAIId(leg);
122
133
  return options;
@@ -164,7 +175,7 @@ function withoutCallFallback(options) {
164
175
  //#region src/models/ai-sdk/transport.ts
165
176
  /**
166
177
  * The typed AI SDK error for the gateway's own error envelope — a missing
167
- * gateway, an unpaid account — on the universal path.
178
+ * gateway, an unpaid account — on the provider-native path.
168
179
  */
169
180
  function errorFromGatewayEnvelope(body, context) {
170
181
  return CloudflareAIError.fromCore(errorFromGatewayEnvelope$1(body, context));
@@ -194,16 +205,16 @@ function createTransport(settings) {
194
205
  const inner = createTransport$1(settings);
195
206
  return {
196
207
  logIdFallback: (response) => inner.logIdFallback(response),
197
- async run(request) {
208
+ async native(request) {
198
209
  try {
199
- return await inner.run(request);
210
+ return await inner.native(request);
200
211
  } catch (error) {
201
212
  throw toAISDKError(error);
202
213
  }
203
214
  },
204
- async universal(request) {
215
+ async run(request) {
205
216
  try {
206
- return await inner.universal(request);
217
+ return await inner.run(request);
207
218
  } catch (error) {
208
219
  throw toAISDKError(error);
209
220
  }
@@ -489,7 +500,7 @@ var CloudflareEmbeddingModel = class {
489
500
  provider: this.provider,
490
501
  values: options.values
491
502
  });
492
- const resolved = resolveOptions(_classPrivateFieldGet2(_config$3, this).providerGateway, _classPrivateFieldGet2(_options$3, this), parseCallOptions(options.providerOptions));
503
+ const resolved = resolveOptions(_classPrivateFieldGet2(_config$3, this).providerGateway, _classPrivateFieldGet2(_options$3, this), parseModalityCallOptions(options.providerOptions));
493
504
  const input = { text: options.values };
494
505
  const transport = _classPrivateFieldGet2(_config$3, this).transport;
495
506
  return withFallback(this.modelId, resolved.fallback, transport.url, async (modelId) => {
@@ -1129,12 +1140,12 @@ function callHeaders(options, resolved) {
1129
1140
  * attaches to its result. Shared with the non-language models in
1130
1141
  * `models/modality.ts`.
1131
1142
  */
1132
- function cloudflareMetadata(model, resolved, response, transport, provider) {
1143
+ function cloudflareMetadata(model, gateway, response, transport, provider) {
1133
1144
  const headers = response.headers;
1134
1145
  const rawStep = headers.get("cf-aig-step");
1135
1146
  const step = rawStep === null ? NaN : Number(rawStep);
1136
1147
  const metadata = {
1137
- gateway: resolved.gateway.id,
1148
+ ...gateway === void 0 ? {} : { gateway },
1138
1149
  model,
1139
1150
  ...provider === void 0 ? {} : { provider },
1140
1151
  ...Number.isNaN(step) ? {} : { step }
@@ -1302,7 +1313,7 @@ var CloudflareLanguageModel = class {
1302
1313
  return {
1303
1314
  content: generation.content,
1304
1315
  finishReason: generation.finishReason,
1305
- providerMetadata: cloudflareMetadata(modelId, resolved, response, _classPrivateFieldGet2(_config$2, this).transport),
1316
+ providerMetadata: cloudflareMetadata(modelId, resolved.gateway.id, response, _classPrivateFieldGet2(_config$2, this).transport),
1306
1317
  request: { body: request.body },
1307
1318
  response: {
1308
1319
  headers: headersToObject(response.headers),
@@ -1322,7 +1333,7 @@ var CloudflareLanguageModel = class {
1322
1333
  return _assertClassBrand(_CloudflareLanguageModel_brand, this, _withFallback$1).call(this, call, (model) => model.doStream(legOptions), async (modelId) => {
1323
1334
  const request = buildRequest(modelId, options, resolved, true);
1324
1335
  const response = await _assertClassBrand(_CloudflareLanguageModel_brand, this, _send).call(this, modelId, request, options, resolved);
1325
- const providerMetadata = cloudflareMetadata(modelId, resolved, response, _classPrivateFieldGet2(_config$2, this).transport);
1336
+ const providerMetadata = cloudflareMetadata(modelId, resolved.gateway.id, response, _classPrivateFieldGet2(_config$2, this).transport);
1326
1337
  const contentType = response.headers.get("content-type") ?? "";
1327
1338
  const decorate = decorateStream(request.warnings, providerMetadata);
1328
1339
  let parts;
@@ -1368,6 +1379,7 @@ function _resolve$1(call) {
1368
1379
  }
1369
1380
  async function _send(modelId, request, options, resolved) {
1370
1381
  const response = await _classPrivateFieldGet2(_config$2, this).transport.run({
1382
+ format: "chat-completions",
1371
1383
  gateway: resolved.gateway,
1372
1384
  headers: callHeaders(options, resolved),
1373
1385
  input: request.body,
@@ -1394,7 +1406,7 @@ function _withFallback$1(call, runLeg, runSelf, mode = "generate") {
1394
1406
  model: this.modelId,
1395
1407
  run: () => runSelf(this.modelId)
1396
1408
  }, ...legs.map((leg) => typeof leg === "string" ? {
1397
- model: requireWorkersAIId(leg),
1409
+ model: requireLanguageModelId(leg),
1398
1410
  run: () => runSelf(leg)
1399
1411
  } : {
1400
1412
  model: leg.modelId,
@@ -1441,36 +1453,34 @@ function requestUrl(input) {
1441
1453
  }
1442
1454
  /**
1443
1455
  * The body of either `fetch` call form: the `RequestInit`'s when one was
1444
- * given, else the `Request`'s own, read from a clone so the caller's object
1445
- * is neither consumed nor mutated.
1456
+ * given, else the `Request`'s own, from a clone so the caller's object is
1457
+ * neither consumed nor mutated.
1446
1458
  */
1447
- async function requestBody(input, init) {
1459
+ function requestBody(input, init) {
1448
1460
  if (init?.body !== void 0) return init.body;
1449
- if (input instanceof Request && input.body !== null) return await input.clone().text();
1461
+ if (input instanceof Request && input.body !== null) return input.clone().body;
1450
1462
  }
1451
- /**
1452
- * The vendor's body as the universal request's `query`. Only JSON travels:
1453
- * the gateway's universal request has one JSON field for the whole upstream
1454
- * body, so a multipart upload or a streamed body cannot be expressed.
1455
- */
1456
- function universalQuery(body) {
1457
- if (typeof body !== "string") {
1458
- const kind = body === null || body === void 0 ? "an empty" : body instanceof FormData ? "a FormData" : `a ${body.constructor?.name ?? typeof body}`;
1459
- throw new TypeError(`AI Gateway's universal request carries a JSON body only, and this model sent ${kind} body. File uploads and other multipart requests cannot be routed through the gateway; call the vendor directly for those.`);
1460
- }
1463
+ /** The method of either `fetch` call form. */
1464
+ function requestMethod(input, init) {
1465
+ return init?.method ?? (input instanceof Request ? input.method : "POST");
1466
+ }
1467
+ /** The vendor model id out of a JSON body, for error reporting. */
1468
+ function modelOfBody(body) {
1469
+ if (typeof body !== "string") return void 0;
1461
1470
  try {
1462
- return JSON.parse(body);
1463
- } catch (error) {
1464
- throw new TypeError(`AI Gateway's universal request carries a JSON body only, and this model sent a body that is not JSON: ${String(error)}`);
1471
+ return modelOf(JSON.parse(body));
1472
+ } catch {
1473
+ return;
1465
1474
  }
1466
1475
  }
1467
1476
  /**
1468
- * The vendor's own request headers, minus the credential the gateway supplies
1469
- * itself and the length of a body we are about to re-serialize.
1477
+ * The vendor's own request headers, minus the length of a body we are about
1478
+ * to re-serialize, and minus the vendor's credential unless the model asked
1479
+ * for it to be forwarded.
1470
1480
  */
1471
- function forwardedHeaders(init, input, route) {
1481
+ function forwardedHeaders(init, input, route, vendorKey) {
1472
1482
  const source = init?.headers ?? (input instanceof Request ? input.headers : void 0);
1473
- const dropped = /* @__PURE__ */ new Set([...route.authHeaders, "content-length"]);
1483
+ const dropped = /* @__PURE__ */ new Set([...vendorKey === "request" ? [] : route.authHeaders, "content-length"]);
1474
1484
  const headers = {};
1475
1485
  new Headers(source).forEach((value, key) => {
1476
1486
  if (!dropped.has(key.toLowerCase())) headers[key] = value;
@@ -1487,42 +1497,42 @@ function replayed(response, text) {
1487
1497
  });
1488
1498
  }
1489
1499
  /**
1490
- * The `fetch` a routed model is given. It never reaches the vendor: it maps
1491
- * the vendor's URL onto a gateway provider slug and endpoint, hands the body
1492
- * over untouched, and returns the gateway's answer as the vendor's own.
1500
+ * The `fetch` a routed model is given. It maps the vendor's URL onto a gateway
1501
+ * provider slug and endpoint and sends the request there unchanged, through
1502
+ * the binding; the answer is the vendor's own.
1493
1503
  */
1494
1504
  function routedFetch(context) {
1495
1505
  const routed = async (input, init) => {
1496
1506
  const route = requireGatewayProvider(requestUrl(input));
1497
- const query = universalQuery(await requestBody(input, init));
1507
+ const body = requestBody(input, init);
1498
1508
  const { resolved } = context;
1499
- const extraHeaders = {
1500
- ...resolved.headers,
1501
- ...resolved.sessionAffinity === void 0 ? {} : { "x-session-affinity": resolved.sessionAffinity }
1502
- };
1503
- const response = await context.config.transport.universal({
1509
+ const response = await context.config.transport.native({
1510
+ body,
1504
1511
  endpoint: route.endpoint,
1505
- ...Object.keys(extraHeaders).length > 0 ? { extraHeaders } : {},
1506
1512
  gateway: resolved.gateway,
1507
- headers: forwardedHeaders(init, input, route),
1513
+ headers: {
1514
+ ...forwardedHeaders(init, input, route, context.vendorKey),
1515
+ ...resolved.headers,
1516
+ ...resolved.sessionAffinity === void 0 ? {} : { "x-session-affinity": resolved.sessionAffinity }
1517
+ },
1518
+ method: requestMethod(input, init),
1508
1519
  provider: route.provider,
1509
- query,
1510
1520
  signal: init?.signal ?? (input instanceof Request ? input.signal : void 0) ?? context.signal
1511
1521
  });
1512
1522
  context.capture.provider = route.provider;
1513
1523
  context.capture.response = response;
1514
1524
  if (response.ok) return response;
1515
1525
  const text = await response.text();
1516
- let body;
1526
+ let envelope;
1517
1527
  try {
1518
- body = JSON.parse(text);
1528
+ envelope = JSON.parse(text);
1519
1529
  } catch {
1520
1530
  return replayed(response, text);
1521
1531
  }
1522
- if (!isGatewayErrorEnvelope(body)) return replayed(response, text);
1523
- throw errorFromGatewayEnvelope(body, {
1524
- model: modelOf(query) ?? route.provider,
1525
- requestBodyValues: query,
1532
+ if (!isGatewayErrorEnvelope(envelope)) return replayed(response, text);
1533
+ throw errorFromGatewayEnvelope(envelope, {
1534
+ model: modelOfBody(body) ?? route.provider,
1535
+ requestBodyValues: void 0,
1526
1536
  responseBody: text,
1527
1537
  responseHeaders: headersToObject(response.headers),
1528
1538
  status: response.status,
@@ -1709,7 +1719,8 @@ function _route(resolved, capture, signal) {
1709
1719
  capture,
1710
1720
  config: _classPrivateFieldGet2(_config$1, this),
1711
1721
  resolved,
1712
- signal
1722
+ signal,
1723
+ vendorKey: _classPrivateFieldGet2(_options$1, this)?.vendorKey ?? "gateway"
1713
1724
  }));
1714
1725
  }
1715
1726
  function _resolve(call) {
@@ -1717,7 +1728,7 @@ function _resolve(call) {
1717
1728
  }
1718
1729
  function _metadata(resolved, capture) {
1719
1730
  const response = capture.response ?? new Response(null);
1720
- return cloudflareMetadata(this.modelId, resolved, response, _classPrivateFieldGet2(_config$1, this).transport, capture.provider);
1731
+ return cloudflareMetadata(this.modelId, resolved.gateway.id, response, _classPrivateFieldGet2(_config$1, this).transport, capture.provider);
1721
1732
  }
1722
1733
  function _response(response, capture) {
1723
1734
  if (capture.response === void 0) return response;
@@ -1752,14 +1763,14 @@ function _withFallback(call, runLeg, run, mode = "generate") {
1752
1763
  }
1753
1764
  /** A Workers AI leg, carrying this model's gateway options but no chain. */
1754
1765
  function _workersAI(modelId) {
1755
- return new CloudflareLanguageModel(requireWorkersAIId(modelId), {
1766
+ return new CloudflareLanguageModel(requireLanguageModelId(modelId), {
1756
1767
  ..._classPrivateFieldGet2(_options$1, this),
1757
1768
  fallback: void 0
1758
1769
  }, _classPrivateFieldGet2(_config$1, this));
1759
1770
  }
1760
1771
  /**
1761
1772
  * Routes any other AI SDK v4 model the vendor built — embedding, image,
1762
- * speech, transcription — through the same universal gateway request. Only
1773
+ * speech, transcription — through the same provider-native request. Only
1763
1774
  * `fetch` is swapped; every `do…` method stays the vendor's, and its result
1764
1775
  * gains `providerMetadata.cloudflare` when the result is an object that can
1765
1776
  * carry one.
@@ -1779,7 +1790,8 @@ function routed(model, options, config) {
1779
1790
  capture,
1780
1791
  config,
1781
1792
  resolved,
1782
- signal: call?.abortSignal
1793
+ signal: call?.abortSignal,
1794
+ vendorKey: options?.vendorKey ?? "gateway"
1783
1795
  }));
1784
1796
  const result = await Reflect.get(clone, property).call(clone, upstream);
1785
1797
  if (result === null || typeof result !== "object") return result;
@@ -1787,13 +1799,18 @@ function routed(model, options, config) {
1787
1799
  return {
1788
1800
  ...result,
1789
1801
  ...routedWarnings(result, resolved),
1790
- providerMetadata: mergeMetadata(existing, metadataFor(result, cloudflareMetadata(String(target.modelId ?? ""), resolved, capture.response ?? new Response(null), config.transport, capture.provider)))
1802
+ providerMetadata: mergeMetadata(existing, metadataFor(result, cloudflareMetadata(String(target.modelId ?? ""), resolved.gateway.id, capture.response ?? new Response(null), config.transport, capture.provider)))
1791
1803
  };
1792
1804
  };
1793
1805
  } });
1794
1806
  }
1795
1807
  //#endregion
1796
1808
  //#region src/models/ai-sdk/models/modality.ts
1809
+ /** Whether the caller set any gateway option, the id included. */
1810
+ function gatewayConfigured(gateway) {
1811
+ const { id, ...options } = gateway;
1812
+ return id !== "default" || Object.keys(options).length > 0;
1813
+ }
1797
1814
  /** The `unsupported` warning shape, which every modality needs. */
1798
1815
  function unsupported(feature, details) {
1799
1816
  return {
@@ -1843,11 +1860,21 @@ var CloudflareModalityModel = class {
1843
1860
  * as JSON or as raw bytes depending on what the model sent back.
1844
1861
  */
1845
1862
  async send(call) {
1846
- const resolved = resolveOptions(_classPrivateFieldGet2(_config, this).providerGateway, _classPrivateFieldGet2(_options, this), parseCallOptions(call.providerOptions));
1863
+ const resolved = resolveOptions(_classPrivateFieldGet2(_config, this).providerGateway, _classPrivateFieldGet2(_options, this), parseModalityCallOptions(call.providerOptions));
1847
1864
  const transport = _classPrivateFieldGet2(_config, this).transport;
1848
1865
  return withFallback(this.modelId, resolved.fallback, transport.url, async (modelId) => {
1849
1866
  const request = call.build(modelId);
1867
+ const direct = request.audio !== void 0;
1868
+ const sent = request.audio === void 0 ? request.input : {
1869
+ ...request.input,
1870
+ audio: {
1871
+ body: toBase64(request.audio.bytes),
1872
+ contentType: request.audio.contentType
1873
+ }
1874
+ };
1875
+ const warnings = direct && gatewayConfigured(resolved.gateway) ? [...request.warnings, unsupported("gateway", `${modelId} goes to Workers AI directly, so the gateway options do not apply.`)] : request.warnings;
1850
1876
  const response = await transport.run({
1877
+ ...request.audio === void 0 ? {} : { audio: request.audio },
1851
1878
  gateway: resolved.gateway,
1852
1879
  headers: {
1853
1880
  ...definedHeaders(call.headers),
@@ -1860,20 +1887,20 @@ var CloudflareModalityModel = class {
1860
1887
  });
1861
1888
  if (!response.ok) throw await errorFromResponse(response, {
1862
1889
  model: modelId,
1863
- requestBodyValues: request.input,
1890
+ requestBodyValues: sent,
1864
1891
  url: transport.url
1865
1892
  });
1866
1893
  const mediaType = (response.headers.get("content-type") ?? "").split(";")[0].trim().toLowerCase();
1867
- const body = await _assertClassBrand(_CloudflareModalityModel_brand, this, _decode).call(this, response, modelId, request.input, mediaType);
1894
+ const body = await _assertClassBrand(_CloudflareModalityModel_brand, this, _decode).call(this, response, modelId, sent, mediaType);
1868
1895
  const answer = {
1869
1896
  headers: headersToObject(response.headers),
1870
- input: request.input,
1897
+ input: sent,
1871
1898
  mediaType,
1872
1899
  modelId,
1873
- providerMetadata: cloudflareMetadata(modelId, resolved, response, transport),
1900
+ providerMetadata: cloudflareMetadata(modelId, direct ? void 0 : resolved.gateway.id, response, transport),
1874
1901
  timestamp: /* @__PURE__ */ new Date(),
1875
1902
  url: transport.url,
1876
- warnings: request.warnings,
1903
+ warnings,
1877
1904
  ...body
1878
1905
  };
1879
1906
  call.check?.(answer);
@@ -2244,13 +2271,13 @@ var CloudflareSpeechModel = class extends CloudflareModalityModel {
2244
2271
  */
2245
2272
  const BYTE_ARRAY_AUDIO = /* @__PURE__ */ new Set(["@cf/openai/whisper", "@cf/openai/whisper-tiny-en"]);
2246
2273
  /**
2247
- * Deepgram's recognition models declare `audio: { body: object, contentType }`.
2248
- * Every documented encoding of that shape answered `400 required properties at
2249
- * '/audio' are 'body,contentType'` on the live run path, because `body` has to
2250
- * be the audio object itself and JSON cannot carry it. Refuse early rather
2251
- * than send a body known to fail.
2274
+ * Models that declare `audio: { body, contentType }`. JSON cannot carry that
2275
+ * body (base64 and byte arrays answer `400 required properties at '/audio' are
2276
+ * 'body,contentType'`), so the audio travels as a raw body.
2252
2277
  */
2253
- const UNSUPPORTED = /* @__PURE__ */ new Set(["@cf/deepgram/nova-3", "@cf/deepgram/flux"]);
2278
+ const RAW_AUDIO = /* @__PURE__ */ new Set(["@cf/deepgram/nova-3"]);
2279
+ /** Deepgram's Flux answers `only supports websocket connections` over HTTP. */
2280
+ const WEBSOCKET_ONLY = /* @__PURE__ */ new Set(["@cf/deepgram/flux"]);
2254
2281
  function transcriptionOptions(providerOptions) {
2255
2282
  const raw = record(providerOptions?.["cloudflare"]) ?? {};
2256
2283
  const vadFilter = raw.vadFilter;
@@ -2262,10 +2289,32 @@ function transcriptionOptions(providerOptions) {
2262
2289
  ...typeof vadFilter === "boolean" ? { vadFilter } : {}
2263
2290
  };
2264
2291
  }
2265
- /** Builds the run-path body for one whisper leg. */
2292
+ /**
2293
+ * Builds the request for a raw-audio model: the audio as a raw body, and
2294
+ * `language` as a field. The whisper-only options have no equivalent there.
2295
+ */
2296
+ function buildRawAudioRequest(modelId, options, extra) {
2297
+ const warnings = [];
2298
+ for (const feature of [
2299
+ "task",
2300
+ "initialPrompt",
2301
+ "prefix",
2302
+ "vadFilter"
2303
+ ]) if (extra[feature] !== void 0) warnings.push(unsupported(feature, `${modelId} has no ${feature}.`));
2304
+ return {
2305
+ audio: {
2306
+ bytes: toBytes(options.audio),
2307
+ contentType: options.mediaType
2308
+ },
2309
+ input: extra.language === void 0 ? {} : { language: extra.language },
2310
+ warnings
2311
+ };
2312
+ }
2313
+ /** Builds the run-path body for one leg. */
2266
2314
  function buildTranscriptionRequest(modelId, options) {
2267
2315
  const warnings = [];
2268
2316
  const extra = transcriptionOptions(options.providerOptions);
2317
+ if (RAW_AUDIO.has(modelId)) return buildRawAudioRequest(modelId, options, extra);
2269
2318
  const input = BYTE_ARRAY_AUDIO.has(modelId) ? { audio: Array.from(toBytes(options.audio)) } : { audio: toBase64(options.audio) };
2270
2319
  if (extra.language !== void 0) input.language = extra.language;
2271
2320
  if (extra.task !== void 0) input.task = extra.task;
@@ -2277,6 +2326,45 @@ function buildTranscriptionRequest(modelId, options) {
2277
2326
  warnings
2278
2327
  };
2279
2328
  }
2329
+ /** Reads a timed `{ text|word, start, end }` entry as a segment. */
2330
+ function timed(entry, textKeys) {
2331
+ const item = record(entry);
2332
+ if (item === void 0) return [];
2333
+ const value = textKeys.map((key) => text(item[key])).find(Boolean);
2334
+ if (value === void 0) return [];
2335
+ return [{
2336
+ endSecond: count(item.end) ?? 0,
2337
+ startSecond: count(item.start) ?? 0,
2338
+ text: value
2339
+ }];
2340
+ }
2341
+ /**
2342
+ * Reads a Deepgram answer: `results.channels[0].alternatives[0]`. Its
2343
+ * sentences are the segments when it sends paragraphs, and its words
2344
+ * otherwise.
2345
+ */
2346
+ function readDeepgram(body) {
2347
+ const channel = record(array(record(body.results)?.channels)?.[0]);
2348
+ const alternative = record(array(channel?.alternatives)?.[0]);
2349
+ const sentences = (array(record(alternative?.paragraphs)?.paragraphs) ?? []).flatMap((paragraph) => array(record(paragraph)?.sentences) ?? []);
2350
+ const segments = sentences.length > 0 ? sentences.flatMap((sentence) => timed(sentence, ["text"])) : (array(alternative?.words) ?? []).flatMap((word) => timed(word, ["punctuated_word", "word"]));
2351
+ return {
2352
+ durationInSeconds: count(record(body.metadata)?.duration),
2353
+ language: text(array(alternative?.languages)?.[0]) ?? text(channel?.detected_language),
2354
+ segments,
2355
+ text: text(alternative?.transcript) ?? ""
2356
+ };
2357
+ }
2358
+ /** Reads a whisper answer. */
2359
+ function readWhisper(body) {
2360
+ const info = record(body.transcription_info);
2361
+ return {
2362
+ durationInSeconds: count(info?.duration),
2363
+ language: text(info?.language),
2364
+ segments: readSegments(body),
2365
+ text: text(body.text) ?? ""
2366
+ };
2367
+ }
2280
2368
  /**
2281
2369
  * Reads segments out of a whisper answer. `segments` is what the large models
2282
2370
  * send; the smaller ones send only `words`, whose timings are the best segment
@@ -2318,10 +2406,10 @@ var CloudflareTranscriptionModel = class extends CloudflareModalityModel {
2318
2406
  const answer = await this.send({
2319
2407
  abortSignal: options.abortSignal,
2320
2408
  build: (modelId) => {
2321
- if (UNSUPPORTED.has(modelId)) throw new CloudflareAIError({
2409
+ if (WEBSOCKET_ONLY.has(modelId)) throw new CloudflareAIError({
2322
2410
  code: "bad-request",
2323
2411
  isRetryable: false,
2324
- message: `${modelId} takes the audio as an object body, which the JSON run path cannot carry. Use @cf/openai/whisper-large-v3-turbo.`,
2412
+ message: `${modelId} takes websocket connections only. Use @cf/deepgram/nova-3 or @cf/openai/whisper-large-v3-turbo.`,
2325
2413
  model: modelId,
2326
2414
  requestBodyValues: void 0,
2327
2415
  url: this.endpoint
@@ -2332,11 +2420,10 @@ var CloudflareTranscriptionModel = class extends CloudflareModalityModel {
2332
2420
  providerOptions: options.providerOptions
2333
2421
  });
2334
2422
  const body = record(answer.json) ?? {};
2335
- const info = record(body.transcription_info);
2336
- const language = text(info?.language);
2423
+ const transcript = record(body.results) === void 0 ? readWhisper(body) : readDeepgram(body);
2337
2424
  return {
2338
- durationInSeconds: count(info?.duration),
2339
- language,
2425
+ durationInSeconds: transcript.durationInSeconds,
2426
+ language: transcript.language,
2340
2427
  providerMetadata: answer.providerMetadata,
2341
2428
  request: { body: JSON.stringify(answer.input) },
2342
2429
  response: {
@@ -2345,8 +2432,8 @@ var CloudflareTranscriptionModel = class extends CloudflareModalityModel {
2345
2432
  modelId: answer.modelId,
2346
2433
  timestamp: answer.timestamp
2347
2434
  },
2348
- segments: readSegments(body),
2349
- text: text(body.text) ?? "",
2435
+ segments: transcript.segments,
2436
+ text: transcript.text,
2350
2437
  warnings: answer.warnings
2351
2438
  };
2352
2439
  }
@@ -2358,21 +2445,22 @@ function isModel(value) {
2358
2445
  return typeof value === "object" && value !== null;
2359
2446
  }
2360
2447
  /**
2361
- * Creates a provider over Workers AI, and over every vendor AI Gateway can
2362
- * reach.
2448
+ * Creates a provider over Workers AI and the AI Gateway catalog.
2363
2449
  *
2364
- * The Workers AI binding is the only way in — Workers AI models go through
2365
- * `env.AI.run`, vendor models through `env.AI.gateway(id).run`, and there is
2366
- * no HTTP transport and no API token. Gateway options are flat (`id`,
2367
- * `cacheTtl`, …) or nested under `gateway`; per-model options and per-call
2368
- * `providerOptions.cloudflare` override them in that order.
2450
+ * A Workers AI id goes to Workers AI and a catalog id or dynamic route to AI
2451
+ * Gateway's `/run`, both on `env.AI.run`; a vendor's model object goes to AI
2452
+ * Gateway's provider-native path. With `{ accountId, apiToken }` instead of
2453
+ * `binding`, the same requests go to the REST API and to
2454
+ * `gateway.ai.cloudflare.com`. Gateway
2455
+ * options are flat (`id`, `cacheTtl`, …) or nested under `gateway`; per-model
2456
+ * options and per-call `providerOptions.cloudflare` override them in that
2457
+ * order.
2369
2458
  *
2370
2459
  * ```ts
2371
2460
  * const ai = createAI({ binding: env.AI, id: "prod", cacheTtl: 60 });
2372
- * const anthropic = createAnthropic({ apiKey: "cloudflare" });
2373
2461
  *
2374
2462
  * ai("@cf/zai-org/glm-4.7-flash");
2375
- * ai(anthropic("claude-opus-4-8"), { fallback: [ai("@cf/zai-org/glm-4.7-flash")] });
2463
+ * ai("anthropic/claude-opus-4.8", { fallback: ["openai/gpt-5.5"] });
2376
2464
  * ai.embedding("@cf/baai/bge-base-en-v1.5");
2377
2465
  * ```
2378
2466
  *
@@ -2384,36 +2472,34 @@ function createAI(settings) {
2384
2472
  transport: createTransport(settings)
2385
2473
  };
2386
2474
  /**
2387
- * Fallback legs are normalized once, here: a model object becomes a routed
2388
- * model, so every leg a model runs is already this provider's.
2475
+ * Fallback legs are normalized once, here. A leg written as an id is gated
2476
+ * at the line that wrote it; a model object is routed like `ai(model)`.
2389
2477
  *
2390
2478
  * A leg inherits the chain's *gateway* options and nothing else. The rest of
2391
2479
  * the bag — `reasoningEffort`, `chatTemplateKwargs`, `headers`,
2392
- * `sessionAffinity` — was written for the model it was written on, and a leg
2393
- * that was configured with its own keeps every one of them.
2480
+ * `sessionAffinity`, `vendorKey` — was written for the model it was written
2481
+ * on, and a leg that was configured with its own keeps every one of them.
2394
2482
  */
2395
2483
  const normalize = (options) => {
2396
2484
  if (options?.fallback === void 0) return options;
2397
2485
  const inherited = gatewayLayerOf(options);
2398
2486
  return {
2399
2487
  ...options,
2400
- fallback: options.fallback.map((leg) => typeof leg === "string" ? requireWorkersAIId(leg) : languageModel(leg, inherited))
2488
+ fallback: options.fallback.map((leg) => typeof leg === "string" ? requireLanguageModelId(leg) : languageModel(leg, inherited))
2401
2489
  };
2402
2490
  };
2403
2491
  function languageModel(model, options) {
2404
2492
  const resolved = normalize(options);
2405
- if (isModel(model)) {
2406
- if (model instanceof CloudflareLanguageModel) {
2407
- const merged = normalize(mergeModelOptions(optionsOf(model), resolved));
2408
- return new CloudflareLanguageModel(model.modelId, merged, config);
2409
- }
2410
- if (model instanceof GatewayLanguageModel) {
2411
- const merged = normalize(mergeModelOptions(optionsOf(model), resolved));
2412
- return new GatewayLanguageModel(model.model, merged, config);
2413
- }
2414
- return new GatewayLanguageModel(model, resolved, config);
2493
+ if (!isModel(model)) return new CloudflareLanguageModel(requireLanguageModelId(model), resolved, config);
2494
+ if (model instanceof CloudflareLanguageModel) {
2495
+ const merged = normalize(mergeModelOptions(optionsOf(model), resolved));
2496
+ return new CloudflareLanguageModel(model.modelId, merged, config);
2497
+ }
2498
+ if (model instanceof GatewayLanguageModel) {
2499
+ const merged = normalize(mergeModelOptions(optionsOf(model), resolved));
2500
+ return new GatewayLanguageModel(model.model, merged, config);
2415
2501
  }
2416
- return new CloudflareLanguageModel(requireWorkersAIId(model), resolved, config);
2502
+ return new GatewayLanguageModel(model, resolved, config);
2417
2503
  }
2418
2504
  const embedding = (modelId, options) => new CloudflareEmbeddingModel(modelId, options, config);
2419
2505
  const image = (modelId, options) => new CloudflareImageModel(modelId, options, config);
@@ -2441,4 +2527,4 @@ function createAI(settings) {
2441
2527
  //#endregion
2442
2528
  export { GatewayLanguageModel as n, CloudflareAIError as r, createAI as t };
2443
2529
 
2444
- //# sourceMappingURL=ai-sdk-Bdsf6mSA.js.map
2530
+ //# sourceMappingURL=ai-sdk-DRPh2rRa.js.map