@@ -15,6 +15,7 @@ import { Config } from "@/config/config"
1515import { SessionCompaction } from "./compaction"
1616import { PermissionNext } from "@/permission/next"
1717import { Question } from "@/question"
18+ import { Telemetry } from "@/telemetry"
1819
1920export namespace SessionProcessor {
2021 const DOOM_LOOP_THRESHOLD = 3
@@ -34,11 +35,16 @@ export namespace SessionProcessor {
3435 let blocked = false
3536 let attempt = 0
3637 let needsCompaction = false
38+ let stepStartTime = Date . now ( )
39+ let toolCallCounter = 0
3740
3841 const result = {
3942 get message ( ) {
4043 return input . assistantMessage
4144 } ,
45+ get toolCallCount ( ) {
46+ return toolCallCounter
47+ } ,
4248 partFromToolCall ( toolCallID : string ) {
4349 return toolcalls [ toolCallID ]
4450 } ,
@@ -195,7 +201,17 @@ export namespace SessionProcessor {
195201 attachments : value . output . attachments ,
196202 } ,
197203 } )
198-
204+ toolCallCounter ++
205+ Telemetry . track ( {
206+ type : "tool_call" ,
207+ timestamp : Date . now ( ) ,
208+ session_id : input . sessionID ,
209+ message_id : input . assistantMessage . id ,
210+ tool_name : match . tool ,
211+ tool_type : match . tool . startsWith ( "mcp__" ) ? "mcp" : "standard" ,
212+ status : "success" ,
213+ duration_ms : Date . now ( ) - match . state . time . start ,
214+ } )
199215 delete toolcalls [ value . toolCallId ]
200216 }
201217 break
@@ -216,7 +232,18 @@ export namespace SessionProcessor {
216232 } ,
217233 } ,
218234 } )
219-
235+ toolCallCounter ++
236+ Telemetry . track ( {
237+ type : "tool_call" ,
238+ timestamp : Date . now ( ) ,
239+ session_id : input . sessionID ,
240+ message_id : input . assistantMessage . id ,
241+ tool_name : match . tool ,
242+ tool_type : match . tool . startsWith ( "mcp__" ) ? "mcp" : "standard" ,
243+ status : "error" ,
244+ duration_ms : Date . now ( ) - match . state . time . start ,
245+ error : ( value . error as any ) . toString ( ) . slice ( 0 , 500 ) ,
246+ } )
220247 if (
221248 value . error instanceof PermissionNext . RejectedError ||
222249 value . error instanceof Question . RejectedError
@@ -231,6 +258,7 @@ export namespace SessionProcessor {
231258 throw value . error
232259
233260 case "start-step" :
261+ stepStartTime = Date . now ( )
234262 snapshot = await Snapshot . track ( )
235263 await Session . updatePart ( {
236264 id : Identifier . ascending ( "part" ) ,
@@ -261,6 +289,25 @@ export namespace SessionProcessor {
261289 cost : usage . cost ,
262290 } )
263291 await Session . updateMessage ( input . assistantMessage )
292+ Telemetry . track ( {
293+ type : "generation" ,
294+ timestamp : Date . now ( ) ,
295+ session_id : input . sessionID ,
296+ message_id : input . assistantMessage . id ,
297+ model_id : input . model . id ,
298+ provider_id : input . model . providerID ,
299+ agent : input . assistantMessage . agent ?? "" ,
300+ finish_reason : value . finishReason ,
301+ tokens : {
302+ input : usage . tokens . input ,
303+ output : usage . tokens . output ,
304+ reasoning : usage . tokens . reasoning ,
305+ cache_read : usage . tokens . cache . read ,
306+ cache_write : usage . tokens . cache . write ,
307+ } ,
308+ cost : usage . cost ,
309+ duration_ms : Date . now ( ) - stepStartTime ,
310+ } )
264311 if ( snapshot ) {
265312 const patch = await Snapshot . patch ( snapshot )
266313 if ( patch . files . length ) {
@@ -352,6 +399,14 @@ export namespace SessionProcessor {
352399 error : e ,
353400 stack : JSON . stringify ( e . stack ) ,
354401 } )
402+ Telemetry . track ( {
403+ type : "error" ,
404+ timestamp : Date . now ( ) ,
405+ session_id : input . sessionID ,
406+ error_name : e ?. name ?? "UnknownError" ,
407+ error_message : ( e ?. message ?? String ( e ) ) . slice ( 0 , 1000 ) ,
408+ context : "processor" ,
409+ } )
355410 const error = MessageV2 . fromError ( e , { providerID : input . model . providerID } )
356411 if ( MessageV2 . ContextOverflowError . isInstance ( error ) ) {
357412 // TODO: Handle context overflow error
0 commit comments