@openclaw/ai 2026.7.2-beta.2 → 2026.7.2-beta.4

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 (46) hide show
  1. package/README.md +6 -5
  2. package/dist/{anthropic-BIRSg5x9.mjs → anthropic-CrUDIBpM.mjs} +173 -47
  3. package/dist/{api-registry-Byvoz8Ha.d.mts → api-registry-BMphkFf1.d.mts} +1 -2
  4. package/dist/{azure-openai-responses-CHi7Wo4A.mjs → azure-openai-responses-CbrpVeEv.mjs} +9 -11
  5. package/dist/{env-api-keys-DnhYpc27.mjs → env-api-keys-DrgeBuva.mjs} +1 -1
  6. package/dist/{event-stream-uQspnL8S.d.mts → event-stream-Douf9dob.d.mts} +1 -1
  7. package/dist/event-stream.d.mts +1 -1
  8. package/dist/{google-BmsqsNwR.mjs → google-Cs62KA7t.mjs} +4 -4
  9. package/dist/{google-shared-Dx2aba47.mjs → google-shared-CMLI-tCZ.mjs} +4 -3
  10. package/dist/{google-vertex-HZ_0rTwS.mjs → google-vertex-B4SD3U0f.mjs} +3 -3
  11. package/dist/host-WvWBo4h8.d.mts +173 -0
  12. package/dist/host-XYGZcgO8.mjs +98 -0
  13. package/dist/index-BVVgDSdq.d.mts +1 -0
  14. package/dist/index.d.mts +7 -50
  15. package/dist/index.mjs +1 -1
  16. package/dist/internal/anthropic.d.mts +9 -3
  17. package/dist/internal/anthropic.mjs +3 -3
  18. package/dist/internal/openai.d.mts +2 -279
  19. package/dist/internal/openai.mjs +5 -5
  20. package/dist/internal/runtime.d.mts +8 -5
  21. package/dist/internal/runtime.mjs +22 -12
  22. package/dist/internal/shared.d.mts +4 -2
  23. package/dist/internal/shared.mjs +2 -2
  24. package/dist/{mistral-DxMPt9q9.mjs → mistral-D5Ps7Led.mjs} +26 -10
  25. package/dist/{model-utils-Q1LSRIdo.mjs → model-utils-1GiZ2_rr.mjs} +3 -1
  26. package/dist/openai-CoGicoDt.d.mts +332 -0
  27. package/dist/{openai-chatgpt-responses-BuH2NvsR.mjs → openai-chatgpt-responses-h0o5yV8Y.mjs} +47 -48
  28. package/dist/{openai-completions-DPR_O2RW.mjs → openai-completions-exO8NFQf.mjs} +342 -102
  29. package/dist/{openai-responses-Cov-Vdc2.mjs → openai-responses-BHpmtUKo.mjs} +5 -5
  30. package/dist/{openai-responses-shared-Befb4D6R.mjs → openai-responses-shared-CzCurmY1.mjs} +527 -268
  31. package/dist/{openai-tool-projection-CFqm42J2.mjs → openai-tool-projection-ITOU9bG1.mjs} +1 -1
  32. package/dist/provider-error-C4VvV_3t.mjs +41 -0
  33. package/dist/providers.d.mts +1 -1
  34. package/dist/providers.mjs +8 -8
  35. package/dist/{stream-first-event-timeout-RjWszj8c.mjs → stream-first-event-timeout-DP4xEyBY.mjs} +45 -1
  36. package/dist/{transform-messages-BmS70CP5.mjs → system-prompt-cache-boundary-CbHeV4_l.mjs} +171 -161
  37. package/dist/transports.d.mts +590 -0
  38. package/dist/transports.mjs +5701 -0
  39. package/dist/{types-Cx2zJtyz.d.mts → types-AFwwWium.d.mts} +7 -0
  40. package/dist/types.d.mts +4 -4
  41. package/dist/{validation-Cej7htKc.d.mts → validation-sxvxC8J-.d.mts} +1 -1
  42. package/dist/validation.d.mts +1 -1
  43. package/npm-shrinkwrap.json +43 -50
  44. package/package.json +36 -10
  45. package/dist/host-4t713IeR.mjs +0 -37
  46. /package/dist/{index-BoTnz8cv.d.mts → anthropic-BoTnz8cv.d.mts} +0 -0
@@ -1,16 +1,299 @@
1
- import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-DnhYpc27.mjs";
1
+ import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-DrgeBuva.mjs";
2
2
  import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
