#!/usr/bin/env node
import {
  ToolRegistry,
  googleSearchContext,
  truncateOutput
} from "./chunk-7WFMYFHC.js";
import "./chunk-HDSKW7Q3.js";
import "./chunk-ZWVIDFGY.js";
import "./chunk-H7TXZO6D.js";
import {
  runTool
} from "./chunk-WY2DDJTH.js";
import {
  getDangerLevel
} from "./chunk-HIU2SH4V.js";
import "./chunk-TZQHYZKT.js";
import {
  SUBAGENT_ALLOWED_TOOLS
} from "./chunk-KRU4DFRH.js";
import "./chunk-4BKXL7SM.js";
import "./chunk-MM3F43H6.js";
import "./chunk-KHYD3WXE.js";
import "./chunk-SLSWPBK3.js";
import "./chunk-VNNYHW6N.js";
import "./chunk-OVWE4E46.js";
import "./chunk-PDX44BCA.js";

// src/hub/task-orchestrator.ts
import { createInterface } from "readline";
import { existsSync, readFileSync, writeFileSync, unlinkSync, renameSync } from "fs";
import { join } from "path";
import chalk from "chalk";

// src/hub/task-executor.ts
var TASK_EXCLUDED_TOOLS = /* @__PURE__ */ new Set(["write_todos", "save_memory", "ask_user", "spawn_agent"]);
var _cachedRegistry = null;
var _cachedToolDefs = null;
function getTaskToolRegistry() {
  if (_cachedRegistry && _cachedToolDefs) {
    return { registry: _cachedRegistry, toolDefs: _cachedToolDefs };
  }
  const registry = new ToolRegistry();
  for (const tool of registry.listAll()) {
    if (!SUBAGENT_ALLOWED_TOOLS.has(tool.definition.name) || TASK_EXCLUDED_TOOLS.has(tool.definition.name)) {
      registry.unregister(tool.definition.name);
    }
  }
  _cachedRegistry = registry;
  _cachedToolDefs = registry.getDefinitions();
  return { registry, toolDefs: _cachedToolDefs };
}
async function executeTask(options) {
  const {
    task,
    role,
    provider,
    model,
    maxRounds,
    context,
    configManager,
    onToolCall,
    onToolResult,
    onRound
  } = options;
  const { registry, toolDefs } = getTaskToolRegistry();
  const contextSection = context ? `

## Reference Documents
${context}` : "";
  const systemPrompt = `# Task Execution \u2014 Role: ${role.name}

${role.persona}

## Your Task
${task}

## Working Directory
You MUST work in the current directory (${process.cwd()}). Do NOT create sub-directories like "my-project" or "todo-app". Place all files directly in the current directory or in logical sub-folders (e.g. public/, src/, db/).

## Rules
1. Focus exclusively on completing the task described above.
2. Use tools to read, create, and modify files as needed.
3. Be efficient \u2014 minimize unnecessary tool calls. Do NOT use write_todos.
4. Destructive operations (rm -rf, etc.) will be automatically blocked.
5. You cannot interact with users \u2014 work independently based on the task description.
6. Use the same language as the task description.
7. If files from a previous task already exist, build on them \u2014 do NOT recreate from scratch.

## CRITICAL \u2014 When to Stop
Once you have completed the task (files created/modified, code written, tests passing), you MUST immediately respond with a plain text summary. Do NOT call any more tools after the work is done. Your text summary should include:
- What was accomplished
- Files created or modified
- Current state / any issues
If you keep calling tools after the task is done, you are wasting rounds. STOP and write your summary.${contextSection}`;
  const messages = [
    { role: "user", content: `Please execute the following task:

${task}`, timestamp: /* @__PURE__ */ new Date() }
  ];
  const extraMessages = [];
  const totalUsage = { inputTokens: 0, outputTokens: 0 };
  let finalContent = "";
  let roundsUsed = 0;
  const executor = new TaskToolExecutor(registry, onToolCall, onToolResult);
  let toolCallCount = 0;
  try {
    for (let round = 0; round < maxRounds; round++) {
      roundsUsed = round + 1;
      executor.setRoundInfo(round + 1, maxRounds);
      onRound?.(round + 1, maxRounds);
      if (configManager) {
        googleSearchContext.configManager = configManager;
      }
      let activeSystemPrompt = systemPrompt;
      const remaining = maxRounds - round;
      if (remaining <= 3 && remaining > 1) {
        activeSystemPrompt += `

\u26A0\uFE0F You have ${remaining} rounds remaining. Finish your current work NOW and respond with a text summary on the next turn. Do NOT start new sub-tasks.`;
      } else if (remaining === 1) {
        activeSystemPrompt += "\n\n\u{1F6D1} LAST ROUND. Do NOT call any more tools. You MUST respond with a text summary of what you accomplished. List files created/modified and the current state.";
      }
      const result = await provider.chatWithTools(
        {
          messages,
          model,
          systemPrompt: activeSystemPrompt,
          stream: false,
          temperature: 0.3,
          maxTokens: 8192,
          ...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
        },
        // On the very last round, send empty tools to force text response
        round === maxRounds - 1 ? [] : toolDefs
      );
      if (result.usage) {
        totalUsage.inputTokens += result.usage.inputTokens;
        totalUsage.outputTokens += result.usage.outputTokens;
      }
      if ("content" in result) {
        finalContent = result.content;
        break;
      }
      toolCallCount += result.toolCalls.length;
      const toolResults = await executor.executeAll(result.toolCalls);
      const reasoningContent = "reasoningContent" in result ? result.reasoningContent : void 0;
      const newMsgs = provider.buildToolResultMessages(result.toolCalls, toolResults, reasoningContent);
      extraMessages.push(...newMsgs);
    }
    if (!finalContent) {
      if (toolCallCount > 0) {
        finalContent = `(Task completed work using ${toolCallCount} tool calls across ${maxRounds} rounds, but did not produce a final summary)`;
      } else {
        finalContent = `(Task agent reached maximum rounds (${maxRounds}) without producing output)`;
      }
    }
  } catch (err) {
    const errMsg = err instanceof Error ? err.message : String(err);
    finalContent = `(Task execution error: ${errMsg})`;
  }
  return {
    content: finalContent,
    // Success if: got a real response, OR did useful tool work (soft success)
    success: !finalContent.startsWith("(Task") || toolCallCount > 0,
    roundsUsed,
    usage: totalUsage
  };
}
var TaskToolExecutor = class {
  constructor(registry, onToolCall, onToolResult) {
    this.registry = registry;
    this.onToolCall = onToolCall;
    this.onToolResult = onToolResult;
  }
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  setRoundInfo(_current, _total) {
  }
  async execute(call) {
    const tool = this.registry.get(call.name);
    if (!tool) {
      return { callId: call.id, content: `Unknown tool: ${call.name}`, isError: true };
    }
    const dangerLevel = getDangerLevel(call.name, call.arguments);
    if (dangerLevel === "destructive") {
      this.onToolResult?.(call.name, "BLOCKED: destructive operation", true);
      return {
        callId: call.id,
        content: "Destructive operations are not allowed in task mode.",
        isError: true
      };
    }
    this.onToolCall?.(call, dangerLevel);
    try {
      const rawContent = await runTool(tool, call.arguments, call.name);
      const content = truncateOutput(rawContent, call.name);
      this.onToolResult?.(call.name, rawContent, false);
      return { callId: call.id, content, isError: false };
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err);
      this.onToolResult?.(call.name, message, true);
      return { callId: call.id, content: message, isError: true };
    }
  }
  async executeAll(calls) {
    const results = [];
    for (const call of calls) {
      results.push(await this.execute(call));
    }
    return results;
  }
};

