@aeye/openai 0.3.10 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/openai.d.ts CHANGED
@@ -1,12 +1,14 @@
1
1
  /**
2
2
  * OpenAI Provider
3
3
  *
4
- * Provider for OpenAI's GPT models, DALL-E, Whisper, and TTS.
5
- * Also serves as base class for OpenAI-compatible providers.
4
+ * Provider for OpenAI's chat (Chat Completions and Responses), GPT Image,
5
+ * transcription, speech, and embedding models. Also serves as base class for
6
+ * OpenAI-compatible providers.
6
7
  */
7
- import type { AIContextAny, AIMetadataAny, EmbeddingRequest, EmbeddingResponse, ImageAnalyzeRequest, ImageEditRequest, ImageGenerationRequest, ImageGenerationResponse, Message, ModelInfo, Provider, SpeechRequest, SpeechResponse, TranscriptionRequest, TranscriptionResponse } from '@aeye/ai';
8
- import { BaseRequest, type Chunk, type DescriptorFamily, type Executor, type MessageContent, ModelInput, type Request, type Response, SchemaBudget, type Streamer, type ToolCall } from '@aeye/core';
8
+ import type { AIContextAny, AIMetadataAny, BatchJob, BatchResult, DecisionRequest, DecisionResponse, EmbeddingRequest, EmbeddingResponse, ImageEditRequest, ImageGenerationRequest, ImageGenerationResponse, Message, ModelInfo, Provider, RerankRequest, RerankResponse, SpeechRequest, SpeechResponse, TranscriptionRequest, TranscriptionResponse } from '@aeye/ai';
9
+ import { BaseRequest, type Chunk, type DescriptorFamily, type Executor, type MessageContent, type Model, ModelInput, type Request, type Response, type SchemaBudget, type SchemaRejectedError, type Streamer, type ToolCall } from '@aeye/core';
9
10
  import OpenAI from 'openai';
11
+ import { type OpenAIDecisionParams, type SystemOneDecisionParams } from './decisions';
10
12
  import { type RetryConfig, type RetryEvents } from './retry';
11
13
  /**
12
14
  * Hook called before a request is made to the provider.
@@ -18,7 +20,7 @@ import { type RetryConfig, type RetryEvents } from './retry';
18
20
  * @param ctx - The context object
19
21
  * @param metadata - Optional metadata
20
22
  */
21
- export type PreRequestHook<TRequest = any, TParams = any> = (request: TRequest, params: TParams, ctx: AIContextAny, metadata?: AIMetadataAny) => void | Promise<void>;
23
+ export type PreRequestHook<TRequest, TParams> = (request: TRequest, params: TParams, ctx: AIContextAny, metadata?: AIMetadataAny) => void | Promise<void>;
22
24
  /**
23
25
  * Hook called after a response is received from the provider.
24
26
  *
@@ -31,7 +33,7 @@ export type PreRequestHook<TRequest = any, TParams = any> = (request: TRequest,
31
33
  * @param ctx - The context object
32
34
  * @param metadata - Optional metadata
33
35
  */
34
- export type PostRequestHook<TRequest = any, TParams = any, TResponse = any> = (request: TRequest, params: TParams, response: TResponse, ctx: AIContextAny, metadata?: AIMetadataAny) => void | Promise<void>;
36
+ export type PostRequestHook<TRequest, TParams, TResponse> = (request: TRequest, params: TParams, response: TResponse, ctx: AIContextAny, metadata?: AIMetadataAny) => void | Promise<void>;
35
37
  /**
36
38
  * Hook called when an error occurs during a request to the provider.
37
39
  *
@@ -43,47 +45,82 @@ export type PostRequestHook<TRequest = any, TParams = any, TResponse = any> = (r
43
45
  * @param ctx - The context object
44
46
  * @param metadata - Optional metadata
45
47
  */
46
- export type ErrorHook<TRequest = any, TParams = any> = (request: TRequest, params: TParams, error: Error, ctx: AIContextAny, metadata?: AIMetadataAny) => void | Promise<void>;
48
+ export type ErrorHook<TRequest, TParams> = (request: TRequest, params: TParams, error: Error, ctx: AIContextAny, metadata?: AIMetadataAny) => void | Promise<void>;
47
49
  /**
48
- * Hooks for different operation types.
50
+ * Each operation's @aeye request, the parameters sent for it, and its @aeye response.
49
51
  */
