@providerprotocol/agents 0.0.2 → 0.0.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.
Files changed (73) hide show
  1. package/dist/checkpoint/index.d.ts +43 -0
  2. package/dist/checkpoint/index.js +64 -0
  3. package/dist/checkpoint/index.js.map +1 -0
  4. package/{src/execution/loop.ts → dist/chunk-4ESYN66B.js} +54 -162
  5. package/dist/chunk-4ESYN66B.js.map +1 -0
  6. package/dist/chunk-EKRXMSDX.js +8 -0
  7. package/dist/chunk-EKRXMSDX.js.map +1 -0
  8. package/dist/chunk-PHI5ULBV.js +427 -0
  9. package/dist/chunk-PHI5ULBV.js.map +1 -0
  10. package/dist/execution/index.d.ts +105 -0
  11. package/dist/execution/index.js +679 -0
  12. package/dist/execution/index.js.map +1 -0
  13. package/dist/index-qsPwbY86.d.ts +65 -0
  14. package/dist/index.d.ts +101 -0
  15. package/dist/index.js +218 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/middleware/index.d.ts +23 -0
  18. package/dist/middleware/index.js +82 -0
  19. package/dist/middleware/index.js.map +1 -0
  20. package/dist/thread-tree/index.d.ts +115 -0
  21. package/dist/thread-tree/index.js +4 -0
  22. package/dist/thread-tree/index.js.map +1 -0
  23. package/dist/types-2Vsthzyu.d.ts +163 -0
  24. package/dist/types-BhX9uD_d.d.ts +91 -0
  25. package/dist/types-DR02gtFv.d.ts +270 -0
  26. package/dist/types-NGQMdnaD.d.ts +65 -0
  27. package/package.json +40 -8
  28. package/.claude/settings.local.json +0 -29
  29. package/AGENTS.md +0 -681
  30. package/CLAUDE.md +0 -681
  31. package/bun.lock +0 -472
  32. package/eslint.config.js +0 -75
  33. package/index.ts +0 -1
  34. package/llms.md +0 -796
  35. package/specs/UAP-1.0.md +0 -2355
  36. package/src/agent/index.ts +0 -384
  37. package/src/agent/types.ts +0 -91
  38. package/src/checkpoint/file.ts +0 -126
  39. package/src/checkpoint/index.ts +0 -40
  40. package/src/checkpoint/types.ts +0 -95
  41. package/src/execution/index.ts +0 -37
  42. package/src/execution/plan.ts +0 -497
  43. package/src/execution/react.ts +0 -340
  44. package/src/execution/tool-ordering.ts +0 -186
  45. package/src/execution/types.ts +0 -315
  46. package/src/index.ts +0 -80
  47. package/src/middleware/index.ts +0 -7
  48. package/src/middleware/logging.ts +0 -123
  49. package/src/middleware/types.ts +0 -69
  50. package/src/state/index.ts +0 -301
  51. package/src/state/types.ts +0 -173
  52. package/src/thread-tree/index.ts +0 -249
  53. package/src/thread-tree/types.ts +0 -29
  54. package/src/utils/uuid.ts +0 -7
  55. package/tests/live/agent-anthropic.test.ts +0 -288
  56. package/tests/live/agent-strategy-hooks.test.ts +0 -268
  57. package/tests/live/checkpoint.test.ts +0 -243
  58. package/tests/live/execution-strategies.test.ts +0 -255
  59. package/tests/live/plan-strategy.test.ts +0 -160
  60. package/tests/live/subagent-events.live.test.ts +0 -249
  61. package/tests/live/thread-tree.test.ts +0 -186
  62. package/tests/unit/agent.test.ts +0 -703
  63. package/tests/unit/checkpoint.test.ts +0 -232
  64. package/tests/unit/execution/equivalence.test.ts +0 -402
  65. package/tests/unit/execution/loop.test.ts +0 -437
  66. package/tests/unit/execution/plan.test.ts +0 -590
  67. package/tests/unit/execution/react.test.ts +0 -604
  68. package/tests/unit/execution/subagent-events.test.ts +0 -235
  69. package/tests/unit/execution/tool-ordering.test.ts +0 -310
  70. package/tests/unit/middleware/logging.test.ts +0 -276
  71. package/tests/unit/state.test.ts +0 -573
  72. package/tests/unit/thread-tree.test.ts +0 -249
  73. package/tsconfig.json +0 -29