3
- import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
4
- import { n as calculateCost, r as clampThinkingLevel, t as applyProviderReportedUsageCost } from "./model-utils-Q1LSRIdo.mjs";
3
+ import { n as getAiTransportHost } from "./host-XYGZcgO8.mjs";
4
+ import { C as isImageWithMediaPayload, D as buildBaseOptions, a as stripSystemPromptCacheBoundary, c as transformMessages, g as normalizeLowercaseStringOrEmpty, i as splitSystemPromptCacheBoundary, x as extractToolResultText, y as describeToolResultMediaPlaceholder } from "./system-prompt-cache-boundary-CbHeV4_l.mjs";
5
+ import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
6
+ import { n as calculateCost, r as clampThinkingLevel, t as applyProviderReportedUsageCost } from "./model-utils-1GiZ2_rr.mjs";
5
7
  import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
6
8
  import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
7
- import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
8
- import { C as stripSystemPromptCacheBoundary, S as splitSystemPromptCacheBoundary, i as extractToolResultText, l as buildBaseOptions, n as describeToolResultMediaPlaceholder, o as isImageWithMediaPayload, t as transformMessages } from "./transform-messages-BmS70CP5.mjs";
9
9
  import { a as resolveCacheRetention, i as resolveCloudflareBaseUrl, n as hasCopilotVisionInput, r as isCloudflareProvider, t as buildCopilotDynamicHeaders } from "./github-copilot-headers-BsH5cqGj.mjs";
10
10
  import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-BlVe67g6.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-CFqm42J2.mjs";
11
+ import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-DP4xEyBY.mjs";
12
+ import { t as formatProviderError } from "./provider-error-C4VvV_3t.mjs";
13
+ import { a as clampOpenAIPromptCacheKey, n as reconcileOpenAICompletionsToolChoice, t as projectOpenAITools } from "./openai-tool-projection-ITOU9bG1.mjs";
13
14
  import OpenAI from "openai";
