@core-ai/openai 0.7.0 → 0.8.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.
@@ -29,41 +29,53 @@ var openaiImageProviderOptionsSchema = z.object({
29
29
  style: z.enum(["vivid", "natural"]).optional(),
30
30
  user: z.string().optional()
31
31
  }).strict();
32
- function parseOpenAIResponsesGenerateProviderOptions(providerOptions) {
32
+ function parseOpenAIProviderOptions(providerOptions, schema) {
33
33
  const rawOptions = providerOptions?.openai;
34
34
  if (rawOptions === void 0) {
35
35
  return void 0;
36
36
  }
37
- return openaiResponsesGenerateProviderOptionsSchema.parse(rawOptions);
37
+ return schema.parse(rawOptions);
38
+ }
39
+ function parseOpenAIResponsesGenerateProviderOptions(providerOptions) {
40
+ return parseOpenAIProviderOptions(
41
+ providerOptions,
42
+ openaiResponsesGenerateProviderOptionsSchema
43
+ );
38
44
  }
39
45
  function parseOpenAICompatGenerateProviderOptions(providerOptions) {
40
- const rawOptions = providerOptions?.openai;
41
- if (rawOptions === void 0) {
42
- return void 0;
43
- }
44
- return openaiCompatGenerateProviderOptionsSchema.parse(rawOptions);
46
+ return parseOpenAIProviderOptions(
47
+ providerOptions,
48
+ openaiCompatGenerateProviderOptionsSchema
49
+ );
45
50
  }
46
51
  function parseOpenAIEmbedProviderOptions(providerOptions) {
47
- const rawOptions = providerOptions?.openai;
48
- if (rawOptions === void 0) {
49
- return void 0;
50
- }
51
- return openaiEmbedProviderOptionsSchema.parse(rawOptions);
52
+ return parseOpenAIProviderOptions(
53
+ providerOptions,
54
+ openaiEmbedProviderOptionsSchema
55
+ );
52
56
  }
53
57
  function parseOpenAIImageProviderOptions(providerOptions) {
54
- const rawOptions = providerOptions?.openai;
55
- if (rawOptions === void 0) {
56
- return void 0;
57
- }
58
- return openaiImageProviderOptionsSchema.parse(rawOptions);
58
+ return parseOpenAIProviderOptions(
59
+ providerOptions,
60
+ openaiImageProviderOptionsSchema
61
+ );
59
62
  }
60
63
  var openaiResponsesProviderOptionsSchema = openaiResponsesGenerateProviderOptionsSchema;
61
64
  var openaiCompatProviderOptionsSchema = openaiCompatGenerateProviderOptionsSchema;
62
65
 
66
+ // src/shared/provider-factory.ts
67
+ import OpenAI from "openai";
68
+
63
69
  // src/openai-error.ts
64
- import { APIError } from "openai";
65
- import { ProviderError } from "@core-ai/core-ai";
70
+ import { APIError, APIUserAbortError } from "openai";
71
+ import { AbortedError, ProviderError } from "@core-ai/core-ai";
72
+ function isOpenAIAbortError(error) {
73
+ return error instanceof APIUserAbortError || error instanceof Error && error.name === "AbortError";
74
+ }
66
75
  function wrapOpenAIError(error) {
76
+ if (isOpenAIAbortError(error)) {
77
+ return new AbortedError(error, "openai");
78
+ }
67
79
  if (error instanceof APIError) {
68
80
  return new ProviderError(error.message, "openai", error.status, error);
69
81
  }
@@ -160,6 +172,19 @@ function mapOpenAIImageProviderOptionsToRequestFields(options) {
160
172
  };
161
173
  }
162
174
 
175
+ // src/shared/provider-factory.ts
176
+ function createOpenAIProvider(options, createChatModel) {
177
+ const client = options.client ?? new OpenAI({
178
+ apiKey: options.apiKey,
179
+ baseURL: options.baseURL
180
+ });
181
+ return {
182
+ chatModel: (modelId) => createChatModel(client, modelId),
183
+ embeddingModel: (modelId) => createOpenAIEmbeddingModel(client, modelId),
184
+ imageModel: (modelId) => createOpenAIImageModel(client, modelId)
185
+ };
186
+ }
187
+
163
188
  // src/shared/tools.ts
164
189
  import { zodSchemaToJsonSchema } from "@core-ai/core-ai";
165
190
  var DEFAULT_STRUCTURED_OUTPUT_TOOL_NAME = "core_ai_generate_object";
@@ -212,7 +237,168 @@ function createStructuredOutputOptions(options) {
212
237
  };
213
238
  }
214
239
 