@@ -1,437 +0,0 @@
1
- import { describe, test, expect, mock, beforeEach } from 'bun:test';
2
- import { UserMessage, AssistantMessage } from '@providerprotocol/ai';
3
- import type { Turn, LLMInstance, Tool, ToolCall, ToolExecution } from '@providerprotocol/ai';
4
- import { loop } from '../../../src/execution/loop.ts';
5
- import { AgentState } from '../../../src/state/index.ts';
6
- import type { ExecutionContext } from '../../../src/execution/types.ts';
7
-
8
- // Mock Turn factory
9
- function createMockTurn(options: {
10
- text?: string;
11
- toolCalls?: ToolCall[];
12
- toolExecutions?: ToolExecution[];
13
- }): Turn {
14
- const response = new AssistantMessage(options.text ?? 'Hello', options.toolCalls);
15
- return {
16
- response,
17
- messages: [response],
18
- toolExecutions: options.toolExecutions ?? [],
19
- usage: {
20
- inputTokens: 10,
21
- outputTokens: 20,
22
- totalTokens: 30,
23
- },
24
- cycles: 1,
25
- } as unknown as Turn;
26
- }
27
-
28
- // Mock LLM factory
29
- function createMockLLM(turns: Turn[]): LLMInstance {
30
- let callIndex = 0;
31
-
32
- return {
33
- generate: mock(async () => {
34
- const turn = turns[callIndex] ?? turns[turns.length - 1];
35
- callIndex++;
36
- return turn;
37
- }),
38
- stream: mock(() => {
39
- const turn = turns[callIndex] ?? turns[turns.length - 1];
40
- callIndex++;
41
-
42
- const events: Array<{ type: string; delta?: { text?: string } }> = [];
43
- if (turn) {
44
- events.push({ type: 'text_delta', delta: { text: turn.response.text } });
45
- events.push({ type: 'message_stop' });
46
- }
47
-
48
- return {
49
- async *[Symbol.asyncIterator] () {
50
- for (const event of events) {
51
- yield event;
52
- }
53
- },
54
- turn: Promise.resolve(turn),
55
- };
56
- }),
57
- } as unknown as LLMInstance;
58
- }
59
-
60
- describe('loop() execution strategy', () => {
61
- let state: AgentState;
62
- let input: UserMessage;
63
- let tools: Tool[];
64
-
65
- beforeEach(() => {
66
- state = AgentState.initial();
67
- input = new UserMessage('Hello');
68
- tools = [];
69
- });
70
-
71
- describe('execute()', () => {
72
- test('returns turn and updated state', async () => {
73
- const mockTurn = createMockTurn({ text: 'Hi there!' });
74
- const llm = createMockLLM([mockTurn]);
75
-
76
- const strategy = loop();
77
- const context: ExecutionContext = {
78
- agent: { id: 'test-agent' },
79
- llm,
80
- input,
81
- state,
82
- tools,
83
- strategy: {},
84
- };
85
-
86
- const result = await strategy.execute(context);
87
-
88
- expect(result.turn).toBe(mockTurn);
89
- expect(result.state.messages.length).toBeGreaterThan(0);
90
- });
91
-
92
- test('loops on tool calls', async () => {
93
- const toolCall: ToolCall = {
94
- toolCallId: 'call-1',
95
- toolName: 'test_tool',
96
- arguments: { arg: 'value' },
97
- };
98
-
99
- const turn1 = createMockTurn({
100
- text: 'Calling tool...',
101
- toolCalls: [toolCall],
102
- toolExecutions: [{ toolCallId: 'call-1', toolName: 'test_tool', arguments: { arg: 'value' }, result: 'done', duration: 100, isError: false }],
103
- });
104
- const turn2 = createMockTurn({ text: 'Done!', toolCalls: [] });
105
-
106
- const llm = createMockLLM([turn1, turn2]);
107
-
108
- const strategy = loop();
109
- const context: ExecutionContext = {
110
- agent: { id: 'test-agent' },
111
- llm,
112
- input,
113
- state,
114
- tools,
115
- strategy: {},
116
- };
117
-
118
- const result = await strategy.execute(context);
119
-
120
- expect(llm.generate).toHaveBeenCalledTimes(2);
121
- expect(result.turn.response.text).toBe('Done!');
122
- });
123
-
124
- test('respects maxIterations', async () => {
125
- const toolCall: ToolCall = {
126
- toolCallId: 'call-1',
127
- toolName: 'test_tool',
128
- arguments: {},
129
- };
130
-
131
- const turnWithTool = createMockTurn({
132
- text: 'Looping...',
133
- toolCalls: [toolCall],
134
- toolExecutions: [{ toolCallId: 'call-1', toolName: 'test_tool', arguments: {}, result: 'ok', duration: 10, isError: false }],
135
- });
136
-
137
- const llm = createMockLLM([turnWithTool, turnWithTool, turnWithTool, turnWithTool, turnWithTool]);
138
-
139
- const strategy = loop({ maxIterations: 3 });
140
- const context: ExecutionContext = {
141
- agent: { id: 'test-agent' },
142
- llm,
143
- input,
144
- state,
145
- tools,
146
- strategy: {},
147
- };
148
-
149
- await strategy.execute(context);
150
-
151
- expect(llm.generate).toHaveBeenCalledTimes(3);
152
- });
153
-
154
- test('defaults to Infinity maxIterations', async () => {
155
- const strategy = loop();
156
- expect(strategy.name).toBe('loop');
157
- // The default is Infinity, but we can't easily test infinite behavior
158
- // We test this by verifying it loops more than a small number
159
- });
160
-
161
- test('calls onStepStart hook', async () => {
162
- const mockTurn = createMockTurn({ text: 'Response' });
163
- const llm = createMockLLM([mockTurn]);
164
- const onStepStart = mock(() => {});
165
-
166
- const strategy = loop();
167
- const context: ExecutionContext = {
168
- agent: { id: 'test-agent' },
169
- llm,
170
- input,
171
- state,
172
- tools,
173
- strategy: { onStepStart },
174
- };
175
-
176
- await strategy.execute(context);
177
-
178
- expect(onStepStart).toHaveBeenCalledTimes(1);
179
- // Verify the hook was called with step number and a state object
180
- expect(onStepStart).toHaveBeenCalled();
181
- });
182
-
183
- test('calls onStepEnd hook', async () => {
184
- const mockTurn = createMockTurn({ text: 'Response' });
185
- const llm = createMockLLM([mockTurn]);
186
- const onStepEnd = mock(() => {});
187
-
188
- const strategy = loop();
189
- const context: ExecutionContext = {
190
- agent: { id: 'test-agent' },
191
- llm,
192
- input,
193
- state,
194
- tools,
195
- strategy: { onStepEnd },
196
- };
197
-
198
- await strategy.execute(context);
199
-
200
- expect(onStepEnd).toHaveBeenCalledTimes(1);
201
- // Verify the hook was called with step number and result object
202
- expect(onStepEnd).toHaveBeenCalled();
203
- });
204
-
205
- test('calls onAct hook on tool calls', async () => {
206
- const toolCall: ToolCall = {
207
- toolCallId: 'call-1',
208
- toolName: 'test_tool',
209
- arguments: {},
210
- };
211
-
212
- const turn1 = createMockTurn({
213
- text: 'Using tool',
214
- toolCalls: [toolCall],
215
- });
216
- const turn2 = createMockTurn({ text: 'Done' }); // Terminating turn
217
- const llm = createMockLLM([turn1, turn2]);
218
- const onAct = mock(() => {});
219
-
220
- const strategy = loop();
221
- const context: ExecutionContext = {
222
- agent: { id: 'test-agent' },
223
- llm,
224
- input,
225
- state,
226
- tools,
227
- strategy: { onAct },
228
- };
229
-
230
- await strategy.execute(context);
231
-
232
- expect(onAct).toHaveBeenCalledWith(1, [toolCall]);
233
- });
234
-
235
- test('calls onObserve hook on tool executions', async () => {
236
- const execution: ToolExecution = {
237
- toolCallId: 'call-1',
238
- toolName: 'test_tool',
239
- arguments: {},
240
- result: 'result',
241
- duration: 100,
242
- isError: false,
243
- };
244
-
245
- // Turn with tool execution but no tool calls (so it terminates)
246
- const turn = createMockTurn({
247
- text: 'Done',
248
- toolExecutions: [execution],
249
- });
250
- const llm = createMockLLM([turn]);
251
- const onObserve = mock(() => {});
252
-
253
- const strategy = loop();
254
- const context: ExecutionContext = {
255
- agent: { id: 'test-agent' },
256
- llm,
257
- input,
258
- state,
259
- tools,
260
- strategy: { onObserve },
261
- };
262
-
263
- await strategy.execute(context);
264
-
265
- expect(onObserve).toHaveBeenCalledWith(1, [execution]);
266
- });
267
-
268
- test('calls onComplete hook', async () => {
269
- const mockTurn = createMockTurn({ text: 'Response' });
270
- const llm = createMockLLM([mockTurn]);
271
- const onComplete = mock(() => {});
272
-
273
- const strategy = loop();
274
- const context: ExecutionContext = {
275
- agent: { id: 'test-agent' },
276
- llm,
277
- input,
278
- state,
279
- tools,
280
- strategy: { onComplete },
281
- };
282
-
283
- await strategy.execute(context);
284
-
285
- expect(onComplete).toHaveBeenCalledTimes(1);
286
- });
287
-
288
- test('respects stopCondition', async () => {
289
- const toolCall: ToolCall = {
290
- toolCallId: 'call-1',
291
- toolName: 'test_tool',
292
- arguments: {},
293
- };
294
-
295
- const turnWithTool = createMockTurn({
296
- text: 'Looping...',
297
- toolCalls: [toolCall],
298
- toolExecutions: [{ toolCallId: 'call-1', toolName: 'test_tool', arguments: {}, result: 'ok', duration: 10, isError: false }],
299
- });
300
-
301
- const llm = createMockLLM([turnWithTool, turnWithTool, turnWithTool]);
302
-
303
- const stopAfter = 2;
304
- const strategy = loop();
305
- const context: ExecutionContext = {
306
- agent: { id: 'test-agent' },
307
- llm,
308
- input,
309
- state,
310
- tools,
311
- strategy: {
312
- stopCondition: (s) => s.step >= stopAfter,
313
- },
314
- };
315
-
316
- await strategy.execute(context);
317
-
318
- expect(llm.generate).toHaveBeenCalledTimes(2);
319
- });
320
-
321
- test('updates state step number', async () => {
322
- const toolCall: ToolCall = {
323
- toolCallId: 'call-1',
324
- toolName: 'test_tool',
325
- arguments: {},
326
- };
327
-
328
- const turn1 = createMockTurn({
329
- text: 'Step 1',
330
- toolCalls: [toolCall],
331
- toolExecutions: [{ toolCallId: 'call-1', toolName: 'test_tool', arguments: {}, result: 'ok', duration: 10, isError: false }],
332
- });
333
- const turn2 = createMockTurn({ text: 'Step 2' });
334
-
335
- const llm = createMockLLM([turn1, turn2]);
336
-
337
- const strategy = loop();
338
- const context: ExecutionContext = {
339
- agent: { id: 'test-agent' },
340
- llm,
341
- input,
342
- state,
343
- tools,
344
- strategy: {},
345
- };
346
-
347
- const result = await strategy.execute(context);
348
-
349
- expect(result.state.step).toBe(2);
350
- });
351
- });
352
-
353
- describe('stream()', () => {
354
- test('yields events and resolves result', async () => {
355
- const mockTurn = createMockTurn({ text: 'Streamed response' });
356
- const llm = createMockLLM([mockTurn]);
357
-
358
- const strategy = loop();
359
- const context: ExecutionContext = {
360
- agent: { id: 'test-agent' },
361
- llm,
362
- input,
363
- state,
364
- tools,
365
- strategy: {},
366
- };
367
-
368
- const streamResult = strategy.stream(context);
369
- const events: unknown[] = [];
370
-
371
- for await (const event of streamResult) {
372
- events.push(event);
373
- }
374
-
375
- const result = await streamResult.result;
376
-
377
- expect(events.length).toBeGreaterThan(0);
378
- expect(result.turn).toBeDefined();
379
- expect(result.state).toBeDefined();
380
- });
381
-
382
- test('emits step_start and step_end events', async () => {
383
- const mockTurn = createMockTurn({ text: 'Response' });
384
- const llm = createMockLLM([mockTurn]);
385
-
386
- const strategy = loop();
387
- const context: ExecutionContext = {
388
- agent: { id: 'test-agent' },
389
- llm,
390
- input,
391
- state,
392
- tools,
393
- strategy: {},
394
- };
395
-
396
- const streamResult = strategy.stream(context);
397
- const uapEvents: Array<{ source: string; uap?: { type: string } }> = [];
398
-
399
- for await (const event of streamResult) {
400
- if (event.source === 'uap') {
401
- uapEvents.push(event as { source: string; uap?: { type: string } });
402
- }
403
- }
404
-
405
- await streamResult.result;
406
-
407
- const stepStart = uapEvents.find((e) => e.uap?.type === 'step_start');
408
- const stepEnd = uapEvents.find((e) => e.uap?.type === 'step_end');
409
-
410
- expect(stepStart).toBeDefined();
411
- expect(stepEnd).toBeDefined();
412
- });
413
-
414
- test('supports abort()', async () => {
415
- const mockTurn = createMockTurn({ text: 'Response' });
416
- const llm = createMockLLM([mockTurn]);
417
-
418
- const strategy = loop();
419
- const context: ExecutionContext = {
420
- agent: { id: 'test-agent' },
421
- llm,
422
- input,
423
- state,
424
- tools,
425
- strategy: {},
426
- };
427
-
428
- const streamResult = strategy.stream(context);
429
-
430
- // Abort immediately
431
- streamResult.abort();
432
-
433
- // The stream should handle abort gracefully
434
- // Note: exact behavior depends on timing
435
- });
436
- });
437
- });