confused-ai-core 0.1.0
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/FEATURES.md +169 -0
- package/package.json +119 -0
- package/src/agent.ts +187 -0
- package/src/agentic/index.ts +87 -0
- package/src/agentic/runner.ts +386 -0
- package/src/agentic/types.ts +91 -0
- package/src/artifacts/artifact.ts +417 -0
- package/src/artifacts/index.ts +42 -0
- package/src/artifacts/media.ts +304 -0
- package/src/cli/index.ts +122 -0
- package/src/core/base-agent.ts +151 -0
- package/src/core/context-builder.ts +106 -0
- package/src/core/index.ts +8 -0
- package/src/core/schemas.ts +17 -0
- package/src/core/types.ts +158 -0
- package/src/create-agent.ts +309 -0
- package/src/debug-logger.ts +188 -0
- package/src/dx/agent.ts +88 -0
- package/src/dx/define-agent.ts +183 -0
- package/src/dx/dev-logger.ts +57 -0
- package/src/dx/index.ts +11 -0
- package/src/errors.ts +175 -0
- package/src/execution/engine.ts +522 -0
- package/src/execution/graph-builder.ts +362 -0
- package/src/execution/index.ts +8 -0
- package/src/execution/types.ts +257 -0
- package/src/execution/worker-pool.ts +308 -0
- package/src/extensions/index.ts +123 -0
- package/src/guardrails/allowlist.ts +155 -0
- package/src/guardrails/index.ts +17 -0
- package/src/guardrails/types.ts +159 -0
- package/src/guardrails/validator.ts +265 -0
- package/src/index.ts +74 -0
- package/src/knowledge/index.ts +5 -0
- package/src/knowledge/types.ts +52 -0
- package/src/learning/in-memory-store.ts +72 -0
- package/src/learning/index.ts +6 -0
- package/src/learning/types.ts +42 -0
- package/src/llm/cache.ts +300 -0
- package/src/llm/index.ts +22 -0
- package/src/llm/model-resolver.ts +81 -0
- package/src/llm/openai-provider.ts +313 -0
- package/src/llm/openrouter-provider.ts +29 -0
- package/src/llm/types.ts +131 -0
- package/src/memory/in-memory-store.ts +255 -0
- package/src/memory/index.ts +7 -0
- package/src/memory/types.ts +193 -0
- package/src/memory/vector-store.ts +251 -0
- package/src/observability/console-logger.ts +123 -0
- package/src/observability/index.ts +12 -0
- package/src/observability/metrics.ts +85 -0
- package/src/observability/otlp-exporter.ts +417 -0
- package/src/observability/tracer.ts +105 -0
- package/src/observability/types.ts +341 -0
- package/src/orchestration/agent-adapter.ts +33 -0
- package/src/orchestration/index.ts +34 -0
- package/src/orchestration/load-balancer.ts +151 -0
- package/src/orchestration/mcp-types.ts +59 -0
- package/src/orchestration/message-bus.ts +192 -0
- package/src/orchestration/orchestrator.ts +349 -0
- package/src/orchestration/pipeline.ts +66 -0
- package/src/orchestration/supervisor.ts +107 -0
- package/src/orchestration/swarm.ts +1099 -0
- package/src/orchestration/toolkit.ts +47 -0
- package/src/orchestration/types.ts +339 -0
- package/src/planner/classical-planner.ts +383 -0
- package/src/planner/index.ts +8 -0
- package/src/planner/llm-planner.ts +353 -0
- package/src/planner/types.ts +227 -0
- package/src/planner/validator.ts +297 -0
- package/src/production/circuit-breaker.ts +290 -0
- package/src/production/graceful-shutdown.ts +251 -0
- package/src/production/health.ts +333 -0
- package/src/production/index.ts +57 -0
- package/src/production/latency-eval.ts +62 -0
- package/src/production/rate-limiter.ts +287 -0
- package/src/production/resumable-stream.ts +289 -0
- package/src/production/types.ts +81 -0
- package/src/sdk/index.ts +374 -0
- package/src/session/db-driver.ts +50 -0
- package/src/session/in-memory-store.ts +235 -0
- package/src/session/index.ts +12 -0
- package/src/session/sql-store.ts +315 -0
- package/src/session/sqlite-store.ts +61 -0
- package/src/session/types.ts +153 -0
- package/src/tools/base-tool.ts +223 -0
- package/src/tools/browser-tool.ts +123 -0
- package/src/tools/calculator-tool.ts +265 -0
- package/src/tools/file-tools.ts +394 -0
- package/src/tools/github-tool.ts +432 -0
- package/src/tools/hackernews-tool.ts +187 -0
- package/src/tools/http-tool.ts +118 -0
- package/src/tools/index.ts +99 -0
- package/src/tools/jira-tool.ts +373 -0
- package/src/tools/notion-tool.ts +322 -0
- package/src/tools/openai-tool.ts +236 -0
- package/src/tools/registry.ts +131 -0
- package/src/tools/serpapi-tool.ts +234 -0
- package/src/tools/shell-tool.ts +118 -0
- package/src/tools/slack-tool.ts +327 -0
- package/src/tools/telegram-tool.ts +127 -0
- package/src/tools/types.ts +229 -0
- package/src/tools/websearch-tool.ts +335 -0
- package/src/tools/wikipedia-tool.ts +177 -0
- package/src/tools/yfinance-tool.ts +33 -0
- package/src/voice/index.ts +17 -0
- package/src/voice/voice-provider.ts +228 -0
- package/tests/artifact.test.ts +241 -0
- package/tests/circuit-breaker.test.ts +171 -0
- package/tests/health.test.ts +192 -0
- package/tests/llm-cache.test.ts +186 -0
- package/tests/rate-limiter.test.ts +161 -0
- package/tsconfig.json +29 -0
- package/vitest.config.ts +47 -0
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution Graph Builder
|
|
3
|
+
*
|
|
4
|
+
* Builds and manages execution graphs for task dependency resolution
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
ExecutionGraph,
|
|
9
|
+
ExecutionNode,
|
|
10
|
+
ExecutionNodeStatus,
|
|
11
|
+
} from './types.js';
|
|
12
|
+
import {
|
|
13
|
+
Plan,
|
|
14
|
+
} from '../planner/types.js';
|
|
15
|
+
import type { EntityId } from '../core/types.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Options for building an execution graph
|
|
19
|
+
*/
|
|
20
|
+
export interface GraphBuildOptions {
|
|
21
|
+
readonly validateDependencies?: boolean;
|
|
22
|
+
readonly detectCycles?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Graph validation error
|
|
27
|
+
*/
|
|
28
|
+
export class GraphValidationError extends Error {
|
|
29
|
+
constructor(message: string, public readonly details: unknown) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.name = 'GraphValidationError';
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Mutable execution graph for internal use
|
|
37
|
+
*/
|
|
38
|
+
interface MutableExecutionGraph extends ExecutionGraph {
|
|
39
|
+
nodes: Map<EntityId, MutableExecutionNode>;
|
|
40
|
+
readyQueue: EntityId[];
|
|
41
|
+
completedCount: number;
|
|
42
|
+
failedCount: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Mutable execution node for internal use
|
|
47
|
+
*/
|
|
48
|
+
interface MutableExecutionNode extends ExecutionNode {
|
|
49
|
+
status: ExecutionNodeStatus;
|
|
50
|
+
dependencies: Set<EntityId>;
|
|
51
|
+
dependents: Set<EntityId>;
|
|
52
|
+
startedAt?: Date;
|
|
53
|
+
completedAt?: Date;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Execution graph builder
|
|
58
|
+
*/
|
|
59
|
+
export class ExecutionGraphBuilder {
|
|
60
|
+
private options: Required<GraphBuildOptions>;
|
|
61
|
+
|
|
62
|
+
constructor(options: GraphBuildOptions = {}) {
|
|
63
|
+
this.options = {
|
|
64
|
+
validateDependencies: true,
|
|
65
|
+
detectCycles: true,
|
|
66
|
+
...options,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Build an execution graph from a plan
|
|
72
|
+
*/
|
|
73
|
+
build(plan: Plan): ExecutionGraph {
|
|
74
|
+
const nodes = new Map<EntityId, MutableExecutionNode>();
|
|
75
|
+
const readyQueue: EntityId[] = [];
|
|
76
|
+
|
|
77
|
+
// Create nodes for all tasks
|
|
78
|
+
for (const task of plan.tasks) {
|
|
79
|
+
const node: MutableExecutionNode = {
|
|
80
|
+
task,
|
|
81
|
+
status: ExecutionNodeStatus.PENDING,
|
|
82
|
+
dependencies: new Set(task.dependencies),
|
|
83
|
+
dependents: new Set(),
|
|
84
|
+
};
|
|
85
|
+
nodes.set(task.id, node);
|
|
86
|
+
|
|
87
|
+
// Add to ready queue if no dependencies
|
|
88
|
+
if (task.dependencies.length === 0) {
|
|
89
|
+
readyQueue.push(task.id);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Build reverse dependency map (dependents)
|
|
94
|
+
for (const [id, node] of nodes) {
|
|
95
|
+
for (const depId of node.dependencies) {
|
|
96
|
+
const depNode = nodes.get(depId);
|
|
97
|
+
if (depNode) {
|
|
98
|
+
depNode.dependents.add(id);
|
|
99
|
+
} else if (this.options.validateDependencies) {
|
|
100
|
+
throw new GraphValidationError(
|
|
101
|
+
`Task ${id} has unknown dependency: ${depId}`,
|
|
102
|
+
{ taskId: id, dependencyId: depId }
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Detect cycles if enabled
|
|
109
|
+
if (this.options.detectCycles) {
|
|
110
|
+
const cycle = this.detectCycle(nodes);
|
|
111
|
+
if (cycle) {
|
|
112
|
+
throw new GraphValidationError(
|
|
113
|
+
`Circular dependency detected: ${cycle.join(' -> ')}`,
|
|
114
|
+
{ cycle }
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const graph: MutableExecutionGraph = {
|
|
120
|
+
planId: plan.id,
|
|
121
|
+
nodes,
|
|
122
|
+
readyQueue,
|
|
123
|
+
completedCount: 0,
|
|
124
|
+
failedCount: 0,
|
|
125
|
+
totalCount: plan.tasks.length,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return graph as ExecutionGraph;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Detect cycles in the graph using DFS
|
|
133
|
+
*/
|
|
134
|
+
private detectCycle(nodes: Map<EntityId, MutableExecutionNode>): EntityId[] | null {
|
|
135
|
+
const visited = new Set<EntityId>();
|
|
136
|
+
const recursionStack = new Set<EntityId>();
|
|
137
|
+
const path: EntityId[] = [];
|
|
138
|
+
|
|
139
|
+
const dfs = (nodeId: EntityId): EntityId[] | null => {
|
|
140
|
+
visited.add(nodeId);
|
|
141
|
+
recursionStack.add(nodeId);
|
|
142
|
+
path.push(nodeId);
|
|
143
|
+
|
|
144
|
+
const node = nodes.get(nodeId);
|
|
145
|
+
if (node) {
|
|
146
|
+
for (const dependentId of node.dependents) {
|
|
147
|
+
if (!visited.has(dependentId)) {
|
|
148
|
+
const cycle = dfs(dependentId);
|
|
149
|
+
if (cycle) return cycle;
|
|
150
|
+
} else if (recursionStack.has(dependentId)) {
|
|
151
|
+
// Found a cycle
|
|
152
|
+
const cycleStart = path.indexOf(dependentId);
|
|
153
|
+
return [...path.slice(cycleStart), dependentId];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
path.pop();
|
|
159
|
+
recursionStack.delete(nodeId);
|
|
160
|
+
return null;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
for (const nodeId of nodes.keys()) {
|
|
164
|
+
if (!visited.has(nodeId)) {
|
|
165
|
+
const cycle = dfs(nodeId);
|
|
166
|
+
if (cycle) return cycle;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get tasks that are ready to execute (all dependencies completed)
|
|
175
|
+
*/
|
|
176
|
+
getReadyTasks(graph: ExecutionGraph): EntityId[] {
|
|
177
|
+
const ready: EntityId[] = [];
|
|
178
|
+
const mutableGraph = graph as MutableExecutionGraph;
|
|
179
|
+
|
|
180
|
+
for (const [id, node] of mutableGraph.nodes) {
|
|
181
|
+
if (node.status !== ExecutionNodeStatus.PENDING) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const allDepsCompleted = Array.from(node.dependencies).every(depId => {
|
|
186
|
+
const depNode = mutableGraph.nodes.get(depId);
|
|
187
|
+
return depNode?.status === ExecutionNodeStatus.COMPLETED;
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
if (allDepsCompleted) {
|
|
191
|
+
ready.push(id);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return ready;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Update node status and propagate to dependents
|
|
200
|
+
*/
|
|
201
|
+
updateNodeStatus(
|
|
202
|
+
graph: ExecutionGraph,
|
|
203
|
+
nodeId: EntityId,
|
|
204
|
+
status: ExecutionNodeStatus
|
|
205
|
+
): void {
|
|
206
|
+
const mutableGraph = graph as MutableExecutionGraph;
|
|
207
|
+
const node = mutableGraph.nodes.get(nodeId);
|
|
208
|
+
if (!node) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
node.status = status;
|
|
213
|
+
|
|
214
|
+
// Update counters
|
|
215
|
+
if (status === ExecutionNodeStatus.COMPLETED) {
|
|
216
|
+
mutableGraph.completedCount++;
|
|
217
|
+
} else if (status === ExecutionNodeStatus.FAILED) {
|
|
218
|
+
mutableGraph.failedCount++;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// If completed or failed, check dependents
|
|
222
|
+
if (status === ExecutionNodeStatus.COMPLETED || status === ExecutionNodeStatus.FAILED) {
|
|
223
|
+
node.completedAt = new Date();
|
|
224
|
+
|
|
225
|
+
// Add ready dependents to queue
|
|
226
|
+
for (const dependentId of node.dependents) {
|
|
227
|
+
const dependent = mutableGraph.nodes.get(dependentId);
|
|
228
|
+
if (dependent && dependent.status === ExecutionNodeStatus.PENDING) {
|
|
229
|
+
const allDepsCompleted = Array.from(dependent.dependencies).every(depId => {
|
|
230
|
+
const depNode = mutableGraph.nodes.get(depId);
|
|
231
|
+
return depNode?.status === ExecutionNodeStatus.COMPLETED;
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
if (allDepsCompleted && !mutableGraph.readyQueue.includes(dependentId)) {
|
|
235
|
+
mutableGraph.readyQueue.push(dependentId);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get the execution order (topological sort)
|
|
244
|
+
*/
|
|
245
|
+
getExecutionOrder(graph: ExecutionGraph): EntityId[] {
|
|
246
|
+
const order: EntityId[] = [];
|
|
247
|
+
const visited = new Set<EntityId>();
|
|
248
|
+
const temp = new Set<EntityId>();
|
|
249
|
+
const mutableGraph = graph as MutableExecutionGraph;
|
|
250
|
+
|
|
251
|
+
const visit = (nodeId: EntityId): void => {
|
|
252
|
+
if (temp.has(nodeId)) {
|
|
253
|
+
throw new GraphValidationError('Cycle detected during topological sort', { nodeId });
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (visited.has(nodeId)) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
temp.add(nodeId);
|
|
261
|
+
const node = mutableGraph.nodes.get(nodeId);
|
|
262
|
+
|
|
263
|
+
if (node) {
|
|
264
|
+
for (const depId of node.dependencies) {
|
|
265
|
+
visit(depId);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
temp.delete(nodeId);
|
|
270
|
+
visited.add(nodeId);
|
|
271
|
+
order.push(nodeId);
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
for (const nodeId of mutableGraph.nodes.keys()) {
|
|
275
|
+
if (!visited.has(nodeId)) {
|
|
276
|
+
visit(nodeId);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return order;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Clone a graph
|
|
285
|
+
*/
|
|
286
|
+
clone(graph: ExecutionGraph): ExecutionGraph {
|
|
287
|
+
const mutableGraph = graph as MutableExecutionGraph;
|
|
288
|
+
const newNodes = new Map<EntityId, MutableExecutionNode>();
|
|
289
|
+
|
|
290
|
+
for (const [id, node] of mutableGraph.nodes) {
|
|
291
|
+
newNodes.set(id, {
|
|
292
|
+
task: node.task,
|
|
293
|
+
status: node.status,
|
|
294
|
+
dependencies: new Set(node.dependencies),
|
|
295
|
+
dependents: new Set(node.dependents),
|
|
296
|
+
result: node.result,
|
|
297
|
+
startedAt: node.startedAt,
|
|
298
|
+
completedAt: node.completedAt,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const newGraph: MutableExecutionGraph = {
|
|
303
|
+
planId: mutableGraph.planId,
|
|
304
|
+
nodes: newNodes,
|
|
305
|
+
readyQueue: [...mutableGraph.readyQueue],
|
|
306
|
+
completedCount: mutableGraph.completedCount,
|
|
307
|
+
failedCount: mutableGraph.failedCount,
|
|
308
|
+
totalCount: mutableGraph.totalCount,
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
return newGraph as ExecutionGraph;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Get graph statistics
|
|
316
|
+
*/
|
|
317
|
+
getStats(graph: ExecutionGraph): {
|
|
318
|
+
total: number;
|
|
319
|
+
pending: number;
|
|
320
|
+
running: number;
|
|
321
|
+
completed: number;
|
|
322
|
+
failed: number;
|
|
323
|
+
cancelled: number;
|
|
324
|
+
} {
|
|
325
|
+
const mutableGraph = graph as MutableExecutionGraph;
|
|
326
|
+
let pending = 0;
|
|
327
|
+
let running = 0;
|
|
328
|
+
let completed = 0;
|
|
329
|
+
let failed = 0;
|
|
330
|
+
let cancelled = 0;
|
|
331
|
+
|
|
332
|
+
for (const node of mutableGraph.nodes.values()) {
|
|
333
|
+
switch (node.status) {
|
|
334
|
+
case ExecutionNodeStatus.PENDING:
|
|
335
|
+
case ExecutionNodeStatus.READY:
|
|
336
|
+
pending++;
|
|
337
|
+
break;
|
|
338
|
+
case ExecutionNodeStatus.RUNNING:
|
|
339
|
+
running++;
|
|
340
|
+
break;
|
|
341
|
+
case ExecutionNodeStatus.COMPLETED:
|
|
342
|
+
completed++;
|
|
343
|
+
break;
|
|
344
|
+
case ExecutionNodeStatus.FAILED:
|
|
345
|
+
failed++;
|
|
346
|
+
break;
|
|
347
|
+
case ExecutionNodeStatus.CANCELLED:
|
|
348
|
+
cancelled++;
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
total: mutableGraph.totalCount,
|
|
355
|
+
pending,
|
|
356
|
+
running,
|
|
357
|
+
completed,
|
|
358
|
+
failed,
|
|
359
|
+
cancelled,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Execution engine types and interfaces
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { EntityId } from '../core/types.js';
|
|
6
|
+
import type { Task, TaskResult, Plan, PlanExecutionResult } from '../planner/types.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Execution engine configuration
|
|
10
|
+
*/
|
|
11
|
+
export interface ExecutionEngineConfig {
|
|
12
|
+
readonly maxConcurrency: number;
|
|
13
|
+
readonly defaultTimeoutMs: number;
|
|
14
|
+
readonly enableParallelExecution: boolean;
|
|
15
|
+
readonly workerPoolSize?: number;
|
|
16
|
+
readonly retryPolicy?: ExecutionRetryPolicy;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Execution retry policy
|
|
21
|
+
*/
|
|
22
|
+
export interface ExecutionRetryPolicy {
|
|
23
|
+
readonly maxRetries: number;
|
|
24
|
+
readonly backoffStrategy: BackoffStrategy;
|
|
25
|
+
readonly initialDelayMs: number;
|
|
26
|
+
readonly maxDelayMs: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Backoff strategies
|
|
31
|
+
*/
|
|
32
|
+
export enum BackoffStrategy {
|
|
33
|
+
FIXED = 'fixed',
|
|
34
|
+
LINEAR = 'linear',
|
|
35
|
+
EXPONENTIAL = 'exponential',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Execution context passed to tasks
|
|
40
|
+
*/
|
|
41
|
+
export interface ExecutionContext {
|
|
42
|
+
readonly executionId: EntityId;
|
|
43
|
+
readonly taskId: EntityId;
|
|
44
|
+
readonly planId: EntityId;
|
|
45
|
+
readonly inputs: Map<EntityId, unknown>;
|
|
46
|
+
readonly sharedState: Map<string, unknown>;
|
|
47
|
+
readonly metadata: TaskExecutionMetadata;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Task execution metadata
|
|
52
|
+
*/
|
|
53
|
+
export interface TaskExecutionMetadata {
|
|
54
|
+
readonly startedAt: Date;
|
|
55
|
+
readonly timeoutAt?: Date;
|
|
56
|
+
readonly attemptNumber: number;
|
|
57
|
+
readonly previousAttempts?: TaskResult[];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Task executor interface
|
|
62
|
+
*/
|
|
63
|
+
export interface TaskExecutor {
|
|
64
|
+
/**
|
|
65
|
+
* Execute a single task
|
|
66
|
+
*/
|
|
67
|
+
execute(task: Task, context: ExecutionContext): Promise<TaskResult>;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check if this executor can handle the task
|
|
71
|
+
*/
|
|
72
|
+
canExecute(task: Task): boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Execution graph node
|
|
77
|
+
*/
|
|
78
|
+
export interface ExecutionNode {
|
|
79
|
+
readonly task: Task;
|
|
80
|
+
readonly status: ExecutionNodeStatus;
|
|
81
|
+
readonly dependencies: Set<EntityId>;
|
|
82
|
+
readonly dependents: Set<EntityId>;
|
|
83
|
+
readonly result?: TaskResult;
|
|
84
|
+
readonly startedAt?: Date;
|
|
85
|
+
readonly completedAt?: Date;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Execution node status
|
|
90
|
+
*/
|
|
91
|
+
export enum ExecutionNodeStatus {
|
|
92
|
+
PENDING = 'pending',
|
|
93
|
+
READY = 'ready',
|
|
94
|
+
RUNNING = 'running',
|
|
95
|
+
COMPLETED = 'completed',
|
|
96
|
+
FAILED = 'failed',
|
|
97
|
+
CANCELLED = 'cancelled',
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Execution graph representing task dependencies
|
|
102
|
+
*/
|
|
103
|
+
export interface ExecutionGraph {
|
|
104
|
+
readonly planId: EntityId;
|
|
105
|
+
readonly nodes: Map<EntityId, ExecutionNode>;
|
|
106
|
+
readonly readyQueue: EntityId[];
|
|
107
|
+
readonly completedCount: number;
|
|
108
|
+
readonly failedCount: number;
|
|
109
|
+
readonly totalCount: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Execution engine interface
|
|
114
|
+
*/
|
|
115
|
+
export interface ExecutionEngine {
|
|
116
|
+
/**
|
|
117
|
+
* Execute a plan
|
|
118
|
+
*/
|
|
119
|
+
execute(plan: Plan, options?: ExecutionOptions): Promise<PlanExecutionResult>;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Cancel an ongoing execution
|
|
123
|
+
*/
|
|
124
|
+
cancel(executionId: EntityId): Promise<boolean>;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Get execution status
|
|
128
|
+
*/
|
|
129
|
+
getStatus(executionId: EntityId): ExecutionStatus | undefined;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Register a task executor
|
|
133
|
+
*/
|
|
134
|
+
registerExecutor(executor: TaskExecutor): void;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Subscribe to execution events
|
|
138
|
+
*/
|
|
139
|
+
on(event: ExecutionEventType, handler: ExecutionEventHandler): void;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Unsubscribe from execution events
|
|
143
|
+
*/
|
|
144
|
+
off(event: ExecutionEventType, handler: ExecutionEventHandler): void;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Execution options
|
|
149
|
+
*/
|
|
150
|
+
export interface ExecutionOptions {
|
|
151
|
+
readonly executionId?: EntityId;
|
|
152
|
+
readonly timeoutMs?: number;
|
|
153
|
+
readonly onTaskStart?: (taskId: EntityId) => void;
|
|
154
|
+
readonly onTaskComplete?: (taskId: EntityId, result: TaskResult) => void;
|
|
155
|
+
readonly onTaskError?: (taskId: EntityId, error: Error) => void;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Execution status
|
|
160
|
+
*/
|
|
161
|
+
export interface ExecutionStatus {
|
|
162
|
+
readonly executionId: EntityId;
|
|
163
|
+
readonly planId: EntityId;
|
|
164
|
+
readonly state: ExecutionState;
|
|
165
|
+
readonly progress: ExecutionProgress;
|
|
166
|
+
readonly currentTasks: EntityId[];
|
|
167
|
+
readonly startedAt: Date;
|
|
168
|
+
readonly estimatedCompletionAt?: Date;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Execution state
|
|
173
|
+
*/
|
|
174
|
+
export enum ExecutionState {
|
|
175
|
+
PENDING = 'pending',
|
|
176
|
+
RUNNING = 'running',
|
|
177
|
+
PAUSED = 'paused',
|
|
178
|
+
COMPLETED = 'completed',
|
|
179
|
+
FAILED = 'failed',
|
|
180
|
+
CANCELLED = 'cancelled',
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Execution progress
|
|
185
|
+
*/
|
|
186
|
+
export interface ExecutionProgress {
|
|
187
|
+
readonly total: number;
|
|
188
|
+
readonly completed: number;
|
|
189
|
+
readonly failed: number;
|
|
190
|
+
readonly pending: number;
|
|
191
|
+
readonly running: number;
|
|
192
|
+
readonly percentage: number;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Execution event types
|
|
197
|
+
*/
|
|
198
|
+
export type ExecutionEventType =
|
|
199
|
+
| 'execution:start'
|
|
200
|
+
| 'execution:complete'
|
|
201
|
+
| 'execution:fail'
|
|
202
|
+
| 'execution:cancel'
|
|
203
|
+
| 'task:start'
|
|
204
|
+
| 'task:complete'
|
|
205
|
+
| 'task:fail'
|
|
206
|
+
| 'task:retry';
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Execution event handler
|
|
210
|
+
*/
|
|
211
|
+
export type ExecutionEventHandler = (event: ExecutionEvent) => void;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Execution event
|
|
215
|
+
*/
|
|
216
|
+
export interface ExecutionEvent {
|
|
217
|
+
readonly type: ExecutionEventType;
|
|
218
|
+
readonly executionId: EntityId;
|
|
219
|
+
readonly timestamp: Date;
|
|
220
|
+
readonly data: unknown;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Worker pool configuration
|
|
225
|
+
*/
|
|
226
|
+
export interface WorkerPoolConfig {
|
|
227
|
+
readonly minWorkers: number;
|
|
228
|
+
readonly maxWorkers: number;
|
|
229
|
+
readonly idleTimeoutMs: number;
|
|
230
|
+
readonly taskTimeoutMs: number;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Parallel executor interface
|
|
235
|
+
*/
|
|
236
|
+
export interface ParallelExecutor {
|
|
237
|
+
/**
|
|
238
|
+
* Execute multiple independent tasks in parallel
|
|
239
|
+
*/
|
|
240
|
+
executeParallel(tasks: Task[], context: ExecutionContext): Promise<TaskResult[]>;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Get current pool status
|
|
244
|
+
*/
|
|
245
|
+
getPoolStatus(): WorkerPoolStatus;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Worker pool status
|
|
250
|
+
*/
|
|
251
|
+
export interface WorkerPoolStatus {
|
|
252
|
+
readonly totalWorkers: number;
|
|
253
|
+
readonly activeWorkers: number;
|
|
254
|
+
readonly idleWorkers: number;
|
|
255
|
+
readonly pendingTasks: number;
|
|
256
|
+
readonly completedTasks: number;
|
|
257
|
+
}
|