@agentionai/agents 0.4.2 → 0.6.1
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.
- package/README.md +2 -2
- package/dist/agents/AgentConfig.d.ts +19 -0
- package/dist/agents/BaseAgent.d.ts +39 -0
- package/dist/agents/BaseAgent.js +100 -1
- package/dist/agents/anthropic/ClaudeAgent.d.ts +0 -2
- package/dist/agents/anthropic/ClaudeAgent.js +8 -4
- package/dist/agents/google/GeminiAgent.d.ts +0 -2
- package/dist/agents/google/GeminiAgent.js +4 -4
- package/dist/agents/mistral/MistralAgent.d.ts +0 -2
- package/dist/agents/mistral/MistralAgent.js +4 -4
- package/dist/agents/openai/OpenAiAgent.d.ts +0 -2
- package/dist/agents/openai/OpenAiAgent.js +4 -4
- package/dist/{vectorstore → embeddings}/OpenAIEmbeddings.d.ts +10 -2
- package/dist/{vectorstore → embeddings}/OpenAIEmbeddings.js +5 -1
- package/dist/embeddings/VoyageAIEmbeddings.d.ts +80 -0
- package/dist/embeddings/VoyageAIEmbeddings.js +139 -0
- package/dist/embeddings/index.d.ts +23 -0
- package/dist/embeddings/index.js +29 -0
- package/dist/graph/AgentGraph.d.ts +77 -0
- package/dist/graph/AgentGraph.js +112 -1
- package/dist/graph/context/ContextStore.d.ts +69 -0
- package/dist/graph/context/ContextStore.js +101 -0
- package/dist/graph/context/ContextTools.d.ts +52 -0
- package/dist/graph/context/ContextTools.js +148 -0
- package/dist/graph/context/index.d.ts +3 -0
- package/dist/graph/context/index.js +11 -0
- package/dist/graph/planning/PlanExecutor.d.ts +184 -0
- package/dist/graph/planning/PlanExecutor.js +396 -0
- package/dist/graph/planning/PlanStore.d.ts +81 -0
- package/dist/graph/planning/PlanStore.js +199 -0
- package/dist/graph/planning/PlanningTools.d.ts +45 -0
- package/dist/graph/planning/PlanningTools.js +178 -0
- package/dist/graph/planning/index.d.ts +5 -0
- package/dist/graph/planning/index.js +14 -0
- package/dist/graph/planning/types.d.ts +41 -0
- package/dist/graph/planning/types.js +3 -0
- package/dist/history/History.js +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/ingestion/IngestionPipeline.d.ts +1 -1
- package/dist/vectorstore/LanceDBVectorStore.d.ts +67 -2
- package/dist/vectorstore/LanceDBVectorStore.js +134 -23
- package/dist/vectorstore/index.d.ts +6 -4
- package/dist/vectorstore/index.js +10 -6
- package/package.json +12 -3
- /package/dist/{vectorstore → embeddings}/Embeddings.d.ts +0 -0
- /package/dist/{vectorstore → embeddings}/Embeddings.js +0 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlanExecutor = void 0;
|
|
4
|
+
const BaseExecutor_1 = require("../BaseExecutor");
|
|
5
|
+
/**
|
|
6
|
+
* Orchestrates plan-based execution with clear separation of concerns:
|
|
7
|
+
* 1. Planning Phase: Uses a planning agent to create a plan
|
|
8
|
+
* 2. Execution Phase: Assigns workers (agents or graph nodes) to execute each step
|
|
9
|
+
* 3. Completion: Compiles results and returns summary
|
|
10
|
+
*
|
|
11
|
+
* The PlanExecutor acts as the orchestrator, tracking progress and delegating
|
|
12
|
+
* work to specialized workers. Planning and execution are separate phases.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const planStore = AgentGraph.createPlanStore();
|
|
17
|
+
* const contextStore = AgentGraph.createContextStore();
|
|
18
|
+
*
|
|
19
|
+
* // Planning agent creates the plan
|
|
20
|
+
* const planner = new ClaudeAgent({
|
|
21
|
+
* tools: AgentGraph.createPlanningTools(planStore),
|
|
22
|
+
* description: 'You are a planning agent. Create a detailed plan with clear steps.',
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // Worker agent executes individual steps
|
|
26
|
+
* const worker = new ClaudeAgent({
|
|
27
|
+
* tools: AgentGraph.createContextTools(contextStore),
|
|
28
|
+
* description: 'You execute a single step. Store results in context.',
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* const executor = new PlanExecutor(planStore, planner, worker, {
|
|
32
|
+
* onStepComplete: (step, result, num) => {
|
|
33
|
+
* console.log(`Completed step ${num}: ${step.description}`);
|
|
34
|
+
* },
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* const result = await executor.execute('Research and summarize quantum computing');
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
class PlanExecutor extends BaseExecutor_1.BaseExecutor {
|
|
41
|
+
/**
|
|
42
|
+
* Create a new PlanExecutor.
|
|
43
|
+
*
|
|
44
|
+
* @param planStore - The plan store to track plan state
|
|
45
|
+
* @param planningAgent - Agent responsible for creating the plan
|
|
46
|
+
* @param worker - Agent or GraphNode that executes individual steps
|
|
47
|
+
* @param options - Configuration options
|
|
48
|
+
*/
|
|
49
|
+
constructor(planStore, planningAgent, worker, options = {}) {
|
|
50
|
+
super();
|
|
51
|
+
this.planStore = planStore;
|
|
52
|
+
this.name = "PlanExecutor";
|
|
53
|
+
this.nodeType = "pipeline";
|
|
54
|
+
this.planningAgent = planningAgent;
|
|
55
|
+
this.worker = worker;
|
|
56
|
+
this.options = {
|
|
57
|
+
maxSteps: options.maxSteps ?? 50,
|
|
58
|
+
concurrency: options.concurrency ?? 1,
|
|
59
|
+
stopOnFailure: options.stopOnFailure ?? true,
|
|
60
|
+
maxContextSteps: options.maxContextSteps ?? 0, // Default: no auto context
|
|
61
|
+
onPlanCreated: options.onPlanCreated,
|
|
62
|
+
onStepStart: options.onStepStart,
|
|
63
|
+
onStepComplete: options.onStepComplete,
|
|
64
|
+
onStepFailed: options.onStepFailed,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Execute the plan:
|
|
69
|
+
* 1. Planning Phase: Ask planning agent to create a plan
|
|
70
|
+
* 2. Execution Phase: Execute each step with the worker
|
|
71
|
+
* 3. Completion: Return finalOutput (for chaining)
|
|
72
|
+
*
|
|
73
|
+
* Returns the finalOutput string for easy chaining in pipelines.
|
|
74
|
+
* Use getLastResult() to access the full PlanExecutionResult with details.
|
|
75
|
+
*/
|
|
76
|
+
async execute(input) {
|
|
77
|
+
const collector = this.getCollector();
|
|
78
|
+
const execId = collector?.startExecution(this.name, "pipeline", input);
|
|
79
|
+
try {
|
|
80
|
+
// Phase 1: Planning
|
|
81
|
+
await this.planningPhase(input, collector);
|
|
82
|
+
// Phase 2: Execution
|
|
83
|
+
const stepResults = await this.executionPhase(collector);
|
|
84
|
+
// Phase 3: Compile results
|
|
85
|
+
const result = this.compileResult(stepResults);
|
|
86
|
+
// Store for getLastResult()
|
|
87
|
+
this.lastResult = result;
|
|
88
|
+
if (execId) {
|
|
89
|
+
collector?.endExecution(execId, result.success, result.finalOutput);
|
|
90
|
+
}
|
|
91
|
+
// Return finalOutput for chaining
|
|
92
|
+
return result.finalOutput;
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (execId) {
|
|
96
|
+
collector?.endExecution(execId, false, undefined, undefined, error instanceof Error ? error.message : String(error));
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get the detailed result from the last execution.
|
|
103
|
+
* Contains full plan details, step results, and metadata.
|
|
104
|
+
*/
|
|
105
|
+
getLastResult() {
|
|
106
|
+
return this.lastResult;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Phase 1: Planning
|
|
110
|
+
* Instructs the planning agent to create a plan based on the task.
|
|
111
|
+
*/
|
|
112
|
+
async planningPhase(task, collector) {
|
|
113
|
+
const planExecId = collector?.startExecution("Planning Phase", "agent", task);
|
|
114
|
+
try {
|
|
115
|
+
const planningPrompt = this.createPlanningPrompt(task);
|
|
116
|
+
const planningResult = (await this.planningAgent.execute(planningPrompt));
|
|
117
|
+
// Extract token usage
|
|
118
|
+
const tokenUsage = this.extractTokenUsage(this.planningAgent);
|
|
119
|
+
if (planExecId) {
|
|
120
|
+
collector?.endExecution(planExecId, true, planningResult, tokenUsage);
|
|
121
|
+
}
|
|
122
|
+
// Verify plan was created
|
|
123
|
+
const plan = this.planStore.getActivePlan();
|
|
124
|
+
if (!plan || plan.steps.length === 0) {
|
|
125
|
+
throw new Error("Planning agent failed to create a plan. Please ensure the agent has planning tools.");
|
|
126
|
+
}
|
|
127
|
+
// Enforce maxSteps limit
|
|
128
|
+
if (plan.steps.length > this.options.maxSteps) {
|
|
129
|
+
throw new Error(`Planning agent created ${plan.steps.length} steps, which exceeds the maximum of ${this.options.maxSteps}. ` +
|
|
130
|
+
`Please reduce the plan size or increase maxSteps option.`);
|
|
131
|
+
}
|
|
132
|
+
// Notify plan creation
|
|
133
|
+
this.options.onPlanCreated?.(plan.goal, plan.steps);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
if (planExecId) {
|
|
137
|
+
collector?.endExecution(planExecId, false, undefined, undefined, error instanceof Error ? error.message : String(error));
|
|
138
|
+
}
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Phase 2: Execution
|
|
144
|
+
* Executes each step in the plan using the worker.
|
|
145
|
+
*/
|
|
146
|
+
async executionPhase(collector) {
|
|
147
|
+
const plan = this.planStore.getActivePlan();
|
|
148
|
+
if (!plan) {
|
|
149
|
+
throw new Error("No active plan found");
|
|
150
|
+
}
|
|
151
|
+
const results = [];
|
|
152
|
+
let stepNumber = 0;
|
|
153
|
+
const activePromises = new Map();
|
|
154
|
+
let stopError;
|
|
155
|
+
while (stepNumber < this.options.maxSteps) {
|
|
156
|
+
// Wait if we've reached concurrency limit
|
|
157
|
+
if (activePromises.size >= this.options.concurrency) {
|
|
158
|
+
await Promise.race(activePromises.values());
|
|
159
|
+
}
|
|
160
|
+
// If a step failed and stopOnFailure is set, drain remaining promises then throw
|
|
161
|
+
if (stopError) {
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
const nextStep = this.planStore.getNextStep();
|
|
165
|
+
if (!nextStep) {
|
|
166
|
+
// No more pending steps
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
stepNumber++;
|
|
170
|
+
// Notify step start
|
|
171
|
+
this.options.onStepStart?.(nextStep, stepNumber, plan.steps.length);
|
|
172
|
+
// Mark step as in_progress
|
|
173
|
+
this.planStore.updateStep(nextStep.id, "in_progress");
|
|
174
|
+
const stepExecId = collector?.startExecution(`Step ${stepNumber}: ${nextStep.description}`, this.isAgent(this.worker) ? "agent" : "custom", nextStep.description);
|
|
175
|
+
// Wrap step execution in an async function
|
|
176
|
+
const executeStep = async () => {
|
|
177
|
+
try {
|
|
178
|
+
// Execute the step with the worker
|
|
179
|
+
const stepInput = this.createStepInput(nextStep, stepNumber);
|
|
180
|
+
const rawResult = await this.worker.execute(stepInput);
|
|
181
|
+
const stepResult = String(rawResult);
|
|
182
|
+
// Extract token usage if worker is an agent
|
|
183
|
+
const tokenUsage = this.isAgent(this.worker)
|
|
184
|
+
? this.extractTokenUsage(this.worker)
|
|
185
|
+
: undefined;
|
|
186
|
+
if (stepExecId) {
|
|
187
|
+
collector?.endExecution(stepExecId, true, stepResult, tokenUsage);
|
|
188
|
+
}
|
|
189
|
+
// Mark step as completed
|
|
190
|
+
this.planStore.updateStep(nextStep.id, "completed", stepResult);
|
|
191
|
+
results.push({
|
|
192
|
+
step: nextStep,
|
|
193
|
+
result: stepResult,
|
|
194
|
+
});
|
|
195
|
+
// Notify step completion
|
|
196
|
+
this.options.onStepComplete?.(nextStep, stepResult, stepNumber);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
200
|
+
if (stepExecId) {
|
|
201
|
+
collector?.endExecution(stepExecId, false, undefined, undefined, errorMessage);
|
|
202
|
+
}
|
|
203
|
+
// Mark step as failed
|
|
204
|
+
this.planStore.updateStep(nextStep.id, "failed", errorMessage);
|
|
205
|
+
results.push({
|
|
206
|
+
step: nextStep,
|
|
207
|
+
error: errorMessage,
|
|
208
|
+
});
|
|
209
|
+
// Notify step failure
|
|
210
|
+
this.options.onStepFailed?.(nextStep, error instanceof Error ? error : new Error(errorMessage), stepNumber);
|
|
211
|
+
// Record error to stop after in-flight steps complete
|
|
212
|
+
if (this.options.stopOnFailure) {
|
|
213
|
+
stopError = new Error(`Step ${stepNumber} failed: ${errorMessage}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
// Remove from active promises when complete
|
|
218
|
+
activePromises.delete(nextStep.id);
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
// Store the promise in activePromises
|
|
222
|
+
const promise = executeStep();
|
|
223
|
+
activePromises.set(nextStep.id, promise);
|
|
224
|
+
// For sequential execution (concurrency=1), await immediately
|
|
225
|
+
if (this.options.concurrency === 1) {
|
|
226
|
+
await promise;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Always wait for all in-flight promises to finish before returning/throwing
|
|
230
|
+
if (activePromises.size > 0) {
|
|
231
|
+
await Promise.allSettled(activePromises.values());
|
|
232
|
+
}
|
|
233
|
+
if (stopError) {
|
|
234
|
+
throw stopError;
|
|
235
|
+
}
|
|
236
|
+
if (stepNumber >= this.options.maxSteps) {
|
|
237
|
+
const plan = this.planStore.getActivePlan();
|
|
238
|
+
const remainingSteps = plan?.steps.filter((s) => s.status === "pending").length;
|
|
239
|
+
if (remainingSteps && remainingSteps > 0) {
|
|
240
|
+
throw new Error(`Maximum steps (${this.options.maxSteps}) reached with ${remainingSteps} steps remaining`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return results;
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Create a prompt for the planning agent.
|
|
247
|
+
*/
|
|
248
|
+
createPlanningPrompt(task) {
|
|
249
|
+
return `You are a planning agent. Your job is to create a detailed execution plan for the following task.
|
|
250
|
+
|
|
251
|
+
Task: ${task}
|
|
252
|
+
|
|
253
|
+
CRITICAL: You can create a maximum of ${this.options.maxSteps} steps. Plan accordingly and prioritize the most important subtasks.
|
|
254
|
+
|
|
255
|
+
CONTEXT LIMIT WARNING: Each step will be executed independently with limited context. To avoid rate limits and context overflow:
|
|
256
|
+
- Break work into VERY SMALL, ATOMIC steps
|
|
257
|
+
- Each step should process only 1-3 items at a time
|
|
258
|
+
- Never create steps that say "analyze all", "process everything", "read all files", etc.
|
|
259
|
+
- Instead, break into multiple steps: "Read file1", "Read file2", "Read file3"
|
|
260
|
+
|
|
261
|
+
Use the create_plan tool to create a plan with clear, actionable steps. Each step MUST be:
|
|
262
|
+
|
|
263
|
+
1. MICRO-SIZED - Can be completed in under 10 seconds with minimal tokens
|
|
264
|
+
2. SINGLE ACTION - Exactly ONE thing to do (read ONE file, list ONE directory, etc.)
|
|
265
|
+
3. SPECIFIC - Mention exact file names, directories, or items (not "all files")
|
|
266
|
+
4. NO BATCH OPERATIONS - Process items one-by-one, not in bulk
|
|
267
|
+
5. SEQUENTIAL - Let each step's output inform the next step
|
|
268
|
+
|
|
269
|
+
GOOD EXAMPLES (SMALL STEPS):
|
|
270
|
+
✓ "List files in the lib/graph directory"
|
|
271
|
+
✓ "Read the first 50 lines of PlanExecutor.ts"
|
|
272
|
+
✓ "Search for the definition of 'createPlan' function"
|
|
273
|
+
✓ "Summarize the purpose of SequentialExecutor class in 2 sentences"
|
|
274
|
+
|
|
275
|
+
BAD EXAMPLES (TOO LARGE):
|
|
276
|
+
✗ "Read and analyze all files in lib/graph" (reads too much, use multiple steps)
|
|
277
|
+
✗ "Analyze the entire codebase architecture" (too broad, break into 5+ steps)
|
|
278
|
+
✗ "Review all test files and identify issues" (batch operation, do one at a time)
|
|
279
|
+
✗ "Research best practices and implement them" (vague, multi-step)
|
|
280
|
+
|
|
281
|
+
STRATEGY FOR AVOIDING RATE LIMITS:
|
|
282
|
+
- If analyzing multiple files: Create one step per file
|
|
283
|
+
- If processing a list: Create one step per item
|
|
284
|
+
- If researching: Create steps for: 1) identify what to research, 2) research item 1, 3) research item 2, etc.
|
|
285
|
+
- If the task seems large: Create 2x as many steps as you initially think
|
|
286
|
+
|
|
287
|
+
Break down complex tasks into the SMALLEST possible steps. Having ${this.options.maxSteps} small steps is much better than having ${Math.floor(this.options.maxSteps / 2)} larger ones.
|
|
288
|
+
|
|
289
|
+
After creating the plan, respond with a brief confirmation.`;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Create input for a step execution.
|
|
293
|
+
*
|
|
294
|
+
* By default, only includes the current step information.
|
|
295
|
+
* Workers should use context_get to retrieve data from previous steps.
|
|
296
|
+
* This prevents token overflow from accumulating context.
|
|
297
|
+
*/
|
|
298
|
+
createStepInput(step, stepNumber) {
|
|
299
|
+
const plan = this.planStore.getActivePlan();
|
|
300
|
+
const completedSteps = plan?.steps.filter((s) => s.status === "completed") || [];
|
|
301
|
+
// Limit context to prevent token overflow
|
|
302
|
+
// Only include the most recent N steps based on maxContextSteps option
|
|
303
|
+
const recentSteps = this.options.maxContextSteps > 0
|
|
304
|
+
? completedSteps.slice(-this.options.maxContextSteps)
|
|
305
|
+
: [];
|
|
306
|
+
const input = {
|
|
307
|
+
stepNumber,
|
|
308
|
+
totalSteps: plan?.steps.length,
|
|
309
|
+
currentStep: {
|
|
310
|
+
id: step.id,
|
|
311
|
+
description: step.description,
|
|
312
|
+
},
|
|
313
|
+
planGoal: plan?.goal,
|
|
314
|
+
};
|
|
315
|
+
// Only add previous steps if maxContextSteps > 0
|
|
316
|
+
if (this.options.maxContextSteps > 0 && recentSteps.length > 0) {
|
|
317
|
+
input.previousSteps = recentSteps.map((s) => ({
|
|
318
|
+
description: s.description,
|
|
319
|
+
output: s.output,
|
|
320
|
+
}));
|
|
321
|
+
input.contextNote = `Showing last ${recentSteps.length} of ${completedSteps.length} completed steps`;
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
input.contextNote =
|
|
325
|
+
"Use context_get tool to retrieve data from previous steps if needed";
|
|
326
|
+
}
|
|
327
|
+
return JSON.stringify(input, null, 2);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Compile the final result from step results.
|
|
331
|
+
*/
|
|
332
|
+
compileResult(stepResults) {
|
|
333
|
+
const plan = this.planStore.getActivePlan();
|
|
334
|
+
if (!plan) {
|
|
335
|
+
throw new Error("No active plan found");
|
|
336
|
+
}
|
|
337
|
+
const completedSteps = stepResults.filter((r) => r.result).length;
|
|
338
|
+
const failedSteps = stepResults.filter((r) => r.error).length;
|
|
339
|
+
// Create consolidated output for chaining
|
|
340
|
+
const finalOutput = this.createFinalOutput(plan.goal, stepResults);
|
|
341
|
+
return {
|
|
342
|
+
success: plan.status === "completed",
|
|
343
|
+
goal: plan.goal,
|
|
344
|
+
totalSteps: plan.steps.length,
|
|
345
|
+
completedSteps,
|
|
346
|
+
failedSteps,
|
|
347
|
+
summary: this.planStore.getSummary(),
|
|
348
|
+
finalOutput,
|
|
349
|
+
stepResults,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Create a clean, consolidated output from all step results.
|
|
354
|
+
* This output is designed for chaining to the next graph node.
|
|
355
|
+
*/
|
|
356
|
+
createFinalOutput(goal, stepResults) {
|
|
357
|
+
const completedResults = stepResults
|
|
358
|
+
.filter((r) => r.result)
|
|
359
|
+
.map((r) => r.result)
|
|
360
|
+
.join("\n\n");
|
|
361
|
+
// If there are any failures, include them
|
|
362
|
+
const failures = stepResults.filter((r) => r.error);
|
|
363
|
+
const failureText = failures.length > 0
|
|
364
|
+
? `\n\nFailed steps (${failures.length}):\n${failures
|
|
365
|
+
.map((f) => `- ${f.step.description}: ${f.error}`)
|
|
366
|
+
.join("\n")}`
|
|
367
|
+
: "";
|
|
368
|
+
return `Goal: ${goal}\n\nResults:\n${completedResults}${failureText}`;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Check if a worker is a BaseAgent.
|
|
372
|
+
*/
|
|
373
|
+
isAgent(worker) {
|
|
374
|
+
return "getName" in worker;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Extract token usage from an agent if available.
|
|
378
|
+
*/
|
|
379
|
+
extractTokenUsage(agent) {
|
|
380
|
+
if (!agent.lastTokenUsage)
|
|
381
|
+
return undefined;
|
|
382
|
+
return {
|
|
383
|
+
inputTokens: agent.lastTokenUsage.input_tokens,
|
|
384
|
+
outputTokens: agent.lastTokenUsage.output_tokens,
|
|
385
|
+
totalTokens: agent.lastTokenUsage.total_tokens,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get the plan store.
|
|
390
|
+
*/
|
|
391
|
+
getPlanStore() {
|
|
392
|
+
return this.planStore;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
exports.PlanExecutor = PlanExecutor;
|
|
396
|
+
//# sourceMappingURL=PlanExecutor.js.map
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Plan, PlanStep, PlanStepStatus } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Manages plans within a pipeline execution.
|
|
4
|
+
* Provides methods to create, update, and track plan progress.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* const planStore = new PlanStore();
|
|
9
|
+
* const plan = planStore.createPlan('Research AI', ['Search papers', 'Analyze findings', 'Write summary']);
|
|
10
|
+
*
|
|
11
|
+
* // Work through steps
|
|
12
|
+
* const nextStep = planStore.getNextStep();
|
|
13
|
+
* planStore.updateStep(nextStep.id, 'completed', 'Found 5 relevant papers');
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare class PlanStore {
|
|
17
|
+
private plans;
|
|
18
|
+
private activePlanId?;
|
|
19
|
+
/**
|
|
20
|
+
* Create a new plan with a goal and list of step descriptions.
|
|
21
|
+
* @param goal - The overall goal to achieve
|
|
22
|
+
* @param steps - Array of step descriptions
|
|
23
|
+
* @returns The created plan
|
|
24
|
+
*/
|
|
25
|
+
createPlan(goal: string, steps: string[]): Plan;
|
|
26
|
+
/**
|
|
27
|
+
* Get the currently active plan.
|
|
28
|
+
* @returns The active plan or undefined if none
|
|
29
|
+
*/
|
|
30
|
+
getActivePlan(): Plan | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Get a plan by its ID.
|
|
33
|
+
* @param id - The plan ID
|
|
34
|
+
* @returns The plan or undefined if not found
|
|
35
|
+
*/
|
|
36
|
+
getPlan(id: string): Plan | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Set the active plan by ID.
|
|
39
|
+
* @param id - The plan ID to set as active
|
|
40
|
+
* @returns True if the plan exists and was set as active
|
|
41
|
+
*/
|
|
42
|
+
setActivePlan(id: string): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Update a step's status and optionally its output or error.
|
|
45
|
+
* @param stepId - The step ID to update
|
|
46
|
+
* @param status - The new status
|
|
47
|
+
* @param output - Optional output from the step
|
|
48
|
+
* @param error - Optional error message
|
|
49
|
+
*/
|
|
50
|
+
updateStep(stepId: string, status: PlanStepStatus, output?: string, error?: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Get the next pending step that can be executed.
|
|
53
|
+
* @returns The next pending step or undefined if none
|
|
54
|
+
*/
|
|
55
|
+
getNextStep(): PlanStep | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Add a new step to the active plan.
|
|
58
|
+
* @param description - The step description
|
|
59
|
+
* @returns The created step or undefined if no active plan
|
|
60
|
+
*/
|
|
61
|
+
addStep(description: string): PlanStep | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Get a human-readable summary of the active plan.
|
|
64
|
+
* @returns A formatted summary string
|
|
65
|
+
*/
|
|
66
|
+
getSummary(): string;
|
|
67
|
+
/**
|
|
68
|
+
* Get all plans.
|
|
69
|
+
* @returns Array of all plans
|
|
70
|
+
*/
|
|
71
|
+
getAllPlans(): Plan[];
|
|
72
|
+
/**
|
|
73
|
+
* Clear all plans.
|
|
74
|
+
*/
|
|
75
|
+
clear(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Update the overall plan status based on step statuses.
|
|
78
|
+
*/
|
|
79
|
+
private updatePlanStatus;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=PlanStore.d.ts.map
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlanStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Manages plans within a pipeline execution.
|
|
6
|
+
* Provides methods to create, update, and track plan progress.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const planStore = new PlanStore();
|
|
11
|
+
* const plan = planStore.createPlan('Research AI', ['Search papers', 'Analyze findings', 'Write summary']);
|
|
12
|
+
*
|
|
13
|
+
* // Work through steps
|
|
14
|
+
* const nextStep = planStore.getNextStep();
|
|
15
|
+
* planStore.updateStep(nextStep.id, 'completed', 'Found 5 relevant papers');
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
class PlanStore {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.plans = new Map();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a new plan with a goal and list of step descriptions.
|
|
24
|
+
* @param goal - The overall goal to achieve
|
|
25
|
+
* @param steps - Array of step descriptions
|
|
26
|
+
* @returns The created plan
|
|
27
|
+
*/
|
|
28
|
+
createPlan(goal, steps) {
|
|
29
|
+
const id = `plan_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
const plan = {
|
|
32
|
+
id,
|
|
33
|
+
goal,
|
|
34
|
+
steps: steps.map((description, index) => ({
|
|
35
|
+
id: `step_${index + 1}`,
|
|
36
|
+
description,
|
|
37
|
+
status: "pending",
|
|
38
|
+
})),
|
|
39
|
+
status: "created",
|
|
40
|
+
createdAt: now,
|
|
41
|
+
updatedAt: now,
|
|
42
|
+
};
|
|
43
|
+
this.plans.set(id, plan);
|
|
44
|
+
this.activePlanId = id;
|
|
45
|
+
return plan;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the currently active plan.
|
|
49
|
+
* @returns The active plan or undefined if none
|
|
50
|
+
*/
|
|
51
|
+
getActivePlan() {
|
|
52
|
+
return this.activePlanId ? this.plans.get(this.activePlanId) : undefined;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get a plan by its ID.
|
|
56
|
+
* @param id - The plan ID
|
|
57
|
+
* @returns The plan or undefined if not found
|
|
58
|
+
*/
|
|
59
|
+
getPlan(id) {
|
|
60
|
+
return this.plans.get(id);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Set the active plan by ID.
|
|
64
|
+
* @param id - The plan ID to set as active
|
|
65
|
+
* @returns True if the plan exists and was set as active
|
|
66
|
+
*/
|
|
67
|
+
setActivePlan(id) {
|
|
68
|
+
if (this.plans.has(id)) {
|
|
69
|
+
this.activePlanId = id;
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Update a step's status and optionally its output or error.
|
|
76
|
+
* @param stepId - The step ID to update
|
|
77
|
+
* @param status - The new status
|
|
78
|
+
* @param output - Optional output from the step
|
|
79
|
+
* @param error - Optional error message
|
|
80
|
+
*/
|
|
81
|
+
updateStep(stepId, status, output, error) {
|
|
82
|
+
const plan = this.getActivePlan();
|
|
83
|
+
if (!plan)
|
|
84
|
+
return;
|
|
85
|
+
const step = plan.steps.find((s) => s.id === stepId);
|
|
86
|
+
if (!step)
|
|
87
|
+
return;
|
|
88
|
+
step.status = status;
|
|
89
|
+
if (output !== undefined)
|
|
90
|
+
step.output = output;
|
|
91
|
+
if (error !== undefined)
|
|
92
|
+
step.error = error;
|
|
93
|
+
plan.updatedAt = Date.now();
|
|
94
|
+
// Update plan status based on steps
|
|
95
|
+
this.updatePlanStatus(plan);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get the next pending step that can be executed.
|
|
99
|
+
* @returns The next pending step or undefined if none
|
|
100
|
+
*/
|
|
101
|
+
getNextStep() {
|
|
102
|
+
const plan = this.getActivePlan();
|
|
103
|
+
if (!plan || plan.status === "completed" || plan.status === "failed") {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
// Mark plan as executing if it was just created
|
|
107
|
+
if (plan.status === "created") {
|
|
108
|
+
plan.status = "executing";
|
|
109
|
+
plan.updatedAt = Date.now();
|
|
110
|
+
}
|
|
111
|
+
return plan.steps.find((step) => step.status === "pending");
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Add a new step to the active plan.
|
|
115
|
+
* @param description - The step description
|
|
116
|
+
* @returns The created step or undefined if no active plan
|
|
117
|
+
*/
|
|
118
|
+
addStep(description) {
|
|
119
|
+
const plan = this.getActivePlan();
|
|
120
|
+
if (!plan)
|
|
121
|
+
return undefined;
|
|
122
|
+
const maxIndex = plan.steps.reduce((max, s) => {
|
|
123
|
+
const match = s.id.match(/^step_(\d+)$/);
|
|
124
|
+
return match ? Math.max(max, parseInt(match[1], 10)) : max;
|
|
125
|
+
}, 0);
|
|
126
|
+
const newStep = {
|
|
127
|
+
id: `step_${maxIndex + 1}`,
|
|
128
|
+
description,
|
|
129
|
+
status: "pending",
|
|
130
|
+
};
|
|
131
|
+
plan.steps.push(newStep);
|
|
132
|
+
plan.updatedAt = Date.now();
|
|
133
|
+
return newStep;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Get a human-readable summary of the active plan.
|
|
137
|
+
* @returns A formatted summary string
|
|
138
|
+
*/
|
|
139
|
+
getSummary() {
|
|
140
|
+
const plan = this.getActivePlan();
|
|
141
|
+
if (!plan)
|
|
142
|
+
return "No active plan";
|
|
143
|
+
const statusEmoji = {
|
|
144
|
+
pending: "[ ]",
|
|
145
|
+
in_progress: "[~]",
|
|
146
|
+
completed: "[x]",
|
|
147
|
+
failed: "[!]",
|
|
148
|
+
skipped: "[-]",
|
|
149
|
+
};
|
|
150
|
+
const lines = [
|
|
151
|
+
`Plan: ${plan.goal}`,
|
|
152
|
+
`Status: ${plan.status}`,
|
|
153
|
+
`Steps:`,
|
|
154
|
+
...plan.steps.map((step) => ` ${statusEmoji[step.status]} ${step.id}: ${step.description}`),
|
|
155
|
+
];
|
|
156
|
+
return lines.join("\n");
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get all plans.
|
|
160
|
+
* @returns Array of all plans
|
|
161
|
+
*/
|
|
162
|
+
getAllPlans() {
|
|
163
|
+
return Array.from(this.plans.values());
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Clear all plans.
|
|
167
|
+
*/
|
|
168
|
+
clear() {
|
|
169
|
+
this.plans.clear();
|
|
170
|
+
this.activePlanId = undefined;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Update the overall plan status based on step statuses.
|
|
174
|
+
*/
|
|
175
|
+
updatePlanStatus(plan) {
|
|
176
|
+
const allCompleted = plan.steps.every((s) => s.status === "completed" || s.status === "skipped");
|
|
177
|
+
const anyFailed = plan.steps.some((s) => s.status === "failed");
|
|
178
|
+
const anyInProgress = plan.steps.some((s) => s.status === "in_progress");
|
|
179
|
+
let newStatus;
|
|
180
|
+
if (allCompleted) {
|
|
181
|
+
newStatus = "completed";
|
|
182
|
+
}
|
|
183
|
+
else if (anyFailed) {
|
|
184
|
+
newStatus = "failed";
|
|
185
|
+
}
|
|
186
|
+
else if (anyInProgress || plan.steps.some((s) => s.status === "completed")) {
|
|
187
|
+
newStatus = "executing";
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
newStatus = plan.status;
|
|
191
|
+
}
|
|
192
|
+
if (plan.status !== newStatus) {
|
|
193
|
+
plan.status = newStatus;
|
|
194
|
+
plan.updatedAt = Date.now();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
exports.PlanStore = PlanStore;
|
|
199
|
+
//# sourceMappingURL=PlanStore.js.map
|