@@ -57,7 +57,11 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
57
57
this . options . enableGpt5ReasoningSummary = true
58
58
}
59
59
const apiKey = this . options . openAiNativeApiKey ?? "not-provided"
60
- this . client = new OpenAI ( { baseURL : this . options . openAiNativeBaseUrl , apiKey } )
60
+ this . client = new OpenAI ( {
61
+ baseURL : this . options . openAiNativeBaseUrl ,
62
+ apiKey,
63
+ timeout : 15 * 1000 * 60 , // 15 minutes default timeout
64
+ } )
61
65
}
62
66
63
67
private normalizeGpt5Usage ( usage : any , model : OpenAiNativeModel ) : ApiStreamUsageChunk | undefined {
@@ -136,7 +140,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
136
140
const isOriginalO1 = model . id === "o1"
137
141
const { reasoning } = this . getModel ( )
138
142
139
- const response = await this . client . chat . completions . create ( {
143
+ const params : any = {
140
144
model : model . id ,
141
145
messages : [
142
146
{
@@ -148,9 +152,30 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
148
152
stream : true ,
149
153
stream_options : { include_usage : true } ,
150
154
...( reasoning && reasoning ) ,
151
- } )
155
+ }
156
+
157
+ // Add service_tier parameter if configured and not "auto"
158
+ if ( this . options . serviceTier && this . options . serviceTier !== "auto" ) {
159
+ params . service_tier = this . options . serviceTier
160
+ console . log ( "[DEBUG] Setting service_tier parameter:" , this . options . serviceTier )
161
+ console . log ( "[DEBUG] Full request params:" , JSON . stringify ( params , null , 2 ) )
162
+ } else {
163
+ console . log ( "[DEBUG] Service tier not set or is 'auto'. Current value:" , this . options . serviceTier )
164
+ }
165
+
166
+ const response = await this . client . chat . completions . create ( params , { timeout : 15 * 1000 * 60 } )
167
+ console . log ( "[DEBUG] OpenAI Chat Completions Response (O1Family):" , response )
152
168
153
- yield * this . handleStreamResponse ( response , model )
169
+ if ( typeof ( response as any ) [ Symbol . asyncIterator ] !== "function" ) {
170
+ throw new Error (
171
+ "OpenAI SDK did not return an AsyncIterable for streaming response. Please check SDK version and usage." ,
172
+ )
173
+ }
174
+
175
+ yield * this . handleStreamResponse (
176
+ response as unknown as AsyncIterable < OpenAI . Chat . Completions . ChatCompletionChunk > ,
177
+ model ,
178
+ )
154
179
}
155
180
156
181
private async * handleReasonerMessage (
@@ -161,7 +186,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
161
186
) : ApiStream {
162
187
const { reasoning } = this . getModel ( )
163
188
164
- const stream = await this . client . chat . completions . create ( {
189
+ const params : any = {
165
190
model : family ,
166
191
messages : [
167
192
{
@@ -173,9 +198,29 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
173
198
stream : true ,
174
199
stream_options : { include_usage : true } ,
175
200
...( reasoning && reasoning ) ,
176
- } )
201
+ }
202
+
203
+ // Add service_tier parameter if configured and not "auto"
204
+ if ( this . options . serviceTier && this . options . serviceTier !== "auto" ) {
205
+ params . service_tier = this . options . serviceTier
206
+ console . log ( "[DEBUG] Setting service_tier parameter:" , this . options . serviceTier )
207
+ console . log ( "[DEBUG] Full request params:" , JSON . stringify ( params , null , 2 ) )
208
+ } else {
209
+ console . log ( "[DEBUG] Service tier not set or is 'auto'. Current value:" , this . options . serviceTier )
210
+ }
211
+
212
+ const stream = await this . client . chat . completions . create ( params , { timeout : 15 * 1000 * 60 } )
177
213
178
- yield * this . handleStreamResponse ( stream , model )
214
+ if ( typeof ( stream as any ) [ Symbol . asyncIterator ] !== "function" ) {
215
+ throw new Error (
216
+ "OpenAI SDK did not return an AsyncIterable for streaming response. Please check SDK version and usage." ,
217
+ )
218
+ }
219
+
220
+ yield * this . handleStreamResponse (
221
+ stream as unknown as AsyncIterable < OpenAI . Chat . Completions . ChatCompletionChunk > ,
222
+ model ,
223
+ )
179
224
}
180
225
181
226
private async * handleDefaultModelMessage (
@@ -200,7 +245,16 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
200
245
params . verbosity = verbosity
201
246
}
202
247
203
- const stream = await this . client . chat . completions . create ( params )
248
+ // Add service_tier parameter if configured and not "auto"
249
+ if ( this . options . serviceTier && this . options . serviceTier !== "auto" ) {
250
+ params . service_tier = this . options . serviceTier
251
+ console . log ( "[DEBUG] Setting service_tier parameter:" , this . options . serviceTier )
252
+ console . log ( "[DEBUG] Full request params:" , JSON . stringify ( params , null , 2 ) )
253
+ } else {
254
+ console . log ( "[DEBUG] Service tier not set or is 'auto'. Current value:" , this . options . serviceTier )
255
+ }
256
+
257
+ const stream = await this . client . chat . completions . create ( params , { timeout : 15 * 1000 * 60 } )
204
258
205
259
if ( typeof ( stream as any ) [ Symbol . asyncIterator ] !== "function" ) {
206
260
throw new Error (
@@ -277,6 +331,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
277
331
temperature ?: number
278
332
max_output_tokens ?: number
279
333
previous_response_id ?: string
334
+ service_tier ?: string
280
335
}
281
336
282
337
const requestBody : Gpt5RequestBody = {
@@ -297,9 +352,20 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
297
352
...( requestPreviousResponseId && { previous_response_id : requestPreviousResponseId } ) ,
298
353
}
299
354
355
+ // Add service_tier parameter if configured and not "auto"
356
+ if ( this . options . serviceTier && this . options . serviceTier !== "auto" ) {
357
+ requestBody . service_tier = this . options . serviceTier
358
+ console . log ( "[DEBUG] Setting service_tier parameter:" , this . options . serviceTier )
359
+ console . log ( "[DEBUG] Full request body:" , JSON . stringify ( requestBody , null , 2 ) )
360
+ } else {
361
+ console . log ( "[DEBUG] Service tier not set or is 'auto'. Current value:" , this . options . serviceTier )
362
+ }
363
+
300
364
try {
301
365
// Use the official SDK
302
- const stream = ( await ( this . client as any ) . responses . create ( requestBody ) ) as AsyncIterable < any >
366
+ const stream = ( await ( this . client as any ) . responses . create ( requestBody , {
367
+ timeout : 15 * 1000 * 60 ,
368
+ } ) ) as AsyncIterable < any >
303
369
304
370
if ( typeof ( stream as any ) [ Symbol . asyncIterator ] !== "function" ) {
305
371
throw new Error (
@@ -308,11 +374,13 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
308
374
}
309
375
310
376
for await ( const event of stream ) {
377
+ console . log ( "[DEBUG] GPT-5 Responses API Stream Event:" , event ) // Log each event
311
378
for await ( const outChunk of this . processGpt5Event ( event , model ) ) {
312
379
yield outChunk
313
380
}
314
381
}
315
382
} catch ( sdkErr : any ) {
383
+ console . error ( "[DEBUG] OpenAI Responses API SDK Error:" , sdkErr ) // Log SDK errors
316
384
// Check if this is a 400 error about previous_response_id not found
317
385
const errorMessage = sdkErr ?. message || sdkErr ?. error ?. message || ""
318
386
const is400Error = sdkErr ?. status === 400 || sdkErr ?. response ?. status === 400
@@ -419,6 +487,15 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
419
487
const baseUrl = this . options . openAiNativeBaseUrl || "https://api.openai.com"
420
488
const url = `${ baseUrl } /v1/responses`
421
489
490
+ // Log the exact request being sent
491
+ console . log ( "[DEBUG] GPT-5 Responses API Request URL:" , url )
492
+ console . log ( "[DEBUG] GPT-5 Responses API Request Headers:" , {
493
+ "Content-Type" : "application/json" ,
494
+ Authorization : `Bearer ${ apiKey . substring ( 0 , 8 ) } ...` , // Log only first 8 chars of API key for security
495
+ Accept : "text/event-stream" ,
496
+ } )
497
+ console . log ( "[DEBUG] GPT-5 Responses API Request Body:" , JSON . stringify ( requestBody , null , 2 ) )
498
+
422
499
try {
423
500
const response = await fetch ( url , {
424
501
method : "POST" ,
@@ -430,8 +507,18 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
430
507
body : JSON . stringify ( requestBody ) ,
431
508
} )
432
509
510
+ // Log the response status
511
+ console . log ( "[DEBUG] GPT-5 Responses API Response Status:" , response . status )
512
+ // Convert headers to a plain object for logging
513
+ const headersObj : Record < string , string > = { }
514
+ response . headers . forEach ( ( value , key ) => {
515
+ headersObj [ key ] = value
516
+ } )
517
+ console . log ( "[DEBUG] GPT-5 Responses API Response Headers:" , headersObj )
518
+
433
519
if ( ! response . ok ) {
434
520
const errorText = await response . text ( )
521
+ console . log ( "[DEBUG] GPT-5 Responses API Error Response Body:" , errorText )
435
522
436
523
let errorMessage = `GPT-5 API request failed (${ response . status } )`
437
524
let errorDetails = ""
@@ -471,6 +558,11 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
471
558
this . resolveResponseId ( undefined )
472
559
473
560
// Retry the request without the previous_response_id
561
+ console . log (
562
+ "[DEBUG] GPT-5 Responses API Retry Request Body:" ,
563
+ JSON . stringify ( retryRequestBody , null , 2 ) ,
564
+ )
565
+
474
566
const retryResponse = await fetch ( url , {
475
567
method : "POST" ,
476
568
headers : {
@@ -481,7 +573,11 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
481
573
body : JSON . stringify ( retryRequestBody ) ,
482
574
} )
483
575
576
+ console . log ( "[DEBUG] GPT-5 Responses API Retry Response Status:" , retryResponse . status )
577
+
484
578
if ( ! retryResponse . ok ) {
579
+ const retryErrorText = await retryResponse . text ( )
580
+ console . log ( "[DEBUG] GPT-5 Responses API Retry Error Response Body:" , retryErrorText )
485
581
// If retry also fails, throw the original error
486
582
throw new Error ( `GPT-5 API retry failed (${ retryResponse . status } )` )
487
583
}
@@ -537,6 +633,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
537
633
// Handle streaming response
538
634
yield * this . handleGpt5StreamResponse ( response . body , model )
539
635
} catch ( error ) {
636
+ console . error ( "[DEBUG] GPT-5 Responses API Fetch Error:" , error ) // Log fetch errors
540
637
if ( error instanceof Error ) {
541
638
// Re-throw with the original error message if it's already formatted
542
639
if ( error . message . includes ( "GPT-5" ) ) {
@@ -1040,6 +1137,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
1040
1137
* Used by both the official SDK streaming path and (optionally) by the SSE fallback.
1041
1138
*/
1042
1139
private async * processGpt5Event ( event : any , model : OpenAiNativeModel ) : ApiStream {
1140
+ console . log ( "[DEBUG] processGpt5Event: Processing event type:" , event ?. type )
1043
1141
// Persist response id for conversation continuity when available
1044
1142
if ( event ?. response ?. id ) {
1045
1143
this . resolveResponseId ( event . response . id )
@@ -1148,6 +1246,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
1148
1246
model : OpenAiNativeModel ,
1149
1247
) : ApiStream {
1150
1248
for await ( const chunk of stream ) {
1249
+ console . log ( "[DEBUG] handleStreamResponse: OpenAI Chat Completions Stream Chunk:" , chunk ) // Log each chunk here
1151
1250
const delta = chunk . choices [ 0 ] ?. delta
1152
1251
1153
1252
if ( delta ?. content ) {
0 commit comments