@@ -21,7 +21,10 @@ import {
21
21
LanguageModelResponse ,
22
22
LanguageModelStreamResponse ,
23
23
LanguageModelStreamResponsePart ,
24
- LanguageModelTextResponse
24
+ LanguageModelTextResponse ,
25
+ TokenUsageService ,
26
+ TokenUsageParams ,
27
+ UserRequest
25
28
} from '@theia/ai-core' ;
26
29
import { CancellationToken , isArray } from '@theia/core' ;
27
30
import { Anthropic } from '@anthropic-ai/sdk' ;
@@ -100,14 +103,15 @@ export class AnthropicModel implements LanguageModel {
100
103
public model : string ,
101
104
public enableStreaming : boolean ,
102
105
public apiKey : ( ) => string | undefined ,
103
- public maxTokens : number = DEFAULT_MAX_TOKENS
106
+ public maxTokens : number = DEFAULT_MAX_TOKENS ,
107
+ protected readonly tokenUsageService ?: TokenUsageService
104
108
) { }
105
109
106
110
protected getSettings ( request : LanguageModelRequest ) : Readonly < Record < string , unknown > > {
107
111
return request . settings ?? { } ;
108
112
}
109
113
110
- async request ( request : LanguageModelRequest , cancellationToken ?: CancellationToken ) : Promise < LanguageModelResponse > {
114
+ async request ( request : UserRequest , cancellationToken ?: CancellationToken ) : Promise < LanguageModelResponse > {
111
115
if ( ! request . messages ?. length ) {
112
116
throw new Error ( 'Request must contain at least one message' ) ;
113
117
}
@@ -144,7 +148,7 @@ export class AnthropicModel implements LanguageModel {
144
148
145
149
protected async handleStreamingRequest (
146
150
anthropic : Anthropic ,
147
- request : LanguageModelRequest ,
151
+ request : UserRequest ,
148
152
cancellationToken ?: CancellationToken ,
149
153
toolMessages ?: readonly Anthropic . Messages . MessageParam [ ]
150
154
) : Promise < LanguageModelStreamResponse > {
@@ -173,6 +177,7 @@ export class AnthropicModel implements LanguageModel {
173
177
const toolCalls : ToolCallback [ ] = [ ] ;
174
178
let toolCall : ToolCallback | undefined ;
175
179
const currentMessages : Message [ ] = [ ] ;
180
+ let currentMessage : Message | undefined = undefined ;
176
181
177
182
for await ( const event of stream ) {
178
183
if ( event . type === 'content_block_start' ) {
@@ -217,6 +222,21 @@ export class AnthropicModel implements LanguageModel {
217
222
}
218
223
} else if ( event . type === 'message_start' ) {
219
224
currentMessages . push ( event . message ) ;
225
+ currentMessage = event . message ;
226
+ } else if ( event . type === 'message_stop' ) {
227
+ if ( currentMessage ) {
228
+ yield { input_tokens : currentMessage . usage . input_tokens , output_tokens : currentMessage . usage . output_tokens } ;
229
+ // Record token usage if token usage service is available
230
+ if ( that . tokenUsageService && currentMessage . usage ) {
231
+ const tokenUsageParams : TokenUsageParams = {
232
+ inputTokens : currentMessage . usage . input_tokens ,
233
+ outputTokens : currentMessage . usage . output_tokens ,
234
+ requestId : request . requestId
235
+ } ;
236
+ await that . tokenUsageService . recordTokenUsage ( that . id , tokenUsageParams ) ;
237
+ }
238
+ }
239
+
220
240
}
221
241
}
222
242
if ( toolCalls . length > 0 ) {
@@ -278,10 +298,9 @@ export class AnthropicModel implements LanguageModel {
278
298
279
299
protected async handleNonStreamingRequest (
280
300
anthropic : Anthropic ,
281
- request : LanguageModelRequest
301
+ request : UserRequest
282
302
) : Promise < LanguageModelTextResponse > {
283
303
const settings = this . getSettings ( request ) ;
284
-
285
304
const { messages, systemMessage } = transformToAnthropicParams ( request . messages ) ;
286
305
287
306
const params : Anthropic . MessageCreateParams = {
@@ -296,6 +315,16 @@ export class AnthropicModel implements LanguageModel {
296
315
const response = await anthropic . messages . create ( params ) ;
297
316
const textContent = response . content [ 0 ] ;
298
317
318
+ // Record token usage if token usage service is available
319
+ if ( this . tokenUsageService && response . usage ) {
320
+ const tokenUsageParams : TokenUsageParams = {
321
+ inputTokens : response . usage . input_tokens ,
322
+ outputTokens : response . usage . output_tokens ,
323
+ requestId : request . requestId
324
+ } ;
325
+ await this . tokenUsageService . recordTokenUsage ( this . id , tokenUsageParams ) ;
326
+ }
327
+
299
328
if ( textContent ?. type === 'text' ) {
300
329
return { text : textContent . text } ;
301
330
}
0 commit comments