1
1
import { expect , test , describe } from 'vitest' ;
2
2
3
+ import { ToolContext } from '../../core/types.js' ;
3
4
import { LogLevel , Logger } from '../../utils/logger.js' ;
5
+
4
6
import { AgentState } from './AgentTracker.js' ;
5
- import { ToolContext } from '../../core/types.js' ;
6
7
7
8
// Helper function to directly invoke a listener with a log message
8
- function emitLog (
9
- logger : Logger ,
10
- level : LogLevel ,
11
- message : string
12
- ) {
9
+ function emitLog ( logger : Logger , level : LogLevel , message : string ) {
13
10
const lines = [ message ] ;
14
11
// Directly call all listeners on this logger
15
- logger . listeners . forEach ( listener => {
12
+ logger . listeners . forEach ( ( listener ) => {
16
13
listener ( logger , level , lines ) ;
17
14
} ) ;
18
15
}
@@ -38,10 +35,17 @@ describe('Log capture functionality', () => {
38
35
const mainLogger = new Logger ( { name : 'main' } ) ;
39
36
const agentLogger = new Logger ( { name : 'agent' , parent : mainLogger } ) ;
40
37
const toolLogger = new Logger ( { name : 'tool' , parent : agentLogger } ) ;
41
- const deepToolLogger = new Logger ( { name : 'deep-tool' , parent : toolLogger } ) ;
38
+ const deepToolLogger = new Logger ( {
39
+ name : 'deep-tool' ,
40
+ parent : toolLogger ,
41
+ } ) ;
42
42
43
43
// Create the log capture listener
44
- const logCaptureListener = ( logger : Logger , logLevel : LogLevel , lines : string [ ] ) => {
44
+ const logCaptureListener = (
45
+ logger : Logger ,
46
+ logLevel : LogLevel ,
47
+ lines : string [ ] ,
48
+ ) => {
45
49
// Only capture log, warn, and error levels (not debug or info)
46
50
if (
47
51
logLevel === LogLevel . log ||
@@ -55,7 +59,7 @@ describe('Log capture functionality', () => {
55
59
} else if ( logger . parent === agentLogger ) {
56
60
isAgentOrImmediateTool = true ;
57
61
}
58
-
62
+
59
63
if ( isAgentOrImmediateTool ) {
60
64
const logPrefix =
61
65
logLevel === LogLevel . warn
@@ -66,7 +70,8 @@ describe('Log capture functionality', () => {
66
70
67
71
// Add each line to the capturedLogs array with logger name for context
68
72
lines . forEach ( ( line ) => {
69
- const loggerPrefix = logger . name !== 'agent' ? `[${ logger . name } ] ` : '' ;
73
+ const loggerPrefix =
74
+ logger . name !== 'agent' ? `[${ logger . name } ] ` : '' ;
70
75
agentState . capturedLogs . push ( `${ logPrefix } ${ loggerPrefix } ${ line } ` ) ;
71
76
} ) ;
72
77
}
@@ -97,20 +102,44 @@ describe('Log capture functionality', () => {
97
102
// Verify that only the expected messages were captured
98
103
// We should have 6 messages: 3 from agent (log, warn, error) and 3 from tools (log, warn, error)
99
104
expect ( agentState . capturedLogs . length ) . toBe ( 6 ) ;
100
-
105
+
101
106
// Agent messages at log, warn, and error levels should be captured
102
- expect ( agentState . capturedLogs . some ( log => log === 'Agent log message' ) ) . toBe ( true ) ;
103
- expect ( agentState . capturedLogs . some ( log => log === '[WARN] Agent warning message' ) ) . toBe ( true ) ;
104
- expect ( agentState . capturedLogs . some ( log => log === '[ERROR] Agent error message' ) ) . toBe ( true ) ;
105
-
107
+ expect (
108
+ agentState . capturedLogs . some ( ( log ) => log === 'Agent log message' ) ,
109
+ ) . toBe ( true ) ;
110
+ expect (
111
+ agentState . capturedLogs . some (
112
+ ( log ) => log === '[WARN] Agent warning message' ,
113
+ ) ,
114
+ ) . toBe ( true ) ;
115
+ expect (
116
+ agentState . capturedLogs . some (
117
+ ( log ) => log === '[ERROR] Agent error message' ,
118
+ ) ,
119
+ ) . toBe ( true ) ;
120
+
106
121
// Tool messages at log, warn, and error levels should be captured
107
- expect ( agentState . capturedLogs . some ( log => log === '[tool] Tool log message' ) ) . toBe ( true ) ;
108
- expect ( agentState . capturedLogs . some ( log => log === '[WARN] [tool] Tool warning message' ) ) . toBe ( true ) ;
109
- expect ( agentState . capturedLogs . some ( log => log === '[ERROR] [tool] Tool error message' ) ) . toBe ( true ) ;
110
-
122
+ expect (
123
+ agentState . capturedLogs . some ( ( log ) => log === '[tool] Tool log message' ) ,
124
+ ) . toBe ( true ) ;
125
+ expect (
126
+ agentState . capturedLogs . some (
127
+ ( log ) => log === '[WARN] [tool] Tool warning message' ,
128
+ ) ,
129
+ ) . toBe ( true ) ;
130
+ expect (
131
+ agentState . capturedLogs . some (
132
+ ( log ) => log === '[ERROR] [tool] Tool error message' ,
133
+ ) ,
134
+ ) . toBe ( true ) ;
135
+
111
136
// Debug and info messages should not be captured
112
- expect ( agentState . capturedLogs . some ( log => log . includes ( 'debug' ) ) ) . toBe ( false ) ;
113
- expect ( agentState . capturedLogs . some ( log => log . includes ( 'info' ) ) ) . toBe ( false ) ;
137
+ expect ( agentState . capturedLogs . some ( ( log ) => log . includes ( 'debug' ) ) ) . toBe (
138
+ false ,
139
+ ) ;
140
+ expect ( agentState . capturedLogs . some ( ( log ) => log . includes ( 'info' ) ) ) . toBe (
141
+ false ,
142
+ ) ;
114
143
} ) ;
115
144
116
145
test ( 'should handle nested loggers correctly' , ( ) => {
@@ -133,18 +162,26 @@ describe('Log capture functionality', () => {
133
162
const mainLogger = new Logger ( { name : 'main' } ) ;
134
163
const agentLogger = new Logger ( { name : 'agent' , parent : mainLogger } ) ;
135
164
const toolLogger = new Logger ( { name : 'tool' , parent : agentLogger } ) ;
136
- const deepToolLogger = new Logger ( { name : 'deep-tool' , parent : toolLogger } ) ;
165
+ const deepToolLogger = new Logger ( {
166
+ name : 'deep-tool' ,
167
+ parent : toolLogger ,
168
+ } ) ;
137
169
138
170
// Create the log capture listener that filters based on nesting level
139
- const logCaptureListener = ( logger : Logger , logLevel : LogLevel , lines : string [ ] ) => {
171
+ const logCaptureListener = (
172
+ logger : Logger ,
173
+ logLevel : LogLevel ,
174
+ lines : string [ ] ,
175
+ ) => {
140
176
// Only capture log, warn, and error levels
141
177
if (
142
178
logLevel === LogLevel . log ||
143
179
logLevel === LogLevel . warn ||
144
180
logLevel === LogLevel . error
145
181
) {
146
182
// Check nesting level - only capture from agent and immediate tools
147
- if ( logger . nesting <= 2 ) { // agent has nesting=1, immediate tools have nesting=2
183
+ if ( logger . nesting <= 2 ) {
184
+ // agent has nesting=1, immediate tools have nesting=2
148
185
const logPrefix =
149
186
logLevel === LogLevel . warn
150
187
? '[WARN] '
@@ -153,7 +190,8 @@ describe('Log capture functionality', () => {
153
190
: '' ;
154
191
155
192
lines . forEach ( ( line ) => {
156
- const loggerPrefix = logger . name !== 'agent' ? `[${ logger . name } ] ` : '' ;
193
+ const loggerPrefix =
194
+ logger . name !== 'agent' ? `[${ logger . name } ] ` : '' ;
157
195
agentState . capturedLogs . push ( `${ logPrefix } ${ loggerPrefix } ${ line } ` ) ;
158
196
} ) ;
159
197
}
@@ -164,15 +202,25 @@ describe('Log capture functionality', () => {
164
202
mainLogger . listeners . push ( logCaptureListener ) ;
165
203
166
204
// Log at different nesting levels
167
- emitLog ( mainLogger , LogLevel . log , 'Main logger message' ) ; // nesting = 0
168
- emitLog ( agentLogger , LogLevel . log , 'Agent logger message' ) ; // nesting = 1
169
- emitLog ( toolLogger , LogLevel . log , 'Tool logger message' ) ; // nesting = 2
170
- emitLog ( deepToolLogger , LogLevel . log , 'Deep tool message' ) ; // nesting = 3
205
+ emitLog ( mainLogger , LogLevel . log , 'Main logger message' ) ; // nesting = 0
206
+ emitLog ( agentLogger , LogLevel . log , 'Agent logger message' ) ; // nesting = 1
207
+ emitLog ( toolLogger , LogLevel . log , 'Tool logger message' ) ; // nesting = 2
208
+ emitLog ( deepToolLogger , LogLevel . log , 'Deep tool message' ) ; // nesting = 3
171
209
172
210
// We should capture from agent (nesting=1) and tool (nesting=2) but not deeper
173
211
expect ( agentState . capturedLogs . length ) . toBe ( 3 ) ;
174
- expect ( agentState . capturedLogs . some ( log => log . includes ( 'Agent logger message' ) ) ) . toBe ( true ) ;
175
- expect ( agentState . capturedLogs . some ( log => log . includes ( 'Tool logger message' ) ) ) . toBe ( true ) ;
176
- expect ( agentState . capturedLogs . some ( log => log . includes ( 'Deep tool message' ) ) ) . toBe ( false ) ;
212
+ expect (
213
+ agentState . capturedLogs . some ( ( log ) =>
214
+ log . includes ( 'Agent logger message' ) ,
215
+ ) ,
216
+ ) . toBe ( true ) ;
217
+ expect (
218
+ agentState . capturedLogs . some ( ( log ) =>
219
+ log . includes ( 'Tool logger message' ) ,
220
+ ) ,
221
+ ) . toBe ( true ) ;
222
+ expect (
223
+ agentState . capturedLogs . some ( ( log ) => log . includes ( 'Deep tool message' ) ) ,
224
+ ) . toBe ( false ) ;
177
225
} ) ;
178
- } ) ;
226
+ } ) ;
0 commit comments