@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,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
- });