@@ -43,6 +43,7 @@ export class RPCAdapter {
4343 private imageManager : ImageManager | null = null ;
4444 private sessionId : string | null = null ;
4545 private currentTurnId : string | null = null ;
46+ private turnStartTime : number | null = null ;
4647 private currentMessageId : string | null = null ;
4748 private currentMessageContent = '' ;
4849 private pendingPermissions = new Map < string , PendingPermission > ( ) ;
@@ -139,6 +140,7 @@ export class RPCAdapter {
139140
140141 // Start a new turn
141142 this . currentTurnId = generateId ( 'turn' ) ;
143+ this . turnStartTime = Date . now ( ) ;
142144 writeNotification ( RPC_NOTIFICATIONS . TURN_START , {
143145 turnId : this . currentTurnId ,
144146 timestamp : createTimestamp ( ) ,
@@ -243,7 +245,49 @@ export class RPCAdapter {
243245 try {
244246 // Debug: log instruction being executed
245247 process . stderr . write ( `[RPC DEBUG] Executing instruction: ${ instruction . substring ( 0 , 100 ) } \n` ) ;
246- success = await this . agent . runInstruction ( instruction ) ;
248+
249+ // Check if it's a slash command and handle it directly
250+ if ( this . agent . isSlashCommand ( instruction ) ) {
251+ const { command, args } = this . agent . parseSlashCommand ( instruction ) ;
252+ process . stderr . write ( `[RPC DEBUG] Handling slash command: ${ command } , args: ${ JSON . stringify ( args ) } \n` ) ;
253+
254+ // First check if the command is supported
255+ if ( this . agent . isSlashCommandSupported ( command ) ) {
256+ const result = await this . agent . handleSlashCommand ( command , args ) ;
257+ if ( result !== null ) {
258+ // Slash command returned data
259+ this . currentMessageContent = result ;
260+ writeNotification ( RPC_NOTIFICATIONS . MESSAGE_UPDATE , {
261+ messageId : this . currentMessageId ,
262+ delta : result ,
263+ timestamp : createTimestamp ( ) ,
264+ } ) ;
265+ } else {
266+ // Command was handled but returned null (output went to console)
267+ // This is success - the command was executed
268+ this . currentMessageContent = `Command ${ command } executed.` ;
269+ writeNotification ( RPC_NOTIFICATIONS . MESSAGE_UPDATE , {
270+ messageId : this . currentMessageId ,
271+ delta : this . currentMessageContent ,
272+ timestamp : createTimestamp ( ) ,
273+ } ) ;
274+ }
275+ success = true ;
276+ } else {
277+ // Command not found
278+ this . currentMessageContent = `Unknown command: ${ command } . Type /help for available commands.` ;
279+ writeNotification ( RPC_NOTIFICATIONS . MESSAGE_UPDATE , {
280+ messageId : this . currentMessageId ,
281+ delta : this . currentMessageContent ,
282+ timestamp : createTimestamp ( ) ,
283+ } ) ;
284+ success = false ;
285+ }
286+ } else {
287+ // Not a slash command - run as regular instruction via LLM
288+ success = await this . agent . runInstruction ( instruction ) ;
289+ }
290+
247291 process . stderr . write ( `[RPC DEBUG] Instruction completed, success=${ success } , content length=${ this . currentMessageContent . length } \n` ) ;
248292 } catch ( err ) {
249293 const errorMessage = err instanceof Error ? err . message : String ( err ) ;
@@ -268,29 +312,39 @@ export class RPCAdapter {
268312 timestamp : createTimestamp ( ) ,
269313 } ) ;
270314
271- // End turn with context percent
315+ // End turn with stats
316+ const durationMs = this . turnStartTime ? Date . now ( ) - this . turnStartTime : undefined ;
317+ const snapshot = this . agent ?. getStatusSnapshot ( ) ;
272318 writeNotification ( RPC_NOTIFICATIONS . TURN_END , {
273319 turnId : this . currentTurnId ! ,
274320 timestamp : createTimestamp ( ) ,
275321 contextPercent : this . contextPercent ,
322+ tokensUsed : snapshot ?. tokensUsed ,
323+ durationMs,
276324 } ) ;
277325
278326 this . status = 'idle' ;
279327 this . currentTurnId = null ;
328+ this . turnStartTime = null ;
280329 this . currentMessageId = null ;
281330 this . abortController = null ;
282331
283332 return { success } ;
284333 } catch ( error ) {
285- // End turn on error with context percent
334+ // End turn on error with stats
335+ const durationMs = this . turnStartTime ? Date . now ( ) - this . turnStartTime : undefined ;
336+ const snapshot = this . agent ?. getStatusSnapshot ( ) ;
286337 writeNotification ( RPC_NOTIFICATIONS . TURN_END , {
287338 turnId : this . currentTurnId ! ,
288339 timestamp : createTimestamp ( ) ,
289340 contextPercent : this . contextPercent ,
341+ tokensUsed : snapshot ?. tokensUsed ,
342+ durationMs,
290343 } ) ;
291344
292345 this . status = 'idle' ;
293346 this . currentTurnId = null ;
347+ this . turnStartTime = null ;
294348 this . currentMessageId = null ;
295349 this . abortController = null ;
296350
@@ -330,15 +384,20 @@ export class RPCAdapter {
330384
331385 // End turn if one is in progress
332386 if ( this . currentTurnId ) {
387+ const durationMs = this . turnStartTime ? Date . now ( ) - this . turnStartTime : undefined ;
388+ const snapshot = this . agent ?. getStatusSnapshot ( ) ;
333389 writeNotification ( RPC_NOTIFICATIONS . TURN_END , {
334390 turnId : this . currentTurnId ,
335391 timestamp : createTimestamp ( ) ,
336392 contextPercent : this . contextPercent ,
393+ tokensUsed : snapshot ?. tokensUsed ,
394+ durationMs,
337395 } ) ;
338396 }
339397
340398 // Reset state
341399 this . currentTurnId = null ;
400+ this . turnStartTime = null ;
342401 this . currentMessageId = null ;
343402 this . currentMessageContent = '' ;
344403 this . abortController = null ;
0 commit comments