@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.
- package/README.md +6 -5
- package/dist/{anthropic-BIRSg5x9.mjs → anthropic-CrUDIBpM.mjs} +173 -47
- package/dist/{api-registry-Byvoz8Ha.d.mts → api-registry-BMphkFf1.d.mts} +1 -2
- package/dist/{azure-openai-responses-CHi7Wo4A.mjs → azure-openai-responses-CbrpVeEv.mjs} +9 -11
- package/dist/{env-api-keys-DnhYpc27.mjs → env-api-keys-DrgeBuva.mjs} +1 -1
- package/dist/{event-stream-uQspnL8S.d.mts → event-stream-Douf9dob.d.mts} +1 -1
- package/dist/event-stream.d.mts +1 -1
- package/dist/{google-BmsqsNwR.mjs → google-Cs62KA7t.mjs} +4 -4
- package/dist/{google-shared-Dx2aba47.mjs → google-shared-CMLI-tCZ.mjs} +4 -3
- package/dist/{google-vertex-HZ_0rTwS.mjs → google-vertex-B4SD3U0f.mjs} +3 -3
- package/dist/host-WvWBo4h8.d.mts +173 -0
- package/dist/host-XYGZcgO8.mjs +98 -0
- package/dist/index-BVVgDSdq.d.mts +1 -0
- package/dist/index.d.mts +7 -50
- package/dist/index.mjs +1 -1
- package/dist/internal/anthropic.d.mts +9 -3
- package/dist/internal/anthropic.mjs +3 -3
- package/dist/internal/openai.d.mts +2 -279
- package/dist/internal/openai.mjs +5 -5
- package/dist/internal/runtime.d.mts +8 -5
- package/dist/internal/runtime.mjs +22 -12
- package/dist/internal/shared.d.mts +4 -2
- package/dist/internal/shared.mjs +2 -2
- package/dist/{mistral-DxMPt9q9.mjs → mistral-D5Ps7Led.mjs} +26 -10
- package/dist/{model-utils-Q1LSRIdo.mjs → model-utils-1GiZ2_rr.mjs} +3 -1
- package/dist/openai-CoGicoDt.d.mts +332 -0
- package/dist/{openai-chatgpt-responses-BuH2NvsR.mjs → openai-chatgpt-responses-h0o5yV8Y.mjs} +47 -48
- package/dist/{openai-completions-DPR_O2RW.mjs → openai-completions-exO8NFQf.mjs} +342 -102
- package/dist/{openai-responses-Cov-Vdc2.mjs → openai-responses-BHpmtUKo.mjs} +5 -5
- package/dist/{openai-responses-shared-Befb4D6R.mjs → openai-responses-shared-CzCurmY1.mjs} +527 -268
- package/dist/{openai-tool-projection-CFqm42J2.mjs → openai-tool-projection-ITOU9bG1.mjs} +1 -1
- package/dist/provider-error-C4VvV_3t.mjs +41 -0
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +8 -8
- package/dist/{stream-first-event-timeout-RjWszj8c.mjs → stream-first-event-timeout-DP4xEyBY.mjs} +45 -1
- package/dist/{transform-messages-BmS70CP5.mjs → system-prompt-cache-boundary-CbHeV4_l.mjs} +171 -161
- package/dist/transports.d.mts +590 -0
- package/dist/transports.mjs +5701 -0
- package/dist/{types-Cx2zJtyz.d.mts → types-AFwwWium.d.mts} +7 -0
- package/dist/types.d.mts +4 -4
- package/dist/{validation-Cej7htKc.d.mts → validation-sxvxC8J-.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/npm-shrinkwrap.json +43 -50
- package/package.json +36 -10
- package/dist/host-4t713IeR.mjs +0 -37
- /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-
|
|
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-
|
|
4
|
-
import {
|
|
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-
|
|
12
|
-
import {
|
|
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 =
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
345
|
-
for (const detail of reasoningDetails) if (detail
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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.
|
|
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 =
|
|
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
|
-
|
|
473
|
-
|
|
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:
|
|
784
|
+
enable_thinking: reasoningEnabled,
|
|
476
785
|
preserve_thinking: true
|
|
477
786
|
};
|
|
478
787
|
else if (compat.thinkingFormat === "deepseek" && model.reasoning) {
|
|
479
|
-
params.thinking = { type:
|
|
480
|
-
if (
|
|
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 (
|
|
484
|
-
else if (
|
|
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:
|
|
488
|
-
if (
|
|
489
|
-
} else if (
|
|
490
|
-
else if (
|
|
491
|
-
|
|
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 (
|
|
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-
|
|
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-
|
|
4
|
-
import {
|
|
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 {
|
|
7
|
-
import { a as clampOpenAIPromptCacheKey } from "./openai-tool-projection-
|
|
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({
|