import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { v4 as uuidv4 } from "uuid";
import { logger } from "../../../core/monitoring/logger.js";
import { FrameManager } from "../../../core/context/frame-manager.js";
import { sessionManager } from "../../../core/session/index.js";
import { RalphStackMemoryBridge } from "../bridge/ralph-stackmemory-bridge.js";
class MultiLoopOrchestrator {
  frameManager;
  activeTasks = /* @__PURE__ */ new Map();
  activeLoops = /* @__PURE__ */ new Map();
  config;
  constructor(config) {
    this.config = {
      maxConcurrentLoops: 3,
      dependencyResolutionTimeout: 3e4,
      // 30 seconds
      enableAdaptivePlanning: true,
      sharedContextEnabled: true,
      fallbackStrategy: "sequential",
      ...config
    };
    logger.info("Multi-loop orchestrator initialized", this.config);
  }
  async initialize() {
    try {
      await sessionManager.initialize();
      const session = await sessionManager.getOrCreateSession({});
      if (session.database) {
        this.frameManager = new FrameManager(session.database, session.projectId);
      }
      logger.info("Orchestrator initialized successfully");
    } catch (error) {
      logger.error("Failed to initialize orchestrator", error);
      throw error;
    }
  }
  /**
   * Break down complex task into manageable loops
   */
  async orchestrateComplexTask(description, criteria, options) {
    logger.info("Orchestrating complex task", {
      task: description.substring(0, 100),
      criteriaCount: criteria.length,
      maxLoops: options?.maxLoops || this.config.maxConcurrentLoops
    });
    const orchestrationId = uuidv4();
    try {
      const breakdown = options?.customBreakdown || await this.analyzeAndBreakdownTask(description, criteria);
      const executionPlan = await this.createExecutionPlan(breakdown, options);
      const dependencyErrors = this.validateDependencies(executionPlan);
      if (dependencyErrors.length > 0) {
        throw new Error(`Dependency errors: ${dependencyErrors.join(", ")}`);
      }
      const orchestratedTask = {
        id: orchestrationId,
        description,
        breakdown,
        executionPlan,
        status: "planning",
        startTime: Date.now(),
        loops: /* @__PURE__ */ new Map(),
        sharedContext: {}
      };
      this.activeTasks.set(orchestrationId, orchestratedTask);
      const result = await this.executeOrchestration(orchestratedTask);
      logger.info("Complex task orchestration completed", {
        orchestrationId,
        status: result.success ? "success" : "failure",
        loopsExecuted: result.completedLoops.length,
        duration: Date.now() - orchestratedTask.startTime
      });
      return result;
    } catch (error) {
      logger.error("Orchestration failed", error);
      throw error;
    } finally {
      this.activeTasks.delete(orchestrationId);
    }
  }
  /**
   * Execute coordinated parallel loops
   */
  async executeParallelLoops(tasks, coordination) {
    logger.info(`Executing ${tasks.length} parallel loops`);
    const execution = {
      id: uuidv4(),
      tasks,
      startTime: Date.now(),
      results: /* @__PURE__ */ new Map(),
      sharedState: coordination?.sharedState || {}
    };
    const promises = tasks.map((task) => this.executeParallelTask(task, execution));
    try {
      await Promise.allSettled(promises);
      execution.endTime = Date.now();
      execution.status = Array.from(execution.results.values()).every((r) => r.success) ? "success" : "partial";
      return execution;
    } catch (error) {
      logger.error("Parallel execution failed", error);
      execution.status = "failed";
      execution.error = error.message;
      return execution;
    }
  }
  /**
   * Analyze and break down complex task
   */
  async analyzeAndBreakdownTask(description, criteria) {
    const complexity = this.assessTaskComplexity(description);
    if (complexity.score < 5) {
      return [{
        id: uuidv4(),
        title: description,
        description,
        criteria,
        priority: 1,
        estimatedIterations: 3,
        dependencies: [],
        type: "single"
      }];
    }
    const subtasks = [];
    if (this.needsSetup(description)) {
      subtasks.push({
        id: uuidv4(),
        title: "Project Setup",
        description: "Set up project structure and dependencies",
        criteria: ["Project structure created", "Dependencies installed"],
        priority: 1,
        estimatedIterations: 2,
        dependencies: [],
        type: "setup"
      });
    }
    const coreTask = this.extractCoreTask(description);
    if (coreTask) {
      subtasks.push({
        id: uuidv4(),
        title: "Core Implementation",
        description: coreTask,
        criteria: criteria.filter((c) => c.toLowerCase().includes("function") || c.toLowerCase().includes("implement")),
        priority: 2,
        estimatedIterations: 5,
        dependencies: subtasks.length > 0 ? [subtasks[0].id] : [],
        type: "implementation"
      });
    }
    if (this.needsTesting(criteria)) {
      subtasks.push({
        id: uuidv4(),
        title: "Testing Implementation",
        description: "Create comprehensive tests",
        criteria: criteria.filter((c) => c.toLowerCase().includes("test")),
        priority: 3,
        estimatedIterations: 3,
        dependencies: subtasks.length > 0 ? [subtasks[subtasks.length - 1].id] : [],
        type: "testing"
      });
    }
    if (this.needsDocumentation(criteria)) {
      subtasks.push({
        id: uuidv4(),
        title: "Documentation",
        description: "Create documentation and examples",
        criteria: criteria.filter((c) => c.toLowerCase().includes("doc")),
        priority: 4,
        estimatedIterations: 2,
        dependencies: [],
        type: "documentation"
      });
    }
    return subtasks.length > 0 ? subtasks : [{
      id: uuidv4(),
      title: description,
      description,
      criteria,
      priority: 1,
      estimatedIterations: Math.min(8, Math.max(3, complexity.score)),
      dependencies: [],
      type: "single"
    }];
  }
  /**
   * Create execution plan from breakdown
   */
  async createExecutionPlan(breakdown, options) {
    const plan = {
      phases: [],
      totalEstimatedTime: 0,
      parallelizable: !options?.forceSequential && breakdown.length > 1
    };
    if (options?.forceSequential || !this.canExecuteInParallel(breakdown)) {
      plan.phases = breakdown.map((task, index) => ({
        id: `phase-${index + 1}`,
        tasks: [task],
        dependencies: index > 0 ? [`phase-${index}`] : [],
        parallelExecution: false
      }));
    } else {
      const phases = this.groupTasksByDependencies(breakdown);
      plan.phases = phases;
    }
    plan.totalEstimatedTime = plan.phases.reduce(
      (sum, phase) => sum + Math.max(...phase.tasks.map((t) => t.estimatedIterations)) * 3e4,
      // 30s per iteration
      0
    );
    return plan;
  }
  /**
   * Execute the orchestration plan
   */
  async executeOrchestration(task) {
    const result = {
      orchestrationId: task.id,
      success: false,
      completedLoops: [],
      failedLoops: [],
      totalDuration: 0,
      insights: []
    };
    try {
      task.status = "executing";
      for (const phase of task.executionPlan.phases) {
        logger.info(`Executing phase ${phase.id} with ${phase.tasks.length} tasks`);
        if (phase.parallelExecution && phase.tasks.length > 1) {
          const parallelResult = await this.executeParallelLoops(phase.tasks);
          for (const [taskId, taskResult] of parallelResult.results) {
            if (taskResult.success) {
              result.completedLoops.push(taskResult.loopId);
            } else {
              result.failedLoops.push({ loopId: taskResult.loopId, error: taskResult.error || "Unknown error" });
            }
          }
        } else {
          for (const phaseTask of phase.tasks) {
            const loopResult = await this.executeTaskLoop(phaseTask, task);
            if (loopResult.success) {
              result.completedLoops.push(loopResult.loopId);
              if (this.config.sharedContextEnabled) {
                await this.updateSharedContext(task, loopResult);
              }
            } else {
              result.failedLoops.push({ loopId: loopResult.loopId, error: loopResult.error || "Unknown error" });
              if (this.config.fallbackStrategy === "abort") {
                throw new Error(`Task failed: ${loopResult.error}`);
              }
            }
          }
        }
      }
      task.status = "completed";
      result.success = result.failedLoops.length === 0;
      result.totalDuration = Date.now() - task.startTime;
      result.insights = this.generateOrchestrationInsights(task, result);
      return result;
    } catch (error) {
      task.status = "failed";
      result.success = false;
      result.error = error.message;
      return result;
    }
  }
  /**
   * Execute a single task as a Ralph loop
   */
  async executeTaskLoop(taskBreakdown, orchestratedTask) {
    try {
      const bridge = new RalphStackMemoryBridge({
        baseDir: `.ralph-${taskBreakdown.id}`,
        maxIterations: taskBreakdown.estimatedIterations * 2,
        // Allow extra iterations
        useStackMemory: true
      });
      await bridge.initialize({
        task: taskBreakdown.description,
        criteria: taskBreakdown.criteria.join("\n")
      });
      this.activeLoops.set(taskBreakdown.id, bridge);
      orchestratedTask.loops.set(taskBreakdown.id, {
        bridge,
        status: "running",
        startTime: Date.now()
      });
      await bridge.run();
      const loopInfo = orchestratedTask.loops.get(taskBreakdown.id);
      if (loopInfo) {
        loopInfo.status = "completed";
        loopInfo.endTime = Date.now();
      }
      this.activeLoops.delete(taskBreakdown.id);
      return { success: true, loopId: taskBreakdown.id };
    } catch (error) {
      logger.error(`Task loop failed: ${taskBreakdown.title}`, error);
      const loopInfo = orchestratedTask.loops.get(taskBreakdown.id);
      if (loopInfo) {
        loopInfo.status = "failed";
        loopInfo.error = error.message;
        loopInfo.endTime = Date.now();
      }
      this.activeLoops.delete(taskBreakdown.id);
      return { success: false, loopId: taskBreakdown.id, error: error.message };
    }
  }
  /**
   * Execute a task in parallel context
   */
  async executeParallelTask(task, execution) {
    try {
      const result = await this.executeTaskLoop(task, {
        id: execution.id,
        description: `Parallel task: ${task.title}`,
        breakdown: [task],
        executionPlan: { phases: [], totalEstimatedTime: 0, parallelizable: false },
        status: "executing",
        startTime: execution.startTime,
        loops: /* @__PURE__ */ new Map(),
        sharedContext: execution.sharedState
      });
      execution.results.set(task.id, result);
    } catch (error) {
      execution.results.set(task.id, {
        success: false,
        loopId: task.id,
        error: error.message
      });
    }
  }
  /**
   * Update shared context between tasks
   */
  async updateSharedContext(orchestratedTask, loopResult) {
    logger.debug("Updating shared context", { orchestrationId: orchestratedTask.id, loopId: loopResult.loopId });
  }
  /**
   * Generate insights from orchestration
   */
  generateOrchestrationInsights(task, result) {
    const insights = [];
    const avgLoopDuration = Array.from(task.loops.values()).filter((l) => l.endTime && l.startTime).map((l) => l.endTime - l.startTime).reduce((sum, duration) => sum + duration, 0) / task.loops.size;
    if (avgLoopDuration > 0) {
      insights.push(`Average loop duration: ${Math.round(avgLoopDuration / 1e3)}s`);
    }
    const successRate = result.completedLoops.length / (result.completedLoops.length + result.failedLoops.length);
    insights.push(`Success rate: ${Math.round(successRate * 100)}%`);
    if (task.breakdown.length > 3) {
      insights.push("Complex task benefited from breakdown into multiple loops");
    }
    return insights;
  }
  // Helper methods for task analysis
  assessTaskComplexity(description) {
    const factors = [];
    let score = 1;
    if (description.length > 200) {
      score += 2;
      factors.push("long description");
    }
    if (description.includes("and")) {
      score += 1;
      factors.push("multiple requirements");
    }
    if (description.toLowerCase().includes("test")) {
      score += 2;
      factors.push("testing required");
    }
    if (description.toLowerCase().includes("document")) {
      score += 1;
      factors.push("documentation needed");
    }
    if (description.toLowerCase().includes("refactor")) {
      score += 3;
      factors.push("refactoring complexity");
    }
    return { score, factors };
  }
  needsSetup(description) {
    const setupKeywords = ["project", "initialize", "setup", "scaffold", "create structure"];
    return setupKeywords.some((keyword) => description.toLowerCase().includes(keyword));
  }
  needsTesting(criteria) {
    return criteria.some((c) => c.toLowerCase().includes("test"));
  }
  needsDocumentation(criteria) {
    return criteria.some((c) => c.toLowerCase().includes("doc"));
  }
  extractCoreTask(description) {
    const sentences = description.split(".");
    return sentences.find((s) => s.toLowerCase().includes("implement") || s.toLowerCase().includes("create") || s.toLowerCase().includes("add")) || null;
  }
  canExecuteInParallel(breakdown) {
    return breakdown.some((task) => task.dependencies.length === 0);
  }
  groupTasksByDependencies(breakdown) {
    const phases = [];
    const processed = /* @__PURE__ */ new Set();
    while (processed.size < breakdown.length) {
      const readyTasks = breakdown.filter(
        (task) => !processed.has(task.id) && task.dependencies.every((dep) => processed.has(dep))
      );
      if (readyTasks.length === 0) break;
      phases.push({
        id: `phase-${phases.length + 1}`,
        tasks: readyTasks,
        dependencies: phases.length > 0 ? [`phase-${phases.length}`] : [],
        parallelExecution: readyTasks.length > 1
      });
      readyTasks.forEach((task) => processed.add(task.id));
    }
    return phases;
  }
  validateDependencies(plan) {
    const errors = [];
    const allTaskIds = new Set(
      plan.phases.flatMap((phase) => phase.tasks.map((task) => task.id))
    );
    for (const phase of plan.phases) {
      for (const task of phase.tasks) {
        for (const dep of task.dependencies) {
          if (!allTaskIds.has(dep)) {
            errors.push(`Task ${task.id} depends on non-existent task ${dep}`);
          }
        }
      }
    }
    return errors;
  }
  /**
   * Monitor orchestration progress
   */
  getOrchestrationStatus(orchestrationId) {
    return this.activeTasks.get(orchestrationId) || null;
  }
  /**
   * Stop orchestration
   */
  async stopOrchestration(orchestrationId) {
    const task = this.activeTasks.get(orchestrationId);
    if (!task) return;
    for (const [loopId, loopInfo] of task.loops) {
      if (loopInfo.status === "running") {
        try {
          loopInfo.status = "stopped";
          this.activeLoops.delete(loopId);
        } catch (error) {
          logger.error(`Failed to stop loop ${loopId}`, error);
        }
      }
    }
    task.status = "stopped";
    this.activeTasks.delete(orchestrationId);
    logger.info("Orchestration stopped", { orchestrationId });
  }
}
const multiLoopOrchestrator = new MultiLoopOrchestrator();
export {
  MultiLoopOrchestrator,
  multiLoopOrchestrator
};
//# sourceMappingURL=multi-loop-orchestrator.js.map
