@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,703 +0,0 @@
1
- import { describe, test, expect } from 'bun:test';
2
- import { UserMessage, AssistantMessage } from '@providerprotocol/ai';
3
- import type { Turn, Tool, ModelReference, LLMInstance } from '@providerprotocol/ai';
4
- import { agent } from '../../src/agent/index.ts';
5
- import { AgentState } from '../../src/state/index.ts';
6
- import type { ExecutionStrategy } from '../../src/execution/types.ts';
7
- import type { Middleware } from '../../src/middleware/types.ts';
8
-
9
- // Mock model reference - use unknown cast for unit tests
10
- const mockModel = {
11
- provider: 'mock',
12
- modelId: 'mock-model',
13
- } as unknown as ModelReference;
14
-
15
- // Mock Turn factory
16
- function createMockTurn(text: string = 'Response'): Turn {
17
- const response = new AssistantMessage(text);
18
- return {
19
- response,
20
- messages: [response],
21
- toolExecutions: [],
22
- usage: {
23
- inputTokens: 10,
24
- outputTokens: 20,
25
- totalTokens: 30,
26
- },
27
- cycles: 1,
28
- } as unknown as Turn;
29
- }
30
-
31
- // Mock LLM instance for testing
32
- const mockLLM = {
33
- generate: async () => createMockTurn(),
34
- stream: () => ({
35
- async *[Symbol.asyncIterator] () {},
36
- turn: Promise.resolve(createMockTurn()),
37
- }),
38
- } as unknown as LLMInstance;
39
-
40
- describe('agent()', () => {
41
- describe('creation', () => {
42
- test('creates agent with unique ID', () => {
43
- // Create a custom execution strategy for testing
44
- const mockStrategy: ExecutionStrategy = {
45
- name: 'mock',
46
- async execute() {
47
- return {
48
- turn: createMockTurn(),
49
- state: AgentState.initial(),
50
- };
51
- },
52
- stream() {
53
- return {
54
- async *[Symbol.asyncIterator] () {},
55
- result: Promise.resolve({
56
- turn: createMockTurn(),
57
- state: AgentState.initial(),
58
- }),
59
- abort: () => {},
60
- };
61
- },
62
- };
63
-
64
- const agent1 = agent({
65
- model: mockModel,
66
- execution: mockStrategy,
67
- _llmInstance: mockLLM,
68
- });
69
-
70
- const agent2 = agent({
71
- model: mockModel,
72
- execution: mockStrategy,
73
- _llmInstance: mockLLM,
74
- });
75
-
76
- expect(agent1.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);
77
- expect(agent1.id).not.toBe(agent2.id);
78
- });
79
-
80
- test('stores model reference', () => {
81
- const mockStrategy: ExecutionStrategy = {
82
- name: 'mock',
83
- async execute() {
84
- return {
85
- turn: createMockTurn(),
86
- state: AgentState.initial(),
87
- };
88
- },
89
- stream() {
90
- return {
91
- async *[Symbol.asyncIterator] () {},
92
- result: Promise.resolve({
93
- turn: createMockTurn(),
94
- state: AgentState.initial(),
95
- }),
96
- abort: () => {},
97
- };
98
- },
99
- };
100
-
101
- const a = agent({
102
- model: mockModel,
103
- execution: mockStrategy,
104
- _llmInstance: mockLLM,
105
- });
106
-
107
- expect(a.model).toBe(mockModel);
108
- });
109
-
110
- test('stores tools', () => {
111
- const mockTool: Tool = {
112
- name: 'test_tool',
113
- description: 'A test tool',
114
- parameters: { type: 'object', properties: {} },
115
- run: async () => 'result',
116
- };
117
-
118
- const mockStrategy: ExecutionStrategy = {
119
- name: 'mock',
120
- async execute() {
121
- return {
122
- turn: createMockTurn(),
123
- state: AgentState.initial(),
124
- };
125
- },
126
- stream() {
127
- return {
128
- async *[Symbol.asyncIterator] () {},
129
- result: Promise.resolve({
130
- turn: createMockTurn(),
131
- state: AgentState.initial(),
132
- }),
133
- abort: () => {},
134
- };
135
- },
136
- };
137
-
138
- const a = agent({
139
- model: mockModel,
140
- tools: [mockTool],
141
- execution: mockStrategy,
142
- _llmInstance: mockLLM,
143
- });
144
-
145
- expect(a.tools).toHaveLength(1);
146
- expect(a.tools[0]).toBe(mockTool);
147
- });
148
-
149
- test('stores system prompt', () => {
150
- const mockStrategy: ExecutionStrategy = {
151
- name: 'mock',
152
- async execute() {
153
- return {
154
- turn: createMockTurn(),
155
- state: AgentState.initial(),
156
- };
157
- },
158
- stream() {
159
- return {
160
- async *[Symbol.asyncIterator] () {},
161
- result: Promise.resolve({
162
- turn: createMockTurn(),
163
- state: AgentState.initial(),
164
- }),
165
- abort: () => {},
166
- };
167
- },
168
- };
169
-
170
- const a = agent({
171
- model: mockModel,
172
- system: 'You are a helpful assistant.',
173
- execution: mockStrategy,
174
- _llmInstance: mockLLM,
175
- });
176
-
177
- expect(a.system).toBe('You are a helpful assistant.');
178
- });
179
-
180
- test('defaults to empty tools array', () => {
181
- const mockStrategy: ExecutionStrategy = {
182
- name: 'mock',
183
- async execute() {
184
- return {
185
- turn: createMockTurn(),
186
- state: AgentState.initial(),
187
- };
188
- },
189
- stream() {
190
- return {
191
- async *[Symbol.asyncIterator] () {},
192
- result: Promise.resolve({
193
- turn: createMockTurn(),
194
- state: AgentState.initial(),
195
- }),
196
- abort: () => {},
197
- };
198
- },
199
- };
200
-
201
- const a = agent({
202
- model: mockModel,
203
- execution: mockStrategy,
204
- _llmInstance: mockLLM,
205
- });
206
-
207
- expect(a.tools).toEqual([]);
208
- });
209
- });
210
-
211
- describe('generate()', () => {
212
- test('accepts string input', async () => {
213
- let capturedInput: unknown;
214
-
215
- const mockStrategy: ExecutionStrategy = {
216
- name: 'mock',
217
- async execute(ctx) {
218
- capturedInput = ctx.input;
219
- return {
220
- turn: createMockTurn(),
221
- state: ctx.state,
222
- };
223
- },
224
- stream() {
225
- return {
226
- async *[Symbol.asyncIterator] () {},
227
- result: Promise.resolve({
228
- turn: createMockTurn(),
229
- state: AgentState.initial(),
230
- }),
231
- abort: () => {},
232
- };
233
- },
234
- };
235
-
236
- const a = agent({
237
- model: mockModel,
238
- execution: mockStrategy,
239
- _llmInstance: mockLLM,
240
- });
241
-
242
- await a.generate('Hello', AgentState.initial());
243
-
244
- expect(capturedInput).toBeInstanceOf(UserMessage);
245
- });
246
-
247
- test('accepts Message input', async () => {
248
- let capturedInput: unknown;
249
- const inputMessage = new UserMessage('Hello');
250
-
251
- const mockStrategy: ExecutionStrategy = {
252
- name: 'mock',
253
- async execute(ctx) {
254
- capturedInput = ctx.input;
255
- return {
256
- turn: createMockTurn(),
257
- state: ctx.state,
258
- };
259
- },
260
- stream() {
261
- return {
262
- async *[Symbol.asyncIterator] () {},
263
- result: Promise.resolve({
264
- turn: createMockTurn(),
265
- state: AgentState.initial(),
266
- }),
267
- abort: () => {},
268
- };
269
- },
270
- };
271
-
272
- const a = agent({
273
- model: mockModel,
274
- execution: mockStrategy,
275
- _llmInstance: mockLLM,
276
- });
277
-
278
- await a.generate(inputMessage, AgentState.initial());
279
-
280
- expect(capturedInput).toBe(inputMessage);
281
- });
282
-
283
- test('returns turn and state', async () => {
284
- const mockTurn = createMockTurn('Test response');
285
- const mockState = AgentState.initial().withStep(1);
286
-
287
- const mockStrategy: ExecutionStrategy = {
288
- name: 'mock',
289
- async execute() {
290
- return {
291
- turn: mockTurn,
292
- state: mockState,
293
- };
294
- },
295
- stream() {
296
- return {
297
- async *[Symbol.asyncIterator] () {},
298
- result: Promise.resolve({
299
- turn: mockTurn,
300
- state: mockState,
301
- }),
302
- abort: () => {},
303
- };
304
- },
305
- };
306
-
307
- const a = agent({
308
- model: mockModel,
309
- execution: mockStrategy,
310
- _llmInstance: mockLLM,
311
- });
312
-
313
- const result = await a.generate('Hello', AgentState.initial());
314
-
315
- expect(result.turn).toBe(mockTurn);
316
- expect(result.state).toBe(mockState);
317
- });
318
-
319
- test('passes state to execution strategy', async () => {
320
- let capturedState: AgentState | undefined;
321
- const inputState = AgentState.initial()
322
- .withStep(5)
323
- .withMetadata('test', 'value');
324
-
325
- const mockStrategy: ExecutionStrategy = {
326
- name: 'mock',
327
- async execute(ctx) {
328
- capturedState = ctx.state;
329
- return {
330
- turn: createMockTurn(),
331
- state: ctx.state,
332
- };
333
- },
334
- stream() {
335
- return {
336
- async *[Symbol.asyncIterator] () {},
337
- result: Promise.resolve({
338
- turn: createMockTurn(),
339
- state: AgentState.initial(),
340
- }),
341
- abort: () => {},
342
- };
343
- },
344
- };
345
-
346
- const a = agent({
347
- model: mockModel,
348
- execution: mockStrategy,
349
- _llmInstance: mockLLM,
350
- });
351
-
352
- await a.generate('Hello', inputState);
353
-
354
- expect(capturedState?.step).toBe(5);
355
- expect(capturedState?.metadata).toEqual({ test: 'value' });
356
- });
357
- });
358
-
359
- describe('ask()', () => {
360
- test('preserves conversation history', async () => {
361
- let callCount = 0;
362
-
363
- const mockStrategy: ExecutionStrategy = {
364
- name: 'mock',
365
- async execute(ctx) {
366
- callCount++;
367
- return {
368
- turn: createMockTurn(`Response ${callCount}`),
369
- state: ctx.state.withStep(callCount),
370
- };
371
- },
372
- stream() {
373
- return {
374
- async *[Symbol.asyncIterator] () {},
375
- result: Promise.resolve({
376
- turn: createMockTurn(),
377
- state: AgentState.initial(),
378
- }),
379
- abort: () => {},
380
- };
381
- },
382
- };
383
-
384
- const a = agent({
385
- model: mockModel,
386
- execution: mockStrategy,
387
- _llmInstance: mockLLM,
388
- });
389
-
390
- const state0 = AgentState.initial();
391
- const result1 = await a.ask('First message', state0);
392
-
393
- // State should have the input message added
394
- expect(result1.state.messages.length).toBeGreaterThan(0);
395
-
396
- const result2 = await a.ask('Second message', result1.state);
397
-
398
- // State should have accumulated messages
399
- expect(result2.state.messages.length).toBeGreaterThan(result1.state.messages.length);
400
- });
401
- });
402
-
403
- describe('query()', () => {
404
- test('is stateless', async () => {
405
- const mockStrategy: ExecutionStrategy = {
406
- name: 'mock',
407
- async execute(ctx) {
408
- // State should be fresh
409
- expect(ctx.state.messages).toHaveLength(0);
410
- expect(ctx.state.step).toBe(0);
411
-
412
- return {
413
- turn: createMockTurn(),
414
- state: ctx.state,
415
- };
416
- },
417
- stream() {
418
- return {
419
- async *[Symbol.asyncIterator] () {},
420
- result: Promise.resolve({
421
- turn: createMockTurn(),
422
- state: AgentState.initial(),
423
- }),
424
- abort: () => {},
425
- };
426
- },
427
- };
428
-
429
- const a = agent({
430
- model: mockModel,
431
- execution: mockStrategy,
432
- _llmInstance: mockLLM,
433
- });
434
-
435
- const turn = await a.query('Question');
436
-
437
- expect(turn).toBeDefined();
438
- expect(turn.response.text).toBe('Response');
439
- });
440
-
441
- test('returns only Turn, not state', async () => {
442
- const mockStrategy: ExecutionStrategy = {
443
- name: 'mock',
444
- async execute(ctx) {
445
- return {
446
- turn: createMockTurn('Answer'),
447
- state: ctx.state,
448
- };
449
- },
450
- stream() {
451
- return {
452
- async *[Symbol.asyncIterator] () {},
453
- result: Promise.resolve({
454
- turn: createMockTurn(),
455
- state: AgentState.initial(),
456
- }),
457
- abort: () => {},
458
- };
459
- },
460
- };
461
-
462
- const a = agent({
463
- model: mockModel,
464
- execution: mockStrategy,
465
- _llmInstance: mockLLM,
466
- });
467
-
468
- const turn = await a.query('Question');
469
-
470
- // Should return Turn, not GenerateResult
471
- expect(turn.response).toBeDefined();
472
- expect(turn.response.text).toBe('Answer');
473
- expect((turn as unknown as { state?: unknown }).state).toBeUndefined();
474
- });
475
- });
476
-
477
- describe('middleware', () => {
478
- test('runs before middleware in order', async () => {
479
- const order: string[] = [];
480
-
481
- const mw1: Middleware = {
482
- name: 'first',
483
- async before(ctx) {
484
- order.push('first-before');
485
- return ctx;
486
- },
487
- };
488
-
489
- const mw2: Middleware = {
490
- name: 'second',
491
- async before(ctx) {
492
- order.push('second-before');
493
- return ctx;
494
- },
495
- };
496
-
497
- const mockStrategy: ExecutionStrategy = {
498
- name: 'mock',
499
- async execute(ctx) {
500
- order.push('execute');
501
- return {
502
- turn: createMockTurn(),
503
- state: ctx.state,
504
- };
505
- },
506
- stream() {
507
- return {
508
- async *[Symbol.asyncIterator] () {},
509
- result: Promise.resolve({
510
- turn: createMockTurn(),
511
- state: AgentState.initial(),
512
- }),
513
- abort: () => {},
514
- };
515
- },
516
- };
517
-
518
- const a = agent({
519
- model: mockModel,
520
- middleware: [mw1, mw2],
521
- execution: mockStrategy,
522
- _llmInstance: mockLLM,
523
- });
524
-
525
- await a.generate('Hello', AgentState.initial());
526
-
527
- expect(order).toEqual(['first-before', 'second-before', 'execute']);
528
- });
529
-
530
- test('runs after middleware in reverse order', async () => {
531
- const order: string[] = [];
532
-
533
- const mw1: Middleware = {
534
- name: 'first',
535
- async after(ctx, result) {
536
- order.push('first-after');
537
- return result;
538
- },
539
- };
540
-
541
- const mw2: Middleware = {
542
- name: 'second',
543
- async after(ctx, result) {
544
- order.push('second-after');
545
- return result;
546
- },
547
- };
548
-
549
- const mockStrategy: ExecutionStrategy = {
550
- name: 'mock',
551
- async execute(ctx) {
552
- order.push('execute');
553
- return {
554
- turn: createMockTurn(),
555
- state: ctx.state,
556
- };
557
- },
558
- stream() {
559
- return {
560
- async *[Symbol.asyncIterator] () {},
561
- result: Promise.resolve({
562
- turn: createMockTurn(),
563
- state: AgentState.initial(),
564
- }),
565
- abort: () => {},
566
- };
567
- },
568
- };
569
-
570
- const a = agent({
571
- model: mockModel,
572
- middleware: [mw1, mw2],
573
- execution: mockStrategy,
574
- _llmInstance: mockLLM,
575
- });
576
-
577
- await a.generate('Hello', AgentState.initial());
578
-
579
- expect(order).toEqual(['execute', 'second-after', 'first-after']);
580
- });
581
-
582
- test('middleware can modify result', async () => {
583
- const mw: Middleware = {
584
- name: 'modifier',
585
- async after(ctx, result) {
586
- return {
587
- ...result,
588
- state: result.state.withMetadata('modified', true),
589
- };
590
- },
591
- };
592
-
593
- const mockStrategy: ExecutionStrategy = {
594
- name: 'mock',
595
- async execute(ctx) {
596
- return {
597
- turn: createMockTurn(),
598
- state: ctx.state,
599
- };
600
- },
601
- stream() {
602
- return {
603
- async *[Symbol.asyncIterator] () {},
604
- result: Promise.resolve({
605
- turn: createMockTurn(),
606
- state: AgentState.initial(),
607
- }),
608
- abort: () => {},
609
- };
610
- },
611
- };
612
-
613
- const a = agent({
614
- model: mockModel,
615
- middleware: [mw],
616
- execution: mockStrategy,
617
- _llmInstance: mockLLM,
618
- });
619
-
620
- const result = await a.generate('Hello', AgentState.initial());
621
-
622
- expect(result.state.metadata).toEqual({ modified: true });
623
- });
624
- });
625
-
626
- describe('stream()', () => {
627
- test('returns AgentStreamResult', async () => {
628
- const mockStrategy: ExecutionStrategy = {
629
- name: 'mock',
630
- async execute(ctx) {
631
- return {
632
- turn: createMockTurn(),
633
- state: ctx.state,
634
- };
635
- },
636
- stream() {
637
- return {
638
- async *[Symbol.asyncIterator] () {
639
- yield { source: 'uap' as const, uap: { type: 'step_start' as const, step: 1, agentId: 'test', data: {} } };
640
- },
641
- result: Promise.resolve({
642
- turn: createMockTurn(),
643
- state: AgentState.initial(),
644
- }),
645
- abort: () => {},
646
- };
647
- },
648
- };
649
-
650
- const a = agent({
651
- model: mockModel,
652
- execution: mockStrategy,
653
- _llmInstance: mockLLM,
654
- });
655
-
656
- const stream = a.stream('Hello', AgentState.initial());
657
-
658
- expect(stream[Symbol.asyncIterator]).toBeDefined();
659
- expect(stream.result).toBeInstanceOf(Promise);
660
- expect(typeof stream.abort).toBe('function');
661
- });
662
-
663
- test('yields events from strategy', async () => {
664
- const mockStrategy: ExecutionStrategy = {
665
- name: 'mock',
666
- async execute(ctx) {
667
- return {
668
- turn: createMockTurn(),
669
- state: ctx.state,
670
- };
671
- },
672
- stream() {
673
- return {
674
- async *[Symbol.asyncIterator] () {
675
- yield { source: 'uap' as const, uap: { type: 'step_start' as const, step: 1, agentId: 'test', data: {} } };
676
- yield { source: 'uap' as const, uap: { type: 'step_end' as const, step: 1, agentId: 'test', data: {} } };
677
- },
678
- result: Promise.resolve({
679
- turn: createMockTurn(),
680
- state: AgentState.initial(),
681
- }),
682
- abort: () => {},
683
- };
684
- },
685
- };
686
-
687
- const a = agent({
688
- model: mockModel,
689
- execution: mockStrategy,
690
- _llmInstance: mockLLM,
691
- });
692
-
693
- const stream = a.stream('Hello', AgentState.initial());
694
- const events: unknown[] = [];
695
-
696
- for await (const event of stream) {
697
- events.push(event);
698
- }
699
-
700
- expect(events).toHaveLength(2);
701
- });
702
- });
703
- });