240
+ // src/shared/structured-output.ts
241
+ import {
242
+ StructuredOutputNoObjectGeneratedError,
243
+ StructuredOutputParseError,
244
+ StructuredOutputValidationError
245
+ } from "@core-ai/core-ai";
246
+ function extractStructuredObject(result, schema, provider, toolName) {
247
+ const structuredToolCall = result.toolCalls.find(
248
+ (toolCall) => toolCall.name === toolName
249
+ );
250
+ if (structuredToolCall) {
251
+ return validateStructuredToolArguments(
252
+ schema,
253
+ structuredToolCall.arguments,
254
+ provider
255
+ );
256
+ }
257
+ const rawOutput = result.content?.trim();
258
+ if (rawOutput && rawOutput.length > 0) {
259
+ return parseAndValidateStructuredPayload(schema, rawOutput, provider);
260
+ }
261
+ throw new StructuredOutputNoObjectGeneratedError(
262
+ "model did not emit a structured object payload",
263
+ provider
264
+ );
265
+ }
266
+ async function* transformStructuredOutputStream(stream, schema, provider, toolName) {
267
+ let validatedObject;
268
+ let contentBuffer = "";
269
+ const toolArgumentDeltas = /* @__PURE__ */ new Map();
270
+ for await (const event of stream) {
271
+ if (event.type === "text-delta") {
272
+ contentBuffer += event.text;
273
+ yield {
274
+ type: "object-delta",
275
+ text: event.text
276
+ };
277
+ continue;
278
+ }
279
+ if (event.type === "tool-call-delta") {
280
+ const previous = toolArgumentDeltas.get(event.toolCallId) ?? "";
281
+ toolArgumentDeltas.set(
282
+ event.toolCallId,
283
+ `${previous}${event.argumentsDelta}`
284
+ );
285
+ yield {
286
+ type: "object-delta",
287
+ text: event.argumentsDelta
288
+ };
289
+ continue;
290
+ }
291
+ if (event.type === "tool-call-end" && event.toolCall.name === toolName) {
292
+ validatedObject = validateStructuredToolArguments(
293
+ schema,
294
+ event.toolCall.arguments,
295
+ provider
296
+ );
297
+ yield {
298
+ type: "object",
299
+ object: validatedObject
300
+ };
301
+ continue;
302
+ }
303
+ if (event.type === "finish") {
304
+ if (validatedObject === void 0) {
305
+ const fallbackPayload = getFallbackStructuredPayload(
306
+ contentBuffer,
307
+ toolArgumentDeltas
308
+ );
309
+ if (!fallbackPayload) {
310
+ throw new StructuredOutputNoObjectGeneratedError(
311
+ "structured output stream ended without an object payload",
312
+ provider
313
+ );
314
+ }
315
+ validatedObject = parseAndValidateStructuredPayload(
316
+ schema,
317
+ fallbackPayload,
318
+ provider
319
+ );
320
+ yield {
321
+ type: "object",
322
+ object: validatedObject
323
+ };
324
+ }
325
+ yield {
326
+ type: "finish",
327
+ finishReason: event.finishReason,
328
+ usage: event.usage
329
+ };
330
+ }
331
+ }
332
+ }
333
+ function getFallbackStructuredPayload(contentBuffer, toolArgumentDeltas) {
334
+ for (const delta of toolArgumentDeltas.values()) {
335
+ const trimmed = delta.trim();
336
+ if (trimmed.length > 0) {
337
+ return trimmed;
338
+ }
339
+ }
340
+ const trimmedContent = contentBuffer.trim();
341
+ if (trimmedContent.length > 0) {
342
+ return trimmedContent;
343
+ }
344
+ return void 0;
345
+ }
346
+ function validateStructuredToolArguments(schema, toolArguments, provider) {
347
+ return validateStructuredObject(
348
+ schema,
349
+ toolArguments,
350
+ provider,
351
+ JSON.stringify(toolArguments)
352
+ );
353
+ }
354
+ function parseAndValidateStructuredPayload(schema, rawPayload, provider) {
355
+ const parsedPayload = parseJson(rawPayload, provider);
356
+ return validateStructuredObject(
357
+ schema,
358
+ parsedPayload,
359
+ provider,
360
+ rawPayload
361
+ );
362
+ }
363
+ function parseJson(rawOutput, provider) {
364
+ try {
365
+ return JSON.parse(rawOutput);
366
+ } catch (error) {
367
+ throw new StructuredOutputParseError(
368
+ "failed to parse structured output as JSON",
369
+ provider,
370
+ {
371
+ rawOutput,
372
+ cause: error
373
+ }
374
+ );
375
+ }
376
+ }
377
+ function validateStructuredObject(schema, value, provider, rawOutput) {
378
+ const parsed = schema.safeParse(value);
379
+ if (parsed.success) {
380
+ return parsed.data;
381
+ }
382
+ throw new StructuredOutputValidationError(
383
+ "structured output does not match schema",
384
+ provider,
385
+ formatZodIssues(parsed.error.issues),
386
+ {
387
+ rawOutput
388
+ }
389
+ );
390
+ }
391
+ function formatZodIssues(issues) {
392
+ return issues.map((issue) => {
393
+ const path = issue.path.length > 0 ? issue.path.map((segment) => String(segment)).join(".") : "<root>";
394
+ return `${path}: ${issue.message}`;
395
+ });
396
+ }
397
+
215
398
  // src/model-capabilities.ts
