astrabot 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.
Files changed (47) hide show
  1. package/README.md +411 -0
  2. package/ai/ai.config.ts +27 -0
  3. package/ai/auto-retry.ts +117 -0
  4. package/ai/config-loader.ts +132 -0
  5. package/ai/index.ts +4 -0
  6. package/ai/retry-prompt.ts +30 -0
  7. package/bin/astra +2 -0
  8. package/core/retry/error-classifier.ts +208 -0
  9. package/core/retry/index.ts +29 -0
  10. package/core/retry/retry-config.ts +142 -0
  11. package/core/retry/retry-engine.ts +215 -0
  12. package/game/index.html +573 -0
  13. package/game/neon-breaker.html +1037 -0
  14. package/index.ts +140 -0
  15. package/modes/agent/action-tracker.ts +47 -0
  16. package/modes/agent/agent-tools.ts +338 -0
  17. package/modes/agent/approval.ts +184 -0
  18. package/modes/agent/diff-view.ts +34 -0
  19. package/modes/agent/orchestrator.ts +234 -0
  20. package/modes/agent/tool-executor.ts +993 -0
  21. package/modes/agent/types.ts +68 -0
  22. package/modes/ask/orchestrator.ts +230 -0
  23. package/modes/auto.ts +88 -0
  24. package/modes/cli.ts +43 -0
  25. package/modes/multi/agent-pool-manager.ts +337 -0
  26. package/modes/multi/examples.ts +441 -0
  27. package/modes/multi/message-broker.ts +179 -0
  28. package/modes/multi/multi-agent-orchestrator.ts +891 -0
  29. package/modes/multi/orchestrator.ts +414 -0
  30. package/modes/multi/types.ts +245 -0
  31. package/modes/multi/workflow-builder.ts +569 -0
  32. package/modes/plan/orchestrator.ts +198 -0
  33. package/modes/plan/planner.ts +121 -0
  34. package/modes/plan/selection.ts +43 -0
  35. package/modes/plan/types.ts +13 -0
  36. package/modes/plan/web-tools.ts +132 -0
  37. package/modes/setup.ts +210 -0
  38. package/package.json +62 -0
  39. package/session/index.ts +45 -0
  40. package/session/session-context.ts +188 -0
  41. package/session/session-manager.ts +374 -0
  42. package/session/session-tools.ts +109 -0
  43. package/session/store.ts +278 -0
  44. package/tsconfig.json +30 -0
  45. package/tui/spinner.ts +182 -0
  46. package/tui/terminal-md.ts +17 -0
  47. package/tui/wakeup.ts +231 -0
