@core-ai/openai 0.24.0 → 0.25.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.
@@ -2,8 +2,10 @@
2
2
  import {
3
3
  getRegisteredModelCapabilities,
4
4
  MULTIMODAL_INPUT_MODALITIES,
5
+ SUPPORTED_TOOL_SCHEMA_STRICTNESS,
5
6
  stripModelDateSuffix,
6
7
  TEXT_ONLY_MODALITIES,
8
+ UNSUPPORTED_TOOL_SCHEMA_STRICTNESS,
7
9
  UNKNOWN_MODEL
8
10
  } from "@core-ai/core-ai";
9
11
  var STANDARD_EFFORTS = [
@@ -37,7 +39,8 @@ function createCapabilities({
37
39
  supportedEfforts,
38
40
  restrictsSamplingParams,
39
41
  maxTokensParameter = "max_completion_tokens",
40
- modalities = MULTIMODAL_INPUT_MODALITIES
42
+ modalities = MULTIMODAL_INPUT_MODALITIES,
43
+ strictToolSchemas = SUPPORTED_TOOL_SCHEMA_STRICTNESS
41
44
  }) {
42
45
  return {
43
46
  reasoning: {
@@ -47,6 +50,9 @@ function createCapabilities({
47
50
  supportedToolChoices: ["auto", "none", "required", "tool"]
48
51
  },
49
52
  modalities,
53
+ tools: {
54
+ strictSchemas: strictToolSchemas
55
+ },
50
56
  chatCompletions: {
51
57
  maxTokensParameter
52
58
  }
@@ -83,7 +89,8 @@ var GPT_5_HIGH_REASONING_CAPABILITIES = createCapabilities({
83
89
  });
84
90
  function createNoReasoningCapabilities({
85
91
  maxTokensParameter,
86
- modalities = MULTIMODAL_INPUT_MODALITIES
92
+ modalities = MULTIMODAL_INPUT_MODALITIES,
93
+ strictToolSchemas = SUPPORTED_TOOL_SCHEMA_STRICTNESS
87
94
  }) {
88
95
  return {
89
96
  reasoning: {
@@ -93,6 +100,9 @@ function createNoReasoningCapabilities({
93
100
  supportedToolChoices: ["auto", "none", "required", "tool"]
94
101
  },
95
102
  modalities,
103
+ tools: {
104
+ strictSchemas: strictToolSchemas
105
+ },
96
106
  chatCompletions: {
97
107
  maxTokensParameter
98
108
  }
@@ -101,21 +111,19 @@ function createNoReasoningCapabilities({
101
111
  var NO_REASONING_CAPABILITIES = createNoReasoningCapabilities({
102
112
  maxTokensParameter: "max_tokens"
103
113
  });
104
- var NO_REASONING_TEXT_ONLY_CAPABILITIES = createNoReasoningCapabilities({
105
- maxTokensParameter: "max_tokens",
106
- modalities: TEXT_ONLY_MODALITIES
107
- });
108
114
  var NO_REASONING_EFFORT_TEXT_ONLY_CAPABILITIES = createNoReasoningCapabilities({
109
115
  maxTokensParameter: "max_completion_tokens",
110
116
  modalities: TEXT_ONLY_MODALITIES
111
117
  });
112
118
  var AUDIO_CAPABILITIES = createNoReasoningCapabilities({
113
119
  maxTokensParameter: "max_completion_tokens",
114
- modalities: OPENAI_AUDIO_INPUT_MODALITIES
120
+ modalities: OPENAI_AUDIO_INPUT_MODALITIES,
121
+ strictToolSchemas: UNSUPPORTED_TOOL_SCHEMA_STRICTNESS
115
122
  });
116
123
  var GPT_4O_AUDIO_CAPABILITIES = createNoReasoningCapabilities({
117
124
  maxTokensParameter: "max_tokens",
118
- modalities: OPENAI_AUDIO_INPUT_MODALITIES
125
+ modalities: OPENAI_AUDIO_INPUT_MODALITIES,
126
+ strictToolSchemas: UNSUPPORTED_TOOL_SCHEMA_STRICTNESS
119
127
  });
120
128
  var O_SERIES_MAX_REASONING_CAPABILITIES = createCapabilities({
121
129
  supportedEfforts: MAX_EFFORTS,
@@ -126,7 +134,17 @@ var O_SERIES_TEXT_ONLY_CAPABILITIES = createCapabilities({
126
134
  restrictsSamplingParams: false,
127
135
  modalities: TEXT_ONLY_MODALITIES
128
136
  });
137
+ var LEGACY_NO_STRICT_TOOLS_CAPABILITIES = createNoReasoningCapabilities({
138
+ maxTokensParameter: "max_tokens",
139
+ strictToolSchemas: UNSUPPORTED_TOOL_SCHEMA_STRICTNESS
140
+ });
141
+ var LEGACY_NO_STRICT_TOOLS_TEXT_ONLY_CAPABILITIES = createNoReasoningCapabilities({
142
+ maxTokensParameter: "max_tokens",
143
+ modalities: TEXT_ONLY_MODALITIES,
144
+ strictToolSchemas: UNSUPPORTED_TOOL_SCHEMA_STRICTNESS
145
+ });
129
146
  var OPENAI_MODEL_CAPABILITIES = {
147
+ "gpt-4o-2024-05-13": LEGACY_NO_STRICT_TOOLS_CAPABILITIES,
130
148
  "gpt-5.6-sol": GPT_5_MAX_REASONING_CAPABILITIES,
131
149
  "gpt-5.6-terra": SAMPLING_RESTRICTED_STANDARD_CAPABILITIES,
132
150
  "gpt-5.6-luna": GPT_5_MINIMAL_REASONING_CAPABILITIES,
@@ -160,8 +178,8 @@ var OPENAI_MODEL_CAPABILITIES = {
160
178
  "gpt-4.1-nano": NO_REASONING_CAPABILITIES,
161
179
  "gpt-4o": NO_REASONING_CAPABILITIES,
162
180
  "gpt-4o-mini": NO_REASONING_CAPABILITIES,
163
- "gpt-4-turbo": NO_REASONING_CAPABILITIES,
164
- "gpt-3.5-turbo": NO_REASONING_TEXT_ONLY_CAPABILITIES,
181
+ "gpt-4-turbo": LEGACY_NO_STRICT_TOOLS_CAPABILITIES,
182
+ "gpt-3.5-turbo": LEGACY_NO_STRICT_TOOLS_TEXT_ONLY_CAPABILITIES,
165
183
  "gpt-audio-1.5": AUDIO_CAPABILITIES,
166
184
  "gpt-audio": AUDIO_CAPABILITIES,
167
185
  "gpt-audio-mini": AUDIO_CAPABILITIES,
@@ -177,7 +195,14 @@ var OPENAI_REASONING_EFFORT_MAP = {
177
195
  max: "xhigh"
178
196
  };
179
197
  function getOpenAIModelCapabilities(modelId) {
180
- return getRegisteredModelCapabilities(OPENAI_MODEL_CAPABILITIES, modelId) ?? UNKNOWN_MODEL_CAPABILITIES;
198
+ return getRegisteredModelCapabilities(
199
+ OPENAI_MODEL_CAPABILITIES,
200
+ getFineTuneBaseModelId(modelId) ?? modelId
201
+ ) ?? UNKNOWN_MODEL_CAPABILITIES;
202
+ }
203
+ var FINE_TUNE_MODEL_ID_PATTERN = /^ft:([^:]+):/;
204
+ function getFineTuneBaseModelId(modelId) {
205
+ return FINE_TUNE_MODEL_ID_PATTERN.exec(modelId)?.[1];
181
206
  }
182
207
  function toOpenAIResponsesCapabilities(capabilities) {
183
208
  if (!capabilities.modalities.input.includes("audio")) {
@@ -285,17 +310,37 @@ import {
285
310
  } from "@core-ai/core-ai";
286
311
 
287
312
  // src/shared/tools.ts
288
- import { zodSchemaToJsonSchema } from "@core-ai/core-ai";
289
- function convertTools(tools) {
313
+ import {
314
+ normalizeStrictJsonSchema,
315
+ validateToolSchemaStrictness,
316
+ zodSchemaToJsonSchema
317
+ } from "@core-ai/core-ai";
318
+ function convertTools(tools, options) {
319
+ validateToolSchemaStrictness({ tools, ...options });
290
320
  return Object.values(tools).map((tool) => ({
291
321
  type: "function",
292
322
  function: {
293
323
  name: tool.name,
294
324
  description: tool.description,
295
- parameters: zodSchemaToJsonSchema(tool.parameters)
325
+ parameters: convertToolParameters(tool),
326
+ ...tool.strict === true ? { strict: true } : {}
296
327
  }
297
328
  }));
298
329
  }
330
+ function convertResponseTools(tools, options) {
331
+ validateToolSchemaStrictness({ tools, ...options });
332
+ return Object.values(tools).map((tool) => ({
333
+ type: "function",
334
+ name: tool.name,
335
+ description: tool.description,
336
+ parameters: convertToolParameters(tool),
337
+ strict: tool.strict === true
338
+ }));
339
+ }
340
+ function convertToolParameters(tool) {
341
+ const schema = zodSchemaToJsonSchema(tool.parameters);
342
+ return tool.strict === true ? normalizeStrictJsonSchema(schema) : schema;
343
+ }
299
344
  function convertToolChoice(choice) {
300
345
  if (typeof choice === "string") {
301
346
  return choice;
@@ -529,7 +574,13 @@ function createRequestBase(modelId, options, adapterOptions) {
529
574
  return {
530
575
  model: modelId,
531
576
  messages: convertMessages(options.messages, adapterOptions),
532
- ...options.tools && Object.keys(options.tools).length > 0 ? { tools: convertTools(options.tools) } : {},
577
+ ...options.tools && Object.keys(options.tools).length > 0 ? {
578
+ tools: convertTools(options.tools, {
579
+ capabilities: adapterOptions.capabilities,
580
+ modelId,
581
+ providerId: adapterOptions.providerId
582
+ })
583
+ } : {},
533
584
  ...options.toolChoice ? { tool_choice: convertToolChoice(options.toolChoice) } : {},
534
585
  ...reasoningFields,
535
586
  ...mapSamplingToRequestFields(modelId, options, adapterOptions)
@@ -1411,9 +1462,11 @@ import {
1411
1462
  } from "@core-ai/core-ai";
1412
1463
  var DEFAULT_PROVIDER_ID = "openai";
1413
1464
  function resolveAdapterOptions(modelId, adapterOptions) {
1414
- const capabilities = adapterOptions.capabilities ?? getOpenAIModelCapabilities(modelId);
1415
1465
  return {
1416
- capabilities: toOpenAIResponsesCapabilities(capabilities),
1466
+ // Callers that pass capabilities (the provider factory) have already
1467
+ // applied the Responses-specific restrictions; only the fallback
1468
+ // lookup applies them here.
1469
+ capabilities: adapterOptions.capabilities ?? toOpenAIResponsesCapabilities(getOpenAIModelCapabilities(modelId)),
1417
1470
  // Also the ownership key for encrypted reasoning metadata — Azure
1418
1471
  // (`azure-openai`) must not share the `openai` namespace.
1419
1472
  providerId: adapterOptions.providerId ?? DEFAULT_PROVIDER_ID
@@ -1603,7 +1656,13 @@ function createRequestBase2(modelId, options, { capabilities, providerId }) {
1603
1656
  includeReasoning: capabilities.reasoning.mode !== "unsupported",
1604
1657
  providerId
1605
1658
  }),
1606
- ...options.tools && Object.keys(options.tools).length > 0 ? { tools: convertResponseTools(options.tools) } : {},
1659
+ ...options.tools && Object.keys(options.tools).length > 0 ? {
1660
+ tools: convertResponseTools(options.tools, {
1661
+ capabilities,
1662
+ modelId,
1663
+ providerId
1664
+ })
1665
+ } : {},
1607
1666
  ...options.toolChoice ? { tool_choice: convertResponseToolChoice(options.toolChoice) } : {},
1608
1667
  ...mapReasoningToRequestFields2(options, capabilities),
1609
1668
  ...mapSamplingToRequestFields2(options)
@@ -1619,14 +1678,6 @@ function validateResponsesInputModalities(options) {
1619
1678
  throw error;
1620
1679
  }
1621
1680
  }
1622
- function convertResponseTools(tools) {
1623
- return convertTools(tools).map((tool) => ({
1624
- type: "function",
1625
- name: tool.function.name,
1626
- description: tool.function.description,
1627
- parameters: tool.function.parameters
1628
- }));
1629
- }
1630
1681
  function convertResponseToolChoice(choice) {
1631
1682
  const converted = convertToolChoice(choice);
1632
1683
  if (typeof converted === "string") {
@@ -2313,23 +2364,18 @@ function createOpenAIProvider(options, factoryOptions = {}) {
2313
2364
  });
2314
2365
  const providerId = factoryOptions.providerId ?? "openai";
2315
2366
  const compatibilityOptions = typeof factoryOptions.compatibility === "object" ? factoryOptions.compatibility : void 0;
2316
- const createResponsesModel = (modelId) => {
2317
- const capabilities = getRegisteredModelCapabilities2(
2318
- factoryOptions.modelCapabilities,
2319
- modelId
2320
- ) ?? getOpenAIModelCapabilities(modelId);
2321
- return createOpenAIChatModel(
2322
- client,
2323
- modelId,
2324
- toOpenAIResponsesCapabilities(capabilities),
2325
- providerId
2326
- );
2327
- };
2367
+ const resolveCapabilities = (modelId) => getRegisteredModelCapabilities2(
2368
+ factoryOptions.modelCapabilities,
2369
+ modelId
2370
+ ) ?? getOpenAIModelCapabilities(modelId);
2371
+ const createResponsesModel = (modelId) => createOpenAIChatModel(
2372
+ client,
2373
+ modelId,
2374
+ toOpenAIResponsesCapabilities(resolveCapabilities(modelId)),
2375
+ providerId
2376
+ );
2328
2377
  const createChatCompletionsModel = (modelId) => {
2329
- const capabilities = getRegisteredModelCapabilities2(
2330
- factoryOptions.modelCapabilities,
2331
- modelId
2332
- ) ?? getOpenAIModelCapabilities(modelId);
2378
+ const capabilities = resolveCapabilities(modelId);
2333
2379
  const compatibility = factoryOptions.compatibility ? {
2334
2380
  reasoning: typeof compatibilityOptions?.reasoning === "object" ? {
2335
2381
  ...compatibilityOptions.reasoning,
package/dist/compat.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  getOpenAIModelCapabilities,
5
5
  openaiCompatGenerateProviderOptionsSchema,
6
6
  openaiCompatProviderOptionsSchema
7
- } from "./chunk-SCXEGDFV.js";
7
+ } from "./chunk-IZPTRJP3.js";
8
8
 
9
9
  // src/compat/provider.ts
10
10
  import OpenAI from "openai";
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  openaiImageProviderOptionsSchema,
11
11
  openaiResponsesGenerateProviderOptionsSchema,
12
12
  openaiResponsesProviderOptionsSchema
13
- } from "./chunk-SCXEGDFV.js";
13
+ } from "./chunk-IZPTRJP3.js";
14
14
 
15
15
  // src/provider.ts
16
16
  function createOpenAI(options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/openai",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "OpenAI provider package for @core-ai/core-ai",
5
5
  "license": "MIT",
6
6
  "author": "Omnifact (https://omnifact.ai)",
@@ -50,7 +50,7 @@
50
50
  "test:watch": "vitest"
51
51
  },
52
52
  "dependencies": {
53
- "@core-ai/core-ai": "^0.24.0",
53
+ "@core-ai/core-ai": "^0.25.0",
54
54
  "openai": "^6.46.0"
55
55
  },
56
56
  "peerDependencies": {