@openclaw/ai 2026.7.2-beta.1 → 2026.7.2-beta.3
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/dist/{anthropic-Cvm71xlk.mjs → anthropic-D7SyZQ5v.mjs} +58 -39
- package/dist/{api-registry-Byvoz8Ha.d.mts → api-registry-DXBIXISf.d.mts} +1 -1
- package/dist/{azure-openai-responses-b4lfJxYS.mjs → azure-openai-responses-BkZgyZ3I.mjs} +5 -4
- package/dist/{event-stream-uQspnL8S.d.mts → event-stream-BPemFrFW.d.mts} +1 -1
- package/dist/event-stream.d.mts +1 -1
- package/dist/{google-C7PoDjpW.mjs → google-C_biGbV7.mjs} +2 -2
- package/dist/{google-shared-C7ohrmOI.mjs → google-shared-BK-NoHl8.mjs} +5 -4
- package/dist/{google-vertex-L_ABazIA.mjs → google-vertex-CvdzF1U7.mjs} +2 -2
- package/dist/index.d.mts +4 -4
- package/dist/internal/anthropic.d.mts +8 -2
- package/dist/internal/anthropic.mjs +3 -3
- package/dist/internal/openai.d.mts +27 -2
- package/dist/internal/openai.mjs +5 -5
- package/dist/internal/runtime.d.mts +2 -2
- package/dist/internal/runtime.mjs +3 -2
- package/dist/internal/shared.d.mts +13 -2
- package/dist/internal/shared.mjs +2 -2
- package/dist/{mistral-D-39Trax.mjs → mistral-BdrQmDWp.mjs} +25 -9
- package/dist/{model-utils-Q1LSRIdo.mjs → model-utils-1GiZ2_rr.mjs} +3 -1
- package/dist/{openai-chatgpt-responses-DCA0K85L.mjs → openai-chatgpt-responses-DP63Qt01.mjs} +11 -9
- package/dist/{openai-completions-B2jr3vtJ.mjs → openai-completions-zLDfebnN.mjs} +42 -21
- package/dist/{openai-responses-DTpD8YVy.mjs → openai-responses-ClspWt4I.mjs} +3 -3
- package/dist/{openai-responses-shared-B9mtGvXq.mjs → openai-responses-shared-CwnGU0KW.mjs} +412 -284
- package/dist/{openai-tool-projection-cTLC4F65.mjs → openai-tool-projection-WHf2nuOI.mjs} +1 -1
- package/dist/provider-error-LMfTEkfO.mjs +40 -0
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +8 -8
- package/dist/{transform-messages-DNWpwvXA.mjs → transform-messages-eb6lxDLB.mjs} +18 -3
- package/dist/{types-Cx2zJtyz.d.mts → types-CYORveZ7.d.mts} +6 -0
- package/dist/types.d.mts +3 -3
- package/dist/{validation-Cej7htKc.d.mts → validation-BX8euiDv.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as getEnvApiKey } from "./env-api-keys-DnhYpc27.mjs";
|
|
2
2
|
import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
|
|
3
3
|
import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
|
|
4
|
-
import { n as calculateCost, r as clampThinkingLevel } from "./model-utils-
|
|
4
|
+
import { n as calculateCost, r as clampThinkingLevel } from "./model-utils-1GiZ2_rr.mjs";
|
|
5
5
|
import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
|
|
6
6
|
import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { i as extractToolResultText, l as buildBaseOptions, n as describeToolResultMediaPlaceholder, o as isImageWithMediaPayload, s as truncateUtf16Safe, t as transformMessages, u as clampMaxTokensToModel, w as stripSystemPromptCacheBoundary } from "./transform-messages-eb6lxDLB.mjs";
|
|
8
8
|
import { t as shortHash } from "./hash-CHgqbJmD.mjs";
|
|
9
9
|
import { t as createSseByteGuard } from "./streaming-byte-guard-BrbkbwUu.mjs";
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
@@ -75,7 +75,7 @@ const streamMistral = (model, context, options) => {
|
|
|
75
75
|
...model.headers,
|
|
76
76
|
...options?.headers
|
|
77
77
|
};
|
|
78
|
-
if (options?.sessionId) headers["x-affinity"] ||= options.sessionId;
|
|
78
|
+
if (resolveMistralPromptCacheKey(options) && options?.sessionId) headers["x-affinity"] ||= options.sessionId;
|
|
79
79
|
const mistralStream = await mistral.chat.stream(payload, {
|
|
80
80
|
headers,
|
|
81
81
|
signal: options?.signal
|
|
@@ -113,7 +113,10 @@ const streamMistral = (model, context, options) => {
|
|
|
113
113
|
const streamSimpleMistral = (model, context, options) => {
|
|
114
114
|
const apiKey = options?.apiKey || getEnvApiKey(model.provider);
|
|
115
115
|
if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
|
|
116
|
-
const base =
|
|
116
|
+
const base = {
|
|
117
|
+
...buildBaseOptions(model, options, apiKey),
|
|
118
|
+
maxTokens: clampMaxTokensToModel(model, options?.maxTokens)
|
|
119
|
+
};
|
|
117
120
|
const clampedReasoning = options?.reasoning ? clampThinkingLevel(model, options.reasoning) : void 0;
|
|
118
121
|
const reasoning = clampedReasoning === "off" ? void 0 : clampedReasoning;
|
|
119
122
|
const shouldUseReasoning = model.reasoning && reasoning !== void 0;
|
|
@@ -218,12 +221,23 @@ function buildChatPayload(model, context, messages, options) {
|
|
|
218
221
|
}
|
|
219
222
|
if (options?.promptMode) payload.promptMode = options.promptMode;
|
|
220
223
|
if (options?.reasoningEffort) payload.reasoningEffort = options.reasoningEffort;
|
|
224
|
+
const promptCacheKey = resolveMistralPromptCacheKey(options);
|
|
225
|
+
if (promptCacheKey) payload.promptCacheKey = promptCacheKey;
|
|
221
226
|
if (context.systemPrompt) payload.messages.unshift({
|
|
222
227
|
role: "system",
|
|
223
228
|
content: sanitizeSurrogates(stripSystemPromptCacheBoundary(context.systemPrompt))
|
|
224
229
|
});
|
|
225
230
|
return payload;
|
|
226
231
|
}
|
|
232
|
+
function resolveMistralPromptCacheKey(options) {
|
|
233
|
+
if (options?.cacheRetention === "none") return;
|
|
234
|
+
return options?.promptCacheKey?.trim() || options?.sessionId?.trim() || void 0;
|
|
235
|
+
}
|
|
236
|
+
function readMistralCachedPromptTokens(usage, promptTokens) {
|
|
237
|
+
const record = usage;
|
|
238
|
+
const rawCachedTokens = record.promptTokensDetails?.cachedTokens ?? record.prompt_tokens_details?.cached_tokens ?? record.cachedTokens ?? record.cached_tokens;
|
|
239
|
+
return Math.min(promptTokens, Math.max(0, typeof rawCachedTokens === "number" && Number.isFinite(rawCachedTokens) ? rawCachedTokens : 0));
|
|
240
|
+
}
|
|
227
241
|
async function consumeChatStream(model, output, stream, mistralStream) {
|
|
228
242
|
let currentBlock = null;
|
|
229
243
|
const blocks = output.content;
|
|
@@ -309,11 +323,13 @@ async function consumeChatStream(model, output, stream, mistralStream) {
|
|
|
309
323
|
const chunk = event.data;
|
|
310
324
|
output.responseId ||= chunk.id;
|
|
311
325
|
if (chunk.usage) {
|
|
312
|
-
|
|
326
|
+
const promptTokens = chunk.usage.promptTokens || 0;
|
|
327
|
+
const cachedPromptTokens = readMistralCachedPromptTokens(chunk.usage, promptTokens);
|
|
328
|
+
output.usage.input = Math.max(0, promptTokens - cachedPromptTokens);
|
|
313
329
|
output.usage.output = chunk.usage.completionTokens || 0;
|
|
314
|
-
output.usage.cacheRead =
|
|
330
|
+
output.usage.cacheRead = cachedPromptTokens;
|
|
315
331
|
output.usage.cacheWrite = 0;
|
|
316
|
-
output.usage.totalTokens = chunk.usage.totalTokens || output.usage.input + output.usage.output;
|
|
332
|
+
output.usage.totalTokens = chunk.usage.totalTokens || output.usage.input + output.usage.output + output.usage.cacheRead;
|
|
317
333
|
calculateCost(model, output.usage);
|
|
318
334
|
}
|
|
319
335
|
const choice = chunk.choices[0];
|
|
@@ -576,14 +592,14 @@ function toChatMessages(messages, supportsImages) {
|
|
|
576
592
|
continue;
|
|
577
593
|
}
|
|
578
594
|
const toolContent = [];
|
|
579
|
-
const toolText = buildToolResultText(extractToolResultText(msg.content), describeToolResultMediaPlaceholder(msg.content), msg.content.some(
|
|
595
|
+
const toolText = buildToolResultText(extractToolResultText(msg.content), describeToolResultMediaPlaceholder(msg.content), msg.content.some(isImageWithMediaPayload), supportsImages, msg.isError);
|
|
580
596
|
toolContent.push({
|
|
581
597
|
type: "text",
|
|
582
598
|
text: toolText
|
|
583
599
|
});
|
|
584
600
|
for (const part of msg.content) {
|
|
585
601
|
if (!supportsImages) continue;
|
|
586
|
-
if (part
|
|
602
|
+
if (!isImageWithMediaPayload(part)) continue;
|
|
587
603
|
toolContent.push({
|
|
588
604
|
type: "image_url",
|
|
589
605
|
imageUrl: `data:${part.mimeType};base64,${part.data}`
|
|
@@ -2,10 +2,12 @@ import { c as resolveClaudeNativeThinkingLevelMap, i as requiresClaudeMandatoryA
|
|
|
2
2
|
//#region packages/ai/src/model-utils.ts
|
|
3
3
|
/** Calculates and stores model cost fields from token usage and per-million pricing. */
|
|
4
4
|
function calculateCost(model, usage) {
|
|
5
|
+
const cacheWrite1h = Math.min(usage.cacheWrite, Math.max(0, usage.cacheWrite1h ?? 0));
|
|
6
|
+
const cacheWrite5m = usage.cacheWrite - cacheWrite1h;
|
|
5
7
|
usage.cost.input = model.cost.input / 1e6 * usage.input;
|
|
6
8
|
usage.cost.output = model.cost.output / 1e6 * usage.output;
|
|
7
9
|
usage.cost.cacheRead = model.cost.cacheRead / 1e6 * usage.cacheRead;
|
|
8
|
-
usage.cost.cacheWrite = model.cost.cacheWrite
|
|
10
|
+
usage.cost.cacheWrite = (model.cost.cacheWrite * cacheWrite5m + model.cost.input * 2 * cacheWrite1h) / 1e6;
|
|
9
11
|
usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
|
|
10
12
|
return usage.cost;
|
|
11
13
|
}
|
package/dist/{openai-chatgpt-responses-DCA0K85L.mjs → openai-chatgpt-responses-DP63Qt01.mjs}
RENAMED
|
@@ -3,10 +3,10 @@ import { i as formatThrownValue, n as createAssistantMessageDiagnostic, t as app
|
|
|
3
3
|
import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
|
|
4
4
|
import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-4t713IeR.mjs";
|
|
5
5
|
import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { l as buildBaseOptions, w as stripSystemPromptCacheBoundary } from "./transform-messages-eb6lxDLB.mjs";
|
|
7
|
+
import { M as supportsOpenAITemperature, a as resolveResponsesReasoningEffort, i as processResponsesStream, n as convertResponsesMessages, s as convertResponsesToolPayload } from "./openai-responses-shared-CwnGU0KW.mjs";
|
|
8
8
|
import { i as getFirstStreamEventTimeoutMs, o as clampTimerTimeoutMs, r as getFirstStreamEventTimeoutHandler, s as resolveTimerTimeoutMs, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-RjWszj8c.mjs";
|
|
9
|
-
import { a as clampOpenAIPromptCacheKey } from "./openai-tool-projection-
|
|
9
|
+
import { a as clampOpenAIPromptCacheKey } from "./openai-tool-projection-WHf2nuOI.mjs";
|
|
10
10
|
import { parseRetryAfterHttpDateMs } from "./internal/retry-after.mjs";
|
|
11
11
|
import { i as registerSessionResourceCleanup, n as resolveOpenAICodexAccountId } from "./openai-chatgpt-jwt-DhAAzLkj.mjs";
|
|
12
12
|
import { t as createSseByteGuard } from "./streaming-byte-guard-BrbkbwUu.mjs";
|
|
@@ -38,7 +38,7 @@ function loadNodeOs() {
|
|
|
38
38
|
}
|
|
39
39
|
const os = loadNodeOs();
|
|
40
40
|
const DEFAULT_CODEX_BASE_URL = "https://chatgpt.com/backend-api";
|
|
41
|
-
const
|
|
41
|
+
const DEFAULT_MAX_RETRIES = 3;
|
|
42
42
|
const BASE_DELAY_MS = 1e3;
|
|
43
43
|
const REQUEST_COMPRESSION_ZSTD_LEVEL = 3;
|
|
44
44
|
const CODEX_TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set(["openai", "opencode"]);
|
|
@@ -127,8 +127,9 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
127
127
|
let body = buildRequestBody(model, context, options);
|
|
128
128
|
const nextBody = await options?.onPayload?.(body, model);
|
|
129
129
|
if (nextBody !== void 0) body = nextBody;
|
|
130
|
-
const
|
|
131
|
-
const
|
|
130
|
+
const sessionId = clampOpenAIPromptCacheKey(options?.sessionId);
|
|
131
|
+
const websocketRequestId = sessionId || createCodexRequestId();
|
|
132
|
+
const sseHeaders = buildSSEHeaders(modelHeaders, optionHeaders, accountId, apiKey, sessionId);
|
|
132
133
|
const websocketHeaders = buildWebSocketHeaders(modelHeaders, optionHeaders, accountId, apiKey, websocketRequestId);
|
|
133
134
|
const bodyJson = JSON.stringify(body);
|
|
134
135
|
requestTimeoutMs = resolveRequestTimeoutMs(options);
|
|
@@ -184,7 +185,8 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
184
185
|
const sseBody = compressedBody ?? bodyJson;
|
|
185
186
|
let response;
|
|
186
187
|
let lastError;
|
|
187
|
-
|
|
188
|
+
const maxRetries = options?.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
189
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
188
190
|
if (activeSignal?.aborted) throw new Error("Request was aborted");
|
|
189
191
|
try {
|
|
190
192
|
response = await fetch(resolveCodexUrl(model.baseUrl), {
|
|
@@ -199,7 +201,7 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
199
201
|
}, model);
|
|
200
202
|
if (response.ok) break;
|
|
201
203
|
const errorText = await readChatGptResponsesErrorTextLimited(response);
|
|
202
|
-
if (attempt <
|
|
204
|
+
if (attempt < maxRetries && isRetryableError(response.status, errorText)) {
|
|
203
205
|
let delayMs = BASE_DELAY_MS * 2 ** attempt;
|
|
204
206
|
const retryAfterMs = response.headers.get("retry-after-ms");
|
|
205
207
|
if (retryAfterMs !== null) {
|
|
@@ -233,7 +235,7 @@ const streamOpenAICodexResponses = (model, context, options) => {
|
|
|
233
235
|
if (error.name === "TimeoutError" && requestTimeoutMs !== void 0) throw new Error(`Request timed out after ${requestTimeoutMs}ms`, { cause: error });
|
|
234
236
|
}
|
|
235
237
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
236
|
-
if (attempt <
|
|
238
|
+
if (attempt < maxRetries && !lastError.message.includes("usage limit")) {
|
|
237
239
|
await sleepWithAbort(BASE_DELAY_MS * 2 ** attempt, activeSignal);
|
|
238
240
|
continue;
|
|
239
241
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-DnhYpc27.mjs";
|
|
2
2
|
import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
|
|
3
3
|
import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
|
|
4
|
-
import { n as calculateCost, r as clampThinkingLevel, t as applyProviderReportedUsageCost } from "./model-utils-
|
|
4
|
+
import { n as calculateCost, r as clampThinkingLevel, t as applyProviderReportedUsageCost } from "./model-utils-1GiZ2_rr.mjs";
|
|
5
5
|
import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
|
|
6
6
|
import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
|
|
7
7
|
import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
|
|
8
|
-
import {
|
|
8
|
+
import { C as splitSystemPromptCacheBoundary, i as extractToolResultText, l as buildBaseOptions, n as describeToolResultMediaPlaceholder, o as isImageWithMediaPayload, t as transformMessages, w as stripSystemPromptCacheBoundary } from "./transform-messages-eb6lxDLB.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
|
+
import { t as formatProviderError } from "./provider-error-LMfTEkfO.mjs";
|
|
10
11
|
import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-BlVe67g6.mjs";
|
|
11
12
|
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-
|
|
13
|
+
import { a as clampOpenAIPromptCacheKey, n as reconcileOpenAICompletionsToolChoice, t as projectOpenAITools } from "./openai-tool-projection-WHf2nuOI.mjs";
|
|
13
14
|
import OpenAI from "openai";
|
|
14
15
|
//#region packages/ai/src/providers/openai-stop-reason.ts
|
|
15
16
|
function mapOpenAIStopReason(reason, options) {
|
|
@@ -67,14 +68,16 @@ function isThinkingContentBlock(block) {
|
|
|
67
68
|
function isToolCallBlock(block) {
|
|
68
69
|
return block.type === "toolCall";
|
|
69
70
|
}
|
|
70
|
-
function isImageContentBlock(block) {
|
|
71
|
-
return block.type === "image";
|
|
72
|
-
}
|
|
73
71
|
const EMPTY_TOOL_RESULT_TEXT = "(no output)";
|
|
74
72
|
function sanitizeToolResultText(text, fallback) {
|
|
75
73
|
const sanitized = sanitizeSurrogates(text);
|
|
76
74
|
return sanitized.trim().length > 0 ? sanitized : fallback;
|
|
77
75
|
}
|
|
76
|
+
function isEncryptedReasoningDetail(detail) {
|
|
77
|
+
if (typeof detail !== "object" || detail === null) return false;
|
|
78
|
+
const candidate = detail;
|
|
79
|
+
return candidate.type === "reasoning.encrypted" && typeof candidate.id === "string" && candidate.id.length > 0 && typeof candidate.data === "string" && candidate.data.length > 0;
|
|
80
|
+
}
|
|
78
81
|
const streamOpenAICompletions = (model, context, options) => {
|
|
79
82
|
const stream = new AssistantMessageEventStream();
|
|
80
83
|
(async () => {
|
|
@@ -115,7 +118,7 @@ const streamOpenAICompletions = (model, context, options) => {
|
|
|
115
118
|
const requestOptions = {
|
|
116
119
|
signal: firstEventAbort.signal,
|
|
117
120
|
...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
|
|
118
|
-
|
|
121
|
+
maxRetries: options?.maxRetries ?? 0
|
|
119
122
|
};
|
|
120
123
|
const { data: openaiStream, response } = await client.chat.completions.create(params, requestOptions).withResponse();
|
|
121
124
|
await options?.onResponse?.({
|
|
@@ -132,6 +135,7 @@ const streamOpenAICompletions = (model, context, options) => {
|
|
|
132
135
|
const toolCallBlocksByIndex = /* @__PURE__ */ new Map();
|
|
133
136
|
const toolCallBlocksById = /* @__PURE__ */ new Map();
|
|
134
137
|
const toolCallBlocksByFirstId = /* @__PURE__ */ new Map();
|
|
138
|
+
const pendingReasoningDetailsByToolCallId = /* @__PURE__ */ new Map();
|
|
135
139
|
const blocks = output.content;
|
|
136
140
|
const finishedBlocks = /* @__PURE__ */ new Set();
|
|
137
141
|
const contentIndices = /* @__PURE__ */ new WeakMap();
|
|
@@ -141,7 +145,13 @@ const streamOpenAICompletions = (model, context, options) => {
|
|
|
141
145
|
};
|
|
142
146
|
const getContentIndex = (block) => contentIndices.get(block) ?? -1;
|
|
143
147
|
const rememberFirstToolCallById = (id, block) => {
|
|
144
|
-
if (
|
|
148
|
+
if (toolCallBlocksByFirstId.has(id)) return;
|
|
149
|
+
toolCallBlocksByFirstId.set(id, block);
|
|
150
|
+
const pendingDetail = pendingReasoningDetailsByToolCallId.get(id);
|
|
151
|
+
if (pendingDetail) {
|
|
152
|
+
block.thoughtSignature = pendingDetail;
|
|
153
|
+
pendingReasoningDetailsByToolCallId.delete(id);
|
|
154
|
+
}
|
|
145
155
|
};
|
|
146
156
|
const finishBlock = (block) => {
|
|
147
157
|
const contentIndex = getContentIndex(block);
|
|
@@ -344,10 +354,12 @@ const streamOpenAICompletions = (model, context, options) => {
|
|
|
344
354
|
}
|
|
345
355
|
}
|
|
346
356
|
const reasoningDetails = choiceDelta.reasoning_details;
|
|
347
|
-
if (
|
|
348
|
-
for (const detail of reasoningDetails) if (detail
|
|
357
|
+
if (Array.isArray(reasoningDetails)) {
|
|
358
|
+
for (const detail of reasoningDetails) if (isEncryptedReasoningDetail(detail)) {
|
|
359
|
+
const serializedDetail = JSON.stringify(detail);
|
|
349
360
|
const matchingToolCall = toolCallBlocksByFirstId.get(detail.id);
|
|
350
|
-
if (matchingToolCall) matchingToolCall.thoughtSignature =
|
|
361
|
+
if (matchingToolCall) matchingToolCall.thoughtSignature = serializedDetail;
|
|
362
|
+
else pendingReasoningDetailsByToolCallId.set(detail.id, serializedDetail);
|
|
351
363
|
}
|
|
352
364
|
}
|
|
353
365
|
}
|
|
@@ -376,9 +388,9 @@ const streamOpenAICompletions = (model, context, options) => {
|
|
|
376
388
|
delete block.streamIndex;
|
|
377
389
|
}
|
|
378
390
|
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
379
|
-
output.errorMessage =
|
|
391
|
+
output.errorMessage = formatProviderError(error);
|
|
380
392
|
const rawMetadata = error?.error?.metadata?.raw;
|
|
381
|
-
if (rawMetadata) output.errorMessage += `\n${rawMetadata}`;
|
|
393
|
+
if (rawMetadata && !output.errorMessage.includes(rawMetadata)) output.errorMessage += `\n${rawMetadata}`;
|
|
382
394
|
stream.push({
|
|
383
395
|
type: "error",
|
|
384
396
|
reason: output.stopReason,
|
|
@@ -415,7 +427,8 @@ function createClient(model, context, apiKey, optionsHeaders, sessionId, compat
|
|
|
415
427
|
});
|
|
416
428
|
Object.assign(headers, copilotHeaders);
|
|
417
429
|
}
|
|
418
|
-
if (sessionId && compat.sendSessionAffinityHeaders)
|
|
430
|
+
if (sessionId && compat.sendSessionAffinityHeaders) if (compat.sessionAffinityFormat === "openrouter") headers["x-session-id"] = sessionId;
|
|
431
|
+
else {
|
|
419
432
|
headers.session_id = sessionId;
|
|
420
433
|
headers["x-client-request-id"] = sessionId;
|
|
421
434
|
headers["x-session-affinity"] = sessionId;
|
|
@@ -472,7 +485,10 @@ function buildParams(model, context, options, compat = getCompat(model), cacheRe
|
|
|
472
485
|
const toolChoice = reconcileOpenAICompletionsToolChoice(options.toolChoice, toolProjection ?? projectOpenAITools([]));
|
|
473
486
|
if (toolChoice !== void 0) params.tool_choice = toolChoice;
|
|
474
487
|
}
|
|
475
|
-
if (compat.thinkingFormat === "zai" && model.reasoning) params.
|
|
488
|
+
if (compat.thinkingFormat === "zai" && model.reasoning) params.thinking = options?.reasoningEffort ? {
|
|
489
|
+
type: "enabled",
|
|
490
|
+
clear_thinking: false
|
|
491
|
+
} : { type: "disabled" };
|
|
476
492
|
else if (compat.thinkingFormat === "qwen" && model.reasoning) params.enable_thinking = Boolean(options?.reasoningEffort);
|
|
477
493
|
else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) params.chat_template_kwargs = {
|
|
478
494
|
enable_thinking: Boolean(options?.reasoningEffort),
|
|
@@ -494,7 +510,7 @@ function buildParams(model, context, options, compat = getCompat(model), cacheRe
|
|
|
494
510
|
const offValue = model.thinkingLevelMap?.off;
|
|
495
511
|
if (typeof offValue === "string") params.reasoning_effort = offValue;
|
|
496
512
|
}
|
|
497
|
-
if (model.
|
|
513
|
+
if (model.compat?.openRouterRouting) params.provider = model.compat.openRouterRouting;
|
|
498
514
|
if (model.baseUrl.includes("ai-gateway.vercel.sh") && model.compat?.vercelGatewayRouting) {
|
|
499
515
|
const routing = model.compat.vercelGatewayRouting;
|
|
500
516
|
if (routing.only || routing.order) {
|
|
@@ -699,7 +715,7 @@ function convertMessages(model, context, compat, options = {}) {
|
|
|
699
715
|
if (toolMsg?.role !== "toolResult") break;
|
|
700
716
|
const textResult = extractToolResultText(toolMsg.content);
|
|
701
717
|
const mediaPlaceholder = describeToolResultMediaPlaceholder(toolMsg.content);
|
|
702
|
-
const hasImages = toolMsg.content.some(
|
|
718
|
+
const hasImages = toolMsg.content.some(isImageWithMediaPayload);
|
|
703
719
|
const toolResultMsg = {
|
|
704
720
|
role: "tool",
|
|
705
721
|
content: sanitizeToolResultText(textResult, mediaPlaceholder ?? EMPTY_TOOL_RESULT_TEXT),
|
|
@@ -708,7 +724,7 @@ function convertMessages(model, context, compat, options = {}) {
|
|
|
708
724
|
if (compat.requiresToolResultName && toolMsg.toolName) toolResultMsg.name = toolMsg.toolName;
|
|
709
725
|
params.push(toolResultMsg);
|
|
710
726
|
if (hasImages && model.input.includes("image")) {
|
|
711
|
-
for (const block of toolMsg.content) if (
|
|
727
|
+
for (const block of toolMsg.content) if (isImageWithMediaPayload(block)) imageBlocks.push({
|
|
712
728
|
type: "image_url",
|
|
713
729
|
image_url: { url: `data:${block.mimeType};base64,${block.data}` }
|
|
714
730
|
});
|
|
@@ -788,15 +804,18 @@ function detectCompat(model) {
|
|
|
788
804
|
const isMoonshot = provider === "moonshotai" || provider === "moonshotai-cn" || baseUrl.includes("api.moonshot.");
|
|
789
805
|
const isCloudflareWorkersAI = provider === "cloudflare-workers-ai" || baseUrl.includes("api.cloudflare.com");
|
|
790
806
|
const isCloudflareAiGateway = provider === "cloudflare-ai-gateway" || baseUrl.includes("gateway.ai.cloudflare.com");
|
|
807
|
+
const isOpenRouter = provider === "openrouter" || baseUrl.includes("openrouter.ai");
|
|
791
808
|
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;
|
|
792
|
-
const useMaxTokens = baseUrl.includes("chutes.ai") || isMoonshot || isCloudflareAiGateway || isTogether;
|
|
809
|
+
const useMaxTokens = baseUrl.includes("chutes.ai") || isMoonshot || isCloudflareAiGateway || isTogether || isZai;
|
|
793
810
|
const isGrok = provider === "xai" || baseUrl.includes("api.x.ai");
|
|
794
811
|
const isDeepSeek = provider === "deepseek" || baseUrl.includes("deepseek.com");
|
|
795
812
|
const isXiaomi = provider === "xiaomi" || baseUrl.includes("xiaomimimo.com");
|
|
813
|
+
const supportsOpenRouterDeveloperRole = isOpenRouter && (model.id.startsWith("anthropic/") || model.id.startsWith("openai/"));
|
|
814
|
+
const usesOpenRouterSessionAffinity = isOpenRouter || model.compat?.thinkingFormat === "openrouter" || model.compat?.openRouterRouting !== void 0;
|
|
796
815
|
const cacheControlFormat = provider === "openrouter" && model.id.startsWith("anthropic/") ? "anthropic" : void 0;
|
|
797
816
|
return {
|
|
798
817
|
supportsStore: !isNonStandard,
|
|
799
|
-
supportsDeveloperRole: !isNonStandard,
|
|
818
|
+
supportsDeveloperRole: supportsOpenRouterDeveloperRole || !isNonStandard && !isOpenRouter,
|
|
800
819
|
supportsReasoningEffort: !isGrok && !isZai && !isMoonshot && !isTogether && !isCloudflareAiGateway,
|
|
801
820
|
supportsUsageInStreaming: true,
|
|
802
821
|
maxTokensField: useMaxTokens ? "max_tokens" : "max_completion_tokens",
|
|
@@ -804,13 +823,14 @@ function detectCompat(model) {
|
|
|
804
823
|
requiresAssistantAfterToolResult: false,
|
|
805
824
|
requiresThinkingAsText: false,
|
|
806
825
|
requiresReasoningContentOnAssistantMessages: isDeepSeek || isXiaomi,
|
|
807
|
-
thinkingFormat: isDeepSeek ? "deepseek" : isXiaomi ? "deepseek" : isZai ? "zai" : isTogether ? "together" :
|
|
826
|
+
thinkingFormat: isDeepSeek ? "deepseek" : isXiaomi ? "deepseek" : isZai ? "zai" : isTogether ? "together" : isOpenRouter ? "openrouter" : "openai",
|
|
808
827
|
openRouterRouting: {},
|
|
809
828
|
vercelGatewayRouting: {},
|
|
810
829
|
zaiToolStream: false,
|
|
811
830
|
supportsStrictMode: !isMoonshot && !isTogether && !isCloudflareAiGateway,
|
|
812
831
|
cacheControlFormat,
|
|
813
832
|
sendSessionAffinityHeaders: false,
|
|
833
|
+
sessionAffinityFormat: usesOpenRouterSessionAffinity ? "openrouter" : "openai",
|
|
814
834
|
supportsPromptCacheKey: false,
|
|
815
835
|
supportsLongCacheRetention: !(isTogether || isCloudflareWorkersAI || isCloudflareAiGateway)
|
|
816
836
|
};
|
|
@@ -839,6 +859,7 @@ function getCompat(model) {
|
|
|
839
859
|
supportsStrictMode: model.compat.supportsStrictMode ?? detected.supportsStrictMode,
|
|
840
860
|
cacheControlFormat: model.compat.cacheControlFormat ?? detected.cacheControlFormat,
|
|
841
861
|
sendSessionAffinityHeaders: model.compat.sendSessionAffinityHeaders ?? detected.sendSessionAffinityHeaders,
|
|
862
|
+
sessionAffinityFormat: detected.sessionAffinityFormat,
|
|
842
863
|
supportsPromptCacheKey: model.compat.supportsPromptCacheKey ?? detected.supportsPromptCacheKey,
|
|
843
864
|
supportsLongCacheRetention: model.compat.supportsLongCacheRetention ?? detected.supportsLongCacheRetention
|
|
844
865
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-DnhYpc27.mjs";
|
|
2
2
|
import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
|
|
3
3
|
import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { l as buildBaseOptions } from "./transform-messages-eb6lxDLB.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 { M as supportsOpenAITemperature, a as resolveResponsesReasoningEffort, n as convertResponsesMessages, o as runResponsesStreamLifecycle, r as createResponsesAssistantOutput, t as applyCommonResponsesParams } from "./openai-responses-shared-CwnGU0KW.mjs";
|
|
7
|
+
import { a as clampOpenAIPromptCacheKey } from "./openai-tool-projection-WHf2nuOI.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({
|