@openclaw/ai 2026.8.1-beta.3 → 2026.8.2
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-B8KwTtlb.mjs → anthropic-DTGZ4VMY.mjs} +25 -23
- package/dist/{anthropic-compaction-replay-4Zx7-aCr.mjs → anthropic-compaction-replay-CKCDrZJv.mjs} +34 -35
- package/dist/{anthropic-payload-policy-CSx7MoKH.d.mts → anthropic-payload-policy-BTzmNC14.d.mts} +3 -2
- package/dist/{api-registry-DFxSnFqG.d.mts → api-registry-BbUHEKER.d.mts} +2 -1
- package/dist/{azure-openai-responses-Aa4mVcYG.mjs → azure-openai-responses-BmqaDXM1.mjs} +6 -5
- package/dist/{number-coercion-H9qHik3g.mjs → base64-CEFBpSkN.mjs} +73 -1
- package/dist/diagnostics.d.mts +2 -3
- package/dist/diagnostics.mjs +1 -1
- package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-bktO00EJ.mjs} +2 -15
- package/dist/{event-stream-D91-ohD_.d.mts → event-stream-DcvAPSBe.d.mts} +1 -2
- package/dist/event-stream-pXT3FI6X.d.mts +1 -0
- package/dist/event-stream.d.mts +2 -1
- package/dist/{google-yDRnipeq.mjs → google-CqjVZMwo.mjs} +8 -6
- package/dist/{google-shared-M1dl64nz.mjs → google-shared-Bnqni5j3.mjs} +34 -25
- package/dist/{google-vertex-DCJHM_a5.mjs → google-vertex-D_WREEJi.mjs} +8 -6
- package/dist/{host-DF_yxOsA.mjs → host-BIaiBURL.mjs} +4 -8
- package/dist/{host-DJq_FGcz.d.mts → host-DKFUAmCn.d.mts} +3 -3
- package/dist/index-CefaUGSS.d.mts +111 -0
- package/dist/index.d.mts +9 -10
- package/dist/index.mjs +4 -5
- package/dist/internal/anthropic.d.mts +51 -49
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -3
- package/dist/internal/openai-responses-payload-policy.mjs +2 -3
- package/dist/internal/openai.d.mts +65 -63
- package/dist/internal/openai.mjs +10 -9
- package/dist/internal/retry-after.d.mts +2 -3
- package/dist/internal/runtime.d.mts +51 -40
- package/dist/internal/runtime.mjs +9 -9
- package/dist/internal/shared.d.mts +25 -25
- package/dist/internal/shared.mjs +3 -3
- package/dist/{json-parse-CDnesDM_.mjs → json-parse-BuAJEbdW.mjs} +18 -2
- package/dist/{mistral-D6hRXI7A.mjs → mistral-C24jVd6f.mjs} +34 -32
- package/dist/{openai-chatgpt-responses-C339VIfT.mjs → openai-chatgpt-responses-Czum0oXz.mjs} +38 -20
- package/dist/openai-completions-BfFwac6f.mjs +404 -0
- package/dist/{openai-completions-compat-B0KTleXp.d.mts → openai-completions-compat-SZhi0Lf4.d.mts} +3 -3
- package/dist/openai-completions-stream-DGOvau4J.mjs +1625 -0
- package/dist/{openai-responses-BXEcr-Tp.mjs → openai-responses-BAryVEJM.mjs} +11 -7
- package/dist/openai-responses-compaction-window-DO7yV7az.mjs +686 -0
- package/dist/{openai-responses-contracts-CD75pQ0m.d.mts → openai-responses-contracts-BthRXano.d.mts} +14 -5
- package/dist/{openai-responses-payload-policy-CNGFT9zr.d.mts → openai-responses-payload-policy-rLRPsSmB.d.mts} +1 -0
- package/dist/{openai-responses-prompt-observer-internal-BG-1AsBI.mjs → openai-responses-prompt-observer-internal--R0kZLOZ.mjs} +3 -2
- package/dist/{openai-responses-shared-Cvt5MgEm.mjs → openai-responses-shared-CxgdGBvm.mjs} +332 -1484
- package/dist/openai-stop-reason-Drnn_6Qj.mjs +28 -0
- package/dist/openai-tool-schema-CSMh5e9O.mjs +1697 -0
- package/dist/{provider-error-C8mBRJDl.mjs → provider-error-BI8kIViN.mjs} +14 -88
- package/dist/{provider-options-Cc5ZQ6Aa.d.mts → provider-options-DJd_9euj.d.mts} +13 -4
- package/dist/{provider-transcript-transform--gtf0ZbR.mjs → provider-transcript-transform-WvJmFUAf.mjs} +1 -1
- package/dist/provider-types.d.mts +18 -17
- package/dist/providers.d.mts +5 -6
- package/dist/providers.mjs +9 -9
- package/dist/{reasoning-tag-text-partitioner-5ygO2rZc.mjs → reasoning-tag-text-partitioner-BsUX44Tq.mjs} +30 -20
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{sanitize-unicode-BP7HLLZn.mjs → sanitize-unicode-S6binQG-.mjs} +2 -9
- package/dist/simple-options-rdOPzr7Z.mjs +155 -0
- package/dist/{anthropic-BQXQudmA.mjs → src-C8U7lkoa.mjs} +75 -1
- package/dist/{stream-first-event-timeout-MK28puvq.mjs → stream-first-event-timeout-DcNjoFQE.mjs} +1 -1
- package/dist/{streaming-byte-guard-BrbkbwUu.mjs → streaming-byte-guard-CC-HMn_u.mjs} +5 -6
- package/dist/string-normalization--fwJ4S2q.mjs +16 -0
- package/dist/{tool-schema-json-projection-FEr-jOoZ.mjs → tool-schema-json-projection-BtZiml7r.mjs} +22 -32
- package/dist/transport-stream-shared-BbG7PThh.d.mts +138 -0
- package/dist/{simple-options-oqsXB6U3.mjs → transport-stream-shared-D8nQWCUo.mjs} +10 -118
- package/dist/{transport-utils-Bv0FHkd0.mjs → transport-utils-CtuS1Upe.mjs} +10 -10
- package/dist/transports.d.mts +130 -189
- package/dist/transports.mjs +227 -1249
- package/dist/{types-DTAP49HF.d.mts → types-Beemor2E.d.mts} +58 -24
- package/dist/types-COdhCX0U.d.mts +1 -0
- package/dist/types.d.mts +6 -5
- package/dist/types.mjs +3 -4
- package/dist/utf16-slice-qz3nsy87.mjs +84 -0
- package/dist/{validation-DYNNrU9u.d.mts → validation-CC6s7Smp.d.mts} +1 -2
- package/dist/{validation-B61OhAio.mjs → validation-CJZtym2g.mjs} +7 -5
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +6 -6
- package/dist/anthropic-BECQCNdF.d.mts +0 -98
- package/dist/event-stream-BVVgDSdq.d.mts +0 -1
- package/dist/headers-B_e4-1J0.mjs +0 -9
- package/dist/index-BVVgDSdq.d.mts +0 -1
- package/dist/openai-completions-D88orSJ9.mjs +0 -632
- package/dist/openai-responses-contracts-DvILoqBk.mjs +0 -247
- package/dist/openai-responses-payload-policy-BDo8CQsx.mjs +0 -208
- package/dist/openai-stop-reason-9OONKyAm.mjs +0 -579
- package/dist/openai-tool-projection-CHGLt03m.mjs +0 -426
- package/dist/provider-options-AvldWZt8.mjs +0 -21
- package/dist/record-coerce-DdXsgUd_.mjs +0 -23
- package/dist/src-D2H6yKkH.mjs +0 -2
- package/dist/stream-first-event-timeout-DvDeSucC.d.mts +0 -29
- package/dist/string-coerce-fsri9iCu.mjs +0 -34
- package/dist/types-BVVgDSdq.d.mts +0 -1
- package/dist/utf16-slice-CvGodqok.mjs +0 -29
|
@@ -1,579 +0,0 @@
|
|
|
1
|
-
import { n as normalizeLowercaseStringOrEmpty } from "./string-coerce-fsri9iCu.mjs";
|
|
2
|
-
import { t as sanitizeSurrogates } from "./sanitize-unicode-BP7HLLZn.mjs";
|
|
3
|
-
import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload } from "./host-DF_yxOsA.mjs";
|
|
4
|
-
import { a as isRecord, r as asOptionalObjectRecord } from "./record-coerce-DdXsgUd_.mjs";
|
|
5
|
-
import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
|
|
6
|
-
import { d as finalizeTerminalToolCallArguments, j as stripSystemPromptCacheBoundary } from "./simple-options-oqsXB6U3.mjs";
|
|
7
|
-
import { o as resolveProviderRequestCapabilities } from "./tool-schema-json-projection-FEr-jOoZ.mjs";
|
|
8
|
-
import { u as measureUtf8AppendBytes } from "./openai-tool-projection-CHGLt03m.mjs";
|
|
9
|
-
import { t as transformProviderMessages } from "./provider-transcript-transform--gtf0ZbR.mjs";
|
|
10
|
-
import { randomUUID } from "node:crypto";
|
|
11
|
-
//#region packages/ai/src/utils/assistant-text-phase.ts
|
|
12
|
-
const EMPTY_ASSISTANT_TEXT_BLOCK_SET = /* @__PURE__ */ new Set();
|
|
13
|
-
function isAssistantTextPhaseBlock(block) {
|
|
14
|
-
if (!block || typeof block !== "object") return false;
|
|
15
|
-
const record = block;
|
|
16
|
-
return record.type === "text" && typeof record.text === "string";
|
|
17
|
-
}
|
|
18
|
-
function encodeAssistantTextSignatureV1(id, phase) {
|
|
19
|
-
return JSON.stringify({
|
|
20
|
-
v: 1,
|
|
21
|
-
id,
|
|
22
|
-
...phase ? { phase } : {}
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
function tagUnphasedText(content, phase, idPrefix) {
|
|
26
|
-
const textBlocks = content.filter(isAssistantTextPhaseBlock);
|
|
27
|
-
let phaseIndex = textBlocks.filter((block) => block.textSignature !== void 0).length;
|
|
28
|
-
const tagged = /* @__PURE__ */ new Map();
|
|
29
|
-
for (const block of textBlocks) {
|
|
30
|
-
if (block.text.trim().length === 0 || block.textSignature !== void 0) continue;
|
|
31
|
-
const signature = encodeAssistantTextSignatureV1(`${idPrefix}-${phaseIndex}`, phase);
|
|
32
|
-
block.textSignature = signature;
|
|
33
|
-
tagged.set(block, signature);
|
|
34
|
-
phaseIndex += 1;
|
|
35
|
-
}
|
|
36
|
-
return tagged;
|
|
37
|
-
}
|
|
38
|
-
/** Tags unphased narration before a tool-call event becomes consumer-visible. */
|
|
39
|
-
function tagPendingCommentaryText(content) {
|
|
40
|
-
return tagUnphasedText(content, "commentary", "commentary");
|
|
41
|
-
}
|
|
42
|
-
/** Records the confirmed final-answer boundary after reasoning resumes. */
|
|
43
|
-
function tagInterruptedTextPhases(content, interruptedText, preservedVisibleText = EMPTY_ASSISTANT_TEXT_BLOCK_SET) {
|
|
44
|
-
const interruptedTextIndex = content.indexOf(interruptedText);
|
|
45
|
-
if (interruptedTextIndex === -1) return;
|
|
46
|
-
const finalAnswerIndex = content.findIndex((block, index) => index > interruptedTextIndex && isAssistantTextPhaseBlock(block) && block.text.trim().length > 0);
|
|
47
|
-
if (finalAnswerIndex === -1) return;
|
|
48
|
-
tagUnphasedText(content.slice(0, finalAnswerIndex).filter((block) => !preservedVisibleText.has(block)), "commentary", "commentary");
|
|
49
|
-
tagUnphasedText(content.filter((block, index) => index >= finalAnswerIndex || preservedVisibleText.has(block)), "final_answer", "final-answer");
|
|
50
|
-
}
|
|
51
|
-
/** Prevents unresolved completion text from becoming a fallback answer after stream failure. */
|
|
52
|
-
function tagUnresolvedTextAsCommentary(message) {
|
|
53
|
-
if (message.openclawDelivery?.textPhaseRequiresTerminal) tagUnphasedText(message.content, "commentary", "commentary");
|
|
54
|
-
}
|
|
55
|
-
/** Rolls back only the exact provisional signatures created by this transport turn. */
|
|
56
|
-
function clearPendingCommentaryText(tags) {
|
|
57
|
-
for (const [block, signature] of tags) if (block.textSignature === signature) delete block.textSignature;
|
|
58
|
-
tags.clear();
|
|
59
|
-
}
|
|
60
|
-
function rememberPendingCommentaryTags(target, tagged) {
|
|
61
|
-
for (const [block, signature] of tagged) target.set(block, signature);
|
|
62
|
-
}
|
|
63
|
-
//#endregion
|
|
64
|
-
//#region packages/ai/src/providers/openai-response-format.ts
|
|
65
|
-
const JSON_SCHEMA_RESPONSE_FORMAT_NAME = "openclaw_response";
|
|
66
|
-
const OLLAMA_CLOUD_ORIGIN = "https://ollama.com";
|
|
67
|
-
function isKnownOpenAIJsonSchemaModelId(modelId) {
|
|
68
|
-
if (typeof modelId !== "string") return false;
|
|
69
|
-
if (/^gpt-5(?:[.-]|$)/i.test(modelId) || /^gpt-4\.1(?:-|$)/i.test(modelId)) return true;
|
|
70
|
-
const gpt4o = /^gpt-4o(-mini)?(?:-(\d{4}-\d{2}-\d{2}))?$/i.exec(modelId);
|
|
71
|
-
if (gpt4o) {
|
|
72
|
-
const snapshot = gpt4o[2];
|
|
73
|
-
return !snapshot || snapshot >= (gpt4o[1] ? "2024-07-18" : "2024-08-06");
|
|
74
|
-
}
|
|
75
|
-
return /^(?:o1|o3(?:-mini|-pro)?|o4-mini)(?:-\d{4}-\d{2}-\d{2})?$/i.test(modelId);
|
|
76
|
-
}
|
|
77
|
-
function shouldOmitOllamaCompatResponseFormat(params) {
|
|
78
|
-
if (!params.provider.includes("ollama")) return false;
|
|
79
|
-
if (params.hasTools()) return true;
|
|
80
|
-
try {
|
|
81
|
-
return new URL(params.baseUrl).origin === OLLAMA_CLOUD_ORIGIN;
|
|
82
|
-
} catch {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Maps the shared JSON Schema option to Chat Completions while preserving the
|
|
88
|
-
* older provider-shaped json_object/json_schema inputs accepted by model params.
|
|
89
|
-
*/
|
|
90
|
-
function resolveOpenAICompletionsResponseFormat(responseFormat, supportsJsonSchemaResponseFormat) {
|
|
91
|
-
if (!responseFormat) return;
|
|
92
|
-
if (responseFormat.type === "json_object") return responseFormat;
|
|
93
|
-
if (responseFormat.type === "text") return responseFormat;
|
|
94
|
-
if (responseFormat.type === "json_schema" && isRecord(responseFormat.json_schema)) return responseFormat;
|
|
95
|
-
if (!supportsJsonSchemaResponseFormat) return;
|
|
96
|
-
return {
|
|
97
|
-
type: "json_schema",
|
|
98
|
-
json_schema: {
|
|
99
|
-
name: JSON_SCHEMA_RESPONSE_FORMAT_NAME,
|
|
100
|
-
schema: responseFormat
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
//#endregion
|
|
105
|
-
//#region packages/ai/src/transports/openai-completions-compat.ts
|
|
106
|
-
function isDefaultRouteProvider(provider, ...ids) {
|
|
107
|
-
return provider !== void 0 && ids.includes(provider);
|
|
108
|
-
}
|
|
109
|
-
/** Resolves default request flags for an OpenAI-compatible completions endpoint. */
|
|
110
|
-
function resolveOpenAICompletionsCompatDefaults(input) {
|
|
111
|
-
const { provider, modelId, endpointClass, knownProviderFamily, supportsNativeStreamingUsageCompat = false, supportsOpenAICompletionsStreamingUsageCompat = false, usesExplicitProxyLikeEndpoint = false } = input;
|
|
112
|
-
const isDefaultRoute = endpointClass === "default";
|
|
113
|
-
const usesConfiguredNonOpenAIEndpoint = endpointClass !== "default" && endpointClass !== "openai-public";
|
|
114
|
-
const isMoonshot = knownProviderFamily === "moonshot" || endpointClass === "moonshot-native";
|
|
115
|
-
const isMoonshotLike = isMoonshot || knownProviderFamily === "modelstudio" || endpointClass === "modelstudio-native";
|
|
116
|
-
const isModelStudioLike = knownProviderFamily === "modelstudio" || endpointClass === "modelstudio-native" || isDefaultRoute && isDefaultRouteProvider(provider, "dashscope", "modelstudio", "qwen");
|
|
117
|
-
const isZai = endpointClass === "zai-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "zai");
|
|
118
|
-
const isDeepSeek = endpointClass === "deepseek-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "deepseek");
|
|
119
|
-
const isTogether = knownProviderFamily === "together" || input.baseUrl?.includes("api.together.ai") === true || input.baseUrl?.includes("api.together.xyz") === true || isDefaultRoute && isDefaultRouteProvider(input.provider, "together");
|
|
120
|
-
const isCloudflareAiGateway = provider === "cloudflare-ai-gateway" || input.baseUrl?.includes("gateway.ai.cloudflare.com") === true;
|
|
121
|
-
const isXiaomi = endpointClass === "xiaomi-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "xiaomi");
|
|
122
|
-
const isNonStandard = endpointClass === "cerebras-native" || endpointClass === "chutes-native" || endpointClass === "deepseek-native" || endpointClass === "mistral-public" || endpointClass === "opencode-native" || endpointClass === "xai-native" || isXiaomi || isZai || isDefaultRoute && isDefaultRouteProvider(input.provider, "cerebras", "chutes", "deepseek", "opencode", "xai");
|
|
123
|
-
const isOpenRouterLike = input.provider === "openrouter" || endpointClass === "openrouter";
|
|
124
|
-
const isLocalEndpoint = endpointClass === "local";
|
|
125
|
-
const usesMaxTokens = endpointClass === "chutes-native" || endpointClass === "mistral-public" || knownProviderFamily === "mistral" || isMoonshot || isCloudflareAiGateway || isZai || isTogether || isDefaultRoute && isDefaultRouteProvider(provider, "chutes");
|
|
126
|
-
return {
|
|
127
|
-
supportsStore: !isNonStandard && knownProviderFamily !== "mistral" && !usesExplicitProxyLikeEndpoint,
|
|
128
|
-
supportsDeveloperRole: !isNonStandard && !isMoonshotLike && !usesConfiguredNonOpenAIEndpoint,
|
|
129
|
-
supportsReasoningEffort: !isZai && !isTogether && knownProviderFamily !== "mistral" && endpointClass !== "xai-native" && !usesExplicitProxyLikeEndpoint,
|
|
130
|
-
supportsUsageInStreaming: supportsOpenAICompletionsStreamingUsageCompat || !isNonStandard && (isLocalEndpoint || !usesConfiguredNonOpenAIEndpoint || supportsNativeStreamingUsageCompat),
|
|
131
|
-
maxTokensField: usesMaxTokens ? "max_tokens" : "max_completion_tokens",
|
|
132
|
-
thinkingFormat: isDeepSeek || isXiaomi ? "deepseek" : isZai ? "zai" : isTogether ? "together" : isOpenRouterLike ? "openrouter" : "openai",
|
|
133
|
-
visibleReasoningDetailTypes: isOpenRouterLike ? ["response.output_text", "response.text"] : [],
|
|
134
|
-
supportsStrictMode: !isZai && !usesConfiguredNonOpenAIEndpoint,
|
|
135
|
-
supportsJsonSchemaResponseFormat: (endpointClass === "openai-public" || isDefaultRoute && isDefaultRouteProvider(provider, "openai")) && isKnownOpenAIJsonSchemaModelId(modelId),
|
|
136
|
-
requiresReasoningContentOnAssistantMessages: isDeepSeek || isXiaomi,
|
|
137
|
-
requiresNonEmptyUserOrAssistantMessage: isModelStudioLike,
|
|
138
|
-
cacheControlFormat: provider === "openrouter" && modelId?.startsWith("anthropic/") === true ? "anthropic" : void 0,
|
|
139
|
-
sessionAffinityFormat: isOpenRouterLike ? "openrouter" : "openai",
|
|
140
|
-
supportsLongCacheRetention: provider !== "cloudflare-workers-ai" && provider !== "cloudflare-ai-gateway" && knownProviderFamily !== "together" && !input.baseUrl?.includes("api.cloudflare.com") && !input.baseUrl?.includes("gateway.ai.cloudflare.com") && !input.baseUrl?.includes("api.together.ai") && !input.baseUrl?.includes("api.together.xyz")
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
function resolveOpenAICompletionsCompatDefaultsFromCapabilities(input) {
|
|
144
|
-
return resolveOpenAICompletionsCompatDefaults(input);
|
|
145
|
-
}
|
|
146
|
-
/** Detects endpoint capabilities and defaults for an OpenAI-completions model. */
|
|
147
|
-
function detectOpenAICompletionsCompat(model, resolveCapabilities) {
|
|
148
|
-
const capabilities = (resolveCapabilities ?? ((input) => resolveProviderRequestCapabilities(input, model)))({
|
|
149
|
-
provider: model.provider,
|
|
150
|
-
api: "openai-completions",
|
|
151
|
-
baseUrl: model.baseUrl,
|
|
152
|
-
capability: "llm",
|
|
153
|
-
transport: "stream",
|
|
154
|
-
modelId: model.id,
|
|
155
|
-
compat: model.compat && typeof model.compat === "object" ? model.compat : void 0
|
|
156
|
-
});
|
|
157
|
-
return {
|
|
158
|
-
capabilities,
|
|
159
|
-
defaults: resolveOpenAICompletionsCompatDefaultsFromCapabilities({
|
|
160
|
-
provider: model.provider,
|
|
161
|
-
modelId: model.id,
|
|
162
|
-
baseUrl: model.baseUrl,
|
|
163
|
-
...capabilities
|
|
164
|
-
})
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
function resolveSessionAffinity(model, detectedFormat) {
|
|
168
|
-
if (model.compat?.sendSessionAffinityHeaders !== true) return "none";
|
|
169
|
-
if (detectedFormat === "openrouter" || model.compat.thinkingFormat === "openrouter" || model.compat.openRouterRouting !== void 0) return "openrouter";
|
|
170
|
-
return "openai";
|
|
171
|
-
}
|
|
172
|
-
/** Applies explicit model overrides once on top of the canonical transport defaults. */
|
|
173
|
-
function resolveOpenAICompletionsCompat(model, resolveCapabilities) {
|
|
174
|
-
const { defaults } = detectOpenAICompletionsCompat(model, resolveCapabilities);
|
|
175
|
-
const configured = model.compat;
|
|
176
|
-
return {
|
|
177
|
-
supportsStore: configured?.supportsStore ?? defaults.supportsStore,
|
|
178
|
-
supportsDeveloperRole: configured?.supportsDeveloperRole ?? defaults.supportsDeveloperRole,
|
|
179
|
-
supportsReasoningEffort: configured?.supportsReasoningEffort ?? defaults.supportsReasoningEffort,
|
|
180
|
-
supportsUsageInStreaming: configured?.supportsUsageInStreaming ?? defaults.supportsUsageInStreaming,
|
|
181
|
-
maxTokensField: configured?.maxTokensField ?? defaults.maxTokensField,
|
|
182
|
-
requiresToolResultName: configured?.requiresToolResultName ?? false,
|
|
183
|
-
requiresAssistantAfterToolResult: configured?.requiresAssistantAfterToolResult ?? false,
|
|
184
|
-
requiresThinkingAsText: configured?.requiresThinkingAsText ?? false,
|
|
185
|
-
requiresReasoningContentOnAssistantMessages: configured?.requiresReasoningContentOnAssistantMessages ?? defaults.requiresReasoningContentOnAssistantMessages,
|
|
186
|
-
thinkingFormat: configured?.thinkingFormat ?? defaults.thinkingFormat,
|
|
187
|
-
openRouterRouting: configured?.openRouterRouting,
|
|
188
|
-
vercelGatewayRouting: configured?.vercelGatewayRouting ?? {},
|
|
189
|
-
zaiToolStream: configured?.zaiToolStream ?? false,
|
|
190
|
-
supportsStrictMode: configured?.supportsStrictMode ?? defaults.supportsStrictMode,
|
|
191
|
-
supportsJsonSchemaResponseFormat: configured?.supportsJsonSchemaResponseFormat ?? defaults.supportsJsonSchemaResponseFormat,
|
|
192
|
-
cacheControlFormat: configured?.cacheControlFormat ?? defaults.cacheControlFormat,
|
|
193
|
-
sessionAffinity: resolveSessionAffinity(model, defaults.sessionAffinityFormat),
|
|
194
|
-
supportsPromptCacheKey: configured?.supportsPromptCacheKey ?? false,
|
|
195
|
-
supportsLongCacheRetention: configured?.supportsLongCacheRetention ?? defaults.supportsLongCacheRetention,
|
|
196
|
-
visibleReasoningDetailTypes: configured && "visibleReasoningDetailTypes" in configured ? configured.visibleReasoningDetailTypes ?? defaults.visibleReasoningDetailTypes : defaults.visibleReasoningDetailTypes,
|
|
197
|
-
requiresNonEmptyUserOrAssistantMessage: defaults.requiresNonEmptyUserOrAssistantMessage
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
//#endregion
|
|
201
|
-
//#region packages/ai/src/providers/openai-completions-tool-calls.ts
|
|
202
|
-
const MAX_BUFFERED_TOOL_CALL_ARGUMENT_BYTES = 256e3;
|
|
203
|
-
const MAX_BUFFERED_LEGACY_FOLLOWING_DELTA_BYTES = 256e3;
|
|
204
|
-
const MAX_BUFFERED_LEGACY_FOLLOWING_DELTAS = 1024;
|
|
205
|
-
/** Normalize the SDK's legacy single-function lane into its modern tool-call shape. */
|
|
206
|
-
function createOpenAICompletionsToolCallDeltaNormalizer() {
|
|
207
|
-
let sawModernToolCall = false;
|
|
208
|
-
let pendingLegacyArgumentBytes = 0;
|
|
209
|
-
let pendingFollowingDeltaBytes = 0;
|
|
210
|
-
let pendingLegacyToolCall;
|
|
211
|
-
const modernArguments = /* @__PURE__ */ new Map();
|
|
212
|
-
const pendingFollowingDeltas = [];
|
|
213
|
-
const takePendingFollowingDeltas = () => {
|
|
214
|
-
pendingFollowingDeltaBytes = 0;
|
|
215
|
-
return pendingFollowingDeltas.splice(0).map((delta) => ({
|
|
216
|
-
delta,
|
|
217
|
-
toolCalls: []
|
|
218
|
-
}));
|
|
219
|
-
};
|
|
220
|
-
const bufferFollowingDelta = (delta) => {
|
|
221
|
-
const nextDeltaBytes = Buffer.byteLength(JSON.stringify(delta), "utf8");
|
|
222
|
-
if (pendingFollowingDeltaBytes + nextDeltaBytes > MAX_BUFFERED_LEGACY_FOLLOWING_DELTA_BYTES || pendingFollowingDeltas.length >= MAX_BUFFERED_LEGACY_FOLLOWING_DELTAS) throw new Error("Exceeded legacy tool-call content buffer limit");
|
|
223
|
-
pendingFollowingDeltaBytes += nextDeltaBytes;
|
|
224
|
-
pendingFollowingDeltas.push(delta);
|
|
225
|
-
};
|
|
226
|
-
const withoutToolCalls = (delta) => {
|
|
227
|
-
const ordinaryDelta = { ...delta };
|
|
228
|
-
delete ordinaryDelta.function_call;
|
|
229
|
-
delete ordinaryDelta.tool_calls;
|
|
230
|
-
return ordinaryDelta;
|
|
231
|
-
};
|
|
232
|
-
const hasObservableContent = (value) => {
|
|
233
|
-
if (typeof value === "string") return value.length > 0;
|
|
234
|
-
if (Array.isArray(value)) return value.some(hasObservableContent);
|
|
235
|
-
if (isRecord(value)) return Object.entries(value).some(([field, nestedValue]) => field !== "type" && field !== "id" && field !== "index" && hasObservableContent(nestedValue));
|
|
236
|
-
return false;
|
|
237
|
-
};
|
|
238
|
-
const hasOrdinaryContent = (delta) => Object.entries(delta).some(([field, value]) => field !== "role" && hasObservableContent(value));
|
|
239
|
-
return (delta, finishReason) => {
|
|
240
|
-
const ordinaryDelta = withoutToolCalls(delta);
|
|
241
|
-
if (delta.tool_calls && delta.tool_calls.length > 0) {
|
|
242
|
-
for (const toolCall of delta.tool_calls) {
|
|
243
|
-
const index = typeof toolCall.index === "number" ? toolCall.index : void 0;
|
|
244
|
-
const state = (index === void 0 ? void 0 : modernArguments.get(index)) ?? (toolCall.id ? modernArguments.get(toolCall.id) : void 0) ?? {
|
|
245
|
-
bytes: 0,
|
|
246
|
-
pendingHighSurrogate: false
|
|
247
|
-
};
|
|
248
|
-
if (index !== void 0) modernArguments.set(index, state);
|
|
249
|
-
if (toolCall.id) modernArguments.set(toolCall.id, state);
|
|
250
|
-
const argumentDelta = toolCall.function?.arguments ?? "";
|
|
251
|
-
const append = measureUtf8AppendBytes(state.pendingHighSurrogate, argumentDelta);
|
|
252
|
-
state.bytes += append.bytes;
|
|
253
|
-
if (state.bytes > MAX_BUFFERED_TOOL_CALL_ARGUMENT_BYTES) throw new Error("Exceeded tool-call argument buffer limit");
|
|
254
|
-
state.pendingHighSurrogate = append.endsWithHighSurrogate;
|
|
255
|
-
}
|
|
256
|
-
const precedingDeltas = takePendingFollowingDeltas();
|
|
257
|
-
sawModernToolCall = true;
|
|
258
|
-
pendingLegacyArgumentBytes = 0;
|
|
259
|
-
pendingLegacyToolCall = void 0;
|
|
260
|
-
return [...precedingDeltas, {
|
|
261
|
-
delta: ordinaryDelta,
|
|
262
|
-
toolCalls: delta.tool_calls
|
|
263
|
-
}];
|
|
264
|
-
}
|
|
265
|
-
const functionCall = delta.function_call;
|
|
266
|
-
if (sawModernToolCall) return [{
|
|
267
|
-
delta: ordinaryDelta,
|
|
268
|
-
toolCalls: []
|
|
269
|
-
}];
|
|
270
|
-
const hadPendingLegacyCall = pendingLegacyToolCall !== void 0;
|
|
271
|
-
const leadingDeltas = [];
|
|
272
|
-
if (hasOrdinaryContent(ordinaryDelta)) if (hadPendingLegacyCall) bufferFollowingDelta(ordinaryDelta);
|
|
273
|
-
else leadingDeltas.push({
|
|
274
|
-
delta: ordinaryDelta,
|
|
275
|
-
toolCalls: []
|
|
276
|
-
});
|
|
277
|
-
if (functionCall && (functionCall.name || functionCall.arguments)) {
|
|
278
|
-
const nextFunctionName = pendingLegacyToolCall?.function?.name ? void 0 : functionCall.name;
|
|
279
|
-
const nextArgumentBytes = Buffer.byteLength(functionCall.arguments ?? "", "utf8") + Buffer.byteLength(nextFunctionName ?? "", "utf8");
|
|
280
|
-
if (pendingLegacyArgumentBytes + nextArgumentBytes > MAX_BUFFERED_TOOL_CALL_ARGUMENT_BYTES) throw new Error("Exceeded tool-call argument buffer limit");
|
|
281
|
-
pendingLegacyArgumentBytes += nextArgumentBytes;
|
|
282
|
-
pendingLegacyToolCall ??= {
|
|
283
|
-
index: 0,
|
|
284
|
-
id: `call_${randomUUID().replaceAll("-", "").slice(0, 24)}`,
|
|
285
|
-
type: "function",
|
|
286
|
-
function: {}
|
|
287
|
-
};
|
|
288
|
-
const pendingFunction = pendingLegacyToolCall.function ??= {};
|
|
289
|
-
if (nextFunctionName) pendingFunction.name = nextFunctionName;
|
|
290
|
-
if (functionCall.arguments) pendingFunction.arguments = (pendingFunction.arguments ?? "") + functionCall.arguments;
|
|
291
|
-
}
|
|
292
|
-
if (!pendingLegacyToolCall) return leadingDeltas.length > 0 ? leadingDeltas : [{
|
|
293
|
-
delta: ordinaryDelta,
|
|
294
|
-
toolCalls: []
|
|
295
|
-
}];
|
|
296
|
-
if (finishReason === "function_call") {
|
|
297
|
-
const confirmedLegacyToolCall = pendingLegacyToolCall;
|
|
298
|
-
pendingLegacyToolCall = void 0;
|
|
299
|
-
pendingLegacyArgumentBytes = 0;
|
|
300
|
-
return [
|
|
301
|
-
...leadingDeltas,
|
|
302
|
-
{
|
|
303
|
-
delta: {},
|
|
304
|
-
toolCalls: [confirmedLegacyToolCall]
|
|
305
|
-
},
|
|
306
|
-
...takePendingFollowingDeltas()
|
|
307
|
-
];
|
|
308
|
-
}
|
|
309
|
-
if (finishReason) {
|
|
310
|
-
pendingLegacyArgumentBytes = 0;
|
|
311
|
-
pendingLegacyToolCall = void 0;
|
|
312
|
-
return [...leadingDeltas, ...takePendingFollowingDeltas()];
|
|
313
|
-
}
|
|
314
|
-
return leadingDeltas;
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
/** Publish only executable calls; streaming scratch state never belongs in replay. */
|
|
318
|
-
function finalizeOpenAICompletionsToolCalls(output, options = {}) {
|
|
319
|
-
const isToolCall = (block) => block.type === "toolCall";
|
|
320
|
-
const hasToolCalls = output.content.some(isToolCall);
|
|
321
|
-
if (output.stopReason === "toolUse" && !hasToolCalls) output.stopReason = "stop";
|
|
322
|
-
if (output.stopReason === "stop" && hasToolCalls && options.allowSilentToolCallPromotion !== false && !output.content.some((block) => {
|
|
323
|
-
const candidate = block;
|
|
324
|
-
return candidate.type === "text" && typeof candidate.text === "string" && candidate.text.trim().length > 0;
|
|
325
|
-
})) output.stopReason = "toolUse";
|
|
326
|
-
if (output.stopReason !== "toolUse") {
|
|
327
|
-
if (hasToolCalls) output.content = output.content.filter((block) => !isToolCall(block));
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
const toolCalls = output.content.filter(isToolCall);
|
|
331
|
-
const rejectToolCalls = () => {
|
|
332
|
-
output.stopReason = "error";
|
|
333
|
-
output.errorMessage = "Provider returned an incomplete or malformed tool call";
|
|
334
|
-
output.content = output.content.filter((candidate) => !isToolCall(candidate));
|
|
335
|
-
};
|
|
336
|
-
if (toolCalls.some((call) => typeof call.name !== "string" || call.name.trim().length === 0 || typeof call.partialArgs !== "string" || call.partialArgs.trim().length === 0)) {
|
|
337
|
-
rejectToolCalls();
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
try {
|
|
341
|
-
finalizeTerminalToolCallArguments(toolCalls, (call) => call.partialArgs);
|
|
342
|
-
} catch {
|
|
343
|
-
rejectToolCalls();
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
for (let contentIndex = 0; contentIndex < output.content.length; contentIndex += 1) {
|
|
347
|
-
const block = output.content[contentIndex];
|
|
348
|
-
if (!block || !isToolCall(block)) continue;
|
|
349
|
-
delete block.partialArgs;
|
|
350
|
-
delete block.streamIndex;
|
|
351
|
-
options.onConfirmedToolCall?.(block, contentIndex);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
//#endregion
|
|
355
|
-
//#region packages/ai/src/openai-completions-messages.ts
|
|
356
|
-
const EMPTY_TOOL_RESULT_TEXT = "(no output)";
|
|
357
|
-
function isTextContentBlock(block) {
|
|
358
|
-
return block.type === "text";
|
|
359
|
-
}
|
|
360
|
-
function isThinkingContentBlock(block) {
|
|
361
|
-
return block.type === "thinking";
|
|
362
|
-
}
|
|
363
|
-
function isToolCallBlock(block) {
|
|
364
|
-
return block.type === "toolCall";
|
|
365
|
-
}
|
|
366
|
-
function sanitizeToolResultText(text, fallback) {
|
|
367
|
-
const sanitized = sanitizeSurrogates(text);
|
|
368
|
-
return sanitized.trim().length > 0 ? sanitized : fallback;
|
|
369
|
-
}
|
|
370
|
-
/** Whether replayed messages require a tools marker for proxy compatibility. */
|
|
371
|
-
function hasToolCallHistory(messages) {
|
|
372
|
-
return messages.some((message) => message.role === "toolResult" || message.role === "assistant" && Array.isArray(message.content) && message.content.some((block) => block.type === "toolCall"));
|
|
373
|
-
}
|
|
374
|
-
/** Convert a normalized transcript to OpenAI Chat Completions messages. */
|
|
375
|
-
function convertMessages(model, context, compat, options = {}) {
|
|
376
|
-
const params = [];
|
|
377
|
-
const normalizeToolCallId = (id) => {
|
|
378
|
-
if (id.includes("|")) return id.slice(0, id.indexOf("|")).replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
|
|
379
|
-
if (model.provider === "openai") return id.length > 40 ? truncateUtf16Safe(id, 40) : id;
|
|
380
|
-
return id;
|
|
381
|
-
};
|
|
382
|
-
const transformedMessages = transformProviderMessages(context.messages, model, (id) => normalizeToolCallId(id));
|
|
383
|
-
if (context.systemPrompt) {
|
|
384
|
-
const role = model.reasoning && compat.supportsDeveloperRole ? "developer" : "system";
|
|
385
|
-
const systemPrompt = options.preserveSystemPromptCacheBoundary ? context.systemPrompt : stripSystemPromptCacheBoundary(context.systemPrompt);
|
|
386
|
-
params.push({
|
|
387
|
-
role,
|
|
388
|
-
content: sanitizeSurrogates(systemPrompt)
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
let lastRole = null;
|
|
392
|
-
for (let i = 0; i < transformedMessages.length; i++) {
|
|
393
|
-
const msg = transformedMessages[i];
|
|
394
|
-
if (!msg) continue;
|
|
395
|
-
if (compat.requiresAssistantAfterToolResult && lastRole === "toolResult" && msg.role === "user") params.push({
|
|
396
|
-
role: "assistant",
|
|
397
|
-
content: "I have processed the tool results."
|
|
398
|
-
});
|
|
399
|
-
if (msg.role === "user") {
|
|
400
|
-
const isRuntimeContextCarrier = msg.runtimeContextCarrier === true;
|
|
401
|
-
if (typeof msg.content === "string") {
|
|
402
|
-
const userParam = {
|
|
403
|
-
role: "user",
|
|
404
|
-
content: sanitizeSurrogates(msg.content)
|
|
405
|
-
};
|
|
406
|
-
if (isRuntimeContextCarrier) options.cacheOptOutIndexes?.add(params.length);
|
|
407
|
-
params.push(userParam);
|
|
408
|
-
} else {
|
|
409
|
-
const content = msg.content.map((item) => {
|
|
410
|
-
if (item.type === "text") return {
|
|
411
|
-
type: "text",
|
|
412
|
-
text: sanitizeSurrogates(item.text)
|
|
413
|
-
};
|
|
414
|
-
if (item.type === "video") return {
|
|
415
|
-
type: "video_url",
|
|
416
|
-
video_url: { url: `data:${item.mimeType};base64,${item.data}` }
|
|
417
|
-
};
|
|
418
|
-
return {
|
|
419
|
-
type: "image_url",
|
|
420
|
-
image_url: { url: `data:${item.mimeType};base64,${item.data}` }
|
|
421
|
-
};
|
|
422
|
-
});
|
|
423
|
-
if (content.length === 0) continue;
|
|
424
|
-
const userParam = {
|
|
425
|
-
role: "user",
|
|
426
|
-
content
|
|
427
|
-
};
|
|
428
|
-
if (isRuntimeContextCarrier) options.cacheOptOutIndexes?.add(params.length);
|
|
429
|
-
params.push(userParam);
|
|
430
|
-
}
|
|
431
|
-
} else if (msg.role === "assistant") {
|
|
432
|
-
const assistantMsg = {
|
|
433
|
-
role: "assistant",
|
|
434
|
-
content: compat.requiresAssistantAfterToolResult ? "" : null
|
|
435
|
-
};
|
|
436
|
-
const assistantTextParts = msg.content.filter(isTextContentBlock).filter((block) => block.text.trim().length > 0).map((block) => ({
|
|
437
|
-
type: "text",
|
|
438
|
-
text: sanitizeSurrogates(block.text)
|
|
439
|
-
}));
|
|
440
|
-
const assistantText = assistantTextParts.map((part) => part.text).join("\n");
|
|
441
|
-
const nonEmptyThinkingBlocks = msg.content.filter(isThinkingContentBlock).filter((block) => block.thinking.trim().length > 0);
|
|
442
|
-
if (nonEmptyThinkingBlocks.length > 0) if (compat.requiresThinkingAsText) assistantMsg.content = [{
|
|
443
|
-
type: "text",
|
|
444
|
-
text: nonEmptyThinkingBlocks.map((block) => sanitizeSurrogates(block.thinking)).join("\n\n")
|
|
445
|
-
}, ...assistantTextParts];
|
|
446
|
-
else {
|
|
447
|
-
if (assistantText.length > 0) assistantMsg.content = assistantText;
|
|
448
|
-
let signature = nonEmptyThinkingBlocks.at(0)?.thinkingSignature;
|
|
449
|
-
if (model.provider === "opencode-go" && signature === "reasoning") signature = "reasoning_content";
|
|
450
|
-
if (signature && signature.length > 0) assistantMsg[signature] = nonEmptyThinkingBlocks.map((block) => block.thinking).join("\n");
|
|
451
|
-
}
|
|
452
|
-
else if (assistantText.length > 0) assistantMsg.content = assistantText;
|
|
453
|
-
const toolCalls = msg.content.filter(isToolCallBlock);
|
|
454
|
-
if (toolCalls.length > 0) {
|
|
455
|
-
assistantMsg.tool_calls = toolCalls.map((toolCall) => ({
|
|
456
|
-
id: toolCall.id,
|
|
457
|
-
type: "function",
|
|
458
|
-
function: {
|
|
459
|
-
name: toolCall.name,
|
|
460
|
-
arguments: JSON.stringify(toolCall.arguments)
|
|
461
|
-
}
|
|
462
|
-
}));
|
|
463
|
-
const reasoningDetails = toolCalls.flatMap((toolCall) => {
|
|
464
|
-
const signature = toolCall.thoughtSignature;
|
|
465
|
-
if (!signature) return [];
|
|
466
|
-
try {
|
|
467
|
-
const parsed = JSON.parse(signature);
|
|
468
|
-
return parsed ? [parsed] : [];
|
|
469
|
-
} catch {
|
|
470
|
-
return [];
|
|
471
|
-
}
|
|
472
|
-
});
|
|
473
|
-
if (reasoningDetails.length > 0) assistantMsg.reasoning_details = reasoningDetails;
|
|
474
|
-
}
|
|
475
|
-
if (compat.requiresReasoningContentOnAssistantMessages && model.reasoning && assistantMsg.reasoning_content === void 0) assistantMsg.reasoning_content = "";
|
|
476
|
-
const content = assistantMsg.content;
|
|
477
|
-
if (!(content !== null && content !== void 0 && (typeof content === "string" ? content.length > 0 : content.length > 0)) && !assistantMsg.tool_calls) continue;
|
|
478
|
-
params.push(assistantMsg);
|
|
479
|
-
} else if (msg.role === "toolResult") {
|
|
480
|
-
const imageBlocks = [];
|
|
481
|
-
let j = i;
|
|
482
|
-
while (j < transformedMessages.length) {
|
|
483
|
-
const toolMsg = transformedMessages.at(j);
|
|
484
|
-
if (toolMsg?.role !== "toolResult") break;
|
|
485
|
-
const textResult = extractToolResultText(toolMsg.content);
|
|
486
|
-
const mediaPlaceholder = describeToolResultMediaPlaceholder(toolMsg.content);
|
|
487
|
-
const hasImages = toolMsg.content.some(isImageWithMediaPayload);
|
|
488
|
-
const toolResultMsg = {
|
|
489
|
-
role: "tool",
|
|
490
|
-
content: sanitizeToolResultText(textResult, mediaPlaceholder ?? EMPTY_TOOL_RESULT_TEXT),
|
|
491
|
-
tool_call_id: toolMsg.toolCallId
|
|
492
|
-
};
|
|
493
|
-
if (compat.requiresToolResultName && toolMsg.toolName) toolResultMsg.name = toolMsg.toolName;
|
|
494
|
-
params.push(toolResultMsg);
|
|
495
|
-
if (hasImages && model.input.includes("image")) {
|
|
496
|
-
for (const block of toolMsg.content) if (isImageWithMediaPayload(block)) imageBlocks.push({
|
|
497
|
-
type: "image_url",
|
|
498
|
-
image_url: { url: `data:${block.mimeType};base64,${block.data}` }
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
j += 1;
|
|
502
|
-
}
|
|
503
|
-
i = j - 1;
|
|
504
|
-
if (imageBlocks.length > 0) {
|
|
505
|
-
if (compat.requiresAssistantAfterToolResult) params.push({
|
|
506
|
-
role: "assistant",
|
|
507
|
-
content: "I have processed the tool results."
|
|
508
|
-
});
|
|
509
|
-
params.push({
|
|
510
|
-
role: "user",
|
|
511
|
-
content: [{
|
|
512
|
-
type: "text",
|
|
513
|
-
text: "Attached image(s) from tool result:"
|
|
514
|
-
}, ...imageBlocks]
|
|
515
|
-
});
|
|
516
|
-
lastRole = "user";
|
|
517
|
-
} else lastRole = "toolResult";
|
|
518
|
-
continue;
|
|
519
|
-
}
|
|
520
|
-
lastRole = msg.role;
|
|
521
|
-
}
|
|
522
|
-
return params;
|
|
523
|
-
}
|
|
524
|
-
//#endregion
|
|
525
|
-
//#region packages/ai/src/transports/openai-reasoning-compat.ts
|
|
526
|
-
/**
|
|
527
|
-
* OpenAI reasoning-effort compatibility helpers.
|
|
528
|
-
*
|
|
529
|
-
* Keeps provider metadata and built-in model exceptions on one path before request payloads are built.
|
|
530
|
-
*/
|
|
531
|
-
const OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.1-codex-mini"]);
|
|
532
|
-
function readCompatReasoningEffortMap(compat) {
|
|
533
|
-
const rawMap = asOptionalObjectRecord(asOptionalObjectRecord(compat)?.reasoningEffortMap);
|
|
534
|
-
if (!rawMap) return {};
|
|
535
|
-
return Object.fromEntries(Object.entries(rawMap).filter((entry) => typeof entry[0] === "string" && typeof entry[1] === "string"));
|
|
536
|
-
}
|
|
537
|
-
/** Resolves the reasoning effort remap for an OpenAI-compatible model. */
|
|
538
|
-
function resolveOpenAIReasoningEffortMap(model, fallbackMap = {}) {
|
|
539
|
-
const provider = normalizeLowercaseStringOrEmpty(model.provider ?? "");
|
|
540
|
-
const id = normalizeLowercaseStringOrEmpty(model.id ?? "");
|
|
541
|
-
const builtinMap = provider === "openai" && OPENAI_MEDIUM_ONLY_REASONING_MODEL_IDS.has(id) ? {
|
|
542
|
-
minimal: "medium",
|
|
543
|
-
low: "medium"
|
|
544
|
-
} : {};
|
|
545
|
-
return {
|
|
546
|
-
...fallbackMap,
|
|
547
|
-
...builtinMap,
|
|
548
|
-
...readCompatReasoningEffortMap(model.compat)
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
//#endregion
|
|
552
|
-
//#region packages/ai/src/providers/openai-stop-reason.ts
|
|
553
|
-
function mapOpenAIStopReason(reason, options) {
|
|
554
|
-
if (reason === null) return { stopReason: "stop" };
|
|
555
|
-
switch (reason) {
|
|
556
|
-
case "stop":
|
|
557
|
-
case "end": return { stopReason: "stop" };
|
|
558
|
-
case "length": return { stopReason: "length" };
|
|
559
|
-
case "function_call":
|
|
560
|
-
case "tool_calls": return { stopReason: "toolUse" };
|
|
561
|
-
case "tool_call":
|
|
562
|
-
if (options?.allowSingularToolCall) return { stopReason: "toolUse" };
|
|
563
|
-
break;
|
|
564
|
-
case "content_filter": return {
|
|
565
|
-
stopReason: "error",
|
|
566
|
-
errorMessage: "Provider finish_reason: content_filter"
|
|
567
|
-
};
|
|
568
|
-
case "network_error": return {
|
|
569
|
-
stopReason: "error",
|
|
570
|
-
errorMessage: "Provider finish_reason: network_error"
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
return {
|
|
574
|
-
stopReason: "error",
|
|
575
|
-
errorMessage: `Provider finish_reason: ${reason}`
|
|
576
|
-
};
|
|
577
|
-
}
|
|
578
|
-
//#endregion
|
|
579
|
-
export { createOpenAICompletionsToolCallDeltaNormalizer as a, resolveOpenAICompletionsCompat as c, clearPendingCommentaryText as d, rememberPendingCommentaryTags as f, tagUnresolvedTextAsCommentary as h, hasToolCallHistory as i, resolveOpenAICompletionsResponseFormat as l, tagPendingCommentaryText as m, resolveOpenAIReasoningEffortMap as n, finalizeOpenAICompletionsToolCalls as o, tagInterruptedTextPhases as p, convertMessages as r, detectOpenAICompletionsCompat as s, mapOpenAIStopReason as t, shouldOmitOllamaCompatResponseFormat as u };
|