@zhivex-ai/openai 0.13.7 → 0.14.1
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 +30 -0
- package/dist/capabilities.d.ts +1 -15
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +1 -182
- package/dist/capabilities.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +165 -124
- package/dist/index.js.map +1 -1
- package/dist/model-profiles.d.ts +31 -0
- package/dist/model-profiles.d.ts.map +1 -0
- package/dist/model-profiles.js +244 -0
- package/dist/model-profiles.js.map +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ export { OpenAIAgentsClient } from "./agents.js";
|
|
|
7
7
|
import { toJSONSchema, z } from "zod";
|
|
8
8
|
import { OpenAILiveModel, isOpenAILiveModel } from "./live.js";
|
|
9
9
|
import { createOpenAIImageGenerationModel, normalizeOpenAIImageGenerationCall, normalizeOpenAIImageGenerationPartialImage } from "./image-generation.js";
|
|
10
|
-
import { groundedCapabilities, supportsOpenAIModernResponses,
|
|
10
|
+
import { groundedCapabilities, supportsOpenAIModernResponses, assertOpenAIModelRequestSupported, resolveOpenAIModelProfile, modelCapabilities } from "./capabilities.js";
|
|
11
11
|
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";
|
|
12
12
|
const MIB = 1024 * 1024;
|
|
13
13
|
const DEFAULT_HOSTED_IMAGE_EVENT_BYTES = 32 * MIB;
|
|
@@ -270,8 +270,7 @@ const responsesImageGenerationConfig = (tools, limits) => {
|
|
|
270
270
|
: {})
|
|
271
271
|
};
|
|
272
272
|
};
|
|
273
|
-
const assertResponsesToolsSupported = (modelId, tools) => {
|
|
274
|
-
const currentCapabilities = modelCapabilities(modelId).agentCapabilities;
|
|
273
|
+
const assertResponsesToolsSupported = (modelId, tools, currentCapabilities) => {
|
|
275
274
|
for (const definition of Object.values(tools ?? {})) {
|
|
276
275
|
const type = isCallableToolDefinition(definition) ? openAILocalResponsesToolType(definition) : definition.type;
|
|
277
276
|
if (type === "tool_search" && !currentCapabilities?.toolSearch) {
|
|
@@ -283,22 +282,22 @@ const assertResponsesToolsSupported = (modelId, tools) => {
|
|
|
283
282
|
if (type === "computer" && !currentCapabilities?.computerUse) {
|
|
284
283
|
throw new UnsupportedFeatureError(`Provider "openai" model "${modelId}" does not support the Responses computer tool.`);
|
|
285
284
|
}
|
|
286
|
-
if (type === "shell" && !
|
|
285
|
+
if (type === "shell" && !currentCapabilities?.shell) {
|
|
287
286
|
throw new UnsupportedFeatureError(`Provider "openai" model "${modelId}" does not support the Responses ${type} tool.`);
|
|
288
287
|
}
|
|
289
|
-
if (type === "apply_patch" && !
|
|
288
|
+
if (type === "apply_patch" && !currentCapabilities?.applyPatch) {
|
|
290
289
|
throw new UnsupportedFeatureError(`Provider "openai" model "${modelId}" does not support the Responses ${type} tool.`);
|
|
291
290
|
}
|
|
292
291
|
if (type === "skill" && !currentCapabilities?.skills) {
|
|
293
292
|
throw new UnsupportedFeatureError(`Provider "openai" model "${modelId}" does not support the Responses skills tool.`);
|
|
294
293
|
}
|
|
295
|
-
if (type === "programmatic_tool_calling" && !
|
|
294
|
+
if (type === "programmatic_tool_calling" && !currentCapabilities?.programmaticToolCalling) {
|
|
296
295
|
throw new UnsupportedFeatureError(`Provider "openai" model "${modelId}" does not support Programmatic Tool Calling.`);
|
|
297
296
|
}
|
|
298
297
|
}
|
|
299
298
|
};
|
|
300
|
-
const assertOpenAIResponsesOptionsSupported = (modelId, options) => {
|
|
301
|
-
if (options.multi_agent?.enabled && !
|
|
299
|
+
const assertOpenAIResponsesOptionsSupported = (modelId, options, currentCapabilities) => {
|
|
300
|
+
if (options.multi_agent?.enabled && !currentCapabilities?.multiAgent) {
|
|
302
301
|
throw new UnsupportedFeatureError(`Provider "openai" model "${modelId}" does not support Multi-agent.`);
|
|
303
302
|
}
|
|
304
303
|
};
|
|
@@ -934,7 +933,7 @@ const addTokenUsage = (left, right) => {
|
|
|
934
933
|
return right;
|
|
935
934
|
if (!right)
|
|
936
935
|
return left;
|
|
937
|
-
const sum = (a, b) => a === undefined
|
|
936
|
+
const sum = (a, b) => a === undefined || b === undefined ? undefined : a + b;
|
|
938
937
|
return {
|
|
939
938
|
inputTokens: sum(left.inputTokens, right.inputTokens),
|
|
940
939
|
cachedInputTokens: sum(left.cachedInputTokens, right.cachedInputTokens),
|
|
@@ -1382,7 +1381,8 @@ const streamGenerateResult = async function* (result) {
|
|
|
1382
1381
|
type: "finish",
|
|
1383
1382
|
finishReason: result.finishReason,
|
|
1384
1383
|
providerFinishReason: result.providerFinishReason,
|
|
1385
|
-
usage: result.usage
|
|
1384
|
+
usage: result.usage,
|
|
1385
|
+
providerRequestCount: result.providerRequestCount
|
|
1386
1386
|
};
|
|
1387
1387
|
};
|
|
1388
1388
|
const extractSources = (value) => {
|
|
@@ -1419,45 +1419,43 @@ class OpenAILanguageModel {
|
|
|
1419
1419
|
responseLimits;
|
|
1420
1420
|
provider = "openai";
|
|
1421
1421
|
capabilities;
|
|
1422
|
-
constructor(modelId, apiKey, baseURL, fetcher, responseLimits) {
|
|
1422
|
+
constructor(modelId, apiKey, baseURL, fetcher, responseLimits, capabilityOptions) {
|
|
1423
1423
|
this.modelId = modelId;
|
|
1424
1424
|
this.apiKey = apiKey;
|
|
1425
1425
|
this.baseURL = baseURL;
|
|
1426
1426
|
this.fetcher = fetcher;
|
|
1427
1427
|
this.responseLimits = responseLimits;
|
|
1428
|
-
|
|
1428
|
+
const base = modelCapabilities(modelId, capabilityOptions.unknownModelCapabilities);
|
|
1429
|
+
const override = (capabilityOptions.modelCapabilities && Object.hasOwn(capabilityOptions.modelCapabilities, modelId) ? capabilityOptions.modelCapabilities[modelId] : undefined);
|
|
1430
|
+
this.capabilities = { ...base, ...override,
|
|
1431
|
+
agentCapabilities: { ...base.agentCapabilities, ...override?.agentCapabilities }, toolHistory: "json" };
|
|
1429
1432
|
}
|
|
1430
1433
|
usesResponsesAPI(input, options) {
|
|
1431
|
-
if (
|
|
1432
|
-
|
|
1433
|
-
const effort = input.reasoning?.effort ?? raw.reasoning?.effort ?? raw.reasoning_effort;
|
|
1434
|
-
if (effort !== undefined && !["none", "low", "medium", "high", "xhigh", "max"].includes(String(effort))) {
|
|
1435
|
-
throw new UnsupportedFeatureError(`GPT-6 Sol/Luna does not support reasoning effort "${effort}".`);
|
|
1436
|
-
}
|
|
1437
|
-
if (effort !== "none") {
|
|
1438
|
-
if (input.temperature !== undefined || raw.temperature !== undefined || raw.top_p !== undefined || raw.top_logprobs !== undefined ||
|
|
1439
|
-
(options.apiMode === "chat" && raw.logprobs !== undefined) || raw.include?.includes("message.output_text.logprobs")) {
|
|
1440
|
-
throw new UnsupportedFeatureError('GPT-6 Sol/Luna sampling and logprobs controls require reasoning effort "none".');
|
|
1441
|
-
}
|
|
1442
|
-
if (options.apiMode === "chat" && Object.keys(input.tools ?? {}).length) {
|
|
1443
|
-
throw new UnsupportedFeatureError('GPT-6 Sol/Luna tool calling with reasoning requires the Responses API; Chat Completions requires effort "none".');
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1434
|
+
if (!this.capabilities.tools && (Object.keys(input.tools ?? {}).length || input.messages.some(message => message.parts.some(part => part.type === "tool-call" || part.type === "tool-result")))) {
|
|
1435
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared tool support.`);
|
|
1446
1436
|
}
|
|
1447
|
-
if (
|
|
1448
|
-
|
|
1449
|
-
const effort = input.reasoning?.effort ?? raw.reasoning?.effort ?? raw.reasoning_effort;
|
|
1450
|
-
if (effort !== undefined && !["low", "medium", "high", "xhigh", "max"].includes(String(effort))) {
|
|
1451
|
-
throw new UnsupportedFeatureError(`GPT-6 Astra does not support reasoning effort "${effort}".`);
|
|
1452
|
-
}
|
|
1453
|
-
if (input.temperature !== undefined || raw.temperature !== undefined || raw.top_p !== undefined || raw.top_logprobs !== undefined ||
|
|
1454
|
-
(options.apiMode === "chat" && raw.logprobs !== undefined) || raw.include?.includes("message.output_text.logprobs")) {
|
|
1455
|
-
throw new UnsupportedFeatureError("GPT-6 Astra does not support the requested sampling or logprobs controls.");
|
|
1456
|
-
}
|
|
1457
|
-
if (options.apiMode === "chat" && Object.keys(input.tools ?? {}).length) {
|
|
1458
|
-
throw new UnsupportedFeatureError("GPT-6 Astra tool calling requires the Responses API.");
|
|
1459
|
-
}
|
|
1437
|
+
if (!this.capabilities.vision && input.messages.some(message => message.parts.some(part => part.type === "image"))) {
|
|
1438
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared vision support.`);
|
|
1460
1439
|
}
|
|
1440
|
+
const rawFormat = options.bodyOptions.response_format;
|
|
1441
|
+
const rawText = options.bodyOptions.text;
|
|
1442
|
+
const formatTypes = [rawFormat?.type, rawText?.format?.type];
|
|
1443
|
+
if (!this.capabilities.structuredOutput && (input.structuredOutput?.mode === "native" || formatTypes.includes("json_schema"))) {
|
|
1444
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared native structured output support.`);
|
|
1445
|
+
}
|
|
1446
|
+
if (!this.capabilities.jsonMode && formatTypes.includes("json_object")) {
|
|
1447
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared JSON mode support.`);
|
|
1448
|
+
}
|
|
1449
|
+
if (!this.capabilities.parallelToolCalls && options.bodyOptions.parallel_tool_calls === true) {
|
|
1450
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared parallel tool calling support.`);
|
|
1451
|
+
}
|
|
1452
|
+
if (!this.capabilities.reasoning && (input.reasoning || options.bodyOptions.reasoning || options.bodyOptions.reasoning_effort)) {
|
|
1453
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared reasoning support.`);
|
|
1454
|
+
}
|
|
1455
|
+
if (!this.capabilities.toolChoice && (input.toolChoice !== undefined || options.bodyOptions.tool_choice !== undefined)) {
|
|
1456
|
+
throw new UnsupportedFeatureError(`OpenAI model "${this.modelId}" has no declared tool choice support.`);
|
|
1457
|
+
}
|
|
1458
|
+
assertOpenAIModelRequestSupported(this.modelId, input, options);
|
|
1461
1459
|
const requiresResponses = hasResponsesOnlyTools(input.tools) || options.multiAgentEnabled;
|
|
1462
1460
|
if (options.apiMode === "chat") {
|
|
1463
1461
|
if (requiresResponses) {
|
|
@@ -1465,12 +1463,12 @@ class OpenAILanguageModel {
|
|
|
1465
1463
|
}
|
|
1466
1464
|
return false;
|
|
1467
1465
|
}
|
|
1468
|
-
return options.apiMode === "responses" || requiresResponses ||
|
|
1466
|
+
return options.apiMode === "responses" || requiresResponses || resolveOpenAIModelProfile(this.modelId).defaultApi === "responses";
|
|
1469
1467
|
}
|
|
1470
1468
|
async generateViaResponses(input, signal, options) {
|
|
1471
1469
|
const responseBodyOptions = openAIResponsesBodyOptions(options.bodyOptions, this.modelId);
|
|
1472
|
-
assertResponsesToolsSupported(this.modelId, input.tools);
|
|
1473
|
-
assertOpenAIResponsesOptionsSupported(this.modelId, responseBodyOptions);
|
|
1470
|
+
assertResponsesToolsSupported(this.modelId, input.tools, this.capabilities.agentCapabilities);
|
|
1471
|
+
assertOpenAIResponsesOptionsSupported(this.modelId, responseBodyOptions, this.capabilities.agentCapabilities);
|
|
1474
1472
|
const previousResponse = responseBodyOptions.store === false ? undefined : getProviderResponseId(input.messages);
|
|
1475
1473
|
const messages = previousResponse && previousResponse.index < input.messages.length - 1
|
|
1476
1474
|
? input.messages.slice(previousResponse.index + 1)
|
|
@@ -1478,75 +1476,119 @@ class OpenAILanguageModel {
|
|
|
1478
1476
|
let nextPreviousResponseId = previousResponse?.responseId;
|
|
1479
1477
|
let nextInput = messages.length ? toResponsesInput(messages, input.toolResultFormat, input.messages) : [];
|
|
1480
1478
|
let accumulatedUsage;
|
|
1479
|
+
const ptc = hasProgrammaticToolCalling(input.tools);
|
|
1480
|
+
const requestLimit = Math.min(input.maxProviderRequests ?? 8, 8);
|
|
1481
|
+
if (!Number.isSafeInteger(requestLimit) || requestLimit < 1)
|
|
1482
|
+
throw new ConfigurationError("maxProviderRequests must be a positive integer.");
|
|
1483
|
+
let providerRequestCount = 0;
|
|
1484
|
+
let usageComplete = true;
|
|
1485
|
+
const failure = (diagnosticCode, cause) => new ProviderToolCallError({
|
|
1486
|
+
provider: "openai", transport: "responses", diagnosticCode,
|
|
1487
|
+
reason: cause instanceof ProviderToolCallError ? cause.reason : "response_failed",
|
|
1488
|
+
retryable: false, effectsPossible: providerRequestCount > 0,
|
|
1489
|
+
confirmedUsage: accumulatedUsage, usageComplete, providerRequestCount
|
|
1490
|
+
});
|
|
1481
1491
|
let statelessInternalOutputs = [];
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
}))
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1492
|
+
try {
|
|
1493
|
+
for (let continuation = 0; continuation < requestLimit; continuation += 1) {
|
|
1494
|
+
const remainingOutputTokens = input.maxTokens === undefined ? undefined
|
|
1495
|
+
: input.maxTokens - (accumulatedUsage?.outputTokens ?? 0);
|
|
1496
|
+
if (ptc && remainingOutputTokens !== undefined && remainingOutputTokens < 1)
|
|
1497
|
+
throw failure("OPENAI_PTC_OUTPUT_LIMIT");
|
|
1498
|
+
if (ptc) {
|
|
1499
|
+
signal?.throwIfAborted();
|
|
1500
|
+
providerRequestCount++;
|
|
1501
|
+
usageComplete = false;
|
|
1502
|
+
}
|
|
1503
|
+
const response = await withResponseRetry(() => this.fetcher(`${this.baseURL}/responses`, {
|
|
1504
|
+
method: "POST",
|
|
1505
|
+
headers: options.headers,
|
|
1506
|
+
signal,
|
|
1507
|
+
body: JSON.stringify({
|
|
1508
|
+
...responseBodyOptions,
|
|
1509
|
+
model: this.modelId,
|
|
1510
|
+
...(nextPreviousResponseId ? { previous_response_id: nextPreviousResponseId } : {}),
|
|
1511
|
+
...(nextInput.length ? { input: nextInput } : {}),
|
|
1512
|
+
tools: mapResponsesTools(input.tools),
|
|
1513
|
+
...(input.toolChoice ? { tool_choice: mapResponsesToolChoice(input.toolChoice) } : {}),
|
|
1514
|
+
text: mapResponsesStructuredOutput(input) ?? responseBodyOptions.text,
|
|
1515
|
+
temperature: input.temperature,
|
|
1516
|
+
max_output_tokens: ptc ? remainingOutputTokens : input.maxTokens,
|
|
1517
|
+
...mapResponsesReasoning(input, responseBodyOptions.reasoning)
|
|
1518
|
+
})
|
|
1519
|
+
}), { ...input, abortSignal: signal, ...(ptc ? { maxRetries: 0 } : {}) }, "OpenAI");
|
|
1520
|
+
const json = await parseJson(response);
|
|
1521
|
+
const reportedUsage = mapResponsesUsage(json.usage);
|
|
1522
|
+
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 || Object.values(reportedUsage).some(value => value !== undefined && (!Number.isSafeInteger(value) || value < 0)))) {
|
|
1523
|
+
throw failure("OPENAI_PTC_USAGE_UNKNOWN");
|
|
1524
|
+
}
|
|
1525
|
+
const nextUsage = addTokenUsage(accumulatedUsage, reportedUsage);
|
|
1526
|
+
if (ptc && Object.values(nextUsage ?? {}).some(value => value !== undefined && !Number.isSafeInteger(value)))
|
|
1527
|
+
throw failure("OPENAI_PTC_USAGE_UNKNOWN");
|
|
1528
|
+
accumulatedUsage = nextUsage;
|
|
1529
|
+
if (ptc)
|
|
1530
|
+
usageComplete = true;
|
|
1531
|
+
if (ptc && input.maxTokens !== undefined && accumulatedUsage.outputTokens > input.maxTokens)
|
|
1532
|
+
throw failure("OPENAI_PTC_OUTPUT_LIMIT");
|
|
1533
|
+
const assistantMessage = parseResponsesAssistantMessage(json, options.multiAgentEnabled, localResponsesTools(input.tools), this.responseLimits.toolCallArgumentChars);
|
|
1534
|
+
const currentOutput = Array.isArray(json.output)
|
|
1535
|
+
? json.output
|
|
1536
|
+
: [];
|
|
1537
|
+
const completeStatelessOutput = [...statelessInternalOutputs, ...currentOutput];
|
|
1538
|
+
if (responseBodyOptions.store === false && completeStatelessOutput.length) {
|
|
1539
|
+
assistantMessage.parts = assistantMessage.parts.filter((part) => part.type !== "provider-data" ||
|
|
1540
|
+
part.provider !== "openai" ||
|
|
1541
|
+
!part.data ||
|
|
1542
|
+
typeof part.data !== "object" ||
|
|
1543
|
+
part.data.type !== "responses_output");
|
|
1544
|
+
assistantMessage.parts.push(providerDataPart("openai", {
|
|
1545
|
+
type: "responses_output",
|
|
1546
|
+
items: completeStatelessOutput
|
|
1547
|
+
}));
|
|
1548
|
+
}
|
|
1549
|
+
const hasToolCalls = assistantMessage.parts.some((part) => part.type === "tool-call");
|
|
1550
|
+
const hasRefusal = (json.output ?? []).some((item) => item?.type === "message" &&
|
|
1551
|
+
(item.content ?? []).some((content) => content?.type === "refusal"));
|
|
1552
|
+
const hasFinalMessage = (json.output ?? []).some((item) => item?.type === "message" &&
|
|
1553
|
+
(!options.multiAgentEnabled || (item.agent?.agent_name === "/root" && item.phase === "final_answer")));
|
|
1554
|
+
const shouldContinueProgram = hasProgrammaticToolCalling(input.tools) &&
|
|
1555
|
+
json.status === "completed" &&
|
|
1556
|
+
!hasToolCalls &&
|
|
1557
|
+
!hasFinalMessage &&
|
|
1558
|
+
(json.output ?? []).some((item) => item?.type === "program" || item?.type === "program_output");
|
|
1559
|
+
if (!shouldContinueProgram) {
|
|
1560
|
+
return {
|
|
1561
|
+
messages: [assistantMessage],
|
|
1562
|
+
text: extractMessageText(assistantMessage),
|
|
1563
|
+
audio: extractAudioOutputs(assistantMessage),
|
|
1564
|
+
images: extractResponsesImageOutputs(json, responsesImageGenerationConfig(input.tools)?.outputFormat),
|
|
1565
|
+
finishReason: normalizeResponsesFinishReason(json.status, hasToolCalls, hasRefusal),
|
|
1566
|
+
providerFinishReason: json.status,
|
|
1567
|
+
usage: accumulatedUsage,
|
|
1568
|
+
...(ptc ? { providerRequestCount } : {}),
|
|
1569
|
+
rawResponse: json
|
|
1570
|
+
};
|
|
1571
|
+
}
|
|
1572
|
+
if (responseBodyOptions.store === false) {
|
|
1573
|
+
statelessInternalOutputs = completeStatelessOutput;
|
|
1574
|
+
nextInput = [...nextInput, ...currentOutput];
|
|
1575
|
+
}
|
|
1576
|
+
else {
|
|
1577
|
+
nextPreviousResponseId = json.id;
|
|
1578
|
+
nextInput = [];
|
|
1579
|
+
}
|
|
1547
1580
|
}
|
|
1581
|
+
throw failure("OPENAI_PTC_REQUEST_LIMIT");
|
|
1582
|
+
}
|
|
1583
|
+
catch (error) {
|
|
1584
|
+
if (!ptc)
|
|
1585
|
+
throw error;
|
|
1586
|
+
if (error instanceof ProviderToolCallError && error.providerRequestCount !== undefined)
|
|
1587
|
+
throw error;
|
|
1588
|
+
// Never replay a dispatched program; the receipt distinguishes a confirmed
|
|
1589
|
+
// prefix from a failed/uncertain request and intentionally omits raw payloads.
|
|
1590
|
+
throw failure(error instanceof ProviderToolCallError ? error.diagnosticCode : "OPENAI_PTC_REQUEST_FAILED", error);
|
|
1548
1591
|
}
|
|
1549
|
-
throw new ProviderHTTPError("OpenAI Programmatic Tool Calling exceeded 8 internal continuations.", 500);
|
|
1550
1592
|
}
|
|
1551
1593
|
async generate(input) {
|
|
1552
1594
|
const { signal, cleanup } = getRequestOptions(input);
|
|
@@ -1565,7 +1607,7 @@ class OpenAILanguageModel {
|
|
|
1565
1607
|
messages: mapMessages(input.messages, input.toolResultFormat),
|
|
1566
1608
|
tools: mapTools(input.tools),
|
|
1567
1609
|
...(input.toolChoice ? { tool_choice: mapToolChoice(input.toolChoice) } : {}),
|
|
1568
|
-
response_format: mapStructuredOutput(input),
|
|
1610
|
+
response_format: mapStructuredOutput(input) ?? options.bodyOptions.response_format,
|
|
1569
1611
|
temperature: input.temperature,
|
|
1570
1612
|
...(input.reasoning ? {} : { max_tokens: input.maxTokens }),
|
|
1571
1613
|
...mapChatReasoning(input),
|
|
@@ -1594,19 +1636,18 @@ class OpenAILanguageModel {
|
|
|
1594
1636
|
const options = resolveOpenAILanguageRequestOptions(input.providerOptions, this.apiKey);
|
|
1595
1637
|
if (this.usesResponsesAPI(input, options)) {
|
|
1596
1638
|
const responseBodyOptions = openAIResponsesBodyOptions(options.bodyOptions, this.modelId);
|
|
1597
|
-
assertResponsesToolsSupported(this.modelId, input.tools);
|
|
1598
|
-
assertOpenAIResponsesOptionsSupported(this.modelId, responseBodyOptions);
|
|
1639
|
+
assertResponsesToolsSupported(this.modelId, input.tools, this.capabilities.agentCapabilities);
|
|
1640
|
+
assertOpenAIResponsesOptionsSupported(this.modelId, responseBodyOptions, this.capabilities.agentCapabilities);
|
|
1599
1641
|
const { signal, cleanup } = getRequestOptions(input);
|
|
1600
1642
|
if (hasProgrammaticToolCalling(input.tools)) {
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
})();
|
|
1643
|
+
try {
|
|
1644
|
+
const result = await this.generateViaResponses(input, signal, options);
|
|
1645
|
+
return streamGenerateResult(result);
|
|
1646
|
+
}
|
|
1647
|
+
finally {
|
|
1648
|
+
// PTC is fully materialized before an iterator is returned.
|
|
1649
|
+
cleanup();
|
|
1650
|
+
}
|
|
1610
1651
|
}
|
|
1611
1652
|
const previousResponse = responseBodyOptions.store === false ? undefined : getProviderResponseId(input.messages);
|
|
1612
1653
|
const messages = previousResponse && previousResponse.index < input.messages.length - 1
|
|
@@ -1623,7 +1664,7 @@ class OpenAILanguageModel {
|
|
|
1623
1664
|
...(messages.length ? { input: toResponsesInput(messages, input.toolResultFormat, input.messages) } : {}),
|
|
1624
1665
|
tools: mapResponsesTools(input.tools),
|
|
1625
1666
|
...(input.toolChoice ? { tool_choice: mapResponsesToolChoice(input.toolChoice) } : {}),
|
|
1626
|
-
text: mapResponsesStructuredOutput(input),
|
|
1667
|
+
text: mapResponsesStructuredOutput(input) ?? responseBodyOptions.text,
|
|
1627
1668
|
temperature: input.temperature,
|
|
1628
1669
|
max_output_tokens: input.maxTokens,
|
|
1629
1670
|
...mapResponsesReasoning(input, responseBodyOptions.reasoning),
|
|
@@ -1652,7 +1693,7 @@ class OpenAILanguageModel {
|
|
|
1652
1693
|
messages: mapMessages(input.messages, input.toolResultFormat),
|
|
1653
1694
|
tools: mapTools(input.tools),
|
|
1654
1695
|
...(input.toolChoice ? { tool_choice: mapToolChoice(input.toolChoice) } : {}),
|
|
1655
|
-
response_format: mapStructuredOutput(input),
|
|
1696
|
+
response_format: mapStructuredOutput(input) ?? options.bodyOptions.response_format,
|
|
1656
1697
|
temperature: input.temperature,
|
|
1657
1698
|
...(input.reasoning ? {} : { max_tokens: input.maxTokens }),
|
|
1658
1699
|
...mapChatReasoning(input),
|
|
@@ -1751,7 +1792,7 @@ export const createOpenAI = (options = {}) => {
|
|
|
1751
1792
|
languageModel: (modelId) => {
|
|
1752
1793
|
if (modelId.startsWith("gpt-live-"))
|
|
1753
1794
|
throw new UnsupportedFeatureError("GPT-Live is a voice model; use openai.realtimeModel(modelId).");
|
|
1754
|
-
return new OpenAILanguageModel(modelId, apiKey, baseURL, fetcher, responseLimits);
|
|
1795
|
+
return new OpenAILanguageModel(modelId, apiKey, baseURL, fetcher, responseLimits, options);
|
|
1755
1796
|
},
|
|
1756
1797
|
embeddingModel: (modelId) => new OpenAIEmbeddingModel(modelId, apiKey, baseURL, fetcher),
|
|
1757
1798
|
transcriptionModel: (modelId) => new OpenAITranscriptionModel(modelId, apiKey, baseURL, fetcher, responseLimits),
|