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,569 @@
1
+ import type {
2
+ AgentConfig,
3
+ MultiAgentWorkflow,
4
+ OrchestrationStrategy,
5
+ StrategyType,
6
+ StrategyConfig,
7
+ } from "./types";
8
+
9
+ // ─── WorkflowBuilder ─────────────────────────────────────────────────────────
10
+
11
+ /**
12
+ * Fluent builder for creating multi-agent workflows.
13
+ * Supports all strategy types including DAG (dependency-aware) execution.
14
+ */
15
+ export class WorkflowBuilder {
16
+ private workflow: MultiAgentWorkflow;
17
+
18
+ constructor(workflowId: string, goal: string) {
19
+ this.workflow = {
20
+ id: workflowId,
21
+ goal,
22
+ agents: [],
23
+ strategy: {
24
+ type: "sequential",
25
+ config: { failureMode: "fail-fast" },
26
+ },
27
+ initialPrompt: goal,
28
+ createdAt: new Date(),
29
+ updatedAt: new Date(),
30
+ };
31
+ }
32
+
33
+ // ─── Agent Additions ───────────────────────────────────────────────────────
34
+
35
+ addAgent(config: AgentConfig): this {
36
+ this.workflow.agents.push(config);
37
+ this.workflow.updatedAt = new Date();
38
+ return this;
39
+ }
40
+
41
+ addResearcher(
42
+ id: string,
43
+ name: string,
44
+ description: string,
45
+ options?: AgentOptions,
46
+ ): this {
47
+ return this.addAgent({
48
+ id,
49
+ role: "researcher",
50
+ name,
51
+ description,
52
+ model: options?.model,
53
+ systemPrompt: options?.systemPrompt,
54
+ maxSteps: options?.maxSteps ?? 30,
55
+ dependsOn: options?.dependsOn,
56
+ timeoutMs: options?.timeoutMs,
57
+ tags: options?.tags,
58
+ tools: [
59
+ "read_file",
60
+ "read_multiple_files",
61
+ "list_files",
62
+ "search_files",
63
+ "analyze_codebase",
64
+ "grep",
65
+ "web_search",
66
+ "fetch_url",
67
+ "git_status",
68
+ "git_log",
69
+ "git_diff",
70
+ "detect_framework",
71
+ "read_package_json",
72
+ "read_skill",
73
+ "list_skills",
74
+ "show_pending_changes",
75
+ ],
76
+ });
77
+ }
78
+
79
+ addImplementer(
80
+ id: string,
81
+ name: string,
82
+ description: string,
83
+ options?: AgentOptions,
84
+ ): this {
85
+ return this.addAgent({
86
+ id,
87
+ role: "implementer",
88
+ name,
89
+ description,
90
+ model: options?.model,
91
+ systemPrompt: options?.systemPrompt,
92
+ maxSteps: options?.maxSteps ?? 50,
93
+ dependsOn: options?.dependsOn,
94
+ timeoutMs: options?.timeoutMs,
95
+ tags: options?.tags,
96
+ tools: [
97
+ "read_file",
98
+ "read_multiple_files",
99
+ "list_files",
100
+ "search_files",
101
+ "analyze_codebase",
102
+ "grep",
103
+ "create_file",
104
+ "modify_file",
105
+ "replace_in_file",
106
+ "append_to_file",
107
+ "insert_at_line",
108
+ "delete_file",
109
+ "create_folder",
110
+ "run_command",
111
+ "run_tests",
112
+ "run_test_file",
113
+ "lint_project",
114
+ "format_project",
115
+ "git_status",
116
+ "git_log",
117
+ "git_diff",
118
+ "detect_framework",
119
+ "read_package_json",
120
+ "show_pending_changes",
121
+ "apply_changes",
122
+ ],
123
+ });
124
+ }
125
+
126
+ addReviewer(
127
+ id: string,
128
+ name: string,
129
+ description: string,
130
+ options?: AgentOptions,
131
+ ): this {
132
+ return this.addAgent({
133
+ id,
134
+ role: "reviewer",
135
+ name,
136
+ description,
137
+ model: options?.model,
138
+ systemPrompt: options?.systemPrompt,
139
+ maxSteps: options?.maxSteps ?? 25,
140
+ dependsOn: options?.dependsOn,
141
+ timeoutMs: options?.timeoutMs,
142
+ tags: options?.tags,
143
+ tools: [
144
+ "read_file",
145
+ "read_multiple_files",
146
+ "list_files",
147
+ "search_files",
148
+ "analyze_codebase",
149
+ "grep",
150
+ "git_status",
151
+ "git_log",
152
+ "git_diff",
153
+ "run_tests",
154
+ "run_test_file",
155
+ "lint_project",
156
+ "detect_framework",
157
+ "show_pending_changes",
158
+ ],
159
+ });
160
+ }
161
+
162
+ addCoordinator(
163
+ id: string,
164
+ name: string,
165
+ description: string,
166
+ options?: AgentOptions,
167
+ ): this {
168
+ return this.addAgent({
169
+ id,
170
+ role: "coordinator",
171
+ name,
172
+ description,
173
+ model: options?.model,
174
+ systemPrompt: options?.systemPrompt,
175
+ maxSteps: options?.maxSteps ?? 20,
176
+ dependsOn: options?.dependsOn,
177
+ timeoutMs: options?.timeoutMs,
178
+ tags: options?.tags,
179
+ tools: [
180
+ "read_file",
181
+ "list_files",
182
+ "search_files",
183
+ "analyze_codebase",
184
+ "git_status",
185
+ "detect_framework",
186
+ "create_plan",
187
+ "get_plan",
188
+ ],
189
+ });
190
+ }
191
+
192
+ addCustomAgent(
193
+ id: string,
194
+ name: string,
195
+ description: string,
196
+ tools: string[],
197
+ options?: AgentOptions,
198
+ ): this {
199
+ return this.addAgent({
200
+ id,
201
+ role: "custom",
202
+ name,
203
+ description,
204
+ model: options?.model,
205
+ systemPrompt: options?.systemPrompt,
206
+ maxSteps: options?.maxSteps ?? 30,
207
+ dependsOn: options?.dependsOn,
208
+ timeoutMs: options?.timeoutMs,
209
+ tags: options?.tags,
210
+ tools,
211
+ });
212
+ }
213
+
214
+ // ─── Strategy ──────────────────────────────────────────────────────────────
215
+
216
+ withSequentialStrategy(config?: Partial<StrategyConfig>): this {
217
+ this.workflow.strategy = {
218
+ type: "sequential",
219
+ config: { failureMode: "fail-fast", ...config },
220
+ };
221
+ return this._touch();
222
+ }
223
+
224
+ withParallelStrategy(maxConcurrent = 3, timeout = 30_000, config?: Partial<StrategyConfig>): this {
225
+ this.workflow.strategy = {
226
+ type: "parallel",
227
+ config: { maxConcurrentAgents: maxConcurrent, timeout, failureMode: "continue", ...config },
228
+ };
229
+ return this._touch();
230
+ }
231
+
232
+ withHierarchicalStrategy(config?: Partial<StrategyConfig>): this {
233
+ this.workflow.strategy = {
234
+ type: "hierarchical",
235
+ config: { failureMode: "fail-fast", ...config },
236
+ };
237
+ return this._touch();
238
+ }
239
+
240
+ withCollaborativeStrategy(timeout = 60_000, config?: Partial<StrategyConfig>): this {
241
+ this.workflow.strategy = {
242
+ type: "collaborative",
243
+ config: { timeout, failureMode: "continue", ...config },
244
+ };
245
+ return this._touch();
246
+ }
247
+
248
+ /**
249
+ * DAG strategy: agents run as soon as all their `dependsOn` are satisfied.
250
+ * You must set `dependsOn` on each AgentConfig that has prerequisites.
251
+ */
252
+ withDagStrategy(maxConcurrent = 4, timeout = 60_000, config?: Partial<StrategyConfig>): this {
253
+ this.workflow.strategy = {
254
+ type: "dag",
255
+ config: {
256
+ maxConcurrentAgents: maxConcurrent,
257
+ timeout,
258
+ failureMode: "fail-at-end",
259
+ ...config,
260
+ },
261
+ };
262
+ return this._touch();
263
+ }
264
+
265
+ withRetryOnFailure(maxRetries = 2): this {
266
+ this.workflow.strategy.config.retryOnFailure = true;
267
+ this.workflow.strategy.config.maxRetries = maxRetries;
268
+ return this._touch();
269
+ }
270
+
271
+ withFallbackAgents(agentIds: string[]): this {
272
+ this.workflow.strategy.config.fallbackAgents = agentIds;
273
+ return this._touch();
274
+ }
275
+
276
+ withFailureMode(mode: StrategyConfig["failureMode"]): this {
277
+ this.workflow.strategy.config.failureMode = mode;
278
+ return this._touch();
279
+ }
280
+
281
+ withExpectedOutput(description: string): this {
282
+ this.workflow.expectedOutput = description;
283
+ return this._touch();
284
+ }
285
+
286
+ withMeta(meta: Record<string, unknown>): this {
287
+ this.workflow.meta = { ...this.workflow.meta, ...meta };
288
+ return this._touch();
289
+ }
290
+
291
+ // ─── Build & Inspect ───────────────────────────────────────────────────────
292
+
293
+ build(): MultiAgentWorkflow {
294
+ return { ...this.workflow, agents: [...this.workflow.agents] };
295
+ }
296
+
297
+ getWorkflow(): MultiAgentWorkflow {
298
+ return this.workflow;
299
+ }
300
+
301
+ // ─── Validation ────────────────────────────────────────────────────────────
302
+
303
+ static validateWorkflow(
304
+ workflow: MultiAgentWorkflow
305
+ ): ValidationResult {
306
+
307
+ const builder = new WorkflowBuilder(
308
+ workflow.id,
309
+ workflow.goal
310
+ );
311
+
312
+ builder.getWorkflow().agents.push(
313
+ ...workflow.agents
314
+ );
315
+
316
+ return builder.validate();
317
+ }
318
+
319
+ validate(): ValidationResult {
320
+ const errors: string[] = [];
321
+ const warnings: string[] = [];
322
+
323
+ if (!this.workflow.id.trim()) errors.push("Workflow ID is required");
324
+ if (!this.workflow.goal.trim()) errors.push("Goal is required");
325
+ if (this.workflow.agents.length === 0)
326
+ errors.push("At least one agent is required");
327
+
328
+ // Duplicate IDs
329
+ const agentIds = this.workflow.agents.map((a) => a.id);
330
+ const seen = new Set<string>();
331
+ const duplicates = agentIds.filter((id) => {
332
+ if (seen.has(id)) return true;
333
+ seen.add(id);
334
+ return false;
335
+ });
336
+ if (duplicates.length > 0)
337
+ errors.push(`Duplicate agent IDs: ${duplicates.join(", ")}`);
338
+
339
+ // Per-agent checks
340
+ for (const agent of this.workflow.agents) {
341
+ if (!agent.id.trim())
342
+ errors.push("Agent ID cannot be empty");
343
+ if (!agent.name.trim())
344
+ errors.push(`Agent name cannot be empty (id: ${agent.id})`);
345
+ if (agent.maxSteps <= 0)
346
+ errors.push(`Agent ${agent.id}: maxSteps must be > 0`);
347
+ if (agent.tools.length === 0)
348
+ errors.push(`Agent ${agent.id}: must have at least one tool`);
349
+ if (agent.timeoutMs !== undefined && agent.timeoutMs <= 0)
350
+ errors.push(`Agent ${agent.id}: timeoutMs must be > 0`);
351
+
352
+ // Dependency checks
353
+ for (const dep of agent.dependsOn ?? []) {
354
+ if (!agentIds.includes(dep))
355
+ errors.push(`Agent ${agent.id}: dependency '${dep}' not found`);
356
+ if (dep === agent.id)
357
+ errors.push(`Agent ${agent.id}: cannot depend on itself`);
358
+ }
359
+ }
360
+
361
+ // DAG cycle detection
362
+ if (this.workflow.strategy.type === "dag") {
363
+ const cycle = this._detectCycle();
364
+ if (cycle) errors.push(`Dependency cycle detected: ${cycle}`);
365
+ }
366
+
367
+ // Strategy-specific checks
368
+ const validStrategies: StrategyType[] = [
369
+ "sequential", "parallel", "hierarchical", "collaborative", "dag",
370
+ ];
371
+ if (!validStrategies.includes(this.workflow.strategy.type))
372
+ errors.push(`Invalid strategy type: ${this.workflow.strategy.type}`);
373
+
374
+ if (
375
+ this.workflow.strategy.type === "hierarchical" &&
376
+ !this.workflow.agents.some((a) => a.role === "coordinator")
377
+ ) {
378
+ errors.push("Hierarchical strategy requires a coordinator agent");
379
+ }
380
+
381
+ if (
382
+ this.workflow.strategy.type === "collaborative" &&
383
+ this.workflow.agents.length > 1 &&
384
+ !this.workflow.strategy.config.timeout
385
+ ) {
386
+ warnings.push(
387
+ "Collaborative strategy with multiple agents should have a timeout configured",
388
+ );
389
+ }
390
+
391
+ // Fallback agent existence
392
+ for (const fid of this.workflow.strategy.config.fallbackAgents ?? []) {
393
+ if (!agentIds.includes(fid))
394
+ errors.push(`Fallback agent '${fid}' not found in workflow agents`);
395
+ }
396
+
397
+ // Warn if DAG strategy used but no agent has dependsOn
398
+ if (
399
+ this.workflow.strategy.type === "dag" &&
400
+ this.workflow.agents.every((a) => !a.dependsOn?.length)
401
+ ) {
402
+ warnings.push(
403
+ "DAG strategy selected but no agent has dependsOn — consider using parallel instead",
404
+ );
405
+ }
406
+
407
+ return { isValid: errors.length === 0, errors, warnings };
408
+ }
409
+
410
+ private _detectCycle(): string | null {
411
+ const graph = new Map<string, string[]>();
412
+ for (const agent of this.workflow.agents) {
413
+ graph.set(agent.id, agent.dependsOn ?? []);
414
+ }
415
+
416
+ const visited = new Set<string>();
417
+ const stack = new Set<string>();
418
+
419
+ const dfs = (id: string, path: string[]): string | null => {
420
+ if (stack.has(id)) return [...path, id].join(" → ");
421
+ if (visited.has(id)) return null;
422
+
423
+ visited.add(id);
424
+ stack.add(id);
425
+
426
+ for (const dep of graph.get(id) ?? []) {
427
+ const cycle = dfs(dep, [...path, id]);
428
+ if (cycle) return cycle;
429
+ }
430
+
431
+ stack.delete(id);
432
+ return null;
433
+ };
434
+
435
+ for (const agent of this.workflow.agents) {
436
+ const cycle = dfs(agent.id, []);
437
+ if (cycle) return cycle;
438
+ }
439
+ return null;
440
+ }
441
+
442
+ private _touch(): this {
443
+ this.workflow.updatedAt = new Date();
444
+ return this;
445
+ }
446
+ }
447
+
448
+ // ─── Supporting Types ─────────────────────────────────────────────────────────
449
+
450
+ export interface AgentOptions {
451
+ model?: string;
452
+ systemPrompt?: string;
453
+ maxSteps?: number;
454
+ dependsOn?: string[];
455
+ timeoutMs?: number;
456
+ tags?: string[];
457
+ }
458
+
459
+ export interface ValidationResult {
460
+ isValid: boolean;
461
+ errors: string[];
462
+ warnings: string[];
463
+ }
464
+
465
+ // ─── Workflow Templates ────────────────────────────────────────────────────────
466
+
467
+ export class WorkflowTemplates {
468
+ static codeReviewWorkflow(workflowId: string, goal: string): MultiAgentWorkflow {
469
+ return new WorkflowBuilder(workflowId, goal)
470
+ .addResearcher("research_agent", "Research Agent", "Analyzes the codebase and gathers requirements")
471
+ .addImplementer("impl_agent", "Implementation Agent", "Writes and modifies code", {
472
+ dependsOn: ["research_agent"],
473
+ })
474
+ .addReviewer("review_agent", "Review Agent", "Reviews code for quality and correctness", {
475
+ dependsOn: ["impl_agent"],
476
+ })
477
+ .withSequentialStrategy()
478
+ .withRetryOnFailure(1)
479
+ .build();
480
+ }
481
+
482
+ static featureDevelopmentWorkflow(workflowId: string, goal: string): MultiAgentWorkflow {
483
+ return new WorkflowBuilder(workflowId, goal)
484
+ .addCoordinator("coordinator", "Coordinator", "Plans the feature development")
485
+ .addImplementer("backend_dev", "Backend Developer", "Implements backend functionality", {
486
+ dependsOn: ["coordinator"],
487
+ })
488
+ .addImplementer("frontend_dev", "Frontend Developer", "Implements frontend functionality", {
489
+ dependsOn: ["coordinator"],
490
+ })
491
+ .addReviewer("qa_agent", "QA Agent", "Tests and validates the feature", {
492
+ dependsOn: ["backend_dev", "frontend_dev"],
493
+ })
494
+ .withDagStrategy(3, 60_000)
495
+ .build();
496
+ }
497
+
498
+ static bugFixingWorkflow(workflowId: string, goal: string): MultiAgentWorkflow {
499
+ return new WorkflowBuilder(workflowId, goal)
500
+ .addResearcher("debug_agent", "Debug Agent", "Analyzes the bug and traces its cause")
501
+ .addImplementer("fix_agent", "Fix Agent", "Implements the bug fix", {
502
+ dependsOn: ["debug_agent"],
503
+ })
504
+ .addReviewer("test_agent", "Test Agent", "Verifies the fix works correctly", {
505
+ dependsOn: ["fix_agent"],
506
+ })
507
+ .withSequentialStrategy()
508
+ .withRetryOnFailure(2)
509
+ .build();
510
+ }
511
+
512
+ static collaborativeResearchWorkflow(workflowId: string, goal: string): MultiAgentWorkflow {
513
+ return new WorkflowBuilder(workflowId, goal)
514
+ .addResearcher("researcher_1", "Researcher 1", "Primary research")
515
+ .addResearcher("researcher_2", "Researcher 2", "Secondary research")
516
+ .addResearcher("researcher_3", "Researcher 3", "Validation research")
517
+ .withParallelStrategy(3, 45_000)
518
+ .build();
519
+ }
520
+
521
+ /**
522
+ * Security audit: researcher scans, two parallel auditors review separately,
523
+ * then a coordinator synthesizes findings — true DAG execution.
524
+ */
525
+ static securityAuditWorkflow(workflowId: string, goal: string): MultiAgentWorkflow {
526
+ return new WorkflowBuilder(workflowId, goal)
527
+ .addResearcher("scanner", "Code Scanner", "Scans codebase for potential vulnerabilities")
528
+ .addReviewer("static_auditor", "Static Auditor", "Static analysis of security issues", {
529
+ dependsOn: ["scanner"],
530
+ tags: ["security"],
531
+ })
532
+ .addReviewer("dependency_auditor", "Dependency Auditor", "Audits third-party dependencies", {
533
+ dependsOn: ["scanner"],
534
+ tags: ["security"],
535
+ })
536
+ .addCoordinator("report_coordinator", "Report Coordinator", "Synthesizes audit findings into a report", {
537
+ dependsOn: ["static_auditor", "dependency_auditor"],
538
+ })
539
+ .withDagStrategy(2, 90_000)
540
+ .withExpectedOutput("Full security audit report with prioritized findings")
541
+ .build();
542
+ }
543
+
544
+ /**
545
+ * Full-stack feature with database, API, and frontend in parallel, then E2E tests.
546
+ */
547
+ static fullStackFeatureWorkflow(workflowId: string, goal: string): MultiAgentWorkflow {
548
+ return new WorkflowBuilder(workflowId, goal)
549
+ .addCoordinator("architect", "Architect", "Designs the system and creates specs", {
550
+ model: "openrouter/owl-alpha",
551
+ })
552
+ .addImplementer("db_dev", "DB Developer", "Schema design and migrations", {
553
+ dependsOn: ["architect"],
554
+ })
555
+ .addImplementer("api_dev", "API Developer", "REST/GraphQL endpoints", {
556
+ dependsOn: ["architect"],
557
+ })
558
+ .addImplementer("ui_dev", "UI Developer", "Frontend components and pages", {
559
+ dependsOn: ["architect"],
560
+ })
561
+ .addReviewer("integration_tester", "Integration Tester", "End-to-end integration tests", {
562
+ dependsOn: ["db_dev", "api_dev", "ui_dev"],
563
+ })
564
+ .withDagStrategy(3, 120_000)
565
+ .withRetryOnFailure(1)
566
+ .withExpectedOutput("Full feature implementation with passing tests")
567
+ .build();
568
+ }
569
+ }