#!/usr/bin/env node
import {
  AGENT_MODULE_FILENAMES,
  AgentLoggerService,
  AgentMonitorService,
  CLI_BUNDLE_DIR,
  CLI_PACKAGE_ROOT,
  CLI_ROOT_CANDIDATES,
  MemoryAdapter,
  MemoryStore,
  MonitoringCleanup,
  SHOULD_DEBUG_BOOTSTRAP,
  bootstrapWorkspace,
  clearTerminal,
  copyPromptFile,
  createSpinnerLoggers,
  debug,
  debugLog,
  ensureDir,
  ensurePromptFile,
  ensureSpecificationsTemplate,
  error,
  executeAgent,
  formatAgentLog,
  getAgentLoggers,
  getEngine,
  hasTemplateChanged,
  isModuleStep,
  isWorkflowTemplate,
  loadAgentConfig,
  loadAgentTemplate,
  loadAgents,
  loadPlaceholdersConfig,
  loadWorkflowModule,
  mirrorAgentsToJson,
  processPromptString,
  registry,
  renderMainMenu,
  renderTypewriter,
  resolvePlaceholderPath,
  runStartupFlow,
  runWorkflowQueue,
  selectFromMenu,
  setActiveTemplate,
  slugify,
  startSpinner,
  stopSpinner,
  validateSpecification,
  warn,
  writeFileIfChanged
} from "./chunk-CJNY3EXZ.js";

// src/runtime/cli-setup.ts
import { Command as Command2 } from "commander";
import { existsSync as existsSync4, realpathSync } from "fs";
import { fileURLToPath as fileURLToPath4 } from "url";
import * as path5 from "path";

// src/cli/commands/start.command.ts
import * as path from "path";
var DEFAULT_SPEC_PATH = ".codemachine/inputs/specifications.md";
function registerStartCommand(program) {
  program.command("start").description("Run the workflow queue until completion (non-interactive)").option("--spec <path>", "Path to the planning specification file").action(async (options, command) => {
    const cwd = process.env.CODEMACHINE_CWD || process.cwd();
    const globalOpts = command.optsWithGlobals ? command.optsWithGlobals() : command.opts();
    const specPath = options.spec ?? globalOpts.spec ?? DEFAULT_SPEC_PATH;
    const specificationPath = path.resolve(cwd, specPath);
    debug(`Starting workflow (spec: ${specificationPath})`);
    clearTerminal();
    try {
      await runWorkflowQueue({ cwd, specificationPath });
      console.log("\n\u2713 Workflow completed successfully");
      process.exit(0);
    } catch (error2) {
      console.error("\n\u2717 Workflow failed:", error2 instanceof Error ? error2.message : String(error2));
      process.exit(1);
    }
  });
}

// src/cli/commands/templates.command.ts
import * as path2 from "path";
import { existsSync, readdirSync } from "fs";
import { rm } from "fs/promises";
import { fileURLToPath } from "url";
var packageRoot = (() => {
  const moduleDir = path2.dirname(fileURLToPath(import.meta.url));
  let current = moduleDir;
  while (true) {
    if (existsSync(path2.join(current, "package.json"))) return current;
    const parent = path2.dirname(current);
    if (parent === current) return moduleDir;
    current = parent;
  }
})();
var templatesDir = path2.resolve(packageRoot, "templates", "workflows");
function printAvailableWorkflowTemplatesHeading() {
  console.log("\nAvailable workflow templates:\n");
}
async function handleTemplateSelectionSuccess(template, templateFilePath) {
  const templateFileName = path2.basename(templateFilePath);
  const cwd = process.env.CODEMACHINE_CWD || process.cwd();
  const cmRoot = path2.join(cwd, ".codemachine");
  const agentsDir = path2.join(cmRoot, "agents");
  console.log(`
Selected: ${template.name}`);
  console.log(`Template path: ${path2.relative(process.cwd(), templateFilePath)}`);
  console.log(`
Steps:`);
  template.steps.forEach((step, index) => {
    if (isModuleStep(step)) {
      console.log(`  ${index + 1}. ${step.agentName} [${step.agentId}]`);
    } else {
      console.log(`  ${index + 1}. [UI Element]`);
    }
  });
  const changed = await hasTemplateChanged(cmRoot, templateFileName);
  if (changed) {
    console.log("\n\u{1F504} Template changed, regenerating agents...");
    if (existsSync(agentsDir)) {
      await rm(agentsDir, { recursive: true, force: true });
    }
    await setActiveTemplate(cmRoot, templateFileName);
    await bootstrapWorkspace({
      cwd,
      templatePath: templateFilePath
    });
    console.log("\u2705 Agents regenerated successfully");
  } else {
    console.log("\n\u2713 Template unchanged, agents folder up to date");
    await setActiveTemplate(cmRoot, templateFileName);
  }
  console.log(`
\u2705 Template saved to .codemachine/template.json`);
}
async function getAvailableTemplates() {
  if (!existsSync(templatesDir)) {
    return [];
  }
  const files = readdirSync(templatesDir).filter(
    (file) => file.endsWith(".workflow.js") && !file.startsWith("_example.")
  );
  const templates = [];
  for (const file of files) {
    try {
      const filePath = path2.join(templatesDir, file);
      const template = await loadWorkflowModule(filePath);
      if (isWorkflowTemplate(template)) {
        templates.push({
          title: template.name,
          value: filePath,
          description: `${template.steps.length} step(s) - ${file}`
        });
      }
    } catch (error2) {
      console.warn(`Warning: Could not load template ${file}:`, error2);
    }
  }
  return templates.sort((a, b) => a.title.localeCompare(b.title));
}
async function runTemplatesCommand(inSession = false) {
  try {
    const templates = await getAvailableTemplates();
    if (templates.length === 0) {
      console.log("No workflow templates found in templates/workflows/");
      return;
    }
    printAvailableWorkflowTemplatesHeading();
    const selectedTemplate = await selectFromMenu({
      message: "Choose a workflow template:",
      choices: templates,
      initial: 0
    });
    if (selectedTemplate) {
      const template = await loadWorkflowModule(selectedTemplate);
      if (isWorkflowTemplate(template)) {
        await handleTemplateSelectionSuccess(template, selectedTemplate);
      }
    } else {
      console.log("No template selected.");
    }
  } catch (error2) {
    console.error("Error loading templates:", error2);
    if (!inSession) {
      process.exit(1);
    }
  }
}
function registerTemplatesCommand(program) {
  program.command("templates").description("List and select workflow templates").action(runTemplatesCommand);
}

