@providerprotocol/agents 0.0.2 → 0.0.4

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 (74) hide show
  1. package/LICENSE +21 -0
  2. package/dist/checkpoint/index.d.ts +43 -0
  3. package/dist/checkpoint/index.js +73 -0
  4. package/dist/checkpoint/index.js.map +1 -0
  5. package/{src/execution/loop.ts → dist/chunk-4ESYN66B.js} +54 -162
  6. package/dist/chunk-4ESYN66B.js.map +1 -0
  7. package/dist/chunk-EKRXMSDX.js +8 -0
  8. package/dist/chunk-EKRXMSDX.js.map +1 -0
  9. package/dist/chunk-T47B3VAF.js +427 -0
  10. package/dist/chunk-T47B3VAF.js.map +1 -0
  11. package/dist/execution/index.d.ts +105 -0
  12. package/dist/execution/index.js +679 -0
  13. package/dist/execution/index.js.map +1 -0
  14. package/dist/index-qsPwbY86.d.ts +65 -0
  15. package/dist/index.d.ts +101 -0
  16. package/dist/index.js +218 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/middleware/index.d.ts +23 -0
  19. package/dist/middleware/index.js +82 -0
  20. package/dist/middleware/index.js.map +1 -0
  21. package/dist/thread-tree/index.d.ts +115 -0
  22. package/dist/thread-tree/index.js +4 -0
  23. package/dist/thread-tree/index.js.map +1 -0
  24. package/dist/types-2Vsthzyu.d.ts +163 -0
  25. package/dist/types-BiyEVOnf.d.ts +65 -0
  26. package/dist/types-D1egxttz.d.ts +270 -0
  27. package/dist/types-DChRdQoX.d.ts +98 -0
  28. package/package.json +41 -9
  29. package/.claude/settings.local.json +0 -29
  30. package/AGENTS.md +0 -681
  31. package/CLAUDE.md +0 -681
  32. package/bun.lock +0 -472
  33. package/eslint.config.js +0 -75
  34. package/index.ts +0 -1
  35. package/llms.md +0 -796
  36. package/specs/UAP-1.0.md +0 -2355
  37. package/src/agent/index.ts +0 -384
  38. package/src/agent/types.ts +0 -91
  39. package/src/checkpoint/file.ts +0 -126
  40. package/src/checkpoint/index.ts +0 -40
  41. package/src/checkpoint/types.ts +0 -95
  42. package/src/execution/index.ts +0 -37
  43. package/src/execution/plan.ts +0 -497
  44. package/src/execution/react.ts +0 -340
  45. package/src/execution/tool-ordering.ts +0 -186
  46. package/src/execution/types.ts +0 -315
  47. package/src/index.ts +0 -80
  48. package/src/middleware/index.ts +0 -7
  49. package/src/middleware/logging.ts +0 -123
  50. package/src/middleware/types.ts +0 -69
  51. package/src/state/index.ts +0 -301
  52. package/src/state/types.ts +0 -173
  53. package/src/thread-tree/index.ts +0 -249
  54. package/src/thread-tree/types.ts +0 -29
  55. package/src/utils/uuid.ts +0 -7
  56. package/tests/live/agent-anthropic.test.ts +0 -288
  57. package/tests/live/agent-strategy-hooks.test.ts +0 -268
  58. package/tests/live/checkpoint.test.ts +0 -243
  59. package/tests/live/execution-strategies.test.ts +0 -255
  60. package/tests/live/plan-strategy.test.ts +0 -160
  61. package/tests/live/subagent-events.live.test.ts +0 -249
  62. package/tests/live/thread-tree.test.ts +0 -186
  63. package/tests/unit/agent.test.ts +0 -703
  64. package/tests/unit/checkpoint.test.ts +0 -232
  65. package/tests/unit/execution/equivalence.test.ts +0 -402
  66. package/tests/unit/execution/loop.test.ts +0 -437
  67. package/tests/unit/execution/plan.test.ts +0 -590
  68. package/tests/unit/execution/react.test.ts +0 -604
  69. package/tests/unit/execution/subagent-events.test.ts +0 -235
  70. package/tests/unit/execution/tool-ordering.test.ts +0 -310
  71. package/tests/unit/middleware/logging.test.ts +0 -276
  72. package/tests/unit/state.test.ts +0 -573
  73. package/tests/unit/thread-tree.test.ts +0 -249
  74. 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
- });