@@ -12,7 +12,7 @@ import { CanceledMessage, ChatLocation } from '../../../platform/chat/common/com
1212import { IEndpointProvider } from '../../../platform/endpoint/common/endpointProvider' ;
1313import { IIgnoreService } from '../../../platform/ignore/common/ignoreService' ;
1414import { ILogService } from '../../../platform/log/common/logService' ;
15- import { FilterReason } from '../../../platform/networking/common/openai' ;
15+ import { APIUsage , FilterReason } from '../../../platform/networking/common/openai' ;
1616import { ITabsAndEditorsService } from '../../../platform/tabs/common/tabsAndEditorsService' ;
1717import { getWorkspaceFileDisplayPath , IWorkspaceService } from '../../../platform/workspace/common/workspaceService' ;
1818import { ChatResponseStreamImpl } from '../../../util/common/chatResponseStreamImpl' ;
@@ -36,7 +36,7 @@ import { UnknownIntent } from '../../intents/node/unknownIntent';
3636import { ContributedToolName } from '../../tools/common/toolNames' ;
3737import { ChatVariablesCollection } from '../common/chatVariablesCollection' ;
3838import { Conversation , getGlobalContextCacheKey , GlobalContextMessageMetadata , ICopilotChatResult , ICopilotChatResultIn , normalizeSummariesOnRounds , RenderedUserMessageMetadata , Turn , TurnStatus } from '../common/conversation' ;
39- import { InternalToolReference } from '../common/intents' ;
39+ import { InternalToolReference , IToolCallRound } from '../common/intents' ;
4040import { ChatTelemetryBuilder } from './chatParticipantTelemetry' ;
4141import { DefaultIntentRequestHandler } from './defaultIntentRequestHandler' ;
4242import { IDocumentContext } from './documentContext' ;
@@ -254,9 +254,14 @@ export class ChatParticipantRequestHandler {
254254
255255 result = await chatResult ;
256256 const endpoint = await this . _endpointProvider . getChatEndpoint ( this . request ) ;
257+ const resultMetadata = ( result as ICopilotChatResultIn ) . metadata ;
258+ const totalUsage = getTotalUsage ( resultMetadata ?. toolCallRounds ) ;
259+ const usageStr = totalUsage
260+ ? ` • ↑${ totalUsage . prompt_tokens } ↓${ totalUsage . completion_tokens } tokens`
261+ : '' ;
257262 result . details = this . _authService . copilotToken ?. isNoAuthUser ?
258- `${ endpoint . name } ` :
259- `${ endpoint . name } • ${ endpoint . multiplier ?? 0 } x` ;
263+ `${ endpoint . name } ${ usageStr } ` :
264+ `${ endpoint . name } • ${ endpoint . multiplier ?? 0 } x${ usageStr } ` ;
260265 }
261266
262267 this . _conversationStore . addConversation ( this . turn . id , this . conversation ) ;
@@ -463,3 +468,36 @@ function anchorPartToMarkdown(workspaceService: IWorkspaceService, anchor: ChatR
463468
464469 return `[${ text } ](${ path } ${ anchor . title ? `"${ anchor . title } "` : '' } )` ;
465470}
471+
472+ /**
473+ * Calculates the total API usage by summing usage from all tool call rounds.
474+ */
475+ function getTotalUsage ( toolCallRounds : readonly IToolCallRound [ ] | undefined ) : APIUsage | undefined {
476+ if ( ! toolCallRounds ?. length ) {
477+ return undefined ;
478+ }
479+
480+ const initial : APIUsage = {
481+ completion_tokens : 0 ,
482+ prompt_tokens : 0 ,
483+ total_tokens : 0 ,
484+ prompt_tokens_details : { cached_tokens : 0 }
485+ } ;
486+
487+ const hasAnyUsage = toolCallRounds . some ( round => round . usage ) ;
488+ if ( ! hasAnyUsage ) {
489+ return undefined ;
490+ }
491+
492+ return toolCallRounds . reduce ( ( acc , round ) : APIUsage => {
493+ const usage = round . usage || initial ;
494+ return {
495+ completion_tokens : acc . completion_tokens + usage . completion_tokens ,
496+ prompt_tokens : acc . prompt_tokens + usage . prompt_tokens ,
497+ total_tokens : acc . total_tokens + usage . total_tokens ,
498+ prompt_tokens_details : {
499+ cached_tokens : ( acc . prompt_tokens_details ?. cached_tokens ?? 0 ) + ( usage . prompt_tokens_details ?. cached_tokens ?? 0 ) ,
500+ }
501+ } ;
502+ } , initial ) ;
503+ }
0 commit comments