// src/cli/commands/auth.command.ts
async function selectAuthProvider() {
  const choices = registry.getAll().map((engine) => ({
    title: engine.metadata.name,
    value: engine.metadata.id,
    description: engine.metadata.description
  }));
  return await selectFromMenu({
    message: "Choose authentication provider:",
    choices,
    initial: 0
  });
}
async function handleLogin(providerId) {
  const engine = registry.get(providerId);
  if (!engine) {
    throw new Error(`Unknown provider: ${providerId}`);
  }
  const action = await engine.auth.nextAuthMenuAction();
  if (action === "logout") {
    if (providerId === "ccr") {
      console.log(`
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
      console.log(`  \u2705  ${engine.metadata.name} CLI Detected`);
      console.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
      console.log(`
\u{1F4A1} Tip: CCR is installed but you might still need to configure it`);
      console.log(`       (if you haven't already).
`);
      console.log(`To configure CCR:`);
      console.log(`  1. Run: ccr ui`);
      console.log(`     Opens the web UI to add your providers
`);
      console.log(`  2. Or manually edit: ~/.claude-code-router/config.json
`);
      console.log(`\u{1F680} Easiest way to use CCR inside Codemachine:`);
      console.log(`   Logout from all other engines using:`);
      console.log(`     codemachine auth logout`);
      console.log(`   This will run CCR by default for all engines.
`);
      console.log(`   Or modify the template by adding ccr engine.`);
      console.log(`   For full guide, check:`);
      console.log(`   https://github.com/moazbuilds/CodeMachine-CLI/blob/main/docs/customizing-workflows.md
`);
      console.log(`For more help, visit:`);
      console.log(`  https://github.com/musistudio/claude-code-router
`);
      console.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
`);
    } else {
      console.log(`Already authenticated with ${engine.metadata.name}. Use \`codemachine auth logout\` to sign out.`);
    }
    return;
  }
  await engine.auth.ensureAuth();
  console.log(`${engine.metadata.name} authentication successful.`);
}
async function handleLogout(providerId) {
  const engine = registry.get(providerId);
  if (!engine) {
    throw new Error(`Unknown provider: ${providerId}`);
  }
  if (providerId === "ccr") {
    console.log(`
\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
    console.log(`  \u2139\uFE0F  ${engine.metadata.name} Logout`);
    console.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
    console.log(`
CCR authentication is managed by the CCR CLI itself.`);
    console.log(`There is no logout action required in Codemachine.
`);
    console.log(`To reconfigure CCR, simply run: ccr ui
`);
    console.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
`);
    return;
  }
  await engine.auth.clearAuth();
  console.log(`Signed out from ${engine.metadata.name}. Next action will be \`login\`.`);
}
function registerAuthCommands(program) {
  const authCommand = program.command("auth").description("Authentication helpers");
  authCommand.command("login").description("Authenticate with Codemachine services").action(async () => {
    const provider = await selectAuthProvider();
    if (!provider) {
      console.log("No provider selected.");
      return;
    }
    await handleLogin(provider);
  });
  authCommand.command("logout").description("Log out of Codemachine services").action(async () => {
    const provider = await selectAuthProvider();
    if (!provider) {
      console.log("No provider selected.");
      return;
    }
    await handleLogout(provider);
  });
}

// src/agents/coordinator/parser.ts
var CoordinatorParser = class {
  /**
   * Parse coordination script
   */
  parse(script) {
    const trimmed = script.trim();
    if (!trimmed) {
      throw new Error("Coordination script cannot be empty");
    }
    const hasSequential = trimmed.includes("&&");
    const hasParallel = trimmed.includes("&") && !hasSequential;
    if (hasSequential && trimmed.includes("&") && trimmed.split("&&").some((part) => part.includes("&"))) {
      return this.parseMixed(trimmed);
    }
    if (hasSequential) {
      return this.parseSequential(trimmed);
    }
    if (hasParallel) {
      return this.parseParallel(trimmed);
    }
    return this.parseSingle(trimmed);
  }
  /**
   * Parse single command (no & or &&)
   */
  parseSingle(script) {
    const command = this.parseCommand(script);
    return {
      groups: [
        {
          mode: "sequential",
          commands: [command]
        }
      ]
    };
  }
  /**
   * Parse parallel commands (separated by &)
   */
  parseParallel(script) {
    const parts = this.smartSplit(script, "&").map((p) => p.trim());
    const commands = parts.map((part) => this.parseCommand(part));
    return {
      groups: [
        {
          mode: "parallel",
          commands
        }
      ]
    };
  }
  /**
   * Parse sequential commands (separated by &&)
   */
  parseSequential(script) {
    const parts = this.smartSplitMultiChar(script, "&&").map((p) => p.trim());
    const commands = parts.map((part) => this.parseCommand(part));
    return {
      groups: [
        {
          mode: "sequential",
          commands
        }
      ]
    };
  }
  /**
   * Parse mixed mode (contains both & and &&)
   * For now, we'll treat && as group separators and & as parallel within groups
   *
   * Example: "db 'schema' && frontend 'ui' & backend 'api' && test 'e2e'"
   * Groups:
   * 1. Sequential: db 'schema'
   * 2. Parallel: frontend 'ui', backend 'api'
   * 3. Sequential: test 'e2e'
   */
  parseMixed(script) {
    const sequentialParts = this.smartSplitMultiChar(script, "&&").map((p) => p.trim());
    const groups = sequentialParts.map((part) => {
      if (this.containsOutsideQuotes(part, "&")) {
        const parallelParts = this.smartSplit(part, "&").map((p) => p.trim());
        return {
          mode: "parallel",
          commands: parallelParts.map((p) => this.parseCommand(p))
        };
      } else {
        return {
          mode: "sequential",
          commands: [this.parseCommand(part)]
        };
      }
    });
    return { groups };
  }
  /**
   * Parse a single command: "agent-name 'prompt text'" or enhanced syntax
   */
  parseCommand(commandStr) {
    const trimmed = commandStr.trim();
    const enhancedMatch = trimmed.match(/^(\S+)\[([^\]]+)\](?:\s+(.+))?$/);
    if (enhancedMatch) {
      const name = enhancedMatch[1];
      const optionsStr = enhancedMatch[2];
      const trailingPart = enhancedMatch[3];
      const options = this.parseOptions(optionsStr);
      let trailingPrompt;
      if (trailingPart) {
        trailingPrompt = this.extractQuotedString(trailingPart.trim());
      }
      return {
        name,
        prompt: options.prompt || trailingPrompt || void 0,
        input: options.input,
        tail: options.tail,
        options: options.extra
      };
    }
    const spaceIndex = trimmed.indexOf(" ");
    if (spaceIndex > 0) {
      const name = trimmed.substring(0, spaceIndex);
      const rest = trimmed.substring(spaceIndex + 1).trim();
      const prompt = this.extractQuotedString(rest);
      if (prompt !== null) {
        return { name, prompt };
      }
      return { name, prompt: rest };
    }
    if (trimmed.match(/^\S+$/)) {
      return {
        name: trimmed
      };
    }
    throw new Error(`Invalid command syntax: ${commandStr}
Expected: agent-name 'prompt' or agent[options] 'prompt'`);
  }
  /**
   * Extract a quoted string, handling both single and double quotes
   * Returns the string content without quotes, or the original string if not quoted
   * Intelligently distinguishes apostrophes from closing quotes
   */
  extractQuotedString(str) {
    const trimmed = str.trim();
    if (trimmed.startsWith("'") || trimmed.startsWith('"')) {
      const quoteChar = trimmed[0];
      let i = 1;
      while (i < trimmed.length) {
        if (trimmed[i] === quoteChar && (i === 1 || trimmed[i - 1] !== "\\")) {
          const nextChar = i < trimmed.length - 1 ? trimmed[i + 1] : "";
          const isClosing = i === trimmed.length - 1 || nextChar === " " || nextChar === "	";
          if (isClosing) {
            return trimmed.substring(1, i);
          }
        }
        i++;
      }
      return trimmed.substring(1);
    }
    return trimmed;
  }
  /**
   * Parse options string from brackets
   * Format: key:value,key:value
   */
  parseOptions(optionsStr) {
    const result = {
      extra: {}
    };
    const parts = this.smartSplit(optionsStr, ",");
    for (const part of parts) {
      const trimmedPart = part.trim();
      if (!trimmedPart) continue;
      const colonIndex = trimmedPart.indexOf(":");
      if (colonIndex === -1) {
        continue;
      }
      const key = trimmedPart.substring(0, colonIndex).trim();
      const value = trimmedPart.substring(colonIndex + 1).trim();
      switch (key) {
        case "input":
          result.input = this.parseInput(value);
          break;
        case "tail":
          result.tail = this.parseTail(value);
          break;
        case "prompt":
          result.prompt = this.unquote(value);
          break;
        default:
          result.extra[key] = this.unquote(value);
      }
    }
    return result;
  }
  /**
   * Parse input value (semicolon-separated file paths)
   */
  parseInput(value) {
    const unquoted = this.unquote(value);
    return unquoted.split(";").map((p) => p.trim()).filter((p) => p.length > 0);
  }
  /**
   * Parse tail value (must be a number)
   */
  parseTail(value) {
    const unquoted = this.unquote(value);
    const num = parseInt(unquoted, 10);
    return isNaN(num) ? void 0 : num;
  }
  /**
   * Remove surrounding quotes from a string
   */
  unquote(str) {
    const trimmed = str.trim();
    if (trimmed.startsWith('"') && trimmed.endsWith('"') || trimmed.startsWith("'") && trimmed.endsWith("'")) {
      return trimmed.substring(1, trimmed.length - 1);
    }
    return trimmed;
  }
  /**
   * Smart split that respects quotes
   * Splits by delimiter but keeps quoted strings intact
   * Distinguishes between apostrophes and quote delimiters
   */
  smartSplit(str, delimiter) {
    const result = [];
    let current = "";
    let inQuotes = false;
    let quoteChar = "";
    for (let i = 0; i < str.length; i++) {
      const char = str[i];
      if ((char === '"' || char === "'") && (i === 0 || str[i - 1] !== "\\")) {
        if (!inQuotes) {
          const prevChar = i > 0 ? str[i - 1] : "";
          const isOpening = i === 0 || prevChar === " " || prevChar === delimiter || prevChar === "	";
          if (isOpening) {
            inQuotes = true;
            quoteChar = char;
          }
        } else if (char === quoteChar) {
          const nextChar = i < str.length - 1 ? str[i + 1] : "";
          const isClosing = i === str.length - 1 || nextChar === " " || nextChar === delimiter || nextChar === "	";
          if (isClosing) {
            inQuotes = false;
            quoteChar = "";
          }
        }
      }
      if (char === delimiter && !inQuotes) {
        result.push(current);
        current = "";
      } else {
        current += char;
      }
    }
    if (current) {
      result.push(current);
    }
    return result;
  }
  /**
   * Smart split for multi-character delimiters that respects quotes
   * Distinguishes between apostrophes and quote delimiters
   */
  smartSplitMultiChar(str, delimiter) {
    const result = [];
    let current = "";
    let inQuotes = false;
    let quoteChar = "";
    for (let i = 0; i < str.length; i++) {
      const char = str[i];
      if ((char === '"' || char === "'") && (i === 0 || str[i - 1] !== "\\")) {
        if (!inQuotes) {
          const prevChar = i > 0 ? str[i - 1] : "";
          const isOpening = i === 0 || prevChar === " " || prevChar === "	";
          if (isOpening) {
            inQuotes = true;
            quoteChar = char;
          }
        } else if (char === quoteChar) {
          const nextChar = i < str.length - 1 ? str[i + 1] : "";
          const isClosing = i === str.length - 1 || nextChar === " " || nextChar === "	";
          if (isClosing) {
            inQuotes = false;
            quoteChar = "";
          }
        }
      }
      if (!inQuotes && str.substring(i, i + delimiter.length) === delimiter) {
        result.push(current);
        current = "";
        i += delimiter.length - 1;
      } else {
        current += char;
      }
    }
    if (current) {
      result.push(current);
    }
    return result;
  }
  /**
   * Check if a string contains a character outside of quotes
   * Distinguishes between apostrophes and quote delimiters
   */
  containsOutsideQuotes(str, searchChar) {
    let inQuotes = false;
    let quoteChar = "";
    for (let i = 0; i < str.length; i++) {
      const char = str[i];
      if ((char === '"' || char === "'") && (i === 0 || str[i - 1] !== "\\")) {
        if (!inQuotes) {
          const prevChar = i > 0 ? str[i - 1] : "";
          const isOpening = i === 0 || prevChar === " " || prevChar === "	";
          if (isOpening) {
            inQuotes = true;
            quoteChar = char;
          }
        } else if (char === quoteChar) {
          const nextChar = i < str.length - 1 ? str[i + 1] : "";
          const isClosing = i === str.length - 1 || nextChar === " " || nextChar === "	";
          if (isClosing) {
            inQuotes = false;
            quoteChar = "";
          }
        }
      }
      if (char === searchChar && !inQuotes) {
        return true;
      }
    }
    return false;
  }
};

