1- import { UsageData } from './types/protocol' ;
1+ import { RequestUsageData , UsageData } from './types/protocol' ;
22
3- type UsageInput = Partial <
4- UsageData & {
3+ type RequestUsageInput = Partial <
4+ RequestUsageData & {
55 input_tokens : number ;
66 output_tokens : number ;
77 total_tokens : number ;
88 input_tokens_details : object ;
99 output_tokens_details : object ;
1010 }
11- > & { requests ?: number } ;
11+ > ;
12+
13+ type UsageInput = Partial <
14+ UsageData & {
15+ input_tokens : number ;
16+ output_tokens : number ;
17+ total_tokens : number ;
18+ input_tokens_details :
19+ | Record < string , number >
20+ | Array < Record < string , number > >
21+ | object ;
22+ output_tokens_details :
23+ | Record < string , number >
24+ | Array < Record < string , number > >
25+ | object ;
26+ request_usage_entries : RequestUsageInput [ ] ;
27+ }
28+ > & { requests ?: number ; requestUsageEntries ?: RequestUsageInput [ ] } ;
29+
30+ /**
31+ * Usage details for a single API request.
32+ */
33+ export class RequestUsage {
34+ /**
35+ * The number of input tokens used for this request.
36+ */
37+ public inputTokens : number ;
38+
39+ /**
40+ * The number of output tokens used for this request.
41+ */
42+ public outputTokens : number ;
43+
44+ /**
45+ * The total number of tokens sent and received for this request.
46+ */
47+ public totalTokens : number ;
48+
49+ /**
50+ * Details about the input tokens used for this request.
51+ */
52+ public inputTokensDetails : Record < string , number > ;
53+
54+ /**
55+ * Details about the output tokens used for this request.
56+ */
57+ public outputTokensDetails : Record < string , number > ;
58+
59+ constructor ( input ?: RequestUsageInput ) {
60+ this . inputTokens = input ?. inputTokens ?? input ?. input_tokens ?? 0 ;
61+ this . outputTokens = input ?. outputTokens ?? input ?. output_tokens ?? 0 ;
62+ this . totalTokens =
63+ input ?. totalTokens ??
64+ input ?. total_tokens ??
65+ this . inputTokens + this . outputTokens ;
66+ const inputTokensDetails =
67+ input ?. inputTokensDetails ?? input ?. input_tokens_details ;
68+ this . inputTokensDetails = inputTokensDetails
69+ ? ( inputTokensDetails as Record < string , number > )
70+ : { } ;
71+ const outputTokensDetails =
72+ input ?. outputTokensDetails ?? input ?. output_tokens_details ;
73+ this . outputTokensDetails = outputTokensDetails
74+ ? ( outputTokensDetails as Record < string , number > )
75+ : { } ;
76+ }
77+ }
1278
1379/**
1480 * Tracks token usage and request counts for an agent run.
@@ -44,6 +110,11 @@ export class Usage {
44110 */
45111 public outputTokensDetails : Array < Record < string , number > > = [ ] ;
46112
113+ /**
114+ * List of per-request usage entries for detailed cost calculations.
115+ */
116+ public requestUsageEntries : RequestUsage [ ] | undefined ;
117+
47118 constructor ( input ?: UsageInput ) {
48119 if ( typeof input === 'undefined' ) {
49120 this . requests = 0 ;
@@ -52,29 +123,58 @@ export class Usage {
52123 this . totalTokens = 0 ;
53124 this . inputTokensDetails = [ ] ;
54125 this . outputTokensDetails = [ ] ;
126+ this . requestUsageEntries = undefined ;
55127 } else {
56128 this . requests = input ?. requests ?? 1 ;
57129 this . inputTokens = input ?. inputTokens ?? input ?. input_tokens ?? 0 ;
58130 this . outputTokens = input ?. outputTokens ?? input ?. output_tokens ?? 0 ;
59- this . totalTokens = input ?. totalTokens ?? input ?. total_tokens ?? 0 ;
131+ this . totalTokens =
132+ input ?. totalTokens ??
133+ input ?. total_tokens ??
134+ this . inputTokens + this . outputTokens ;
60135 const inputTokensDetails =
61136 input ?. inputTokensDetails ?? input ?. input_tokens_details ;
62- this . inputTokensDetails = inputTokensDetails
63- ? [ inputTokensDetails as Record < string , number > ]
64- : [ ] ;
137+ if ( Array . isArray ( inputTokensDetails ) ) {
138+ this . inputTokensDetails = inputTokensDetails as Array <
139+ Record < string , number >
140+ > ;
141+ } else {
142+ this . inputTokensDetails = inputTokensDetails
143+ ? [ inputTokensDetails as Record < string , number > ]
144+ : [ ] ;
145+ }
65146 const outputTokensDetails =
66147 input ?. outputTokensDetails ?? input ?. output_tokens_details ;
67- this . outputTokensDetails = outputTokensDetails
68- ? [ outputTokensDetails as Record < string , number > ]
69- : [ ] ;
148+ if ( Array . isArray ( outputTokensDetails ) ) {
149+ this . outputTokensDetails = outputTokensDetails as Array <
150+ Record < string , number >
151+ > ;
152+ } else {
153+ this . outputTokensDetails = outputTokensDetails
154+ ? [ outputTokensDetails as Record < string , number > ]
155+ : [ ] ;
156+ }
157+
158+ const requestUsageEntries =
159+ input ?. requestUsageEntries ?? input ?. request_usage_entries ;
160+ const normalizedRequestUsageEntries = Array . isArray ( requestUsageEntries )
161+ ? requestUsageEntries . map ( ( entry ) =>
162+ entry instanceof RequestUsage ? entry : new RequestUsage ( entry ) ,
163+ )
164+ : undefined ;
165+ this . requestUsageEntries =
166+ normalizedRequestUsageEntries &&
167+ normalizedRequestUsageEntries . length > 0
168+ ? normalizedRequestUsageEntries
169+ : undefined ;
70170 }
71171 }
72172
73173 add ( newUsage : Usage ) {
74- this . requests += newUsage . requests ;
75- this . inputTokens += newUsage . inputTokens ;
76- this . outputTokens += newUsage . outputTokens ;
77- this . totalTokens += newUsage . totalTokens ;
174+ this . requests += newUsage . requests ?? 0 ;
175+ this . inputTokens += newUsage . inputTokens ?? 0 ;
176+ this . outputTokens += newUsage . outputTokens ?? 0 ;
177+ this . totalTokens += newUsage . totalTokens ?? 0 ;
78178 if ( newUsage . inputTokensDetails ) {
79179 // The type does not allow undefined, but it could happen runtime
80180 this . inputTokensDetails . push ( ...newUsage . inputTokensDetails ) ;
@@ -83,7 +183,30 @@ export class Usage {
83183 // The type does not allow undefined, but it could happen runtime
84184 this . outputTokensDetails . push ( ...newUsage . outputTokensDetails ) ;
85185 }
186+
187+ if (
188+ Array . isArray ( newUsage . requestUsageEntries ) &&
189+ newUsage . requestUsageEntries . length > 0
190+ ) {
191+ this . requestUsageEntries ??= [ ] ;
192+ this . requestUsageEntries . push (
193+ ...newUsage . requestUsageEntries . map ( ( entry ) =>
194+ entry instanceof RequestUsage ? entry : new RequestUsage ( entry ) ,
195+ ) ,
196+ ) ;
197+ } else if ( newUsage . requests === 1 && newUsage . totalTokens > 0 ) {
198+ this . requestUsageEntries ??= [ ] ;
199+ this . requestUsageEntries . push (
200+ new RequestUsage ( {
201+ inputTokens : newUsage . inputTokens ,
202+ outputTokens : newUsage . outputTokens ,
203+ totalTokens : newUsage . totalTokens ,
204+ inputTokensDetails : newUsage . inputTokensDetails ?. [ 0 ] ,
205+ outputTokensDetails : newUsage . outputTokensDetails ?. [ 0 ] ,
206+ } ) ,
207+ ) ;
208+ }
86209 }
87210}
88211
89- export { UsageData } ;
212+ export { RequestUsageData , UsageData } ;
0 commit comments