@@ -24,11 +24,6 @@ type OpenRouterChatCompletionParams = OpenAI.Chat.ChatCompletionCreateParams & {
2424 thinking ?: BetaThinkingConfigParam
2525}
2626
27- // Add custom interface for OpenRouter usage chunk.
28- interface OpenRouterApiStreamUsageChunk extends ApiStreamUsageChunk {
29- fullResponseText : string
30- }
31-
3227export class OpenRouterHandler extends BaseProvider implements SingleCompletionHandler {
3328 protected options : ApiHandlerOptions
3429 private client : OpenAI
@@ -110,7 +105,7 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
110105 top_p : topP ,
111106 messages : openAiMessages ,
112107 stream : true ,
113- include_reasoning : true ,
108+ stream_options : { include_usage : true } ,
114109 // Only include provider if openRouterSpecificProvider is not "[default]".
115110 ...( this . options . openRouterSpecificProvider &&
116111 this . options . openRouterSpecificProvider !== OPENROUTER_DEFAULT_PROVIDER_NAME && {
@@ -122,7 +117,7 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
122117
123118 const stream = await this . client . chat . completions . create ( completionParams )
124119
125- let genId : string | undefined
120+ let lastUsage
126121
127122 for await ( const chunk of stream as unknown as AsyncIterable < OpenAI . Chat . Completions . ChatCompletionChunk > ) {
128123 // OpenRouter returns an error object instead of the OpenAI SDK throwing an error.
@@ -132,10 +127,6 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
132127 throw new Error ( `OpenRouter API Error ${ error ?. code } : ${ error ?. message } ` )
133128 }
134129
135- if ( ! genId && chunk . id ) {
136- genId = chunk . id
137- }
138-
139130 const delta = chunk . choices [ 0 ] ?. delta
140131
141132 if ( "reasoning" in delta && delta . reasoning ) {
@@ -146,47 +137,23 @@ export class OpenRouterHandler extends BaseProvider implements SingleCompletionH
146137 fullResponseText += delta . content
147138 yield { type : "text" , text : delta . content } as ApiStreamChunk
148139 }
149- }
150-
151- const endpoint = `${ this . client . baseURL } /generation?id=${ genId } `
152140
153- const config : AxiosRequestConfig = {
154- headers : { Authorization : `Bearer ${ this . options . openRouterApiKey } ` } ,
155- timeout : 3_000 ,
141+ if ( chunk . usage ) {
142+ lastUsage = chunk . usage
143+ }
156144 }
157145
158- let attempt = 0
159- let lastError : Error | undefined
160- const startTime = Date . now ( )
161-
162- while ( attempt ++ < 10 ) {
163- await delay ( attempt * 100 ) // Give OpenRouter some time to produce the generation metadata.
164-
165- try {
166- const response = await axios . get ( endpoint , config )
167- const generation = response . data ?. data
168-
169- yield {
170- type : "usage" ,
171- inputTokens : generation ?. native_tokens_prompt || 0 ,
172- outputTokens : generation ?. native_tokens_completion || 0 ,
173- totalCost : generation ?. total_cost || 0 ,
174- fullResponseText,
175- } as OpenRouterApiStreamUsageChunk
176-
177- break
178- } catch ( error : unknown ) {
179- if ( error instanceof Error ) {
180- lastError = error
181- }
182- }
146+ if ( lastUsage ) {
147+ yield this . processUsageMetrics ( lastUsage )
183148 }
149+ }
184150
185- if ( lastError ) {
186- console . error (
187- `Failed to fetch OpenRouter generation details after attempt #${ attempt } (${ Date . now ( ) - startTime } ms) [${ genId } ]` ,
188- lastError ,
189- )
151+ processUsageMetrics ( usage : any ) : ApiStreamUsageChunk {
152+ return {
153+ type : "usage" ,
154+ inputTokens : usage ?. prompt_tokens || 0 ,
155+ outputTokens : usage ?. completion_tokens || 0 ,
156+ totalCost : usage ?. cost || 0 ,
190157 }
191158 }
192159
0 commit comments