@strands-agents/sdk 1.0.0-rc.2 → 1.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/src/__fixtures__/agent-helpers.d.ts.map +1 -1
- package/dist/src/__fixtures__/agent-helpers.js +1 -0
- package/dist/src/__fixtures__/agent-helpers.js.map +1 -1
- package/dist/src/agent/__tests__/agent-as-tool.test.d.ts +2 -0
- package/dist/src/agent/__tests__/agent-as-tool.test.d.ts.map +1 -0
- package/dist/src/agent/__tests__/agent-as-tool.test.js +347 -0
- package/dist/src/agent/__tests__/agent-as-tool.test.js.map +1 -0
- package/dist/src/agent/__tests__/agent.cancel.test.d.ts +2 -0
- package/dist/src/agent/__tests__/agent.cancel.test.d.ts.map +1 -0
- package/dist/src/agent/__tests__/agent.cancel.test.js +337 -0
- package/dist/src/agent/__tests__/agent.cancel.test.js.map +1 -0
- package/dist/src/agent/__tests__/agent.test.js +4 -1
- package/dist/src/agent/__tests__/agent.test.js.map +1 -1
- package/dist/src/agent/__tests__/snapshot.test.js +12 -1
- package/dist/src/agent/__tests__/snapshot.test.js.map +1 -1
- package/dist/src/agent/agent-as-tool.d.ts +96 -0
- package/dist/src/agent/agent-as-tool.d.ts.map +1 -0
- package/dist/src/agent/agent-as-tool.js +135 -0
- package/dist/src/agent/agent-as-tool.js.map +1 -0
- package/dist/src/agent/agent.d.ts +87 -3
- package/dist/src/agent/agent.d.ts.map +1 -1
- package/dist/src/agent/agent.js +188 -5
- package/dist/src/agent/agent.js.map +1 -1
- package/dist/src/agent/snapshot.d.ts +1 -33
- package/dist/src/agent/snapshot.d.ts.map +1 -1
- package/dist/src/agent/snapshot.js +4 -4
- package/dist/src/agent/snapshot.js.map +1 -1
- package/dist/src/errors.d.ts +9 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +12 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/models/__tests__/bedrock.test.js +51 -0
- package/dist/src/models/__tests__/bedrock.test.js.map +1 -1
- package/dist/src/models/bedrock.d.ts +10 -0
- package/dist/src/models/bedrock.d.ts.map +1 -1
- package/dist/src/models/bedrock.js +25 -2
- package/dist/src/models/bedrock.js.map +1 -1
- package/dist/src/multiagent/__tests__/snapshot.test.d.ts +2 -0
- package/dist/src/multiagent/__tests__/snapshot.test.d.ts.map +1 -0
- package/dist/src/multiagent/__tests__/snapshot.test.js +161 -0
- package/dist/src/multiagent/__tests__/snapshot.test.js.map +1 -0
- package/dist/src/multiagent/plugins.d.ts +8 -8
- package/dist/src/multiagent/plugins.d.ts.map +1 -1
- package/dist/src/multiagent/plugins.js +1 -30
- package/dist/src/multiagent/plugins.js.map +1 -1
- package/dist/src/multiagent/snapshot.d.ts +51 -0
- package/dist/src/multiagent/snapshot.d.ts.map +1 -0
- package/dist/src/multiagent/snapshot.js +69 -0
- package/dist/src/multiagent/snapshot.js.map +1 -0
- package/dist/src/session/__tests__/session-manager.test.js +244 -1
- package/dist/src/session/__tests__/session-manager.test.js.map +1 -1
- package/dist/src/session/index.d.ts +2 -2
- package/dist/src/session/index.d.ts.map +1 -1
- package/dist/src/session/session-manager.d.ts +42 -4
- package/dist/src/session/session-manager.d.ts.map +1 -1
- package/dist/src/session/session-manager.js +64 -10
- package/dist/src/session/session-manager.js.map +1 -1
- package/dist/src/session/types.d.ts +1 -1
- package/dist/src/tools/tool.d.ts +1 -1
- package/dist/src/tsconfig.tsbuildinfo +1 -1
- package/dist/src/types/agent.d.ts +63 -0
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/agent.js.map +1 -1
- package/dist/src/types/messages.d.ts +2 -1
- package/dist/src/types/messages.d.ts.map +1 -1
- package/dist/src/types/messages.js.map +1 -1
- package/dist/src/types/snapshot.d.ts +28 -0
- package/dist/src/types/snapshot.d.ts.map +1 -0
- package/dist/src/types/snapshot.js +8 -0
- package/dist/src/types/snapshot.js.map +1 -0
- package/dist/src/vended-tools/http-request/http-request.d.ts.map +1 -1
- package/dist/src/vended-tools/http-request/http-request.js +7 -22
- package/dist/src/vended-tools/http-request/http-request.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { Agent } from '../agent.js';
|
|
3
|
+
import { AfterInvocationEvent, AfterModelCallEvent, BeforeModelCallEvent } from '../../hooks/index.js';
|
|
4
|
+
import { MockMessageModel } from '../../__fixtures__/mock-message-model.js';
|
|
5
|
+
import { createMockTool } from '../../__fixtures__/tool-helpers.js';
|
|
6
|
+
import { TextBlock, ToolResultBlock } from '../../types/messages.js';
|
|
7
|
+
import { tool } from '../../tools/tool-factory.js';
|
|
8
|
+
describe('Agent Cancellation', () => {
|
|
9
|
+
describe('cancel() when idle', () => {
|
|
10
|
+
it('is a no-op and cancelSignal is not aborted', () => {
|
|
11
|
+
const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
|
|
12
|
+
const agent = new Agent({ model });
|
|
13
|
+
expect(agent.cancelSignal.aborted).toBe(false);
|
|
14
|
+
agent.cancel(); // Should not throw
|
|
15
|
+
expect(agent.cancelSignal.aborted).toBe(false);
|
|
16
|
+
expect(agent.cancelSignal.aborted).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('cancel at top of loop (checkpoint A)', () => {
|
|
20
|
+
it('cancels immediately with already-aborted signal', async () => {
|
|
21
|
+
const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
|
|
22
|
+
const agent = new Agent({ model, printer: false });
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
controller.abort();
|
|
25
|
+
const result = await agent.invoke('Hi', { cancelSignal: controller.signal });
|
|
26
|
+
expect(result.stopReason).toBe('cancelled');
|
|
27
|
+
expect(result.lastMessage.content[0]).toEqual(new TextBlock('Cancelled by user'));
|
|
28
|
+
// User message is not appended — cancel fires before message append in the loop
|
|
29
|
+
expect(agent.messages).toHaveLength(1);
|
|
30
|
+
expect(agent.messages[0].role).toBe('assistant');
|
|
31
|
+
});
|
|
32
|
+
it('cancels at top of second cycle when tool calls cancel()', async () => {
|
|
33
|
+
const executedTools = [];
|
|
34
|
+
let agent;
|
|
35
|
+
const tool = createMockTool('cancelTool', () => {
|
|
36
|
+
executedTools.push('cancelTool');
|
|
37
|
+
agent.cancel();
|
|
38
|
+
return new ToolResultBlock({
|
|
39
|
+
toolUseId: 'tool-1',
|
|
40
|
+
status: 'success',
|
|
41
|
+
content: [new TextBlock('Done')],
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
const model = new MockMessageModel()
|
|
45
|
+
.addTurn({ type: 'toolUseBlock', name: 'cancelTool', toolUseId: 'tool-1', input: {} })
|
|
46
|
+
.addTurn({ type: 'textBlock', text: 'Should not reach' });
|
|
47
|
+
agent = new Agent({ model, tools: [tool], printer: false });
|
|
48
|
+
const result = await agent.invoke('Go');
|
|
49
|
+
expect(result.stopReason).toBe('cancelled');
|
|
50
|
+
expect(executedTools).toEqual(['cancelTool']);
|
|
51
|
+
// messages: user, assistant(toolUse), user(toolResult), assistant(synthetic cancel)
|
|
52
|
+
expect(agent.messages).toHaveLength(4);
|
|
53
|
+
expect(agent.messages[3].content[0]).toEqual(new TextBlock('Cancelled by user'));
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
describe('cancel during model streaming (checkpoint B)', () => {
|
|
57
|
+
it('cancels when signal is aborted before model processes events', async () => {
|
|
58
|
+
const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
|
|
59
|
+
const agent = new Agent({ model, printer: false });
|
|
60
|
+
agent.addHook(BeforeModelCallEvent, () => {
|
|
61
|
+
agent.cancel();
|
|
62
|
+
});
|
|
63
|
+
const result = await agent.invoke('Hi');
|
|
64
|
+
expect(result.stopReason).toBe('cancelled');
|
|
65
|
+
expect(result.lastMessage.content[0]).toEqual(new TextBlock('Cancelled by user'));
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
describe('cancel before tool execution (checkpoint C)', () => {
|
|
69
|
+
it('creates error results for all pending tools without executing them', async () => {
|
|
70
|
+
let toolExecuted = false;
|
|
71
|
+
const tool = createMockTool('myTool', () => {
|
|
72
|
+
toolExecuted = true;
|
|
73
|
+
return new ToolResultBlock({
|
|
74
|
+
toolUseId: 'tool-1',
|
|
75
|
+
status: 'success',
|
|
76
|
+
content: [new TextBlock('Success')],
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
const model = new MockMessageModel().addTurn({
|
|
80
|
+
type: 'toolUseBlock',
|
|
81
|
+
name: 'myTool',
|
|
82
|
+
toolUseId: 'tool-1',
|
|
83
|
+
input: {},
|
|
84
|
+
});
|
|
85
|
+
const agent = new Agent({ model, tools: [tool], printer: false });
|
|
86
|
+
agent.addHook(AfterModelCallEvent, (event) => {
|
|
87
|
+
if (event.stopData?.stopReason === 'toolUse') {
|
|
88
|
+
agent.cancel();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
const result = await agent.invoke('Do it');
|
|
92
|
+
expect(result.stopReason).toBe('cancelled');
|
|
93
|
+
expect(toolExecuted).toBe(false);
|
|
94
|
+
// Messages: user, assistant(toolUse), user(cancelled toolResult)
|
|
95
|
+
expect(agent.messages).toHaveLength(3);
|
|
96
|
+
const toolResultMsg = agent.messages[2];
|
|
97
|
+
expect(toolResultMsg.content[0]).toEqual(new ToolResultBlock({
|
|
98
|
+
toolUseId: 'tool-1',
|
|
99
|
+
status: 'error',
|
|
100
|
+
content: [new TextBlock('Tool execution cancelled')],
|
|
101
|
+
}));
|
|
102
|
+
});
|
|
103
|
+
it('creates error results for multiple pending tools', async () => {
|
|
104
|
+
const tool1 = createMockTool('tool1', () => {
|
|
105
|
+
return new ToolResultBlock({ toolUseId: 't1', status: 'success', content: [new TextBlock('R1')] });
|
|
106
|
+
});
|
|
107
|
+
const tool2 = createMockTool('tool2', () => {
|
|
108
|
+
return new ToolResultBlock({ toolUseId: 't2', status: 'success', content: [new TextBlock('R2')] });
|
|
109
|
+
});
|
|
110
|
+
const model = new MockMessageModel().addTurn([
|
|
111
|
+
{ type: 'toolUseBlock', name: 'tool1', toolUseId: 't1', input: {} },
|
|
112
|
+
{ type: 'toolUseBlock', name: 'tool2', toolUseId: 't2', input: {} },
|
|
113
|
+
]);
|
|
114
|
+
const agent = new Agent({ model, tools: [tool1, tool2], printer: false });
|
|
115
|
+
agent.addHook(AfterModelCallEvent, (event) => {
|
|
116
|
+
if (event.stopData?.stopReason === 'toolUse') {
|
|
117
|
+
agent.cancel();
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
const result = await agent.invoke('Do both');
|
|
121
|
+
expect(result.stopReason).toBe('cancelled');
|
|
122
|
+
const toolResultMsg = agent.messages[2];
|
|
123
|
+
expect(toolResultMsg.content).toHaveLength(2);
|
|
124
|
+
expect(toolResultMsg.content[0]).toEqual(new ToolResultBlock({ toolUseId: 't1', status: 'error', content: [new TextBlock('Tool execution cancelled')] }));
|
|
125
|
+
expect(toolResultMsg.content[1]).toEqual(new ToolResultBlock({ toolUseId: 't2', status: 'error', content: [new TextBlock('Tool execution cancelled')] }));
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
describe('cancel between sequential tool executions', () => {
|
|
129
|
+
it('skips remaining tools after first tool calls cancel()', async () => {
|
|
130
|
+
const executedTools = [];
|
|
131
|
+
let agent;
|
|
132
|
+
const tool1 = createMockTool('firstTool', () => {
|
|
133
|
+
executedTools.push('firstTool');
|
|
134
|
+
agent.cancel();
|
|
135
|
+
return new ToolResultBlock({ toolUseId: 't1', status: 'success', content: [new TextBlock('Done')] });
|
|
136
|
+
});
|
|
137
|
+
const tool2 = createMockTool('secondTool', () => {
|
|
138
|
+
executedTools.push('secondTool');
|
|
139
|
+
return new ToolResultBlock({ toolUseId: 't2', status: 'success', content: [new TextBlock('Done')] });
|
|
140
|
+
});
|
|
141
|
+
const model = new MockMessageModel()
|
|
142
|
+
.addTurn([
|
|
143
|
+
{ type: 'toolUseBlock', name: 'firstTool', toolUseId: 't1', input: {} },
|
|
144
|
+
{ type: 'toolUseBlock', name: 'secondTool', toolUseId: 't2', input: {} },
|
|
145
|
+
])
|
|
146
|
+
.addTurn({ type: 'textBlock', text: 'Should not reach' });
|
|
147
|
+
agent = new Agent({ model, tools: [tool1, tool2], printer: false });
|
|
148
|
+
const result = await agent.invoke('Go');
|
|
149
|
+
expect(result.stopReason).toBe('cancelled');
|
|
150
|
+
expect(executedTools).toEqual(['firstTool']);
|
|
151
|
+
// First tool succeeded, second was cancelled
|
|
152
|
+
// messages: user, assistant(toolUse), user(toolResults), assistant(synthetic cancel)
|
|
153
|
+
expect(agent.messages).toHaveLength(4);
|
|
154
|
+
const toolResultMsg = agent.messages[2];
|
|
155
|
+
expect(toolResultMsg.content[0]).toEqual(new ToolResultBlock({ toolUseId: 't1', status: 'success', content: [new TextBlock('Done')] }));
|
|
156
|
+
expect(toolResultMsg.content[1]).toEqual(new ToolResultBlock({ toolUseId: 't2', status: 'error', content: [new TextBlock('Tool execution cancelled')] }));
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe('InvokeOptions.cancelSignal', () => {
|
|
160
|
+
it('cancels via external AbortSignal', async () => {
|
|
161
|
+
const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
|
|
162
|
+
const agent = new Agent({ model, printer: false });
|
|
163
|
+
const controller = new AbortController();
|
|
164
|
+
agent.addHook(BeforeModelCallEvent, () => {
|
|
165
|
+
controller.abort();
|
|
166
|
+
});
|
|
167
|
+
const result = await agent.invoke('Hi', { cancelSignal: controller.signal });
|
|
168
|
+
expect(result.stopReason).toBe('cancelled');
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('agent reuse after cancel', () => {
|
|
172
|
+
it('allows a second invocation after cancellation', async () => {
|
|
173
|
+
const model = new MockMessageModel()
|
|
174
|
+
.addTurn({ type: 'textBlock', text: 'First' })
|
|
175
|
+
.addTurn({ type: 'textBlock', text: 'Second' });
|
|
176
|
+
const agent = new Agent({ model, printer: false });
|
|
177
|
+
let hookCallCount = 0;
|
|
178
|
+
agent.addHook(BeforeModelCallEvent, () => {
|
|
179
|
+
hookCallCount++;
|
|
180
|
+
if (hookCallCount === 1) {
|
|
181
|
+
agent.cancel();
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
// First invocation: cancelled
|
|
185
|
+
const result1 = await agent.invoke('Hello');
|
|
186
|
+
expect(result1.stopReason).toBe('cancelled');
|
|
187
|
+
// Second invocation: succeeds normally
|
|
188
|
+
const result2 = await agent.invoke('Hello again');
|
|
189
|
+
expect(result2.stopReason).toBe('endTurn');
|
|
190
|
+
expect(result2.lastMessage.content[0]).toEqual(new TextBlock('Second'));
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
describe('cancel via stream break (for-await + break)', () => {
|
|
194
|
+
it('appends assistant message when stream is broken out of after cancel()', async () => {
|
|
195
|
+
const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'A long story...' });
|
|
196
|
+
const agent = new Agent({ model, printer: false });
|
|
197
|
+
for await (const event of agent.stream('Write a story')) {
|
|
198
|
+
if (event.type === 'modelStreamUpdateEvent') {
|
|
199
|
+
agent.cancel();
|
|
200
|
+
break;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const lastMessage = agent.messages[agent.messages.length - 1];
|
|
204
|
+
expect(lastMessage.role).toBe('assistant');
|
|
205
|
+
expect(lastMessage.content[0]).toEqual(new TextBlock('Cancelled by user'));
|
|
206
|
+
});
|
|
207
|
+
it('allows reuse after cancellation via stream break', async () => {
|
|
208
|
+
const model = new MockMessageModel()
|
|
209
|
+
.addTurn({ type: 'textBlock', text: 'A long story...' })
|
|
210
|
+
.addTurn({ type: 'textBlock', text: 'pineapple' });
|
|
211
|
+
const agent = new Agent({ model, printer: false });
|
|
212
|
+
// First invocation: cancel during streaming via break
|
|
213
|
+
for await (const event of agent.stream('Write a story')) {
|
|
214
|
+
if (event.type === 'modelStreamUpdateEvent') {
|
|
215
|
+
agent.cancel();
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Second invocation: should succeed normally
|
|
220
|
+
const result = await agent.invoke('Say the word "pineapple"');
|
|
221
|
+
expect(result.stopReason).toBe('endTurn');
|
|
222
|
+
expect(result.lastMessage.content[0]).toEqual(new TextBlock('pineapple'));
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
describe('AfterInvocationEvent', () => {
|
|
226
|
+
it('still fires when invocation is cancelled', async () => {
|
|
227
|
+
const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
|
|
228
|
+
const agent = new Agent({ model, printer: false });
|
|
229
|
+
let afterInvocationFired = false;
|
|
230
|
+
agent.addHook(AfterInvocationEvent, () => {
|
|
231
|
+
afterInvocationFired = true;
|
|
232
|
+
});
|
|
233
|
+
agent.addHook(BeforeModelCallEvent, () => {
|
|
234
|
+
agent.cancel();
|
|
235
|
+
});
|
|
236
|
+
await agent.invoke('Hi');
|
|
237
|
+
expect(afterInvocationFired).toBe(true);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
describe('messages state invariants', () => {
|
|
241
|
+
it('has no orphaned toolUse blocks after cancel during streaming', async () => {
|
|
242
|
+
const model = new MockMessageModel().addTurn({ type: 'textBlock', text: 'Hello' });
|
|
243
|
+
const agent = new Agent({ model, printer: false });
|
|
244
|
+
agent.addHook(BeforeModelCallEvent, () => {
|
|
245
|
+
agent.cancel();
|
|
246
|
+
});
|
|
247
|
+
await agent.invoke('Hi');
|
|
248
|
+
// Every assistant message with toolUse blocks must be followed by a user message with matching toolResults
|
|
249
|
+
for (let i = 0; i < agent.messages.length; i++) {
|
|
250
|
+
const msg = agent.messages[i];
|
|
251
|
+
if (msg.role === 'assistant') {
|
|
252
|
+
const toolUseBlocks = msg.content.filter((b) => b.type === 'toolUseBlock');
|
|
253
|
+
if (toolUseBlocks.length > 0) {
|
|
254
|
+
const nextMsg = agent.messages[i + 1];
|
|
255
|
+
expect(nextMsg).toBeDefined();
|
|
256
|
+
expect(nextMsg.role).toBe('user');
|
|
257
|
+
const toolResultBlocks = nextMsg.content.filter((b) => b.type === 'toolResultBlock');
|
|
258
|
+
expect(toolResultBlocks).toHaveLength(toolUseBlocks.length);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
it('has no orphaned toolUse blocks after cancel before tools', async () => {
|
|
264
|
+
const tool = createMockTool('myTool', () => {
|
|
265
|
+
return new ToolResultBlock({ toolUseId: 'tool-1', status: 'success', content: [new TextBlock('Done')] });
|
|
266
|
+
});
|
|
267
|
+
const model = new MockMessageModel().addTurn({
|
|
268
|
+
type: 'toolUseBlock',
|
|
269
|
+
name: 'myTool',
|
|
270
|
+
toolUseId: 'tool-1',
|
|
271
|
+
input: {},
|
|
272
|
+
});
|
|
273
|
+
const agent = new Agent({ model, tools: [tool], printer: false });
|
|
274
|
+
agent.addHook(AfterModelCallEvent, (event) => {
|
|
275
|
+
if (event.stopData?.stopReason === 'toolUse') {
|
|
276
|
+
agent.cancel();
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
await agent.invoke('Do it');
|
|
280
|
+
// Verify every toolUse has a matching toolResult
|
|
281
|
+
for (let i = 0; i < agent.messages.length; i++) {
|
|
282
|
+
const msg = agent.messages[i];
|
|
283
|
+
if (msg.role === 'assistant') {
|
|
284
|
+
const toolUseBlocks = msg.content.filter((b) => b.type === 'toolUseBlock');
|
|
285
|
+
if (toolUseBlocks.length > 0) {
|
|
286
|
+
const nextMsg = agent.messages[i + 1];
|
|
287
|
+
expect(nextMsg).toBeDefined();
|
|
288
|
+
expect(nextMsg.role).toBe('user');
|
|
289
|
+
const toolResultBlocks = nextMsg.content.filter((b) => b.type === 'toolResultBlock');
|
|
290
|
+
expect(toolResultBlocks).toHaveLength(toolUseBlocks.length);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
describe('tool-level cancellation cooperation', () => {
|
|
297
|
+
it('exposes cancelSignal to tools via context.agent', async () => {
|
|
298
|
+
let signalSeen;
|
|
299
|
+
const signalTool = tool({
|
|
300
|
+
name: 'signalTool',
|
|
301
|
+
description: 'Tool that reads the cancellation signal',
|
|
302
|
+
callback: (_input, context) => {
|
|
303
|
+
signalSeen = context?.agent.cancelSignal;
|
|
304
|
+
return 'done';
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
const model = new MockMessageModel()
|
|
308
|
+
.addTurn({ type: 'toolUseBlock', name: 'signalTool', toolUseId: 't1', input: {} })
|
|
309
|
+
.addTurn({ type: 'textBlock', text: 'Done' });
|
|
310
|
+
const agent = new Agent({ model, tools: [signalTool], printer: false });
|
|
311
|
+
await agent.invoke('Go');
|
|
312
|
+
expect(signalSeen).toBeInstanceOf(AbortSignal);
|
|
313
|
+
expect(signalSeen.aborted).toBe(false);
|
|
314
|
+
});
|
|
315
|
+
it('signal is aborted when tool checks it after cancel()', async () => {
|
|
316
|
+
let signalAborted;
|
|
317
|
+
let agent;
|
|
318
|
+
const checkTool = tool({
|
|
319
|
+
name: 'checkTool',
|
|
320
|
+
description: 'Tool that cancels then checks the signal',
|
|
321
|
+
callback: (_input, context) => {
|
|
322
|
+
agent.cancel();
|
|
323
|
+
signalAborted = context?.agent.cancelSignal.aborted;
|
|
324
|
+
return 'done';
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
const model = new MockMessageModel()
|
|
328
|
+
.addTurn({ type: 'toolUseBlock', name: 'checkTool', toolUseId: 't1', input: {} })
|
|
329
|
+
.addTurn({ type: 'textBlock', text: 'Should not reach' });
|
|
330
|
+
agent = new Agent({ model, tools: [checkTool], printer: false });
|
|
331
|
+
const result = await agent.invoke('Go');
|
|
332
|
+
expect(signalAborted).toBe(true);
|
|
333
|
+
expect(result.stopReason).toBe('cancelled');
|
|
334
|
+
});
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
//# sourceMappingURL=agent.cancel.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.cancel.test.js","sourceRoot":"","sources":["../../../../src/agent/__tests__/agent.cancel.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -117,7 +117,7 @@ describe('Agent', () => {
|
|
|
117
117
|
});
|
|
118
118
|
});
|
|
119
119
|
describe('hook error cleanup', () => {
|
|
120
|
-
it('fires AfterInvocationEvent when consumer breaks from stream', async () => {
|
|
120
|
+
it('fires AfterInvocationEvent when consumer breaks from stream and allows reinvocation', async () => {
|
|
121
121
|
const model = new MockMessageModel()
|
|
122
122
|
.addTurn({ type: 'toolUseBlock', name: 'testTool', toolUseId: 'tool-1', input: {} })
|
|
123
123
|
.addTurn({ type: 'textBlock', text: 'Done' });
|
|
@@ -135,6 +135,9 @@ describe('Agent', () => {
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
expect(afterInvocationCallback).toHaveBeenCalledOnce();
|
|
138
|
+
const result = await agent.invoke('Test again');
|
|
139
|
+
expect(result.stopReason).toBe('endTurn');
|
|
140
|
+
expect(result.lastMessage.content[0]).toEqual(new TextBlock('Done'));
|
|
138
141
|
});
|
|
139
142
|
});
|
|
140
143
|
});
|