@providerprotocol/agents 0.0.1 → 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 (74) hide show
  1. package/README.md +333 -6
  2. package/dist/checkpoint/index.d.ts +43 -0
  3. package/dist/checkpoint/index.js +64 -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-PHI5ULBV.js +427 -0
  10. package/dist/chunk-PHI5ULBV.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-BhX9uD_d.d.ts +91 -0
  26. package/dist/types-DR02gtFv.d.ts +270 -0
  27. package/dist/types-NGQMdnaD.d.ts +65 -0
  28. package/package.json +40 -8
  29. package/.claude/settings.local.json +0 -27
  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,573 +0,0 @@
1
- import { describe, test, expect, beforeEach } from 'bun:test';
2
- import { UserMessage, AssistantMessage } from '@providerprotocol/ai';
3
- import { AgentState } from '../../src/state/index.ts';
4
- import type { PlanStep, SubagentExecutionTrace } from '../../src/state/index.ts';
5
-
6
- describe('AgentState', () => {
7
- describe('initial()', () => {
8
- test('creates state with empty messages', () => {
9
- const state = AgentState.initial();
10
- expect(state.messages).toEqual([]);
11
- });
12
-
13
- test('creates state with step 0', () => {
14
- const state = AgentState.initial();
15
- expect(state.step).toBe(0);
16
- });
17
-
18
- test('creates state with empty metadata', () => {
19
- const state = AgentState.initial();
20
- expect(state.metadata).toEqual({});
21
- });
22
-
23
- test('creates state with empty reasoning', () => {
24
- const state = AgentState.initial();
25
- expect(state.reasoning).toEqual([]);
26
- });
27
-
28
- test('creates state with undefined plan', () => {
29
- const state = AgentState.initial();
30
- expect(state.plan).toBeUndefined();
31
- });
32
-
33
- test('creates state with empty subagentTraces', () => {
34
- const state = AgentState.initial();
35
- expect(state.subagentTraces).toEqual([]);
36
- });
37
-
38
- test('creates state with unique UUIDv4 id', () => {
39
- const state1 = AgentState.initial();
40
- const state2 = AgentState.initial();
41
-
42
- expect(state1.id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i);
43
- expect(state1.id).not.toBe(state2.id);
44
- });
45
- });
46
-
47
- describe('withMessage()', () => {
48
- let state: AgentState;
49
-
50
- beforeEach(() => {
51
- state = AgentState.initial();
52
- });
53
-
54
- test('returns new state with message added', () => {
55
- const message = new UserMessage('Hello');
56
- const newState = state.withMessage(message);
57
-
58
- expect(newState.messages).toHaveLength(1);
59
- expect(newState.messages[0]).toBe(message);
60
- });
61
-
62
- test('does not modify original state', () => {
63
- const message = new UserMessage('Hello');
64
- state.withMessage(message);
65
-
66
- expect(state.messages).toHaveLength(0);
67
- });
68
-
69
- test('returns state with new id', () => {
70
- const message = new UserMessage('Hello');
71
- const newState = state.withMessage(message);
72
-
73
- expect(newState.id).not.toBe(state.id);
74
- });
75
-
76
- test('preserves other state properties', () => {
77
- const stateWithMeta = state.withMetadata('key', 'value').withStep(5);
78
- const message = new UserMessage('Hello');
79
- const newState = stateWithMeta.withMessage(message);
80
-
81
- expect(newState.metadata).toEqual({ key: 'value' });
82
- expect(newState.step).toBe(5);
83
- });
84
- });
85
-
86
- describe('withMessages()', () => {
87
- test('appends multiple messages', () => {
88
- const state = AgentState.initial();
89
- const messages = [
90
- new UserMessage('Hello'),
91
- new AssistantMessage('Hi there!'),
92
- ];
93
-
94
- const newState = state.withMessages(messages);
95
-
96
- expect(newState.messages).toHaveLength(2);
97
- });
98
-
99
- test('appends to existing messages', () => {
100
- const state = AgentState.initial()
101
- .withMessage(new UserMessage('First'));
102
-
103
- const newState = state.withMessages([
104
- new AssistantMessage('Response'),
105
- new UserMessage('Second'),
106
- ]);
107
-
108
- expect(newState.messages).toHaveLength(3);
109
- });
110
- });
111
-
112
- describe('withContext()', () => {
113
- test('replaces all messages', () => {
114
- const state = AgentState.initial()
115
- .withMessage(new UserMessage('First'))
116
- .withMessage(new AssistantMessage('Response'))
117
- .withMessage(new UserMessage('Second'));
118
-
119
- const newMessages = [
120
- new UserMessage('Replacement'),
121
- ];
122
-
123
- const newState = state.withContext(newMessages);
124
-
125
- expect(newState.messages).toHaveLength(1);
126
- expect(newState.messages[0]).toBe(newMessages[0]);
127
- });
128
-
129
- test('does not modify original state', () => {
130
- const originalMessage = new UserMessage('Original');
131
- const state = AgentState.initial()
132
- .withMessage(originalMessage);
133
-
134
- state.withContext([new UserMessage('Replacement')]);
135
-
136
- expect(state.messages).toHaveLength(1);
137
- expect(state.messages[0]).toBe(originalMessage);
138
- });
139
-
140
- test('returns state with new id', () => {
141
- const state = AgentState.initial()
142
- .withMessage(new UserMessage('Hello'));
143
-
144
- const newState = state.withContext([new UserMessage('New')]);
145
-
146
- expect(newState.id).not.toBe(state.id);
147
- });
148
-
149
- test('preserves other state properties', () => {
150
- const state = AgentState.initial()
151
- .withMessage(new UserMessage('Original'))
152
- .withStep(5)
153
- .withMetadata('key', 'value')
154
- .withReasoning('Some reasoning');
155
-
156
- const newState = state.withContext([new UserMessage('Replaced')]);
157
-
158
- expect(newState.step).toBe(5);
159
- expect(newState.metadata).toEqual({ key: 'value' });
160
- expect(newState.reasoning).toEqual(['Some reasoning']);
161
- });
162
-
163
- test('can replace with empty messages array', () => {
164
- const state = AgentState.initial()
165
- .withMessage(new UserMessage('First'))
166
- .withMessage(new AssistantMessage('Second'));
167
-
168
- const newState = state.withContext([]);
169
-
170
- expect(newState.messages).toHaveLength(0);
171
- });
172
-
173
- test('enables context window management patterns', () => {
174
- // Simulate pruning old tool outputs
175
- const state = AgentState.initial()
176
- .withMessage(new UserMessage('Query 1'))
177
- .withMessage(new AssistantMessage('Long tool output response 1'))
178
- .withMessage(new UserMessage('Query 2'))
179
- .withMessage(new AssistantMessage('Long tool output response 2'))
180
- .withMessage(new UserMessage('Query 3'));
181
-
182
- // Prune to keep only last 2 messages (simulating context management)
183
- const prunedMessages = state.messages.slice(-2);
184
- const newState = state.withContext([...prunedMessages]);
185
-
186
- expect(newState.messages).toHaveLength(2);
187
- });
188
- });
189
-
190
- describe('withStep()', () => {
191
- test('updates step number', () => {
192
- const state = AgentState.initial();
193
- const newState = state.withStep(5);
194
-
195
- expect(newState.step).toBe(5);
196
- });
197
-
198
- test('does not modify original state', () => {
199
- const state = AgentState.initial();
200
- state.withStep(5);
201
-
202
- expect(state.step).toBe(0);
203
- });
204
- });
205
-
206
- describe('withMetadata()', () => {
207
- test('adds metadata entry', () => {
208
- const state = AgentState.initial();
209
- const newState = state.withMetadata('key', 'value');
210
-
211
- expect(newState.metadata).toEqual({ key: 'value' });
212
- });
213
-
214
- test('updates existing metadata entry', () => {
215
- const state = AgentState.initial()
216
- .withMetadata('key', 'old');
217
-
218
- const newState = state.withMetadata('key', 'new');
219
-
220
- expect(newState.metadata).toEqual({ key: 'new' });
221
- });
222
-
223
- test('preserves other metadata entries', () => {
224
- const state = AgentState.initial()
225
- .withMetadata('a', 1)
226
- .withMetadata('b', 2);
227
-
228
- const newState = state.withMetadata('c', 3);
229
-
230
- expect(newState.metadata).toEqual({ a: 1, b: 2, c: 3 });
231
- });
232
- });
233
-
234
- describe('withReasoning()', () => {
235
- test('appends reasoning trace', () => {
236
- const state = AgentState.initial();
237
- const newState = state.withReasoning('I should do X');
238
-
239
- expect(newState.reasoning).toEqual(['I should do X']);
240
- });
241
-
242
- test('appends to existing reasoning', () => {
243
- const state = AgentState.initial()
244
- .withReasoning('First thought');
245
-
246
- const newState = state.withReasoning('Second thought');
247
-
248
- expect(newState.reasoning).toEqual(['First thought', 'Second thought']);
249
- });
250
- });
251
-
252
- describe('withPlan()', () => {
253
- test('sets plan', () => {
254
- const state = AgentState.initial();
255
- const plan: PlanStep[] = [
256
- { id: '1', description: 'Step 1', dependsOn: [], status: 'pending' },
257
- { id: '2', description: 'Step 2', dependsOn: ['1'], status: 'pending' },
258
- ];
259
-
260
- const newState = state.withPlan(plan);
261
-
262
- expect(newState.plan).toHaveLength(2);
263
- expect(newState.plan?.[0]?.description).toBe('Step 1');
264
- });
265
-
266
- test('replaces existing plan', () => {
267
- const state = AgentState.initial()
268
- .withPlan([{ id: '1', description: 'Old', dependsOn: [], status: 'pending' }]);
269
-
270
- const newPlan: PlanStep[] = [
271
- { id: '2', description: 'New', dependsOn: [], status: 'pending' },
272
- ];
273
-
274
- const newState = state.withPlan(newPlan);
275
-
276
- expect(newState.plan).toHaveLength(1);
277
- expect(newState.plan?.[0]?.description).toBe('New');
278
- });
279
- });
280
-
281
- describe('withSubagentTrace()', () => {
282
- test('adds subagent trace', () => {
283
- const state = AgentState.initial();
284
- const trace: SubagentExecutionTrace = {
285
- subagentId: 'agent-123',
286
- subagentType: 'explorer',
287
- parentToolCallId: 'tool-456',
288
- prompt: 'Find all TypeScript files',
289
- startTime: 1000,
290
- endTime: 2000,
291
- success: true,
292
- result: 'Found 10 files',
293
- toolExecutions: [
294
- {
295
- toolName: 'Glob',
296
- toolCallId: 'glob-001',
297
- arguments: { pattern: '**/*.ts' },
298
- result: 'file1.ts, file2.ts',
299
- duration: 50,
300
- },
301
- ],
302
- };
303
-
304
- const newState = state.withSubagentTrace(trace);
305
-
306
- expect(newState.subagentTraces).toHaveLength(1);
307
- expect(newState.subagentTraces[0]).toEqual(trace);
308
- });
309
-
310
- test('appends to existing traces', () => {
311
- const trace1: SubagentExecutionTrace = {
312
- subagentId: 'agent-1',
313
- subagentType: 'explorer',
314
- parentToolCallId: 'tool-1',
315
- prompt: 'First task',
316
- startTime: 1000,
317
- endTime: 1500,
318
- success: true,
319
- };
320
-
321
- const trace2: SubagentExecutionTrace = {
322
- subagentId: 'agent-2',
323
- subagentType: 'planner',
324
- parentToolCallId: 'tool-2',
325
- prompt: 'Second task',
326
- startTime: 2000,
327
- endTime: 2500,
328
- success: true,
329
- };
330
-
331
- const state = AgentState.initial()
332
- .withSubagentTrace(trace1);
333
- const newState = state.withSubagentTrace(trace2);
334
-
335
- expect(newState.subagentTraces).toHaveLength(2);
336
- expect(newState.subagentTraces[0]?.subagentId).toBe('agent-1');
337
- expect(newState.subagentTraces[1]?.subagentId).toBe('agent-2');
338
- });
339
-
340
- test('does not modify original state', () => {
341
- const state = AgentState.initial();
342
- const trace: SubagentExecutionTrace = {
343
- subagentId: 'agent-123',
344
- subagentType: 'explorer',
345
- parentToolCallId: 'tool-456',
346
- prompt: 'Test',
347
- startTime: 1000,
348
- endTime: 2000,
349
- success: true,
350
- };
351
-
352
- state.withSubagentTrace(trace);
353
-
354
- expect(state.subagentTraces).toHaveLength(0);
355
- });
356
-
357
- test('preserves other state properties', () => {
358
- const state = AgentState.initial()
359
- .withMessage(new UserMessage('Hello'))
360
- .withStep(3)
361
- .withMetadata('key', 'value');
362
-
363
- const trace: SubagentExecutionTrace = {
364
- subagentId: 'agent-123',
365
- subagentType: 'explorer',
366
- parentToolCallId: 'tool-456',
367
- prompt: 'Test',
368
- startTime: 1000,
369
- endTime: 2000,
370
- success: true,
371
- };
372
-
373
- const newState = state.withSubagentTrace(trace);
374
-
375
- expect(newState.messages).toHaveLength(1);
376
- expect(newState.step).toBe(3);
377
- expect(newState.metadata).toEqual({ key: 'value' });
378
- });
379
- });
380
-
381
- describe('serialization', () => {
382
- test('toJSON() serializes all properties', () => {
383
- const trace: SubagentExecutionTrace = {
384
- subagentId: 'agent-123',
385
- subagentType: 'explorer',
386
- parentToolCallId: 'tool-456',
387
- prompt: 'Test prompt',
388
- startTime: 1000,
389
- endTime: 2000,
390
- success: true,
391
- result: 'Test result',
392
- toolExecutions: [{ toolName: 'Glob', arguments: {}, result: 'files' }],
393
- };
394
-
395
- const state = AgentState.initial()
396
- .withMessage(new UserMessage('Hello'))
397
- .withStep(3)
398
- .withMetadata('key', 'value')
399
- .withReasoning('Thinking...')
400
- .withPlan([{ id: '1', description: 'Step', dependsOn: [], status: 'pending' }])
401
- .withSubagentTrace(trace);
402
-
403
- const json = state.toJSON();
404
-
405
- expect(json.version).toBe('1.0.0');
406
- expect(json.id).toBe(state.id);
407
- expect(json.messages).toHaveLength(1);
408
- expect(json.step).toBe(3);
409
- expect(json.metadata).toEqual({ key: 'value' });
410
- expect(json.reasoning).toEqual(['Thinking...']);
411
- expect(json.plan).toHaveLength(1);
412
- expect(json.subagentTraces).toHaveLength(1);
413
- expect(json.subagentTraces?.[0]?.subagentId).toBe('agent-123');
414
- });
415
-
416
- test('toJSON() omits subagentTraces when empty', () => {
417
- const state = AgentState.initial();
418
- const json = state.toJSON();
419
-
420
- expect(json.subagentTraces).toBeUndefined();
421
- });
422
-
423
- test('fromJSON() deserializes correctly', () => {
424
- const trace: SubagentExecutionTrace = {
425
- subagentId: 'agent-123',
426
- subagentType: 'explorer',
427
- parentToolCallId: 'tool-456',
428
- prompt: 'Test',
429
- startTime: 1000,
430
- endTime: 2000,
431
- success: true,
432
- };
433
-
434
- const original = AgentState.initial()
435
- .withMessage(new UserMessage('Hello'))
436
- .withStep(3)
437
- .withMetadata('key', 'value')
438
- .withReasoning('Thinking...')
439
- .withSubagentTrace(trace);
440
-
441
- const json = original.toJSON();
442
- const restored = AgentState.fromJSON(json);
443
-
444
- expect(restored.id).toBe(original.id);
445
- expect(restored.messages).toHaveLength(1);
446
- expect(restored.step).toBe(3);
447
- expect(restored.metadata).toEqual({ key: 'value' });
448
- expect(restored.reasoning).toEqual(['Thinking...']);
449
- expect(restored.subagentTraces).toHaveLength(1);
450
- expect(restored.subagentTraces[0]?.subagentId).toBe('agent-123');
451
- });
452
-
453
- test('fromJSON() handles missing subagentTraces', () => {
454
- const json = {
455
- version: '1.0.0',
456
- id: 'test-id',
457
- messages: [],
458
- step: 0,
459
- metadata: {},
460
- reasoning: [],
461
- // No subagentTraces field
462
- };
463
-
464
- const restored = AgentState.fromJSON(json);
465
- expect(restored.subagentTraces).toEqual([]);
466
- });
467
-
468
- test('round-trip preserves data', () => {
469
- const trace: SubagentExecutionTrace = {
470
- subagentId: 'agent-roundtrip',
471
- subagentType: 'explorer',
472
- parentToolCallId: 'tool-rt',
473
- prompt: 'Round trip test',
474
- startTime: 1000,
475
- endTime: 2000,
476
- success: true,
477
- result: 'Found it',
478
- toolExecutions: [
479
- {
480
- toolName: 'Glob',
481
- toolCallId: 'glob-rt',
482
- arguments: { pattern: '*.ts' },
483
- result: 'file.ts',
484
- duration: 100,
485
- },
486
- ],
487
- };
488
-
489
- const original = AgentState.initial()
490
- .withMessage(new UserMessage('Hello'))
491
- .withMessage(new AssistantMessage('Hi'))
492
- .withStep(5)
493
- .withMetadata('count', 42)
494
- .withReasoning('First')
495
- .withReasoning('Second')
496
- .withPlan([
497
- { id: '1', description: 'A', dependsOn: [], status: 'completed' },
498
- { id: '2', description: 'B', dependsOn: ['1'], status: 'pending' },
499
- ])
500
- .withSubagentTrace(trace);
501
-
502
- const json = original.toJSON();
503
- const restored = AgentState.fromJSON(json);
504
-
505
- expect(restored.id).toBe(original.id);
506
- expect(restored.messages.length).toBe(original.messages.length);
507
- expect(restored.step).toBe(original.step);
508
- expect(restored.metadata).toEqual(original.metadata);
509
- expect(restored.reasoning).toEqual([...original.reasoning]);
510
- expect(restored.plan?.length).toBe(original.plan?.length);
511
- expect(restored.subagentTraces.length).toBe(original.subagentTraces.length);
512
- expect(restored.subagentTraces[0]?.subagentId).toBe('agent-roundtrip');
513
- expect(restored.subagentTraces[0]?.toolExecutions?.[0]?.toolName).toBe('Glob');
514
- });
515
-
516
- test('fromJSON() throws on version mismatch', () => {
517
- const json = {
518
- version: '2.0.0',
519
- id: 'test',
520
- messages: [],
521
- step: 0,
522
- metadata: {},
523
- reasoning: [],
524
- };
525
-
526
- expect(() => AgentState.fromJSON(json)).toThrow('Unsupported UAP version');
527
- });
528
- });
529
-
530
- describe('immutability', () => {
531
- test('all operations return new instances', () => {
532
- const state = AgentState.initial();
533
- const operations = [
534
- () => state.withMessage(new UserMessage('test')),
535
- () => state.withMessages([new UserMessage('test')]),
536
- () => state.withContext([new UserMessage('test')]),
537
- () => state.withStep(1),
538
- () => state.withMetadata('key', 'value'),
539
- () => state.withReasoning('thinking'),
540
- () => state.withPlan([{ id: '1', description: 'test', dependsOn: [], status: 'pending' }]),
541
- () => state.withSubagentTrace({
542
- subagentId: 'test',
543
- subagentType: 'explorer',
544
- parentToolCallId: 'tool-1',
545
- prompt: 'test',
546
- startTime: 1000,
547
- endTime: 2000,
548
- success: true,
549
- }),
550
- ];
551
-
552
- for (const op of operations) {
553
- const newState = op();
554
- expect(newState).not.toBe(state);
555
- expect(newState.id).not.toBe(state.id);
556
- }
557
- });
558
-
559
- test('each state has unique ID', () => {
560
- const ids = new Set<string>();
561
- let state = AgentState.initial();
562
- ids.add(state.id);
563
-
564
- for (let i = 0; i < 10; i++) {
565
- state = state.withStep(i);
566
- expect(ids.has(state.id)).toBe(false);
567
- ids.add(state.id);
568
- }
569
-
570
- expect(ids.size).toBe(11);
571
- });
572
- });
573
- });