@openclaw/ai 2026.7.2-beta.6 → 2026.7.33

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 (78) hide show
  1. package/README.md +5 -6
  2. package/dist/{anthropic-CH4UUnZr.mjs → anthropic-BML72tLz.mjs} +468 -101
  3. package/dist/{api-registry-DlMgPR39.d.mts → api-registry-BXYnCOIR.d.mts} +2 -1
  4. package/dist/{azure-openai-responses-client-compat-C7K7QfUE.mjs → azure-openai-responses-client-compat-a_O_GVQV.mjs} +2 -23
  5. package/dist/{azure-openai-responses-CImcwB83.mjs → azure-openai-responses-kEN8II8I.mjs} +13 -11
  6. package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-CtMlqaQ4.mjs} +4 -5
  7. package/dist/{event-stream-YjaPW20U.d.mts → event-stream-0nZeBKl2.d.mts} +1 -1
  8. package/dist/{event-stream-D8n2uFee.mjs → event-stream-ReMmOTzX.mjs} +6 -14
  9. package/dist/event-stream.d.mts +1 -1
  10. package/dist/event-stream.mjs +1 -1
  11. package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-BsH5cqGj.mjs} +12 -1
  12. package/dist/{google-CtSg0iTS.mjs → google-DTM4O3e9.mjs} +5 -5
  13. package/dist/{google-shared-DNBz5rcD.mjs → google-shared-BAP0BQVi.mjs} +22 -34
  14. package/dist/{google-vertex-31f1uS9L.mjs → google-vertex-D58MZHCQ.mjs} +19 -6
  15. package/dist/host-4t713IeR.mjs +37 -0
  16. package/dist/{anthropic-SrGtwsJu.d.mts → index-BoTnz8cv.d.mts} +1 -27
  17. package/dist/index.d.mts +50 -7
  18. package/dist/index.mjs +5 -5
  19. package/dist/internal/anthropic.d.mts +62 -22
  20. package/dist/internal/anthropic.mjs +4 -5
  21. package/dist/internal/openai.d.mts +82 -98
  22. package/dist/internal/openai.mjs +6 -8
  23. package/dist/internal/runtime.d.mts +34 -13
  24. package/dist/internal/runtime.mjs +14 -26
  25. package/dist/internal/shared.d.mts +9 -26
  26. package/dist/internal/shared.mjs +2 -6
  27. package/dist/{json-parse-BvXNt1-7.mjs → json-parse-DzNSIQBq.mjs} +6 -4
  28. package/dist/{llm-request-activity-BjtkplhG.mjs → llm-request-activity-CehVkZP-.mjs} +19 -1
  29. package/dist/{mistral-CWmpvWYh.mjs → mistral-CePVNdws.mjs} +39 -141
  30. package/dist/model-utils-DgmOla96.mjs +69 -0
  31. package/dist/{openai-chatgpt-responses-B84Ibtrd.mjs → openai-chatgpt-responses-BHqbcipc.mjs} +154 -101
  32. package/dist/{openai-completions-DsOxhOD1.mjs → openai-completions-9qYFVS7H.mjs} +295 -81
  33. package/dist/{openai-responses-BT7A3sLu.mjs → openai-responses-D6l9URyV.mjs} +8 -10
  34. package/dist/openai-responses-shared-L3PWZvkm.mjs +1949 -0
  35. package/dist/{openai-tool-projection-OhX64DoP.mjs → openai-tool-projection-BPlyXt8H.mjs} +12 -32
  36. package/dist/providers.d.mts +2 -3
  37. package/dist/providers.mjs +10 -11
  38. package/dist/reasoning-tag-text-partitioner-axhAdUwg.mjs +394 -0
  39. package/dist/{src-QkygScBs.mjs → src-CZ503MYJ.mjs} +5 -24
  40. package/dist/{stream-first-event-timeout-BBys9hSb.mjs → stream-first-event-timeout-RjWszj8c.mjs} +22 -2
  41. package/dist/transform-messages-BhGF_fF4.mjs +507 -0
  42. package/dist/{types-bzp5k29J.d.mts → types-DRgdPqaZ.d.mts} +0 -19
  43. package/dist/types.d.mts +5 -5
  44. package/dist/types.mjs +4 -4
  45. package/dist/{validation-B-j7cOYp.d.mts → validation-BDMWOr8d.d.mts} +1 -1
  46. package/dist/{validation-DAa_yFOM.mjs → validation-FrchoOlv.mjs} +7 -2
  47. package/dist/validation.d.mts +1 -1
  48. package/dist/validation.mjs +1 -1
  49. package/npm-shrinkwrap.json +645 -0
  50. package/package.json +11 -36
  51. package/dist/anthropic-usage-DWU-x8MI.mjs +0 -459
  52. package/dist/cache-retention-0x979a5V.mjs +0 -12
  53. package/dist/deferred-event-buffer-DAvyP7qA.mjs +0 -19
  54. package/dist/error-coercion-DgxlWC0n.mjs +0 -15
  55. package/dist/host-B9GUmcra.d.mts +0 -173
  56. package/dist/host-Dog2WQiR.mjs +0 -369
  57. package/dist/index-BVVgDSdq.d.mts +0 -1
  58. package/dist/internal/retry-after.d.mts +0 -5
  59. package/dist/internal/retry-after.mjs +0 -101
  60. package/dist/number-coercion-DvG7SNMg.mjs +0 -129
  61. package/dist/openai-completions-compat-DBWjXoMZ.d.mts +0 -43
  62. package/dist/openai-prompt-cache-2uo_1OR1.d.mts +0 -7
  63. package/dist/openai-prompt-cache-mZTCdRPo.mjs +0 -12
  64. package/dist/openai-reasoning-compat-YgeLncHw.mjs +0 -396
  65. package/dist/openai-responses-shared-pXl6Wd8S.mjs +0 -392
  66. package/dist/openai-responses-stream-internal-Cw5txaGW.mjs +0 -2964
  67. package/dist/prompt-cache-stability-Cwcjv_fx.d.mts +0 -13
  68. package/dist/provider-error-CAEvRjry.mjs +0 -47
  69. package/dist/provider-options-D8bB3z9b.d.mts +0 -144
  70. package/dist/reasoning-tag-text-partitioner-CGDyLWUR.mjs +0 -12209
  71. package/dist/simple-options-9lhRrN73.mjs +0 -50
  72. package/dist/stream-first-event-timeout-DvDeSucC.d.mts +0 -29
  73. package/dist/tls-certificate-errors-DXSpluKI.mjs +0 -93
  74. package/dist/tool-result-text-CTpIRbYd.mjs +0 -225
  75. package/dist/transform-messages-C8mBqZxF.mjs +0 -2
  76. package/dist/transport-stream-shared-D81p90xq.mjs +0 -297
  77. package/dist/transports.d.mts +0 -573
  78. package/dist/transports.mjs +0 -4110
