@@ -4,25 +4,36 @@ import { firstValueFrom } from "rxjs";
4
4
import {
5
5
BaseEvent ,
6
6
EventType ,
7
- AgentState ,
8
7
RunStartedEvent ,
9
8
ToolCallStartEvent ,
10
9
ToolCallArgsEvent ,
11
10
ToolCallEndEvent ,
11
+ RunAgentInput ,
12
+ AssistantMessage ,
12
13
} from "@ag-ui/core" ;
13
14
import { defaultApplyEvents } from "../default" ;
15
+ import { AbstractAgent } from "@/agent" ;
16
+
17
+ const FAKE_AGENT = null as unknown as AbstractAgent ;
14
18
15
19
describe ( "defaultApplyEvents with tool calls" , ( ) => {
16
20
it ( "should handle a single tool call correctly" , async ( ) => {
17
21
// Create a subject and state for events
18
22
const events$ = new Subject < BaseEvent > ( ) ;
19
- const initialState : AgentState = {
23
+ const initialState = {
20
24
messages : [ ] ,
21
- state : { } ,
25
+ state : {
26
+ count : 0 ,
27
+ text : "hello" ,
28
+ } ,
29
+ threadId : "test-thread" ,
30
+ runId : "test-run" ,
31
+ tools : [ ] ,
32
+ context : [ ] ,
22
33
} ;
23
34
24
35
// Create the observable stream
25
- const result$ = defaultApplyEvents ( initialState , events$ ) ;
36
+ const result$ = defaultApplyEvents ( initialState , events$ , FAKE_AGENT , [ ] ) ;
26
37
27
38
// Collect all emitted state updates in an array
28
39
const stateUpdatesPromise = firstValueFrom ( result$ . pipe ( toArray ( ) ) ) ;
@@ -70,36 +81,46 @@ describe("defaultApplyEvents with tool calls", () => {
70
81
expect ( stateUpdates . length ) . toBe ( 4 ) ;
71
82
72
83
// First update: tool call created
73
- expect ( stateUpdates [ 0 ] . messages . length ) . toBe ( 1 ) ;
74
- expect ( stateUpdates [ 0 ] . messages [ 0 ] ?. toolCalls ?. length ) . toBe ( 1 ) ;
75
- expect ( stateUpdates [ 0 ] . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool1" ) ;
76
- expect ( stateUpdates [ 0 ] . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. name ) . toBe ( "search" ) ;
77
- expect ( stateUpdates [ 0 ] . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe ( "" ) ;
84
+ expect ( stateUpdates [ 0 ] . messages ?. length ) . toBe ( 1 ) ;
85
+ expect ( ( stateUpdates [ 0 ] . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. length ) . toBe ( 1 ) ;
86
+ expect ( ( stateUpdates [ 0 ] . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool1" ) ;
87
+ expect ( ( stateUpdates [ 0 ] . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. name ) . toBe (
88
+ "search" ,
89
+ ) ;
90
+ expect (
91
+ ( stateUpdates [ 0 ] . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. arguments ,
92
+ ) . toBe ( "" ) ;
78
93
79
94
// Second update: first args chunk added
80
- expect ( stateUpdates [ 1 ] . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe ( '{"query": "' ) ;
95
+ expect (
96
+ ( stateUpdates [ 1 ] . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. arguments ,
97
+ ) . toBe ( '{"query": "' ) ;
81
98
82
99
// Third update: second args chunk appended
83
- expect ( stateUpdates [ 2 ] . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe (
84
- '{"query": "test search' ,
85
- ) ;
100
+ expect (
101
+ ( stateUpdates [ 2 ] . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. arguments ,
102
+ ) . toBe ( '{"query": "test search' ) ;
86
103
87
104
// Fourth update: third args chunk appended
88
- expect ( stateUpdates [ 3 ] . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe (
89
- '{"query": "test search"}' ,
90
- ) ;
105
+ expect (
106
+ ( stateUpdates [ 3 ] . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. arguments ,
107
+ ) . toBe ( '{"query": "test search"}' ) ;
91
108
} ) ;
92
109
93
110
it ( "should handle multiple tool calls correctly" , async ( ) => {
94
111
// Create a subject and state for events
95
112
const events$ = new Subject < BaseEvent > ( ) ;
96
- const initialState : AgentState = {
113
+ const initialState : RunAgentInput = {
97
114
messages : [ ] ,
98
115
state : { } ,
116
+ threadId : "test-thread" ,
117
+ runId : "test-run" ,
118
+ tools : [ ] ,
119
+ context : [ ] ,
99
120
} ;
100
121
101
122
// Create the observable stream
102
- const result$ = defaultApplyEvents ( initialState , events$ ) ;
123
+ const result$ = defaultApplyEvents ( initialState , events$ , FAKE_AGENT , [ ] ) ;
103
124
104
125
// Collect all emitted state updates in an array
105
126
const stateUpdatesPromise = firstValueFrom ( result$ . pipe ( toArray ( ) ) ) ;
@@ -157,19 +178,25 @@ describe("defaultApplyEvents with tool calls", () => {
157
178
158
179
// Check last state update for the correct tool calls
159
180
const finalState = stateUpdates [ stateUpdates . length - 1 ] ;
160
- expect ( finalState . messages . length ) . toBe ( 2 ) ;
181
+ expect ( finalState . messages ? .length ) . toBe ( 2 ) ;
161
182
162
183
// First message should have first tool call
163
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. length ) . toBe ( 1 ) ;
164
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool1" ) ;
165
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. name ) . toBe ( "search" ) ;
166
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe ( '{"query":"test"}' ) ;
184
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. length ) . toBe ( 1 ) ;
185
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool1" ) ;
186
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. name ) . toBe (
187
+ "search" ,
188
+ ) ;
189
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe (
190
+ '{"query":"test"}' ,
191
+ ) ;
167
192
168
193
// Second message should have second tool call
169
- expect ( finalState . messages [ 1 ] ?. toolCalls ?. length ) . toBe ( 1 ) ;
170
- expect ( finalState . messages [ 1 ] ?. toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool2" ) ;
171
- expect ( finalState . messages [ 1 ] ?. toolCalls ?. [ 0 ] ?. function ?. name ) . toBe ( "calculate" ) ;
172
- expect ( finalState . messages [ 1 ] ?. toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe (
194
+ expect ( ( finalState . messages ?. [ 1 ] as AssistantMessage ) . toolCalls ?. length ) . toBe ( 1 ) ;
195
+ expect ( ( finalState . messages ?. [ 1 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool2" ) ;
196
+ expect ( ( finalState . messages ?. [ 1 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. name ) . toBe (
197
+ "calculate" ,
198
+ ) ;
199
+ expect ( ( finalState . messages ?. [ 1 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe (
173
200
'{"expression":"1+1"}' ,
174
201
) ;
175
202
} ) ;
@@ -180,7 +207,7 @@ describe("defaultApplyEvents with tool calls", () => {
180
207
181
208
// Create initial state with an existing message
182
209
const parentMessageId = "existing_message" ;
183
- const initialState : AgentState = {
210
+ const initialState : RunAgentInput = {
184
211
messages : [
185
212
{
186
213
id : parentMessageId ,
@@ -190,10 +217,14 @@ describe("defaultApplyEvents with tool calls", () => {
190
217
} ,
191
218
] ,
192
219
state : { } ,
220
+ threadId : "test-thread" ,
221
+ runId : "test-run" ,
222
+ tools : [ ] ,
223
+ context : [ ] ,
193
224
} ;
194
225
195
226
// Create the observable stream
196
- const result$ = defaultApplyEvents ( initialState , events$ ) ;
227
+ const result$ = defaultApplyEvents ( initialState , events$ , FAKE_AGENT , [ ] ) ;
197
228
198
229
// Collect all emitted state updates in an array
199
230
const stateUpdatesPromise = firstValueFrom ( result$ . pipe ( toArray ( ) ) ) ;
@@ -230,25 +261,33 @@ describe("defaultApplyEvents with tool calls", () => {
230
261
231
262
// Check that the tool call was added to the existing message
232
263
const finalState = stateUpdates [ stateUpdates . length - 1 ] ;
233
- expect ( finalState . messages . length ) . toBe ( 1 ) ;
234
- expect ( finalState . messages [ 0 ] . id ) . toBe ( parentMessageId ) ;
235
- expect ( finalState . messages [ 0 ] . content ) . toBe ( "I'll help you with that." ) ;
236
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. length ) . toBe ( 1 ) ;
237
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool1" ) ;
238
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. name ) . toBe ( "search" ) ;
239
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe ( '{"query":"test"}' ) ;
264
+ expect ( finalState . messages ?. length ) . toBe ( 1 ) ;
265
+ expect ( finalState . messages ?. [ 0 ] ?. id ) . toBe ( parentMessageId ) ;
266
+ expect ( finalState . messages ?. [ 0 ] ?. content ) . toBe ( "I'll help you with that." ) ;
267
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. length ) . toBe ( 1 ) ;
268
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool1" ) ;
269
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. name ) . toBe (
270
+ "search" ,
271
+ ) ;
272
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe (
273
+ '{"query":"test"}' ,
274
+ ) ;
240
275
} ) ;
241
276
242
277
it ( "should handle errors and partial updates correctly" , async ( ) => {
243
278
// Create a subject and state for events
244
279
const events$ = new Subject < BaseEvent > ( ) ;
245
- const initialState : AgentState = {
280
+ const initialState : RunAgentInput = {
246
281
messages : [ ] ,
247
282
state : { } ,
283
+ threadId : "test-thread" ,
284
+ runId : "test-run" ,
285
+ tools : [ ] ,
286
+ context : [ ] ,
248
287
} ;
249
288
250
289
// Create the observable stream
251
- const result$ = defaultApplyEvents ( initialState , events$ ) ;
290
+ const result$ = defaultApplyEvents ( initialState , events$ , FAKE_AGENT , [ ] ) ;
252
291
253
292
// Collect all emitted state updates in an array
254
293
const stateUpdatesPromise = firstValueFrom ( result$ . pipe ( toArray ( ) ) ) ;
@@ -289,19 +328,25 @@ describe("defaultApplyEvents with tool calls", () => {
289
328
290
329
// Check the final JSON (should be valid now)
291
330
const finalState = stateUpdates [ stateUpdates . length - 1 ] ;
292
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe ( '{"query:"test"}' ) ;
331
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. arguments ) . toBe (
332
+ '{"query:"test"}' ,
333
+ ) ;
293
334
} ) ;
294
335
295
336
it ( "should handle advanced scenarios with multiple tools and text messages" , async ( ) => {
296
337
// Create a subject and state for events
297
338
const events$ = new Subject < BaseEvent > ( ) ;
298
- const initialState : AgentState = {
339
+ const initialState : RunAgentInput = {
299
340
messages : [ ] ,
300
341
state : { } ,
342
+ threadId : "test-thread" ,
343
+ runId : "test-run" ,
344
+ tools : [ ] ,
345
+ context : [ ] ,
301
346
} ;
302
347
303
348
// Create the observable stream
304
- const result$ = defaultApplyEvents ( initialState , events$ ) ;
349
+ const result$ = defaultApplyEvents ( initialState , events$ , FAKE_AGENT , [ ] ) ;
305
350
306
351
// Collect all emitted state updates in an array
307
352
const stateUpdatesPromise = firstValueFrom ( result$ . pipe ( toArray ( ) ) ) ;
@@ -355,16 +400,20 @@ describe("defaultApplyEvents with tool calls", () => {
355
400
356
401
// Check the final state for both tool calls
357
402
const finalState = stateUpdates [ stateUpdates . length - 1 ] ;
358
- expect ( finalState . messages . length ) . toBe ( 2 ) ;
403
+ expect ( finalState . messages ? .length ) . toBe ( 2 ) ;
359
404
360
405
// Verify first tool call
361
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. length ) . toBe ( 1 ) ;
362
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool1" ) ;
363
- expect ( finalState . messages [ 0 ] ?. toolCalls ?. [ 0 ] ?. function ?. name ) . toBe ( "search" ) ;
406
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. length ) . toBe ( 1 ) ;
407
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool1" ) ;
408
+ expect ( ( finalState . messages ?. [ 0 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. name ) . toBe (
409
+ "search" ,
410
+ ) ;
364
411
365
412
// Verify second tool call
366
- expect ( finalState . messages [ 1 ] ?. toolCalls ?. length ) . toBe ( 1 ) ;
367
- expect ( finalState . messages [ 1 ] ?. toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool2" ) ;
368
- expect ( finalState . messages [ 1 ] ?. toolCalls ?. [ 0 ] ?. function ?. name ) . toBe ( "calculate" ) ;
413
+ expect ( ( finalState . messages ?. [ 1 ] as AssistantMessage ) . toolCalls ?. length ) . toBe ( 1 ) ;
414
+ expect ( ( finalState . messages ?. [ 1 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. id ) . toBe ( "tool2" ) ;
415
+ expect ( ( finalState . messages ?. [ 1 ] as AssistantMessage ) . toolCalls ?. [ 0 ] ?. function ?. name ) . toBe (
416
+ "calculate" ,
417
+ ) ;
369
418
} ) ;
370
419
} ) ;
0 commit comments