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