Skip to content

Commit 78ddebb

Browse files
Fix nondeterministic Node E2E test
1 parent 1603120 commit 78ddebb

3 files changed

Lines changed: 182 additions & 67 deletions

File tree

nodejs/test/e2e/multi-client.test.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,16 @@ describe("Multi-client broadcast", async () => {
230230
tools: [toolB],
231231
});
232232

233-
// Send a prompt that requires both tools
234-
const response = await session1.sendAndWait({
235-
prompt: "Use the city_lookup tool with countryCode 'US' and the currency_lookup tool with countryCode 'US'. Tell me both results.",
233+
// Send prompts sequentially to avoid nondeterministic tool_call ordering
234+
const response1 = await session1.sendAndWait({
235+
prompt: "Use the city_lookup tool with countryCode 'US' and tell me the result.",
236236
});
237+
expect(response1?.data.content).toContain("CITY_FOR_US");
237238

238-
expect(response?.data.content).toContain("CITY_FOR_US");
239-
expect(response?.data.content).toContain("CURRENCY_FOR_US");
239+
const response2 = await session1.sendAndWait({
240+
prompt: "Now use the currency_lookup tool with countryCode 'US' and tell me the result.",
241+
});
242+
expect(response2?.data.content).toContain("CURRENCY_FOR_US");
240243

241244
await session2.disconnect();
242245
}
@@ -267,12 +270,16 @@ describe("Multi-client broadcast", async () => {
267270
tools: [toolB],
268271
});
269272

270-
// Verify both tools work before disconnect
271-
const bothResponse = await session1.sendAndWait({
272-
prompt: "Use the stable_tool with input 'test1' and the ephemeral_tool with input 'test2'. Tell me both results.",
273+
// Verify both tools work before disconnect (sequential to avoid nondeterministic tool_call ordering)
274+
const stableResponse = await session1.sendAndWait({
275+
prompt: "Use the stable_tool with input 'test1' and tell me the result.",
276+
});
277+
expect(stableResponse?.data.content).toContain("STABLE_test1");
278+
279+
const ephemeralResponse = await session1.sendAndWait({
280+
prompt: "Use the ephemeral_tool with input 'test2' and tell me the result.",
273281
});
274-
expect(bothResponse?.data.content).toContain("STABLE_test1");
275-
expect(bothResponse?.data.content).toContain("EPHEMERAL_test2");
282+
expect(ephemeralResponse?.data.content).toContain("EPHEMERAL_test2");
276283

277284
// Disconnect client 2 without destroying the shared session
278285
await client2.forceStop();

test/snapshots/multi_client/disconnecting_client_removes_its_tools.yaml

Lines changed: 101 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,63 @@ conversations:
55
- role: system
66
content: ${system}
77
- role: user
8-
content: Use the stable_tool with input 'test1' and the ephemeral_tool with input 'test2'. Tell me both results.
8+
content: Use the stable_tool with input 'test1' and tell me the result.
99
- role: assistant
10-
content: I'll call both tools for you and report the results.
10+
content: I'll call the stable_tool with input 'test1' for you.
1111
- role: assistant
1212
tool_calls:
1313
- id: toolcall_0
1414
type: function
1515
function:
1616
name: report_intent
17-
arguments: '{"intent":"Testing stable and ephemeral tools"}'
17+
arguments: '{"intent":"Testing stable_tool"}'
1818
- role: assistant
1919
tool_calls:
2020
- id: toolcall_1
2121
type: function
2222
function:
2323
name: stable_tool
2424
arguments: '{"input":"test1"}'
25+
- messages:
26+
- role: system
27+
content: ${system}
28+
- role: user
29+
content: Use the stable_tool with input 'test1' and tell me the result.
30+
- role: assistant
31+
content: I'll call the stable_tool with input 'test1' for you.
32+
tool_calls:
33+
- id: toolcall_0
34+
type: function
35+
function:
36+
name: report_intent
37+
arguments: '{"intent":"Testing stable_tool"}'
38+
- id: toolcall_1
39+
type: function
40+
function:
41+
name: stable_tool
42+
arguments: '{"input":"test1"}'
43+
- role: tool
44+
tool_call_id: toolcall_0
45+
content: Intent logged
46+
- role: tool
47+
tool_call_id: toolcall_1
48+
content: STABLE_test1
49+
- role: assistant
50+
content: "The stable_tool returned: **STABLE_test1**"
51+
- role: user
52+
content: Use the ephemeral_tool with input 'test2' and tell me the result.
53+
- role: assistant
54+
content: I'll call the ephemeral_tool with input 'test2' for you.
2555
- role: assistant
2656
tool_calls:
2757
- id: toolcall_2
58+
type: function
59+
function:
60+
name: report_intent
61+
arguments: '{"intent":"Testing ephemeral_tool"}'
62+
- role: assistant
63+
tool_calls:
64+
- id: toolcall_3
2865
type: function
2966
function:
3067
name: ephemeral_tool
@@ -33,39 +70,51 @@ conversations:
3370
- role: system
3471
content: ${system}
3572
- role: user
36-
content: Use the stable_tool with input 'test1' and the ephemeral_tool with input 'test2'. Tell me both results.
73+
content: Use the stable_tool with input 'test1' and tell me the result.
3774
- role: assistant
38-
content: I'll call both tools for you and report the results.
75+
content: I'll call the stable_tool with input 'test1' for you.
3976
tool_calls:
4077
- id: toolcall_0
4178
type: function
4279
function:
4380
name: report_intent
44-
arguments: '{"intent":"Testing stable and ephemeral tools"}'
81+
arguments: '{"intent":"Testing stable_tool"}'
4582
- id: toolcall_1
4683
type: function
4784
function:
4885
name: stable_tool
4986
arguments: '{"input":"test1"}'
50-
- id: toolcall_2
51-
type: function
52-
function:
53-
name: ephemeral_tool
54-
arguments: '{"input":"test2"}'
5587
- role: tool
5688
tool_call_id: toolcall_0
5789
content: Intent logged
5890
- role: tool
5991
tool_call_id: toolcall_1
6092
content: STABLE_test1
93+
- role: assistant
94+
content: "The stable_tool returned: **STABLE_test1**"
95+
- role: user
96+
content: Use the ephemeral_tool with input 'test2' and tell me the result.
97+
- role: assistant
98+
content: I'll call the ephemeral_tool with input 'test2' for you.
99+
tool_calls:
100+
- id: toolcall_2
101+
type: function
102+
function:
103+
name: report_intent
104+
arguments: '{"intent":"Testing ephemeral_tool"}'
105+
- id: toolcall_3
106+
type: function
107+
function:
108+
name: ephemeral_tool
109+
arguments: '{"input":"test2"}'
61110
- role: tool
62111
tool_call_id: toolcall_2
112+
content: Intent logged
113+
- role: tool
114+
tool_call_id: toolcall_3
63115
content: EPHEMERAL_test2
64116
- role: assistant
65-
content: |-
66-
Both tools executed successfully:
67-
- **stable_tool** returned: `STABLE_test1`
68-
- **ephemeral_tool** returned: `EPHEMERAL_test2`
117+
content: "The ephemeral_tool returned: **EPHEMERAL_test2**"
69118
- role: user
70119
content: >-
71120
<tools_changed_notice>
@@ -81,17 +130,18 @@ conversations:
81130
82131
Use the stable_tool with input 'still_here'. Also try using ephemeral_tool if it is available.
83132
- role: assistant
84-
content: I'll call the stable_tool and check on the ephemeral_tool availability.
133+
content: I'll call the stable_tool with input 'still_here'. The ephemeral_tool is no longer available, so I can only use
134+
the stable_tool.
85135
- role: assistant
86136
tool_calls:
87-
- id: toolcall_3
137+
- id: toolcall_4
88138
type: function
89139
function:
90140
name: report_intent
91141
arguments: '{"intent":"Testing tool availability"}'
92142
- role: assistant
93143
tool_calls:
94-
- id: toolcall_4
144+
- id: toolcall_5
95145
type: function
96146
function:
97147
name: stable_tool
@@ -100,39 +150,51 @@ conversations:
100150
- role: system
101151
content: ${system}
102152
- role: user
103-
content: Use the stable_tool with input 'test1' and the ephemeral_tool with input 'test2'. Tell me both results.
153+
content: Use the stable_tool with input 'test1' and tell me the result.
104154
- role: assistant
105-
content: I'll call both tools for you and report the results.
155+
content: I'll call the stable_tool with input 'test1' for you.
106156
tool_calls:
107157
- id: toolcall_0
108158
type: function
109159
function:
110160
name: report_intent
111-
arguments: '{"intent":"Testing stable and ephemeral tools"}'
161+
arguments: '{"intent":"Testing stable_tool"}'
112162
- id: toolcall_1
113163
type: function
114164
function:
115165
name: stable_tool
116166
arguments: '{"input":"test1"}'
117-
- id: toolcall_2
118-
type: function
119-
function:
120-
name: ephemeral_tool
121-
arguments: '{"input":"test2"}'
122167
- role: tool
123168
tool_call_id: toolcall_0
124169
content: Intent logged
125170
- role: tool
126171
tool_call_id: toolcall_1
127172
content: STABLE_test1
173+
- role: assistant
174+
content: "The stable_tool returned: **STABLE_test1**"
175+
- role: user
176+
content: Use the ephemeral_tool with input 'test2' and tell me the result.
177+
- role: assistant
178+
content: I'll call the ephemeral_tool with input 'test2' for you.
179+
tool_calls:
180+
- id: toolcall_2
181+
type: function
182+
function:
183+
name: report_intent
184+
arguments: '{"intent":"Testing ephemeral_tool"}'
185+
- id: toolcall_3
186+
type: function
187+
function:
188+
name: ephemeral_tool
189+
arguments: '{"input":"test2"}'
128190
- role: tool
129191
tool_call_id: toolcall_2
192+
content: Intent logged
193+
- role: tool
194+
tool_call_id: toolcall_3
130195
content: EPHEMERAL_test2
131196
- role: assistant
132-
content: |-
133-
Both tools executed successfully:
134-
- **stable_tool** returned: `STABLE_test1`
135-
- **ephemeral_tool** returned: `EPHEMERAL_test2`
197+
content: "The ephemeral_tool returned: **EPHEMERAL_test2**"
136198
- role: user
137199
content: >-
138200
<tools_changed_notice>
@@ -148,28 +210,27 @@ conversations:
148210
149211
Use the stable_tool with input 'still_here'. Also try using ephemeral_tool if it is available.
150212
- role: assistant
151-
content: I'll call the stable_tool and check on the ephemeral_tool availability.
213+
content: I'll call the stable_tool with input 'still_here'. The ephemeral_tool is no longer available, so I can only use
214+
the stable_tool.
152215
tool_calls:
153-
- id: toolcall_3
216+
- id: toolcall_4
154217
type: function
155218
function:
156219
name: report_intent
157220
arguments: '{"intent":"Testing tool availability"}'
158-
- id: toolcall_4
221+
- id: toolcall_5
159222
type: function
160223
function:
161224
name: stable_tool
162225
arguments: '{"input":"still_here"}'
163226
- role: tool
164-
tool_call_id: toolcall_3
227+
tool_call_id: toolcall_4
165228
content: Intent logged
166229
- role: tool
167-
tool_call_id: toolcall_4
230+
tool_call_id: toolcall_5
168231
content: STABLE_still_here
169232
- role: assistant
170-
content: >-
171-
**stable_tool** returned: `STABLE_still_here`
172-
233+
content: |-
234+
The stable_tool returned: **STABLE_still_here**
173235
174-
The **ephemeral_tool** is no longer available (it was removed as indicated in the tools_changed_notice), so I
175-
couldn't call it.
236+
The ephemeral_tool is not available anymore (it was removed), so I could only call the stable_tool.

0 commit comments

Comments
 (0)