@@ -1,22 +1,43 @@
1
- import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-DrgeBuva.mjs";
2
- import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
3
- import { n as getAiTransportHost } from "./host-Dog2WQiR.mjs";
4
- import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
5
- import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
6
- import { u as splitSystemPromptCacheBoundary } from "./tool-result-text-CTpIRbYd.mjs";
7
- import { n as reconcileOpenAICompletionsToolChoice, t as projectOpenAITools } from "./openai-tool-projection-OhX64DoP.mjs";
8
- import { c as calculateCost, l as clampThinkingLevel, s as applyProviderReportedUsageCost } from "./number-coercion-DvG7SNMg.mjs";
9
- import { a as resolveOpenAICompletionsCompat, c as clearPendingCommentaryText, l as rememberPendingCommentaryTags, n as mapOpenAIStopReason, o as resolveOpenAICompletionsResponseFormat, r as convertMessages, s as shouldOmitOllamaCompatResponseFormat, t as resolveOpenAIReasoningEffortMap, u as tagPendingCommentaryText } from "./openai-reasoning-compat-YgeLncHw.mjs";
10
- import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
11
- import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
12
- import { d as transportAbortError } from "./transport-stream-shared-D81p90xq.mjs";
13
- import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-CGDyLWUR.mjs";
14
- import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-BBys9hSb.mjs";
1
+ import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-CtMlqaQ4.mjs";
2
+ import { t as AssistantMessageEventStream } from "./event-stream-ReMmOTzX.mjs";
3
+ import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
4
+ import { n as calculateCost, r as clampThinkingLevel, t as applyProviderReportedUsageCost } from "./model-utils-DgmOla96.mjs";
15
5
  import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
16
- import { t as formatProviderError } from "./provider-error-CAEvRjry.mjs";
17
- import { i as resolveCloudflareBaseUrl, n as hasCopilotVisionInput, r as isCloudflareProvider, t as buildCopilotDynamicHeaders } from "./github-copilot-headers-NCJtz9i0.mjs";
18
- import { n as buildBaseOptions } from "./simple-options-9lhRrN73.mjs";
6
+ import { n as parseStreamingJson } from "./json-parse-DzNSIQBq.mjs";
7
+ import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
8
+ import { b as stripSystemPromptCacheBoundary, i as extractToolResultText, n as describeToolResultMediaPlaceholder, o as buildBaseOptions, t as transformMessages, y as splitSystemPromptCacheBoundary } from "./transform-messages-BhGF_fF4.mjs";
9
+ import { a as resolveCacheRetention, i as resolveCloudflareBaseUrl, n as hasCopilotVisionInput, r as isCloudflareProvider, t as buildCopilotDynamicHeaders } from "./github-copilot-headers-BsH5cqGj.mjs";
10
+ import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-axhAdUwg.mjs";
11
+ import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-RjWszj8c.mjs";
12
+ import { a as clampOpenAIPromptCacheKey, n as reconcileOpenAICompletionsToolChoice, t as projectOpenAITools } from "./openai-tool-projection-BPlyXt8H.mjs";
19
13
  import OpenAI from "openai";
14
+ //#region packages/ai/src/providers/openai-stop-reason.ts
15
+ function mapOpenAIStopReason(reason, options) {
16
+ if (reason === null) return { stopReason: "stop" };
17
+ switch (reason) {
18
+ case "stop":
19
+ case "end": return { stopReason: "stop" };
20
+ case "length": return { stopReason: "length" };
21
+ case "function_call":
22
+ case "tool_calls": return { stopReason: "toolUse" };
23
+ case "tool_call":
24
+ if (options?.allowSingularToolCall) return { stopReason: "toolUse" };
25
+ break;
26
+ case "content_filter": return {
27
+ stopReason: "error",
28
+ errorMessage: "Provider finish_reason: content_filter"
29
+ };
30
+ case "network_error": return {
31
+ stopReason: "error",
32
+ errorMessage: "Provider finish_reason: network_error"
33
+ };
34
+ }
35
+ return {
36
+ stopReason: "error",
37
+ errorMessage: `Provider finish_reason: ${reason}`
38
+ };
39
+ }
40
+ //#endregion
20
41
  //#region packages/ai/src/providers/openai-completions.ts
