@openclaw/ai 2026.7.2-beta.4 → 2026.7.2-beta.5
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-CrUDIBpM.mjs → anthropic-CQVj3le6.mjs} +53 -19
- package/dist/{anthropic-BoTnz8cv.d.mts → anthropic-SrGtwsJu.d.mts} +27 -1
- package/dist/{api-registry-BMphkFf1.d.mts → api-registry-DlMgPR39.d.mts} +1 -1
- package/dist/{azure-openai-responses-CbrpVeEv.mjs → azure-openai-responses-DIYgsqFM.mjs} +3 -4
- package/dist/error-coercion-DgxlWC0n.mjs +15 -0
- package/dist/{event-stream-Douf9dob.d.mts → event-stream-YjaPW20U.d.mts} +1 -1
- package/dist/event-stream.d.mts +1 -1
- package/dist/{tool-schema-json-projection-BwNu3nDi.mjs → github-copilot-headers-BCoBNmL7.mjs} +48 -1
- package/dist/{google-Cs62KA7t.mjs → google-f-A8xrae.mjs} +2 -2
- package/dist/{google-shared-CMLI-tCZ.mjs → google-shared-J6qvYINH.mjs} +5 -4
- package/dist/{google-vertex-B4SD3U0f.mjs → google-vertex-D3yMVXIY.mjs} +2 -2
- package/dist/{host-WvWBo4h8.d.mts → host-B9GUmcra.d.mts} +2 -2
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +2 -2
- package/dist/internal/anthropic.d.mts +15 -11
- package/dist/internal/anthropic.mjs +4 -4
- package/dist/internal/openai.d.mts +2 -1
- package/dist/internal/openai.mjs +4 -6
- package/dist/internal/runtime.d.mts +8 -32
- package/dist/internal/runtime.mjs +2 -3
- package/dist/internal/shared.d.mts +13 -8
- package/dist/internal/shared.mjs +2 -2
- package/dist/{mistral-D5Ps7Led.mjs → mistral-CKV-TOQj.mjs} +4 -3
- package/dist/number-coercion-DvG7SNMg.mjs +129 -0
- package/dist/{openai-CoGicoDt.d.mts → openai-BPor_3WI.d.mts} +35 -9
- package/dist/{openai-responses-shared-CzCurmY1.mjs → openai-D3PD6PE-.mjs} +1771 -745
- package/dist/{openai-chatgpt-responses-h0o5yV8Y.mjs → openai-chatgpt-responses-CedIj0hk.mjs} +19 -20
- package/dist/{openai-completions-exO8NFQf.mjs → openai-completions-CiSutyu0.mjs} +366 -227
- package/dist/openai-prompt-cache-2uo_1OR1.d.mts +7 -0
- package/dist/openai-prompt-cache-mZTCdRPo.mjs +12 -0
- package/dist/prompt-cache-stability-Cwcjv_fx.d.mts +13 -0
- package/dist/{provider-error-C4VvV_3t.mjs → provider-error-apVOZI6G.mjs} +8 -2
- package/dist/providers.d.mts +3 -2
- package/dist/providers.mjs +10 -9
- package/dist/{system-prompt-cache-boundary-CbHeV4_l.mjs → shared-CdjNZd35.mjs} +117 -9
- package/dist/{src-CXno1H5g.mjs → src-QkygScBs.mjs} +23 -4
- package/dist/stream-first-event-timeout-C3OgBjIk.mjs +12294 -0
- package/dist/stream-first-event-timeout-DvDeSucC.d.mts +29 -0
- package/dist/transport-stream-shared-BbMELSI4.mjs +297 -0
- package/dist/transports.d.mts +105 -102
- package/dist/transports.mjs +334 -1966
- package/dist/{types-AFwwWium.d.mts → types-bzp5k29J.d.mts} +7 -0
- package/dist/types.d.mts +5 -5
- package/dist/types.mjs +2 -2
- package/dist/{validation-sxvxC8J-.d.mts → validation-B-j7cOYp.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/package.json +1 -2
- package/dist/azure-openai-responses-client-compat-C7K7QfUE.mjs +0 -62
- package/dist/github-copilot-headers-BsH5cqGj.mjs +0 -48
- package/dist/model-utils-1GiZ2_rr.mjs +0 -64
- package/dist/openai-responses-BHpmtUKo.mjs +0 -136
- package/dist/openai-tool-projection-ITOU9bG1.mjs +0 -200
- package/dist/reasoning-tag-text-partitioner-BlVe67g6.mjs +0 -400
- package/dist/stream-first-event-timeout-DP4xEyBY.mjs +0 -150
- package/npm-shrinkwrap.json +0 -638
|
@@ -1,17 +1,43 @@
|
|
|
1
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
3
|
import { n as getAiTransportHost } from "./host-XYGZcgO8.mjs";
|
|
4
|
-
import {
|
|
4
|
+
import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
|
|
5
|
+
import { A as buildBaseOptions, E as isImageWithMediaPayload, O as isRecord, S as describeToolResultMediaPlaceholder, a as splitSystemPromptCacheBoundary, o as stripSystemPromptCacheBoundary, u as transformMessages, w as extractToolResultText, y as normalizeLowercaseStringOrEmpty } from "./shared-CdjNZd35.mjs";
|
|
5
6
|
import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
|
|
6
|
-
import {
|
|
7
|
+
import { c as calculateCost, l as clampThinkingLevel, s as applyProviderReportedUsageCost } from "./number-coercion-DvG7SNMg.mjs";
|
|
8
|
+
import { d as transportAbortError } from "./transport-stream-shared-BbMELSI4.mjs";
|
|
7
9
|
import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
|
|
8
10
|
import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
|
|
9
|
-
import {
|
|
10
|
-
import { t as
|
|
11
|
-
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-
|
|
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";
|
|
11
|
+
import { t as formatProviderError } from "./provider-error-apVOZI6G.mjs";
|
|
12
|
+
import { a as resolveCacheRetention, i as resolveCloudflareBaseUrl, n as hasCopilotVisionInput, o as projectRuntimeToolInputSchema, r as isCloudflareProvider, t as buildCopilotDynamicHeaders } from "./github-copilot-headers-BCoBNmL7.mjs";
|
|
13
|
+
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, o as createReasoningTagTextPartitioner, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-C3OgBjIk.mjs";
|
|
14
14
|
import OpenAI from "openai";
|
|
15
|
+
//#region packages/ai/src/transports/host-policy.ts
|
|
16
|
+
function buildGuardedModelFetch(model, timeoutMs, options) {
|
|
17
|
+
const host = getAiTransportHost();
|
|
18
|
+
if (options !== void 0) return host.buildModelFetch(model, timeoutMs, options) ?? globalThis.fetch;
|
|
19
|
+
if (timeoutMs !== void 0) return host.buildModelFetch(model, timeoutMs) ?? globalThis.fetch;
|
|
20
|
+
return host.buildModelFetch(model) ?? globalThis.fetch;
|
|
21
|
+
}
|
|
22
|
+
function resolveProviderEndpoint(baseUrl) {
|
|
23
|
+
return { endpointClass: getAiTransportHost().resolveProviderEndpointClass(baseUrl) };
|
|
24
|
+
}
|
|
25
|
+
function resolveProviderRequestCapabilities(input) {
|
|
26
|
+
return getAiTransportHost().resolveProviderRequestCapabilities(input);
|
|
27
|
+
}
|
|
28
|
+
function resolveProviderRequestPolicyConfig(input) {
|
|
29
|
+
return { headers: getAiTransportHost().resolveProviderRequestHeaders(input) };
|
|
30
|
+
}
|
|
31
|
+
function resolveModelRequestTimeoutMs(model, timeoutMs) {
|
|
32
|
+
return timeoutMs ?? getAiTransportHost().resolveModelRequestTimeoutMs(model);
|
|
33
|
+
}
|
|
34
|
+
function resolveOpenAIStrictToolSetting(model, options) {
|
|
35
|
+
return getAiTransportHost().resolveOpenAIStrictToolSetting(model, options);
|
|
36
|
+
}
|
|
37
|
+
function transformTransportMessages(messages, model, normalizeToolCallId, options) {
|
|
38
|
+
return getAiTransportHost().transformTransportMessages(messages, model, normalizeToolCallId, options);
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
15
41
|
//#region packages/ai/src/utils/assistant-text-phase.ts
|
|
16
42
|
function isAssistantTextPhaseBlock(block) {
|
|
17
43
|
if (!block || typeof block !== "object") return false;
|
|
@@ -48,6 +74,144 @@ function rememberPendingCommentaryTags(target, tagged) {
|
|
|
48
74
|
for (const [block, signature] of tagged) target.set(block, signature);
|
|
49
75
|
}
|
|
50
76
|
//#endregion
|
|
77
|
+
//#region packages/ai/src/providers/openai-response-format.ts
|
|
78
|
+
const JSON_SCHEMA_RESPONSE_FORMAT_NAME = "openclaw_response";
|
|
79
|
+
const OLLAMA_CLOUD_ORIGIN = "https://ollama.com";
|
|
80
|
+
function isKnownOpenAIJsonSchemaModelId(modelId) {
|
|
81
|
+
if (typeof modelId !== "string") return false;
|
|
82
|
+
if (/^gpt-5(?:[.-]|$)/i.test(modelId) || /^gpt-4\.1(?:-|$)/i.test(modelId)) return true;
|
|
83
|
+
const gpt4o = /^gpt-4o(-mini)?(?:-(\d{4}-\d{2}-\d{2}))?$/i.exec(modelId);
|
|
84
|
+
if (gpt4o) {
|
|
85
|
+
const snapshot = gpt4o[2];
|
|
86
|
+
return !snapshot || snapshot >= (gpt4o[1] ? "2024-07-18" : "2024-08-06");
|
|
87
|
+
}
|
|
88
|
+
return /^(?:o1|o3(?:-mini|-pro)?|o4-mini)(?:-\d{4}-\d{2}-\d{2})?$/i.test(modelId);
|
|
89
|
+
}
|
|
90
|
+
function shouldOmitOllamaCompatResponseFormat(params) {
|
|
91
|
+
if (!params.provider.includes("ollama")) return false;
|
|
92
|
+
if (params.hasTools()) return true;
|
|
93
|
+
try {
|
|
94
|
+
return new URL(params.baseUrl).origin === OLLAMA_CLOUD_ORIGIN;
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Maps the shared JSON Schema option to Chat Completions while preserving the
|
|
101
|
+
* older provider-shaped json_object/json_schema inputs accepted by model params.
|
|
102
|
+
*/
|
|
103
|
+
function resolveOpenAICompletionsResponseFormat(responseFormat, supportsJsonSchemaResponseFormat) {
|
|
104
|
+
if (!responseFormat) return;
|
|
105
|
+
if (responseFormat.type === "json_object") return responseFormat;
|
|
106
|
+
if (responseFormat.type === "text") return responseFormat;
|
|
107
|
+
if (responseFormat.type === "json_schema" && isRecord(responseFormat.json_schema)) return responseFormat;
|
|
108
|
+
if (!supportsJsonSchemaResponseFormat) return;
|
|
109
|
+
return {
|
|
110
|
+
type: "json_schema",
|
|
111
|
+
json_schema: {
|
|
112
|
+
name: JSON_SCHEMA_RESPONSE_FORMAT_NAME,
|
|
113
|
+
schema: responseFormat
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region packages/ai/src/transports/openai-completions-compat.ts
|
|
119
|
+
function isDefaultRouteProvider(provider, ...ids) {
|
|
120
|
+
return provider !== void 0 && ids.includes(provider);
|
|
121
|
+
}
|
|
122
|
+
/** Resolves default request flags for an OpenAI-compatible completions endpoint. */
|
|
123
|
+
function resolveOpenAICompletionsCompatDefaults(input) {
|
|
124
|
+
const { provider, modelId, endpointClass, knownProviderFamily, supportsNativeStreamingUsageCompat = false, supportsOpenAICompletionsStreamingUsageCompat = false, usesExplicitProxyLikeEndpoint = false } = input;
|
|
125
|
+
const isDefaultRoute = endpointClass === "default";
|
|
126
|
+
const usesConfiguredNonOpenAIEndpoint = endpointClass !== "default" && endpointClass !== "openai-public";
|
|
127
|
+
const isMoonshot = knownProviderFamily === "moonshot" || endpointClass === "moonshot-native";
|
|
128
|
+
const isMoonshotLike = isMoonshot || knownProviderFamily === "modelstudio" || endpointClass === "modelstudio-native";
|
|
129
|
+
const isModelStudioLike = knownProviderFamily === "modelstudio" || endpointClass === "modelstudio-native" || isDefaultRoute && isDefaultRouteProvider(provider, "dashscope", "modelstudio", "qwen");
|
|
130
|
+
const isZai = endpointClass === "zai-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "zai");
|
|
131
|
+
const isDeepSeek = endpointClass === "deepseek-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "deepseek");
|
|
132
|
+
const isTogether = knownProviderFamily === "together" || input.baseUrl?.includes("api.together.ai") === true || input.baseUrl?.includes("api.together.xyz") === true || isDefaultRoute && isDefaultRouteProvider(input.provider, "together");
|
|
133
|
+
const isCloudflareAiGateway = provider === "cloudflare-ai-gateway" || input.baseUrl?.includes("gateway.ai.cloudflare.com") === true;
|
|
134
|
+
const isXiaomi = endpointClass === "xiaomi-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "xiaomi");
|
|
135
|
+
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");
|
|
136
|
+
const isOpenRouterLike = input.provider === "openrouter" || endpointClass === "openrouter";
|
|
137
|
+
const isLocalEndpoint = endpointClass === "local";
|
|
138
|
+
const usesMaxTokens = endpointClass === "chutes-native" || endpointClass === "mistral-public" || knownProviderFamily === "mistral" || isMoonshot || isCloudflareAiGateway || isZai || isTogether || isDefaultRoute && isDefaultRouteProvider(provider, "chutes");
|
|
139
|
+
return {
|
|
140
|
+
supportsStore: !isNonStandard && knownProviderFamily !== "mistral" && !usesExplicitProxyLikeEndpoint,
|
|
141
|
+
supportsDeveloperRole: !isNonStandard && !isMoonshotLike && !usesConfiguredNonOpenAIEndpoint,
|
|
142
|
+
supportsReasoningEffort: !isZai && !isTogether && knownProviderFamily !== "mistral" && endpointClass !== "xai-native" && !usesExplicitProxyLikeEndpoint,
|
|
143
|
+
supportsUsageInStreaming: supportsOpenAICompletionsStreamingUsageCompat || !isNonStandard && (isLocalEndpoint || !usesConfiguredNonOpenAIEndpoint || supportsNativeStreamingUsageCompat),
|
|
144
|
+
maxTokensField: usesMaxTokens ? "max_tokens" : "max_completion_tokens",
|
|
145
|
+
thinkingFormat: isDeepSeek || isXiaomi ? "deepseek" : isZai ? "zai" : isTogether ? "together" : isOpenRouterLike ? "openrouter" : "openai",
|
|
146
|
+
visibleReasoningDetailTypes: isOpenRouterLike ? ["response.output_text", "response.text"] : [],
|
|
147
|
+
supportsStrictMode: !isZai && !usesConfiguredNonOpenAIEndpoint,
|
|
148
|
+
supportsJsonSchemaResponseFormat: (endpointClass === "openai-public" || isDefaultRoute && isDefaultRouteProvider(provider, "openai")) && isKnownOpenAIJsonSchemaModelId(modelId),
|
|
149
|
+
requiresReasoningContentOnAssistantMessages: isDeepSeek || isXiaomi,
|
|
150
|
+
requiresNonEmptyUserOrAssistantMessage: isModelStudioLike,
|
|
151
|
+
cacheControlFormat: provider === "openrouter" && modelId?.startsWith("anthropic/") === true ? "anthropic" : void 0,
|
|
152
|
+
sessionAffinityFormat: isOpenRouterLike ? "openrouter" : "openai",
|
|
153
|
+
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")
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function resolveOpenAICompletionsCompatDefaultsFromCapabilities(input) {
|
|
157
|
+
return resolveOpenAICompletionsCompatDefaults(input);
|
|
158
|
+
}
|
|
159
|
+
/** Detects endpoint capabilities and defaults for an OpenAI-completions model. */
|
|
160
|
+
function detectOpenAICompletionsCompat(model, resolveCapabilities = resolveProviderRequestCapabilities) {
|
|
161
|
+
const capabilities = resolveCapabilities({
|
|
162
|
+
provider: model.provider,
|
|
163
|
+
api: "openai-completions",
|
|
164
|
+
baseUrl: model.baseUrl,
|
|
165
|
+
capability: "llm",
|
|
166
|
+
transport: "stream",
|
|
167
|
+
modelId: model.id,
|
|
168
|
+
compat: model.compat && typeof model.compat === "object" ? model.compat : void 0
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
capabilities,
|
|
172
|
+
defaults: resolveOpenAICompletionsCompatDefaultsFromCapabilities({
|
|
173
|
+
provider: model.provider,
|
|
174
|
+
modelId: model.id,
|
|
175
|
+
baseUrl: model.baseUrl,
|
|
176
|
+
...capabilities
|
|
177
|
+
})
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function resolveSessionAffinity(model, detectedFormat) {
|
|
181
|
+
if (model.compat?.sendSessionAffinityHeaders !== true) return "none";
|
|
182
|
+
if (detectedFormat === "openrouter" || model.compat.thinkingFormat === "openrouter" || model.compat.openRouterRouting !== void 0) return "openrouter";
|
|
183
|
+
return "openai";
|
|
184
|
+
}
|
|
185
|
+
/** Applies explicit model overrides once on top of the canonical transport defaults. */
|
|
186
|
+
function resolveOpenAICompletionsCompat(model, resolveCapabilities = resolveProviderRequestCapabilities) {
|
|
187
|
+
const { defaults } = detectOpenAICompletionsCompat(model, resolveCapabilities);
|
|
188
|
+
const configured = model.compat;
|
|
189
|
+
return {
|
|
190
|
+
supportsStore: configured?.supportsStore ?? defaults.supportsStore,
|
|
191
|
+
supportsDeveloperRole: configured?.supportsDeveloperRole ?? defaults.supportsDeveloperRole,
|
|
192
|
+
supportsReasoningEffort: configured?.supportsReasoningEffort ?? defaults.supportsReasoningEffort,
|
|
193
|
+
supportsUsageInStreaming: configured?.supportsUsageInStreaming ?? defaults.supportsUsageInStreaming,
|
|
194
|
+
maxTokensField: configured?.maxTokensField ?? defaults.maxTokensField,
|
|
195
|
+
requiresToolResultName: configured?.requiresToolResultName ?? false,
|
|
196
|
+
requiresAssistantAfterToolResult: configured?.requiresAssistantAfterToolResult ?? false,
|
|
197
|
+
requiresThinkingAsText: configured?.requiresThinkingAsText ?? false,
|
|
198
|
+
requiresReasoningContentOnAssistantMessages: configured?.requiresReasoningContentOnAssistantMessages ?? defaults.requiresReasoningContentOnAssistantMessages,
|
|
199
|
+
thinkingFormat: configured?.thinkingFormat ?? defaults.thinkingFormat,
|
|
200
|
+
openRouterRouting: configured?.openRouterRouting,
|
|
201
|
+
vercelGatewayRouting: configured?.vercelGatewayRouting ?? {},
|
|
202
|
+
zaiToolStream: configured?.zaiToolStream ?? false,
|
|
203
|
+
supportsStrictMode: configured?.supportsStrictMode ?? defaults.supportsStrictMode,
|
|
204
|
+
supportsJsonSchemaResponseFormat: configured?.supportsJsonSchemaResponseFormat ?? defaults.supportsJsonSchemaResponseFormat,
|
|
205
|
+
cacheControlFormat: configured?.cacheControlFormat ?? defaults.cacheControlFormat,
|
|
206
|
+
sessionAffinity: resolveSessionAffinity(model, defaults.sessionAffinityFormat),
|
|
207
|
+
supportsPromptCacheKey: configured?.supportsPromptCacheKey ?? false,
|
|
208
|
+
supportsLongCacheRetention: configured?.supportsLongCacheRetention ?? defaults.supportsLongCacheRetention,
|
|
209
|
+
visibleReasoningDetailTypes: configured && "visibleReasoningDetailTypes" in configured ? configured.visibleReasoningDetailTypes ?? defaults.visibleReasoningDetailTypes : defaults.visibleReasoningDetailTypes,
|
|
210
|
+
requiresNonEmptyUserOrAssistantMessage: defaults.requiresNonEmptyUserOrAssistantMessage
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
if (process.env.VITEST || false) globalThis[Symbol.for("openclaw.openAICompletionsCompatTestApi")] = { resolveOpenAICompletionsCompatDefaults };
|
|
214
|
+
//#endregion
|
|
51
215
|
//#region packages/ai/src/transports/openai-reasoning-compat.ts
|
|
52
216
|
/**
|
|
53
217
|
* OpenAI reasoning-effort compatibility helpers.
|
|
@@ -76,224 +240,6 @@ function resolveOpenAIReasoningEffortMap(model, fallbackMap = {}) {
|
|
|
76
240
|
};
|
|
77
241
|
}
|
|
78
242
|
//#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
|
|
297
243
|
//#region packages/ai/src/providers/openai-stop-reason.ts
|
|
298
244
|
function mapOpenAIStopReason(reason, options) {
|
|
299
245
|
if (reason === null) return { stopReason: "stop" };
|
|
@@ -321,6 +267,192 @@ function mapOpenAIStopReason(reason, options) {
|
|
|
321
267
|
};
|
|
322
268
|
}
|
|
323
269
|
//#endregion
|
|
270
|
+
//#region packages/ai/src/providers/openai-tool-projection.ts
|
|
271
|
+
function unreadableToolDiagnostic(toolIndex) {
|
|
272
|
+
return {
|
|
273
|
+
toolIndex,
|
|
274
|
+
violations: [`tool[${toolIndex}] is unreadable`]
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
/** Snapshots direct/custom tool descriptors before OpenAI payload construction. */
|
|
278
|
+
function projectOpenAITools(tools) {
|
|
279
|
+
let inputToolCount;
|
|
280
|
+
try {
|
|
281
|
+
inputToolCount = tools.length;
|
|
282
|
+
} catch {
|
|
283
|
+
return {
|
|
284
|
+
inputToolCount: 0,
|
|
285
|
+
tools: [],
|
|
286
|
+
diagnostics: [unreadableToolDiagnostic(0)]
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
const projectedTools = [];
|
|
290
|
+
const diagnostics = [];
|
|
291
|
+
for (let toolIndex = 0; toolIndex < inputToolCount; toolIndex += 1) {
|
|
292
|
+
let tool;
|
|
293
|
+
try {
|
|
294
|
+
const candidate = tools[toolIndex];
|
|
295
|
+
if (!candidate) {
|
|
296
|
+
diagnostics.push(unreadableToolDiagnostic(toolIndex));
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
tool = candidate;
|
|
300
|
+
} catch {
|
|
301
|
+
diagnostics.push(unreadableToolDiagnostic(toolIndex));
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
let name;
|
|
305
|
+
try {
|
|
306
|
+
name = tool.name;
|
|
307
|
+
} catch {
|
|
308
|
+
diagnostics.push({
|
|
309
|
+
toolIndex,
|
|
310
|
+
violations: [`tool[${toolIndex}].name is unreadable`]
|
|
311
|
+
});
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
if (typeof name !== "string" || !name) {
|
|
315
|
+
diagnostics.push({
|
|
316
|
+
toolIndex,
|
|
317
|
+
violations: [`tool[${toolIndex}].name is empty`]
|
|
318
|
+
});
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
let parameters;
|
|
322
|
+
try {
|
|
323
|
+
parameters = tool.parameters;
|
|
324
|
+
} catch {
|
|
325
|
+
diagnostics.push({
|
|
326
|
+
toolIndex,
|
|
327
|
+
toolName: name,
|
|
328
|
+
violations: [`${name}.parameters is unreadable`]
|
|
329
|
+
});
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
const schemaProjection = projectRuntimeToolInputSchema(parameters ?? {}, `${name}.parameters`);
|
|
333
|
+
if (!isRecord(schemaProjection.schema) || schemaProjection.violations.length > 0) {
|
|
334
|
+
diagnostics.push({
|
|
335
|
+
toolIndex,
|
|
336
|
+
toolName: name,
|
|
337
|
+
violations: schemaProjection.violations.length > 0 ? schemaProjection.violations : [`${name}.parameters must be a JSON object schema`]
|
|
338
|
+
});
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
let descriptionValue;
|
|
342
|
+
try {
|
|
343
|
+
descriptionValue = tool.description;
|
|
344
|
+
} catch {}
|
|
345
|
+
const description = typeof descriptionValue === "string" ? descriptionValue : void 0;
|
|
346
|
+
projectedTools.push({
|
|
347
|
+
toolIndex,
|
|
348
|
+
name,
|
|
349
|
+
...description !== void 0 ? { description } : {},
|
|
350
|
+
parameters: schemaProjection.schema
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
inputToolCount,
|
|
355
|
+
tools: projectedTools,
|
|
356
|
+
diagnostics
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
function requireProjectedFunction(name, projection, choiceLabel) {
|
|
360
|
+
if (!projection.tools.some((tool) => tool.name === name)) throw new Error(`${choiceLabel} requested unavailable tool "${name}" after schema conversion`);
|
|
361
|
+
}
|
|
362
|
+
/** Keeps Responses tool choices aligned with surviving function schemas. */
|
|
363
|
+
function reconcileOpenAIResponsesToolChoice(choice, projection) {
|
|
364
|
+
if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
|
|
365
|
+
if (choice === "required") {
|
|
366
|
+
if (projection.tools.length === 0) throw new Error("OpenAI Responses tool_choice requires a tool, but no tools survived schema conversion");
|
|
367
|
+
return choice;
|
|
368
|
+
}
|
|
369
|
+
if (choice === "none" || !isRecord(choice)) return choice;
|
|
370
|
+
const choiceType = choice.type;
|
|
371
|
+
if (choiceType === "function") {
|
|
372
|
+
const functionName = choice.name;
|
|
373
|
+
if (typeof functionName !== "string") return choice;
|
|
374
|
+
requireProjectedFunction(functionName, projection, "OpenAI Responses tool_choice");
|
|
375
|
+
return {
|
|
376
|
+
type: "function",
|
|
377
|
+
name: functionName
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
if (choiceType !== "allowed_tools") return choice;
|
|
381
|
+
const mode = choice.mode;
|
|
382
|
+
const tools = choice.tools;
|
|
383
|
+
if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
|
|
384
|
+
const normalizedAllowedTools = [];
|
|
385
|
+
for (const tool of tools) {
|
|
386
|
+
if (!isRecord(tool) || tool.type !== "function") {
|
|
387
|
+
normalizedAllowedTools.push(tool);
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
const functionName = tool.name;
|
|
391
|
+
if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) normalizedAllowedTools.push({
|
|
392
|
+
type: "function",
|
|
393
|
+
name: functionName
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
if (normalizedAllowedTools.length === 0) {
|
|
397
|
+
if (mode === "auto") return "none";
|
|
398
|
+
throw new Error("OpenAI Responses tool_choice requires a tool, but no allowed tools survived schema conversion");
|
|
399
|
+
}
|
|
400
|
+
return {
|
|
401
|
+
type: "allowed_tools",
|
|
402
|
+
mode,
|
|
403
|
+
tools: normalizedAllowedTools
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/** Keeps Chat Completions tool choices aligned with surviving function schemas. */
|
|
407
|
+
function reconcileOpenAICompletionsToolChoice(choice, projection) {
|
|
408
|
+
if (choice === "auto") return projection.tools.length > 0 ? choice : void 0;
|
|
409
|
+
if (choice === "required") {
|
|
410
|
+
if (projection.tools.length === 0) throw new Error("OpenAI Chat Completions tool_choice requires a tool, but no tools survived schema conversion");
|
|
411
|
+
return choice;
|
|
412
|
+
}
|
|
413
|
+
if (choice === "none" || !isRecord(choice)) return choice;
|
|
414
|
+
const choiceType = choice.type;
|
|
415
|
+
if (choiceType === "custom") throw new Error("OpenAI Chat Completions custom tool_choice is unsupported because this adapter emits function tools only");
|
|
416
|
+
if (choiceType === "function") {
|
|
417
|
+
const functionChoice = choice.function;
|
|
418
|
+
if (!isRecord(functionChoice)) return choice;
|
|
419
|
+
const functionName = functionChoice.name;
|
|
420
|
+
if (typeof functionName !== "string") return choice;
|
|
421
|
+
requireProjectedFunction(functionName, projection, "OpenAI Chat Completions tool_choice");
|
|
422
|
+
return {
|
|
423
|
+
type: "function",
|
|
424
|
+
function: { name: functionName }
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (choiceType !== "allowed_tools") return choice;
|
|
428
|
+
const allowedConfig = choice.allowed_tools;
|
|
429
|
+
if (!isRecord(allowedConfig)) return choice;
|
|
430
|
+
const mode = allowedConfig.mode;
|
|
431
|
+
const tools = allowedConfig.tools;
|
|
432
|
+
if (mode !== "auto" && mode !== "required" || !Array.isArray(tools)) return choice;
|
|
433
|
+
const normalizedAllowedTools = [];
|
|
434
|
+
for (const tool of tools) {
|
|
435
|
+
if (!isRecord(tool) || tool.type !== "function") continue;
|
|
436
|
+
const functionChoice = tool.function;
|
|
437
|
+
const functionName = isRecord(functionChoice) ? functionChoice.name : void 0;
|
|
438
|
+
if (typeof functionName === "string" && projection.tools.some((projectedTool) => projectedTool.name === functionName)) normalizedAllowedTools.push({
|
|
439
|
+
type: "function",
|
|
440
|
+
function: { name: functionName }
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
if (normalizedAllowedTools.length === 0) {
|
|
444
|
+
if (mode === "auto") return "none";
|
|
445
|
+
throw new Error("OpenAI Chat Completions tool_choice requires a tool, but no allowed tools survived schema conversion");
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
type: "allowed_tools",
|
|
449
|
+
allowed_tools: {
|
|
450
|
+
mode,
|
|
451
|
+
tools: normalizedAllowedTools
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
//#endregion
|
|
324
456
|
//#region packages/ai/src/providers/openai-completions.ts
|
|
325
457
|
var openai_completions_exports = /* @__PURE__ */ __exportAll({
|
|
326
458
|
convertMessages: () => convertMessages,
|
|
@@ -650,7 +782,7 @@ const streamOpenAICompletions = (model, context, options) => {
|
|
|
650
782
|
}
|
|
651
783
|
flushPartitionedContent();
|
|
652
784
|
for (const block of blocks) finishBlock(block);
|
|
653
|
-
if (options?.signal?.aborted) throw
|
|
785
|
+
if (options?.signal?.aborted) throw transportAbortError(options.signal);
|
|
654
786
|
if (output.stopReason === "aborted") throw new Error("Request was aborted");
|
|
655
787
|
if (output.stopReason === "error") throw new Error(output.errorMessage || "Provider returned an error stop reason");
|
|
656
788
|
if (!hasFinishReason) throw new Error("Stream ended without finish_reason");
|
|
@@ -758,6 +890,13 @@ function buildParams(model, context, options, compat = resolveOpenAICompletionsC
|
|
|
758
890
|
}
|
|
759
891
|
if (options?.temperature !== void 0) params.temperature = options.temperature;
|
|
760
892
|
if (options?.stop !== void 0 && options.stop.length > 0) params.stop = options.stop;
|
|
893
|
+
const requestedResponseFormat = options?.responseFormat;
|
|
894
|
+
const responseFormat = requestedResponseFormat === void 0 ? void 0 : resolveOpenAICompletionsResponseFormat(shouldOmitOllamaCompatResponseFormat({
|
|
895
|
+
provider: model.provider,
|
|
896
|
+
baseUrl: model.baseUrl,
|
|
897
|
+
hasTools: () => Boolean(context.tools?.length)
|
|
898
|
+
}) ? void 0 : requestedResponseFormat, compat.supportsJsonSchemaResponseFormat);
|
|
899
|
+
if (responseFormat !== void 0) params.response_format = responseFormat;
|
|
761
900
|
let toolProjection;
|
|
762
901
|
if (context.tools) {
|
|
763
902
|
const converted = convertTools(context.tools, compat);
|
|
@@ -1081,4 +1220,4 @@ function parseChunkUsage(rawUsage, model) {
|
|
|
1081
1220
|
return usage;
|
|
1082
1221
|
}
|
|
1083
1222
|
//#endregion
|
|
1084
|
-
export {
|
|
1223
|
+
export { transformTransportMessages as C, resolveProviderRequestPolicyConfig as S, buildGuardedModelFetch as _, projectOpenAITools as a, resolveProviderEndpoint as b, mapOpenAIStopReason as c, resolveOpenAICompletionsCompat as d, resolveOpenAICompletionsResponseFormat as f, tagPendingCommentaryText as g, rememberPendingCommentaryTags as h, streamSimpleOpenAICompletions as i, resolveOpenAIReasoningEffortMap as l, clearPendingCommentaryText as m, openai_completions_exports as n, reconcileOpenAICompletionsToolChoice as o, shouldOmitOllamaCompatResponseFormat as p, streamOpenAICompletions as r, reconcileOpenAIResponsesToolChoice as s, convertMessages as t, detectOpenAICompletionsCompat as u, resolveModelRequestTimeoutMs as v, resolveProviderRequestCapabilities as x, resolveOpenAIStrictToolSetting as y };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region packages/ai/src/providers/openai-prompt-cache.d.ts
|
|
2
|
+
/** Maximum prompt cache key length accepted by OpenAI-compatible request metadata. */
|
|
3
|
+
declare const OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH = 64;
|
|
4
|
+
/** Truncates a prompt cache key by Unicode code point count. */
|
|
5
|
+
declare function clampOpenAIPromptCacheKey(key: string | undefined): string | undefined;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { clampOpenAIPromptCacheKey as n, OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH as t };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region packages/ai/src/providers/openai-prompt-cache.ts
|
|
2
|
+
/** Maximum prompt cache key length accepted by OpenAI-compatible request metadata. */
|
|
3
|
+
const OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH = 64;
|
|
4
|
+
/** Truncates a prompt cache key by Unicode code point count. */
|
|
5
|
+
function clampOpenAIPromptCacheKey(key) {
|
|
6
|
+
if (key === void 0) return;
|
|
7
|
+
const chars = Array.from(key);
|
|
8
|
+
if (chars.length <= 64) return key;
|
|
9
|
+
return chars.slice(0, 64).join("");
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { clampOpenAIPromptCacheKey as n, OPENAI_PROMPT_CACHE_KEY_MAX_LENGTH as t };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region packages/ai/src/utils/prompt-cache-stability.d.ts
|
|
2
|
+
/** Canonicalizes provider tool order without relying on host locale settings. */
|
|
3
|
+
declare function sortPromptCacheToolsByName<T extends {
|
|
4
|
+
readonly name?: string;
|
|
5
|
+
readonly wireName?: string;
|
|
6
|
+
readonly description?: string;
|
|
7
|
+
}>(tools: readonly T[]): T[];
|
|
8
|
+
/** Normalize structured prompt text before hashing or snapshot comparison. */
|
|
9
|
+
declare function normalizeStructuredPromptSection(text: string): string;
|
|
10
|
+
/** Normalize, de-dupe, and sort capability ids for stable prompt payloads. */
|
|
11
|
+
declare function normalizePromptCapabilityIds(capabilities: ReadonlyArray<string>): string[];
|
|
12
|
+
//#endregion
|
|
13
|
+
export { normalizeStructuredPromptSection as n, sortPromptCacheToolsByName as r, normalizePromptCapabilityIds as t };
|