#!/usr/bin/env bun /** * Direct pipeline runner — executes a swarm pipeline outside of the TUI. * * Usage: bun cli.ts */ import * as fs from "node:fs/promises"; import * as path from "node:path"; import { discoverAuthStorage } from "@oh-my-pi/pi-coding-agent"; import { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry"; import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings"; import { buildDependencyGraph, buildExecutionWaves, detectCycles } from "./swarm/dag"; import { PipelineController } from "./swarm/pipeline"; import { renderSwarmProgress } from "./swarm/render"; import { parseSwarmYaml, validateSwarmDefinition } from "./swarm/schema"; import { StateTracker } from "./swarm/state"; const yamlPath = process.argv[2]; if (!yamlPath) { console.error("Usage: omp-swarm "); process.exit(1); } const resolvedPath = path.resolve(yamlPath); console.log(`Reading: ${resolvedPath}`); const content = await Bun.file(resolvedPath).text(); const def = parseSwarmYaml(content); console.log(`Swarm: ${def.name}`); console.log(`Mode: ${def.mode}`); console.log(`Target count: ${def.targetCount}`); console.log(`Agents: ${[...def.agents.keys()].join(", ")}`); // Validate const errors = validateSwarmDefinition(def); if (errors.length > 0) { console.error("Validation errors:", errors); process.exit(1); } // Build DAG const deps = buildDependencyGraph(def); const cycles = detectCycles(deps); if (cycles) { console.error("Cycle detected:", cycles); process.exit(1); } const waves = buildExecutionWaves(deps); console.log(`Waves: ${waves.map((w, i) => `W${i + 1}:[${w.join(",")}]`).join(" -> ")}`); // Resolve workspace const workspace = path.isAbsolute(def.workspace) ? def.workspace : path.resolve(path.dirname(resolvedPath), def.workspace); await fs.mkdir(workspace, { recursive: true }); console.log(`Workspace: ${workspace}`); // Initialize const stateTracker = new StateTracker(workspace, def.name); await stateTracker.init([...def.agents.keys()], def.targetCount, def.mode); // Auth + settings const authStorage = await discoverAuthStorage(); const modelRegistry = new ModelRegistry(authStorage); const settings = Settings.isolated(); // Progress display let lastProgressDump = 0; const PROGRESS_INTERVAL_MS = 5000; // Run console.log("\n--- Pipeline starting ---\n"); const controller = new PipelineController(def, waves, stateTracker); const result = await controller.run({ workspace, onProgress: () => { const now = Date.now(); if (now - lastProgressDump > PROGRESS_INTERVAL_MS) { lastProgressDump = now; const lines = renderSwarmProgress(stateTracker.state); console.log(lines.join("\n")); console.log(); } }, authStorage, modelRegistry, settings, }); console.log("\n--- Pipeline finished ---\n"); console.log(`Status: ${result.status}`); console.log(`Iterations completed: ${result.iterations}/${def.targetCount}`); if (result.errors.length > 0) { console.log(`Errors (${result.errors.length}):`); for (const err of result.errors) { console.log(` - ${err}`); } } console.log(`\nState saved to: ${stateTracker.swarmDir}`); // Final state dump const lines = renderSwarmProgress(stateTracker.state); console.log(lines.join("\n"));