// src/agents/coordinator/execution.ts
import * as fs from "fs/promises";
import * as path3 from "path";
import chalk from "chalk";
var CoordinationExecutor = class {
  options;
  constructor(options) {
    this.options = options;
  }
  /**
   * Execute the complete coordination plan
   */
  async execute(plan) {
    const results = [];
    for (const group of plan.groups) {
      const groupResults = await this.executeGroup(group);
      results.push(...groupResults);
      const anyFailed = groupResults.some((r) => !r.success);
      if (anyFailed && group.mode === "sequential") {
        warn("Sequential group had failures, stopping execution");
        break;
      }
    }
    const success = results.every((r) => r.success);
    return {
      parentId: this.options.parentId,
      results,
      success
    };
  }
  /**
   * Execute a command group (either parallel or sequential)
   */
  async executeGroup(group) {
    if (group.mode === "parallel") {
      return this.executeParallel(group.commands);
    } else {
      return this.executeSequential(group.commands);
    }
  }
  /**
   * Execute commands in parallel
   */
  async executeParallel(commands) {
    console.log(chalk.dim(`
\u2192 Executing ${commands.length} agents in parallel...
`));
    const promises = commands.map((cmd) => this.executeCommand(cmd));
    return Promise.all(promises);
  }
  /**
   * Execute commands sequentially
   */
  async executeSequential(commands) {
    const results = [];
    for (let i = 0; i < commands.length; i++) {
      console.log(chalk.dim(`
\u2192 Executing agent ${i + 1}/${commands.length}...
`));
      const result = await this.executeCommand(commands[i]);
      results.push(result);
      if (!result.success) {
        error(`Agent ${result.name} failed, stopping sequential execution`);
        break;
      }
    }
    return results;
  }
  /**
   * Execute a single command
   */
  async executeCommand(command) {
    console.log(chalk.bold.cyan(`
\u250C\u2500 Agent: ${command.name}`));
    if (command.input && command.input.length > 0) {
      console.log(chalk.dim(`\u2502  Input: ${command.input.join(", ")}`));
    }
    console.log(chalk.dim("\u2514" + "\u2500".repeat(60) + "\n"));
    try {
      let inputContent = "";
      if (command.input && command.input.length > 0) {
        inputContent = await this.loadInputFiles(command.input);
      }
      const rawTemplate = await loadAgentTemplate(command.name, this.options.workingDir);
      const template = await processPromptString(rawTemplate, this.options.workingDir);
      const compositePrompt = this.buildCompositePrompt(
        inputContent,
        template,
        command.prompt
      );
      const suppressOutput = command.tail !== void 0 && command.tail > 0;
      const result = await executeAgent(command.name, compositePrompt, {
        workingDir: this.options.workingDir,
        parentId: this.options.parentId,
        displayPrompt: command.prompt,
        // Show user's actual request in logs, not full composite
        logger: suppressOutput ? () => {
        } : this.options.logger ? (chunk) => this.options.logger(command.name, chunk) : void 0,
        stderrLogger: suppressOutput ? () => {
        } : void 0
      });
      const output = result.output;
      const monitoringAgentId = result.agentId || 0;
      let finalOutput = output;
      let tailApplied;
      if (command.tail && command.tail > 0) {
        const lines = output.split("\n");
        if (lines.length > command.tail) {
          finalOutput = lines.slice(-command.tail).join("\n");
          tailApplied = command.tail;
          debug(`Applied tail limiting: ${lines.length} -> ${command.tail} lines`);
        }
      }
      console.log(chalk.green(`
\u2713 Agent ${command.name} completed successfully`));
      if (tailApplied) {
        console.log(chalk.dim(`  (Output limited to last ${tailApplied} lines)`));
      }
      if (suppressOutput && finalOutput) {
        console.log("\n" + chalk.bold("\u2550".repeat(60)));
        console.log(chalk.bold(`Agent Output: ${command.name} ID:${monitoringAgentId}`));
        console.log(chalk.bold("\u2550".repeat(60)) + "\n");
        console.log(finalOutput);
        console.log("\n" + chalk.dim("\u2500".repeat(60)) + "\n");
      }
      return {
        name: command.name,
        agentId: monitoringAgentId,
        success: true,
        prompt: command.prompt,
        input: command.input,
        output: finalOutput,
        tailApplied
      };
    } catch (error2) {
      const errorMessage = error2 instanceof Error ? error2.message : String(error2);
      console.log(chalk.red(`
\u2717 Agent ${command.name} failed: ${errorMessage}`));
      const monitor = AgentMonitorService.getInstance();
      const agents = monitor.queryAgents({
        name: command.name,
        parentId: this.options.parentId
      });
      const agent = agents.sort((a, b) => b.id - a.id)[0];
      return {
        name: command.name,
        agentId: agent?.id || 0,
        success: false,
        prompt: command.prompt,
        input: command.input,
        error: errorMessage
      };
    }
  }
  /**
   * Resolve placeholders in a file path
   * Supports {placeholder_name} syntax for both userDir and packageDir placeholders
   * @param filePath File path that may contain {placeholder} syntax
   * @returns Resolved file path with placeholders replaced
   */
  resolvePlaceholdersInPath(filePath) {
    const placeholderRegex = /\{([^}]+)\}/g;
    const matches = Array.from(filePath.matchAll(placeholderRegex));
    if (matches.length === 0) {
      return filePath;
    }
    const config = loadPlaceholdersConfig();
    let resolvedPath = filePath;
    for (const match of matches) {
      const fullMatch = match[0];
      const placeholderName = match[1];
      const resolved = resolvePlaceholderPath(placeholderName, this.options.workingDir, config);
      if (resolved) {
        const resolvedFilePath = path3.isAbsolute(resolved.filePath) ? resolved.filePath : path3.resolve(resolved.baseDir, resolved.filePath);
        resolvedPath = resolvedPath.replace(fullMatch, resolvedFilePath);
        debug(`Resolved placeholder ${fullMatch} to ${resolvedFilePath}`);
      } else {
        warn(`Placeholder ${fullMatch} not found in config/placeholders.js, treating as literal path`);
      }
    }
    return resolvedPath;
  }
  /**
   * Load multiple input files and concatenate their contents
   * @param filePaths Array of file paths (absolute, relative to workingDir, or with {placeholder} syntax)
   * @returns Concatenated file contents with separators
   */
  async loadInputFiles(filePaths) {
    if (!filePaths || filePaths.length === 0) {
      return "";
    }
    const contents = [];
    for (const filePath of filePaths) {
      try {
        const pathWithPlaceholdersResolved = this.resolvePlaceholdersInPath(filePath);
        const resolvedPath = path3.isAbsolute(pathWithPlaceholdersResolved) ? pathWithPlaceholdersResolved : path3.resolve(this.options.workingDir, pathWithPlaceholdersResolved);
        debug(`Loading input file: ${resolvedPath} (original: ${filePath})`);
        const content = await fs.readFile(resolvedPath, "utf-8");
        contents.push(`
=== File: ${filePath} ===
${content}
${"=".repeat(60)}
`);
      } catch (error2) {
        const message = error2 instanceof Error ? error2.message : String(error2);
        warn(`Failed to load input file ${filePath}: ${message}`);
        contents.push(`
=== File: ${filePath} (FAILED TO LOAD) ===
Error: ${message}
${"=".repeat(60)}
`);
      }
    }
    return contents.join("\n");
  }
  /**
   * Build composite prompt from input files, agent template, and user prompt
   * Sections are ordered: system prompt -> [INPUT FILES] -> [REQUEST]
   * @param inputContent Content from input files
   * @param template Agent template content (already processed)
   * @param userPrompt User-provided prompt (optional)
   * @returns Composite prompt ready for execution
   */
  buildCompositePrompt(inputContent, template, userPrompt) {
    const parts = [];
    if (template && template.trim()) {
      parts.push(template);
      parts.push("");
    }
    if (inputContent && inputContent.trim()) {
      parts.push("[INPUT FILES]");
      parts.push(inputContent);
      parts.push("");
    }
    if (userPrompt && userPrompt.trim()) {
      parts.push("[REQUEST]");
      parts.push(userPrompt);
    }
    return parts.join("\n");
  }
};

