@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
@@ -0,0 +1,679 @@
1
+ export { loop } from '../chunk-4ESYN66B.js';
2
+ import { generateUUID } from '../chunk-EKRXMSDX.js';
3
+ import { UserMessage } from '@providerprotocol/ai';
4
+
5
+ var DEFAULT_REACT_OPTIONS = {
6
+ maxSteps: Infinity,
7
+ reasoningPrompt: "Think step by step about what you need to do next. Consider the current state, what tools are available, and what action would be most helpful."
8
+ };
9
+ function react(options = {}) {
10
+ const opts = { ...DEFAULT_REACT_OPTIONS, ...options };
11
+ return {
12
+ name: "react",
13
+ async execute(context) {
14
+ const { llm, input, state, strategy, signal } = context;
15
+ let currentState = state.withMessage(input).withMetadata("agentId", context.agent.id);
16
+ let step = 0;
17
+ let finalTurn;
18
+ const messages = [...currentState.messages];
19
+ while (true) {
20
+ step++;
21
+ currentState = currentState.withStep(step);
22
+ if (signal?.aborted) {
23
+ throw new Error("Execution aborted");
24
+ }
25
+ strategy.onStepStart?.(step, currentState);
26
+ const reasoningMessages = [
27
+ ...messages,
28
+ new UserMessage(opts.reasoningPrompt)
29
+ ];
30
+ const reasoningTurn = await llm.generate(reasoningMessages);
31
+ const reasoning = reasoningTurn.response.text;
32
+ currentState = currentState.withReasoning(reasoning);
33
+ strategy.onReason?.(step, reasoning);
34
+ messages.push(...reasoningTurn.messages);
35
+ const actionPrompt = new UserMessage(
36
+ "Based on your reasoning, take the appropriate action. Use tools if needed, or provide a final answer."
37
+ );
38
+ messages.push(actionPrompt);
39
+ const actionTurn = await llm.generate(messages);
40
+ finalTurn = actionTurn;
41
+ messages.push(...actionTurn.messages);
42
+ currentState = currentState.withMessages(actionTurn.messages);
43
+ if (actionTurn.response.hasToolCalls) {
44
+ strategy.onAct?.(step, actionTurn.response.toolCalls ?? []);
45
+ }
46
+ if (actionTurn.toolExecutions && actionTurn.toolExecutions.length > 0) {
47
+ strategy.onObserve?.(step, actionTurn.toolExecutions);
48
+ }
49
+ strategy.onStepEnd?.(step, { turn: actionTurn, state: currentState });
50
+ const shouldStop = await strategy.stopCondition?.(currentState);
51
+ if (shouldStop) {
52
+ break;
53
+ }
54
+ if (!actionTurn.response.hasToolCalls) {
55
+ break;
56
+ }
57
+ if (opts.maxSteps !== Infinity && step >= opts.maxSteps) {
58
+ break;
59
+ }
60
+ }
61
+ if (!finalTurn) {
62
+ throw new Error("No turn generated");
63
+ }
64
+ let finalState = currentState;
65
+ if (context.sessionId) {
66
+ finalState = currentState.withMetadata("sessionId", context.sessionId);
67
+ }
68
+ const result = {
69
+ turn: finalTurn,
70
+ state: finalState
71
+ };
72
+ strategy.onComplete?.(result);
73
+ return result;
74
+ },
75
+ stream(context) {
76
+ const { llm, input, state, strategy, signal } = context;
77
+ const agentId = context.agent.id;
78
+ let aborted = false;
79
+ const abortController = new AbortController();
80
+ if (signal) {
81
+ signal.addEventListener("abort", () => abortController.abort());
82
+ }
83
+ let resolveResult;
84
+ let rejectResult;
85
+ const resultPromise = new Promise((resolve, reject) => {
86
+ resolveResult = resolve;
87
+ rejectResult = reject;
88
+ });
89
+ async function* generateEvents() {
90
+ let currentState = state.withMessage(input).withMetadata("agentId", context.agent.id);
91
+ let step = 0;
92
+ let finalTurn;
93
+ const messages = [...currentState.messages];
94
+ try {
95
+ while (!aborted) {
96
+ step++;
97
+ currentState = currentState.withStep(step);
98
+ if (abortController.signal.aborted) {
99
+ throw new Error("Execution aborted");
100
+ }
101
+ strategy.onStepStart?.(step, currentState);
102
+ yield {
103
+ source: "uap",
104
+ uap: {
105
+ type: "step_start",
106
+ step,
107
+ agentId,
108
+ data: { phase: "reasoning" }
109
+ }
110
+ };
111
+ const reasoningMessages = [
112
+ ...messages,
113
+ new UserMessage(opts.reasoningPrompt)
114
+ ];
115
+ const reasoningStream = llm.stream(reasoningMessages);
116
+ let reasoningText = "";
117
+ for await (const event of reasoningStream) {
118
+ if (abortController.signal.aborted) {
119
+ throw new Error("Execution aborted");
120
+ }
121
+ yield { source: "upp", upp: event };
122
+ if (event.type === "text_delta" && event.delta.text) {
123
+ reasoningText += event.delta.text;
124
+ }
125
+ }
126
+ const reasoningTurn = await reasoningStream.turn;
127
+ currentState = currentState.withReasoning(reasoningText || reasoningTurn.response.text);
128
+ strategy.onReason?.(step, reasoningText || reasoningTurn.response.text);
129
+ yield {
130
+ source: "uap",
131
+ uap: {
132
+ type: "reasoning",
133
+ step,
134
+ agentId,
135
+ data: { reasoning: reasoningText || reasoningTurn.response.text }
136
+ }
137
+ };
138
+ messages.push(...reasoningTurn.messages);
139
+ const actionPrompt = new UserMessage(
140
+ "Based on your reasoning, take the appropriate action. Use tools if needed, or provide a final answer."
141
+ );
142
+ messages.push(actionPrompt);
143
+ const actionStream = llm.stream(messages);
144
+ for await (const event of actionStream) {
145
+ if (abortController.signal.aborted) {
146
+ throw new Error("Execution aborted");
147
+ }
148
+ yield { source: "upp", upp: event };
149
+ }
150
+ const actionTurn = await actionStream.turn;
151
+ finalTurn = actionTurn;
152
+ messages.push(...actionTurn.messages);
153
+ currentState = currentState.withMessages(actionTurn.messages);
154
+ if (actionTurn.response.hasToolCalls) {
155
+ strategy.onAct?.(step, actionTurn.response.toolCalls ?? []);
156
+ yield {
157
+ source: "uap",
158
+ uap: {
159
+ type: "action",
160
+ step,
161
+ agentId,
162
+ data: { toolCalls: actionTurn.response.toolCalls }
163
+ }
164
+ };
165
+ }
166
+ if (actionTurn.toolExecutions && actionTurn.toolExecutions.length > 0) {
167
+ strategy.onObserve?.(step, actionTurn.toolExecutions);
168
+ yield {
169
+ source: "uap",
170
+ uap: {
171
+ type: "observation",
172
+ step,
173
+ agentId,
174
+ data: { observations: actionTurn.toolExecutions }
175
+ }
176
+ };
177
+ }
178
+ strategy.onStepEnd?.(step, { turn: actionTurn, state: currentState });
179
+ yield {
180
+ source: "uap",
181
+ uap: {
182
+ type: "step_end",
183
+ step,
184
+ agentId,
185
+ data: { phase: "complete" }
186
+ }
187
+ };
188
+ const shouldStop = await strategy.stopCondition?.(currentState);
189
+ if (shouldStop) {
190
+ break;
191
+ }
192
+ if (!actionTurn.response.hasToolCalls) {
193
+ break;
194
+ }
195
+ if (opts.maxSteps !== Infinity && step >= opts.maxSteps) {
196
+ break;
197
+ }
198
+ }
199
+ if (!finalTurn) {
200
+ throw new Error("No turn generated");
201
+ }
202
+ let finalState = currentState;
203
+ if (context.sessionId) {
204
+ finalState = currentState.withMetadata("sessionId", context.sessionId);
205
+ }
206
+ const result = {
207
+ turn: finalTurn,
208
+ state: finalState
209
+ };
210
+ strategy.onComplete?.(result);
211
+ resolveResult(result);
212
+ } catch (error) {
213
+ const err = error instanceof Error ? error : new Error(String(error));
214
+ strategy.onError?.(err, currentState);
215
+ rejectResult(err);
216
+ throw err;
217
+ }
218
+ }
219
+ const iterator = generateEvents();
220
+ return {
221
+ [Symbol.asyncIterator]() {
222
+ return iterator;
223
+ },
224
+ result: resultPromise,
225
+ abort() {
226
+ aborted = true;
227
+ abortController.abort();
228
+ }
229
+ };
230
+ }
231
+ };
232
+ }
233
+ var DEFAULT_PLAN_OPTIONS = {
234
+ maxPlanSteps: Infinity,
235
+ allowReplan: true,
236
+ planSchema: {
237
+ type: "object",
238
+ properties: {
239
+ steps: {
240
+ type: "array",
241
+ items: {
242
+ type: "object",
243
+ properties: {
244
+ id: { type: "string", description: "Unique step identifier" },
245
+ description: { type: "string", description: "What this step does" },
246
+ tool: { type: "string", description: "Tool to use (if applicable)" },
247
+ dependsOn: {
248
+ type: "array",
249
+ items: { type: "string" },
250
+ description: "IDs of steps this depends on"
251
+ }
252
+ },
253
+ required: ["id", "description", "dependsOn"]
254
+ }
255
+ }
256
+ },
257
+ required: ["steps"]
258
+ }
259
+ };
260
+ var PLAN_PROMPT = `Create a detailed execution plan to accomplish the task.
261
+ Break it down into clear steps, specifying which tool to use for each step if applicable.
262
+ Include dependencies between steps (which steps must complete before others can start).
263
+ Return your plan as a JSON object with a "steps" array.`;
264
+ function plan(options = {}) {
265
+ const opts = { ...DEFAULT_PLAN_OPTIONS, ...options };
266
+ return {
267
+ name: "plan",
268
+ async execute(context) {
269
+ const { llm, input, state, strategy, signal } = context;
270
+ let currentState = state.withMessage(input).withMetadata("agentId", context.agent.id);
271
+ let step = 0;
272
+ let finalTurn;
273
+ const messages = [...currentState.messages];
274
+ step++;
275
+ currentState = currentState.withStep(step);
276
+ if (signal?.aborted) {
277
+ throw new Error("Execution aborted");
278
+ }
279
+ strategy.onStepStart?.(step, currentState);
280
+ const planMessages = [
281
+ ...messages,
282
+ new UserMessage(PLAN_PROMPT)
283
+ ];
284
+ const planTurn = await llm.generate(planMessages);
285
+ let planData;
286
+ try {
287
+ if (planTurn.data) {
288
+ planData = planTurn.data;
289
+ } else {
290
+ const jsonMatch = planTurn.response.text.match(/\{[\s\S]*\}/);
291
+ if (jsonMatch) {
292
+ planData = JSON.parse(jsonMatch[0]);
293
+ } else {
294
+ throw new Error("Could not parse plan from response");
295
+ }
296
+ }
297
+ } catch (err) {
298
+ throw new Error(`Failed to parse execution plan: ${err instanceof Error ? err.message : String(err)}`);
299
+ }
300
+ let planSteps = planData.steps.map((s) => ({
301
+ id: s.id || generateUUID(),
302
+ description: s.description,
303
+ tool: s.tool,
304
+ dependsOn: s.dependsOn || [],
305
+ status: "pending"
306
+ }));
307
+ if (opts.maxPlanSteps !== Infinity && planSteps.length > opts.maxPlanSteps) {
308
+ planSteps = planSteps.slice(0, opts.maxPlanSteps);
309
+ }
310
+ currentState = currentState.withPlan(planSteps);
311
+ messages.push(...planTurn.messages);
312
+ strategy.onStepEnd?.(step, { turn: planTurn, state: currentState });
313
+ const completedSteps = /* @__PURE__ */ new Set();
314
+ while (planSteps.some((s) => s.status === "pending")) {
315
+ const nextStep = planSteps.find(
316
+ (s) => s.status === "pending" && s.dependsOn.every((depId) => completedSteps.has(depId))
317
+ );
318
+ if (!nextStep) {
319
+ break;
320
+ }
321
+ step++;
322
+ currentState = currentState.withStep(step);
323
+ if (signal?.aborted) {
324
+ throw new Error("Execution aborted");
325
+ }
326
+ strategy.onStepStart?.(step, currentState);
327
+ nextStep.status = "in_progress";
328
+ currentState = currentState.withPlan([...planSteps]);
329
+ const stepPrompt = new UserMessage(
330
+ `Execute step "${nextStep.id}": ${nextStep.description}${nextStep.tool ? ` using the ${nextStep.tool} tool` : ""}`
331
+ );
332
+ messages.push(stepPrompt);
333
+ try {
334
+ const stepTurn = await llm.generate(messages);
335
+ finalTurn = stepTurn;
336
+ messages.push(...stepTurn.messages);
337
+ currentState = currentState.withMessages(stepTurn.messages);
338
+ if (stepTurn.response.hasToolCalls) {
339
+ strategy.onAct?.(step, stepTurn.response.toolCalls ?? []);
340
+ }
341
+ if (stepTurn.toolExecutions && stepTurn.toolExecutions.length > 0) {
342
+ strategy.onObserve?.(step, stepTurn.toolExecutions);
343
+ }
344
+ nextStep.status = "completed";
345
+ completedSteps.add(nextStep.id);
346
+ currentState = currentState.withPlan([...planSteps]);
347
+ strategy.onStepEnd?.(step, { turn: stepTurn, state: currentState });
348
+ } catch (err) {
349
+ nextStep.status = "failed";
350
+ currentState = currentState.withPlan([...planSteps]);
351
+ throw err;
352
+ }
353
+ const shouldStop = await strategy.stopCondition?.(currentState);
354
+ if (shouldStop) {
355
+ break;
356
+ }
357
+ }
358
+ if (!finalTurn) {
359
+ finalTurn = planTurn;
360
+ }
361
+ let finalState = currentState;
362
+ if (context.sessionId) {
363
+ finalState = currentState.withMetadata("sessionId", context.sessionId);
364
+ }
365
+ const result = {
366
+ turn: finalTurn,
367
+ state: finalState
368
+ };
369
+ strategy.onComplete?.(result);
370
+ return result;
371
+ },
372
+ stream(context) {
373
+ const { llm, input, state, strategy, signal } = context;
374
+ const agentId = context.agent.id;
375
+ let aborted = false;
376
+ const abortController = new AbortController();
377
+ if (signal) {
378
+ signal.addEventListener("abort", () => abortController.abort());
379
+ }
380
+ let resolveResult;
381
+ let rejectResult;
382
+ const resultPromise = new Promise((resolve, reject) => {
383
+ resolveResult = resolve;
384
+ rejectResult = reject;
385
+ });
386
+ async function* generateEvents() {
387
+ let currentState = state.withMessage(input).withMetadata("agentId", context.agent.id);
388
+ let step = 0;
389
+ let finalTurn;
390
+ const messages = [...currentState.messages];
391
+ try {
392
+ step++;
393
+ currentState = currentState.withStep(step);
394
+ if (abortController.signal.aborted) {
395
+ throw new Error("Execution aborted");
396
+ }
397
+ strategy.onStepStart?.(step, currentState);
398
+ yield {
399
+ source: "uap",
400
+ uap: {
401
+ type: "step_start",
402
+ step,
403
+ agentId,
404
+ data: { phase: "planning" }
405
+ }
406
+ };
407
+ const planMessages = [
408
+ ...messages,
409
+ new UserMessage(PLAN_PROMPT)
410
+ ];
411
+ const planStream = llm.stream(planMessages);
412
+ for await (const event of planStream) {
413
+ if (abortController.signal.aborted) {
414
+ throw new Error("Execution aborted");
415
+ }
416
+ yield { source: "upp", upp: event };
417
+ }
418
+ const planTurn = await planStream.turn;
419
+ let planData;
420
+ try {
421
+ if (planTurn.data) {
422
+ planData = planTurn.data;
423
+ } else {
424
+ const jsonMatch = planTurn.response.text.match(/\{[\s\S]*\}/);
425
+ if (jsonMatch) {
426
+ planData = JSON.parse(jsonMatch[0]);
427
+ } else {
428
+ throw new Error("Could not parse plan from response");
429
+ }
430
+ }
431
+ } catch (err) {
432
+ throw new Error(`Failed to parse execution plan: ${err instanceof Error ? err.message : String(err)}`);
433
+ }
434
+ let planSteps = planData.steps.map((s) => ({
435
+ id: s.id || generateUUID(),
436
+ description: s.description,
437
+ tool: s.tool,
438
+ dependsOn: s.dependsOn || [],
439
+ status: "pending"
440
+ }));
441
+ if (opts.maxPlanSteps !== Infinity && planSteps.length > opts.maxPlanSteps) {
442
+ planSteps = planSteps.slice(0, opts.maxPlanSteps);
443
+ }
444
+ currentState = currentState.withPlan(planSteps);
445
+ messages.push(...planTurn.messages);
446
+ yield {
447
+ source: "uap",
448
+ uap: {
449
+ type: "plan_created",
450
+ step,
451
+ agentId,
452
+ data: { plan: planSteps }
453
+ }
454
+ };
455
+ strategy.onStepEnd?.(step, { turn: planTurn, state: currentState });
456
+ yield {
457
+ source: "uap",
458
+ uap: {
459
+ type: "step_end",
460
+ step,
461
+ agentId,
462
+ data: { phase: "planning" }
463
+ }
464
+ };
465
+ const completedSteps = /* @__PURE__ */ new Set();
466
+ while (planSteps.some((s) => s.status === "pending") && !aborted) {
467
+ const nextStep = planSteps.find(
468
+ (s) => s.status === "pending" && s.dependsOn.every((depId) => completedSteps.has(depId))
469
+ );
470
+ if (!nextStep) {
471
+ break;
472
+ }
473
+ step++;
474
+ currentState = currentState.withStep(step);
475
+ if (abortController.signal.aborted) {
476
+ throw new Error("Execution aborted");
477
+ }
478
+ strategy.onStepStart?.(step, currentState);
479
+ yield {
480
+ source: "uap",
481
+ uap: {
482
+ type: "plan_step_start",
483
+ step,
484
+ agentId,
485
+ data: { planStep: nextStep }
486
+ }
487
+ };
488
+ nextStep.status = "in_progress";
489
+ currentState = currentState.withPlan([...planSteps]);
490
+ const stepPrompt = new UserMessage(
491
+ `Execute step "${nextStep.id}": ${nextStep.description}${nextStep.tool ? ` using the ${nextStep.tool} tool` : ""}`
492
+ );
493
+ messages.push(stepPrompt);
494
+ const stepStream = llm.stream(messages);
495
+ for await (const event of stepStream) {
496
+ if (abortController.signal.aborted) {
497
+ throw new Error("Execution aborted");
498
+ }
499
+ yield { source: "upp", upp: event };
500
+ }
501
+ const stepTurn = await stepStream.turn;
502
+ finalTurn = stepTurn;
503
+ messages.push(...stepTurn.messages);
504
+ currentState = currentState.withMessages(stepTurn.messages);
505
+ if (stepTurn.response.hasToolCalls) {
506
+ strategy.onAct?.(step, stepTurn.response.toolCalls ?? []);
507
+ yield {
508
+ source: "uap",
509
+ uap: {
510
+ type: "action",
511
+ step,
512
+ agentId,
513
+ data: { toolCalls: stepTurn.response.toolCalls }
514
+ }
515
+ };
516
+ }
517
+ if (stepTurn.toolExecutions && stepTurn.toolExecutions.length > 0) {
518
+ strategy.onObserve?.(step, stepTurn.toolExecutions);
519
+ yield {
520
+ source: "uap",
521
+ uap: {
522
+ type: "observation",
523
+ step,
524
+ agentId,
525
+ data: { observations: stepTurn.toolExecutions }
526
+ }
527
+ };
528
+ }
529
+ nextStep.status = "completed";
530
+ completedSteps.add(nextStep.id);
531
+ currentState = currentState.withPlan([...planSteps]);
532
+ strategy.onStepEnd?.(step, { turn: stepTurn, state: currentState });
533
+ yield {
534
+ source: "uap",
535
+ uap: {
536
+ type: "plan_step_end",
537
+ step,
538
+ agentId,
539
+ data: { planStep: nextStep }
540
+ }
541
+ };
542
+ const shouldStop = await strategy.stopCondition?.(currentState);
543
+ if (shouldStop) {
544
+ break;
545
+ }
546
+ }
547
+ if (!finalTurn) {
548
+ finalTurn = planTurn;
549
+ }
550
+ let finalState = currentState;
551
+ if (context.sessionId) {
552
+ finalState = currentState.withMetadata("sessionId", context.sessionId);
553
+ }
554
+ const result = {
555
+ turn: finalTurn,
556
+ state: finalState
557
+ };
558
+ strategy.onComplete?.(result);
559
+ resolveResult(result);
560
+ } catch (error) {
561
+ const err = error instanceof Error ? error : new Error(String(error));
562
+ strategy.onError?.(err, currentState);
563
+ rejectResult(err);
564
+ throw err;
565
+ }
566
+ }
567
+ const iterator = generateEvents();
568
+ return {
569
+ [Symbol.asyncIterator]() {
570
+ return iterator;
571
+ },
572
+ result: resultPromise,
573
+ abort() {
574
+ aborted = true;
575
+ abortController.abort();
576
+ }
577
+ };
578
+ }
579
+ };
580
+ }
581
+
582
+ // src/execution/tool-ordering.ts
583
+ function buildToolMap(tools) {
584
+ const map = /* @__PURE__ */ new Map();
585
+ for (const tool of tools) {
586
+ map.set(tool.name, tool);
587
+ }
588
+ return map;
589
+ }
590
+ function getModelDependencies(call) {
591
+ const orderedCall = call;
592
+ return orderedCall.after ?? [];
593
+ }
594
+ function orderToolCalls(toolCalls, tools) {
595
+ if (toolCalls.length === 0) {
596
+ return [];
597
+ }
598
+ const toolMap = buildToolMap(tools);
599
+ const groups = [];
600
+ const completedCallIds = /* @__PURE__ */ new Set();
601
+ const completedToolNames = /* @__PURE__ */ new Set();
602
+ const pending = [...toolCalls];
603
+ while (pending.length > 0) {
604
+ const readyForExecution = [];
605
+ let hasSequential = false;
606
+ const stillPending = [];
607
+ for (const call of pending) {
608
+ const tool = toolMap.get(call.toolName);
609
+ const toolDependsOn = tool?.dependsOn ?? [];
610
+ const modelDependsOn = getModelDependencies(call);
611
+ const toolDepsOk = toolDependsOn.every(
612
+ (depName) => completedToolNames.has(depName)
613
+ );
614
+ const modelDepsOk = modelDependsOn.every(
615
+ (depId) => completedCallIds.has(depId)
616
+ );
617
+ if (toolDepsOk && modelDepsOk) {
618
+ readyForExecution.push(call);
619
+ if (tool?.sequential) {
620
+ hasSequential = true;
621
+ }
622
+ } else {
623
+ stillPending.push(call);
624
+ }
625
+ }
626
+ if (readyForExecution.length === 0 && stillPending.length > 0) {
627
+ groups.push({
628
+ calls: stillPending,
629
+ isBarrier: false
630
+ });
631
+ break;
632
+ }
633
+ if (hasSequential) {
634
+ for (const call of readyForExecution) {
635
+ const tool = toolMap.get(call.toolName);
636
+ groups.push({
637
+ calls: [call],
638
+ isBarrier: tool?.sequential ?? false
639
+ });
640
+ completedCallIds.add(call.toolCallId);
641
+ completedToolNames.add(call.toolName);
642
+ }
643
+ } else {
644
+ groups.push({
645
+ calls: readyForExecution,
646
+ isBarrier: false
647
+ });
648
+ for (const call of readyForExecution) {
649
+ completedCallIds.add(call.toolCallId);
650
+ completedToolNames.add(call.toolName);
651
+ }
652
+ }
653
+ pending.length = 0;
654
+ pending.push(...stillPending);
655
+ }
656
+ return groups;
657
+ }
658
+ function hasToolDependencies(tools) {
659
+ for (const tool of tools) {
660
+ const t = tool;
661
+ if (t.sequential || t.dependsOn && t.dependsOn.length > 0) {
662
+ return true;
663
+ }
664
+ }
665
+ return false;
666
+ }
667
+ function hasCallDependencies(toolCalls) {
668
+ for (const call of toolCalls) {
669
+ const ordered = call;
670
+ if (ordered.after && ordered.after.length > 0) {
671
+ return true;
672
+ }
673
+ }
674
+ return false;
675
+ }
676
+
677
+ export { hasCallDependencies, hasToolDependencies, orderToolCalls, plan, react };
678
+ //# sourceMappingURL=index.js.map
679
+ //# sourceMappingURL=index.js.map