// src/hub/task-orchestrator.ts
var TASK_STATE_FILE = ".aicli-task.json";
var TaskOrchestrator = class {
  constructor(config, providers, configManager) {
    this.config = config;
    this.providers = providers;
    this.configManager = configManager;
  }
  aborted = false;
  abort() {
    this.aborted = true;
  }
  /**
   * Run the full task mode workflow, with resume support.
   */
  async run(goal) {
    const provider = this.providers.get(this.config.defaultProvider);
    if (!provider) {
      console.error(chalk.red(`  \u2717 Provider "${this.config.defaultProvider}" not available.`));
      return;
    }
    const saved = this.loadState();
    let plan = null;
    if (saved && saved.tasks.some((t) => t.status === "pending" || t.status === "failed")) {
      const doneCount = saved.tasks.filter((t) => t.status === "done").length;
      const totalCount = saved.tasks.length;
      console.log();
      console.log(chalk.bold.yellow(`  \u26A1 Found saved task plan (${doneCount}/${totalCount} completed)`));
      console.log(chalk.dim(`    Goal: ${saved.goal}`));
      console.log();
      const resume = await this.askResume();
      if (resume) {
        plan = saved;
        for (const t of plan.tasks) {
          if (t.status === "failed") t.status = "pending";
        }
        this.renderPlan(plan);
      }
    }
    if (!plan) {
      this.renderPhaseHeader("PLAN", "Architect is decomposing the goal into tasks...");
      plan = await this.generatePlan(goal, provider);
      if (!plan || plan.tasks.length === 0) {
        console.log(chalk.red("  \u2717 Failed to generate a task plan."));
        return;
      }
      this.renderPlan(plan);
      this.renderPhaseHeader("APPROVE", "Review the task plan");
      const approved = await this.waitForApproval(plan);
      if (!approved) {
        console.log(chalk.yellow("  \u26A0 Task plan rejected. Exiting."));
        return;
      }
    }
    this.renderPhaseHeader("EXECUTE", "Agents are executing tasks...");
    await this.executePlan(plan, provider);
    this.renderPhaseHeader("REVIEW", "Generating project summary...");
    await this.generateReview(plan, provider);
    const allDone = plan.tasks.every((t) => t.status === "done");
    if (allDone) {
      this.deleteState();
    }
  }
  // ── State Persistence ────────────────────────────────────────────
  get stateFilePath() {
    return join(process.cwd(), TASK_STATE_FILE);
  }
  saveState(plan) {
    try {
      const tmpPath = this.stateFilePath + ".tmp";
      writeFileSync(tmpPath, JSON.stringify(plan, null, 2), "utf-8");
      renameSync(tmpPath, this.stateFilePath);
    } catch {
    }
  }
  loadState() {
    try {
      if (!existsSync(this.stateFilePath)) return null;
      const raw = readFileSync(this.stateFilePath, "utf-8");
      const parsed = JSON.parse(raw);
      if (!parsed.goal || !Array.isArray(parsed.tasks)) return null;
      return parsed;
    } catch {
      return null;
    }
  }
  deleteState() {
    try {
      if (existsSync(this.stateFilePath)) unlinkSync(this.stateFilePath);
    } catch {
    }
  }
  async askResume() {
    const rl = createInterface({ input: process.stdin, output: process.stdout });
    try {
      const answer = await Promise.race([
        new Promise((resolve) => {
          rl.question(chalk.green("  Resume from saved state? (y/n) > "), resolve);
        }),
        new Promise(
          (_, reject) => setTimeout(() => reject(new Error("timeout")), 3e4)
        )
      ]).catch(() => "y");
      return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
    } finally {
      rl.close();
    }
  }
  // ── Phase 1: Plan Generation ──────────────────────────────────────
  async generatePlan(goal, provider) {
    const roles = this.config.roles;
    const roleList = roles.map((r) => `- ${r.id} (${r.name}): ${(r.persona ?? "").slice(0, 100)}...`).join("\n");
    const contextSection = this.config.context ? `

## Reference Documents
${this.config.context}` : "";
    const systemPrompt = `You are a senior project planner. Your job is to decompose a high-level goal into concrete, executable tasks and assign each to the most appropriate team member.

## Available Team Members
${roleList}

## Rules
1. Break the goal into 8-25 concrete, SMALL tasks. Each task should create or modify 1-3 files at most.
2. Each task must be completable in ~10 tool calls (read file, write file, run bash). If a task seems too big, split it further.
3. BAD example: "Build the entire frontend" \u2014 too big! GOOD example: "Create index.html with todo list layout and CSS styling"
4. Assign each task to the most appropriate role based on their expertise.
5. Specify dependencies (which tasks must complete before this one can start). Keep dependency chains short \u2014 prefer parallel tasks.
6. Order tasks logically \u2014 foundational work (init project, install deps) first, then backend, then frontend, then integration/testing.
7. The LAST task should always be: start/run the application and verify it works.
8. Use the same language as the goal.${contextSection}

## Output Format
You MUST output ONLY a JSON array (no markdown fences, no explanation before/after). Each element:
{"id": 1, "description": "task description", "assignee": "role_id", "dependencies": []}

Example:
[
  {"id": 1, "description": "Initialize project with package.json and TypeScript config", "assignee": "backend", "dependencies": []},
  {"id": 2, "description": "Design database schema for users and courses", "assignee": "dba", "dependencies": []},
  {"id": 3, "description": "Implement user authentication API", "assignee": "backend", "dependencies": [1, 2]}
]`;
    const messages = [
      { role: "user", content: `Goal: ${goal}`, timestamp: /* @__PURE__ */ new Date() }
    ];
    try {
      const response = await provider.chat({
        messages,
        model: this.config.defaultModel,
        systemPrompt,
        stream: false,
        temperature: 0.3,
        maxTokens: 8192
      });
      let jsonStr = response.content.trim();
      const fenceMatch = jsonStr.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
      if (fenceMatch) {
        jsonStr = fenceMatch[1].trim();
      }
      const parsed = JSON.parse(jsonStr);
      if (!Array.isArray(parsed) || parsed.length === 0) {
        throw new Error("Empty task list");
      }
      for (let i = 0; i < parsed.length; i++) {
        const t = parsed[i];
        if (typeof t !== "object" || t === null) {
          throw new Error(`Task #${i + 1}: not an object`);
        }
        if (typeof t.description !== "string" || !t.description.trim()) {
          throw new Error(`Task #${i + 1}: missing or empty "description"`);
        }
        if (typeof t.assignee !== "string" || !t.assignee.trim()) {
          throw new Error(`Task #${i + 1}: missing or empty "assignee"`);
        }
        if (t.dependencies != null && !Array.isArray(t.dependencies)) {
          throw new Error(`Task #${i + 1}: "dependencies" must be an array`);
        }
      }
      const roleMap = new Map(roles.map((r) => [r.id, r.name]));
      const tasks = parsed.map((t, i) => ({
        id: typeof t.id === "number" ? t.id : i + 1,
        description: t.description,
        assignee: t.assignee,
        assigneeName: roleMap.get(t.assignee) ?? t.assignee,
        dependencies: Array.isArray(t.dependencies) ? t.dependencies : [],
        status: "pending"
      }));
      return { goal, tasks };
    } catch (err) {
      console.error(chalk.red(`  \u2717 Plan generation failed: ${err.message}`));
      return null;
    }
  }
  // ── Phase 2: Human Approval ───────────────────────────────────────
  async waitForApproval(plan) {
    console.log();
    console.log(chalk.bold("  Approve this plan?"));
    console.log(chalk.dim("    y = approve and start execution"));
    console.log(chalk.dim("    n = reject and exit"));
    console.log(chalk.dim('    e = edit (remove tasks by number, e.g. "e 3,5,7")'));
    console.log();
    const rl = createInterface({ input: process.stdin, output: process.stdout });
    try {
      while (true) {
        const answer = await new Promise((resolve) => {
          rl.question(chalk.green("  > "), resolve);
        });
        const trimmed = answer.trim().toLowerCase();
        if (trimmed === "y" || trimmed === "yes") {
          return true;
        }
        if (trimmed === "n" || trimmed === "no") {
          return false;
        }
        if (trimmed.startsWith("e ") || trimmed.startsWith("e,")) {
          const idsStr = trimmed.slice(1).trim().replace(/^,/, "");
          const ids = idsStr.split(/[,\s]+/).map(Number).filter((n) => !isNaN(n));
          const removeSet = new Set(ids);
          plan.tasks = plan.tasks.filter((t) => !removeSet.has(t.id));
          for (const t of plan.tasks) {
            t.dependencies = t.dependencies.filter((d) => !removeSet.has(d));
          }
          console.log(chalk.dim(`  Removed tasks: ${ids.join(", ")}`));
          console.log();
          this.renderPlan(plan);
          console.log(chalk.dim("  y = approve / n = reject / e <ids> = edit more"));
          continue;
        }
        console.log(chalk.dim("  Please enter y, n, or e <task_ids>"));
      }
    } finally {
      rl.close();
    }
  }
  // ── Phase 3: Task Execution ───────────────────────────────────────
  async executePlan(plan, provider) {
    const maxRoundsPerTask = this.config.maxToolRoundsPerTurn ?? 30;
    const roleMap = new Map(this.config.roles.map((r) => [r.id, r]));
    const completedIds = new Set(
      plan.tasks.filter((t) => t.status === "done").map((t) => t.id)
    );
    this.saveState(plan);
    while (!this.aborted) {
      const nextTask = plan.tasks.find(
        (t) => t.status === "pending" && t.dependencies.every((d) => completedIds.has(d))
      );
      if (!nextTask) {
        const pending = plan.tasks.filter((t) => t.status === "pending");
        if (pending.length === 0) break;
        const failedIds = new Set(plan.tasks.filter((t) => t.status === "failed").map((t) => t.id));
        const hasCycle = pending.every(
          (t) => t.dependencies.some((d) => !completedIds.has(d) && !failedIds.has(d) && pending.some((p) => p.id === d))
        );
        if (hasCycle) {
          console.log(chalk.red(`  \u2717 Circular dependency detected among ${pending.length} task(s):`));
        } else {
          console.log(chalk.red(`  \u2717 Cannot proceed: ${pending.length} task(s) have unmet dependencies.`));
        }
        for (const t of pending) {
          const unmet = t.dependencies.filter((d) => !completedIds.has(d));
          console.log(chalk.dim(`    Task #${t.id}: waiting on [${unmet.join(", ")}]`));
        }
        break;
      }
      nextTask.status = "running";
      const role = roleMap.get(nextTask.assignee) ?? {
        id: nextTask.assignee,
        name: nextTask.assigneeName,
        persona: `You are ${nextTask.assigneeName}, an expert in your domain.`
      };
      this.renderTaskStart(nextTask);
      const result = await executeTask({
        task: nextTask.description,
        role,
        provider,
        model: this.config.defaultModel,
        maxRounds: maxRoundsPerTask,
        context: this.config.context,
        configManager: this.configManager,
        onToolCall: (call, danger) => {
          const icon = danger === "write" ? chalk.yellow("\u270E") : chalk.cyan("\u2699");
          console.log(chalk.dim(`    ${icon} ${call.name}`));
        },
        onRound: (round, max) => {
          if (round === 1 || round % 5 === 0) {
            process.stdout.write(chalk.dim(`    [round ${round}/${max}]\r`));
          }
        }
      });
      nextTask.status = result.success ? "done" : "failed";
      nextTask.result = result.content;
      nextTask.roundsUsed = result.roundsUsed;
      nextTask.usage = result.usage;
      if (result.success) {
        completedIds.add(nextTask.id);
      }
      this.saveState(plan);
      this.renderTaskEnd(nextTask, result);
      if (this.aborted) {
        console.log(chalk.yellow("\n  \u26A0 Execution interrupted by user."));
        break;
      }
    }
    this.renderExecutionSummary(plan);
  }
  // ── Phase 4: Review ───────────────────────────────────────────────
  async generateReview(plan, provider) {
    const doneTasks = plan.tasks.filter((t) => t.status === "done");
    const failedTasks = plan.tasks.filter((t) => t.status === "failed");
    const pendingTasks = plan.tasks.filter((t) => t.status === "pending");
    if (doneTasks.length === 0) {
      console.log(chalk.yellow("  No tasks were completed \u2014 skipping review."));
      return;
    }
    const transcript = plan.tasks.map((t) => {
      const status = t.status === "done" ? "\u2713" : t.status === "failed" ? "\u2717" : "\u25CB";
      const result = t.result ? `
  Result: ${t.result.slice(0, 500)}` : "";
      return `[${status}] #${t.id} ${t.description} (${t.assigneeName})${result}`;
    }).join("\n\n");
    const messages = [
      {
        role: "user",
        content: `Please provide a structured review of the project execution.

## Original Goal
${plan.goal}

## Task Execution Results
${transcript}

## Statistics
- Completed: ${doneTasks.length}/${plan.tasks.length}
- Failed: ${failedTasks.length}
- Pending: ${pendingTasks.length}

Please summarize:
1. What was accomplished
2. Key files created/modified
3. Issues encountered
4. Recommended next steps

Use the same language as the original goal.`,
        timestamp: /* @__PURE__ */ new Date()
      }
    ];
    try {
      const response = await provider.chat({
        messages,
        model: this.config.defaultModel,
        stream: false,
        temperature: 0.3,
        maxTokens: 4096
      });
      console.log();
      console.log(chalk.bold.white("  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
      console.log(chalk.bold.white("  \u2551") + chalk.bold.green("  \u{1F4CB} Project Review                                         ") + chalk.bold.white("\u2551"));
      console.log(chalk.bold.white("  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
      console.log();
      for (const line of response.content.split("\n")) {
        console.log("  " + line);
      }
      console.log();
    } catch (err) {
      console.log(chalk.red(`  \u2717 Review generation failed: ${err.message}`));
    }
  }
  // ── Rendering ─────────────────────────────────────────────────────
  renderPhaseHeader(phase, description) {
    console.log();
    console.log(chalk.bold.cyan(`  \u2501\u2501\u2501\u2501 Phase: ${phase} \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`));
    console.log(chalk.dim(`  ${description}`));
    console.log();
  }
  renderPlan(plan) {
    console.log(chalk.bold(`  \u{1F4CB} Task Plan (${plan.tasks.length} tasks):`));
    console.log();
    for (const task of plan.tasks) {
      const deps = task.dependencies.length > 0 ? chalk.dim(` [after: ${task.dependencies.join(", ")}]`) : "";
      const roleColor = this.getRoleColor(task.assignee);
      console.log(
        `    ${chalk.bold(`#${task.id}`)} ${task.description}`
      );
      console.log(
        `       ${roleColor(`\u2192 ${task.assigneeName}`)}${deps}`
      );
    }
    console.log();
  }
  renderTaskStart(task) {
    const roleColor = this.getRoleColor(task.assignee);
    console.log();
    console.log(chalk.bold(`  \u250C\u2500\u2500 Task #${task.id}: ${task.description}`));
    console.log(chalk.dim(`  \u2502  Assigned to: `) + roleColor(task.assigneeName));
  }
  renderTaskEnd(task, result) {
    if (task.status === "done") {
      console.log(chalk.green(`  \u2502  \u2713 Completed (${result.roundsUsed} rounds, ${result.usage.inputTokens + result.usage.outputTokens} tokens)`));
    } else {
      console.log(chalk.red(`  \u2502  \u2717 Failed (${result.roundsUsed} rounds)`));
    }
    const lines = result.content.split("\n").slice(0, 5);
    for (const line of lines) {
      console.log(chalk.dim(`  \u2502  ${line}`));
    }
    if (result.content.split("\n").length > 5) {
      console.log(chalk.dim(`  \u2502  ... (${result.content.split("\n").length - 5} more lines)`));
    }
    console.log(chalk.bold(`  \u2514${"\u2500".repeat(60)}`));
  }
  renderExecutionSummary(plan) {
    const done = plan.tasks.filter((t) => t.status === "done").length;
    const failed = plan.tasks.filter((t) => t.status === "failed").length;
    const pending = plan.tasks.filter((t) => t.status === "pending").length;
    const totalTokens = plan.tasks.reduce((sum, t) => {
      return sum + (t.usage ? t.usage.inputTokens + t.usage.outputTokens : 0);
    }, 0);
    console.log();
    console.log(chalk.bold("  \u2500\u2500 Execution Summary \u2500\u2500"));
    console.log(`    ${chalk.green("\u2713")} Completed: ${done}`);
    if (failed > 0) console.log(`    ${chalk.red("\u2717")} Failed: ${failed}`);
    if (pending > 0) console.log(`    ${chalk.dim("\u25CB")} Pending: ${pending}`);
    console.log(`    ${chalk.dim("\u2299")} Total tokens: ${totalTokens.toLocaleString()}`);
    console.log();
  }
  getRoleColor(roleId) {
    const colors = {
      architect: chalk.cyan,
      dba: chalk.yellow,
      frontend: chalk.green,
      backend: chalk.blue,
      security: chalk.red,
      tester: chalk.magenta,
      human: chalk.white
    };
    return colors[roleId] ?? chalk.white;
  }
};
export {
  TaskOrchestrator
};