// src/agents/coordinator/service.ts
import chalk2 from "chalk";
var CoordinatorService = class _CoordinatorService {
  static instance;
  parser;
  constructor() {
    this.parser = new CoordinatorParser();
    debug("CoordinatorService initialized");
  }
  /**
   * Get singleton instance
   */
  static getInstance() {
    if (!_CoordinatorService.instance) {
      _CoordinatorService.instance = new _CoordinatorService();
    }
    return _CoordinatorService.instance;
  }
  /**
   * Execute a coordination script
   */
  async execute(script, options) {
    console.log(chalk2.bold("\n\u{1F3AD} Starting coordination...\n"));
    console.log(chalk2.dim(`Script: ${script}
`));
    let plan;
    try {
      plan = this.parser.parse(script);
      debug(`Parsed coordination plan with ${plan.groups.length} groups`);
    } catch (error2) {
      const message = error2 instanceof Error ? error2.message : String(error2);
      console.error(chalk2.red(`
\u2717 Failed to parse coordination script: ${message}
`));
      throw error2;
    }
    const monitor = AgentMonitorService.getInstance();
    let contextParentId;
    const parentIdEnv = process.env.CODEMACHINE_PARENT_AGENT_ID;
    if (parentIdEnv) {
      const parsed = parseInt(parentIdEnv, 10);
      if (!isNaN(parsed)) {
        contextParentId = parsed;
        debug(`Found parent agent ID from environment: ${contextParentId}`);
      }
    }
    if (contextParentId === void 0) {
      const activeAgents = monitor.getActiveAgents();
      if (activeAgents.length > 0) {
        const mostRecent = activeAgents.sort(
          (a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime()
        )[0];
        contextParentId = mostRecent.id;
        debug(`Inferred parent agent from active agents: ${contextParentId} (${mostRecent.name})`);
      }
    }
    if (contextParentId !== void 0) {
      console.log(chalk2.dim(`Coordination under parent agent ID: ${contextParentId}
`));
    } else {
      console.log(chalk2.dim(`Coordination running as standalone session
`));
    }
    const executor = new CoordinationExecutor({
      workingDir: options.workingDir,
      parentId: contextParentId,
      // Agents register directly under workflow agent
      logger: options.logger
    });
    let result;
    try {
      result = await executor.execute(plan);
      this.printSummary(result);
      return result;
    } catch (error2) {
      console.error(chalk2.red(`
\u2717 Coordination failed: ${error2}
`));
      throw error2;
    }
  }
  /**
   * Print execution summary
   */
  printSummary(result) {
    console.log("\n" + chalk2.bold("\u2550".repeat(60)));
    console.log(chalk2.bold("Coordination Summary"));
    console.log(chalk2.bold("\u2550".repeat(60)) + "\n");
    const succeeded = result.results.filter((r) => r.success).length;
    const failed = result.results.filter((r) => !r.success).length;
    console.log(`${chalk2.dim("Total agents:")} ${result.results.length}`);
    console.log(`${chalk2.green("\u2713 Succeeded:")} ${succeeded}`);
    if (failed > 0) {
      console.log(`${chalk2.red("\u2717 Failed:")} ${failed}`);
    }
    console.log("\n" + chalk2.bold("Agent Results:"));
    result.results.forEach((r, index) => {
      const icon = r.success ? chalk2.green("\u2713") : chalk2.red("\u2717");
      const status = r.success ? chalk2.green("Completed") : chalk2.red("Failed");
      console.log(`  ${index + 1}. ${icon} ${chalk2.bold(r.name)} - ${status} (ID: ${r.agentId})`);
      if (r.input && r.input.length > 0) {
        console.log(`     ${chalk2.dim("Input:")} ${r.input.join(", ")}`);
      }
      if (r.prompt) {
        const displayPrompt = r.prompt.length > 80 ? r.prompt.substring(0, 77) + "..." : r.prompt;
        console.log(`     ${chalk2.dim("Prompt:")} ${displayPrompt}`);
      }
      if (r.error) {
        console.log(`     ${chalk2.red("Error:")} ${r.error}`);
      }
    });
    console.log("\n" + chalk2.dim("\u2500".repeat(60)));
    console.log(chalk2.dim(`View logs: codemachine agents logs <id>`));
    console.log(chalk2.dim(`List all agents: codemachine agents`));
    console.log("");
  }
};

// src/cli/commands/run.command.ts
import chalk3 from "chalk";
async function registerRunCommand(program) {
  const { registry: registry2 } = await import("./engines-2ZKMGRLJ.js");
  const defaultEngine = registry2.getDefault();
  const defaultEngineName = defaultEngine?.metadata.name ?? "default engine";
  program.command("run <script>").description(`Run agent(s) with enhanced syntax using ${defaultEngineName}`).option("--model <model>", "Model to use (overrides agent config)").option("-d, --dir <directory>", "Working directory", process.cwd()).action(async (script, options) => {
    MonitoringCleanup.setup();
    try {
      await runScript(script, options);
      process.exit(0);
    } catch (error2) {
      const message = error2 instanceof Error ? error2.message : String(error2);
      console.error(chalk3.red(`
Execution failed: ${message}
`));
      process.exit(1);
    }
  });
  await registerEngineRunCommands(program);
}
async function runScript(script, options) {
  const trimmed = script.trim();
  const coordinator = CoordinatorService.getInstance();
  await coordinator.execute(trimmed, {
    workingDir: options.dir
  });
}
async function registerEngineRunCommands(program) {
  const { registry: registry2 } = await import("./engines-2ZKMGRLJ.js");
  for (const engine of registry2.getAll()) {
    const engineCommand = program.command(engine.metadata.cliCommand).description(`Use ${engine.metadata.name} engine for agent execution`);
    engineCommand.command("run").description(`Run agent(s) with ${engine.metadata.name}`).argument("<script>", "Agent script to execute").option("--model <model>", "Model to use (overrides agent config)").option("-d, --dir <directory>", "Working directory", process.cwd()).action(async (script, options) => {
      MonitoringCleanup.setup();
      try {
        await runScript(script, options);
        process.exit(0);
      } catch (error2) {
        const message = error2 instanceof Error ? error2.message : String(error2);
        console.error(chalk3.red(`
Execution failed: ${message}
`));
        process.exit(1);
      }
    });
  }
}

// src/cli/commands/step.command.ts
import * as path4 from "path";
async function ensureEngineAuth(engineType) {
  const { registry: registry2 } = await import("./engines-2ZKMGRLJ.js");
  const engine = registry2.get(engineType);
  if (!engine) {
    const availableEngines = registry2.getAllIds().join(", ");
    throw new Error(
      `Unknown engine type: ${engineType}. Available engines: ${availableEngines}`
    );
  }
  const isAuthed = await engine.auth.isAuthenticated();
  if (!isAuthed) {
    console.error(`
${engine.metadata.name} authentication required`);
    console.error(`
Run the following command to authenticate:
`);
    console.error(`  codemachine auth login
`);
    throw new Error(`${engine.metadata.name} authentication required`);
  }
}
async function executeStep(agentId, additionalPrompt, options) {
  const workingDir = process.cwd();
  if (options.reasoning && !["low", "medium", "high"].includes(options.reasoning)) {
    throw new Error(`Invalid reasoning level: ${options.reasoning}. Must be one of: low, medium, high`);
  }
  const agentConfig = await loadAgentConfig(agentId, workingDir);
  const rawTemplate = await loadAgentTemplate(agentId, workingDir);
  const agentTemplate = await processPromptString(rawTemplate, workingDir);
  const { registry: registry2 } = await import("./engines-2ZKMGRLJ.js");
  let engineType;
  if (options.engine) {
    engineType = options.engine;
  } else if (agentConfig.engine) {
    engineType = agentConfig.engine;
  } else {
    const engines = registry2.getAll();
    let foundEngine = null;
    for (const engine2 of engines) {
      const isAuth = await engine2.auth.isAuthenticated();
      if (isAuth) {
        foundEngine = engine2;
        break;
      }
    }
    if (!foundEngine) {
      foundEngine = registry2.getDefault();
    }
    if (!foundEngine) {
      throw new Error("No engines registered. Please install at least one engine.");
    }
    engineType = foundEngine.metadata.id;
    console.log(`\u2139\uFE0F  No engine specified for agent '${agentId}', using ${foundEngine.metadata.name} (${engineType})`);
  }
  await ensureEngineAuth(engineType);
  const engineModule = registry2.get(engineType);
  if (!engineModule) {
    throw new Error(`Engine not found: ${engineType}`);
  }
  const model = options.model ?? agentConfig.model ?? engineModule.metadata.defaultModel;
  const modelReasoningEffort = options.reasoning ?? agentConfig.modelReasoningEffort ?? engineModule.metadata.defaultModelReasoningEffort;
  const memoryDir = path4.resolve(workingDir, ".codemachine", "memory");
  const adapter = new MemoryAdapter(memoryDir);
  const store = new MemoryStore(adapter);
  let compositePrompt;
  if (additionalPrompt) {
    compositePrompt = `${agentTemplate}

[REQUEST]
${additionalPrompt}`;
  } else {
    compositePrompt = agentTemplate;
  }
  const engine = getEngine(engineType);
  console.log("\u2550".repeat(80));
  console.log(formatAgentLog(agentId, `${agentConfig.name} started to work.`));
  const { stdout: baseStdoutLogger, stderr: baseStderrLogger } = getAgentLoggers(agentId);
  const workflowStartTime = Date.now();
  const spinnerState = startSpinner(agentConfig.name, engineType, workflowStartTime, model, modelReasoningEffort);
  const { stdoutLogger, stderrLogger } = createSpinnerLoggers(
    baseStdoutLogger,
    baseStderrLogger,
    spinnerState
  );
  try {
    let totalStdout = "";
    const result = await engine.run({
      prompt: compositePrompt,
      workingDir,
      model,
      modelReasoningEffort,
      onData: (chunk) => {
        totalStdout += chunk;
        stdoutLogger(chunk);
      },
      onErrorData: (chunk) => {
        stderrLogger(chunk);
      }
    });
    stopSpinner(spinnerState);
    const stdout = result.stdout || totalStdout;
    const slice = stdout.slice(-2e3);
    await store.append({
      agentId,
      content: slice,
      timestamp: (/* @__PURE__ */ new Date()).toISOString()
    });
    console.log(formatAgentLog(agentId, `${agentConfig.name} has completed their work.`));
    console.log("\n" + "\u2550".repeat(80) + "\n");
  } catch (error2) {
    stopSpinner(spinnerState);
    console.error(
      formatAgentLog(
        agentId,
        `${agentConfig.name} failed: ${error2 instanceof Error ? error2.message : String(error2)}`
      )
    );
    throw error2;
  }
}
async function registerStepCommand(program) {
  program.command("step").description("Execute a single workflow step (agent from config/main.agents.js)").argument("<id>", "Agent id from config/main.agents.js").argument("[prompt...]", "Optional additional prompt to append to the agent's main prompt").option("--model <model>", "Model to use (overrides agent config)").option("--engine <engine>", "Engine to use (overrides agent config and defaults)").option("--reasoning <level>", "Reasoning effort level: low, medium, or high (overrides agent config)").action(async (id, promptParts, options) => {
    const additionalPrompt = promptParts.join(" ").trim();
    await executeStep(id, additionalPrompt, options);
  });
}

// src/cli/commands/agents/index.ts
import { Command } from "commander";

// src/cli/commands/agents/list.ts
import chalk4 from "chalk";
function listAgents() {
  const monitor = AgentMonitorService.getInstance();
  const activeAgents = monitor.getActiveAgents();
  const offlineAgents = monitor.getOfflineAgents();
  const fullTree = monitor.buildAgentTree();
  const activeTrees = fullTree.filter((tree) => tree.agent.status === "running");
  const offlineTrees = fullTree.filter((tree) => tree.agent.status !== "running");
  console.log("");
  if (activeAgents.length > 0 && activeTrees.length > 0) {
    console.log(chalk4.bold.green(`ACTIVE AGENTS (${activeAgents.length} running)`));
    activeTrees.forEach((tree, index) => {
      printTreeNode(tree, "", index === activeTrees.length - 1, "active");
    });
    console.log("");
  }
  if (offlineAgents.length > 0 && offlineTrees.length > 0) {
    console.log(chalk4.bold.gray(`OFFLINE AGENTS (${offlineAgents.length} terminated)`));
    offlineTrees.forEach((tree, index) => {
      printTreeNode(tree, "", index === offlineTrees.length - 1, "offline");
    });
    console.log("");
  }
  const total = activeAgents.length + offlineAgents.length;
  console.log(chalk4.dim("\u2500".repeat(60)));
  console.log(chalk4.dim(`Total: ${total} agents (${activeAgents.length} active, ${offlineAgents.length} offline)`));
  console.log("");
}
function printTreeNode(node, prefix, isLast, mode) {
  const { agent } = node;
  const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
  const tag = agent.parentId ? chalk4.cyan("[SUB]") : chalk4.magenta("[MAIN]");
  const statusText = formatStatus(agent);
  const statusIcon = getStatusIcon(agent.status);
  console.log(`${prefix}${connector} ${tag} ${chalk4.bold(agent.name)} ${statusIcon}`);
  const idLine = buildIdLine(agent, statusText, mode);
  console.log(`${prefix}${isLast ? " " : "\u2502"}   ${idLine}`);
  if (agent.prompt.length > 60) {
    console.log(`${prefix}${isLast ? " " : "\u2502"}   ${chalk4.dim("Prompt:")} ${agent.prompt.substring(0, 57)}...`);
  } else {
    console.log(`${prefix}${isLast ? " " : "\u2502"}   ${chalk4.dim("Prompt:")} ${agent.prompt}`);
  }
  if (mode === "offline" || agent.status !== "running") {
    console.log(
      `${prefix}${isLast ? " " : "\u2502"}   ${chalk4.dim("Ran:")} ${formatRunRange(agent)}`
    );
    if (agent.error) {
      console.log(`${prefix}${isLast ? " " : "\u2502"}   ${chalk4.red("Error:")} ${agent.error}`);
    }
  }
  if (node.children.length > 0) {
    const childPrefix = prefix + (isLast ? "    " : "\u2502   ");
    node.children.forEach((child, index) => {
      printTreeNode(child, childPrefix, index === node.children.length - 1, mode);
    });
  }
}
function buildIdLine(agent, statusText, mode) {
  const segments = [
    `${chalk4.dim("ID:")} ${agent.id}`,
    `${chalk4.dim("Status:")} ${statusText}`
  ];
  if (mode === "active") {
    const uptime = formatDuration(Date.now() - new Date(agent.startTime).getTime());
    segments.push(`${chalk4.dim("Uptime:")} ${uptime}`);
  } else {
    const durationText = formatAgentDuration(agent);
    segments.push(`${chalk4.dim("Duration:")} ${durationText}`);
  }
  return segments.join(` ${chalk4.dim("|")} `);
}
function formatStatus(agent) {
  switch (agent.status) {
    case "running":
      return chalk4.green("Running");
    case "completed":
      return chalk4.green("Completed");
    case "failed":
      return chalk4.red("Failed");
    default:
      return chalk4.gray(agent.status);
  }
}
function getStatusIcon(status) {
  switch (status) {
    case "running":
      return chalk4.green("\u27F3");
    case "completed":
      return chalk4.green("\u2713");
    case "failed":
      return chalk4.red("\u2717");
    default:
      return chalk4.gray("\u25CB");
  }
}
function formatAgentDuration(agent) {
  if (agent.status === "running") {
    return formatDuration(Date.now() - new Date(agent.startTime).getTime());
  }
  if (typeof agent.duration === "number") {
    return formatDuration(agent.duration);
  }
  if (agent.endTime) {
    const start = new Date(agent.startTime).getTime();
    const end = new Date(agent.endTime).getTime();
    if (!Number.isNaN(start) && !Number.isNaN(end) && end >= start) {
      return formatDuration(end - start);
    }
  }
  return "N/A";
}
function formatRunRange(agent) {
  const start = formatTimestamp(agent.startTime);
  const end = agent.endTime ? formatTimestamp(agent.endTime) : "N/A";
  return `${start} \u2192 ${end}`;
}
function formatTimestamp(timestamp) {
  if (!timestamp) {
    return "N/A";
  }
  const date = new Date(timestamp);
  if (Number.isNaN(date.getTime())) {
    return "N/A";
  }
  return date.toLocaleString();
}
function formatDuration(ms) {
  const seconds = Math.floor(ms / 1e3);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  if (hours > 0) {
    return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
  } else if (minutes > 0) {
    return `${minutes}m ${seconds % 60}s`;
  } else {
    return `${seconds}s`;
  }
}

// src/cli/commands/agents/logs.ts
import chalk5 from "chalk";
async function showAgentLogs(agentId) {
  const monitor = AgentMonitorService.getInstance();
  const loggerService = AgentLoggerService.getInstance();
  const agent = monitor.getAgent(agentId);
  if (!agent) {
    console.error(chalk5.red(`Agent ${agentId} not found`));
    console.error(chalk5.dim('Use "codemachine agents" to see all agents'));
    process.exit(1);
  }
  console.log("");
  console.log(chalk5.bold(`Agent ${agentId} - ${agent.name}`));
  console.log(chalk5.dim("\u2500".repeat(60)));
  console.log(`${chalk5.dim("Status:")} ${getStatusWithColor(agent.status)}`);
  console.log(`${chalk5.dim("Started:")} ${new Date(agent.startTime).toLocaleString()}`);
  if (agent.endTime) {
    console.log(`${chalk5.dim("Ended:")} ${new Date(agent.endTime).toLocaleString()}`);
  }
  if (agent.duration) {
    console.log(`${chalk5.dim("Duration:")} ${formatDuration2(agent.duration)}`);
  }
  console.log(`${chalk5.dim("Prompt:")} ${agent.prompt}`);
  if (agent.telemetry) {
    console.log(chalk5.dim("Telemetry:"));
    console.log(`  ${chalk5.dim("Tokens In:")} ${agent.telemetry.tokensIn}`);
    console.log(`  ${chalk5.dim("Tokens Out:")} ${agent.telemetry.tokensOut}`);
    if (agent.telemetry.cached) {
      console.log(`  ${chalk5.dim("Cached:")} ${agent.telemetry.cached}`);
    }
    if (agent.telemetry.cost) {
      console.log(`  ${chalk5.dim("Cost:")} $${agent.telemetry.cost.toFixed(4)}`);
    }
  }
  console.log(chalk5.dim("\u2500".repeat(60)));
  console.log(chalk5.bold("Logs:"));
  console.log("");
  try {
    await loggerService.streamLogs(agentId, (chunk) => {
      process.stdout.write(chunk);
    });
  } catch (error2) {
    console.error(chalk5.red(`Error reading logs: ${error2}`));
    process.exit(1);
  }
  console.log("");
}
function getStatusWithColor(status) {
  switch (status) {
    case "running":
      return chalk5.green("Running");
    case "completed":
      return chalk5.green("Completed");
    case "failed":
      return chalk5.red("Failed");
    default:
      return chalk5.gray(status);
  }
}
function formatDuration2(ms) {
  const seconds = Math.floor(ms / 1e3);
  const minutes = Math.floor(seconds / 60);
  const hours = Math.floor(minutes / 60);
  if (hours > 0) {
    return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
  } else if (minutes > 0) {
    return `${minutes}m ${seconds % 60}s`;
  } else {
    return `${seconds}s`;
  }
}

// src/cli/commands/agents/index.ts
function createAgentsCommand() {
  const command = new Command("agents").description("Manage and monitor agents");
  command.command("list", { isDefault: true }).description("List all active and offline agents").action(() => {
    listAgents();
  });
  command.command("logs <id>").description("View logs for a specific agent").action(async (id) => {
    const agentId = parseInt(id, 10);
    if (isNaN(agentId)) {
      console.error(`Invalid agent ID: ${id}`);
      process.exit(1);
    }
    await showAgentLogs(agentId);
  });
  return command;
}

// src/cli/commands/agents/register.ts
function registerAgentsCommand(program) {
  const agentsCommand = createAgentsCommand();
  program.addCommand(agentsCommand);
}

// src/cli/controllers/keyboard-controls.ts
import { EventEmitter } from "events";

// src/cli/controllers/session-shell.ts
import { createRequire } from "module";
import { existsSync as existsSync2 } from "fs";
import { dirname as dirname2, join as join2, parse } from "path";
import { fileURLToPath as fileURLToPath2 } from "url";
import { spawn } from "child_process";
import React3 from "react";
import { render } from "ink";

// src/cli/components/SessionShell.tsx
import { useState as useState2 } from "react";
import { Box as Box2, Text as Text2 } from "ink";

// src/cli/components/SessionInput.tsx
import { useState, useEffect } from "react";
import { Box, Text, useInput } from "ink";
import TextInput from "ink-text-input";
import { jsx, jsxs } from "react/jsx-runtime";
var SessionInput = ({
  onSubmit,
  placeholder = "Type /start to see the magic",
  slashCommands
}) => {
  const [input, setInput] = useState("");
  const [showSuggestions, setShowSuggestions] = useState(false);
  const [filteredCommands, setFilteredCommands] = useState([]);
  const [selectedIndex, setSelectedIndex] = useState(0);
  useEffect(() => {
    if (input.startsWith("/")) {
      const query = input.slice(1).toLowerCase();
      const matches = slashCommands.filter(
        (cmd) => cmd.command.toLowerCase().startsWith(query)
      );
      setFilteredCommands(matches);
      setShowSuggestions(matches.length > 0);
      setSelectedIndex(0);
    } else {
      setShowSuggestions(false);
      setFilteredCommands([]);
    }
  }, [input, slashCommands]);
  useInput((input2, key) => {
    if (!showSuggestions || filteredCommands.length === 0) {
      return;
    }
    if (key.upArrow) {
      setSelectedIndex(
        (prev) => prev > 0 ? prev - 1 : filteredCommands.length - 1
      );
    } else if (key.downArrow) {
      setSelectedIndex(
        (prev) => prev < filteredCommands.length - 1 ? prev + 1 : 0
      );
    }
  });
  const handleSubmit = (value) => {
    if (showSuggestions && filteredCommands.length > 0) {
      const selected = filteredCommands[selectedIndex];
      const selectedCommand = `/${selected.command}`;
      onSubmit(selectedCommand);
      setInput("");
      setShowSuggestions(false);
      return;
    }
    if (value.trim()) {
      onSubmit(value);
      setInput("");
      setShowSuggestions(false);
    }
  };
  const handleChange = (value) => {
    setInput(value);
  };
  const maxVisibleItems = 5;
  const getVisibleCommands = () => {
    if (filteredCommands.length <= maxVisibleItems) {
      return { commands: filteredCommands, startIndex: 0 };
    }
    let startIndex = Math.max(0, selectedIndex - Math.floor(maxVisibleItems / 2));
    const endIndex = startIndex + maxVisibleItems;
    if (endIndex > filteredCommands.length) {
      startIndex = Math.max(0, filteredCommands.length - maxVisibleItems);
    }
    return {
      commands: filteredCommands.slice(startIndex, startIndex + maxVisibleItems),
      startIndex
    };
  };
  const { commands: visibleCommands, startIndex: visibleStartIndex } = getVisibleCommands();
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: "100%", children: [
    /* @__PURE__ */ jsxs(
      Box,
      {
        borderStyle: "round",
        borderColor: "cyan",
        paddingX: 1,
        width: "100%",
        children: [
          /* @__PURE__ */ jsxs(Box, { marginRight: 1, children: [
            /* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: "CODEMACHINE" }),
            /* @__PURE__ */ jsx(Text, { dimColor: true, children: " \u203A " })
          ] }),
          /* @__PURE__ */ jsx(Box, { flexGrow: 1, children: /* @__PURE__ */ jsx(
            TextInput,
            {
              value: input,
              onChange: handleChange,
              onSubmit: handleSubmit,
              placeholder,
              showCursor: true
            }
          ) })
        ]
      }
    ),
    showSuggestions && filteredCommands.length > 0 && /* @__PURE__ */ jsxs(
      Box,
      {
        flexDirection: "column",
        marginTop: 1,
        borderStyle: "round",
        borderColor: "gray",
        paddingX: 1,
        paddingY: 0,
        children: [
          /* @__PURE__ */ jsx(Box, { marginBottom: 0, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
            "\u2191\u2193 navigate \u2022 Enter to execute ",
            filteredCommands.length > maxVisibleItems && `(${selectedIndex + 1}/${filteredCommands.length})`
          ] }) }),
          visibleCommands.map((cmd, index) => {
            const actualIndex = visibleStartIndex + index;
            return /* @__PURE__ */ jsxs(Box, { marginLeft: 1, children: [
              /* @__PURE__ */ jsx(Text, { color: actualIndex === selectedIndex ? "green" : "gray", children: actualIndex === selectedIndex ? "\u203A " : "  " }),
              /* @__PURE__ */ jsxs(Text, { color: actualIndex === selectedIndex ? "cyan" : "white", children: [
                "/",
                cmd.command
              ] }),
              /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
                " - ",
                cmd.description
              ] })
            ] }, cmd.command);
          })
        ]
      }
    )
  ] });
};

