@@ -17,6 +17,7 @@ import {
17
17
ExtractResult ,
18
18
ObserveOptions ,
19
19
ObserveResult ,
20
+ StagehandMetrics ,
20
21
} from "../types/stagehand" ;
21
22
import { AgentExecuteOptions , AgentResult } from "." ;
22
23
import {
@@ -165,6 +166,99 @@ export class StagehandAPI {
165
166
return response ;
166
167
}
167
168
169
+ async getReplayMetrics ( ) : Promise < StagehandMetrics > {
170
+ if ( ! this . sessionId ) {
171
+ throw new Error ( "sessionId is required to fetch metrics." ) ;
172
+ }
173
+
174
+ const response = await this . request ( `/sessions/${ this . sessionId } /replay` , {
175
+ method : "GET" ,
176
+ } ) ;
177
+
178
+ if ( response . status !== 200 ) {
179
+ const errorText = await response . text ( ) ;
180
+ this . logger ( {
181
+ category : "api" ,
182
+ message : `[HTTP ERROR] Failed to fetch metrics. Status ${ response . status } : ${ errorText } ` ,
183
+ level : 1 ,
184
+ } ) ;
185
+ throw new Error (
186
+ `Failed to fetch metrics with status ${ response . status } : ${ errorText } ` ,
187
+ ) ;
188
+ }
189
+
190
+ const data = await response . json ( ) ;
191
+
192
+ if ( ! data . success ) {
193
+ throw new Error (
194
+ `Failed to fetch metrics: ${ data . error || "Unknown error" } ` ,
195
+ ) ;
196
+ }
197
+
198
+ // Parse the API data into StagehandMetrics format
199
+ const apiData = data . data || { } ;
200
+ const metrics : StagehandMetrics = {
201
+ actPromptTokens : 0 ,
202
+ actCompletionTokens : 0 ,
203
+ actInferenceTimeMs : 0 ,
204
+ extractPromptTokens : 0 ,
205
+ extractCompletionTokens : 0 ,
206
+ extractInferenceTimeMs : 0 ,
207
+ observePromptTokens : 0 ,
208
+ observeCompletionTokens : 0 ,
209
+ observeInferenceTimeMs : 0 ,
210
+ agentPromptTokens : 0 ,
211
+ agentCompletionTokens : 0 ,
212
+ agentInferenceTimeMs : 0 ,
213
+ totalPromptTokens : 0 ,
214
+ totalCompletionTokens : 0 ,
215
+ totalInferenceTimeMs : 0 ,
216
+ } ;
217
+
218
+ // Parse pages and their actions
219
+ const pages = apiData . pages || [ ] ;
220
+ for ( const page of pages ) {
221
+ const actions = page . actions || [ ] ;
222
+ for ( const action of actions ) {
223
+ // Get method name and token usage
224
+ const method = ( action . method || "" ) . toLowerCase ( ) ;
225
+ const tokenUsage = action . tokenUsage || { } ;
226
+
227
+ if ( tokenUsage ) {
228
+ const inputTokens = tokenUsage . inputTokens || 0 ;
229
+ const outputTokens = tokenUsage . outputTokens || 0 ;
230
+ const timeMs = tokenUsage . timeMs || 0 ;
231
+
232
+ // Map method to metrics fields
233
+ if ( method === "act" ) {
234
+ metrics . actPromptTokens += inputTokens ;
235
+ metrics . actCompletionTokens += outputTokens ;
236
+ metrics . actInferenceTimeMs += timeMs ;
237
+ } else if ( method === "extract" ) {
238
+ metrics . extractPromptTokens += inputTokens ;
239
+ metrics . extractCompletionTokens += outputTokens ;
240
+ metrics . extractInferenceTimeMs += timeMs ;
241
+ } else if ( method === "observe" ) {
242
+ metrics . observePromptTokens += inputTokens ;
243
+ metrics . observeCompletionTokens += outputTokens ;
244
+ metrics . observeInferenceTimeMs += timeMs ;
245
+ } else if ( method === "agent" ) {
246
+ metrics . agentPromptTokens += inputTokens ;
247
+ metrics . agentCompletionTokens += outputTokens ;
248
+ metrics . agentInferenceTimeMs += timeMs ;
249
+ }
250
+
251
+ // Always update totals for any method with token usage
252
+ metrics . totalPromptTokens += inputTokens ;
253
+ metrics . totalCompletionTokens += outputTokens ;
254
+ metrics . totalInferenceTimeMs += timeMs ;
255
+ }
256
+ }
257
+ }
258
+
259
+ return metrics ;
260
+ }
261
+
168
262
private async execute < T > ( {
169
263
method,
170
264
args,
0 commit comments