@core-ai/openai 0.16.0 → 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.
@@ -1,6 +1,8 @@
1
1
  // src/model-capabilities.ts
2
2
  import {
3
- stripModelDateSuffix
3
+ getRegisteredModelCapabilities,
4
+ stripModelDateSuffix,
5
+ UNKNOWN_MODEL
4
6
  } from "@core-ai/core-ai";
5
7
  var STANDARD_EFFORTS = [
6
8
  "low",
@@ -28,9 +30,10 @@ var HIGH_EFFORT = ["high"];
28
30
  function createCapabilities(supportedEfforts, restrictsSamplingParams, maxTokensParameter = "max_completion_tokens") {
29
31
  return {
30
32
  reasoning: {
31
- supported: true,
33
+ mode: "optional",
32
34
  supportedEfforts,
33
- restrictsSamplingParams
35
+ restrictsSamplingParams,
36
+ supportedToolChoices: ["auto", "none", "required", "tool"]
34
37
  },
35
38
  chatCompletions: {
36
39
  maxTokensParameter
@@ -54,21 +57,28 @@ var GPT_5_MINIMAL_REASONING_CAPABILITIES = createCapabilities(
54
57
  );
55
58
  var GPT_5_PRO_REASONING_CAPABILITIES = createCapabilities(PRO_EFFORTS, true);
56
59
  var GPT_5_HIGH_REASONING_CAPABILITIES = createCapabilities(HIGH_EFFORT, true);
57
- var NO_REASONING_EFFORT_CAPABILITIES = {
58
- reasoning: {
59
- supported: false,
60
- supportedEfforts: [],
61
- restrictsSamplingParams: false
62
- },
63
- chatCompletions: {
64
- maxTokensParameter: "max_completion_tokens"
65
- }
66
- };
60
+ function createNoReasoningCapabilities(maxTokensParameter) {
61
+ return {
62
+ reasoning: {
63
+ mode: "unsupported",
64
+ supportedEfforts: [],
65
+ restrictsSamplingParams: false,
66
+ supportedToolChoices: ["auto", "none", "required", "tool"]
67
+ },
68
+ chatCompletions: {
69
+ maxTokensParameter
70
+ }
71
+ };
72
+ }
73
+ var NO_REASONING_CAPABILITIES = createNoReasoningCapabilities("max_tokens");
74
+ var NO_REASONING_EFFORT_CAPABILITIES = createNoReasoningCapabilities(
75
+ "max_completion_tokens"
76
+ );
67
77
  var O_SERIES_MAX_REASONING_CAPABILITIES = createCapabilities(
68
78
  MAX_EFFORTS,
69
79
  false
70
80
  );
71
- var MODEL_CAPABILITIES = {
81
+ var OPENAI_MODEL_CAPABILITIES = {
72
82
  "gpt-5.6-sol": GPT_5_MAX_REASONING_CAPABILITIES,
73
83
  "gpt-5.6-terra": SAMPLING_RESTRICTED_STANDARD_CAPABILITIES,
74
84
  "gpt-5.6-luna": GPT_5_MINIMAL_REASONING_CAPABILITIES,
@@ -96,7 +106,15 @@ var MODEL_CAPABILITIES = {
96
106
  "o3-mini": DEFAULT_CAPABILITIES,
97
107
  "o4-mini": DEFAULT_CAPABILITIES,
98
108
  o1: DEFAULT_CAPABILITIES,
99
- "o1-mini": NO_REASONING_EFFORT_CAPABILITIES
109
+ "o1-mini": NO_REASONING_EFFORT_CAPABILITIES,
110
+ "gpt-4.1": NO_REASONING_CAPABILITIES,
111
+ "gpt-4.1-mini": NO_REASONING_CAPABILITIES,
112
+ "gpt-4.1-nano": NO_REASONING_CAPABILITIES,
113
+ "gpt-4o": NO_REASONING_CAPABILITIES,
114
+ "gpt-4o-mini": NO_REASONING_CAPABILITIES,
115
+ "gpt-4-turbo": NO_REASONING_CAPABILITIES,
116
+ "gpt-3.5-turbo": NO_REASONING_CAPABILITIES,
117
+ [UNKNOWN_MODEL]: UNKNOWN_MODEL_CAPABILITIES
100
118
  };
101
119
  var OPENAI_REASONING_EFFORT_MAP = {
102
120
  minimal: "minimal",
@@ -106,11 +124,7 @@ var OPENAI_REASONING_EFFORT_MAP = {
106
124
  max: "xhigh"
107
125
  };
108
126
  function getOpenAIModelCapabilities(modelId) {
109
- const normalizedModelId = normalizeModelId(modelId);
110
- return MODEL_CAPABILITIES[normalizedModelId] ?? UNKNOWN_MODEL_CAPABILITIES;
111
- }
112
- function normalizeModelId(modelId) {
113
- return stripModelDateSuffix(modelId);
127
+ return getRegisteredModelCapabilities(OPENAI_MODEL_CAPABILITIES, modelId) ?? UNKNOWN_MODEL_CAPABILITIES;
114
128
  }
115
129
  function toOpenAIReasoningEffort(effort) {
116
130
  return OPENAI_REASONING_EFFORT_MAP[effort];
@@ -147,8 +161,8 @@ var openaiImageProviderOptionsSchema = z.object({
147
161
  style: z.enum(["vivid", "natural"]).optional(),
148
162
  user: z.string().optional()
149
163
  }).strict();
150
- function parseOpenAIProviderOptions(providerOptions, schema) {
151
- const rawOptions = providerOptions?.openai;
164
+ function parseOpenAIProviderOptions(providerOptions, key, schema) {
165
+ const rawOptions = providerOptions?.[key];
152
166
  if (rawOptions === void 0) {
153
167
  return void 0;
154
168
  }
@@ -157,24 +171,31 @@ function parseOpenAIProviderOptions(providerOptions, schema) {
157
171
  function parseOpenAIResponsesGenerateProviderOptions(providerOptions) {
158
172
  return parseOpenAIProviderOptions(
159
173
  providerOptions,
174
+ "openai",
160
175
  openaiResponsesGenerateProviderOptionsSchema
161
176
  );
162
177
  }
163
- function parseOpenAIChatGenerateProviderOptions(providerOptions) {
178
+ function parseOpenAIChatGenerateProviderOptions(providerOptions, config = {
179
+ key: "openai",
180
+ schema: openaiChatGenerateProviderOptionsSchema
181
+ }) {
164
182
  return parseOpenAIProviderOptions(
165
183
  providerOptions,
166
- openaiChatGenerateProviderOptionsSchema
184
+ config.key,
185
+ config.schema
167
186
  );
168
187
  }
169
188
  function parseOpenAIEmbedProviderOptions(providerOptions) {
170
189
  return parseOpenAIProviderOptions(
171
190
  providerOptions,
191
+ "openai",
172
192
  openaiEmbedProviderOptionsSchema
173
193
  );
174
194
  }
175
195
  function parseOpenAIImageProviderOptions(providerOptions) {
176
196
  return parseOpenAIProviderOptions(
177
197
  providerOptions,
198
+ "openai",
178
199
  openaiImageProviderOptionsSchema
179
200
  );
180
201
  }
@@ -186,7 +207,7 @@ var openaiCompatGenerateProviderOptionsSchema = openaiChatGenerateProviderOption
186
207
  import { createObjectStream, createChatStream } from "@core-ai/core-ai";
187
208
 
188
209
  // src/chat-completions/chat-adapter.ts
189
- import { clampReasoningEffort } from "@core-ai/core-ai";
210
+ import { clampReasoningEffort, getProviderMetadata } from "@core-ai/core-ai";
190
211
 
191
212
  // src/shared/tools.ts
192
213
  import { zodSchemaToJsonSchema } from "@core-ai/core-ai";
@@ -226,25 +247,40 @@ function safeParseJsonObject(json) {
226
247
  }
227
248
  }
228
249
  function validateOpenAIReasoningConfig(modelId, options) {
229
- if (!options.reasoning) {
230
- return;
231
- }
232
- const capabilities = getOpenAIModelCapabilities(modelId);
233
- if (!capabilities.reasoning.restrictsSamplingParams) {
250
+ validateReasoningConfig(
251
+ modelId,
252
+ options,
253
+ getOpenAIModelCapabilities(modelId),
254
+ "openai"
255
+ );
256
+ }
257
+ function validateReasoningConfig(modelId, options, capabilities, providerId) {
258
+ const reasoningEnabled = options.reasoning !== void 0 || capabilities.reasoning.mode === "always-on";
259
+ if (!reasoningEnabled) {
234
260
  return;
235
261
  }
236
- const restrictedSamplingParams = [
237
- { name: "temperature", value: options.temperature },
238
- { name: "topP", value: options.topP }
239
- ];
240
- for (const { name, value } of restrictedSamplingParams) {
241
- if (value === void 0) {
242
- continue;
262
+ if (capabilities.reasoning.restrictsSamplingParams) {
263
+ const restrictedSamplingParams = [
264
+ { name: "temperature", value: options.temperature },
265
+ { name: "topP", value: options.topP }
266
+ ];
267
+ for (const { name, value } of restrictedSamplingParams) {
268
+ if (value === void 0) {
269
+ continue;
270
+ }
271
+ throw new ValidationError(
272
+ `${providerId} model "${modelId}" does not support ${name} when reasoning is enabled`,
273
+ void 0,
274
+ providerId
275
+ );
243
276
  }
277
+ }
278
+ const toolChoiceMode = typeof options.toolChoice === "object" ? options.toolChoice.type : options.toolChoice;
279
+ if (toolChoiceMode !== void 0 && !capabilities.reasoning.supportedToolChoices.includes(toolChoiceMode)) {
244
280
  throw new ValidationError(
245
- `OpenAI model "${modelId}" does not support ${name} when reasoning is enabled`,
281
+ `${providerId} model "${modelId}" does not support toolChoice "${toolChoiceMode}" when reasoning is enabled`,
246
282
  void 0,
247
- "openai"
283
+ providerId
248
284
  );
249
285
  }
250
286
  }
@@ -262,10 +298,10 @@ function extractCompatibleReasoningText(source) {
262
298
  }
263
299
 
264
300
  // src/chat-completions/chat-adapter.ts
265
- function convertMessages(messages) {
266
- return messages.map(convertMessage);
301
+ function convertMessages(messages, adapterOptions = {}) {
302
+ return messages.map((message) => convertMessage(message, adapterOptions));
267
303
  }
268
- function convertMessage(message) {
304
+ function convertMessage(message, adapterOptions) {
269
305
  if (message.role === "system") {
270
306
  return {
271
307
  role: "system",
@@ -279,19 +315,32 @@ function convertMessage(message) {
279
315
  };
280
316
  }
281
317
  if (message.role === "assistant") {
282
- const text = message.parts.flatMap((part) => {
283
- if (part.type === "text") return [part.text];
284
- if (part.type === "reasoning" && part.text.length > 0) {
285
- return [`<thinking>${part.text}</thinking>`];
318
+ const nativeReasoning = [];
319
+ const text = [];
320
+ for (const part of message.parts) {
321
+ if (part.type === "text") {
322
+ text.push(part.text);
323
+ continue;
286
324
  }
287
- return [];
288
- }).join("\n\n");
325
+ if (part.type !== "reasoning" || part.text.length === 0) {
326
+ continue;
327
+ }
328
+ const reasoningOptions = adapterOptions.reasoning;
329
+ if (reasoningOptions && getProviderMetadata(
330
+ part.providerMetadata,
331
+ reasoningOptions.providerMetadataKey
332
+ )) {
333
+ nativeReasoning.push(part.text);
334
+ } else {
335
+ text.push(`<thinking>${part.text}</thinking>`);
336
+ }
337
+ }
289
338
  const toolCalls = message.parts.flatMap(
290
339
  (part) => part.type === "tool-call" ? [part.toolCall] : []
291
340
  );
292
- return {
341
+ const assistantMessage = {
293
342
  role: "assistant",
294
- content: text.length > 0 ? text : null,
343
+ content: text.length > 0 ? text.join("\n\n") : null,
295
344
  ...toolCalls.length > 0 ? {
296
345
  tool_calls: toolCalls.map((toolCall) => ({
297
346
  id: toolCall.id,
@@ -303,6 +352,12 @@ function convertMessage(message) {
303
352
  }))
304
353
  } : {}
305
354
  };
355
+ if (adapterOptions.reasoning && nativeReasoning.length > 0) {
356
+ return Object.assign(assistantMessage, {
357
+ [adapterOptions.reasoning.requestField]: nativeReasoning.join("\n\n")
358
+ });
359
+ }
360
+ return assistantMessage;
306
361
  }
307
362
  return {
308
363
  role: "tool",
@@ -334,17 +389,17 @@ function convertUserContentPart(part) {
334
389
  }
335
390
  };
336
391
  }
337
- function createGenerateRequest(modelId, options, adapterOptions = {}) {
392
+ function createGenerateRequest(modelId, options, adapterOptions) {
338
393
  return createRequest(modelId, options, false, adapterOptions);
339
394
  }
340
- function createStreamRequest(modelId, options, adapterOptions = {}) {
395
+ function createStreamRequest(modelId, options, adapterOptions) {
341
396
  return createRequest(modelId, options, true, adapterOptions);
342
397
  }
343
398
  function createRequest(modelId, options, stream, adapterOptions) {
344
399
  const openaiOptions = parseOpenAIChatGenerateProviderOptions(
345
- options.providerOptions
400
+ options.providerOptions,
401
+ adapterOptions.providerOptions
346
402
  );
347
- const structuredOutputFormat = options.structuredOutputFormat;
348
403
  return {
349
404
  ...createRequestBase(modelId, options, adapterOptions),
350
405
  ...stream ? {
@@ -353,28 +408,24 @@ function createRequest(modelId, options, stream, adapterOptions) {
353
408
  include_usage: true
354
409
  }
355
410
  } : {},
356
- ...structuredOutputFormat ? {
357
- response_format: {
358
- type: "json_schema",
359
- json_schema: {
360
- name: structuredOutputFormat.name,
361
- ...structuredOutputFormat.description ? {
362
- description: structuredOutputFormat.description
363
- } : {},
364
- strict: structuredOutputFormat.strict,
365
- schema: structuredOutputFormat.schema
366
- }
367
- }
368
- } : {},
369
- ...mapOpenAIProviderOptionsToRequestFields(openaiOptions)
411
+ ...mapOpenAIProviderOptionsToRequestFields(openaiOptions),
412
+ ...mapResponseFormatToRequestFields(options.structuredOutputFormat)
370
413
  };
371
414
  }
372
415
  function createRequestBase(modelId, options, adapterOptions) {
373
- validateOpenAIReasoningConfig(modelId, options);
374
- const reasoningFields = mapReasoningToRequestFields(modelId, options);
416
+ validateReasoningConfig(
417
+ modelId,
418
+ options,
419
+ adapterOptions.capabilities,
420
+ adapterOptions.providerId
421
+ );
422
+ const reasoningFields = mapReasoningToRequestFields(
423
+ options,
424
+ adapterOptions.capabilities
425
+ );
375
426
  return {
376
427
  model: modelId,
377
- messages: convertMessages(options.messages),
428
+ messages: convertMessages(options.messages, adapterOptions),
378
429
  ...options.tools && Object.keys(options.tools).length > 0 ? { tools: convertTools(options.tools) } : {},
379
430
  ...options.toolChoice ? { tool_choice: convertToolChoice(options.toolChoice) } : {},
380
431
  ...reasoningFields,
@@ -401,6 +452,29 @@ function mapOpenAIProviderOptionsToRequestFields(options) {
401
452
  ...options?.seed !== void 0 ? { seed: options.seed } : {}
402
453
  };
403
454
  }
455
+ function mapResponseFormatToRequestFields(format) {
456
+ if (!format) {
457
+ return {};
458
+ }
459
+ if (format.type === "json_object") {
460
+ return {
461
+ response_format: {
462
+ type: "json_object"
463
+ }
464
+ };
465
+ }
466
+ return {
467
+ response_format: {
468
+ type: "json_schema",
469
+ json_schema: {
470
+ name: format.name,
471
+ ...format.description ? { description: format.description } : {},
472
+ strict: format.strict,
473
+ schema: format.schema
474
+ }
475
+ }
476
+ };
477
+ }
404
478
  function mapGenerateResponse(response, adapterOptions = {}) {
405
479
  const firstChoice = response.choices[0];
406
480
  if (!firstChoice) {
@@ -425,7 +499,12 @@ function mapGenerateResponse(response, adapterOptions = {}) {
425
499
  const content = extractTextContent(firstChoice.message.content);
426
500
  const reasoning = adapterOptions.compatibility ? extractCompatibleReasoningText(firstChoice.message) ?? null : null;
427
501
  const toolCalls = parseToolCalls(firstChoice.message.tool_calls);
428
- const parts = createAssistantParts(reasoning, content, toolCalls);
502
+ const parts = createAssistantParts(
503
+ reasoning,
504
+ content,
505
+ toolCalls,
506
+ adapterOptions.reasoning?.providerMetadataKey
507
+ );
429
508
  return {
430
509
  parts,
431
510
  content,
@@ -519,7 +598,14 @@ async function* transformStream(stream, adapterOptions = {}) {
519
598
  return;
520
599
  }
521
600
  reasoningOpen = false;
522
- yield { type: "reasoning-end" };
601
+ yield {
602
+ type: "reasoning-end",
603
+ ...adapterOptions.reasoning ? {
604
+ providerMetadata: {
605
+ [adapterOptions.reasoning.providerMetadataKey]: {}
606
+ }
607
+ } : {}
608
+ };
523
609
  };
524
610
  for await (const chunk of stream) {
525
611
  if (chunk.usage) {
@@ -623,12 +709,11 @@ async function* transformStream(stream, adapterOptions = {}) {
623
709
  usage
624
710
  };
625
711
  }
626
- function mapReasoningToRequestFields(modelId, options) {
712
+ function mapReasoningToRequestFields(options, capabilities) {
627
713
  if (!options.reasoning) {
628
714
  return {};
629
715
  }
630
- const capabilities = getOpenAIModelCapabilities(modelId);
631
- if (!capabilities.reasoning.supported) {
716
+ if (capabilities.reasoning.mode === "unsupported" || capabilities.reasoning.supportedEfforts.length === 0) {
632
717
  return {};
633
718
  }
634
719
  const clampedEffort = clampReasoningEffort(
@@ -639,12 +724,17 @@ function mapReasoningToRequestFields(modelId, options) {
639
724
  reasoning_effort: toOpenAIReasoningEffort(clampedEffort)
640
725
  };
641
726
  }
642
- function createAssistantParts(reasoning, content, toolCalls) {
727
+ function createAssistantParts(reasoning, content, toolCalls, reasoningProviderMetadataKey) {
643
728
  const parts = [];
644
729
  if (reasoning) {
645
730
  parts.push({
646
731
  type: "reasoning",
647
- text: reasoning
732
+ text: reasoning,
733
+ ...reasoningProviderMetadataKey ? {
734
+ providerMetadata: {
735
+ [reasoningProviderMetadataKey]: {}
736
+ }
737
+ } : {}
648
738
  });
649
739
  }
650
740
  if (content) {
@@ -680,28 +770,176 @@ function extractTextContent(content) {
680
770
 
681
771
  // src/openai-error.ts
682
772
  import { APIError, APIUserAbortError } from "openai";
683
- import { AbortedError, ProviderError } from "@core-ai/core-ai";
684
- function isOpenAIAbortError(error) {
685
- return error instanceof APIUserAbortError || error instanceof Error && error.name === "AbortError";
686
- }
773
+ import {
774
+ AbortedError,
775
+ ContextLengthExceededError,
776
+ ModelOverloadedError,
777
+ ProviderError,
778
+ RateLimitError,
779
+ ServiceUnavailableError,
780
+ asRecord,
781
+ getErrorMessage,
782
+ getHttpStatusCode,
783
+ getRetryAfterSecondsFromError,
784
+ getString,
785
+ isAbortErrorByName,
786
+ isRateLimitStatus,
787
+ isTransientUnavailableStatus
788
+ } from "@core-ai/core-ai";
789
+ var CONTEXT_LENGTH_ERROR_CODES = /* @__PURE__ */ new Set([
790
+ "context_length_exceeded",
791
+ "string_above_max_length"
792
+ ]);
793
+ var TOKEN_LIMIT_PATTERNS = [
794
+ /maximum context length is (\d+) tokens.*resulted in (\d+) tokens/i,
795
+ /maximum context length is (\d+) tokens.*you requested (\d+) tokens/i,
796
+ /configured limit of (\d+) tokens.*resulted in (\d+) tokens/i
797
+ ];
798
+ var OVERLOAD_MESSAGE_ELIGIBLE_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
687
799
  function wrapOpenAIError(error, provider = "openai") {
688
800
  if (isOpenAIAbortError(error)) {
689
801
  return new AbortedError(error, provider);
690
802
  }
803
+ const message = getErrorMessage(error);
804
+ const statusCode = error instanceof APIError ? error.status : getHttpStatusCode(error, ["status"]);
805
+ const options = { statusCode, cause: error };
806
+ const contextLength = getContextLengthDetails(error, message);
807
+ if (contextLength) {
808
+ return new ContextLengthExceededError(message, provider, {
809
+ ...options,
810
+ ...contextLength
811
+ });
812
+ }
813
+ if (isAzureOpenAIBackendCapacityError(error)) {
814
+ return new ServiceUnavailableError(message, provider, options);
815
+ }
816
+ if (isOpenAIInsufficientQuota(error)) {
817
+ return new ProviderError(message, provider, options);
818
+ }
819
+ if (isAzureOpenAINoCapacity(error)) {
820
+ return new ModelOverloadedError(message, provider, options);
821
+ }
822
+ if (isOpenAIOverloaded(error, message, statusCode)) {
823
+ return new ModelOverloadedError(message, provider, options);
824
+ }
825
+ if (isOpenAIRateLimit(error, statusCode)) {
826
+ return new RateLimitError(message, provider, {
827
+ ...options,
828
+ retryAfterSeconds: getRetryAfterSecondsFromError(error)
829
+ });
830
+ }
831
+ if (isTransientUnavailableStatus(statusCode)) {
832
+ return new ServiceUnavailableError(message, provider, options);
833
+ }
834
+ return new ProviderError(message, provider, options);
835
+ }
836
+ function isOpenAIAbortError(error) {
837
+ return error instanceof APIUserAbortError || isAbortErrorByName(error);
838
+ }
839
+ function isOpenAIRateLimit(error, statusCode) {
840
+ if (isRateLimitStatus(statusCode)) {
841
+ return true;
842
+ }
843
+ const code = getProviderErrorCode(error);
844
+ const type = getProviderErrorType(error);
845
+ return code === "rate_limit_exceeded" || type === "rate_limit_error";
846
+ }
847
+ function isOpenAIOverloaded(error, message, statusCode) {
848
+ const providerMessage = getProviderMessage(error) ?? "";
849
+ return indicatesOpenAIOverload(`${providerMessage} ${message}`, statusCode);
850
+ }
851
+ function indicatesOpenAIOverload(text, statusCode) {
852
+ if (statusCode !== void 0 && !OVERLOAD_MESSAGE_ELIGIBLE_STATUS_CODES.has(statusCode)) {
853
+ return false;
854
+ }
855
+ const lower = text.toLowerCase();
856
+ return /\boverloaded\b/.test(lower) || /\bhigh demand\b/.test(lower) || /\brunning out of capacity\b/.test(lower) || /\bspikes in demand\b/.test(lower);
857
+ }
858
+ function getContextLengthDetails(error, fallbackMessage) {
859
+ const providerMessage = getProviderMessage(error) ?? fallbackMessage;
860
+ const code = getProviderErrorCode(error);
861
+ const isKnownContextLengthCode = code !== void 0 && CONTEXT_LENGTH_ERROR_CODES.has(code);
862
+ const tokenCounts = matchTokenLimitCounts(providerMessage);
863
+ if (tokenCounts) {
864
+ return tokenCounts;
865
+ }
866
+ if (!isKnownContextLengthCode) {
867
+ return void 0;
868
+ }
869
+ return {};
870
+ }
871
+ function matchTokenLimitCounts(providerMessage) {
872
+ for (const pattern of TOKEN_LIMIT_PATTERNS) {
873
+ const match = providerMessage.match(pattern);
874
+ if (!match) {
875
+ continue;
876
+ }
877
+ const maxTokens = match[1];
878
+ const actualTokens = match[2];
879
+ if (maxTokens === void 0 || actualTokens === void 0) {
880
+ continue;
881
+ }
882
+ return {
883
+ maxTokens: parseInt(maxTokens, 10),
884
+ actualTokens: parseInt(actualTokens, 10)
885
+ };
886
+ }
887
+ return void 0;
888
+ }
889
+ function isAzureOpenAIBackendCapacityError(error) {
890
+ const type = getProviderErrorType(error);
891
+ const providerMessage = getProviderMessage(error);
892
+ return type === "invalid_request_error" && providerMessage?.toLowerCase() === "backend error.";
893
+ }
894
+ function isOpenAIInsufficientQuota(error) {
895
+ const code = getProviderErrorCode(error);
896
+ const type = getProviderErrorType(error);
897
+ return code === "insufficient_quota" || type === "insufficient_quota";
898
+ }
899
+ function isAzureOpenAINoCapacity(error) {
900
+ return getProviderErrorCode(error) === "NoCapacity";
901
+ }
902
+ function getProviderMessage(error) {
691
903
  if (error instanceof APIError) {
692
- return new ProviderError(
693
- error.message,
694
- provider,
695
- error.status,
696
- error
697
- );
904
+ const nested2 = asRecord(error.error);
905
+ return getString(nested2, "message") ?? error.message;
698
906
  }
699
- return new ProviderError(
700
- error instanceof Error ? error.message : String(error),
701
- provider,
702
- void 0,
703
- error
704
- );
907
+ const record = asRecord(error);
908
+ if (!record) {
909
+ return void 0;
910
+ }
911
+ const nested = asRecord(record.error);
912
+ return getString(nested, "message") ?? getString(record, "message");
913
+ }
914
+ function getProviderErrorCode(error) {
915
+ if (error instanceof APIError) {
916
+ if (typeof error.code === "string") {
917
+ return error.code;
918
+ }
919
+ const nested2 = asRecord(error.error);
920
+ return getString(nested2, "code");
921
+ }
922
+ const record = asRecord(error);
923
+ if (!record) {
924
+ return void 0;
925
+ }
926
+ const nested = asRecord(record.error);
927
+ return getString(record, "code") ?? getString(nested, "code");
928
+ }
929
+ function getProviderErrorType(error) {
930
+ if (error instanceof APIError) {
931
+ if (typeof error.type === "string") {
932
+ return error.type;
933
+ }
934
+ const nested2 = asRecord(error.error);
935
+ return getString(nested2, "type");
936
+ }
937
+ const record = asRecord(error);
938
+ if (!record) {
939
+ return void 0;
940
+ }
941
+ const nested = asRecord(record.error);
942
+ return getString(record, "type") ?? getString(nested, "type");
705
943
  }
706
944
 
707
945
  // src/shared/structured-output.ts
@@ -716,7 +954,7 @@ var DEFAULT_STRUCTURED_OUTPUT_DESCRIPTION = "Return a JSON object that matches t
716
954
  function getStructuredOutputName(options) {
717
955
  return options.schemaName?.trim() || DEFAULT_STRUCTURED_OUTPUT_NAME;
718
956
  }
719
- function createStructuredOutputRequestOptions(options, mode = "native") {
957
+ function createStructuredOutputRequestOptions(options, mode = "json-schema") {
720
958
  const baseOptions = {
721
959
  messages: options.messages,
722
960
  reasoning: options.reasoning,
@@ -743,11 +981,43 @@ function createStructuredOutputRequestOptions(options, mode = "native") {
743
981
  }
744
982
  };
745
983
  }
984
+ if (mode === "json-object") {
985
+ const format = createOpenAIStructuredOutputFormat(options);
986
+ const description = format.description ?? DEFAULT_STRUCTURED_OUTPUT_DESCRIPTION;
987
+ const instruction = [
988
+ "Return only a valid JSON object.",
989
+ `Schema name: ${format.name}.`,
990
+ `Description: ${description}`,
991
+ `JSON Schema: ${JSON.stringify(format.schema)}`,
992
+ "Do not include markdown, prose, or any text outside the JSON object."
993
+ ].join("\n");
994
+ return {
995
+ ...baseOptions,
996
+ messages: insertStructuredOutputSystemMessage(
997
+ options.messages,
998
+ instruction
999
+ ),
1000
+ structuredOutputFormat: {
1001
+ type: "json_object"
1002
+ }
1003
+ };
1004
+ }
746
1005
  return {
747
1006
  ...baseOptions,
748
1007
  structuredOutputFormat: createOpenAIStructuredOutputFormat(options)
749
1008
  };
750
1009
  }
1010
+ function insertStructuredOutputSystemMessage(messages, content) {
1011
+ const firstNonSystemMessageIndex = messages.findIndex(
1012
+ (message) => message.role !== "system"
1013
+ );
1014
+ const insertionIndex = firstNonSystemMessageIndex === -1 ? messages.length : firstNonSystemMessageIndex;
1015
+ return [
1016
+ ...messages.slice(0, insertionIndex),
1017
+ { role: "system", content },
1018
+ ...messages.slice(insertionIndex)
1019
+ ];
1020
+ }
751
1021
  function createOpenAIStructuredOutputFormat(options) {
752
1022
  const name = getStructuredOutputName(options);
753
1023
  const format = zodTextFormat(
@@ -916,10 +1186,19 @@ function formatZodIssues(issues) {
916
1186
  }
917
1187
 
918
1188
  // src/chat-completions/chat-model.ts
919
- function createOpenAIChatCompletionsModel(client, modelId, modelOptions = {}) {
1189
+ function createOpenAIChatCompletionsModel(client, modelId, modelOptions) {
920
1190
  const provider = modelOptions.providerId ?? "openai";
921
- const structuredOutputMode = modelOptions.structuredOutputMode ?? (modelOptions.compatibility ? "tool" : "native");
922
- const nonStandardReasoning = modelOptions.nonStandardReasoning ?? modelOptions.compatibility;
1191
+ const capabilities = modelOptions.capabilities;
1192
+ const compatibilityOptions = modelOptions.compatibility;
1193
+ const structuredOutputMode = compatibilityOptions?.structuredOutputMode ?? (compatibilityOptions ? "tool" : "json-schema");
1194
+ const adapterOptions = {
1195
+ capabilities,
1196
+ compatibility: compatibilityOptions !== void 0 && compatibilityOptions.reasoning !== false,
1197
+ maxTokensParameter: compatibilityOptions?.maxTokensParameter,
1198
+ providerId: provider,
1199
+ providerOptions: modelOptions.providerOptions,
1200
+ reasoning: typeof compatibilityOptions?.reasoning === "object" ? compatibilityOptions.reasoning : void 0
1201
+ };
923
1202
  async function callOpenAIChatCompletionsApi(request, signal) {
924
1203
  try {
925
1204
  return await client.chat.completions.create(request, {
@@ -930,20 +1209,19 @@ function createOpenAIChatCompletionsModel(client, modelId, modelOptions = {}) {
930
1209
  }
931
1210
  }
932
1211
  async function generateChat(options) {
933
- const request = createGenerateRequest(modelId, options, modelOptions);
934
- const response = await callOpenAIChatCompletionsApi(request, options.signal);
935
- return mapGenerateResponse(response, {
936
- compatibility: nonStandardReasoning
937
- });
1212
+ const request = createGenerateRequest(modelId, options, adapterOptions);
1213
+ const response = await callOpenAIChatCompletionsApi(
1214
+ request,
1215
+ options.signal
1216
+ );
1217
+ return mapGenerateResponse(response, adapterOptions);
938
1218
  }
939
1219
  async function streamChat(options) {
940
- const request = createStreamRequest(modelId, options, modelOptions);
1220
+ const request = createStreamRequest(modelId, options, adapterOptions);
941
1221
  return createChatStream(
942
1222
  async () => transformStream(
943
1223
  await callOpenAIChatCompletionsApi(request, options.signal),
944
- {
945
- compatibility: nonStandardReasoning
946
- }
1224
+ adapterOptions
947
1225
  ),
948
1226
  { signal: options.signal }
949
1227
  );
@@ -951,7 +1229,7 @@ function createOpenAIChatCompletionsModel(client, modelId, modelOptions = {}) {
951
1229
  return {
952
1230
  provider,
953
1231
  modelId,
954
- capabilities: getOpenAIModelCapabilities(modelId),
1232
+ capabilities,
955
1233
  generate: generateChat,
956
1234
  stream: streamChat,
957
1235
  async generateObject(options) {
@@ -997,18 +1275,24 @@ function createOpenAIChatCompletionsModel(client, modelId, modelOptions = {}) {
997
1275
 
998
1276
  // src/shared/provider-factory.ts
999
1277
  import OpenAI from "openai";
1278
+ import {
1279
+ getRegisteredModelCapabilities as getRegisteredModelCapabilities2
1280
+ } from "@core-ai/core-ai";
1000
1281
 
1001
1282
  // src/chat-model.ts
1002
1283
  import { createObjectStream as createObjectStream2, createChatStream as createChatStream2 } from "@core-ai/core-ai";
1003
1284
 
1004
1285
  // src/chat-adapter.ts
1005
- import { getProviderMetadata, clampReasoningEffort as clampReasoningEffort2 } from "@core-ai/core-ai";
1286
+ import { getProviderMetadata as getProviderMetadata2, clampReasoningEffort as clampReasoningEffort2 } from "@core-ai/core-ai";
1006
1287
  var ENCRYPTED_REASONING_INCLUDE = "reasoning.encrypted_content";
1007
1288
  var REASONING_SUMMARY_SEPARATOR = "\n\n";
1008
- function convertMessages2(messages) {
1009
- return messages.flatMap(convertMessage2);
1289
+ function convertMessages2(messages, options = {}) {
1290
+ const includeReasoning = options.includeReasoning ?? true;
1291
+ return messages.flatMap(
1292
+ (message) => convertMessage2(message, includeReasoning)
1293
+ );
1010
1294
  }
1011
- function convertMessage2(message) {
1295
+ function convertMessage2(message, includeReasoning) {
1012
1296
  if (message.role === "system") {
1013
1297
  return [
1014
1298
  {
@@ -1026,7 +1310,7 @@ function convertMessage2(message) {
1026
1310
  ];
1027
1311
  }
1028
1312
  if (message.role === "assistant") {
1029
- return convertAssistantMessage(message.parts);
1313
+ return convertAssistantMessage(message.parts, includeReasoning);
1030
1314
  }
1031
1315
  return [
1032
1316
  {
@@ -1036,7 +1320,7 @@ function convertMessage2(message) {
1036
1320
  }
1037
1321
  ];
1038
1322
  }
1039
- function convertAssistantMessage(parts) {
1323
+ function convertAssistantMessage(parts, includeReasoning) {
1040
1324
  const items = [];
1041
1325
  const textParts = [];
1042
1326
  const flushTextBuffer = () => {
@@ -1055,7 +1339,7 @@ function convertAssistantMessage(parts) {
1055
1339
  continue;
1056
1340
  }
1057
1341
  if (part.type === "reasoning") {
1058
- if (getProviderMetadata(
1342
+ if (!includeReasoning || getProviderMetadata2(
1059
1343
  part.providerMetadata,
1060
1344
  "openai"
1061
1345
  ) == null) {
@@ -1090,7 +1374,7 @@ function convertAssistantMessage(parts) {
1090
1374
  return items;
1091
1375
  }
1092
1376
  function getEncryptedReasoningContent(part) {
1093
- const { encryptedContent } = getProviderMetadata(
1377
+ const { encryptedContent } = getProviderMetadata2(
1094
1378
  part.providerMetadata,
1095
1379
  "openai"
1096
1380
  ) ?? {};
@@ -1140,7 +1424,7 @@ function createRequest2(modelId, options, stream) {
1140
1424
  ...options.structuredOutputFormat ? { text: { format: options.structuredOutputFormat } } : {},
1141
1425
  ...mapOpenAIProviderOptionsToRequestFields2(openaiOptions)
1142
1426
  };
1143
- if (options.reasoning && getOpenAIModelCapabilities(modelId).reasoning.supported) {
1427
+ if (options.reasoning && getOpenAIModelCapabilities(modelId).reasoning.mode !== "unsupported") {
1144
1428
  request.include = mergeInclude(request.include, [
1145
1429
  ENCRYPTED_REASONING_INCLUDE
1146
1430
  ]);
@@ -1149,10 +1433,13 @@ function createRequest2(modelId, options, stream) {
1149
1433
  }
1150
1434
  function createRequestBase2(modelId, options) {
1151
1435
  validateOpenAIReasoningConfig(modelId, options);
1436
+ const capabilities = getOpenAIModelCapabilities(modelId);
1152
1437
  return {
1153
1438
  model: modelId,
1154
1439
  store: false,
1155
- input: convertMessages2(options.messages),
1440
+ input: convertMessages2(options.messages, {
1441
+ includeReasoning: capabilities.reasoning.mode !== "unsupported"
1442
+ }),
1156
1443
  ...options.tools && Object.keys(options.tools).length > 0 ? { tools: convertResponseTools(options.tools) } : {},
1157
1444
  ...options.toolChoice ? { tool_choice: convertResponseToolChoice(options.toolChoice) } : {},
1158
1445
  ...mapReasoningToRequestFields2(modelId, options),
@@ -1629,7 +1916,7 @@ function mapReasoningToRequestFields2(modelId, options) {
1629
1916
  return {};
1630
1917
  }
1631
1918
  const capabilities = getOpenAIModelCapabilities(modelId);
1632
- if (!capabilities.reasoning.supported) {
1919
+ if (capabilities.reasoning.mode === "unsupported") {
1633
1920
  return {};
1634
1921
  }
1635
1922
  const effort = toOpenAIReasoningEffort(
@@ -1656,7 +1943,7 @@ function isReasoningItem(item) {
1656
1943
  }
1657
1944
 
1658
1945
  // src/chat-model.ts
1659
- function createOpenAIChatModel(client, modelId, providerId = "openai") {
1946
+ function createOpenAIChatModel(client, modelId, capabilities, providerId = "openai") {
1660
1947
  const provider = providerId;
1661
1948
  async function callOpenAIResponsesApi(request, signal) {
1662
1949
  try {
@@ -1687,7 +1974,7 @@ function createOpenAIChatModel(client, modelId, providerId = "openai") {
1687
1974
  return {
1688
1975
  provider,
1689
1976
  modelId,
1690
- capabilities: getOpenAIModelCapabilities(modelId),
1977
+ capabilities,
1691
1978
  generate: generateChat,
1692
1979
  stream: streamChat,
1693
1980
  async generateObject(options) {
@@ -1817,16 +2104,37 @@ function createOpenAIProvider(options, factoryOptions = {}) {
1817
2104
  baseURL: options.baseURL
1818
2105
  });
1819
2106
  const providerId = factoryOptions.providerId ?? "openai";
1820
- const compatibilityEnabled = factoryOptions.compatibility === true || typeof factoryOptions.compatibility === "object";
1821
2107
  const compatibilityOptions = typeof factoryOptions.compatibility === "object" ? factoryOptions.compatibility : void 0;
1822
- const createResponsesModel = (modelId) => createOpenAIChatModel(client, modelId, providerId);
1823
- const createChatCompletionsModel = (modelId) => createOpenAIChatCompletionsModel(client, modelId, {
1824
- providerId,
1825
- compatibility: compatibilityEnabled,
1826
- nonStandardReasoning: compatibilityEnabled && (compatibilityOptions?.reasoning ?? true),
1827
- structuredOutputMode: compatibilityOptions?.structuredOutputMode,
1828
- maxTokensParameter: compatibilityOptions?.maxTokensParameter
1829
- });
2108
+ const createResponsesModel = (modelId) => {
2109
+ const capabilities = getRegisteredModelCapabilities2(
2110
+ factoryOptions.modelCapabilities,
2111
+ modelId
2112
+ ) ?? getOpenAIModelCapabilities(modelId);
2113
+ return createOpenAIChatModel(client, modelId, capabilities, providerId);
2114
+ };
2115
+ const createChatCompletionsModel = (modelId) => {
2116
+ const capabilities = getRegisteredModelCapabilities2(
2117
+ factoryOptions.modelCapabilities,
2118
+ modelId
2119
+ ) ?? getOpenAIModelCapabilities(modelId);
2120
+ const compatibility = factoryOptions.compatibility ? {
2121
+ reasoning: typeof compatibilityOptions?.reasoning === "object" ? {
2122
+ ...compatibilityOptions.reasoning,
2123
+ providerMetadataKey: compatibilityOptions.reasoning.providerMetadataKey ?? providerId
2124
+ } : compatibilityOptions?.reasoning ?? true,
2125
+ structuredOutputMode: compatibilityOptions?.structuredOutputMode,
2126
+ maxTokensParameter: compatibilityOptions?.maxTokensParameter
2127
+ } : void 0;
2128
+ return createOpenAIChatCompletionsModel(client, modelId, {
2129
+ providerId,
2130
+ capabilities,
2131
+ compatibility,
2132
+ providerOptions: {
2133
+ key: factoryOptions.providerOptionsKey ?? providerId,
2134
+ schema: factoryOptions.providerOptionsSchema ?? openaiChatGenerateProviderOptionsSchema
2135
+ }
2136
+ });
2137
+ };
1830
2138
  const chat = {
1831
2139
  chatModel: createChatCompletionsModel
1832
2140
  };
@@ -1839,6 +2147,7 @@ function createOpenAIProvider(options, factoryOptions = {}) {
1839
2147
  }
1840
2148
 
1841
2149
  export {
2150
+ OPENAI_MODEL_CAPABILITIES,
1842
2151
  getOpenAIModelCapabilities,
1843
2152
  openaiResponsesGenerateProviderOptionsSchema,
1844
2153
  openaiChatGenerateProviderOptionsSchema,
package/dist/compat.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as _core_ai_core_ai from '@core-ai/core-ai';
2
2
  import { ChatModel } from '@core-ai/core-ai';
3
- import { O as OpenAIChatClient, a as OpenAIProvider, b as OpenAIProviderBaseOptions } from './provider-options-CpxtGjm0.js';
4
- export { c as OpenAICompatGenerateProviderOptions, d as OpenAICompatRequestOptions, o as openaiCompatGenerateProviderOptionsSchema, e as openaiCompatProviderOptionsSchema } from './provider-options-CpxtGjm0.js';
3
+ import { O as OpenAIChatClient, a as OpenAIProvider, b as OpenAIProviderBaseOptions } from './provider-factory-DaVZWYPo.js';
4
+ export { c as OpenAICompatGenerateProviderOptions, d as OpenAICompatRequestOptions, o as openaiCompatGenerateProviderOptionsSchema, e as openaiCompatProviderOptionsSchema } from './provider-factory-DaVZWYPo.js';
5
5
  import 'openai';
6
6
  import 'zod';
7
7
 
package/dist/compat.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import {
2
2
  createOpenAIChatCompletionsModel,
3
3
  createOpenAIProvider,
4
+ getOpenAIModelCapabilities,
4
5
  openaiCompatGenerateProviderOptionsSchema,
5
6
  openaiCompatProviderOptionsSchema
6
- } from "./chunk-YORO2XQ3.js";
7
+ } from "./chunk-LVGNSX5F.js";
7
8
 
8
9
  // src/compat/provider.ts
9
10
  import OpenAI from "openai";
@@ -20,8 +21,9 @@ function createOpenAICompatChatProvider(options = {}, providerId = "openai") {
20
21
  });
21
22
  return {
22
23
  chatModel: (modelId) => createOpenAIChatCompletionsModel(client, modelId, {
24
+ capabilities: getOpenAIModelCapabilities(modelId),
23
25
  providerId,
24
- compatibility: true
26
+ compatibility: { reasoning: true }
25
27
  })
26
28
  };
27
29
  }
@@ -29,8 +31,9 @@ function createOpenAICompatChatProvider(options = {}, providerId = "openai") {
29
31
  // src/compat/chat-model.ts
30
32
  function createOpenAICompatChatModel(client, modelId, providerId = "openai") {
31
33
  return createOpenAIChatCompletionsModel(client, modelId, {
34
+ capabilities: getOpenAIModelCapabilities(modelId),
32
35
  providerId,
33
- compatibility: true
36
+ compatibility: { reasoning: true }
34
37
  });
35
38
  }
36
39
  export {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as OpenAIProvider$1, b as OpenAIProviderBaseOptions } from './provider-options-CpxtGjm0.js';
2
- export { O as OpenAIChatClient, f as OpenAIChatCompletionsModelOptions, g as OpenAIChatGenerateProviderOptions, h as OpenAIChatProvider, c as OpenAICompatGenerateProviderOptions, d as OpenAICompatRequestOptions, i as OpenAICompatibility, j as OpenAICompatibilityOptions, k as OpenAIEmbedProviderOptions, l as OpenAIImageProviderOptions, m as OpenAIModelCapabilities, n as OpenAIProviderFactoryOptions, p as OpenAIResponsesGenerateProviderOptions, q as OpenAIResponsesProviderOptions, r as OpenAIStructuredOutputMode, s as createOpenAIChatCompletionsModel, t as createOpenAIProvider, u as getOpenAIModelCapabilities, v as openaiChatGenerateProviderOptionsSchema, o as openaiCompatGenerateProviderOptionsSchema, e as openaiCompatProviderOptionsSchema, w as openaiEmbedProviderOptionsSchema, x as openaiImageProviderOptionsSchema, y as openaiResponsesGenerateProviderOptionsSchema, z as openaiResponsesProviderOptionsSchema } from './provider-options-CpxtGjm0.js';
1
+ import { a as OpenAIProvider$1, b as OpenAIProviderBaseOptions } from './provider-factory-DaVZWYPo.js';
2
+ export { O as OpenAIChatClient, f as OpenAIChatCompletionsModelOptions, g as OpenAIChatGenerateProviderOptions, h as OpenAIChatProvider, c as OpenAICompatGenerateProviderOptions, d as OpenAICompatRequestOptions, i as OpenAICompatibility, j as OpenAICompatibilityOptions, k as OpenAIEmbedProviderOptions, l as OpenAIImageProviderOptions, m as OpenAIModelCapabilities, n as OpenAIProviderFactoryOptions, p as OpenAIResponsesGenerateProviderOptions, q as OpenAIResponsesProviderOptions, r as OpenAIStructuredOutputMode, s as createOpenAIChatCompletionsModel, t as createOpenAIProvider, u as getOpenAIModelCapabilities, v as openaiChatGenerateProviderOptionsSchema, o as openaiCompatGenerateProviderOptionsSchema, e as openaiCompatProviderOptionsSchema, w as openaiEmbedProviderOptionsSchema, x as openaiImageProviderOptionsSchema, y as openaiResponsesGenerateProviderOptionsSchema, z as openaiResponsesProviderOptionsSchema } from './provider-factory-DaVZWYPo.js';
3
3
  import 'openai';
4
4
  import '@core-ai/core-ai';
5
5
  import 'zod';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ OPENAI_MODEL_CAPABILITIES,
2
3
  createOpenAIChatCompletionsModel,
3
4
  createOpenAIProvider,
4
5
  getOpenAIModelCapabilities,
@@ -9,11 +10,13 @@ import {
9
10
  openaiImageProviderOptionsSchema,
10
11
  openaiResponsesGenerateProviderOptionsSchema,
11
12
  openaiResponsesProviderOptionsSchema
12
- } from "./chunk-YORO2XQ3.js";
13
+ } from "./chunk-LVGNSX5F.js";
13
14
 
14
15
  // src/provider.ts
15
16
  function createOpenAI(options = {}) {
16
- return createOpenAIProvider(options);
17
+ return createOpenAIProvider(options, {
18
+ modelCapabilities: OPENAI_MODEL_CAPABILITIES
19
+ });
17
20
  }
18
21
  export {
19
22
  createOpenAI,
@@ -1,5 +1,5 @@
1
1
  import OpenAI from 'openai';
2
- import { ModelCapabilities, ChatModel, EmbeddingModel, ImageModel } from '@core-ai/core-ai';
2
+ import { ModelCapabilities, ChatModel, EmbeddingModel, ImageModel, ModelCapabilitiesRegistry } from '@core-ai/core-ai';
3
3
  import { z } from 'zod';
4
4
 
5
5
  type OpenAIChatCompletionsCapabilities = {
@@ -10,49 +10,22 @@ type OpenAIModelCapabilities = ModelCapabilities & {
10
10
  };
11
11
  declare function getOpenAIModelCapabilities(modelId: string): OpenAIModelCapabilities;
12
12
 
13
- type OpenAIChatCompletionsAdapterOptions = {
14
- compatibility?: boolean;
15
- maxTokensParameter?: OpenAIChatCompletionsCapabilities['maxTokensParameter'];
16
- };
17
-
18
- type OpenAIStructuredOutputMode = 'native' | 'tool';
19
-
20
- type OpenAIChatClient = {
21
- chat: OpenAI['chat'];
22
- };
23
- type OpenAIChatCompletionsModelOptions = OpenAIChatCompletionsAdapterOptions & {
24
- providerId?: string;
25
- nonStandardReasoning?: boolean;
26
- structuredOutputMode?: OpenAIStructuredOutputMode;
27
- };
28
- declare function createOpenAIChatCompletionsModel(client: OpenAIChatClient, modelId: string, modelOptions?: OpenAIChatCompletionsModelOptions): ChatModel;
13
+ type OpenAIStructuredOutputMode = 'json-schema' | 'tool' | 'json-object';
29
14
 
30
- type OpenAIProviderBaseOptions = {
31
- apiKey?: string;
32
- baseURL?: string;
33
- client?: OpenAI;
34
- };
35
- type OpenAIProvider = {
36
- chatModel(modelId: string): ChatModel;
37
- chat: OpenAIChatProvider;
38
- embeddingModel(modelId: string): EmbeddingModel;
39
- imageModel(modelId: string): ImageModel;
40
- };
41
- type OpenAIChatProvider = {
42
- chatModel(modelId: string): ChatModel;
15
+ type OpenAIReasoningCompatibilityOptions = {
16
+ requestField: 'reasoning_content' | 'reasoning';
17
+ providerMetadataKey?: string;
43
18
  };
44
19
  type OpenAICompatibilityOptions = {
45
- reasoning?: boolean;
46
- structuredOutputMode?: OpenAIChatCompletionsModelOptions['structuredOutputMode'];
47
- maxTokensParameter?: OpenAIChatCompletionsModelOptions['maxTokensParameter'];
20
+ reasoning?: boolean | OpenAIReasoningCompatibilityOptions;
21
+ structuredOutputMode?: OpenAIStructuredOutputMode;
22
+ maxTokensParameter?: OpenAIChatCompletionsCapabilities['maxTokensParameter'];
48
23
  };
49
24
  type OpenAICompatibility = boolean | OpenAICompatibilityOptions;
50
- type OpenAIProviderFactoryOptions = {
51
- providerId?: string;
52
- defaultApi?: 'responses' | 'chat-completions';
53
- compatibility?: OpenAICompatibility;
25
+ type OpenAIResolvedReasoningCompatibilityOptions = Required<OpenAIReasoningCompatibilityOptions>;
26
+ type OpenAIResolvedCompatibilityOptions = Pick<OpenAICompatibilityOptions, 'structuredOutputMode' | 'maxTokensParameter'> & {
27
+ reasoning: boolean | OpenAIResolvedReasoningCompatibilityOptions;
54
28
  };
55
- declare function createOpenAIProvider(options: OpenAIProviderBaseOptions, factoryOptions?: OpenAIProviderFactoryOptions): OpenAIProvider;
56
29
 
57
30
  declare const openaiResponsesGenerateProviderOptionsSchema: z.ZodObject<{
58
31
  store: z.ZodOptional<z.ZodBoolean>;
@@ -69,6 +42,7 @@ declare const openaiResponsesGenerateProviderOptionsSchema: z.ZodObject<{
69
42
  }, z.core.$strict>;
70
43
  type OpenAIResponsesGenerateProviderOptions = z.infer<typeof openaiResponsesGenerateProviderOptionsSchema>;
71
44
  declare const openaiChatGenerateProviderOptionsSchema: z.ZodObject<{
45
+ user: z.ZodOptional<z.ZodString>;
72
46
  store: z.ZodOptional<z.ZodBoolean>;
73
47
  serviceTier: z.ZodOptional<z.ZodEnum<{
74
48
  auto: "auto";
@@ -78,13 +52,16 @@ declare const openaiChatGenerateProviderOptionsSchema: z.ZodObject<{
78
52
  priority: "priority";
79
53
  }>>;
80
54
  parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
81
- user: z.ZodOptional<z.ZodString>;
82
55
  stopSequences: z.ZodOptional<z.ZodArray<z.ZodString>>;
83
56
  frequencyPenalty: z.ZodOptional<z.ZodNumber>;
84
57
  presencePenalty: z.ZodOptional<z.ZodNumber>;
85
58
  seed: z.ZodOptional<z.ZodNumber>;
86
59
  }, z.core.$strict>;
87
60
  type OpenAIChatGenerateProviderOptions = z.infer<typeof openaiChatGenerateProviderOptionsSchema>;
61
+ type OpenAIChatGenerateProviderOptionsConfig = {
62
+ key: string;
63
+ schema: z.ZodType<OpenAIChatGenerateProviderOptions>;
64
+ };
88
65
  declare const openaiEmbedProviderOptionsSchema: z.ZodObject<{
89
66
  encodingFormat: z.ZodOptional<z.ZodEnum<{
90
67
  float: "float";
@@ -154,6 +131,7 @@ declare const openaiResponsesProviderOptionsSchema: z.ZodObject<{
154
131
  }, z.core.$strict>;
155
132
  type OpenAIResponsesProviderOptions = OpenAIResponsesGenerateProviderOptions;
156
133
  declare const openaiCompatProviderOptionsSchema: z.ZodObject<{
134
+ user: z.ZodOptional<z.ZodString>;
157
135
  store: z.ZodOptional<z.ZodBoolean>;
158
136
  serviceTier: z.ZodOptional<z.ZodEnum<{
159
137
  auto: "auto";
@@ -163,13 +141,13 @@ declare const openaiCompatProviderOptionsSchema: z.ZodObject<{
163
141
  priority: "priority";
164
142
  }>>;
165
143
  parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
166
- user: z.ZodOptional<z.ZodString>;
167
144
  stopSequences: z.ZodOptional<z.ZodArray<z.ZodString>>;
168
145
  frequencyPenalty: z.ZodOptional<z.ZodNumber>;
169
146
  presencePenalty: z.ZodOptional<z.ZodNumber>;
170
147
  seed: z.ZodOptional<z.ZodNumber>;
171
148
  }, z.core.$strict>;
172
149
  declare const openaiCompatGenerateProviderOptionsSchema: z.ZodObject<{
150
+ user: z.ZodOptional<z.ZodString>;
173
151
  store: z.ZodOptional<z.ZodBoolean>;
174
152
  serviceTier: z.ZodOptional<z.ZodEnum<{
175
153
  auto: "auto";
@@ -179,7 +157,6 @@ declare const openaiCompatGenerateProviderOptionsSchema: z.ZodObject<{
179
157
  priority: "priority";
180
158
  }>>;
181
159
  parallelToolCalls: z.ZodOptional<z.ZodBoolean>;
182
- user: z.ZodOptional<z.ZodString>;
183
160
  stopSequences: z.ZodOptional<z.ZodArray<z.ZodString>>;
184
161
  frequencyPenalty: z.ZodOptional<z.ZodNumber>;
185
162
  presencePenalty: z.ZodOptional<z.ZodNumber>;
@@ -188,4 +165,48 @@ declare const openaiCompatGenerateProviderOptionsSchema: z.ZodObject<{
188
165
  type OpenAICompatGenerateProviderOptions = OpenAIChatGenerateProviderOptions;
189
166
  type OpenAICompatRequestOptions = OpenAIChatGenerateProviderOptions;
190
167
 
168
+ type OpenAIChatCompletionsAdapterOptions = {
169
+ capabilities?: ModelCapabilities;
170
+ compatibility?: boolean;
171
+ maxTokensParameter?: OpenAIChatCompletionsCapabilities['maxTokensParameter'];
172
+ providerId?: string;
173
+ providerOptions?: OpenAIChatGenerateProviderOptionsConfig;
174
+ reasoning?: OpenAIResolvedReasoningCompatibilityOptions;
175
+ };
176
+
177
+ type OpenAIChatClient = {
178
+ chat: OpenAI['chat'];
179
+ };
180
+ type OpenAIChatCompletionsModelOptions = {
181
+ capabilities: ModelCapabilities;
182
+ providerId?: string;
183
+ compatibility?: OpenAIResolvedCompatibilityOptions;
184
+ providerOptions?: OpenAIChatCompletionsAdapterOptions['providerOptions'];
185
+ };
186
+ declare function createOpenAIChatCompletionsModel(client: OpenAIChatClient, modelId: string, modelOptions: OpenAIChatCompletionsModelOptions): ChatModel;
187
+
188
+ type OpenAIProviderBaseOptions = {
189
+ apiKey?: string;
190
+ baseURL?: string;
191
+ client?: OpenAI;
192
+ };
193
+ type OpenAIProvider = {
194
+ chatModel(modelId: string): ChatModel;
195
+ chat: OpenAIChatProvider;
196
+ embeddingModel(modelId: string): EmbeddingModel;
197
+ imageModel(modelId: string): ImageModel;
198
+ };
199
+ type OpenAIChatProvider = {
200
+ chatModel(modelId: string): ChatModel;
201
+ };
202
+ type OpenAIProviderFactoryOptions = {
203
+ modelCapabilities?: ModelCapabilitiesRegistry;
204
+ providerId?: string;
205
+ providerOptionsKey?: string;
206
+ providerOptionsSchema?: OpenAIChatGenerateProviderOptionsConfig['schema'];
207
+ defaultApi?: 'responses' | 'chat-completions';
208
+ compatibility?: OpenAICompatibility;
209
+ };
210
+ declare function createOpenAIProvider(options: OpenAIProviderBaseOptions, factoryOptions?: OpenAIProviderFactoryOptions): OpenAIProvider;
211
+
191
212
  export { type OpenAIChatClient as O, type OpenAIProvider as a, type OpenAIProviderBaseOptions as b, type OpenAICompatGenerateProviderOptions as c, type OpenAICompatRequestOptions as d, openaiCompatProviderOptionsSchema as e, type OpenAIChatCompletionsModelOptions as f, type OpenAIChatGenerateProviderOptions as g, type OpenAIChatProvider as h, type OpenAICompatibility as i, type OpenAICompatibilityOptions as j, type OpenAIEmbedProviderOptions as k, type OpenAIImageProviderOptions as l, type OpenAIModelCapabilities as m, type OpenAIProviderFactoryOptions as n, openaiCompatGenerateProviderOptionsSchema as o, type OpenAIResponsesGenerateProviderOptions as p, type OpenAIResponsesProviderOptions as q, type OpenAIStructuredOutputMode as r, createOpenAIChatCompletionsModel as s, createOpenAIProvider as t, getOpenAIModelCapabilities as u, openaiChatGenerateProviderOptionsSchema as v, openaiEmbedProviderOptionsSchema as w, openaiImageProviderOptionsSchema as x, openaiResponsesGenerateProviderOptionsSchema as y, openaiResponsesProviderOptionsSchema as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/openai",
3
- "version": "0.16.0",
3
+ "version": "0.18.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.16.0",
53
+ "@core-ai/core-ai": "^0.18.0",
54
54
  "openai": "^6.46.0"
55
55
  },
56
56
  "peerDependencies": {