@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,235 +0,0 @@
1
- /**
2
- * Unit tests for sub-agent event types.
3
- *
4
- * @see UAP-1.0 Spec Section 8.7
5
- */
6
-
7
- import { describe, test, expect } from 'bun:test';
8
- import type {
9
- SubagentEvent,
10
- SubagentStartEvent,
11
- SubagentInnerEvent,
12
- SubagentEndEvent,
13
- OnSubagentEvent,
14
- AgentStreamEvent,
15
- } from '../../../src/execution/types.ts';
16
-
17
- describe('SubagentEvent types', () => {
18
- describe('SubagentStartEvent', () => {
19
- test('should have correct structure', () => {
20
- const event: SubagentStartEvent = {
21
- type: 'subagent_start',
22
- subagentId: 'sub-123',
23
- subagentType: 'explorer',
24
- parentToolCallId: 'tool-456',
25
- prompt: 'Find all TypeScript files',
26
- timestamp: Date.now(),
27
- };
28
-
29
- expect(event.type).toBe('subagent_start');
30
- expect(event.subagentId).toBe('sub-123');
31
- expect(event.subagentType).toBe('explorer');
32
- expect(event.parentToolCallId).toBe('tool-456');
33
- expect(event.prompt).toBe('Find all TypeScript files');
34
- expect(typeof event.timestamp).toBe('number');
35
- });
36
- });
37
-
38
- describe('SubagentInnerEvent', () => {
39
- test('should wrap inner AgentStreamEvent', () => {
40
- const innerEvent: AgentStreamEvent = {
41
- source: 'upp',
42
- upp: {
43
- type: 'text_delta',
44
- index: 0,
45
- delta: { text: 'Hello' },
46
- },
47
- };
48
-
49
- const event: SubagentInnerEvent = {
50
- type: 'subagent_event',
51
- subagentId: 'sub-123',
52
- subagentType: 'explorer',
53
- parentToolCallId: 'tool-456',
54
- innerEvent,
55
- };
56
-
57
- expect(event.type).toBe('subagent_event');
58
- expect(event.innerEvent.source).toBe('upp');
59
- expect(event.innerEvent.upp?.type).toBe('text_delta');
60
- });
61
-
62
- test('should wrap UAP events from sub-agent', () => {
63
- const innerEvent: AgentStreamEvent = {
64
- source: 'uap',
65
- uap: {
66
- type: 'step_start',
67
- step: 1,
68
- agentId: 'sub-123',
69
- data: { iteration: 1 },
70
- },
71
- };
72
-
73
- const event: SubagentInnerEvent = {
74
- type: 'subagent_event',
75
- subagentId: 'sub-123',
76
- subagentType: 'planner',
77
- parentToolCallId: 'tool-789',
78
- innerEvent,
79
- };
80
-
81
- expect(event.innerEvent.source).toBe('uap');
82
- expect(event.innerEvent.uap?.type).toBe('step_start');
83
- });
84
- });
85
-
86
- describe('SubagentEndEvent', () => {
87
- test('should have correct structure for successful completion', () => {
88
- const event: SubagentEndEvent = {
89
- type: 'subagent_end',
90
- subagentId: 'sub-123',
91
- subagentType: 'explorer',
92
- parentToolCallId: 'tool-456',
93
- success: true,
94
- result: 'Found 42 TypeScript files',
95
- timestamp: Date.now(),
96
- toolExecutions: [
97
- {
98
- toolName: 'Glob',
99
- arguments: { pattern: '**/*.ts' },
100
- result: 'file1.ts\nfile2.ts',
101
- },
102
- ],
103
- };
104
-
105
- expect(event.type).toBe('subagent_end');
106
- expect(event.success).toBe(true);
107
- expect(event.result).toBe('Found 42 TypeScript files');
108
- expect(event.error).toBeUndefined();
109
- expect(event.toolExecutions).toHaveLength(1);
110
- expect(event.toolExecutions?.[0]?.toolName).toBe('Glob');
111
- });
112
-
113
- test('should have correct structure for failed completion', () => {
114
- const event: SubagentEndEvent = {
115
- type: 'subagent_end',
116
- subagentId: 'sub-123',
117
- subagentType: 'explorer',
118
- parentToolCallId: 'tool-456',
119
- success: false,
120
- error: 'Rate limit exceeded',
121
- timestamp: Date.now(),
122
- };
123
-
124
- expect(event.type).toBe('subagent_end');
125
- expect(event.success).toBe(false);
126
- expect(event.error).toBe('Rate limit exceeded');
127
- expect(event.result).toBeUndefined();
128
- });
129
- });
130
-
131
- describe('SubagentEvent union type', () => {
132
- test('should discriminate by type field', () => {
133
- const events: SubagentEvent[] = [
134
- {
135
- type: 'subagent_start',
136
- subagentId: 'sub-1',
137
- subagentType: 'explorer',
138
- parentToolCallId: 'tool-1',
139
- prompt: 'test',
140
- timestamp: 1000,
141
- },
142
- {
143
- type: 'subagent_event',
144
- subagentId: 'sub-1',
145
- subagentType: 'explorer',
146
- parentToolCallId: 'tool-1',
147
- innerEvent: { source: 'upp', upp: { type: 'text_delta', index: 0, delta: { text: 'hi' } } },
148
- },
149
- {
150
- type: 'subagent_end',
151
- subagentId: 'sub-1',
152
- subagentType: 'explorer',
153
- parentToolCallId: 'tool-1',
154
- success: true,
155
- timestamp: 2000,
156
- },
157
- ];
158
-
159
- // Type narrowing should work correctly
160
- for (const event of events) {
161
- switch (event.type) {
162
- case 'subagent_start':
163
- expect(event.prompt).toBeDefined();
164
- break;
165
- case 'subagent_event':
166
- expect(event.innerEvent).toBeDefined();
167
- break;
168
- case 'subagent_end':
169
- expect(typeof event.success).toBe('boolean');
170
- break;
171
- }
172
- }
173
- });
174
- });
175
-
176
- describe('OnSubagentEvent callback', () => {
177
- test('should be callable with any SubagentEvent', () => {
178
- const receivedEvents: SubagentEvent[] = [];
179
-
180
- const callback: OnSubagentEvent = (event) => {
181
- receivedEvents.push(event);
182
- };
183
-
184
- // Emit start event
185
- callback({
186
- type: 'subagent_start',
187
- subagentId: 'sub-1',
188
- subagentType: 'explorer',
189
- parentToolCallId: 'tool-1',
190
- prompt: 'test',
191
- timestamp: Date.now(),
192
- });
193
-
194
- // Emit inner event
195
- callback({
196
- type: 'subagent_event',
197
- subagentId: 'sub-1',
198
- subagentType: 'explorer',
199
- parentToolCallId: 'tool-1',
200
- innerEvent: { source: 'upp', upp: { type: 'message_stop', index: 0, delta: {} } },
201
- });
202
-
203
- // Emit end event
204
- callback({
205
- type: 'subagent_end',
206
- subagentId: 'sub-1',
207
- subagentType: 'explorer',
208
- parentToolCallId: 'tool-1',
209
- success: true,
210
- result: 'done',
211
- timestamp: Date.now(),
212
- });
213
-
214
- expect(receivedEvents).toHaveLength(3);
215
- expect(receivedEvents[0]?.type).toBe('subagent_start');
216
- expect(receivedEvents[1]?.type).toBe('subagent_event');
217
- expect(receivedEvents[2]?.type).toBe('subagent_end');
218
- });
219
- });
220
- });
221
-
222
- describe('UAPEventType includes subagent events', () => {
223
- test('subagent event types are valid UAPEventType values', () => {
224
- // These should compile without errors
225
- const types: import('../../../src/execution/types.ts').UAPEventType[] = [
226
- 'subagent_start',
227
- 'subagent_event',
228
- 'subagent_end',
229
- ];
230
-
231
- expect(types).toContain('subagent_start');
232
- expect(types).toContain('subagent_event');
233
- expect(types).toContain('subagent_end');
234
- });
235
- });
@@ -1,310 +0,0 @@
1
- import { describe, test, expect } from 'bun:test';
2
- import type { ToolCall } from '@providerprotocol/ai';
3
- import {
4
- orderToolCalls,
5
- hasToolDependencies,
6
- hasCallDependencies,
7
- } from '../../../src/execution/tool-ordering.ts';
8
- import type {
9
- ToolWithDependencies,
10
- OrderedToolCall,
11
- } from '../../../src/execution/types.ts';
12
-
13
- // Helper to create a mock tool
14
- function createTool(
15
- name: string,
16
- options?: { sequential?: boolean; dependsOn?: string[] },
17
- ): ToolWithDependencies {
18
- return {
19
- name,
20
- description: `Tool ${name}`,
21
- parameters: { type: 'object', properties: {} },
22
- run: async () => 'result',
23
- sequential: options?.sequential,
24
- dependsOn: options?.dependsOn,
25
- };
26
- }
27
-
28
- // Helper to create a mock tool call
29
- function createToolCall(
30
- toolName: string,
31
- id?: string,
32
- after?: string[],
33
- ): ToolCall | OrderedToolCall {
34
- const call: OrderedToolCall = {
35
- toolCallId: id ?? `call-${toolName}`,
36
- toolName,
37
- arguments: {},
38
- };
39
- if (after) {
40
- call.after = after;
41
- }
42
- return call;
43
- }
44
-
45
- describe('orderToolCalls()', () => {
46
- test('returns empty array for no tool calls', () => {
47
- const groups = orderToolCalls([], []);
48
- expect(groups).toEqual([]);
49
- });
50
-
51
- test('groups independent tools together', () => {
52
- const tools = [
53
- createTool('tool_a'),
54
- createTool('tool_b'),
55
- createTool('tool_c'),
56
- ];
57
-
58
- const calls = [
59
- createToolCall('tool_a'),
60
- createToolCall('tool_b'),
61
- createToolCall('tool_c'),
62
- ];
63
-
64
- const groups = orderToolCalls(calls, tools);
65
-
66
- expect(groups).toHaveLength(1);
67
- const firstGroup = groups[0];
68
- expect(firstGroup).toBeDefined();
69
- if (firstGroup) {
70
- expect(firstGroup.calls).toHaveLength(3);
71
- expect(firstGroup.isBarrier).toBe(false);
72
- }
73
- });
74
-
75
- test('sequential tool creates barrier', () => {
76
- const tools = [
77
- createTool('read', { sequential: true }),
78
- createTool('process'),
79
- ];
80
-
81
- const calls = [
82
- createToolCall('read'),
83
- createToolCall('process'),
84
- ];
85
-
86
- const groups = orderToolCalls(calls, tools);
87
-
88
- // read should be in its own group as a barrier
89
- expect(groups.length).toBeGreaterThanOrEqual(1);
90
- const readGroup = groups.find((g) => g.calls.some((c) => c.toolName === 'read'));
91
- expect(readGroup?.isBarrier).toBe(true);
92
- });
93
-
94
- test('dependsOn creates ordering', () => {
95
- const tools = [
96
- createTool('read'),
97
- createTool('write', { dependsOn: ['read'] }),
98
- ];
99
-
100
- const calls = [
101
- createToolCall('read'),
102
- createToolCall('write'),
103
- ];
104
-
105
- const groups = orderToolCalls(calls, tools);
106
-
107
- // Should have at least 2 groups due to dependency
108
- expect(groups.length).toBeGreaterThanOrEqual(2);
109
-
110
- // Find read and write group indices
111
- const readGroupIndex = groups.findIndex(
112
- (g) => g.calls.some((c) => c.toolName === 'read'),
113
- );
114
- const writeGroupIndex = groups.findIndex(
115
- (g) => g.calls.some((c) => c.toolName === 'write'),
116
- );
117
-
118
- // read should come before write
119
- expect(readGroupIndex).toBeLessThan(writeGroupIndex);
120
- });
121
-
122
- test('model-driven dependencies (after field)', () => {
123
- const tools = [
124
- createTool('tool_a'),
125
- createTool('tool_b'),
126
- ];
127
-
128
- const calls = [
129
- createToolCall('tool_a', 'call-1'),
130
- createToolCall('tool_b', 'call-2', ['call-1']), // depends on call-1
131
- ] as OrderedToolCall[];
132
-
133
- const groups = orderToolCalls(calls, tools);
134
-
135
- // Should have at least 2 groups due to dependency
136
- expect(groups.length).toBeGreaterThanOrEqual(2);
137
-
138
- // Find group indices
139
- const aGroupIndex = groups.findIndex(
140
- (g) => g.calls.some((c) => c.toolCallId === 'call-1'),
141
- );
142
- const bGroupIndex = groups.findIndex(
143
- (g) => g.calls.some((c) => c.toolCallId === 'call-2'),
144
- );
145
-
146
- // call-1 should come before call-2
147
- expect(aGroupIndex).toBeLessThan(bGroupIndex);
148
- });
149
-
150
- test('complex dependency chain', () => {
151
- // A -> B -> C (chain dependency)
152
- const tools = [
153
- createTool('tool_a'),
154
- createTool('tool_b', { dependsOn: ['tool_a'] }),
155
- createTool('tool_c', { dependsOn: ['tool_b'] }),
156
- ];
157
-
158
- const calls = [
159
- createToolCall('tool_a'),
160
- createToolCall('tool_b'),
161
- createToolCall('tool_c'),
162
- ];
163
-
164
- const groups = orderToolCalls(calls, tools);
165
-
166
- // Should have 3 groups, one for each tool
167
- expect(groups).toHaveLength(3);
168
-
169
- // Verify order
170
- expect(groups[0]?.calls[0]?.toolName).toBe('tool_a');
171
- expect(groups[1]?.calls[0]?.toolName).toBe('tool_b');
172
- expect(groups[2]?.calls[0]?.toolName).toBe('tool_c');
173
- });
174
-
175
- test('parallel tools with shared dependency', () => {
176
- // D depends on both A and B (which can run in parallel)
177
- const tools = [
178
- createTool('tool_a'),
179
- createTool('tool_b'),
180
- createTool('tool_d', { dependsOn: ['tool_a', 'tool_b'] }),
181
- ];
182
-
183
- const calls = [
184
- createToolCall('tool_a'),
185
- createToolCall('tool_b'),
186
- createToolCall('tool_d'),
187
- ];
188
-
189
- const groups = orderToolCalls(calls, tools);
190
-
191
- // First group should have A and B (parallel)
192
- // Second group should have D
193
- expect(groups.length).toBeGreaterThanOrEqual(2);
194
-
195
- const firstGroup = groups[0];
196
- expect(firstGroup).toBeDefined();
197
- if (firstGroup) {
198
- const hasA = firstGroup.calls.some((c) => c.toolName === 'tool_a');
199
- const hasB = firstGroup.calls.some((c) => c.toolName === 'tool_b');
200
- expect(hasA).toBe(true);
201
- expect(hasB).toBe(true);
202
- }
203
-
204
- const dGroupIndex = groups.findIndex(
205
- (g) => g.calls.some((c) => c.toolName === 'tool_d'),
206
- );
207
- expect(dGroupIndex).toBe(groups.length - 1); // D should be last
208
- });
209
-
210
- test('handles unknown tools gracefully', () => {
211
- const tools = [createTool('known')];
212
- const calls = [
213
- createToolCall('known'),
214
- createToolCall('unknown'),
215
- ];
216
-
217
- // Should not throw
218
- const groups = orderToolCalls(calls, tools);
219
- expect(groups.length).toBeGreaterThan(0);
220
- });
221
-
222
- test('handles cyclic dependencies by executing remaining items', () => {
223
- // A depends on B, B depends on A (cycle)
224
- const tools = [
225
- createTool('tool_a', { dependsOn: ['tool_b'] }),
226
- createTool('tool_b', { dependsOn: ['tool_a'] }),
227
- ];
228
-
229
- const calls = [
230
- createToolCall('tool_a'),
231
- createToolCall('tool_b'),
232
- ];
233
-
234
- // Should not hang - should execute items despite cycle
235
- const groups = orderToolCalls(calls, tools);
236
- expect(groups.length).toBeGreaterThan(0);
237
-
238
- // All calls should be included
239
- const allCalls = groups.flatMap((g) => g.calls);
240
- expect(allCalls).toHaveLength(2);
241
- });
242
- });
243
-
244
- describe('hasToolDependencies()', () => {
245
- test('returns false for tools without dependencies', () => {
246
- const tools = [
247
- createTool('tool_a'),
248
- createTool('tool_b'),
249
- ];
250
-
251
- expect(hasToolDependencies(tools)).toBe(false);
252
- });
253
-
254
- test('returns true for sequential tool', () => {
255
- const tools = [
256
- createTool('tool_a'),
257
- createTool('tool_b', { sequential: true }),
258
- ];
259
-
260
- expect(hasToolDependencies(tools)).toBe(true);
261
- });
262
-
263
- test('returns true for tool with dependsOn', () => {
264
- const tools = [
265
- createTool('tool_a'),
266
- createTool('tool_b', { dependsOn: ['tool_a'] }),
267
- ];
268
-
269
- expect(hasToolDependencies(tools)).toBe(true);
270
- });
271
-
272
- test('returns false for empty array', () => {
273
- expect(hasToolDependencies([])).toBe(false);
274
- });
275
- });
276
-
277
- describe('hasCallDependencies()', () => {
278
- test('returns false for calls without after field', () => {
279
- const calls = [
280
- createToolCall('tool_a'),
281
- createToolCall('tool_b'),
282
- ];
283
-
284
- expect(hasCallDependencies(calls)).toBe(false);
285
- });
286
-
287
- test('returns true for call with after field', () => {
288
- const calls = [
289
- createToolCall('tool_a', 'call-1'),
290
- createToolCall('tool_b', 'call-2', ['call-1']),
291
- ] as OrderedToolCall[];
292
-
293
- expect(hasCallDependencies(calls)).toBe(true);
294
- });
295
-
296
- test('returns false for empty array', () => {
297
- expect(hasCallDependencies([])).toBe(false);
298
- });
299
-
300
- test('returns false for empty after array', () => {
301
- const call: OrderedToolCall = {
302
- toolCallId: 'call-1',
303
- toolName: 'tool_a',
304
- arguments: {},
305
- after: [],
306
- };
307
-
308
- expect(hasCallDependencies([call])).toBe(false);
309
- });
310
- });