399
+ import {
400
+ stripModelDateSuffix
401
+ } from "@core-ai/core-ai";
216
402
  var DEFAULT_CAPABILITIES = {
217
403
  reasoning: {
218
404
  supportsEffort: true,
@@ -220,42 +406,33 @@ var DEFAULT_CAPABILITIES = {
220
406
  restrictsSamplingParams: false
221
407
  }
222
408
  };
409
+ var GPT_5_MAX_REASONING_CAPABILITIES = {
410
+ reasoning: {
411
+ supportsEffort: true,
412
+ supportedRange: ["low", "medium", "high", "max"],
413
+ restrictsSamplingParams: true
414
+ }
415
+ };
416
+ var GPT_5_MINIMAL_REASONING_CAPABILITIES = {
417
+ reasoning: {
418
+ supportsEffort: true,
419
+ supportedRange: ["minimal", "low", "medium", "high"],
420
+ restrictsSamplingParams: true
421
+ }
422
+ };
423
+ var NO_REASONING_EFFORT_CAPABILITIES = {
424
+ reasoning: {
425
+ supportsEffort: false,
426
+ supportedRange: [],
427
+ restrictsSamplingParams: false
428
+ }
429
+ };
223
430
  var MODEL_CAPABILITIES = {
224
- "gpt-5.4": {
225
- reasoning: {
226
- supportsEffort: true,
227
- supportedRange: ["low", "medium", "high", "max"],
228
- restrictsSamplingParams: true
229
- }
230
- },
231
- "gpt-5.4-pro": {
232
- reasoning: {
233
- supportsEffort: true,
234
- supportedRange: ["low", "medium", "high", "max"],
235
- restrictsSamplingParams: true
236
- }
237
- },
238
- "gpt-5.2": {
239
- reasoning: {
240
- supportsEffort: true,
241
- supportedRange: ["low", "medium", "high", "max"],
242
- restrictsSamplingParams: true
243
- }
244
- },
245
- "gpt-5.2-codex": {
246
- reasoning: {
247
- supportsEffort: true,
248
- supportedRange: ["low", "medium", "high", "max"],
249
- restrictsSamplingParams: true
250
- }
251
- },
252
- "gpt-5.2-pro": {
253
- reasoning: {
254
- supportsEffort: true,
255
- supportedRange: ["low", "medium", "high", "max"],
256
- restrictsSamplingParams: true
257
- }
258
- },
431
+ "gpt-5.4": GPT_5_MAX_REASONING_CAPABILITIES,
432
+ "gpt-5.4-pro": GPT_5_MAX_REASONING_CAPABILITIES,
433
+ "gpt-5.2": GPT_5_MAX_REASONING_CAPABILITIES,
434
+ "gpt-5.2-codex": GPT_5_MAX_REASONING_CAPABILITIES,
435
+ "gpt-5.2-pro": GPT_5_MAX_REASONING_CAPABILITIES,
259
436
  "gpt-5.1": {
260
437
  reasoning: {
261
438
  supportsEffort: true,
@@ -263,27 +440,9 @@ var MODEL_CAPABILITIES = {
263
440
  restrictsSamplingParams: true
264
441
  }
265
442
  },
266
- "gpt-5": {
267
- reasoning: {
268
- supportsEffort: true,
269
- supportedRange: ["minimal", "low", "medium", "high"],
270
- restrictsSamplingParams: true
271
- }
272
- },
273
- "gpt-5-mini": {
274
- reasoning: {
275
- supportsEffort: true,
276
- supportedRange: ["minimal", "low", "medium", "high"],
277
- restrictsSamplingParams: true
278
- }
279
- },
280
- "gpt-5-nano": {
281
- reasoning: {
282
- supportsEffort: true,
283
- supportedRange: ["minimal", "low", "medium", "high"],
284
- restrictsSamplingParams: true
285
- }
286
- },
443
+ "gpt-5": GPT_5_MINIMAL_REASONING_CAPABILITIES,
444
+ "gpt-5-mini": GPT_5_MINIMAL_REASONING_CAPABILITIES,
445
+ "gpt-5-nano": GPT_5_MINIMAL_REASONING_CAPABILITIES,
287
446
  o3: {
288
447
  reasoning: {
289
448
  supportsEffort: true,
@@ -312,13 +471,7 @@ var MODEL_CAPABILITIES = {
312
471
  restrictsSamplingParams: false
313
472
  }
314
473
  },
315
- "o1-mini": {
316
- reasoning: {
317
- supportsEffort: false,
318
- supportedRange: [],
319
- restrictsSamplingParams: false
320
- }
321
- }
474
+ "o1-mini": NO_REASONING_EFFORT_CAPABILITIES
322
475
  };
323
476
  var EFFORT_RANK = {
324
477
  minimal: 0,
@@ -327,12 +480,19 @@ var EFFORT_RANK = {
327
480
  high: 3,
328
481
  max: 4
329
482
  };
483
+ var OPENAI_REASONING_EFFORT_MAP = {
484
+ minimal: "minimal",
485
+ low: "low",
486
+ medium: "medium",
487
+ high: "high",
488
+ max: "xhigh"
489
+ };
330
490
  function getOpenAIModelCapabilities(modelId) {
331
491
  const normalizedModelId = normalizeModelId(modelId);
332
492
  return MODEL_CAPABILITIES[normalizedModelId] ?? DEFAULT_CAPABILITIES;
333
493
  }
334
494
  function normalizeModelId(modelId) {
335
- return modelId.replace(/-\d{8}$/, "");
495
+ return stripModelDateSuffix(modelId);
336
496
  }
337
497
  function clampReasoningEffort(effort, supportedRange) {
338
498
  if (supportedRange.length === 0 || supportedRange.includes(effort)) {
@@ -351,14 +511,11 @@ function clampReasoningEffort(effort, supportedRange) {
351
511
  return best;
352
512
  }
353
513
  function toOpenAIReasoningEffort(effort) {
354
- if (effort === "max") {
355
- return "xhigh";
356
- }
357
- return effort;
514
+ return OPENAI_REASONING_EFFORT_MAP[effort];
358
515
  }
359
516
 
360
517
  // src/shared/utils.ts
361
- import { ProviderError as ProviderError2 } from "@core-ai/core-ai";
518
+ import { ValidationError } from "@core-ai/core-ai";
362
519
  function safeParseJsonObject(json) {
363
520
  try {
364
521
  const parsed = JSON.parse(json);
@@ -378,15 +535,17 @@ function validateOpenAIReasoningConfig(modelId, options) {
378
535
  if (!capabilities.reasoning.restrictsSamplingParams) {
379
536
  return;
380
537
  }
381
- if (options.temperature !== void 0) {
382
- throw new ProviderError2(
383
- `OpenAI model "${modelId}" does not support temperature when reasoning is enabled`,
384
- "openai"
385
- );
386
- }
387
- if (options.topP !== void 0) {
388
- throw new ProviderError2(
389
- `OpenAI model "${modelId}" does not support topP when reasoning is enabled`,
538
+ const restrictedSamplingParams = [
539
+ { name: "temperature", value: options.temperature },
540
+ { name: "topP", value: options.topP }
541
+ ];
542
+ for (const { name, value } of restrictedSamplingParams) {
543
+ if (value === void 0) {
544
+ continue;
545
+ }
546
+ throw new ValidationError(
547
+ `OpenAI model "${modelId}" does not support ${name} when reasoning is enabled`,
548
+ void 0,
390
549
  "openai"
391
550
  );
392
551
  }
@@ -411,6 +570,7 @@ export {
411
570
  openaiResponsesProviderOptionsSchema,
412
571
  openaiCompatProviderOptionsSchema,
413
572
  wrapOpenAIError,
414
- createOpenAIEmbeddingModel,
415
- createOpenAIImageModel
573
+ extractStructuredObject,
574
+ transformStructuredOutputStream,
575
+ createOpenAIProvider
416
576
  };
package/dist/compat.d.ts CHANGED
@@ -1,18 +1,11 @@
1
- import OpenAI from 'openai';
2
- import { ChatModel, EmbeddingModel, ImageModel } from '@core-ai/core-ai';
3
- export { O as OpenAICompatGenerateProviderOptions, a as OpenAICompatRequestOptions, o as openaiCompatGenerateProviderOptionsSchema, b as openaiCompatProviderOptionsSchema } from './provider-options-l7CmAA94.js';
1
+ import { O as OpenAIProvider, a as OpenAIProviderBaseOptions } from './provider-options-DzqvHoId.js';
2
+ export { b as OpenAICompatGenerateProviderOptions, c as OpenAICompatRequestOptions, o as openaiCompatGenerateProviderOptionsSchema, d as openaiCompatProviderOptionsSchema } from './provider-options-DzqvHoId.js';
3
+ import 'openai';
4
+ import '@core-ai/core-ai';
4
5
  import 'zod';
5
6
 
6
- type OpenAICompatProviderOptions = {
7
- apiKey?: string;
8
- baseURL?: string;
9
- client?: OpenAI;
10
- };
11
- type OpenAICompatProvider = {
12
- chatModel(modelId: string): ChatModel;
13
- embeddingModel(modelId: string): EmbeddingModel;
14
- imageModel(modelId: string): ImageModel;
15
- };
7
+ type OpenAICompatProviderOptions = OpenAIProviderBaseOptions;
8
+ type OpenAICompatProvider = OpenAIProvider;
16
9
  declare function createOpenAICompat(options?: OpenAICompatProviderOptions): OpenAICompatProvider;
17
10
 
18
11
  export { type OpenAICompatProvider, type OpenAICompatProviderOptions, createOpenAICompat };
package/dist/compat.js CHANGED
@@ -2,9 +2,9 @@ import {
2
2
  clampReasoningEffort,
3
3
  convertToolChoice,
4
4
  convertTools,
5
- createOpenAIEmbeddingModel,
6
- createOpenAIImageModel,
5
+ createOpenAIProvider,
7
6
  createStructuredOutputOptions,
7
+ extractStructuredObject,
8
8
  getOpenAIModelCapabilities,
9
9
  getStructuredOutputToolName,
10
10
  openaiCompatGenerateProviderOptionsSchema,
@@ -12,21 +12,13 @@ import {
12
12
  parseOpenAICompatGenerateProviderOptions,
13
13
  safeParseJsonObject,
14
14
  toOpenAIReasoningEffort,
15
+ transformStructuredOutputStream,
15
16
  validateOpenAIReasoningConfig,
16
17
  wrapOpenAIError
17
- } from "./chunk-T4N4CRQS.js";
18
-
19
- // src/compat/provider.ts
20
- import OpenAI from "openai";
18
+ } from "./chunk-6CVAAVYM.js";
21
19
 
22
20
  // src/compat/chat-model.ts
23
- import {
24
- StructuredOutputNoObjectGeneratedError,
25
- StructuredOutputParseError,
26
- StructuredOutputValidationError,
27
- createObjectStream,
28
- createChatStream
29
- } from "@core-ai/core-ai";
21
+ import { createObjectStream, createChatStream } from "@core-ai/core-ai";
30
22
 
31
23
  // src/compat/chat-adapter.ts
32
24
  function convertMessages(messages) {
@@ -441,169 +433,10 @@ function createOpenAICompatChatModel(client, modelId) {
441
433
  }
442
434
  };
443
435
  }
444
- function extractStructuredObject(result, schema, provider, toolName) {
445
- const structuredToolCall = result.toolCalls.find(
446
- (toolCall) => toolCall.name === toolName
447
- );
448
- if (structuredToolCall) {
449
- return validateStructuredToolArguments(
450
- schema,
451
- structuredToolCall.arguments,
452
- provider
453
- );
454
- }
455
- const rawOutput = result.content?.trim();
456
- if (rawOutput && rawOutput.length > 0) {
457
- return parseAndValidateStructuredPayload(schema, rawOutput, provider);
458
- }
459
- throw new StructuredOutputNoObjectGeneratedError(
460
- "model did not emit a structured object payload",
461
- provider
462
- );
463
- }
464
- async function* transformStructuredOutputStream(stream, schema, provider, toolName) {
465
- let validatedObject;
466
- let contentBuffer = "";
467
- const toolArgumentDeltas = /* @__PURE__ */ new Map();
468
- for await (const event of stream) {
469
- if (event.type === "text-delta") {
470
- contentBuffer += event.text;
471
- yield {
472
- type: "object-delta",
473
- text: event.text
474
- };
475
- continue;
476
- }
477
- if (event.type === "tool-call-delta") {
478
- const previous = toolArgumentDeltas.get(event.toolCallId) ?? "";
479
- toolArgumentDeltas.set(
480
- event.toolCallId,
481
- `${previous}${event.argumentsDelta}`
482
- );
483
- yield {
484
- type: "object-delta",
485
- text: event.argumentsDelta
486
- };
487
- continue;
488
- }
489
- if (event.type === "tool-call-end" && event.toolCall.name === toolName) {
490
- validatedObject = validateStructuredToolArguments(
491
- schema,
492
- event.toolCall.arguments,
493
- provider
494
- );
495
- yield {
496
- type: "object",
497
- object: validatedObject
498
- };
499
- continue;
500
- }
501
- if (event.type === "finish") {
502
- if (validatedObject === void 0) {
503
- const fallbackPayload = getFallbackStructuredPayload(
504
- contentBuffer,
505
- toolArgumentDeltas
506
- );
507
- if (!fallbackPayload) {
508
- throw new StructuredOutputNoObjectGeneratedError(
509
- "structured output stream ended without an object payload",
510
- provider
511
- );
512
- }
513
- validatedObject = parseAndValidateStructuredPayload(
514
- schema,
515
- fallbackPayload,
516
- provider
517
- );
518
- yield {
519
- type: "object",
520
- object: validatedObject
521
- };
522
- }
523
- yield {
524
- type: "finish",
525
- finishReason: event.finishReason,
526
- usage: event.usage
527
- };
528
- }
529
- }
530
- }
531
- function getFallbackStructuredPayload(contentBuffer, toolArgumentDeltas) {
532
- for (const delta of toolArgumentDeltas.values()) {
533
- const trimmed = delta.trim();
534
- if (trimmed.length > 0) {
535
- return trimmed;
536
- }
537
- }
538
- const trimmedContent = contentBuffer.trim();
539
- if (trimmedContent.length > 0) {
540
- return trimmedContent;
541
- }
542
- return void 0;
543
- }
544
- function validateStructuredToolArguments(schema, toolArguments, provider) {
545
- return validateStructuredObject(
546
- schema,
547
- toolArguments,
548
- provider,
549
- JSON.stringify(toolArguments)
550
- );
551
- }
552
- function parseAndValidateStructuredPayload(schema, rawPayload, provider) {
553
- const parsedPayload = parseJson(rawPayload, provider);
554
- return validateStructuredObject(
555
- schema,
556
- parsedPayload,
557
- provider,
558
- rawPayload
559
- );
560
- }
561
- function parseJson(rawOutput, provider) {
562
- try {
563
- return JSON.parse(rawOutput);
564
- } catch (error) {
565
- throw new StructuredOutputParseError(
566
- "failed to parse structured output as JSON",
567
- provider,
568
- {
569
- rawOutput,
570
- cause: error
571
- }
572
- );
573
- }
574
- }
575
- function validateStructuredObject(schema, value, provider, rawOutput) {
576
- const parsed = schema.safeParse(value);
577
- if (parsed.success) {
578
- return parsed.data;
579
- }
580
- throw new StructuredOutputValidationError(
581
- "structured output does not match schema",
582
- provider,
583
- formatZodIssues(parsed.error.issues),
584
- {
585
- rawOutput
586
- }
587
- );
588
- }
589
- function formatZodIssues(issues) {
590
- return issues.map((issue) => {
591
- const path = issue.path.length > 0 ? issue.path.map((segment) => String(segment)).join(".") : "<root>";
592
- return `${path}: ${issue.message}`;
593
- });
594
- }
595
436
 
596
437
  // src/compat/provider.ts
597
438
  function createOpenAICompat(options = {}) {
598
- const client = options.client ?? new OpenAI({
599
- apiKey: options.apiKey,
600
- baseURL: options.baseURL
601
- });
602
- return {
603
- chatModel: (modelId) => createOpenAICompatChatModel(client, modelId),
604
- embeddingModel: (modelId) => createOpenAIEmbeddingModel(client, modelId),
605
- imageModel: (modelId) => createOpenAIImageModel(client, modelId)
606
- };
439
+ return createOpenAIProvider(options, createOpenAICompatChatModel);
607
440
  }
608
441
  export {
609
442
  createOpenAICompat,
package/dist/index.d.ts CHANGED
@@ -1,18 +1,11 @@
1
- import OpenAI from 'openai';
2
- import { ChatModel, EmbeddingModel, ImageModel } from '@core-ai/core-ai';
3
- export { O as OpenAICompatGenerateProviderOptions, a as OpenAICompatRequestOptions, c as OpenAIEmbedProviderOptions, d as OpenAIImageProviderOptions, e as OpenAIResponsesGenerateProviderOptions, f as OpenAIResponsesProviderOptions, o as openaiCompatGenerateProviderOptionsSchema, b as openaiCompatProviderOptionsSchema, g as openaiEmbedProviderOptionsSchema, h as openaiImageProviderOptionsSchema, i as openaiResponsesGenerateProviderOptionsSchema, j as openaiResponsesProviderOptionsSchema } from './provider-options-l7CmAA94.js';
1
+ import { O as OpenAIProvider$1, a as OpenAIProviderBaseOptions } from './provider-options-DzqvHoId.js';
2
+ export { b as OpenAICompatGenerateProviderOptions, c as OpenAICompatRequestOptions, e as OpenAIEmbedProviderOptions, f as OpenAIImageProviderOptions, g as OpenAIResponsesGenerateProviderOptions, h as OpenAIResponsesProviderOptions, o as openaiCompatGenerateProviderOptionsSchema, d as openaiCompatProviderOptionsSchema, i as openaiEmbedProviderOptionsSchema, j as openaiImageProviderOptionsSchema, k as openaiResponsesGenerateProviderOptionsSchema, l as openaiResponsesProviderOptionsSchema } from './provider-options-DzqvHoId.js';
3
+ import 'openai';
4
+ import '@core-ai/core-ai';
4
5
  import 'zod';
5
6
 
6
- type OpenAIProviderOptions = {
7
- apiKey?: string;
8
- baseURL?: string;
9
- client?: OpenAI;
10
- };
11
- type OpenAIProvider = {
12
- chatModel(modelId: string): ChatModel;
13
- embeddingModel(modelId: string): EmbeddingModel;
14
- imageModel(modelId: string): ImageModel;
15
- };
7
+ type OpenAIProviderOptions = OpenAIProviderBaseOptions;
8
+ type OpenAIProvider = OpenAIProvider$1;
16
9
  declare function createOpenAI(options?: OpenAIProviderOptions): OpenAIProvider;
17
10
 
18
11
  type OpenAIReasoningMetadata = {
package/dist/index.js CHANGED
@@ -2,9 +2,9 @@ import {
2
2
  clampReasoningEffort,
3
3
  convertToolChoice,
4
4
  convertTools,
5
- createOpenAIEmbeddingModel,
6
- createOpenAIImageModel,
5
+ createOpenAIProvider,
7
6
  createStructuredOutputOptions,
7
+ extractStructuredObject,
8
8
  getOpenAIModelCapabilities,
9
9
  getStructuredOutputToolName,
10
10
  openaiCompatGenerateProviderOptionsSchema,
@@ -16,21 +16,13 @@ import {
16
16
  parseOpenAIResponsesGenerateProviderOptions,
17
17
  safeParseJsonObject,
18
18
  toOpenAIReasoningEffort,
19
+ transformStructuredOutputStream,
19
20
  validateOpenAIReasoningConfig,
20
21
  wrapOpenAIError
21
- } from "./chunk-T4N4CRQS.js";
22
-
23
- // src/provider.ts
24
- import OpenAI from "openai";
22
+ } from "./chunk-6CVAAVYM.js";
25
23
 
26
24
  // src/chat-model.ts
27
- import {
28
- StructuredOutputNoObjectGeneratedError,
29
- StructuredOutputParseError,
30
- StructuredOutputValidationError,
31
- createObjectStream,
32
- createChatStream
33
- } from "@core-ai/core-ai";
25
+ import { createObjectStream, createChatStream } from "@core-ai/core-ai";
34
26
 
35
27
  // src/chat-adapter.ts
36
28
  import { getProviderMetadata } from "@core-ai/core-ai";
@@ -377,14 +369,26 @@ async function* transformStream(stream) {
377
369
  bufferedToolCalls.set(outputIndex, nextToolCall);
378
370
  return nextToolCall;
379
371
  };
372
+ const getNextReasoningStartEvent = () => {
373
+ const transition = getReasoningStartTransition(reasoningStarted);
374
+ reasoningStarted = transition.nextReasoningStarted;
375
+ return transition.event;
376
+ };
377
+ const getNextReasoningEndEvent = (providerMetadata) => {
378
+ const transition = getReasoningEndTransition(
379
+ reasoningStarted,
380
+ providerMetadata
381
+ );
382
+ reasoningStarted = transition.nextReasoningStarted;
383
+ return transition.event;
384
+ };
380
385
  for await (const event of stream) {
381
386
  if (event.type === "response.reasoning_summary_text.delta") {
382
387
  seenSummaryDeltas.add(`${event.item_id}:${event.summary_index}`);
383
388
  emittedReasoningItems.add(event.item_id);
384
- const reasoningStartTransition = getReasoningStartTransition(reasoningStarted);
385
- reasoningStarted = reasoningStartTransition.nextReasoningStarted;
386
- if (reasoningStartTransition.event) {
387
- yield reasoningStartTransition.event;
389
+ const reasoningStartEvent = getNextReasoningStartEvent();
390
+ if (reasoningStartEvent) {
391
+ yield reasoningStartEvent;
388
392
  }
389
393
  yield {
390
394
  type: "reasoning-delta",
@@ -396,10 +400,9 @@ async function* transformStream(stream) {
396
400
  const key = `${event.item_id}:${event.summary_index}`;
397
401
  if (!seenSummaryDeltas.has(key) && event.text.length > 0) {
398
402
  emittedReasoningItems.add(event.item_id);
399
- const reasoningStartTransition = getReasoningStartTransition(reasoningStarted);
400
- reasoningStarted = reasoningStartTransition.nextReasoningStarted;
401
- if (reasoningStartTransition.event) {
402
- yield reasoningStartTransition.event;
403
+ const reasoningStartEvent = getNextReasoningStartEvent();
404
+ if (reasoningStartEvent) {
405
+ yield reasoningStartEvent;
403
406
  }
404
407
  yield {
405
408
  type: "reasoning-delta",
@@ -473,10 +476,9 @@ async function* transformStream(stream) {
473
476
  event.item.summary
474
477
  );
475
478
  if (summaryText.length > 0) {
476
- const reasoningStartTransition = getReasoningStartTransition(reasoningStarted);
477
- reasoningStarted = reasoningStartTransition.nextReasoningStarted;
478
- if (reasoningStartTransition.event) {
479
- yield reasoningStartTransition.event;
479
+ const reasoningStartEvent = getNextReasoningStartEvent();
480
+ if (reasoningStartEvent) {
481
+ yield reasoningStartEvent;
480
482
  }
481
483
  yield {
482
484
  type: "reasoning-delta",
@@ -486,23 +488,20 @@ async function* transformStream(stream) {
486
488
  }
487
489
  const encryptedContent = typeof event.item.encrypted_content === "string" && event.item.encrypted_content.length > 0 ? event.item.encrypted_content : void 0;
488
490
  if (encryptedContent) {
489
- const reasoningStartTransition = getReasoningStartTransition(reasoningStarted);
490
- reasoningStarted = reasoningStartTransition.nextReasoningStarted;
491
- if (reasoningStartTransition.event) {
492
- yield reasoningStartTransition.event;
491
+ const reasoningStartEvent = getNextReasoningStartEvent();
492
+ if (reasoningStartEvent) {
493
+ yield reasoningStartEvent;
493
494
  }
494
495
  }
495
- const reasoningEndTransition2 = getReasoningEndTransition(
496
- reasoningStarted,
496
+ const reasoningEndEvent2 = getNextReasoningEndEvent(
497
497
  {
498
498
  openai: {
499
499
  ...encryptedContent ? { encryptedContent } : {}
500
500
  }
501
501
  }
502
502
  );
503
- reasoningStarted = reasoningEndTransition2.nextReasoningStarted;
504
- if (reasoningEndTransition2.event) {
505
- yield reasoningEndTransition2.event;
503
+ if (reasoningEndEvent2) {
504
+ yield reasoningEndEvent2;
506
505
  }
507
506
  continue;
508
507
  }
@@ -537,13 +536,9 @@ async function* transformStream(stream) {
537
536
  }
538
537
  if (event.type === "response.completed") {
539
538
  latestResponse = event.response;
540
- const reasoningEndTransition2 = getReasoningEndTransition(
541
- reasoningStarted,
542
- { openai: {} }
543
- );
544
- reasoningStarted = reasoningEndTransition2.nextReasoningStarted;
545
- if (reasoningEndTransition2.event) {
546
- yield reasoningEndTransition2.event;
539
+ const reasoningEndEvent2 = getNextReasoningEndEvent({ openai: {} });
540
+ if (reasoningEndEvent2) {
541
+ yield reasoningEndEvent2;
547
542
  }
548
543
  for (const bufferedToolCall of bufferedToolCalls.values()) {
549
544
  if (emittedToolCalls.has(bufferedToolCall.id)) {
@@ -570,12 +565,11 @@ async function* transformStream(stream) {
570
565
  return;
571
566
  }
572
567
  }
573
- const reasoningEndTransition = getReasoningEndTransition(reasoningStarted, {
568
+ const reasoningEndEvent = getNextReasoningEndEvent({
574
569
  openai: {}
575
570
  });
576
- reasoningStarted = reasoningEndTransition.nextReasoningStarted;
577
- if (reasoningEndTransition.event) {
578
- yield reasoningEndTransition.event;
571
+ if (reasoningEndEvent) {
572
+ yield reasoningEndEvent;
579
573
  }
580
574
  const hasToolCalls = bufferedToolCalls.size > 0;
581
575
  const usage = latestResponse ? mapUsage(latestResponse.usage) : mapUsage(void 0);
@@ -682,169 +676,10 @@ function createOpenAIChatModel(client, modelId) {
682
676
  }
683
677
  };
684
678
  }
685
- function extractStructuredObject(result, schema, provider, toolName) {
686
- const structuredToolCall = result.toolCalls.find(
687
- (toolCall) => toolCall.name === toolName
688
- );
689
- if (structuredToolCall) {
690
- return validateStructuredToolArguments(
691
- schema,
692
- structuredToolCall.arguments,
693
- provider
694
- );
695
- }
696
- const rawOutput = result.content?.trim();
697
- if (rawOutput && rawOutput.length > 0) {
698
- return parseAndValidateStructuredPayload(schema, rawOutput, provider);
699
- }
700
- throw new StructuredOutputNoObjectGeneratedError(
701
- "model did not emit a structured object payload",
702
- provider
703
- );
704
- }
705
- async function* transformStructuredOutputStream(stream, schema, provider, toolName) {
706
- let validatedObject;
707
- let contentBuffer = "";
708
- const toolArgumentDeltas = /* @__PURE__ */ new Map();
709
- for await (const event of stream) {
710
- if (event.type === "text-delta") {
711
- contentBuffer += event.text;
712
- yield {
713
- type: "object-delta",
714
- text: event.text
715
- };
716
- continue;
717
- }
718
- if (event.type === "tool-call-delta") {
719
- const previous = toolArgumentDeltas.get(event.toolCallId) ?? "";
720
- toolArgumentDeltas.set(
721
- event.toolCallId,
722
- `${previous}${event.argumentsDelta}`
723
- );
724
- yield {
725
- type: "object-delta",
726
- text: event.argumentsDelta
727
- };
728
- continue;
729
- }
730
- if (event.type === "tool-call-end" && event.toolCall.name === toolName) {
731
- validatedObject = validateStructuredToolArguments(
732
- schema,
733
- event.toolCall.arguments,
734
- provider
735
- );
736
- yield {
737
- type: "object",
738
- object: validatedObject
739
- };
740
- continue;
741
- }
742
- if (event.type === "finish") {
743
- if (validatedObject === void 0) {
744
- const fallbackPayload = getFallbackStructuredPayload(
745
- contentBuffer,
746
- toolArgumentDeltas
747
- );
748
- if (!fallbackPayload) {
749
- throw new StructuredOutputNoObjectGeneratedError(
750
- "structured output stream ended without an object payload",
751
- provider
752
- );
753
- }
754
- validatedObject = parseAndValidateStructuredPayload(
755
- schema,
756
- fallbackPayload,
757
- provider
758
- );
759
- yield {
760
- type: "object",
761
- object: validatedObject
762
- };
763
- }
764
- yield {
765
- type: "finish",
766
- finishReason: event.finishReason,
767
- usage: event.usage
768
- };
769
- }
770
- }
771
- }
772
- function getFallbackStructuredPayload(contentBuffer, toolArgumentDeltas) {
773
- for (const delta of toolArgumentDeltas.values()) {
774
- const trimmed = delta.trim();
775
- if (trimmed.length > 0) {
776
- return trimmed;
777
- }
778
- }
779
- const trimmedContent = contentBuffer.trim();
780
- if (trimmedContent.length > 0) {
781
- return trimmedContent;
782
- }
783
- return void 0;
784
- }
785
- function validateStructuredToolArguments(schema, toolArguments, provider) {
786
- return validateStructuredObject(
787
- schema,
788
- toolArguments,
789
- provider,
790
- JSON.stringify(toolArguments)
791
- );
792
- }
793
- function parseAndValidateStructuredPayload(schema, rawPayload, provider) {
794
- const parsedPayload = parseJson(rawPayload, provider);
795
- return validateStructuredObject(
796
- schema,
797
- parsedPayload,
798
- provider,
799
- rawPayload
800
- );
801
- }
802
- function parseJson(rawOutput, provider) {
803
- try {
804
- return JSON.parse(rawOutput);
805
- } catch (error) {
806
- throw new StructuredOutputParseError(
807
- "failed to parse structured output as JSON",
808
- provider,
809
- {
810
- rawOutput,
811
- cause: error
812
- }
813
- );
814
- }
815
- }
816
- function validateStructuredObject(schema, value, provider, rawOutput) {
817
- const parsed = schema.safeParse(value);
818
- if (parsed.success) {
819
- return parsed.data;
820
- }
821
- throw new StructuredOutputValidationError(
822
- "structured output does not match schema",
823
- provider,
824
- formatZodIssues(parsed.error.issues),
825
- {
826
- rawOutput
827
- }
828
- );
829
- }
830
- function formatZodIssues(issues) {
831
- return issues.map((issue) => {
832
- const path = issue.path.length > 0 ? issue.path.map((segment) => String(segment)).join(".") : "<root>";
833
- return `${path}: ${issue.message}`;
834
- });
835
- }
836
679
 
837
680
  // src/provider.ts
838
681
  function createOpenAI(options = {}) {
839
- const client = options.client ?? new OpenAI({
840
- apiKey: options.apiKey,
841
- baseURL: options.baseURL
842
- });
843
- return {
844
- chatModel: (modelId) => createOpenAIChatModel(client, modelId),
845
- embeddingModel: (modelId) => createOpenAIEmbeddingModel(client, modelId),
846
- imageModel: (modelId) => createOpenAIImageModel(client, modelId)
847
- };
682
+ return createOpenAIProvider(options, createOpenAIChatModel);
848
683
  }
849
684
  export {
850
685
  createOpenAI,
@@ -1,5 +1,18 @@
1
+ import OpenAI from 'openai';
2
+ import { ChatModel, EmbeddingModel, ImageModel } from '@core-ai/core-ai';
1
3
  import { z } from 'zod';
2
4
 
5
+ type OpenAIProviderBaseOptions = {
6
+ apiKey?: string;
7
+ baseURL?: string;
8
+ client?: OpenAI;
9
+ };
10
+ type OpenAIProvider = {
11
+ chatModel(modelId: string): ChatModel;
12
+ embeddingModel(modelId: string): EmbeddingModel;
13
+ imageModel(modelId: string): ImageModel;
14
+ };
15
+
3
16
  declare const openaiResponsesGenerateProviderOptionsSchema: z.ZodObject<{
4
17
  store: z.ZodOptional<z.ZodBoolean>;
5
18
  serviceTier: z.ZodOptional<z.ZodEnum<{
@@ -117,4 +130,4 @@ declare const openaiCompatProviderOptionsSchema: z.ZodObject<{
117
130
  }, z.core.$strict>;
118
131
  type OpenAICompatRequestOptions = OpenAICompatGenerateProviderOptions;
119
132
 
120
- export { type OpenAICompatGenerateProviderOptions as O, type OpenAICompatRequestOptions as a, openaiCompatProviderOptionsSchema as b, type OpenAIEmbedProviderOptions as c, type OpenAIImageProviderOptions as d, type OpenAIResponsesGenerateProviderOptions as e, type OpenAIResponsesProviderOptions as f, openaiEmbedProviderOptionsSchema as g, openaiImageProviderOptionsSchema as h, openaiResponsesGenerateProviderOptionsSchema as i, openaiResponsesProviderOptionsSchema as j, openaiCompatGenerateProviderOptionsSchema as o };
133
+ export { type OpenAIProvider as O, type OpenAIProviderBaseOptions as a, type OpenAICompatGenerateProviderOptions as b, type OpenAICompatRequestOptions as c, openaiCompatProviderOptionsSchema as d, type OpenAIEmbedProviderOptions as e, type OpenAIImageProviderOptions as f, type OpenAIResponsesGenerateProviderOptions as g, type OpenAIResponsesProviderOptions as h, openaiEmbedProviderOptionsSchema as i, openaiImageProviderOptionsSchema as j, openaiResponsesGenerateProviderOptionsSchema as k, openaiResponsesProviderOptionsSchema as l, openaiCompatGenerateProviderOptionsSchema as o };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@core-ai/openai",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "OpenAI provider package for @core-ai/core-ai",
5
5
  "license": "MIT",
6
6
  "author": "Omnifact (https://omnifact.ai)",
@@ -46,7 +46,7 @@
46
46
  "test:watch": "vitest"
47
47
  },
48
48
  "dependencies": {
49
- "@core-ai/core-ai": "^0.7.0",
49
+ "@core-ai/core-ai": "^0.8.0",
50
50
  "openai": "^6.1.0"
51
51
  },
52
52
  "peerDependencies": {