50
- export interface OpenAIHooks {
51
- chat?: {
52
- beforeRequest?: PreRequestHook<Request, OpenAI.Chat.ChatCompletionCreateParams>;
53
- afterRequest?: PostRequestHook<Request, OpenAI.Chat.ChatCompletionCreateParams, Response>;
54
- onError?: ErrorHook<Request, OpenAI.Chat.ChatCompletionCreateParams>;
52
+ export interface OpenAIOperations {
53
+ chat: {
54
+ request: Request;
55
+ params: OpenAI.Chat.ChatCompletionCreateParams;
56
+ response: Response;
55
57
  };
56
- imageGenerate?: {
57
- beforeRequest?: PreRequestHook<ImageGenerationRequest, OpenAI.Images.ImageGenerateParams>;
58
- afterRequest?: PostRequestHook<ImageGenerationRequest, OpenAI.Images.ImageGenerateParams, ImageGenerationResponse>;
59
- onError?: ErrorHook<ImageGenerationRequest, OpenAI.Images.ImageGenerateParams>;
58
+ responses: {
59
+ request: Request;
60
+ params: OpenAI.Responses.ResponseCreateParams;
61
+ response: Response;
60
62
  };
61
- imageEdit?: {
62
- beforeRequest?: PreRequestHook<ImageEditRequest, OpenAI.Images.ImageEditParams>;
63
- afterRequest?: PostRequestHook<ImageEditRequest, OpenAI.Images.ImageEditParams, ImageGenerationResponse>;
64
- onError?: ErrorHook<ImageEditRequest, OpenAI.Images.ImageEditParams>;
63
+ imageGenerate: {
64
+ request: ImageGenerationRequest;
65
+ params: OpenAI.Images.ImageGenerateParams;
66
+ response: ImageGenerationResponse;
65
67
  };
66
- imageAnalyze?: {
67
- beforeRequest?: PreRequestHook<ImageAnalyzeRequest, OpenAI.Chat.ChatCompletionCreateParams>;
68
- afterRequest?: PostRequestHook<ImageAnalyzeRequest, OpenAI.Chat.ChatCompletionCreateParams, Response>;
69
- onError?: ErrorHook<ImageAnalyzeRequest, OpenAI.Chat.ChatCompletionCreateParams>;
68
+ imageEdit: {
69
+ request: ImageEditRequest;
70
+ params: OpenAI.Images.ImageEditParams;
71
+ response: ImageGenerationResponse;
70
72
  };
71
- transcribe?: {
72
- beforeRequest?: PreRequestHook<TranscriptionRequest, OpenAI.Audio.TranscriptionCreateParams>;
73
- afterRequest?: PostRequestHook<TranscriptionRequest, OpenAI.Audio.TranscriptionCreateParams, TranscriptionResponse>;
74
- onError?: ErrorHook<TranscriptionRequest, OpenAI.Audio.TranscriptionCreateParams>;
73
+ transcribe: {
74
+ request: TranscriptionRequest;
75
+ params: OpenAI.Audio.TranscriptionCreateParams;
76
+ response: TranscriptionResponse;
75
77
  };
76
- speech?: {
77
- beforeRequest?: PreRequestHook<SpeechRequest, OpenAI.Audio.Speech.SpeechCreateParams>;
78
- afterRequest?: PostRequestHook<SpeechRequest, OpenAI.Audio.Speech.SpeechCreateParams, SpeechResponse>;
79
- onError?: ErrorHook<SpeechRequest, OpenAI.Audio.Speech.SpeechCreateParams>;
78
+ speech: {
79
+ request: SpeechRequest;
80
+ params: OpenAI.Audio.SpeechCreateParams;
81
+ response: SpeechResponse;
80
82
  };
81
- embed?: {
82
- beforeRequest?: PreRequestHook<EmbeddingRequest, OpenAI.EmbeddingCreateParams>;
83
- afterRequest?: PostRequestHook<EmbeddingRequest, OpenAI.EmbeddingCreateParams, EmbeddingResponse>;
84
- onError?: ErrorHook<EmbeddingRequest, OpenAI.EmbeddingCreateParams>;
83
+ embed: {
84
+ request: EmbeddingRequest;
85
+ params: OpenAI.EmbeddingCreateParams;
86
+ response: EmbeddingResponse;
85
87
  };
88
+ rerank: {
89
+ request: RerankRequest;
90
+ params: RerankParams;
91
+ response: RerankResponse;
92
+ };
93
+ decide: {
94
+ request: DecisionRequest;
95
+ params: OpenAIDecisionParams | SystemOneDecisionParams;
96
+ response: DecisionResponse;
97
+ };
98
+ }
99
+ /**
100
+ * Parameters of a rerank request, in the shape OpenAI-compatible rerank
101
+ * endpoints (OpenRouter's among them) take.
102
+ */
103
+ export interface RerankParams {
104
+ model: string;
105
+ query: string;
106
+ documents: string[];
107
+ top_n?: number;
86
108
  }
109
+ /**
110
+ * Hooks around one operation.
111
+ */
112
+ export interface OperationHooks<TOperation extends OpenAIOperations[keyof OpenAIOperations]> {
113
+ beforeRequest?: PreRequestHook<TOperation['request'], TOperation['params']>;
114
+ afterRequest?: PostRequestHook<TOperation['request'], TOperation['params'], TOperation['response']>;
115
+ onError?: ErrorHook<TOperation['request'], TOperation['params']>;
116
+ }
117
+ /**
118
+ * Hooks for different operation types. Image analysis runs as chat, so
119
+ * it reports through the chat (or responses) hooks.
120
+ */
121
+ export type OpenAIHooks = {
122
+ [K in keyof OpenAIOperations]?: OperationHooks<OpenAIOperations[K]>;
123
+ };
87
124
  /**
88
125
  * Configuration options for the OpenAI provider.
89
126
  *
@@ -123,6 +160,7 @@ export interface OpenAIConfig {
123
160
  organization?: string;
124
161
  project?: string;
125
162
  store?: boolean;
163
+ api?: 'auto' | 'chat' | 'responses';
126
164
  retry?: RetryConfig;
127
165
  retryEvents?: RetryEvents;
128
166
  hooks?: OpenAIHooks;
@@ -134,12 +172,141 @@ export interface OpenAIConfig {
134
172
  transcription?: ModelInput;
135
173
  speech?: ModelInput;
136
174
  embedding?: ModelInput;
175
+ decision?: ModelInput;
176
+ rerank?: ModelInput;
137
177
  };
138
178
  }
179
+ /**
180
+ * Default model for each operation.
181
+ */
182
+ export type DefaultModels = NonNullable<OpenAIConfig['defaultModels']>;
183
+ /**
184
+ * Everything one API call needs, resolved once from the request, context,
185
+ * and config.
186
+ */
187
+ export interface OperationRun<TConfig> {
188
+ config: TConfig;
189
+ client: OpenAI;
190
+ ctx: AIContextAny;
191
+ metadata?: AIMetadataAny;
192
+ model: Model;
193
+ modelInfo?: ModelInfo;
194
+ signal?: AbortSignal;
195
+ retry<R>(call: (signal?: AbortSignal) => Promise<R>): Promise<R>;
196
+ }
197
+ /**
198
+ * The requests of a batch, as OpenAI and OpenRouter both take them: one
199
+ * endpoint and model, and each request's call parameters by id.
200
+ */
201
+ export interface BatchSubmission {
202
+ endpoint: '/v1/chat/completions' | '/v1/responses';
203
+ model: string;
204
+ lines: Array<{
205
+ custom_id: string;
206
+ body: OpenAI.Chat.ChatCompletionCreateParamsNonStreaming | OpenAI.Responses.ResponseCreateParamsNonStreaming;
207
+ }>;
208
+ }
209
+ /**
210
+ * One result of a batch, as OpenAI's output files and OpenRouter's results
211
+ * both carry it. A failed request has an error, or an error body.
212
+ */
213
+ export interface BatchOutputLine {
214
+ custom_id: string;
215
+ response?: {
216
+ status_code: number;
217
+ body: OpenAI.Chat.ChatCompletion | OpenAI.Responses.Response | {
218
+ error: {
219
+ message: string;
220
+ };
221
+ };
222
+ } | null;
223
+ error?: {
224
+ message: string;
225
+ } | null;
226
+ }
227
+ /**
228
+ * OpenAI provider implementation for the @aeye framework.
229
+ *
230
+ * Supports the full range of OpenAI capabilities including:
231
+ * - Chat through Chat Completions, or the Responses API when a model or
232
+ * request needs it (hosted tools, reasoning summaries or reasoning with
233
+ * tools, Responses-only models)
234
+ * - Function calling and structured outputs, streaming, and reasoning
235
+ * - Image, audio, and file input; audio output
236
+ * - Image generation and editing with GPT Image
237
+ * - Transcription (with speaker diarization) and speech synthesis
238
+ * - Text embeddings
239
+ *
240
+ * Can be extended by other OpenAI-compatible providers (e.g., Azure OpenAI, OpenRouter).
241
+ *
242
+ * @example Basic usage
243
+ * ```typescript
244
+ * import { OpenAIProvider } from '@aeye/openai';
245
+ *
246
+ * const provider = new OpenAIProvider({
247
+ * apiKey: process.env.OPENAI_API_KEY!,
248
+ * });
249
+ *
250
+ * // Create an executor for chat completions
251
+ * const executor = provider.createExecutor();
252
+ *
253
+ * const response = await executor(
254
+ * {
255
+ * messages: [
256
+ * { role: 'user', content: 'Hello!' }
257
+ * ]
258
+ * },
259
+ * {},
260
+ * { model: 'gpt-5.4-mini' }
261
+ * );
262
+ * ```
263
+ *
264
+ * @example With function calling
265
+ * ```typescript
266
+ * import { z } from 'zod';
267
+ *
268
+ * const response = await executor(
269
+ * {
270
+ * messages: [
271
+ * { role: 'user', content: 'What is the weather in San Francisco?' }
272
+ * ],
273
+ * tools: [
274
+ * {
275
+ * name: 'get_weather',
276
+ * description: 'Get current weather',
277
+ * parameters: z.object({
278
+ * location: z.string(),
279
+ * }),
280
+ * }
281
+ * ],
282
+ * toolChoice: 'auto',
283
+ * },
284
+ * {},
285
+ * { model: 'gpt-5.4-mini' }
286
+ * );
287
+ * ```
288
+ *
289
+ * @example Extending for custom providers
290
+ * ```typescript
291
+ * class CustomProvider extends OpenAIProvider {
292
+ * readonly name = 'custom';
293
+ *
294
+ * protected createClient(config: OpenAIConfig) {
295
+ * return new OpenAI({
296
+ * apiKey: config.apiKey,
297
+ * baseURL: 'https://custom-api.example.com/v1',
298
+ * });
299
+ * }
300
+ * }
301
+ * ```
302
+ *
303
+ * @template TConfig Configuration type extending OpenAIConfig
304
+ */
139
305
  export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig> implements Provider<TConfig> {
140
306
  readonly name: string;
141
307
  readonly config: TConfig;
142
308
  defaultMetadata?: Provider['defaultMetadata'];
309
+ protected readonly defaults: DefaultModels;
143
310
  constructor(config: TConfig);
144
311
  /**
145
312
  * Create OpenAI client from provider config.
@@ -149,16 +316,6 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
149
316
  *
150
317
  * @param config Provider configuration
151
318
  * @returns Configured OpenAI client instance
152
- *
153
- * @example
154
- * ```typescript
155
- * protected createClient(config: OpenAIConfig): OpenAI {
156
- * return new OpenAI({
157
- * apiKey: config.apiKey,
158
- * baseURL: 'https://custom-endpoint.example.com/v1',
159
- * });
160
- * }
161
- * ```
162
319
  */
163
320
  protected createClient(config: TConfig): OpenAI;
164
321
  /**
@@ -174,41 +331,41 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
174
331
  /**
175
332
  * Customize image generation params before sending to API.
176
333
  *
177
- * @param params Image generation parameters
334
+ * @param params Image generation parameters (mutate in place)
335
+ * @param request Original @aeye request
178
336
  * @param config Provider configuration
179
- * @returns Modified parameters
180
337
  */
181
338
  protected augmentImageGenerateRequest?<TParams extends OpenAI.ImageGenerateParams>(params: TParams, request: ImageGenerationRequest, config: TConfig): void;
182
339
  /**
183
340
  * Customize image edit params before sending to API.
184
341
  *
185
- * @param params Image generation parameters
342
+ * @param params Image edit parameters (mutate in place)
343
+ * @param request Original @aeye request
186
344
  * @param config Provider configuration
187
- * @returns Modified parameters
188
345
  */
189
346
  protected augmentImageEditRequest?<TParams extends OpenAI.ImageEditParams>(params: TParams, request: ImageEditRequest, config: TConfig): void;
190
347
  /**
191
348
  * Customize transcription params before sending to API.
192
349
  *
193
- * @param params Transcription parameters
350
+ * @param params Transcription parameters (mutate in place)
351
+ * @param request Original @aeye request
194
352
  * @param config Provider configuration
195
- * @returns Modified parameters
196
353
  */
197
354
  protected augmentTranscriptionRequest?<TParams extends OpenAI.Audio.TranscriptionCreateParams>(params: TParams, request: TranscriptionRequest, config: TConfig): void;
198
355
  /**
199
356
  * Customize speech generation params before sending to API.
200
357
  *
201
- * @param params Speech synthesis parameters
358
+ * @param params Speech synthesis parameters (mutate in place)
359
+ * @param request Original @aeye request
202
360
  * @param config Provider configuration
203
- * @returns Modified parameters
204
361
  */
205
362
  protected augmentSpeechRequest?<TParams extends OpenAI.Audio.SpeechCreateParams>(params: TParams, request: SpeechRequest, config: TConfig): void;
206
363
  /**
207
364
  * Customize embedding params before sending to API.
208
365
  *
209
- * @param params Embedding parameters
366
+ * @param params Embedding parameters (mutate in place)
367
+ * @param request Original @aeye request
210
368
  * @param config Provider configuration
211
- * @returns Modified parameters
212
369
  */
213
370
  protected augmentEmbeddingRequest?<TParams extends OpenAI.EmbeddingCreateParams>(params: TParams, request: EmbeddingRequest, config: TConfig): void;
214
371
  /**
@@ -218,11 +375,17 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
218
375
  * or to add provider-specific features.
219
376
  *
220
377
  * @param params OpenAI chat completion parameters
221
- * @param config Provider configuration
222
378
  * @param request Original @aeye request
223
- * @returns Modified parameters
379
+ * @param config Provider configuration
224
380
  */
225
381
  protected augmentChatRequest<TParams extends OpenAI.Chat.ChatCompletionCreateParams>(params: TParams, request: Request, config: TConfig): void;
382
+ /**
383
+ * Extra HTTP headers for a chat completion request, such as a router's
384
+ * feature flags. None by default.
385
+ *
386
+ * @param params The params about to be sent
387
+ */
388
+ protected chatHeaders(params: OpenAI.Chat.ChatCompletionCreateParams): Record<string, string> | undefined;
226
389
  /**
227
390
  * Augment chat message with provider-specific data.
228
391
  *
@@ -233,11 +396,6 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
233
396
  protected augmentChatMessage<TMessage extends OpenAI.Chat.ChatCompletionMessageParam>(chatMessage: TMessage, message: Message, config: TConfig): void;
234
397
  /**
235
398
  * Get augmented chat message with provider-specific data.
236
- *
237
- * @param chatMessage - OpenAI chat message
238
- * @param message - Original @aeye message
239
- * @param config - Provider configuration
240
- * @returns
241
399
  */
242
400
  private getChatMessage;
243
401
  /**
@@ -249,47 +407,46 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
249
407
  */
250
408
  protected augmentChatContent<TContent extends OpenAI.Chat.Completions.ChatCompletionContentPart>(chatContent: TContent, content: MessageContent, config: TConfig): void;
251
409
  /**
252
- * Get augmented chat content part with provider-specific data.
253
- *
254
- * @param chatContent - OpenAI chat content part
255
- * @param content - Original @aeye message content
256
- * @param config - Provider configuration
257
- * @returns
410
+ * Get augmented chat content part with provider-specific data. A cache
411
+ * breakpoint on the content marks the part.
258
412
  */
259
413
  private getChatContent;
260
414
  /**
261
415
  * Augment chat chunk with provider-specific data.
262
416
  *
263
- * @param expected
264
- * @param chunk
417
+ * @param expected - The chunk as received
418
+ * @param chunk - @aeye chunk to augment
419
+ * @param config - Provider configuration
265
420
  */
266
421
  protected augmentChatChunk<TParams extends OpenAI.Chat.Completions.ChatCompletionChunk>(expected: TParams, chunk: Chunk, config: TConfig): void;
267
422
  /**
268
423
  * Augment chat response with provider-specific data.
269
424
  *
270
- * @param openai OpenAI chat completion response
271
- * @param response @aeye response object to augment
272
- * @returns
425
+ * @param expected - The completion as received
426
+ * @param response - @aeye response object to augment
427
+ * @param config - Provider configuration
273
428
  */
274
429
  protected augmentChatResponse<TParams extends OpenAI.Chat.Completions.ChatCompletion>(expected: TParams, response: Response, config: TConfig): void;
275
430
  /**
276
- * Convert @aeye MessageContent to OpenAI text content format.
277
- * @param x
278
- * @param name
279
- * @returns
431
+ * Convert @aeye MessageContent to OpenAI text content format, for roles
432
+ * that only accept text.
433
+ *
434
+ * @param x - Message content
435
+ * @param name - Who sent it, for placeholder text
436
+ * @param config - Provider configuration
280
437
  */
281
- protected convertContentText(x: string | MessageContent[], name: string, config: TConfig): string | OpenAI.Chat.Completions.ChatCompletionContentPartText[];
438
+ protected convertContentText(x: string | MessageContent[], name: string, config: TConfig): OpenAI.Chat.Completions.ChatCompletionContentPartText[];
282
439
  /**
283
440
  * Convert @aeye MessageContent to OpenAI format.
284
- * @param x
285
- * @param name
286
- * @returns
441
+ *
442
+ * @param x - Message content
443
+ * @param name - Who sent it, for placeholder text
444
+ * @param config - Provider configuration
287
445
  */
288
- protected convertContent(x: string | MessageContent[], name: string, config: TConfig): Promise<string | OpenAI.Chat.Completions.ChatCompletionContentPart[]>;
446
+ protected convertContent(x: string | MessageContent[], name: string, config: TConfig): Promise<OpenAI.Chat.Completions.ChatCompletionContentPart[]>;
289
447
  /**
290
448
  * Convert @aeye ToolCall to OpenAI format.
291
449
  * @param x ToolCall object
292
- * @returns
293
450
  */
294
451
  protected convertToolCall(x: ToolCall): OpenAI.Chat.ChatCompletionMessageToolCall;
295
452
  /**
@@ -301,15 +458,25 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
301
458
  */
302
459
  protected convertName(name: string | undefined): string | undefined;
303
460
  /**
304
- * Convert @aeye Request messages to OpenAI format.
461
+ * Convert @aeye Request messages to Chat Completions messages.
305
462
  *
306
463
  * Handles conversion of all message types (system, user, assistant, tool)
307
464
  * and content types (text, image, audio, file).
308
465
  *
309
466
  * @param request @aeye request object
467
+ * @param config Provider configuration
310
468
  * @returns Array of OpenAI-formatted messages
311
469
  */
312
470
  protected convertMessages(request: Request, config: TConfig): Promise<OpenAI.Chat.ChatCompletionMessageParam[]>;
471
+ /**
472
+ * Convert @aeye Request messages to Responses API input items. Assistant
473
+ * turns replay their Responses reasoning so stateless requests keep it, and
474
+ * tool results may carry images and files.
475
+ *
476
+ * @param request @aeye request object
477
+ * @param config Provider configuration
478
+ */
479
+ protected convertResponsesInput(request: Request, config: TConfig): Promise<OpenAI.Responses.ResponseInputItem[]>;
313
480
  /**
314
481
  * Convert @aeye tool definitions to OpenAI format.
315
482
  *
@@ -326,10 +493,9 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
326
493
  *
327
494
  * @param request @aeye request (mutated: each tool's `descriptor` field is
328
495
  * pinned for the validation roundtrip)
329
- * @param model the resolved model the request is targeting
330
496
  * @param budget shared allocator (also fed by `convertResponseFormat`)
331
497
  */
332
- protected convertTools(request: Request, model?: ModelInfo, budget?: SchemaBudget): OpenAI.Chat.ChatCompletionTool[] | undefined;
498
+ protected convertTools(request: Request, budget: SchemaBudget): OpenAI.Chat.ChatCompletionFunctionTool[] | undefined;
333
499
  /**
334
500
  * The set of strict descriptor families this provider can speak on the
335
501
  * wire. Defaults to `['openai']` — the OpenAI Chat Completions API only
@@ -339,29 +505,13 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
339
505
  */
340
506
  protected supportedStrictFamilies: ReadonlySet<DescriptorFamily>;
341
507
  /**
342
- * Build a SchemaBudget tuned to the strictest of the model's tool /
343
- * structured-output families. Anthropic-style per-request limits apply
344
- * across BOTH tool schemas and the response_format schema, so the budget
345
- * is shared between `convertTools` and `convertResponseFormat`.
346
- *
347
- * Strict mode engages only when the model's resolved family is in
348
- * `supportedStrictFamilies` AND the model has the corresponding
349
- * capability (`'toolsStrict'` for tools, `'structured'` for output).
350
- * Mismatched families fall back to LENIENT silently — protects the
351
- * wire from receiving a dialect the API doesn't understand.
352
- */
353
- protected buildSchemaBudget(model?: ModelInfo): SchemaBudget;
354
- /**
355
- * Allocate per-tool descriptors in descending-priority order, then return
356
- * them in original declaration order. Mutates `request.tools[i].descriptor`
357
- * to record the chosen id for the Prompt's validation roundtrip.
508
+ * The schema budget for a call: from the selected model, or from the model
509
+ * id alone.
358
510
  */
359
- private allocateToolDescriptors;
511
+ private schemaBudget;
360
512
  /**
361
513
  * Convert @aeye tool choice to OpenAI format.
362
514
  *
363
- * Supports auto, required, none, and specific tool selection.
364
- *
365
515
  * @param request @aeye request object
366
516
  * @returns OpenAI-formatted tool choice option or undefined
367
517
  */
@@ -378,10 +528,10 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
378
528
  * matching strictify before parsing model output.
379
529
  *
380
530
  * @param request @aeye request object (mutated to record descriptor)
381
- * @param model the resolved model the request is targeting
531
+ * @param budget shared allocator (also fed by `convertTools`)
382
532
  * @returns OpenAI-formatted response format or undefined
383
533
  */
384
- protected convertResponseFormat(request: Request, model?: ModelInfo, budget?: SchemaBudget): OpenAI.Chat.ChatCompletionCreateParams['response_format'] | undefined;
534
+ protected convertResponseFormat(request: Request, budget: SchemaBudget): OpenAI.ResponseFormatText | OpenAI.ResponseFormatJSONObject | OpenAI.ResponseFormatJSONSchema | undefined;
385
535
  /**
386
536
  * List available models from OpenAI.
387
537
  *
@@ -398,194 +548,290 @@ export declare class OpenAIProvider<TConfig extends OpenAIConfig = OpenAIConfig>
398
548
  */
399
549
  checkHealth(config?: TConfig): Promise<boolean>;
400
550
  /**
401
- * Get request data common to all request types.
551
+ * Resolve what one API call needs: the effective config and its client,
552
+ * the model (request, then context, then metadata, then configured and
553
+ * built-in defaults), and retries.
402
554
  *
555
+ * @param operation - Operation name for retry events and errors
403
556
  * @param request - The request
404
557
  * @param ctx - The context
405
- * @param effectiveConfig - The effective configuration
406
- * @param defaultModel - Optional default model
407
- * @returns
408
- */
409
- getRequestData<R>(request: BaseRequest, requestSignal: AbortSignal | undefined, ctx: AIContextAny, effectiveConfig: TConfig, operation: string, defaultModel?: ModelInput): {
410
- model: import("@aeye/core").Model;
411
- retry: (fn: (signal?: AbortSignal) => Promise<R>) => Promise<R>;
412
- signal: AbortSignal | undefined;
413
- };
558
+ * @param metadata - Request metadata, for chat
559
+ * @param config - Per-call config override
560
+ * @param signal - Per-call abort signal
561
+ * @param defaultModel - Which configured default model applies
562
+ */
563
+ protected prepare(operation: string, request: BaseRequest, ctx: AIContextAny, metadata: AIMetadataAny | undefined, config: TConfig | undefined, signal: AbortSignal | undefined, defaultModel: keyof DefaultModels): OperationRun<TConfig>;
564
+ /**
565
+ * Send one API call with retries, around the operation's before and error
566
+ * hooks. A context-window rejection becomes a ContextWindowError.
567
+ */
568
+ protected send<K extends keyof OpenAIOperations, R>(op: K, run: OperationRun<TConfig>, request: OpenAIOperations[K]['request'], params: OpenAIOperations[K]['params'], call: (signal?: AbortSignal) => Promise<R>): Promise<R>;
569
+ /**
570
+ * Report a response to the operation's after hook and return it.
571
+ */
572
+ protected finish<K extends keyof OpenAIOperations>(op: K, run: OperationRun<TConfig>, request: OpenAIOperations[K]['request'], params: OpenAIOperations[K]['params'], response: OpenAIOperations[K]['response']): Promise<OpenAIOperations[K]['response']>;
573
+ /**
574
+ * The schema a bad request rejected, if any. OpenAI names it in the error
575
+ * message; OpenAI-compatible providers can look further.
576
+ *
577
+ * @param request - The request as sent
578
+ * @param error - The API's 400 or 422 error
579
+ */
580
+ protected rejectedSchema(request: Request, error: Error): SchemaRejectedError | undefined;
581
+ /**
582
+ * Send a chat call. A request that overflows the context window ends as
583
+ * `length` rather than failing, so the prompt loop can trim and retry. A
584
+ * rejected schema becomes a SchemaRejectedError.
585
+ */
586
+ private sendChat;
587
+ /**
588
+ * Relay streamed chunks, then report the assembled response to the after
589
+ * hook (even when the stream fails part way) and return it.
590
+ */
591
+ private relay;
592
+ /**
593
+ * Whether a chat request goes to the Responses API: always or never when
594
+ * configured, otherwise when the model is Responses-only or the request
595
+ * uses something only Responses offers.
596
+ *
597
+ * @param request - The request
598
+ * @param modelId - The model it targets
599
+ * @param config - Provider configuration
600
+ * @param model - The full model, whose registry entry says whether it is
601
+ * Responses-only; the model id decides otherwise
602
+ */
603
+ protected usesResponses(request: Request, modelId: string, config: TConfig, model?: ModelInfo): boolean;
414
604
  /**
415
- * Create an executor for chat completion requests.
605
+ * Chat Completions parameters for a request, before the stream flag.
416
606
  *
417
- * The executor handles non-streaming chat completions with support for:
418
- * - Multi-turn conversations
419
- * - Function calling
420
- * - Structured outputs
421
- * - Vision (images)
422
- * - Audio inputs
607
+ * @param request - The request
608
+ * @param run - The resolved call
609
+ * @param streaming - Whether the response will stream (audio output
610
+ * streams only as PCM)
611
+ */
612
+ protected buildChatParams(request: Request, run: OperationRun<TConfig>, streaming: boolean): Promise<OpenAI.Chat.ChatCompletionCreateParamsNonStreaming>;
613
+ /**
614
+ * Responses API parameters for a request, before the stream flag.
615
+ * Reasoning comes back encrypted unless responses are stored, so later
616
+ * turns can replay it.
617
+ *
618
+ * @param request - The request
619
+ * @param run - The resolved call
620
+ */
621
+ protected buildResponsesParams(request: Request, run: OperationRun<TConfig>): Promise<OpenAI.Responses.ResponseCreateParamsNonStreaming>;
622
+ /**
623
+ * Map a Chat Completions result to a @aeye response.
624
+ */
625
+ private chatResponse;
626
+ /**
627
+ * Turn a Chat Completions stream into chunks.
628
+ *
629
+ * Tool calls are finalized only on positive evidence they're done: a
630
+ * finish reason on the chunk (the whole response is done), or a higher
631
+ * tool-call index (tool calls arrive in index order). Providers interleave
632
+ * usage-only and keep-alive chunks, so "not updated this chunk" is not
633
+ * evidence. Anything unfinished when the stream completes is finalized
634
+ * then; a stream that fails leaves its calls unfinished.
635
+ */
636
+ private chatChunks;
637
+ /**
638
+ * Run a chat request through Chat Completions.
639
+ */
640
+ private complete;
641
+ /**
642
+ * Stream a chat request through Chat Completions.
643
+ */
644
+ private completeStream;
645
+ /**
646
+ * Run a chat request through the Responses API.
647
+ */
648
+ private respond;
649
+ /**
650
+ * Stream a chat request through the Responses API.
651
+ */
652
+ private respondStream;
653
+ /**
654
+ * Create an executor for chat requests.
423
655
  *
424
656
  * @param config Optional configuration override
425
- * @returns Executor function for chat completions
657
+ * @returns Executor function for chat
426
658
  * @throws {ProviderError} If request fails
427
- * @throws {RateLimitError} If rate limit is exceeded
428
659
  */
429
660
  createExecutor(config?: TConfig): Executor<AIContextAny, AIMetadataAny>;
430
661
  /**
431
- * Create a streamer for streaming chat completion requests.
432
- *
433
- * The streamer yields chunks as they arrive from OpenAI, enabling
434
- * real-time response rendering.
662
+ * Create a streamer for streaming chat requests.
435
663
  *
436
664
  * @param config Optional configuration override
437
665
  * @returns Streamer async generator function
438
666
  * @throws {ProviderError} If request fails
439
- * @throws {RateLimitError} If rate limit is exceeded
440
667
  */
441
668
  createStreamer(config?: TConfig): Streamer<AIContextAny, AIMetadataAny>;
442
669
  /**
443
- * Get image generation parameters based on model and request.
444
- *
445
- * @param request - Image generation request
446
- * @param model - Model ID
447
- * @returns
670
+ * Relay image generation or edit progress, then report the final images
671
+ * to the after hook.
448
672
  */
449
- getGenerateParameters(request: ImageGenerationRequest, model: string): OpenAI.Images.ImageGenerateParams;
673
+ private imageProgress;
450
674
  /**
451
675
  * Generate images.
452
676
  *
453
677
  * @param request Image generation request parameters
454
- * @param ctx Context object (not used)
678
+ * @param ctx Context object
455
679
  * @param config Optional configuration override
456
- * @returns Generated image URLs or base64 data
680
+ * @returns Generated images
457
681
  * @throws {ProviderError} If generation fails
458
- * @throws {RateLimitError} If rate limit is exceeded
459
682
  */
460
683
  generateImage: Provider['generateImage'];
461
684
  /**
462
- * Generate images with streaming progress updates.
463
- *
464
- * Note: OpenAI's API doesn't natively support streaming image generation,
465
- * so this implementation polls for progress or returns the result immediately.
685
+ * Generate images with streaming partial images.
466
686
  *
467
687
  * @param request Image generation request parameters
468
- * @param ctx Context object (not used)
688
+ * @param ctx Context object
469
689
  * @param config Optional configuration override
470
690
  * @returns Async generator yielding progress chunks
471
691
  * @throws {ProviderError} If generation fails
472
- * @throws {RateLimitError} If rate limit is exceeded
473
692
  */
474
693
  generateImageStream: Provider['generateImageStream'];
475
694
  /**
476
- * Get image generation parameters based on model and request.
477
- *
478
- * @param request - Image generation request
479
- * @param model - Model ID
480
- * @returns
695
+ * Image edit parameters shared by the streaming and non-streaming paths.
481
696
  */
482
- getEditParameters(request: ImageEditRequest, model: string): Omit<OpenAI.Images.ImageEditParams, 'image'>;
697
+ private editParams;
483
698
  /**
484
- * Edit images using DALL-E models.
485
- *
486
- * Supports image editing with text prompts and optional masks.
699
+ * Edit or combine images with a text prompt and an optional mask.
487
700
  *
488
701
  * @param request Image edit request parameters
489
- * @param ctx Context object (not used)
702
+ * @param ctx Context object
490
703
  * @param config Optional configuration override
491
- * @returns Edited image URLs or base64 data
704
+ * @returns Edited images
492
705
  * @throws {ProviderError} If editing fails
493
- * @throws {RateLimitError} If rate limit is exceeded
494
706
  */
495
707
  editImage: Provider['editImage'];
496
708
  /**
497
- * Edit images with streaming progress updates.
498
- *
499
- * Note: OpenAI's API doesn't natively support streaming image editing,
500
- * so this implementation returns the result with progress indicators.
709
+ * Edit images with streaming partial images.
501
710
  *
502
711
  * @param request Image edit request parameters
503
- * @param ctx Context object (not used)
712
+ * @param ctx Context object
504
713
  * @param config Optional configuration override
505
714
  * @returns Async generator yielding progress chunks
506
715
  * @throws {ProviderError} If editing fails
507
- * @throws {RateLimitError} If rate limit is exceeded
508
716
  */
509
717
  editImageStream: Provider['editImageStream'];
510
718
  /**
511
- * Transcribe audio to text using Whisper models.
512
- *
513
- * Supports multiple audio formats and optional timestamps.
719
+ * Transcription parameters shared by the streaming and non-streaming
720
+ * paths. Diarization needs chunking, and known speakers go as data URLs.
721
+ */
722
+ private transcriptionParams;
723
+ /**
724
+ * Transcribe audio to text, with timed and speaker-labeled segments when
725
+ * the response format provides them.
514
726
  *
515
727
  * @param request Transcription request parameters
516
- * @param ctx Context object (not used)
728
+ * @param ctx Context object
517
729
  * @param config Optional configuration override
518
- * @returns Transcription text and optional metadata
730
+ * @returns Transcription text and segments
519
731
  * @throws {ProviderError} If transcription fails
520
- * @throws {RateLimitError} If rate limit is exceeded
521
732
  */
522
733
  transcribe: Provider['transcribe'];
523
734
  /**
524
- * Transcribe audio with streaming progress updates.
525
- *
526
- * Note: OpenAI's API doesn't natively support streaming transcription,
527
- * so this implementation returns the result with progress indicators.
735
+ * Transcribe audio with streaming text and segments.
528
736
  *
529
737
  * @param request Transcription request parameters
530
- * @param ctx Context object (not used)
738
+ * @param ctx Context object
531
739
  * @param config Optional configuration override
532
740
  * @returns Async generator yielding transcription chunks
533
741
  * @throws {ProviderError} If transcription fails
534
- * @throws {RateLimitError} If rate limit is exceeded
535
742
  */
536
743
  transcribeStream: Provider['transcribeStream'];
537
744
  /**
538
- * Generate speech from text using TTS models.
539
- *
540
- * Supports multiple voices and audio formats.
745
+ * Generate speech from text.
541
746
  *
542
747
  * @param request Speech synthesis request parameters
543
- * @param ctx Context object (not used)
748
+ * @param ctx Context object
544
749
  * @param config Optional configuration override
545
- * @returns Audio buffer and content type
750
+ * @returns Audio stream and its format
546
751
  * @throws {ProviderError} If speech generation fails
547
- * @throws {RateLimitError} If rate limit is exceeded
548
752
  */
549
753
  speech: Provider['speech'];
550
754
  /**
551
755
  * Generate text embeddings for semantic search and similarity.
552
756
  *
553
- * Supports text-embedding-3-small, text-embedding-3-large, and ada-002 models.
554
- *
555
757
  * @param request Embedding request parameters
556
- * @param ctx Context object (not used)
758
+ * @param ctx Context object
557
759
  * @param config Optional configuration override
558
760
  * @returns Array of embeddings with usage information
559
761
  * @throws {ProviderError} If embedding generation fails
560
- * @throws {RateLimitError} If rate limit is exceeded
561
762
  */
562
763
  embed: Provider['embed'];
563
764
  /**
564
- * Analyze images using vision-capable models.
765
+ * Typed answers about an input. A conversation goes in as Responses input.
565
766
  *
566
- * This method converts the image analysis request into a chat request
567
- * with image content and calls the chat API internally.
568
- *
569
- * @param request Image analysis request parameters
570
- * @param ctx Context object (not used)
767
+ * @param request Decision request parameters
768
+ * @param ctx Context object
571
769
  * @param config Optional configuration override
572
- * @returns Analysis response with text content
573
- * @throws {ProviderError} If analysis fails
574
- * @throws {RateLimitError} If rate limit is exceeded
770
+ * @returns Answers by question name
575
771
  */
576
- analyzeImage: Provider['analyzeImage'];
772
+ decide: Provider['decide'];
577
773
  /**
578
- * Analyze images with streaming response.
774
+ * Run chat requests as one batch on one model. Each request becomes the
775
+ * same call a direct request would make, through Responses when any of
776
+ * them needs it.
579
777
  *
580
- * This method converts the image analysis request into a chat request
581
- * with image content and calls the streaming chat API internally.
778
+ * @param requests Chat requests, whose results come back in this order
779
+ * @param ctx Context object
780
+ * @param config Optional configuration override
781
+ * @returns The submitted batch
782
+ */
783
+ submitBatch: Provider['submitBatch'];
784
+ /**
785
+ * A batch as it stands now, with its results once it completes.
582
786
  *
583
- * @param request Image analysis request parameters
584
- * @param ctx Context object (not used)
787
+ * @param job The batch from submitBatch
788
+ * @param ctx Context object
585
789
  * @param config Optional configuration override
586
- * @returns Async generator yielding response chunks
587
- * @throws {ProviderError} If analysis fails
588
- * @throws {RateLimitError} If rate limit is exceeded
790
+ */
791
+ getBatch: Provider['getBatch'];
792
+ /**
793
+ * Start a batch: OpenAI takes the requests as an uploaded JSONL file.
794
+ *
795
+ * @param batch The requests
796
+ * @param run The resolved call
797
+ */
798
+ protected createBatch(batch: BatchSubmission, run: OperationRun<TConfig>): Promise<BatchJob>;
799
+ /**
800
+ * Read a batch: OpenAI writes results, and failed requests, to files.
801
+ *
802
+ * @param job The batch
803
+ * @param run The resolved call
804
+ */
805
+ protected retrieveBatch(job: BatchJob, run: OperationRun<TConfig>): Promise<BatchJob>;
806
+ /**
807
+ * A batch as @aeye reports it.
808
+ */
809
+ private batchJob;
810
+ /**
811
+ * Results in request order, each mapped as its direct call would be.
812
+ *
813
+ * @param lines The results, in any order
814
+ * @param total How many requests the batch had
815
+ * @param run The resolved call
816
+ */
817
+ protected batchResults(lines: BatchOutputLine[], total: number, run: OperationRun<TConfig>): BatchResult[];
818
+ /**
819
+ * One batch result body as a @aeye response.
820
+ */
821
+ private batchResponse;
822
+ /**
823
+ * An image analysis request as a chat request, and the metadata naming
824
+ * the configured analysis model as the fallback.
825
+ */
826
+ private analysisChat;
827
+ /**
828
+ * Analyze images with a vision model. Runs as a chat request, reported
829
+ * through the chat hooks.
830
+ */
831
+ analyzeImage: Provider['analyzeImage'];
832
+ /**
833
+ * Analyze images with a vision model, streaming the answer. Runs as a
834
+ * chat request, reported through the chat hooks.
589
835
  */
590
836
  analyzeImageStream: Provider['analyzeImageStream'];
591
837
  }