15
+ //#region packages/ai/src/utils/assistant-text-phase.ts
16
+ function isAssistantTextPhaseBlock(block) {
17
+ if (!block || typeof block !== "object") return false;
18
+ const record = block;
19
+ return record.type === "text" && typeof record.text === "string";
20
+ }
21
+ function encodeAssistantTextSignatureV1(id, phase) {
22
+ return JSON.stringify({
23
+ v: 1,
24
+ id,
25
+ ...phase ? { phase } : {}
26
+ });
27
+ }
28
+ /** Tags unphased narration before a tool-call event becomes consumer-visible. */
29
+ function tagPendingCommentaryText(content) {
30
+ const textBlocks = content.filter(isAssistantTextPhaseBlock);
31
+ let commentaryIndex = textBlocks.filter((block) => block.textSignature !== void 0).length;
32
+ const tagged = /* @__PURE__ */ new Map();
33
+ for (const block of textBlocks) {
34
+ if (block.text.trim().length === 0 || block.textSignature !== void 0) continue;
35
+ const signature = encodeAssistantTextSignatureV1(`commentary-${commentaryIndex}`, "commentary");
36
+ block.textSignature = signature;
37
+ tagged.set(block, signature);
38
+ commentaryIndex += 1;
39
+ }
40
+ return tagged;
41
+ }
42
+ /** Rolls back only the exact provisional signatures created by this transport turn. */
43
+ function clearPendingCommentaryText(tags) {
44
+ for (const [block, signature] of tags) if (block.textSignature === signature) delete block.textSignature;
45
+ tags.clear();
46
+ }
47
+ function rememberPendingCommentaryTags(target, tagged) {
48
+ for (const [block, signature] of tagged) target.set(block, signature);
49
+ }
50
+ //#endregion
51
+ //#region packages/ai/src/transports/openai-reasoning-compat.ts
52
+ /**
53
+ * OpenAI reasoning-effort compatibility helpers.
54
+ *
55
+ * Keeps provider metadata and built-in model exceptions on one path before request payloads are built.
56
+ */
57
+ const OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.1-codex-mini"]);
58
+ function readCompatReasoningEffortMap(compat) {
59
+ if (!compat || typeof compat !== "object") return {};
60
+ const rawMap = compat.reasoningEffortMap;
61
+ if (!rawMap || typeof rawMap !== "object") return {};
62
+ return Object.fromEntries(Object.entries(rawMap).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string"));
63
+ }
64
+ /** Resolves the reasoning effort remap for an OpenAI-compatible model. */
65
+ function resolveOpenAIReasoningEffortMap(model, fallbackMap = {}) {
66
+ const provider = normalizeLowercaseStringOrEmpty(model.provider ?? "");
67
+ const id = normalizeLowercaseStringOrEmpty(model.id ?? "");
68
+ const builtinMap = provider === "openai" && OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS.has(id) ? {
69
+ minimal: "medium",
70
+ low: "medium"
71
+ } : {};
72
+ return {
73
+ ...fallbackMap,
74
+ ...builtinMap,
75
+ ...readCompatReasoningEffortMap(model.compat)
76
+ };
77
+ }
78
+ //#endregion
79
+ //#region packages/ai/src/providers/openai-completions-compat.ts
80
+ const DEFAULT_OPENAI_COMPLETIONS_COMPAT = {
81
+ supportsStore: true,
82
+ supportsDeveloperRole: true,
83
+ supportsReasoningEffort: true,
84
+ supportsUsageInStreaming: true,
85
+ maxTokensField: "max_completion_tokens",
86
+ requiresToolResultName: false,
87
+ requiresAssistantAfterToolResult: false,
88
+ requiresThinkingAsText: false,
89
+ requiresReasoningContentOnAssistantMessages: false,
90
+ thinkingFormat: "openai",
91
+ vercelGatewayRouting: {},
92
+ zaiToolStream: false,
93
+ supportsStrictMode: true,
94
+ cacheControlFormat: void 0,
95
+ sessionAffinityFormat: "openai",
96
+ supportsPromptCacheKey: false,
97
+ supportsLongCacheRetention: true
98
+ };
99
+ const OPENAI_COMPLETIONS_COMPAT_MATRIX = {
100
+ openrouter: {
101
+ priority: 10,
102
+ providers: ["openrouter"],
103
+ baseUrlIncludes: ["openrouter.ai"],
104
+ compat: {
105
+ supportsDeveloperRole: false,
106
+ thinkingFormat: "openrouter",
107
+ sessionAffinityFormat: "openrouter"
108
+ }
109
+ },
110
+ cerebras: {
111
+ priority: 20,
112
+ providers: ["cerebras"],
113
+ baseUrlIncludes: ["cerebras.ai"],
114
+ compat: {
115
+ supportsStore: false,
116
+ supportsDeveloperRole: false
117
+ }
118
+ },
119
+ xai: {
120
+ priority: 20,
121
+ providers: ["xai"],
122
+ baseUrlIncludes: ["api.x.ai"],
123
+ compat: {
124
+ supportsStore: false,
125
+ supportsDeveloperRole: false,
126
+ supportsReasoningEffort: false
127
+ }
128
+ },
129
+ moonshot: {
130
+ priority: 20,
131
+ providers: ["moonshotai", "moonshotai-cn"],
132
+ baseUrlIncludes: ["api.moonshot."],
133
+ compat: {
134
+ supportsStore: false,
135
+ supportsDeveloperRole: false,
136
+ supportsReasoningEffort: false,
137
+ maxTokensField: "max_tokens",
138
+ supportsStrictMode: false
139
+ }
140
+ },
141
+ cloudflareWorkersAi: {
142
+ priority: 20,
143
+ providers: ["cloudflare-workers-ai"],
144
+ baseUrlIncludes: ["api.cloudflare.com"],
145
+ compat: {
146
+ supportsStore: false,
147
+ supportsDeveloperRole: false,
148
+ supportsLongCacheRetention: false
149
+ }
150
+ },
151
+ cloudflareAiGateway: {
152
+ priority: 20,
153
+ providers: ["cloudflare-ai-gateway"],
154
+ baseUrlIncludes: ["gateway.ai.cloudflare.com"],
155
+ compat: {
156
+ supportsStore: false,
157
+ supportsDeveloperRole: false,
158
+ supportsReasoningEffort: false,
159
+ maxTokensField: "max_tokens",
160
+ supportsStrictMode: false,
161
+ supportsLongCacheRetention: false
162
+ }
163
+ },
164
+ opencode: {
165
+ priority: 20,
166
+ providers: ["opencode"],
167
+ baseUrlIncludes: ["opencode.ai"],
168
+ compat: {
169
+ supportsStore: false,
170
+ supportsDeveloperRole: false
171
+ }
172
+ },
173
+ chutes: {
174
+ priority: 20,
175
+ baseUrlIncludes: ["chutes.ai"],
176
+ compat: {
177
+ supportsStore: false,
178
+ supportsDeveloperRole: false,
179
+ maxTokensField: "max_tokens"
180
+ }
181
+ },
182
+ together: {
183
+ priority: 30,
184
+ providers: ["together"],
185
+ baseUrlIncludes: ["api.together.ai", "api.together.xyz"],
186
+ compat: {
187
+ supportsStore: false,
188
+ supportsDeveloperRole: false,
189
+ supportsReasoningEffort: false,
190
+ maxTokensField: "max_tokens",
191
+ thinkingFormat: "together",
192
+ supportsStrictMode: false,
193
+ supportsLongCacheRetention: false
194
+ }
195
+ },
196
+ zai: {
197
+ priority: 40,
198
+ providers: ["zai"],
199
+ baseUrlIncludes: ["api.z.ai"],
200
+ compat: {
201
+ supportsStore: false,
202
+ supportsDeveloperRole: false,
203
+ supportsReasoningEffort: false,
204
+ maxTokensField: "max_tokens",
205
+ thinkingFormat: "zai"
206
+ }
207
+ },
208
+ xiaomi: {
209
+ priority: 50,
210
+ providers: ["xiaomi"],
211
+ baseUrlIncludes: ["xiaomimimo.com"],
212
+ compat: {
213
+ thinkingFormat: "deepseek",
214
+ requiresReasoningContentOnAssistantMessages: true
215
+ }
216
+ },
217
+ deepseekProvider: {
218
+ priority: 60,
219
+ providers: ["deepseek"],
220
+ compat: {
221
+ thinkingFormat: "deepseek",
222
+ requiresReasoningContentOnAssistantMessages: true
223
+ }
224
+ },
225
+ deepseekEndpoint: {
226
+ priority: 60,
227
+ baseUrlIncludes: ["deepseek.com"],
228
+ compat: {
229
+ supportsStore: false,
230
+ supportsDeveloperRole: false,
231
+ thinkingFormat: "deepseek",
232
+ requiresReasoningContentOnAssistantMessages: true
233
+ }
234
+ }
235
+ };
236
+ const OPENAI_COMPLETIONS_MODEL_COMPAT_MATRIX = [{
237
+ profile: "openrouter",
238
+ modelIdPrefixes: ["anthropic/", "openai/"],
239
+ compat: { supportsDeveloperRole: true }
240
+ }, {
241
+ providers: ["openrouter"],
242
+ modelIdPrefixes: ["anthropic/"],
243
+ compat: { cacheControlFormat: "anthropic" }
244
+ }];
245
+ const SORTED_OPENAI_COMPLETIONS_COMPAT_RULES = Object.entries(OPENAI_COMPLETIONS_COMPAT_MATRIX).toSorted(([, left], [, right]) => left.priority - right.priority);
246
+ function matchesCompatRule(model, rule) {
247
+ return rule.providers?.includes(model.provider) === true || rule.baseUrlIncludes?.some((fragment) => model.baseUrl.includes(fragment)) === true;
248
+ }
249
+ function matchesModelCompatRule(model, matchedProfiles, rule) {
250
+ if (rule.profile !== void 0 && !matchedProfiles.has(rule.profile)) return false;
251
+ if (rule.providers !== void 0 && !rule.providers.includes(model.provider)) return false;
252
+ return rule.modelIdPrefixes.some((prefix) => model.id.startsWith(prefix));
253
+ }
254
+ /** Detects request compatibility from the provider, endpoint, and model family matrices. */
255
+ function detectOpenAICompletionsCompat(model) {
256
+ const compat = { ...DEFAULT_OPENAI_COMPLETIONS_COMPAT };
257
+ const matchedProfiles = /* @__PURE__ */ new Set();
258
+ for (const [profile, rule] of SORTED_OPENAI_COMPLETIONS_COMPAT_RULES) {
259
+ if (!matchesCompatRule(model, rule)) continue;
260
+ Object.assign(compat, rule.compat);
261
+ matchedProfiles.add(profile);
262
+ }
263
+ for (const rule of OPENAI_COMPLETIONS_MODEL_COMPAT_MATRIX) if (matchesModelCompatRule(model, matchedProfiles, rule)) Object.assign(compat, rule.compat);
264
+ return compat;
265
+ }
266
+ function resolveSessionAffinity(model, detectedFormat) {
267
+ if (model.compat?.sendSessionAffinityHeaders !== true) return "none";
268
+ if (detectedFormat === "openrouter" || model.compat.thinkingFormat === "openrouter" || model.compat.openRouterRouting !== void 0) return "openrouter";
269
+ return "openai";
270
+ }
271
+ /** Applies explicit model overrides to the detected compatibility defaults. */
272
+ function resolveOpenAICompletionsCompat(model) {
273
+ const detected = detectOpenAICompletionsCompat(model);
274
+ const configured = model.compat;
275
+ return {
276
+ supportsStore: configured?.supportsStore ?? detected.supportsStore,
277
+ supportsDeveloperRole: configured?.supportsDeveloperRole ?? detected.supportsDeveloperRole,
278
+ supportsReasoningEffort: configured?.supportsReasoningEffort ?? detected.supportsReasoningEffort,
279
+ supportsUsageInStreaming: configured?.supportsUsageInStreaming ?? detected.supportsUsageInStreaming,
280
+ maxTokensField: configured?.maxTokensField ?? detected.maxTokensField,
281
+ requiresToolResultName: configured?.requiresToolResultName ?? detected.requiresToolResultName,
282
+ requiresAssistantAfterToolResult: configured?.requiresAssistantAfterToolResult ?? detected.requiresAssistantAfterToolResult,
283
+ requiresThinkingAsText: configured?.requiresThinkingAsText ?? detected.requiresThinkingAsText,
284
+ requiresReasoningContentOnAssistantMessages: configured?.requiresReasoningContentOnAssistantMessages ?? detected.requiresReasoningContentOnAssistantMessages,
285
+ thinkingFormat: configured?.thinkingFormat ?? detected.thinkingFormat,
286
+ openRouterRouting: configured?.openRouterRouting,
287
+ vercelGatewayRouting: configured?.vercelGatewayRouting ?? detected.vercelGatewayRouting,
288
+ zaiToolStream: configured?.zaiToolStream ?? detected.zaiToolStream,
289
+ supportsStrictMode: configured?.supportsStrictMode ?? detected.supportsStrictMode,
290
+ cacheControlFormat: configured?.cacheControlFormat ?? detected.cacheControlFormat,
291
+ sessionAffinity: resolveSessionAffinity(model, detected.sessionAffinityFormat),
292
+ supportsPromptCacheKey: configured?.supportsPromptCacheKey ?? detected.supportsPromptCacheKey,
293
+ supportsLongCacheRetention: configured?.supportsLongCacheRetention ?? detected.supportsLongCacheRetention
294
+ };
295
+ }
296
+ //#endregion
14
297
  //#region packages/ai/src/providers/openai-stop-reason.ts
15
298
  function mapOpenAIStopReason(reason, options) {
16
299
  if (reason === null) return { stopReason: "stop" };
@@ -72,6 +355,11 @@ function sanitizeToolResultText(text, fallback) {
72
355
  const sanitized = sanitizeSurrogates(text);
73
356
  return sanitized.trim().length > 0 ? sanitized : fallback;
74
357
  }
358
+ function isEncryptedReasoningDetail(detail) {
359
+ if (typeof detail !== "object" || detail === null) return false;
360
+ const candidate = detail;
361
+ return candidate.type === "reasoning.encrypted" && typeof candidate.id === "string" && candidate.id.length > 0 && typeof candidate.data === "string" && candidate.data.length > 0;
362
+ }
75
363
  const streamOpenAICompletions = (model, context, options) => {
76
364
  const stream = new AssistantMessageEventStream();
77
365
  (async () => {
@@ -98,10 +386,11 @@ const streamOpenAICompletions = (model, context, options) => {
98
386
  stopReason: "stop",
99
387
  timestamp: Date.now()
100
388
  };
389
+ const provisionalCommentaryTags = /* @__PURE__ */ new Map();
101
390
  let firstEventAbort;
102
391
  try {
103
392
  const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
104
- const compat = getCompat(model);
393
+ const compat = resolveOpenAICompletionsCompat(model);
105
394
  const cacheRetention = resolveCacheRetention(options?.cacheRetention);
106
395
  const cacheSessionId = cacheRetention === "none" ? void 0 : options?.sessionId;
107
396
  const client = createClient(model, context, apiKey, options?.headers, cacheSessionId, compat);
@@ -112,7 +401,7 @@ const streamOpenAICompletions = (model, context, options) => {
112
401
  const requestOptions = {
113
402
  signal: firstEventAbort.signal,
114
403
  ...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
115
- ...options?.maxRetries !== void 0 ? { maxRetries: options.maxRetries } : {}
404
+ maxRetries: options?.maxRetries ?? 0
116
405
  };
117
406
  const { data: openaiStream, response } = await client.chat.completions.create(params, requestOptions).withResponse();
118
407
  await options?.onResponse?.({
@@ -129,6 +418,7 @@ const streamOpenAICompletions = (model, context, options) => {
129
418
  const toolCallBlocksByIndex = /* @__PURE__ */ new Map();
130
419
  const toolCallBlocksById = /* @__PURE__ */ new Map();
131
420
  const toolCallBlocksByFirstId = /* @__PURE__ */ new Map();
421
+ const pendingReasoningDetailsByToolCallId = /* @__PURE__ */ new Map();
132
422
  const blocks = output.content;
133
423
  const finishedBlocks = /* @__PURE__ */ new Set();
134
424
  const contentIndices = /* @__PURE__ */ new WeakMap();
@@ -138,7 +428,13 @@ const streamOpenAICompletions = (model, context, options) => {
138
428
  };
139
429
  const getContentIndex = (block) => contentIndices.get(block) ?? -1;
140
430
  const rememberFirstToolCallById = (id, block) => {
141
- if (!toolCallBlocksByFirstId.has(id)) toolCallBlocksByFirstId.set(id, block);
431
+ if (toolCallBlocksByFirstId.has(id)) return;
432
+ toolCallBlocksByFirstId.set(id, block);
433
+ const pendingDetail = pendingReasoningDetailsByToolCallId.get(id);
434
+ if (pendingDetail) {
435
+ block.thoughtSignature = pendingDetail;
436
+ pendingReasoningDetailsByToolCallId.delete(id);
437
+ }
142
438
  };
143
439
  const finishBlock = (block) => {
144
440
  const contentIndex = getContentIndex(block);
@@ -315,9 +611,10 @@ const streamOpenAICompletions = (model, context, options) => {
315
611
  if (choiceDelta.content !== null && choiceDelta.content !== void 0 && choiceDelta.content.length > 0) appendPartitionedContent(choiceDelta.content, Boolean(foundReasoningField));
316
612
  const refusalText = typeof choiceDelta.refusal === "string" ? choiceDelta.refusal : "";
317
613
  if (refusalText.length > 0) appendPartitionedContent(refusalText, Boolean(foundReasoningField));
318
- if (choiceDelta.tool_calls) {
614
+ if (choiceDelta.tool_calls && choiceDelta.tool_calls.length > 0) {
319
615
  flushPartitionedContent();
320
616
  sealNativeReasoningBeforeText();
617
+ rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
321
618
  for (const toolCall of choiceDelta.tool_calls) {
322
619
  const block = ensureToolCallBlock(toolCall);
323
620
  if (!block.id && toolCall.id) {
@@ -341,10 +638,12 @@ const streamOpenAICompletions = (model, context, options) => {
341
638
  }
342
639
  }
343
640
  const reasoningDetails = choiceDelta.reasoning_details;
344
- if (reasoningDetails && Array.isArray(reasoningDetails)) {
345
- for (const detail of reasoningDetails) if (detail.type === "reasoning.encrypted" && detail.id && detail.data) {
641
+ if (Array.isArray(reasoningDetails)) {
642
+ for (const detail of reasoningDetails) if (isEncryptedReasoningDetail(detail)) {
643
+ const serializedDetail = JSON.stringify(detail);
346
644
  const matchingToolCall = toolCallBlocksByFirstId.get(detail.id);
347
- if (matchingToolCall) matchingToolCall.thoughtSignature = JSON.stringify(detail);
645
+ if (matchingToolCall) matchingToolCall.thoughtSignature = serializedDetail;
646
+ else pendingReasoningDetailsByToolCallId.set(detail.id, serializedDetail);
348
647
  }
349
648
  }
350
649
  }
@@ -360,6 +659,8 @@ const streamOpenAICompletions = (model, context, options) => {
360
659
  if (output.stopReason === "toolUse" && !hasToolCalls) output.stopReason = "stop";
361
660
  if (output.stopReason === "stop" && hasToolCalls && !hasVisibleText) output.stopReason = "toolUse";
362
661
  if (hasToolCalls && output.stopReason !== "toolUse") output.content = output.content.filter((block) => block.type !== "toolCall");
662
+ if (output.stopReason !== "toolUse") clearPendingCommentaryText(provisionalCommentaryTags);
663
+ if (output.stopReason === "toolUse") tagPendingCommentaryText(output.content);
363
664
  stream.push({
364
665
  type: "done",
365
666
  reason: output.stopReason,
@@ -373,9 +674,9 @@ const streamOpenAICompletions = (model, context, options) => {
373
674
  delete block.streamIndex;
374
675
  }
375
676
  output.stopReason = options?.signal?.aborted ? "aborted" : "error";
376
- output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
677
+ output.errorMessage = formatProviderError(error);
377
678
  const rawMetadata = error?.error?.metadata?.raw;
378
- if (rawMetadata) output.errorMessage += `\n${rawMetadata}`;
679
+ if (rawMetadata && !output.errorMessage.includes(rawMetadata)) output.errorMessage += `\n${rawMetadata}`;
379
680
  stream.push({
380
681
  type: "error",
381
682
  reason: output.stopReason,
@@ -401,7 +702,7 @@ const streamSimpleOpenAICompletions = (model, context, options) => {
401
702
  toolChoice
402
703
  });
403
704
  };
404
- function createClient(model, context, apiKey, optionsHeaders, sessionId, compat = getCompat(model)) {
705
+ function createClient(model, context, apiKey, optionsHeaders, sessionId, compat = resolveOpenAICompletionsCompat(model)) {
405
706
  if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
406
707
  const headers = { ...model.headers };
407
708
  if (model.provider === "github-copilot") {
@@ -412,7 +713,8 @@ function createClient(model, context, apiKey, optionsHeaders, sessionId, compat
412
713
  });
413
714
  Object.assign(headers, copilotHeaders);
414
715
  }
415
- if (sessionId && compat.sendSessionAffinityHeaders) {
716
+ if (sessionId && compat.sessionAffinity !== "none") if (compat.sessionAffinity === "openrouter") headers["x-session-id"] = sessionId;
717
+ else {
416
718
  headers.session_id = sessionId;
417
719
  headers["x-client-request-id"] = sessionId;
418
720
  headers["x-session-affinity"] = sessionId;
@@ -431,7 +733,7 @@ function createClient(model, context, apiKey, optionsHeaders, sessionId, compat
431
733
  fetch: getAiTransportHost().buildModelFetch(model)
432
734
  });
433
735
  }
434
- function buildParams(model, context, options, compat = getCompat(model), cacheRetention = resolveCacheRetention(options?.cacheRetention)) {
736
+ function buildParams(model, context, options, compat = resolveOpenAICompletionsCompat(model), cacheRetention = resolveCacheRetention(options?.cacheRetention)) {
435
737
  const cacheControl = getCompatCacheControl(compat, cacheRetention);
436
738
  const cacheOptOutIndexes = /* @__PURE__ */ new Set();
437
739
  const messages = convertMessages(model, context, compat, {
@@ -469,29 +771,35 @@ function buildParams(model, context, options, compat = getCompat(model), cacheRe
469
771
  const toolChoice = reconcileOpenAICompletionsToolChoice(options.toolChoice, toolProjection ?? projectOpenAITools([]));
470
772
  if (toolChoice !== void 0) params.tool_choice = toolChoice;
471
773
  }
472
- if (compat.thinkingFormat === "zai" && model.reasoning) params.thinking = { type: options?.reasoningEffort ? "enabled" : "disabled" };
473
- else if (compat.thinkingFormat === "qwen" && model.reasoning) params.enable_thinking = Boolean(options?.reasoningEffort);
774
+ const reasoningEffortMap = resolveOpenAIReasoningEffortMap(model);
775
+ const reasoningEffort = options?.reasoningEffort === void 0 ? void 0 : reasoningEffortMap[options.reasoningEffort] ?? model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
776
+ const reasoningEnabled = reasoningEffort !== void 0;
777
+ const offReasoningEffort = reasoningEffortMap.off ?? model.thinkingLevelMap?.off;
778
+ if (compat.thinkingFormat === "zai" && model.reasoning) params.thinking = reasoningEnabled ? {
779
+ type: "enabled",
780
+ clear_thinking: false
781
+ } : { type: "disabled" };
782
+ else if (compat.thinkingFormat === "qwen" && model.reasoning) params.enable_thinking = reasoningEnabled;
474
783
  else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) params.chat_template_kwargs = {
475
- enable_thinking: Boolean(options?.reasoningEffort),
784
+ enable_thinking: reasoningEnabled,
476
785
  preserve_thinking: true
477
786
  };
478
787
  else if (compat.thinkingFormat === "deepseek" && model.reasoning) {
479
- params.thinking = { type: options?.reasoningEffort ? "enabled" : "disabled" };
480
- if (options?.reasoningEffort && compat.supportsReasoningEffort) params.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
788
+ params.thinking = { type: reasoningEnabled ? "enabled" : "disabled" };
789
+ if (reasoningEnabled && compat.supportsReasoningEffort) params.reasoning_effort = reasoningEffort;
481
790
  } else if (compat.thinkingFormat === "openrouter" && model.reasoning) {
482
791
  const openRouterParams = params;
483
- if (options?.reasoningEffort) openRouterParams.reasoning = { effort: model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort };
484
- else if (model.thinkingLevelMap?.off !== null) openRouterParams.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
792
+ if (reasoningEnabled) openRouterParams.reasoning = { effort: reasoningEffort };
793
+ else if (offReasoningEffort !== null) openRouterParams.reasoning = { effort: offReasoningEffort ?? "none" };
485
794
  } else if (compat.thinkingFormat === "together" && model.reasoning) {
486
795
  const togetherParams = params;
487
- togetherParams.reasoning = { enabled: Boolean(options?.reasoningEffort) };
488
- if (options?.reasoningEffort && compat.supportsReasoningEffort) togetherParams.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
489
- } else if (options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) params.reasoning_effort = model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort;
490
- else if (!options?.reasoningEffort && model.reasoning && compat.supportsReasoningEffort) {
491
- const offValue = model.thinkingLevelMap?.off;
492
- if (typeof offValue === "string") params.reasoning_effort = offValue;
796
+ togetherParams.reasoning = { enabled: reasoningEnabled };
797
+ if (reasoningEnabled && compat.supportsReasoningEffort) togetherParams.reasoning_effort = reasoningEffort;
798
+ } else if (reasoningEnabled && model.reasoning && compat.supportsReasoningEffort) params.reasoning_effort = reasoningEffort;
799
+ else if (model.reasoning && compat.supportsReasoningEffort) {
800
+ if (typeof offReasoningEffort === "string") params.reasoning_effort = offReasoningEffort;
493
801
  }
494
- if (model.baseUrl.includes("openrouter.ai") && model.compat?.openRouterRouting) params.provider = model.compat.openRouterRouting;
802
+ if (compat.openRouterRouting) params.provider = compat.openRouterRouting;
495
803
  if (model.baseUrl.includes("ai-gateway.vercel.sh") && model.compat?.vercelGatewayRouting) {
496
804
  const routing = model.compat.vercelGatewayRouting;
497
805
  if (routing.only || routing.order) {
@@ -772,73 +1080,5 @@ function parseChunkUsage(rawUsage, model) {
772
1080
  applyProviderReportedUsageCost(usage, rawUsage.cost);
773
1081
  return usage;
774
1082
  }
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
- }
843
1083
  //#endregion
844
- export { mapOpenAIStopReason as a, streamSimpleOpenAICompletions as i, openai_completions_exports as n, streamOpenAICompletions as r, convertMessages as t };
1084
+ export { mapOpenAIStopReason as a, rememberPendingCommentaryTags as c, streamSimpleOpenAICompletions as i, tagPendingCommentaryText as l, openai_completions_exports as n, resolveOpenAIReasoningEffortMap as o, streamOpenAICompletions as r, clearPendingCommentaryText as s, convertMessages as t };
@@ -1,10 +1,10 @@
1
- import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-DnhYpc27.mjs";
1
+ import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-DrgeBuva.mjs";
2
2
  import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
3
- import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
4
- import { l as buildBaseOptions } from "./transform-messages-BmS70CP5.mjs";
3
+ import { n as getAiTransportHost } from "./host-XYGZcgO8.mjs";
4
+ import { D as buildBaseOptions } from "./system-prompt-cache-boundary-CbHeV4_l.mjs";
5
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 { M as supportsOpenAITemperature, a as resolveResponsesReasoningEffort, n as convertResponsesMessages, o as runResponsesStreamLifecycle, r as createResponsesAssistantOutput, t as applyCommonResponsesParams } from "./openai-responses-shared-Befb4D6R.mjs";
7
- import { a as clampOpenAIPromptCacheKey } from "./openai-tool-projection-CFqm42J2.mjs";
6
+ import { L as supportsOpenAITemperature, a as resolveResponsesReasoningEffort, n as convertResponsesMessages, o as runResponsesStreamLifecycle, r as createResponsesAssistantOutput, t as applyCommonResponsesParams } from "./openai-responses-shared-CzCurmY1.mjs";
7
+ import { a as clampOpenAIPromptCacheKey } from "./openai-tool-projection-ITOU9bG1.mjs";
8
8
  import OpenAI from "openai";
9
9
  //#region packages/ai/src/providers/openai-responses.ts
10
10
  var openai_responses_exports = /* @__PURE__ */ __exportAll({