21
42
  var openai_completions_exports = /* @__PURE__ */ __exportAll({
22
43
  convertMessages: () => convertMessages,
@@ -37,10 +58,22 @@ function hasToolHistory(messages) {
37
58
  }
38
59
  return false;
39
60
  }
40
- function isEncryptedReasoningDetail(detail) {
41
- if (typeof detail !== "object" || detail === null) return false;
42
- const candidate = detail;
43
- return candidate.type === "reasoning.encrypted" && typeof candidate.id === "string" && candidate.id.length > 0 && typeof candidate.data === "string" && candidate.data.length > 0;
61
+ function isTextContentBlock(block) {
62
+ return block.type === "text";
63
+ }
64
+ function isThinkingContentBlock(block) {
65
+ return block.type === "thinking";
66
+ }
67
+ function isToolCallBlock(block) {
68
+ return block.type === "toolCall";
69
+ }
70
+ function isImageContentBlock(block) {
71
+ return block.type === "image";
72
+ }
73
+ const EMPTY_TOOL_RESULT_TEXT = "(no output)";
74
+ function sanitizeToolResultText(text, fallback) {
75
+ const sanitized = sanitizeSurrogates(text);
76
+ return sanitized.trim().length > 0 ? sanitized : fallback;
44
77
  }
45
78
  const streamOpenAICompletions = (model, context, options) => {
46
79
  const stream = new AssistantMessageEventStream();
@@ -68,11 +101,10 @@ const streamOpenAICompletions = (model, context, options) => {
68
101
  stopReason: "stop",
69
102
  timestamp: Date.now()
70
103
  };
71
- const provisionalCommentaryTags = /* @__PURE__ */ new Map();
72
104
  let firstEventAbort;
73
105
  try {
74
106
  const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
75
- const compat = resolveOpenAICompletionsCompat(model);
107
+ const compat = getCompat(model);
76
108
  const cacheRetention = resolveCacheRetention(options?.cacheRetention);
77
109
  const cacheSessionId = cacheRetention === "none" ? void 0 : options?.sessionId;
78
110
  const client = createClient(model, context, apiKey, options?.headers, cacheSessionId, compat);
@@ -83,7 +115,7 @@ const streamOpenAICompletions = (model, context, options) => {
83
115
  const requestOptions = {
84
116
  signal: firstEventAbort.signal,
85
117
  ...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
86
- maxRetries: options?.maxRetries ?? 0
118
+ ...options?.maxRetries !== void 0 ? { maxRetries: options.maxRetries } : {}
87
119
  };
88
120
  const { data: openaiStream, response } = await client.chat.completions.create(params, requestOptions).withResponse();
89
121
  await options?.onResponse?.({
@@ -100,7 +132,6 @@ const streamOpenAICompletions = (model, context, options) => {
100
132
  const toolCallBlocksByIndex = /* @__PURE__ */ new Map();
101
133
  const toolCallBlocksById = /* @__PURE__ */ new Map();
102
134
  const toolCallBlocksByFirstId = /* @__PURE__ */ new Map();
103
- const pendingReasoningDetailsByToolCallId = /* @__PURE__ */ new Map();
104
135
  const blocks = output.content;
105
136
  const finishedBlocks = /* @__PURE__ */ new Set();
106
137
  const contentIndices = /* @__PURE__ */ new WeakMap();
@@ -110,13 +141,7 @@ const streamOpenAICompletions = (model, context, options) => {
110
141
  };
111
142
  const getContentIndex = (block) => contentIndices.get(block) ?? -1;
112
143
  const rememberFirstToolCallById = (id, block) => {
113
- if (toolCallBlocksByFirstId.has(id)) return;
114
- toolCallBlocksByFirstId.set(id, block);
115
- const pendingDetail = pendingReasoningDetailsByToolCallId.get(id);
116
- if (pendingDetail) {
117
- block.thoughtSignature = pendingDetail;
118
- pendingReasoningDetailsByToolCallId.delete(id);
119
- }
144
+ if (!toolCallBlocksByFirstId.has(id)) toolCallBlocksByFirstId.set(id, block);
120
145
  };
121
146
  const finishBlock = (block) => {
122
147
  const contentIndex = getContentIndex(block);
@@ -135,6 +160,7 @@ const streamOpenAICompletions = (model, context, options) => {
135
160
  partial: output
136
161
  });
137
162
  else if (block.type === "toolCall") {
163
+ block.arguments = parseStreamingJson(block.partialArgs);
138
164
  delete block.partialArgs;
139
165
  delete block.streamIndex;
140
166
  stream.push({
@@ -255,7 +281,6 @@ const streamOpenAICompletions = (model, context, options) => {
255
281
  });
256
282
  for await (const chunk of guardedOpenaiStream) {
257
283
  if (!chunk || typeof chunk !== "object") continue;
258
- notifyLlmRequestActivity(options?.signal);
259
284
  output.responseId ||= chunk.id;
260
285
  if (typeof chunk.model === "string" && chunk.model.length > 0 && chunk.model !== model.id) output.responseModel ||= chunk.model;
261
286
  if (chunk.usage) output.usage = parseChunkUsage(chunk.usage, model);
@@ -294,10 +319,9 @@ const streamOpenAICompletions = (model, context, options) => {
294
319
  if (choiceDelta.content !== null && choiceDelta.content !== void 0 && choiceDelta.content.length > 0) appendPartitionedContent(choiceDelta.content, Boolean(foundReasoningField));
295
320
  const refusalText = typeof choiceDelta.refusal === "string" ? choiceDelta.refusal : "";
296
321
  if (refusalText.length > 0) appendPartitionedContent(refusalText, Boolean(foundReasoningField));
297
- if (choiceDelta.tool_calls && choiceDelta.tool_calls.length > 0) {
322
+ if (choiceDelta.tool_calls) {
298
323
  flushPartitionedContent();
299
324
  sealNativeReasoningBeforeText();
300
- rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
301
325
  for (const toolCall of choiceDelta.tool_calls) {
302
326
  const block = ensureToolCallBlock(toolCall);
303
327
  if (!block.id && toolCall.id) {
@@ -321,19 +345,17 @@ const streamOpenAICompletions = (model, context, options) => {
321
345
  }
322
346
  }
323
347
  const reasoningDetails = choiceDelta.reasoning_details;
324
- if (Array.isArray(reasoningDetails)) {
325
- for (const detail of reasoningDetails) if (isEncryptedReasoningDetail(detail)) {
326
- const serializedDetail = JSON.stringify(detail);
348
+ if (reasoningDetails && Array.isArray(reasoningDetails)) {
349
+ for (const detail of reasoningDetails) if (detail.type === "reasoning.encrypted" && detail.id && detail.data) {
327
350
  const matchingToolCall = toolCallBlocksByFirstId.get(detail.id);
328
- if (matchingToolCall) matchingToolCall.thoughtSignature = serializedDetail;
329
- else pendingReasoningDetailsByToolCallId.set(detail.id, serializedDetail);
351
+ if (matchingToolCall) matchingToolCall.thoughtSignature = JSON.stringify(detail);
330
352
  }
331
353
  }
332
354
  }
333
355
  }
334
356
  flushPartitionedContent();
335
357
  for (const block of blocks) finishBlock(block);
336
- if (options?.signal?.aborted) throw transportAbortError(options.signal);
358
+ if (options?.signal?.aborted) throw new Error("Request was aborted");
337
359
  if (output.stopReason === "aborted") throw new Error("Request was aborted");
338
360
  if (output.stopReason === "error") throw new Error(output.errorMessage || "Provider returned an error stop reason");
339
361
  if (!hasFinishReason) throw new Error("Stream ended without finish_reason");
@@ -342,8 +364,6 @@ const streamOpenAICompletions = (model, context, options) => {
342
364
  if (output.stopReason === "toolUse" && !hasToolCalls) output.stopReason = "stop";
343
365
  if (output.stopReason === "stop" && hasToolCalls && !hasVisibleText) output.stopReason = "toolUse";
344
366
  if (hasToolCalls && output.stopReason !== "toolUse") output.content = output.content.filter((block) => block.type !== "toolCall");
345
- if (output.stopReason !== "toolUse") clearPendingCommentaryText(provisionalCommentaryTags);
346
- if (output.stopReason === "toolUse") tagPendingCommentaryText(output.content);
347
367
  stream.push({
348
368
  type: "done",
349
369
  reason: output.stopReason,
@@ -357,9 +377,9 @@ const streamOpenAICompletions = (model, context, options) => {
357
377
  delete block.streamIndex;
358
378
  }
359
379
  output.stopReason = options?.signal?.aborted ? "aborted" : "error";
360
- output.errorMessage = formatProviderError(error);
380
+ output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
361
381
  const rawMetadata = error?.error?.metadata?.raw;
362
- if (rawMetadata && !output.errorMessage.includes(rawMetadata)) output.errorMessage += `\n${rawMetadata}`;
382
+ if (rawMetadata) output.errorMessage += `\n${rawMetadata}`;
363
383
  stream.push({
364
384
  type: "error",
365
385
  reason: output.stopReason,
@@ -385,7 +405,7 @@ const streamSimpleOpenAICompletions = (model, context, options) => {
385
405
  toolChoice
386
406
  });
387
407
  };
388
- function createClient(model, context, apiKey, optionsHeaders, sessionId, compat = resolveOpenAICompletionsCompat(model)) {
408
+ function createClient(model, context, apiKey, optionsHeaders, sessionId, compat = getCompat(model)) {
389
409
  if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
390
410
  const headers = { ...model.headers };
391
411
  if (model.provider === "github-copilot") {
@@ -396,8 +416,7 @@ function createClient(model, context, apiKey, optionsHeaders, sessionId, compat
396
416
  });
397
417
  Object.assign(headers, copilotHeaders);
398
418
  }
399
- if (sessionId && compat.sessionAffinity !== "none") if (compat.sessionAffinity === "openrouter") headers["x-session-id"] = sessionId;
400
- else {
419
+ if (sessionId && compat.sendSessionAffinityHeaders) {
401
420
  headers.session_id = sessionId;
402
421
  headers["x-client-request-id"] = sessionId;
403
422
  headers["x-session-affinity"] = sessionId;
@@ -416,7 +435,7 @@ function createClient(model, context, apiKey, optionsHeaders, sessionId, compat
416
435
  fetch: getAiTransportHost().buildModelFetch(model)
417
436
  });
418
437
  }
419
- function buildParams(model, context, options, compat = resolveOpenAICompletionsCompat(model), cacheRetention = resolveCacheRetention(options?.cacheRetention)) {
438
+ function buildParams(model, context, options, compat = getCompat(model), cacheRetention = resolveCacheRetention(options?.cacheRetention)) {
420
439
  const cacheControl = getCompatCacheControl(compat, cacheRetention);
421
440
  const cacheOptOutIndexes = /* @__PURE__ */ new Set();
422
441
  const messages = convertMessages(model, context, compat, {
@@ -441,13 +460,6 @@ function buildParams(model, context, options, compat = resolveOpenAICompletionsC
441
460
  }
442
461
  if (options?.temperature !== void 0) params.temperature = options.temperature;
443
462
  if (options?.stop !== void 0 && options.stop.length > 0) params.stop = options.stop;
444
- const requestedResponseFormat = options?.responseFormat;
445
- const responseFormat = requestedResponseFormat === void 0 ? void 0 : resolveOpenAICompletionsResponseFormat(shouldOmitOllamaCompatResponseFormat({
446
- provider: model.provider,
447
- baseUrl: model.baseUrl,
448
- hasTools: () => Boolean(context.tools?.length)
449
- }) ? void 0 : requestedResponseFormat, compat.supportsJsonSchemaResponseFormat);
450
- if (responseFormat !== void 0) params.response_format = responseFormat;
451
463
  let toolProjection;
452
464
  if (context.tools) {
453
465
  const converted = convertTools(context.tools, compat);
@@ -461,36 +473,29 @@ function buildParams(model, context, options, compat = resolveOpenAICompletionsC
461
473
  const toolChoice = reconcileOpenAICompletionsToolChoice(options.toolChoice, toolProjection ?? projectOpenAITools([]));
462
474
  if (toolChoice !== void 0) params.tool_choice = toolChoice;
463
475
  }
464
- const reasoningEffortMap = resolveOpenAIReasoningEffortMap(model);
465
- const thinkingLevelMap = model.thinkingLevelMap;
466
- const reasoningEffort = options?.reasoningEffort === void 0 ? void 0 : reasoningEffortMap[options.reasoningEffort] ?? thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
467
- const reasoningEnabled = reasoningEffort !== void 0 && reasoningEffort !== "none";
468
- const offReasoningEffort = reasoningEffortMap.off ?? model.thinkingLevelMap?.off;
469
- if (compat.thinkingFormat === "zai" && model.reasoning) params.thinking = reasoningEnabled ? {
470
- type: "enabled",
471
- clear_thinking: false
472
- } : { type: "disabled" };
473
- else if (compat.thinkingFormat === "qwen" && model.reasoning) params.enable_thinking = reasoningEnabled;
476
+ if (compat.thinkingFormat === "zai" && model.reasoning) params.enable_thinking = Boolean(options?.reasoningEffort);
477
+ else if (compat.thinkingFormat === "qwen" && model.reasoning) params.enable_thinking = Boolean(options?.reasoningEffort);
474
478
  else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) params.chat_template_kwargs = {
475
- enable_thinking: reasoningEnabled,
479
+ enable_thinking: Boolean(options?.reasoningEffort),
476
480
  preserve_thinking: true
477
481
  };
478
482
  else if (compat.thinkingFormat === "deepseek" && model.reasoning) {
479
- params.thinking = { type: reasoningEnabled ? "enabled" : "disabled" };
480
- if (reasoningEnabled && compat.supportsReasoningEffort) params.reasoning_effort = reasoningEffort;
483
+ params.thinking = { type: options?.reasoningEffort ? "enabled" : "disabled" };
484
+ if (options?.reasoningEffort && compat.supportsReasoningEffort) params.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
481
485
  } else if (compat.thinkingFormat === "openrouter" && model.reasoning) {
482
486
  const openRouterParams = params;
483
- if (reasoningEnabled) openRouterParams.reasoning = { effort: reasoningEffort };
484
- else if (offReasoningEffort !== null) openRouterParams.reasoning = { effort: offReasoningEffort ?? "none" };
487
+ if (options?.reasoningEffort) openRouterParams.reasoning = { effort: model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort };
488
+ else if (model.thinkingLevelMap?.off !== null) openRouterParams.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
485
489
  } else if (compat.thinkingFormat === "together" && model.reasoning) {
486
490
  const togetherParams = params;
487
- togetherParams.reasoning = { enabled: reasoningEnabled };
488
- if (reasoningEnabled && compat.supportsReasoningEffort) togetherParams.reasoning_effort = reasoningEffort;
489
- } else if (reasoningEnabled && model.reasoning && compat.supportsReasoningEffort) params.reasoning_effort = reasoningEffort;
490
- else if (model.reasoning && compat.supportsReasoningEffort) {
491
- if (typeof offReasoningEffort === "string") params.reasoning_effort = offReasoningEffort;
491
+ togetherParams.reasoning = { enabled: Boolean(options?.reasoningEffort) };
492
+ if (options?.reasoningEffort && compat.supportsReasoningEffort) togetherParams.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
493
+ } else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) params.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
494
+ else if (!options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
495
+ const offValue = model.thinkingLevelMap?.off;
496
+ if (typeof offValue === "string") params.reasoning_effort = offValue;
492
497
  }
493
- if (compat.openRouterRouting) params.provider = compat.openRouterRouting;
498
+ if (model.baseUrl.includes("openrouter.ai") && model.compat?.openRouterRouting) params.provider = model.compat.openRouterRouting;
494
499
  if (model.baseUrl.includes("ai-gateway.vercel.sh") && model.compat?.vercelGatewayRouting) {
495
500
  const routing = model.compat.vercelGatewayRouting;
496
501
  if (routing.only || routing.order) {
@@ -528,7 +533,7 @@ function addCacheControlToSystemPrompt(messages, cacheControl) {
528
533
  function addCacheControlToLastConversationMessage(messages, cacheControl, cacheOptOutIndexes) {
529
534
  for (let i = messages.length - 1; i >= 0; i--) {
530
535
  const message = messages[i];
531
- if (!message || cacheOptOutIndexes.has(i)) continue;
536
+ if (cacheOptOutIndexes.has(i)) continue;
532
537
  if (message.role === "user" || message.role === "assistant") {
533
538
  if (addCacheControlToMessage(message, cacheControl)) return;
534
539
  }
@@ -536,8 +541,7 @@ function addCacheControlToLastConversationMessage(messages, cacheControl, cacheO
536
541
  }
537
542
  function addCacheControlToLastTool(tools, cacheControl) {
538
543
  if (!tools || tools.length === 0) return;
539
- const lastTool = tools.at(-1);
540
- if (!lastTool) return;
544
+ const lastTool = tools[tools.length - 1];
541
545
  lastTool.cache_control = cacheControl;
542
546
  }
543
547
  function addCacheControlToInstructionMessage(message, cacheControl) {
@@ -587,6 +591,148 @@ function buildCacheControlledTextParts(text, cacheControl) {
587
591
  text: ""
588
592
  }];
589
593
  }
594
+ function convertMessages(model, context, compat, options = {}) {
595
+ const params = [];
596
+ const normalizeToolCallId = (id) => {
597
+ if (id.includes("|")) {
598
+ const [callId] = id.split("|");
599
+ return callId.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
600
+ }
601
+ if (model.provider === "openai") return id.length > 40 ? id.slice(0, 40) : id;
602
+ return id;
603
+ };
604
+ const transformedMessages = transformMessages(context.messages, model, (id) => normalizeToolCallId(id));
605
+ if (context.systemPrompt) {
606
+ const role = model.reasoning && compat.supportsDeveloperRole ? "developer" : "system";
607
+ const systemPrompt = options.preserveSystemPromptCacheBoundary ? context.systemPrompt : stripSystemPromptCacheBoundary(context.systemPrompt);
608
+ params.push({
609
+ role,
610
+ content: sanitizeSurrogates(systemPrompt)
611
+ });
612
+ }
613
+ let lastRole = null;
614
+ for (let i = 0; i < transformedMessages.length; i++) {
615
+ const msg = transformedMessages[i];
616
+ if (compat.requiresAssistantAfterToolResult && lastRole === "toolResult" && msg.role === "user") params.push({
617
+ role: "assistant",
618
+ content: "I have processed the tool results."
619
+ });
620
+ if (msg.role === "user") {
621
+ const isRuntimeContextCarrier = msg.runtimeContextCarrier === true;
622
+ if (typeof msg.content === "string") {
623
+ const userParam = {
624
+ role: "user",
625
+ content: sanitizeSurrogates(msg.content)
626
+ };
627
+ if (isRuntimeContextCarrier) options.cacheOptOutIndexes?.add(params.length);
628
+ params.push(userParam);
629
+ } else {
630
+ const content = msg.content.map((item) => {
631
+ if (item.type === "text") return {
632
+ type: "text",
633
+ text: sanitizeSurrogates(item.text)
634
+ };
635
+ return {
636
+ type: "image_url",
637
+ image_url: { url: `data:${item.mimeType};base64,${item.data}` }
638
+ };
639
+ });
640
+ if (content.length === 0) continue;
641
+ const userParam = {
642
+ role: "user",
643
+ content
644
+ };
645
+ if (isRuntimeContextCarrier) options.cacheOptOutIndexes?.add(params.length);
646
+ params.push(userParam);
647
+ }
648
+ } else if (msg.role === "assistant") {
649
+ const assistantMsg = {
650
+ role: "assistant",
651
+ content: compat.requiresAssistantAfterToolResult ? "" : null
652
+ };
653
+ const assistantTextParts = msg.content.filter(isTextContentBlock).filter((block) => block.text.trim().length > 0).map((block) => ({
654
+ type: "text",
655
+ text: sanitizeSurrogates(block.text)
656
+ }));
657
+ const assistantText = assistantTextParts.map((part) => part.text).join("");
658
+ const nonEmptyThinkingBlocks = msg.content.filter(isThinkingContentBlock).filter((block) => block.thinking.trim().length > 0);
659
+ if (nonEmptyThinkingBlocks.length > 0) if (compat.requiresThinkingAsText) assistantMsg.content = [{
660
+ type: "text",
661
+ text: nonEmptyThinkingBlocks.map((block) => sanitizeSurrogates(block.thinking)).join("\n\n")
662
+ }, ...assistantTextParts];
663
+ else {
664
+ if (assistantText.length > 0) assistantMsg.content = assistantText;
665
+ let signature = nonEmptyThinkingBlocks[0].thinkingSignature;
666
+ if (model.provider === "opencode-go" && signature === "reasoning") signature = "reasoning_content";
667
+ if (signature && signature.length > 0) assistantMsg[signature] = nonEmptyThinkingBlocks.map((block) => block.thinking).join("\n");
668
+ }
669
+ else if (assistantText.length > 0) assistantMsg.content = assistantText;
670
+ const toolCalls = msg.content.filter(isToolCallBlock);
671
+ if (toolCalls.length > 0) {
672
+ assistantMsg.tool_calls = toolCalls.map((tc) => ({
673
+ id: tc.id,
674
+ type: "function",
675
+ function: {
676
+ name: tc.name,
677
+ arguments: JSON.stringify(tc.arguments)
678
+ }
679
+ }));
680
+ const reasoningDetails = toolCalls.filter((tc) => tc.thoughtSignature).map((tc) => {
681
+ try {
682
+ return JSON.parse(tc.thoughtSignature);
683
+ } catch {
684
+ return null;
685
+ }
686
+ }).filter(Boolean);
687
+ if (reasoningDetails.length > 0) assistantMsg.reasoning_details = reasoningDetails;
688
+ }
689
+ if (compat.requiresReasoningContentOnAssistantMessages && model.reasoning && assistantMsg.reasoning_content === void 0) assistantMsg.reasoning_content = "";
690
+ const content = assistantMsg.content;
691
+ if (!(content !== null && content !== void 0 && (typeof content === "string" ? content.length > 0 : content.length > 0)) && !assistantMsg.tool_calls) continue;
692
+ params.push(assistantMsg);
693
+ } else if (msg.role === "toolResult") {
694
+ const imageBlocks = [];
695
+ let j = i;
696
+ for (; j < transformedMessages.length && transformedMessages[j].role === "toolResult"; j++) {
697
+ const toolMsg = transformedMessages[j];
698
+ const textResult = extractToolResultText(toolMsg.content);
699
+ const mediaPlaceholder = describeToolResultMediaPlaceholder(toolMsg.content);
700
+ const hasImages = toolMsg.content.some((c) => c.type === "image");
701
+ const toolResultMsg = {
702
+ role: "tool",
703
+ content: sanitizeToolResultText(textResult, mediaPlaceholder ?? EMPTY_TOOL_RESULT_TEXT),
704
+ tool_call_id: toolMsg.toolCallId
705
+ };
706
+ if (compat.requiresToolResultName && toolMsg.toolName) toolResultMsg.name = toolMsg.toolName;
707
+ params.push(toolResultMsg);
708
+ if (hasImages && model.input.includes("image")) {
709
+ for (const block of toolMsg.content) if (isImageContentBlock(block)) imageBlocks.push({
710
+ type: "image_url",
711
+ image_url: { url: `data:${block.mimeType};base64,${block.data}` }
712
+ });
713
+ }
714
+ }
715
+ i = j - 1;
716
+ if (imageBlocks.length > 0) {
717
+ if (compat.requiresAssistantAfterToolResult) params.push({
718
+ role: "assistant",
719
+ content: "I have processed the tool results."
720
+ });
721
+ params.push({
722
+ role: "user",
723
+ content: [{
724
+ type: "text",
725
+ text: "Attached image(s) from tool result:"
726
+ }, ...imageBlocks]
727
+ });
728
+ lastRole = "user";
729
+ } else lastRole = "toolResult";
730
+ continue;
731
+ }
732
+ lastRole = msg.role;
733
+ }
734
+ return params;
735
+ }
590
736
  function convertTools(tools, compat) {
591
737
  const projection = projectOpenAITools(tools);
592
738
  return {
@@ -626,5 +772,73 @@ function parseChunkUsage(rawUsage, model) {
626
772
  applyProviderReportedUsageCost(usage, rawUsage.cost);
627
773
  return usage;
628
774
  }
775
+ /**
776
+ * Detect compatibility settings from provider and baseUrl for known providers.
777
+ * Provider takes precedence over URL-based detection since it's explicitly configured.
778
+ * Returns a fully resolved OpenAICompletionsCompat object with all fields set.
779
+ */
780
+ function detectCompat(model) {
781
+ const provider = model.provider;
782
+ const baseUrl = model.baseUrl;
783
+ const isZai = provider === "zai" || baseUrl.includes("api.z.ai");
784
+ const isTogether = provider === "together" || baseUrl.includes("api.together.ai") || baseUrl.includes("api.together.xyz");
785
+ const isMoonshot = provider === "moonshotai" || provider === "moonshotai-cn" || baseUrl.includes("api.moonshot.");
786
+ const isCloudflareWorkersAI = provider === "cloudflare-workers-ai" || baseUrl.includes("api.cloudflare.com");
787
+ const isCloudflareAiGateway = provider === "cloudflare-ai-gateway" || baseUrl.includes("gateway.ai.cloudflare.com");
788
+ const isNonStandard = provider === "cerebras" || baseUrl.includes("cerebras.ai") || provider === "xai" || baseUrl.includes("api.x.ai") || isTogether || baseUrl.includes("chutes.ai") || baseUrl.includes("deepseek.com") || isZai || isMoonshot || provider === "opencode" || baseUrl.includes("opencode.ai") || isCloudflareWorkersAI || isCloudflareAiGateway;
789
+ const useMaxTokens = baseUrl.includes("chutes.ai") || isMoonshot || isCloudflareAiGateway || isTogether || isZai;
790
+ const isGrok = provider === "xai" || baseUrl.includes("api.x.ai");
791
+ const isDeepSeek = provider === "deepseek" || baseUrl.includes("deepseek.com");
792
+ const isXiaomi = provider === "xiaomi" || baseUrl.includes("xiaomimimo.com");
793
+ const cacheControlFormat = provider === "openrouter" && model.id.startsWith("anthropic/") ? "anthropic" : void 0;
794
+ return {
795
+ supportsStore: !isNonStandard,
796
+ supportsDeveloperRole: !isNonStandard,
797
+ supportsReasoningEffort: !isGrok && !isZai && !isMoonshot && !isTogether && !isCloudflareAiGateway,
798
+ supportsUsageInStreaming: true,
799
+ maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
800
+ requiresToolResultName: false,
801
+ requiresAssistantAfterToolResult: false,
802
+ requiresThinkingAsText: false,
803
+ requiresReasoningContentOnAssistantMessages: isDeepSeek || isXiaomi,
804
+ thinkingFormat: isDeepSeek ? "deepseek" : isXiaomi ? "deepseek" : isZai ? "zai" : isTogether ? "together" : provider === "openrouter" || baseUrl.includes("openrouter.ai") ? "openrouter" : "openai",
805
+ openRouterRouting: {},
806
+ vercelGatewayRouting: {},
807
+ zaiToolStream: false,
808
+ supportsStrictMode: !isMoonshot && !isTogether && !isCloudflareAiGateway,
809
+ cacheControlFormat,
810
+ sendSessionAffinityHeaders: false,
811
+ supportsPromptCacheKey: false,
812
+ supportsLongCacheRetention: !(isTogether || isCloudflareWorkersAI || isCloudflareAiGateway)
813
+ };
814
+ }
815
+ /**
816
+ * Get resolved compatibility settings for a model.
817
+ * Uses explicit model.compat if provided, otherwise auto-detects from provider/URL.
818
+ */
819
+ function getCompat(model) {
820
+ const detected = detectCompat(model);
821
+ if (!model.compat) return detected;
822
+ return {
823
+ supportsStore: model.compat.supportsStore ?? detected.supportsStore,
824
+ supportsDeveloperRole: model.compat.supportsDeveloperRole ?? detected.supportsDeveloperRole,
825
+ supportsReasoningEffort: model.compat.supportsReasoningEffort ?? detected.supportsReasoningEffort,
826
+ supportsUsageInStreaming: model.compat.supportsUsageInStreaming ?? detected.supportsUsageInStreaming,
827
+ maxTokensField: model.compat.maxTokensField ?? detected.maxTokensField,
828
+ requiresToolResultName: model.compat.requiresToolResultName ?? detected.requiresToolResultName,
829
+ requiresAssistantAfterToolResult: model.compat.requiresAssistantAfterToolResult ?? detected.requiresAssistantAfterToolResult,
830
+ requiresThinkingAsText: model.compat.requiresThinkingAsText ?? detected.requiresThinkingAsText,
831
+ requiresReasoningContentOnAssistantMessages: model.compat.requiresReasoningContentOnAssistantMessages ?? detected.requiresReasoningContentOnAssistantMessages,
832
+ thinkingFormat: model.compat.thinkingFormat ?? detected.thinkingFormat,
833
+ openRouterRouting: model.compat.openRouterRouting ?? {},
834
+ vercelGatewayRouting: model.compat.vercelGatewayRouting ?? detected.vercelGatewayRouting,
835
+ zaiToolStream: model.compat.zaiToolStream ?? detected.zaiToolStream,
836
+ supportsStrictMode: model.compat.supportsStrictMode ?? detected.supportsStrictMode,
837
+ cacheControlFormat: model.compat.cacheControlFormat ?? detected.cacheControlFormat,
838
+ sendSessionAffinityHeaders: model.compat.sendSessionAffinityHeaders ?? detected.sendSessionAffinityHeaders,
839
+ supportsPromptCacheKey: model.compat.supportsPromptCacheKey ?? detected.supportsPromptCacheKey,
840
+ supportsLongCacheRetention: model.compat.supportsLongCacheRetention ?? detected.supportsLongCacheRetention
841
+ };
842
+ }
629
843
  //#endregion
630
- export { streamOpenAICompletions as n, streamSimpleOpenAICompletions as r, openai_completions_exports as t };
844
+ export { mapOpenAIStopReason as a, streamSimpleOpenAICompletions as i, openai_completions_exports as n, streamOpenAICompletions as r, convertMessages as t };
@@ -1,12 +1,10 @@
1
- import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-DrgeBuva.mjs";
2
- import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
3
- import { n as getAiTransportHost } from "./host-Dog2WQiR.mjs";
4
- import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
5
- import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
6
- import { _t as supportsOpenAITemperature } from "./openai-responses-stream-internal-Cw5txaGW.mjs";
7
- import { i as resolveCloudflareBaseUrl, n as hasCopilotVisionInput, r as isCloudflareProvider, t as buildCopilotDynamicHeaders } from "./github-copilot-headers-NCJtz9i0.mjs";
8
- import { n as buildBaseOptions } from "./simple-options-9lhRrN73.mjs";
9
- import { a as runResponsesStreamLifecycle, i as resolveResponsesReasoningEffort, n as convertResponsesMessages, r as createResponsesAssistantOutput, t as applyCommonResponsesParams } from "./openai-responses-shared-pXl6Wd8S.mjs";
1
+ import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-CtMlqaQ4.mjs";
2
+ import { t as AssistantMessageEventStream } from "./event-stream-ReMmOTzX.mjs";
3
+ import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
4
+ import { o as buildBaseOptions } from "./transform-messages-BhGF_fF4.mjs";
5
+ import { a as resolveCacheRetention, i as resolveCloudflareBaseUrl, n as hasCopilotVisionInput, r as isCloudflareProvider, t as buildCopilotDynamicHeaders } from "./github-copilot-headers-BsH5cqGj.mjs";
6
+ import { a as resolveResponsesReasoningEffort, n as convertResponsesMessages, o as runResponsesStreamLifecycle, r as createResponsesAssistantOutput, t as applyCommonResponsesParams } from "./openai-responses-shared-L3PWZvkm.mjs";
7
+ import { a as clampOpenAIPromptCacheKey } from "./openai-tool-projection-BPlyXt8H.mjs";
10
8
  import OpenAI from "openai";
11
9
  //#region packages/ai/src/providers/openai-responses.ts
12
10
  var openai_responses_exports = /* @__PURE__ */ __exportAll({
@@ -113,7 +111,7 @@ function buildParams(model, context, options) {
113
111
  store: false
114
112
  };
115
113
  if (options?.maxTokens) params.max_output_tokens = options?.maxTokens;
116
- if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options?.temperature;
114
+ if (options?.temperature !== void 0) params.temperature = options?.temperature;
117
115
  if (options?.serviceTier !== void 0) params.service_tier = options.serviceTier;
118
116
  applyCommonResponsesParams(params, model, context, options, { setDefaultReasoningOff: model.provider !== "github-copilot" });
119
117
  return params;