@zhivex-ai/openai 0.16.3 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -10
- package/dist/decision.d.ts.map +1 -1
- package/dist/decision.js +53 -8
- package/dist/decision.js.map +1 -1
- package/dist/index.d.ts +29 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +174 -23
- package/dist/index.js.map +1 -1
- package/dist/live-audio.d.ts +3 -2
- package/dist/live-audio.d.ts.map +1 -1
- package/dist/live-audio.js.map +1 -1
- package/dist/live-session.d.ts +7 -6
- package/dist/live-session.d.ts.map +1 -1
- package/dist/live-session.js +5 -3
- package/dist/live-session.js.map +1 -1
- package/dist/live-webrtc-server.d.ts +5 -3
- package/dist/live-webrtc-server.d.ts.map +1 -1
- package/dist/live-webrtc-server.js +2 -1
- package/dist/live-webrtc-server.js.map +1 -1
- package/dist/live.d.ts +3 -2
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js.map +1 -1
- package/dist/model-profiles.d.ts +7 -0
- package/dist/model-profiles.d.ts.map +1 -1
- package/dist/model-profiles.js +20 -8
- package/dist/model-profiles.js.map +1 -1
- package/dist/realtime.d.ts +4 -3
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +13 -2
- package/dist/realtime.js.map +1 -1
- package/dist/resource-models.d.ts +2 -1
- package/dist/resource-models.d.ts.map +1 -1
- package/dist/resource-models.js +2 -1
- package/dist/resource-models.js.map +1 -1
- package/dist/voice.d.ts +34 -0
- package/dist/voice.d.ts.map +1 -0
- package/dist/voice.js +29 -0
- package/dist/voice.js.map +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4,15 +4,87 @@ import { computerInputSchema, computerScreenshotSchema } from "./computer.js";
|
|
|
4
4
|
export { openAIComputerTool, OpenAIComputerExecutionError } from "./computer.js";
|
|
5
5
|
import { jsonHeaders, parseJson, RESERVED_REQUEST_HEADERS } from "./http.js";
|
|
6
6
|
import { OpenAIRealtimeModel, openAIRealtimeMcpMetadataKey, resolveOpenAIRealtimeHeaders } from "./realtime.js";
|
|
7
|
-
export { openAIRealtimeMcpMetadataKey } from "./realtime.js";
|
|
7
|
+
export { OpenAIRealtimeModel, openAIRealtimeMcpMetadataKey } from "./realtime.js";
|
|
8
8
|
import { OpenAIEmbeddingModel, OpenAITranscriptionModel, OpenAISpeechModel, toUint8Array } from "./resource-models.js";
|
|
9
|
+
export { OpenAISpeechModel } from "./resource-models.js";
|
|
9
10
|
import { OpenAIAgentsClient } from "./agents.js";
|
|
10
11
|
export { OpenAIAgentsClient } from "./agents.js";
|
|
11
12
|
import { toJSONSchema, z } from "zod";
|
|
12
13
|
import { OpenAILiveModel, isOpenAILiveModel } from "./live.js";
|
|
14
|
+
export { OpenAILiveModel } from "./live.js";
|
|
13
15
|
import { createOpenAIImageGenerationModel, normalizeOpenAIImageGenerationCall, normalizeOpenAIImageGenerationPartialImage } from "./image-generation.js";
|
|
14
16
|
import { groundedCapabilities, supportsOpenAIModernResponses, assertOpenAIModelRequestSupported, resolveOpenAIModelProfile, modelCapabilities } from "./capabilities.js";
|
|
15
|
-
import { imageInputToDataUrl, ConfigurationError, ProviderHTTPError, ProviderResponseTooLargeError, ProviderToolCallError, assertTrustedEndpoint, resolveAudioResponseLimits, openWebSocketConnection, hostedTool, providerDataPart, UnsupportedFeatureError, createProviderAdapter, isCallableToolDefinition, isHostedToolDefinition, normalizeFinishReason, streamSSE, streamChatCompletions, toolResultPayload, withRetry, withResponseRetry, withTimeoutSignal } from "@zhivex-ai/core/provider";
|
|
17
|
+
import { imageInputToDataUrl, ConfigurationError, ProviderHTTPError, ProviderResponseTooLargeError, ProviderToolCallError, ValidationError, assertTrustedEndpoint, resolveAudioResponseLimits, openWebSocketConnection, hostedTool, providerDataPart, UnsupportedFeatureError, createProviderAdapter, isCallableToolDefinition, isHostedToolDefinition, normalizeFinishReason, streamSSE, streamChatCompletions, toolResultPayload, withRetry, withResponseRetry, withTimeoutSignal } from "@zhivex-ai/core/provider";
|
|
18
|
+
const TOOL_INPUT_JSON_SCHEMA = Symbol.for("@zhivex-ai/core/json-schema");
|
|
19
|
+
/** Zod inputs stay on toJSONSchema so this package still loads against the oldest core in its peer range. */
|
|
20
|
+
const toolInputSchema = (schema) => {
|
|
21
|
+
if (schema !== null && typeof schema === "object" && schema[TOOL_INPUT_JSON_SCHEMA] === true) {
|
|
22
|
+
return { ...schema.jsonSchema };
|
|
23
|
+
}
|
|
24
|
+
return toJSONSchema(schema);
|
|
25
|
+
};
|
|
26
|
+
const openAISamplingWarnings = new Set();
|
|
27
|
+
const warnOpenAISampling = (option, detail) => {
|
|
28
|
+
const key = `openai:${option}:${detail}`;
|
|
29
|
+
if (openAISamplingWarnings.has(key))
|
|
30
|
+
return;
|
|
31
|
+
openAISamplingWarnings.add(key);
|
|
32
|
+
console.warn(`Provider "openai" does not support ${option}. ${detail} The option was ignored.`);
|
|
33
|
+
};
|
|
34
|
+
const openAIChatCacheTtlWarnings = new Set();
|
|
35
|
+
const warnOpenAIChatPromptCacheTtl = () => {
|
|
36
|
+
const key = 'openai:prompt_cache_options.ttl:12h:chat';
|
|
37
|
+
if (openAIChatCacheTtlWarnings.has(key))
|
|
38
|
+
return;
|
|
39
|
+
openAIChatCacheTtlWarnings.add(key);
|
|
40
|
+
console.warn('Provider "openai" does not support prompt_cache_options.ttl "12h" on Chat Completions. The option was ignored.');
|
|
41
|
+
};
|
|
42
|
+
/** Chat Completions support for a 12-hour cache TTL is unconfirmed, so that value is ignored. */
|
|
43
|
+
const openAIChatBodyOptions = (options) => {
|
|
44
|
+
const cache = options.prompt_cache_options;
|
|
45
|
+
if (cache?.ttl !== "12h")
|
|
46
|
+
return options;
|
|
47
|
+
warnOpenAIChatPromptCacheTtl();
|
|
48
|
+
const rest = { ...cache };
|
|
49
|
+
delete rest.ttl;
|
|
50
|
+
const next = { ...options };
|
|
51
|
+
if (Object.keys(rest).length === 0)
|
|
52
|
+
delete next.prompt_cache_options;
|
|
53
|
+
else
|
|
54
|
+
next.prompt_cache_options = rest;
|
|
55
|
+
return next;
|
|
56
|
+
};
|
|
57
|
+
/** Model profiles that already reject sampling. `topP` still throws in assertOpenAIModelRequestSupported. */
|
|
58
|
+
const openAISamplingRejected = (modelId, input, bodyOptions) => {
|
|
59
|
+
const profile = resolveOpenAIModelProfile(modelId);
|
|
60
|
+
if (profile.sampling === "allowed")
|
|
61
|
+
return null;
|
|
62
|
+
const effort = input.reasoning?.effort ?? bodyOptions.reasoning?.effort ?? bodyOptions.reasoning_effort;
|
|
63
|
+
return profile.sampling === "unsupported" || effort !== "none" ? profile.label : null;
|
|
64
|
+
};
|
|
65
|
+
const openAIChatSampling = (modelId, input, bodyOptions) => {
|
|
66
|
+
const rejected = openAISamplingRejected(modelId, input, bodyOptions);
|
|
67
|
+
if (rejected) {
|
|
68
|
+
if (input.seed !== undefined)
|
|
69
|
+
warnOpenAISampling("seed", `${rejected} does not support seed.`);
|
|
70
|
+
if (input.stopSequences !== undefined) {
|
|
71
|
+
warnOpenAISampling("stopSequences", `${rejected} does not support stop sequences.`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
...(input.topP !== undefined ? { top_p: input.topP } : {}),
|
|
76
|
+
...(!rejected && input.seed !== undefined ? { seed: input.seed } : {}),
|
|
77
|
+
...(!rejected && input.stopSequences !== undefined ? { stop: [...input.stopSequences] } : {})
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
const openAIResponsesSampling = (input) => {
|
|
81
|
+
if (input.seed !== undefined)
|
|
82
|
+
warnOpenAISampling("seed", "The Responses API does not accept seed.");
|
|
83
|
+
if (input.stopSequences !== undefined) {
|
|
84
|
+
warnOpenAISampling("stopSequences", "The Responses API does not accept stop sequences.");
|
|
85
|
+
}
|
|
86
|
+
return input.topP !== undefined ? { top_p: input.topP } : {};
|
|
87
|
+
};
|
|
16
88
|
const MIB = 1024 * 1024;
|
|
17
89
|
const DEFAULT_HOSTED_IMAGE_EVENT_BYTES = 32 * MIB;
|
|
18
90
|
const DEFAULT_HOSTED_IMAGE_TOTAL_BYTES = 128 * MIB;
|
|
@@ -182,6 +254,14 @@ const isOpenAIPromptCacheBreakpointPart = (part) => part.type === "provider-data
|
|
|
182
254
|
part.data !== null &&
|
|
183
255
|
typeof part.data === "object" &&
|
|
184
256
|
part.data.type === "prompt_cache_breakpoint";
|
|
257
|
+
const explicitPromptCacheBreakpoint = (breakpoint) => {
|
|
258
|
+
const record = breakpoint;
|
|
259
|
+
const ttl = record.ttl;
|
|
260
|
+
if (ttl !== undefined && ttl !== "30m" && ttl !== "12h") {
|
|
261
|
+
throw new ValidationError('OpenAI prompt cache breakpoint ttl must be "30m" or "12h".');
|
|
262
|
+
}
|
|
263
|
+
return ttl === "30m" || ttl === "12h" ? { mode: "explicit", ttl } : { mode: "explicit" };
|
|
264
|
+
};
|
|
185
265
|
const promptCacheBreakpointForContentPart = (part) => {
|
|
186
266
|
const metadata = part
|
|
187
267
|
.providerMetadata;
|
|
@@ -190,7 +270,7 @@ const promptCacheBreakpointForContentPart = (part) => {
|
|
|
190
270
|
: metadata;
|
|
191
271
|
const breakpoint = openAIMetadata?.prompt_cache_breakpoint;
|
|
192
272
|
return breakpoint && typeof breakpoint === "object" && !Array.isArray(breakpoint)
|
|
193
|
-
? { prompt_cache_breakpoint:
|
|
273
|
+
? { prompt_cache_breakpoint: explicitPromptCacheBreakpoint(breakpoint) }
|
|
194
274
|
: {};
|
|
195
275
|
};
|
|
196
276
|
const imageDetailForPart = (part) => {
|
|
@@ -201,12 +281,12 @@ const imageDetailForPart = (part) => {
|
|
|
201
281
|
: undefined);
|
|
202
282
|
return detail === "auto" || detail === "low" || detail === "high" || detail === "original" ? detail : undefined;
|
|
203
283
|
};
|
|
204
|
-
const markLastContentBlockForPromptCaching = (content) => {
|
|
284
|
+
const markLastContentBlockForPromptCaching = (content, breakpoint) => {
|
|
205
285
|
const last = content.at(-1);
|
|
206
286
|
if (!last) {
|
|
207
287
|
throw new ConfigurationError("OpenAI prompt cache breakpoints must follow a cacheable content part.");
|
|
208
288
|
}
|
|
209
|
-
last.prompt_cache_breakpoint =
|
|
289
|
+
last.prompt_cache_breakpoint = explicitPromptCacheBreakpoint(breakpoint);
|
|
210
290
|
};
|
|
211
291
|
const mapContentParts = (message) => {
|
|
212
292
|
const hasRichContent = message.parts.some((part) => part.type === "image" ||
|
|
@@ -251,7 +331,7 @@ const mapContentParts = (message) => {
|
|
|
251
331
|
});
|
|
252
332
|
}
|
|
253
333
|
else if (isOpenAIPromptCacheBreakpointPart(part)) {
|
|
254
|
-
markLastContentBlockForPromptCaching(content);
|
|
334
|
+
markLastContentBlockForPromptCaching(content, part.data);
|
|
255
335
|
}
|
|
256
336
|
}
|
|
257
337
|
return content;
|
|
@@ -358,7 +438,7 @@ const mapTools = (input) => input
|
|
|
358
438
|
function: {
|
|
359
439
|
name: tool.name,
|
|
360
440
|
description: tool.description,
|
|
361
|
-
parameters:
|
|
441
|
+
parameters: toolInputSchema(tool.schema)
|
|
362
442
|
}
|
|
363
443
|
};
|
|
364
444
|
}
|
|
@@ -385,7 +465,7 @@ const mapResponsesTools = (input) => input
|
|
|
385
465
|
type: "function",
|
|
386
466
|
name: tool.name,
|
|
387
467
|
description: tool.description,
|
|
388
|
-
parameters:
|
|
468
|
+
parameters: toolInputSchema(tool.schema),
|
|
389
469
|
...openAIResponsesFunctionConfig(tool)
|
|
390
470
|
};
|
|
391
471
|
}
|
|
@@ -798,7 +878,7 @@ const toResponsesInput = (messages, format, history = messages) => {
|
|
|
798
878
|
break;
|
|
799
879
|
case "provider-data":
|
|
800
880
|
if (isOpenAIPromptCacheBreakpointPart(part)) {
|
|
801
|
-
markLastContentBlockForPromptCaching(content);
|
|
881
|
+
markLastContentBlockForPromptCaching(content, part.data);
|
|
802
882
|
}
|
|
803
883
|
break;
|
|
804
884
|
}
|
|
@@ -966,36 +1046,90 @@ const attachTerminalUsage = (error, raw) => new ProviderToolCallError({
|
|
|
966
1046
|
cause: error.cause,
|
|
967
1047
|
usage: mapResponsesUsage(raw)
|
|
968
1048
|
});
|
|
969
|
-
const
|
|
970
|
-
|
|
1049
|
+
const mapOpenAICacheWriteTokensDetails = (details) => {
|
|
1050
|
+
if (!details || typeof details !== "object" || Array.isArray(details))
|
|
1051
|
+
return undefined;
|
|
1052
|
+
const record = details;
|
|
1053
|
+
const read = (key) => typeof record[key] === "number" ? record[key] : undefined;
|
|
1054
|
+
const ttl30mTokens = read("ttl_30m_tokens");
|
|
1055
|
+
const ttl12hTokens = read("ttl_12h_tokens");
|
|
1056
|
+
if (ttl30mTokens === undefined && ttl12hTokens === undefined)
|
|
1057
|
+
return undefined;
|
|
1058
|
+
return {
|
|
1059
|
+
...(ttl30mTokens !== undefined ? { ttl30mTokens } : {}),
|
|
1060
|
+
...(ttl12hTokens !== undefined ? { ttl12hTokens } : {})
|
|
1061
|
+
};
|
|
1062
|
+
};
|
|
1063
|
+
const mapResponsesUsage = (usage) => {
|
|
1064
|
+
if (!usage)
|
|
1065
|
+
return undefined;
|
|
1066
|
+
const cacheWriteTokensDetails = mapOpenAICacheWriteTokensDetails(usage.input_tokens_details?.cache_write_tokens_details);
|
|
1067
|
+
return {
|
|
971
1068
|
inputTokens: usage.input_tokens,
|
|
972
1069
|
cachedInputTokens: usage.input_tokens_details?.cached_tokens,
|
|
973
1070
|
cacheWriteTokens: usage.input_tokens_details?.cache_write_tokens,
|
|
1071
|
+
...(cacheWriteTokensDetails ? { cacheWriteTokensDetails } : {}),
|
|
974
1072
|
outputTokens: usage.output_tokens,
|
|
975
1073
|
reasoningTokens: usage.output_tokens_details?.reasoning_tokens,
|
|
976
1074
|
totalTokens: usage.total_tokens
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
const mapChatUsage = (usage) =>
|
|
980
|
-
|
|
1075
|
+
};
|
|
1076
|
+
};
|
|
1077
|
+
const mapChatUsage = (usage) => {
|
|
1078
|
+
if (!usage)
|
|
1079
|
+
return undefined;
|
|
1080
|
+
const cacheWriteTokensDetails = mapOpenAICacheWriteTokensDetails(usage.prompt_tokens_details?.cache_write_tokens_details);
|
|
1081
|
+
return {
|
|
981
1082
|
inputTokens: usage.prompt_tokens,
|
|
982
1083
|
cachedInputTokens: usage.prompt_tokens_details?.cached_tokens,
|
|
983
1084
|
cacheWriteTokens: usage.prompt_tokens_details?.cache_write_tokens,
|
|
1085
|
+
...(cacheWriteTokensDetails ? { cacheWriteTokensDetails } : {}),
|
|
984
1086
|
outputTokens: usage.completion_tokens,
|
|
985
1087
|
reasoningTokens: usage.completion_tokens_details?.reasoning_tokens,
|
|
986
1088
|
totalTokens: usage.total_tokens
|
|
987
|
-
}
|
|
988
|
-
|
|
1089
|
+
};
|
|
1090
|
+
};
|
|
1091
|
+
const openAIUsageCounters = (usage) => [
|
|
1092
|
+
usage.inputTokens,
|
|
1093
|
+
usage.outputTokens,
|
|
1094
|
+
usage.totalTokens,
|
|
1095
|
+
usage.cachedInputTokens,
|
|
1096
|
+
usage.cacheWriteTokens,
|
|
1097
|
+
usage.reasoningTokens,
|
|
1098
|
+
usage.cacheWriteTokensDetails?.ttl30mTokens,
|
|
1099
|
+
usage.cacheWriteTokensDetails?.ttl12hTokens
|
|
1100
|
+
];
|
|
1101
|
+
const openAIUsageCounterInvalid = (usage) => openAIUsageCounters(usage ?? {}).some((value) => value !== undefined && (!Number.isSafeInteger(value) || value < 0));
|
|
989
1102
|
const addTokenUsage = (left, right) => {
|
|
990
1103
|
if (!left)
|
|
991
1104
|
return right;
|
|
992
1105
|
if (!right)
|
|
993
1106
|
return left;
|
|
994
1107
|
const sum = (a, b) => a === undefined || b === undefined ? undefined : a + b;
|
|
1108
|
+
const consistentDetails = (writes, details) => {
|
|
1109
|
+
if (!details)
|
|
1110
|
+
return (writes ?? 0) === 0;
|
|
1111
|
+
return writes !== undefined && (details.ttl30mTokens ?? 0) + (details.ttl12hTokens ?? 0) === writes;
|
|
1112
|
+
};
|
|
1113
|
+
const cacheWriteTokensDetails = consistentDetails(left.cacheWriteTokens, left.cacheWriteTokensDetails) &&
|
|
1114
|
+
consistentDetails(right.cacheWriteTokens, right.cacheWriteTokensDetails) &&
|
|
1115
|
+
(left.cacheWriteTokensDetails || right.cacheWriteTokensDetails)
|
|
1116
|
+
? {
|
|
1117
|
+
...(left.cacheWriteTokensDetails?.ttl30mTokens !== undefined || right.cacheWriteTokensDetails?.ttl30mTokens !== undefined
|
|
1118
|
+
? { ttl30mTokens: (left.cacheWriteTokensDetails?.ttl30mTokens ?? 0) + (right.cacheWriteTokensDetails?.ttl30mTokens ?? 0) }
|
|
1119
|
+
: {}),
|
|
1120
|
+
...(left.cacheWriteTokensDetails?.ttl12hTokens !== undefined || right.cacheWriteTokensDetails?.ttl12hTokens !== undefined
|
|
1121
|
+
? { ttl12hTokens: (left.cacheWriteTokensDetails?.ttl12hTokens ?? 0) + (right.cacheWriteTokensDetails?.ttl12hTokens ?? 0) }
|
|
1122
|
+
: {})
|
|
1123
|
+
}
|
|
1124
|
+
: undefined;
|
|
995
1125
|
return {
|
|
996
1126
|
inputTokens: sum(left.inputTokens, right.inputTokens),
|
|
997
1127
|
cachedInputTokens: sum(left.cachedInputTokens, right.cachedInputTokens),
|
|
998
1128
|
cacheWriteTokens: sum(left.cacheWriteTokens, right.cacheWriteTokens),
|
|
1129
|
+
...(cacheWriteTokensDetails &&
|
|
1130
|
+
(cacheWriteTokensDetails.ttl30mTokens !== undefined || cacheWriteTokensDetails.ttl12hTokens !== undefined)
|
|
1131
|
+
? { cacheWriteTokensDetails }
|
|
1132
|
+
: {}),
|
|
999
1133
|
outputTokens: sum(left.outputTokens, right.outputTokens),
|
|
1000
1134
|
reasoningTokens: sum(left.reasoningTokens, right.reasoningTokens),
|
|
1001
1135
|
totalTokens: sum(left.totalTokens, right.totalTokens)
|
|
@@ -1493,6 +1627,17 @@ class OpenAILanguageModel {
|
|
|
1493
1627
|
if (!this.capabilities.vision && input.messages.some(message => message.parts.some(part => part.type === "image"))) {
|
|
1494
1628
|
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared vision support.`);
|
|
1495
1629
|
}
|
|
1630
|
+
if (!this.capabilities.audioInput && input.messages.some(message => message.parts.some(part => part.type === "audio"))) {
|
|
1631
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared audio input support.`);
|
|
1632
|
+
}
|
|
1633
|
+
// No OpenAI language model advertises video input unless inputMediaTypes says so.
|
|
1634
|
+
const acceptsVideo = this.capabilities.inputMediaTypes?.some((type) => {
|
|
1635
|
+
const normalized = type.toLowerCase();
|
|
1636
|
+
return normalized === "*/*" || normalized === "video/*" || normalized.startsWith("video/");
|
|
1637
|
+
}) === true;
|
|
1638
|
+
if (!acceptsVideo && input.messages.some(message => message.parts.some(part => part.type === "file" && part.mediaType.toLowerCase().startsWith("video/")))) {
|
|
1639
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared video input support.`);
|
|
1640
|
+
}
|
|
1496
1641
|
const rawFormat = options.bodyOptions.response_format;
|
|
1497
1642
|
const rawText = options.bodyOptions.text;
|
|
1498
1643
|
const formatTypes = [rawFormat?.type, rawText?.format?.type];
|
|
@@ -1569,17 +1714,18 @@ class OpenAILanguageModel {
|
|
|
1569
1714
|
...(input.toolChoice ? { tool_choice: mapResponsesToolChoice(input.toolChoice) } : {}),
|
|
1570
1715
|
text: mapResponsesStructuredOutput(input) ?? responseBodyOptions.text,
|
|
1571
1716
|
temperature: input.temperature,
|
|
1717
|
+
...openAIResponsesSampling(input),
|
|
1572
1718
|
max_output_tokens: ptc ? remainingOutputTokens : input.maxTokens,
|
|
1573
1719
|
...mapResponsesReasoning(input, responseBodyOptions.reasoning)
|
|
1574
1720
|
})
|
|
1575
1721
|
}), { ...input, abortSignal: signal, ...(ptc ? { maxRetries: 0 } : {}) }, "OpenAI");
|
|
1576
1722
|
const json = await parseJson(response);
|
|
1577
1723
|
const reportedUsage = mapResponsesUsage(json.usage);
|
|
1578
|
-
if (ptc && (!reportedUsage || ![reportedUsage.inputTokens, reportedUsage.outputTokens, reportedUsage.totalTokens].every(value => typeof value === "number" && Number.isSafeInteger(value) && value >= 0) || reportedUsage.totalTokens < reportedUsage.inputTokens + reportedUsage.outputTokens ||
|
|
1724
|
+
if (ptc && (!reportedUsage || ![reportedUsage.inputTokens, reportedUsage.outputTokens, reportedUsage.totalTokens].every(value => typeof value === "number" && Number.isSafeInteger(value) && value >= 0) || reportedUsage.totalTokens < reportedUsage.inputTokens + reportedUsage.outputTokens || openAIUsageCounterInvalid(reportedUsage))) {
|
|
1579
1725
|
throw failure("OPENAI_PTC_USAGE_UNKNOWN");
|
|
1580
1726
|
}
|
|
1581
1727
|
const nextUsage = addTokenUsage(accumulatedUsage, reportedUsage);
|
|
1582
|
-
if (ptc &&
|
|
1728
|
+
if (ptc && openAIUsageCounterInvalid(nextUsage))
|
|
1583
1729
|
throw failure("OPENAI_PTC_USAGE_UNKNOWN");
|
|
1584
1730
|
accumulatedUsage = nextUsage;
|
|
1585
1731
|
if (ptc)
|
|
@@ -1658,13 +1804,14 @@ class OpenAILanguageModel {
|
|
|
1658
1804
|
headers: options.headers,
|
|
1659
1805
|
signal,
|
|
1660
1806
|
body: JSON.stringify({
|
|
1661
|
-
...options.bodyOptions,
|
|
1807
|
+
...openAIChatBodyOptions(options.bodyOptions),
|
|
1662
1808
|
model: this.modelId,
|
|
1663
1809
|
messages: mapMessages(input.messages, input.toolResultFormat),
|
|
1664
1810
|
tools: mapTools(input.tools),
|
|
1665
1811
|
...(input.toolChoice ? { tool_choice: mapToolChoice(input.toolChoice) } : {}),
|
|
1666
1812
|
response_format: mapStructuredOutput(input) ?? options.bodyOptions.response_format,
|
|
1667
1813
|
temperature: input.temperature,
|
|
1814
|
+
...openAIChatSampling(this.modelId, input, options.bodyOptions),
|
|
1668
1815
|
...(input.reasoning ? {} : { max_tokens: input.maxTokens }),
|
|
1669
1816
|
...mapChatReasoning(input),
|
|
1670
1817
|
stream: false
|
|
@@ -1722,6 +1869,7 @@ class OpenAILanguageModel {
|
|
|
1722
1869
|
...(input.toolChoice ? { tool_choice: mapResponsesToolChoice(input.toolChoice) } : {}),
|
|
1723
1870
|
text: mapResponsesStructuredOutput(input) ?? responseBodyOptions.text,
|
|
1724
1871
|
temperature: input.temperature,
|
|
1872
|
+
...openAIResponsesSampling(input),
|
|
1725
1873
|
max_output_tokens: input.maxTokens,
|
|
1726
1874
|
...mapResponsesReasoning(input, responseBodyOptions.reasoning),
|
|
1727
1875
|
stream: true
|
|
@@ -1744,13 +1892,14 @@ class OpenAILanguageModel {
|
|
|
1744
1892
|
headers: options.headers,
|
|
1745
1893
|
signal,
|
|
1746
1894
|
body: JSON.stringify({
|
|
1747
|
-
...options.bodyOptions,
|
|
1895
|
+
...openAIChatBodyOptions(options.bodyOptions),
|
|
1748
1896
|
model: this.modelId,
|
|
1749
1897
|
messages: mapMessages(input.messages, input.toolResultFormat),
|
|
1750
1898
|
tools: mapTools(input.tools),
|
|
1751
1899
|
...(input.toolChoice ? { tool_choice: mapToolChoice(input.toolChoice) } : {}),
|
|
1752
1900
|
response_format: mapStructuredOutput(input) ?? options.bodyOptions.response_format,
|
|
1753
1901
|
temperature: input.temperature,
|
|
1902
|
+
...openAIChatSampling(this.modelId, input, options.bodyOptions),
|
|
1754
1903
|
...(input.reasoning ? {} : { max_tokens: input.maxTokens }),
|
|
1755
1904
|
...mapChatReasoning(input),
|
|
1756
1905
|
stream: true,
|
|
@@ -1846,6 +1995,7 @@ export const createOpenAI = (options = {}) => {
|
|
|
1846
1995
|
const responseLimits = resolveOpenAIResponseLimits(options.responseLimits);
|
|
1847
1996
|
return createProviderAdapter({
|
|
1848
1997
|
name: "openai",
|
|
1998
|
+
decisionModel: (modelId = "gpt-6-luna") => createOpenAIDecisionModel(modelId, { apiKey, baseURL, fetch: fetcher, allowUnsafeEndpoints: options.allowUnsafeEndpoints }),
|
|
1849
1999
|
experimentalDecisionModel: (modelId = "gpt-6-luna") => createOpenAIDecisionModel(modelId, { apiKey, baseURL, fetch: fetcher, allowUnsafeEndpoints: options.allowUnsafeEndpoints }),
|
|
1850
2000
|
languageModel: (modelId) => {
|
|
1851
2001
|
if (modelId.startsWith("gpt-live-"))
|
|
@@ -1949,9 +2099,10 @@ export const openAIRealtimeMcpApprovalResult = (response) => ({
|
|
|
1949
2099
|
}
|
|
1950
2100
|
}
|
|
1951
2101
|
});
|
|
1952
|
-
export const openAIPromptCacheBreakpoint = () => providerDataPart("openai", {
|
|
2102
|
+
export const openAIPromptCacheBreakpoint = (breakpoint) => providerDataPart("openai", {
|
|
1953
2103
|
type: "prompt_cache_breakpoint",
|
|
1954
|
-
mode: "explicit"
|
|
2104
|
+
mode: "explicit",
|
|
2105
|
+
...(breakpoint?.ttl ? { ttl: breakpoint.ttl } : {})
|
|
1955
2106
|
});
|
|
1956
2107
|
export const openAIComputerUseTool = (config) => hostedTool({
|
|
1957
2108
|
name: "computer",
|