// src/cli/components/SessionShell.tsx
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
var SLASH_COMMANDS = [
  { command: "start", description: "Run configured workflow queue" },
  { command: "templates", description: "List and select workflow templates" },
  { command: "login", description: "Authenticate with AI services" },
  { command: "logout", description: "Sign out of AI services" },
  { command: "version", description: "Show CLI version" },
  { command: "help", description: "Show this help" },
  { command: "exit", description: "Exit the session" }
];
var SessionShell = ({
  onCommand,
  onExit,
  projectName
}) => {
  const [messages, setMessages] = useState2([]);
  const [isProcessing, setIsProcessing] = useState2(false);
  const handleCommand = async (input) => {
    const trimmed = input.trim();
    if (!trimmed) {
      return;
    }
    setMessages([]);
    if (trimmed === "/exit" || trimmed === "/quit") {
      onExit();
      return;
    }
    setIsProcessing(true);
    try {
      await onCommand(trimmed);
    } catch (error2) {
      setMessages([{
        type: "error",
        text: error2 instanceof Error ? error2.message : String(error2)
      }]);
    } finally {
      setIsProcessing(false);
    }
  };
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", padding: 1, children: [
    /* @__PURE__ */ jsxs2(Box2, { marginBottom: 1, children: [
      /* @__PURE__ */ jsx2(Text2, { color: "cyan", bold: true, children: "CodeMachine CLI" }),
      projectName && /* @__PURE__ */ jsxs2(Fragment, { children: [
        /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2022 " }),
        /* @__PURE__ */ jsx2(Text2, { color: "white", children: projectName })
      ] })
    ] }),
    /* @__PURE__ */ jsxs2(
      Box2,
      {
        marginBottom: 1,
        paddingX: 2,
        paddingY: 1,
        borderStyle: "round",
        borderColor: "gray",
        flexDirection: "column",
        children: [
          /* @__PURE__ */ jsxs2(Text2, { color: "white", children: [
            "\u{1F680} ",
            /* @__PURE__ */ jsx2(Text2, { bold: true, children: "CodeMachine" }),
            " is an autonomous multi-agent platform"
          ] }),
          /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
            "Type ",
            /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "/start" }),
            " to begin or ",
            /* @__PURE__ */ jsx2(Text2, { color: "cyan", children: "/help" }),
            " for options"
          ] })
        ]
      }
    ),
    messages.length > 0 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", marginBottom: 1, children: messages.map((msg, index) => /* @__PURE__ */ jsx2(Box2, { children: /* @__PURE__ */ jsxs2(
      Text2,
      {
        color: msg.type === "error" ? "red" : msg.type === "success" ? "green" : "white",
        children: [
          msg.type === "error" && "\u2717 ",
          msg.type === "success" && "\u2713 ",
          msg.type === "info" && "\u2139 ",
          msg.text
        ]
      }
    ) }, index)) }),
    isProcessing && /* @__PURE__ */ jsx2(Box2, { marginBottom: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Processing..." }) }),
    !isProcessing && /* @__PURE__ */ jsx2(
      SessionInput,
      {
        onSubmit: handleCommand,
        placeholder: "Type /start to see the magic",
        slashCommands: SLASH_COMMANDS
      }
    ),
    /* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Press Ctrl+C to exit at any time" }) })
  ] });
};

// src/cli/controllers/session-shell.ts
function runCliCommand(args) {
  return new Promise((resolve6) => {
    const child = spawn("codemachine", args, {
      stdio: "inherit",
      // Pass stdin/stdout/stderr directly to the child
      shell: false
    });
    child.on("close", (code) => {
      resolve6(code ?? 0);
    });
    child.on("error", (error2) => {
      console.error(`Failed to start command: ${error2.message}`);
      resolve6(1);
    });
  });
}
async function runSessionShell(options) {
  const { cwd, specificationPath, specDisplayPath } = options;
  const showIntro = options.showIntro ?? true;
  if (showIntro) {
    const menu = await renderMainMenu(specDisplayPath);
    await renderTypewriter({ text: menu + "\n" });
  }
  const require2 = createRequire(import.meta.url);
  const packageJsonPath = findPackageJson(import.meta.url);
  const pkg = require2(packageJsonPath);
  let inkInstance = null;
  const handleCommand = async (command) => {
    if (command === "/start") {
      if (inkInstance) {
        inkInstance.unmount();
        inkInstance = null;
      }
      try {
        clearTerminal();
        debug(`Launching workflow queue (spec=${specificationPath})`);
        await runWorkflowQueue({ cwd, specificationPath });
      } catch (error2) {
        console.error(error2 instanceof Error ? error2.message : String(error2));
        process.exit(1);
      }
    } else if (command === "/help" || command === "/h") {
      console.log([
        "",
        "Available commands:",
        "  /start                Run configured workflow queue",
        "  /templates            List and select workflow templates",
        "  /login                Authenticate with AI services",
        "  /logout               Sign out of AI services",
        "  /version              Show CLI version",
        "  /help                 Show this help",
        "  /exit                 Exit the session",
        ""
      ].join("\n"));
    } else if (command === "/version") {
      console.log(`CodeMachine v${pkg.version}`);
    } else if (command === "/login") {
      if (inkInstance) {
        inkInstance.unmount();
        inkInstance = null;
      }
      clearTerminal();
      await runCliCommand(["auth", "login"]);
      startInkUI();
    } else if (command === "/logout") {
      if (inkInstance) {
        inkInstance.unmount();
        inkInstance = null;
      }
      clearTerminal();
      await runCliCommand(["auth", "logout"]);
      startInkUI();
    } else if (command === "/templates" || command === "/template") {
      if (inkInstance) {
        inkInstance.unmount();
        inkInstance = null;
      }
      clearTerminal();
      await runCliCommand(["templates"]);
      startInkUI();
    } else {
      throw new Error(`Unrecognized command: ${command}. Type /help for options.`);
    }
  };
  const handleExit = () => {
    if (inkInstance) {
      inkInstance.unmount();
      inkInstance = null;
    }
    process.exit(0);
  };
  const startInkUI = () => {
    if (inkInstance) {
      inkInstance.unmount();
      inkInstance = null;
    }
    inkInstance = render(
      React3.createElement(SessionShell, {
        onCommand: handleCommand,
        onExit: handleExit,
        projectName: specDisplayPath
      }),
      {
        exitOnCtrlC: true
      }
    );
  };
  startInkUI();
}
function findPackageJson(moduleUrl) {
  let currentDir = dirname2(fileURLToPath2(moduleUrl));
  const { root } = parse(currentDir);
  while (true) {
    const candidate = join2(currentDir, "package.json");
    if (existsSync2(candidate)) return candidate;
    if (currentDir === root) break;
    currentDir = dirname2(currentDir);
  }
  throw new Error("Unable to locate package.json from CLI module");
}

// src/cli/program.ts
import { createRequire as createRequire2 } from "module";
import { existsSync as existsSync3 } from "fs";
import { dirname as dirname3, join as join3, parse as parse2 } from "path";
import { fileURLToPath as fileURLToPath3 } from "url";
async function registerCli(program) {
  const packageJsonPath = findPackageJson2(import.meta.url);
  program.command("version").description("Display CLI version").action(() => {
    const require2 = createRequire2(import.meta.url);
    const pkg = require2(packageJsonPath);
    console.log(`CodeMachine v${pkg.version}`);
  });
  program.command("mcp").description("Model Context Protocol integration stubs").action(() => {
    console.log("Model Context Protocol support coming soon");
  });
  registerStartCommand(program);
  registerTemplatesCommand(program);
  registerAuthCommands(program);
  registerAgentsCommand(program);
  await registerRunCommand(program);
  await registerStepCommand(program);
}
function findPackageJson2(moduleUrl) {
  let currentDir = dirname3(fileURLToPath3(moduleUrl));
  const { root } = parse2(currentDir);
  while (true) {
    const candidate = join3(currentDir, "package.json");
    if (existsSync3(candidate)) return candidate;
    if (currentDir === root) break;
    currentDir = dirname3(currentDir);
  }
  throw new Error("Unable to locate package.json from CLI module");
}

// src/runtime/cli-setup.ts
var DEFAULT_SPEC_PATH2 = ".codemachine/inputs/specifications.md";
var packageRoot2 = (() => {
  const moduleDir = path5.dirname(fileURLToPath4(import.meta.url));
  let current = moduleDir;
  while (true) {
    if (existsSync4(path5.join(current, "package.json"))) return current;
    const parent = path5.dirname(current);
    if (parent === current) return moduleDir;
    current = parent;
  }
})();
var templatesDir2 = path5.resolve(packageRoot2, "templates", "workflows");
async function runCodemachineCli(argv = process.argv) {
  const program = new Command2().name("codemachine").description("Codemachine multi-agent CLI orchestrator").option("-d, --dir <path>", "Target workspace directory", process.cwd()).option("--spec <path>", "Path to the planning specification file", DEFAULT_SPEC_PATH2).action(async (options) => {
    const cwd = process.env.CODEMACHINE_CWD || process.cwd();
    const specDisplayPath = options.spec ?? DEFAULT_SPEC_PATH2;
    const specificationPath = path5.resolve(cwd, specDisplayPath);
    const { mainMenuDisplayed } = await runStartupFlow(specDisplayPath);
    await runSessionShell({ cwd, specificationPath, specDisplayPath, showIntro: !mainMenuDisplayed });
  });
  program.hook("preAction", async () => {
    const { dir } = typeof program.optsWithGlobals === "function" ? program.optsWithGlobals() : program.opts();
    const cwd = dir || process.cwd();
    process.env.CODEMACHINE_CWD = cwd;
    const engines = registry.getAll();
    for (const engine of engines) {
      if (engine.syncConfig) {
        await engine.syncConfig();
      }
    }
    const cmRoot = path5.join(cwd, ".codemachine");
    if (!existsSync4(cmRoot)) {
      const defaultTemplate = path5.join(templatesDir2, "codemachine.workflow.js");
      await bootstrapWorkspace({ cwd, templatePath: defaultTemplate });
    }
  });
  await registerCli(program);
  await program.parseAsync(argv);
}
var shouldRunCli = (() => {
  const entry = process.argv[1];
  if (!entry) return false;
  try {
    const resolvedEntry = realpathSync(entry);
    const modulePath = realpathSync(fileURLToPath4(import.meta.url));
    return resolvedEntry === modulePath;
  } catch {
    return entry.includes("index");
  }
})();
if (shouldRunCli) {
  runCodemachineCli().catch((error2) => {
    console.error(error2);
    process.exitCode = 1;
  });
}
export {
  AGENT_MODULE_FILENAMES,
  CLI_BUNDLE_DIR,
  CLI_PACKAGE_ROOT,
  CLI_ROOT_CANDIDATES,
  SHOULD_DEBUG_BOOTSTRAP,
  bootstrapWorkspace,
  copyPromptFile,
  debugLog,
  ensureDir,
  ensurePromptFile,
  ensureSpecificationsTemplate,
  loadAgents,
  mirrorAgentsToJson,
  runCodemachineCli,
  runStartupFlow,
  slugify,
  validateSpecification,
  writeFileIfChanged
};
//# sourceMappingURL=index.js.map