@@ -0,0 +1,414 @@
1
+ /**
2
+ * Smart Multi-Agent Mode Integration
3
+ *
4
+ * This file integrates the multi-agent orchestration system into the main
5
+ * application. It analyzes the goal text using an LLM to smartly choose
6
+ * a template or dynamically craft a custom agent topology.
7
+ */
8
+
9
+ import { text, isCancel, select, confirm, multiselect, spinner } from "@clack/prompts";
10
+ import chalk from "chalk";
11
+ import { generateText, stepCountIs } from "ai";
12
+ import { getAgentModel } from "../../ai";
13
+ import { MultiAgentOrchestrator } from "./multi-agent-orchestrator";
14
+ import { WorkflowBuilder, WorkflowTemplates } from "./workflow-builder";
15
+ import type { MultiAgentWorkflow, OrchestratorEvent } from "./types";
16
+ import { composeBeforeAfter, formatPatch } from "../agent/diff-view";
17
+ import { renderTerminalMarkdown } from "../../tui/terminal-md";
18
+ import { withSpinner } from "../../tui/spinner";
19
+ import type { ActionLog } from "../agent/types";
20
+
21
+ interface ReviewGroup {
22
+ label: string;
23
+ actionIds: string[];
24
+ patch: string | null;
25
+ }
26
+
27
+ function groupPendingByAgent(agentId: string, pending: ActionLog[]): ReviewGroup[] {
28
+ const byPath = new Map<string, ActionLog[]>();
29
+ const shells: ActionLog[] = [];
30
+
31
+ for (const a of pending) {
32
+ if (a.type === "tool_execute") {
33
+ shells.push(a);
34
+ continue;
35
+ }
36
+ const key = a.path;
37
+ if (!byPath.has(key)) byPath.set(key, []);
38
+ byPath.get(key)!.push(a);
39
+ }
40
+
41
+ const groups: ReviewGroup[] = [];
42
+ const pathEntries = [...byPath.entries()].sort(([a], [b]) => a.localeCompare(b));
43
+
44
+ for (const [p, acts] of pathEntries) {
45
+ const sorted = acts.sort((x, y) => x.timestamp.getTime() - y.timestamp.getTime());
46
+ const ids = sorted.map((x) => x.id);
47
+
48
+ if (sorted.every((x) => x.type === "folder_create")) {
49
+ groups.push({
50
+ label: `Create folder: ${p}`,
51
+ actionIds: ids,
52
+ patch: null,
53
+ });
54
+ continue;
55
+ }
56
+
57
+ const { before, after } = composeBeforeAfter(sorted);
58
+ const patch = formatPatch(p, before, after);
59
+ const kinds = [...new Set(sorted.map((x) => x.type))].join(", ");
60
+ groups.push({ label: `${p} (${kinds})`, actionIds: ids, patch });
61
+ }
62
+
63
+ for (const s of shells) {
64
+ groups.push({
65
+ label: `Shell: ${s.details.command ?? "(no command)"}`,
66
+ actionIds: [s.id],
67
+ patch: null,
68
+ });
69
+ }
70
+
71
+ return groups;
72
+ }
73
+
74
+ const TEMPLATE_CATALOG = [
75
+ { id: "code_review", name: "Code Review", template: WorkflowTemplates.codeReviewWorkflow },
76
+ { id: "feature_dev", name: "Feature Development", template: WorkflowTemplates.featureDevelopmentWorkflow },
77
+ { id: "bug_fix", name: "Bug Fixing", template: WorkflowTemplates.bugFixingWorkflow },
78
+ { id: "research", name: "Collaborative Research", template: WorkflowTemplates.collaborativeResearchWorkflow },
79
+ { id: "security_audit", name: "Security Audit", template: WorkflowTemplates.securityAuditWorkflow },
80
+ { id: "fullstack", name: "Full-Stack Feature", template: WorkflowTemplates.fullStackFeatureWorkflow },
81
+ ];
82
+
83
+ // ─── Main Entry Point ──────────────────────────────────────────────────────
84
+
85
+ export async function runMultiAgentMode(preCapturedGoal?: string): Promise<void> {
86
+ console.log(chalk.bold("\n👥 Multi-Agent Orchestration\n"));
87
+
88
+ // 1. Gather the goal text if not passed directly from Auto Mode
89
+ const finalGoal = preCapturedGoal?.trim() ?? await text({
90
+ message: "What complex operations workflow would you like to run?",
91
+ placeholder: "e.g., 'Audit auth code security and patch the leaks'...",
92
+ });
93
+
94
+ if (!finalGoal || isCancel(finalGoal) || !finalGoal.trim()) return;
95
+
96
+ let workflow: MultiAgentWorkflow | null = null;
97
+
98
+ // 2. AI Intelligence Engine: Analyze and assemble the best team
99
+ const decisionSpinner = spinner();
100
+ decisionSpinner.start("AI analyzing requirements and building optimal agent team topology...");
101
+
102
+ try {
103
+ const analysisResponse = await generateText({
104
+ model: getAgentModel(),
105
+ stopWhen: stepCountIs(1),
106
+ prompt: [
107
+ "You are an expert system architecture manager designing multi-agent software pipelines.",
108
+ "Analyze the following user task goal, and decide the absolute best workflow setup.",
109
+ "",
110
+ `User Task Goal: "${finalGoal}"`,
111
+ "",
112
+ "Available Catalog Templates:",
113
+ "- 'code_review': For reading existing code changes, analyzing style/vulnerabilities, and summarizing changes.",
114
+ "- 'feature_dev': Core workflows needing planning, engineering implementation, and QA reviews.",
115
+ "- 'bug_fix': Repair loops starting with debugging/diagnostics, code patch modifications, and testing cycles.",
116
+ "- 'research': Broad reading, framework discoveries, or documentation analysis without writing active patches.",
117
+ "- 'security_audit': Scanners running sweeps across directories feeding synthesis workflows.",
118
+ "- 'fullstack': Complex tasks requiring layered architectures (Database models, APIs, and UI controls) executing in parallel blocks.",
119
+ "",
120
+ "Your task is to respond with a clean, unformatted JSON object containing instructions on how to structure the agent swarm.",
121
+ "Format your response as a valid raw JSON matching EXACTLY one of these two configurations. Do not use markdown blocks.",
122
+ "",
123
+ "Option A: If a catalog template fits perfectly:",
124
+ '{"decisionType": "template", "templateId": "feature_dev" | "bug_fix" | "code_review" | "research" | "security_audit" | "fullstack"}',
125
+ "",
126
+ "Option B: If the task is unique and requires a customized specialized agent group configuration:",
127
+ '{',
128
+ ' "decisionType": "custom",',
129
+ ' "strategy": "sequential" | "parallel" | "hierarchical" | "collaborative",',
130
+ ' "agents": [',
131
+ ' { "name": "string", "role": "researcher"|"implementer"|"reviewer"|"coordinator", "description": "precise operational prompt instruction directive context for this agent" }',
132
+ ' ]',
133
+ '}'
134
+ ].join("\n"),
135
+ });
136
+
137
+ // Clean any accidental markdown wraps from the raw response text
138
+ let cleanJsonText = analysisResponse.text.trim();
139
+ if (cleanJsonText.startsWith("```")) {
140
+ cleanJsonText = cleanJsonText.replace(/^```json\s*/, "").replace(/```$/, "").trim();
141
+ }
142
+
143
+ const config = JSON.parse(cleanJsonText);
144
+ const timestamp = Date.now();
145
+
146
+ if (config.decisionType === "template" && config.templateId) {
147
+ const match = TEMPLATE_CATALOG.find(t => t.id === config.templateId);
148
+ if (match) {
149
+ decisionSpinner.stop(`✨ AI designated standard pipeline template: [${match.name}]`);
150
+ workflow = match.template(`wf_ai_${config.templateId}_${timestamp}`, finalGoal);
151
+ }
152
+ }
153
+
154
+ // fallback / bespoke generation block
155
+ if (!workflow && config.decisionType === "custom" && Array.isArray(config.agents)) {
156
+ decisionSpinner.stop(`🛠️ AI created bespoke customized workspace swarm [Strategy: ${config.strategy.toUpperCase()}]`);
157
+ const builder = new WorkflowBuilder(`wf_custom_ai_${timestamp}`, finalGoal);
158
+
159
+ for (const a of config.agents) {
160
+ if (a.role === "researcher") builder.addResearcher(a.name, a.name, a.description);
161
+ else if (a.role === "implementer") builder.addImplementer(a.name, a.name, a.description);
162
+ else if (a.role === "reviewer") builder.addReviewer(a.name, a.name, a.description);
163
+ else builder.addCoordinator(a.name, a.name, a.description);
164
+ }
165
+
166
+ if (config.strategy === "parallel") builder.withParallelStrategy(3, 45000);
167
+ else if (config.strategy === "hierarchical") builder.withHierarchicalStrategy();
168
+ else if (config.strategy === "collaborative") builder.withCollaborativeStrategy(60000);
169
+ else builder.withSequentialStrategy();
170
+
171
+ builder.withRetryOnFailure(1);
172
+ workflow = builder.build();
173
+ }
174
+ } catch (err) {
175
+ // Fail-safe graceful fallback if model errors or outputs invalid JSON
176
+ decisionSpinner.stop("⚠️ Model parsing bottleneck; falling back to dynamic Feature Development group");
177
+ }
178
+
179
+ // Double fallback to protect operation runtime loop
180
+ if (!workflow) {
181
+ const timestamp = Date.now();
182
+ workflow = WorkflowTemplates.featureDevelopmentWorkflow(`wf_fallback_${timestamp}`, finalGoal);
183
+ }
184
+
185
+ // 3. Complete Validation Layer
186
+ const validation = WorkflowBuilder.validateWorkflow(workflow);
187
+ if (!validation.isValid) {
188
+ console.log(chalk.red("\n❌ Generated Workflow validation failed:\n"));
189
+ for (const error of validation.errors) console.log(chalk.red(` • ${error}`));
190
+ return;
191
+ }
192
+
193
+ // 4. Summarize and Confirm Execution with User
194
+ displayWorkflowSummary(workflow);
195
+
196
+ const shouldContinue = await confirm({
197
+ message: "Execute this smart-built agent workflow?",
198
+ initialValue: true,
199
+ });
200
+ if (isCancel(shouldContinue) || !shouldContinue) {
201
+ console.log(chalk.dim("\nWorkflow cancelled.\n"));
202
+ return;
203
+ }
204
+
205
+ // 5. Standard Core Operational Orchestrator Lifecycle Loop Execution
206
+ const orchestrator = new MultiAgentOrchestrator(workflow);
207
+
208
+ const unsubscribe = orchestrator.onEvent((event: OrchestratorEvent) => {
209
+ if (event.type === "agent:start") {
210
+ orchestrationLogger.debug(`Agent ${event.agentId} running...`);
211
+ } else if (event.type === "agent:complete") {
212
+ orchestrationLogger.debug(`Agent ${event.agentId} successfully completed steps`);
213
+ }
214
+ });
215
+
216
+ await withSpinner(
217
+ {
218
+ message: "Orchestrating system agents pipeline execution...",
219
+ doneMessage: "workflow steps completed successfully",
220
+ failMessage: "workflow processing routine encountered a bottleneck",
221
+ },
222
+ () => orchestrator.execute(),
223
+ );
224
+
225
+ unsubscribe();
226
+
227
+ // 6. Print Summary Metric Sheets & Route Approval
228
+ displayExecutionResults(orchestrator);
229
+ await runMultiAgentApprovalFlow(orchestrator);
230
+ }
231
+
232
+ // ─── Native Selector Methods (Preserved for standard fallback uses) ────────
233
+
234
+ async function selectTemplateWorkflow(): Promise<MultiAgentWorkflow | null> {
235
+ const selected = await select({
236
+ message: "Select a workflow template",
237
+ options: TEMPLATE_CATALOG.map((t) => ({
238
+ value: t.id,
239
+ label: chalk.bold(t.name),
240
+ })),
241
+ });
242
+ if (isCancel(selected)) return null;
243
+ const catalog = TEMPLATE_CATALOG.find((t) => t.id === selected);
244
+ if (!catalog) return null;
245
+ const goal = await text({ message: "Describe the goal for this workflow" });
246
+ if (isCancel(goal) || !goal.trim()) return null;
247
+ return catalog.template(`workflow_${selected}_${Date.now()}`, goal.trim());
248
+ }
249
+
250
+ async function buildCustomWorkflow(): Promise<MultiAgentWorkflow | null> {
251
+ return null; // Interface is bypassed dynamically by the structural smart engine
252
+ }
253
+
254
+ async function buildAdvancedDAGWorkflow(): Promise<MultiAgentWorkflow | null> {
255
+ return null; // Interface is bypassed dynamically by the structural smart engine
256
+ }
257
+
258
+ // ─── Display & Approval ────────────────────────────────────────────────────
259
+
260
+ function displayWorkflowSummary(workflow: MultiAgentWorkflow): void {
261
+ console.log(chalk.bold("\n📋 Smart Workflow Configuration\n"));
262
+ console.log(`Goal: ${workflow.goal}`);
263
+ console.log(`Strategy: ${chalk.cyan(workflow.strategy.type)}`);
264
+ console.log(`Agents: ${workflow.agents.length}`);
265
+ console.log(
266
+ `${workflow.agents
267
+ .map(
268
+ (a) =>
269
+ ` • ${chalk.bold(a.name)} (${a.role})${a.model ? ` [${chalk.dim(a.model)}]` : ""}${
270
+ a.dependsOn?.length ? ` → depends: ${a.dependsOn.join(", ")}` : ""
271
+ }`,
272
+ )
273
+ .join("\n")}`,
274
+ );
275
+ console.log();
276
+ }
277
+
278
+ async function runMultiAgentApprovalFlow(orchestrator: MultiAgentOrchestrator): Promise<void> {
279
+ const trackers = orchestrator.getAllTrackers();
280
+ const executors = orchestrator.getAllExecutors();
281
+
282
+ let totalPending = 0;
283
+ for (const [, tracker] of trackers) {
284
+ totalPending += tracker.getPendingMutations().length;
285
+ }
286
+
287
+ if (totalPending === 0) {
288
+ console.log(chalk.dim("\nNo staged changes to review.\n"));
289
+ return;
290
+ }
291
+
292
+ console.log(chalk.bold(`\n📝 ${totalPending} staged change(s) from ${trackers.size} agent(s)\n`));
293
+
294
+ const choice = await select({
295
+ message: "Apply staged changes?",
296
+ options: [
297
+ { value: "all", label: "Approve all" },
298
+ { value: "select", label: "Review one by one" },
299
+ { value: "cancel", label: "Discard all" },
300
+ ],
301
+ });
302
+
303
+ if (isCancel(choice) || choice === "cancel") {
304
+ for (const [, tracker] of trackers) {
305
+ for (const action of tracker.getPendingMutations()) {
306
+ tracker.updateStatus(action.id, "rejected", false);
307
+ }
308
+ }
309
+ for (const [, executor] of executors) {
310
+ executor.discardChanges();
311
+ }
312
+ console.log(chalk.yellow("\nAll changes discarded.\n"));
313
+ return;
314
+ }
315
+
316
+ if (choice === "all") {
317
+ for (const [, tracker] of trackers) {
318
+ for (const action of tracker.getPendingMutations()) {
319
+ tracker.updateStatus(action.id, "approved", true);
320
+ }
321
+ }
322
+ } else if (choice === "select") {
323
+ for (const [agentId, tracker] of trackers) {
324
+ const pending = tracker.getPendingMutations();
325
+ if (pending.length === 0) continue;
326
+
327
+ console.log(chalk.bold(`\n🤖 Agent: ${agentId} (${pending.length} change(s))`));
328
+ const groups = groupPendingByAgent(agentId, pending);
329
+
330
+ for (const g of groups) {
331
+ while (true) {
332
+ const opt = await select({
333
+ message: chalk.bold(g.label),
334
+ options: [
335
+ { value: "accept", label: "Accept" },
336
+ { value: "diff", label: "Show diff", hint: g.patch ? "" : "N/A" },
337
+ { value: "reject", label: "Reject" },
338
+ ],
339
+ });
340
+
341
+ if (isCancel(opt)) {
342
+ for (const [, t] of trackers) {
343
+ for (const a of t.getPendingMutations()) t.updateStatus(a.id, "rejected", false);
344
+ }
345
+ for (const [, executor] of executors) executor.discardChanges();
346
+ console.log(chalk.yellow("\nAll changes discarded.\n"));
347
+ return;
348
+ }
349
+
350
+ if (opt === "diff") {
351
+ if (g.patch) {
352
+ console.log("\n" + renderTerminalMarkdown("```diff\n" + g.patch + "\n```\n") + "\n");
353
+ }
354
+ continue;
355
+ }
356
+
357
+ for (const id of g.actionIds) {
358
+ tracker.updateStatus(id, opt === "accept" ? "approved" : "rejected", opt === "accept");
359
+ }
360
+ break;
361
+ }
362
+ }
363
+ }
364
+ }
365
+
366
+ await withSpinner(
367
+ {
368
+ message: "Applying approved changes…",
369
+ doneMessage: "all changes applied",
370
+ failMessage: "some operations failed",
371
+ },
372
+ async () => {
373
+ const allErrors: string[] = [];
374
+ for (const [agentId, executor] of executors) {
375
+ const { errors } = executor.applyApprovedFromTracker();
376
+ allErrors.push(...errors.map((e) => `[${agentId}] ${e}`));
377
+ }
378
+ if (allErrors.length > 0) {
379
+ console.log(chalk.red("\nErrors:\n"));
380
+ for (const e of allErrors) console.log(chalk.red(` · ${e}`));
381
+ } else {
382
+ console.log(chalk.green("\n✔ All changes applied.\n"));
383
+ }
384
+ },
385
+ );
386
+ }
387
+
388
+ function displayExecutionResults(orchestrator: MultiAgentOrchestrator): void {
389
+ const summary = orchestrator.getSummary();
390
+ console.log(chalk.bold("\n📊 Execution Summary\n"));
391
+ const statusColor = summary.status === "completed" ? chalk.green : chalk.red;
392
+ console.log(`Status: ${statusColor(`● ${summary.status}`)}`);
393
+ console.log(`Strategy: ${summary.strategy}`);
394
+ console.log(`Duration: ${summary.duration ? `${summary.duration}ms` : "N/A"}`);
395
+
396
+ console.log(chalk.bold("\n🤖 Pool Stats\n"));
397
+ console.log(`Total Agents Assigned: ${summary.poolStats.totalAgents}`);
398
+ console.log(`Completed Steps: ${chalk.green(String(summary.poolStats.completedAgents))}`);
399
+ console.log(`Completion Accuracy: ${chalk.cyan(`${summary.poolStats.completionPercentage}%`)}`);
400
+ }
401
+
402
+ const orchestrationLogger = {
403
+ debug: (msg: string) => {
404
+ if (process.env.DEBUG) console.log(chalk.dim(`[DEBUG] ${msg}`));
405
+ },
406
+ };
407
+
408
+ export default {
409
+ runMultiAgentMode,
410
+ selectTemplateWorkflow,
411
+ buildCustomWorkflow,
412
+ buildAdvancedDAGWorkflow,
413
+ displayExecutionResults,
414
+ };
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Multi-Agent Orchestration Types
3
+ *
4
+ * Defines the interfaces and types for coordinating multiple agents
5
+ * working together on complex tasks.
6
+ */
7
+
8
+ // ─── Core Agent Types ────────────────────────────────────────────────────────
9
+
10
+ export type AgentRole =
11
+ | "researcher" // Gathers information and analyzes
12
+ | "implementer" // Writes code and modifies files
13
+ | "reviewer" // Reviews changes and validates
14
+ | "coordinator" // Manages workflow and delegates tasks
15
+ | "custom"; // Custom role defined by user
16
+
17
+ export type AgentStatus = "pending" | "running" | "completed" | "failed" | "skipped" | "retrying";
18
+
19
+ export interface AgentConfig {
20
+ id: string;
21
+ role: AgentRole;
22
+ name: string;
23
+ description: string;
24
+ model?: string; // Override default model (e.g. "anthropic/claude-sonnet-4.5")
25
+ maxSteps: number;
26
+ tools: string[]; // List of tool names this agent can use
27
+ systemPrompt?: string; // Custom system instructions
28
+ specializations?: string[]; // What this agent is good at
29
+ /** IDs of agents that must complete before this one starts (DAG dependency) */
30
+ dependsOn?: string[];
31
+ /** Hard timeout in ms for this specific agent (overrides strategy timeout) */
32
+ timeoutMs?: number;
33
+ /** Tags for grouping/filtering agents */
34
+ tags?: string[];
35
+ }
36
+
37
+ // ─── Messaging ───────────────────────────────────────────────────────────────
38
+
39
+ export type MessageType = "request" | "response" | "status" | "error" | "result" | "handoff";
40
+
41
+ export interface AgentMessage {
42
+ id: string;
43
+ fromAgentId: string;
44
+ toAgentId?: string; // undefined = broadcast to all
45
+ type: MessageType;
46
+ content: string;
47
+ context?: Record<string, unknown>;
48
+ timestamp: Date;
49
+ requiresResponse: boolean;
50
+ /** Message this is a reply to */
51
+ replyToId?: string;
52
+ /** Priority for ordering message delivery */
53
+ priority?: "low" | "normal" | "high";
54
+ }
55
+
56
+ // ─── Context & State ─────────────────────────────────────────────────────────
57
+
58
+ export interface AgentContext {
59
+ goal: string;
60
+ conversationHistory: AgentMessage[];
61
+ sharedState: Map<string, unknown>;
62
+ parentContext?: AgentContext;
63
+ metadata: AgentContextMetadata;
64
+ }
65
+
66
+ export interface AgentContextMetadata {
67
+ startTime: Date;
68
+ endTime?: Date;
69
+ currentStep: number;
70
+ completedTasks: string[];
71
+ failedTasks: string[];
72
+ retryCount: number;
73
+ /** Structured findings the agent surfaced for downstream agents */
74
+ findings?: Record<string, unknown>;
75
+ /** Tokens used, if tracked by the model provider */
76
+ tokensUsed?: number;
77
+ }
78
+
79
+ // ─── Execution Results ───────────────────────────────────────────────────────
80
+
81
+ export interface AgentExecutionResult {
82
+ agentId: string;
83
+ success: boolean;
84
+ output: string;
85
+ executedTools: string[];
86
+ messagesReceived: AgentMessage[];
87
+ messagesSent: AgentMessage[];
88
+ context: AgentContext;
89
+ error?: Error;
90
+ /** Wall-clock duration in ms */
91
+ durationMs: number;
92
+ /** Which attempt produced this result (1-based) */
93
+ attemptNumber: number;
94
+ }
95
+
96
+ // ─── Orchestration Strategy ──────────────────────────────────────────────────
97
+
98
+ export type StrategyType = "sequential" | "parallel" | "hierarchical" | "collaborative" | "dag";
99
+
100
+ export interface OrchestrationStrategy {
101
+ type: StrategyType;
102
+ config: StrategyConfig;
103
+ }
104
+
105
+ export interface StrategyConfig {
106
+ maxConcurrentAgents?: number;
107
+ /** Default timeout in ms applied to all agents (can be overridden per-agent) */
108
+ timeout?: number;
109
+ retryOnFailure?: boolean;
110
+ maxRetries?: number;
111
+ fallbackAgents?: string[];
112
+ /**
113
+ * "fail-fast": abort entire workflow on first agent failure (default for sequential).
114
+ * "continue": skip failed agents and continue.
115
+ * "fail-at-end": complete all agents, then surface errors.
116
+ */
117
+ failureMode?: "fail-fast" | "continue" | "fail-at-end";
118
+ }
119
+
120
+ // ─── Workflow ─────────────────────────────────────────────────────────────────
121
+
122
+ export interface MultiAgentWorkflow {
123
+ id: string;
124
+ goal: string;
125
+ agents: AgentConfig[];
126
+ strategy: OrchestrationStrategy;
127
+ initialPrompt: string;
128
+ expectedOutput?: string;
129
+ createdAt: Date;
130
+ updatedAt: Date;
131
+ /** Optional metadata bag for user-defined fields */
132
+ meta?: Record<string, unknown>;
133
+ }
134
+
135
+ // ─── Pool ────────────────────────────────────────────────────────────────────
136
+
137
+ export interface AgentPool {
138
+ agents: Map<string, AgentInstance>;
139
+ activeAgents: Set<string>;
140
+ waitingAgents: Set<string>;
141
+ failedAgents: Set<string>;
142
+ completedAgents: Set<string>;
143
+ }
144
+
145
+ export interface AgentInstance {
146
+ config: AgentConfig;
147
+ context: AgentContext;
148
+ status: AgentStatus;
149
+ /** For backward compat */
150
+ get isActive(): boolean;
151
+ lastMessageTime: Date;
152
+ messageQueue: AgentMessage[];
153
+ completionPercentage: number;
154
+ startedAt?: Date;
155
+ completedAt?: Date;
156
+ }
157
+
158
+ // ─── Orchestrator State ───────────────────────────────────────────────────────
159
+
160
+ export type OrchestratorStatus = "pending" | "running" | "paused" | "completed" | "failed";
161
+
162
+ export interface OrchestratorState {
163
+ workflowId: string;
164
+ status: OrchestratorStatus;
165
+ pool: AgentPool;
166
+ sharedContext: AgentContext;
167
+ timeline: AgentExecutionResult[];
168
+ startTime: Date;
169
+ endTime?: Date;
170
+ currentCoordinator: string;
171
+ /** Emitted events in order */
172
+ events: OrchestratorEvent[];
173
+ }
174
+
175
+ // ─── Events ───────────────────────────────────────────────────────────────────
176
+
177
+ export type OrchestratorEventType =
178
+ | "workflow:start"
179
+ | "workflow:complete"
180
+ | "workflow:failed"
181
+ | "agent:start"
182
+ | "agent:complete"
183
+ | "agent:failed"
184
+ | "agent:retry"
185
+ | "agent:timeout"
186
+ | "strategy:phase"
187
+ | "message:sent";
188
+
189
+ export interface OrchestratorEvent {
190
+ type: OrchestratorEventType;
191
+ timestamp: Date;
192
+ agentId?: string;
193
+ payload?: Record<string, unknown>;
194
+ }
195
+
196
+ export type OrchestratorEventListener = (event: OrchestratorEvent) => void;
197
+
198
+ // ─── Communication ────────────────────────────────────────────────────────────
199
+
200
+ export interface CommunicationChannel {
201
+ messageBuffer: AgentMessage[];
202
+ subscribers: Map<string, (msg: AgentMessage) => void>;
203
+ broadcast(message: Omit<AgentMessage, "id" | "timestamp">): AgentMessage;
204
+ subscribe(agentId: string, callback: (msg: AgentMessage) => void): () => void;
205
+ getMessagesFor(agentId: string): AgentMessage[];
206
+ getConversation(agentId1: string, agentId2: string): AgentMessage[];
207
+ clearBuffer(): void;
208
+ }
209
+
210
+ // ─── Summary Types ────────────────────────────────────────────────────────────
211
+
212
+ export interface AgentResultSummary {
213
+ agentId: string;
214
+ success: boolean;
215
+ role: AgentRole | undefined;
216
+ steps: number;
217
+ durationMs: number;
218
+ toolsUsed: string[];
219
+ attemptNumber: number;
220
+ output?: string;
221
+ }
222
+
223
+ export interface PoolStats {
224
+ totalAgents: number;
225
+ activeAgents: number;
226
+ waitingAgents: number;
227
+ failedAgents: number;
228
+ completedAgents: number;
229
+ completionPercentage: number;
230
+ }
231
+
232
+ export interface OrchestratorSummary {
233
+ workflowId: string;
234
+ status: OrchestratorStatus;
235
+ goal: string;
236
+ strategy: StrategyType;
237
+ startTime: Date;
238
+ endTime?: Date;
239
+ duration: number | null;
240
+ totalAgents: number;
241
+ completedTasks: number;
242
+ failedTasks: number;
243
+ poolStats: PoolStats;
244
+ executionResults: AgentResultSummary[];
245
+ }