11import { Action } from '@/actions/types' ;
22import { ActOptions , Agent } from '@/agent' ;
3- import { blueBright , bold , cyanBright , gray } from 'ansis' ;
43import { BrowserAgent } from './browserAgent' ;
54import { z } from 'zod/v3' ;
65
7- export function narrateAgent ( agent : Agent ) {
6+ export type LogEntry =
7+ | { type : 'start' ; message : string ; timestamp : Date }
8+ | { type : 'stop' ; message : string ; timestamp : Date ; data : {
9+ totalInputTokens : number ;
10+ totalOutputTokens : number ;
11+ totalCachedWriteInputTokens : number ;
12+ totalCachedReadInputTokens : number ;
13+ totalInputTokenCost : number ;
14+ totalOutputTokenCost : number ;
15+ numUniqueModels : number ;
16+ modelDescription : string ;
17+ } }
18+ | { type : 'thought' ; message : string ; timestamp : Date }
19+ | { type : 'act' ; message : string ; timestamp : Date ; data : { task : string ; options : ActOptions } }
20+ | { type : 'action' ; message : string ; timestamp : Date ; data : { action : Action ; actionDefinition : string } }
21+ | { type : 'nav' ; message : string ; timestamp : Date ; data : { url : string } }
22+ | { type : 'extractStarted' ; message : string ; timestamp : Date ; data : { instructions : string ; schema : z . ZodSchema } }
23+ | { type : 'extractDone' ; message : string ; timestamp : Date ; data : { instructions : string ; result : any } } ;
24+
25+ export type LogCallback = ( logEntry : LogEntry ) => void ;
26+
27+
28+ export function narrateAgent ( agent : Agent , onLog : LogCallback ) {
829 let totalInputTokens = 0 ;
930 let totalOutputTokens = 0 ;
1031 let totalCachedWriteInputTokens = 0 ;
@@ -22,56 +43,52 @@ export function narrateAgent(agent: Agent) {
2243 } ) ;
2344
2445 agent . events . on ( 'start' , ( ) => {
25- console . log ( bold ( blueBright ( `▶ [start] agent started with ${ agent . models . describe ( ) } ` ) ) ) ;
46+ const message = `agent started with ${ agent . models . describe ( ) } ` ;
47+ onLog ( { type : 'start' , message, timestamp : new Date ( ) } ) ;
2648 } ) ;
2749
2850 agent . events . on ( 'stop' , ( ) => {
29- console . log ( bold ( blueBright ( `■ [stop] agent stopped` ) ) ) ;
30-
31- console . log ( ` Total usage: ` + bold `${ totalInputTokens + totalCachedWriteInputTokens + totalCachedReadInputTokens } ` + ` input tokens` + ( totalCachedWriteInputTokens > 0 || totalCachedReadInputTokens > 0 ? ` (${ totalCachedWriteInputTokens } cache write, ${ totalCachedReadInputTokens } cache read)` : '' ) + ` / ` + bold `${ totalOutputTokens } ` + ` output tokens` ) ;
32- if ( totalInputTokenCost > 0 || totalOutputTokenCost > 0 ) {
33- if ( agent . models . numUniqueModels === 1 && agent . models . describe ( ) . startsWith ( 'claude-code' ) ) {
34- console . log ( ` Cost: ` + cyanBright `None - using Claude Pro or Max subscription` )
35- } else {
36- console . log ( ` Cost: $${ ( totalInputTokenCost + totalOutputTokenCost ) . toFixed ( 3 ) } ` ) ;
37- }
38- }
39- // Show token usage and cost if available
40- // if (totalInputTokenCost > 0 || totalOutputTokenCost > 0) {
41- // console.log(` Total usage: ` + bold`${totalInputTokens}` + ` input tokens (` + `$${totalInputTokenCost.toFixed(3)}` + `)` + ` / ` + bold`${totalOutputTokens}` + ` output tokens (` + `$${totalOutputTokenCost.toFixed(3)}` + `)`);
42- // } else {
43- // console.log(` Total usage: ` + bold`${totalInputTokens}` + ` input tokens` + ` / ` + bold`${totalOutputTokens}` + ` output tokens`);
44- // }
51+ const message = 'agent stopped' ;
52+ const tokenData = {
53+ totalInputTokens : totalInputTokens + totalCachedWriteInputTokens + totalCachedReadInputTokens ,
54+ totalOutputTokens,
55+ totalCachedWriteInputTokens,
56+ totalCachedReadInputTokens,
57+ totalInputTokenCost,
58+ totalOutputTokenCost,
59+ numUniqueModels : agent . models . numUniqueModels ,
60+ modelDescription : agent . models . describe ( )
61+ } ;
62+ onLog ( { type : 'stop' , message, data : tokenData , timestamp : new Date ( ) } ) ;
4563 } ) ;
4664
4765 agent . events . on ( 'thought' , ( thought : string ) => {
48- console . log ( gray `${ thought } ` ) ;
49- //console.log(gray`⚙︎ ${thought}`);
66+ onLog ( { type : 'thought' , message : thought , timestamp : new Date ( ) } ) ;
5067 } ) ;
5168
5269 agent . events . on ( 'actStarted' , ( task : string , options : ActOptions ) => {
53- console . log ( bold ( cyanBright ( `◆ [ act] ${ task } `) ) ) ;
70+ onLog ( { type : ' act' , message : `act started: ${ task } `, data : { task , options } , timestamp : new Date ( ) } ) ;
5471 } ) ;
5572
5673 agent . events . on ( 'actionStarted' , ( action : Action ) => {
5774 const actionDefinition = agent . identifyAction ( action ) ;
58- console . log ( bold ` ${ actionDefinition . render ( action ) } ` ) ;
75+ const message = actionDefinition . render ( action ) ;
76+ onLog ( { type : 'action' , message : `action started: ${ message } ` , data : { action, actionDefinition : actionDefinition . name } , timestamp : new Date ( ) } ) ;
5977 } ) ;
6078}
6179
62- export function narrateBrowserAgent ( agent : BrowserAgent ) {
63- narrateAgent ( agent ) ;
80+ export function narrateBrowserAgent ( agent : BrowserAgent , onLog : LogCallback ) {
81+ narrateAgent ( agent , onLog ) ;
6482
6583 agent . browserAgentEvents . on ( 'nav' , ( url : string ) => {
66- console . log ( bold ( cyanBright `⛓︎ [ nav] ${ url } `) ) ;
84+ onLog ( { type : ' nav' , message : `navigating to ${ url } `, data : { url } , timestamp : new Date ( ) } ) ;
6785 } ) ;
6886
6987 agent . browserAgentEvents . on ( 'extractStarted' , ( instructions : string , schema : z . ZodSchema ) => {
70- console . log ( bold ( cyanBright `⛏ [ extract] ${ instructions } `) ) ;
88+ onLog ( { type : 'extractStarted' , message : ` extract started: ${ instructions } `, data : { instructions , schema } , timestamp : new Date ( ) } ) ;
7189 } ) ;
90+
7291 agent . browserAgentEvents . on ( 'extractDone' , ( instructions , data ) => {
73- // console.log has a decent default formatter for arbitrary data e.g. objects
74- console . log ( data ) ;
75- //console.log(blueBright`${JSON.stringify(data, null, 2)}`);
92+ onLog ( { type : 'extractDone' , message : `extract completed: ${ instructions } ` , data : { instructions, result : data } , timestamp : new Date ( ) } ) ;
7693 } ) ;
7794}
0 commit comments