"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var index_exports = {};
__export(index_exports, {
  AdapterRegistry: () => AdapterRegistry,
  BaseCLIAdapter: () => BaseCLIAdapter,
  createAdapter: () => createAdapter,
  sanitizeOutput: () => sanitizeOutput
});
module.exports = __toCommonJS(index_exports);

// src/base-adapter.ts
var import_node_child_process = require("child_process");
var BaseCLIAdapter = class {
  /**
   * Auto-response rules for handling known blocking prompts.
   * Subclasses should override this to add CLI-specific rules.
   */
  autoResponseRules = [];
  /**
   * Whether this CLI uses TUI menus requiring arrow-key navigation.
   * Defaults to false; coding agent adapters override to true.
   */
  usesTuiMenus = false;
  /**
   * Default exit detection - look for common exit patterns
   */
  detectExit(output) {
    if (output.includes("Process exited with code")) {
      const match = output.match(/Process exited with code (\d+)/);
      return {
        exited: true,
        code: match ? parseInt(match[1], 10) : 1
      };
    }
    if (output.includes("Command not found") || output.includes("command not found")) {
      return {
        exited: true,
        code: 127,
        error: "Command not found"
      };
    }
    return { exited: false };
  }
  /**
   * Default blocking prompt detection - looks for common prompt patterns.
   * Subclasses should override for CLI-specific detection.
   */
  detectBlockingPrompt(output) {
    let stripped = this.stripAnsi(output);
    stripped = stripped.replace(
      /[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❯❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⏺←→↑↓]/g,
      " "
    );
    stripped = stripped.replace(/ {2,}/g, " ");
    const loginDetection = this.detectLogin(output);
    if (loginDetection.required) {
      return {
        detected: true,
        type: "login",
        prompt: loginDetection.instructions,
        url: loginDetection.url,
        canAutoRespond: false,
        instructions: loginDetection.instructions
      };
    }
    if (/update (available|now|ready)/i.test(stripped) && /\[y\/n\]/i.test(stripped)) {
      return {
        detected: true,
        type: "update",
        prompt: "Update available",
        options: ["y", "n"],
        suggestedResponse: "n",
        canAutoRespond: true,
        instructions: "CLI update available - auto-declining to continue"
      };
    }
    if (/accept.*(terms|license|agreement)/i.test(stripped) && /\[y\/n\]/i.test(stripped)) {
      return {
        detected: true,
        type: "tos",
        prompt: "Terms/license acceptance required",
        options: ["y", "n"],
        canAutoRespond: false,
        instructions: "Please accept the terms of service manually"
      };
    }
    if (/choose.*model|select.*model|which model/i.test(stripped)) {
      return {
        detected: true,
        type: "model_select",
        prompt: "Model selection required",
        canAutoRespond: false,
        instructions: "Please select a model"
      };
    }
    if (/choose.*(project|workspace)|select.*(project|workspace)/i.test(stripped)) {
      return {
        detected: true,
        type: "project_select",
        prompt: "Project/workspace selection required",
        canAutoRespond: false,
        instructions: "Please select a project or workspace"
      };
    }
    if (/\[y\/n\]|\(y\/n\)|\[Y\/n\]|\[y\/N\]|\(Y\)es\/\(N\)o|Yes\/No\??/i.test(
      stripped
    )) {
      return {
        detected: true,
        type: "unknown",
        prompt: stripped.slice(-200),
        options: ["y", "n"],
        canAutoRespond: false,
        instructions: "Confirmation prompt detected"
      };
    }
    if (/^\s*[›>]?\s*[1-9]\.\s+\w+/m.test(stripped) && /\?\s*$/m.test(stripped)) {
      const optionMatches = stripped.match(/[›>]?\s*([1-9])\.\s+([^\n]+)/g);
      const options = optionMatches ? optionMatches.map((m) => m.replace(/^[›>\s]*/, "").trim()) : [];
      return {
        detected: true,
        type: "unknown",
        prompt: stripped.slice(-300),
        options: options.length > 0 ? options : void 0,
        canAutoRespond: false,
        instructions: "Menu selection prompt detected"
      };
    }
    if (/press enter|hit enter|enter to (confirm|continue|proceed)|press return/i.test(
      stripped
    )) {
      return {
        detected: true,
        type: "unknown",
        prompt: stripped.slice(-200),
        suggestedResponse: "\n",
        canAutoRespond: false,
        instructions: "Enter/confirm prompt detected"
      };
    }
    if (/trust|allow|permission|grant access/i.test(stripped) && /\?\s*$/m.test(stripped)) {
      return {
        detected: true,
        type: "permission",
        prompt: stripped.slice(-200),
        canAutoRespond: false,
        instructions: "Permission/trust prompt detected"
      };
    }
    const lines = stripped.split("\n").filter((l) => l.trim());
    const lastLine = lines[lines.length - 1] || "";
    if (/\?\s*$/.test(lastLine) && lastLine.length < 200) {
      return {
        detected: true,
        type: "unknown",
        prompt: lastLine.trim(),
        canAutoRespond: false,
        instructions: "Question prompt detected"
      };
    }
    return { detected: false };
  }
  /**
   * Default task completion detection — delegates to detectReady().
   */
  detectTaskComplete(output) {
    return this.detectReady(output);
  }
  /**
   * Default input formatting — strip ANSI escape codes from input text.
   * Newlines are preserved (pty-manager handles them natively).
   * Transport-specific formatting (e.g., tmux newline collapsing) is
   * handled by the transport layer, not the adapter.
   */
  formatInput(message) {
    return message.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, "").replace(/\\u001b\[[0-9;]*[a-zA-Z]/g, "").trim();
  }
  /**
   * Validate CLI installation by running --version or --help
   */
  async validateInstallation() {
    return new Promise((resolve) => {
      const command = this.getCommand();
      try {
        const proc = (0, import_node_child_process.spawn)(command, ["--version"], {
          shell: true,
          timeout: 5e3
        });
        let output = "";
        proc.stdout?.on("data", (data) => {
          output += data.toString();
        });
        proc.stderr?.on("data", (data) => {
          output += data.toString();
        });
        proc.on("close", (code) => {
          if (code === 0) {
            const versionMatch = output.match(/(\d+\.\d+\.\d+)/);
            resolve({
              installed: true,
              version: versionMatch ? versionMatch[1] : void 0
            });
          } else {
            resolve({
              installed: false,
              error: `Command exited with code ${code}`
            });
          }
        });
        proc.on("error", (err) => {
          resolve({
            installed: false,
            error: err.message
          });
        });
      } catch (err) {
        resolve({
          installed: false,
          error: err instanceof Error ? err.message : "Unknown error"
        });
      }
    });
  }
  /**
   * Helper to check if output contains a question
   */
  containsQuestion(output) {
    const questionPatterns = [
      /\?$/m,
      /would you like/i,
      /do you want/i,
      /should I/i,
      /shall I/i,
      /please (choose|select|confirm)/i,
      /\(y\/n\)/i,
      /\[y\/N\]/i,
      /\[Y\/n\]/i
    ];
    return questionPatterns.some((pattern) => pattern.test(output));
  }
  /**
   * Helper to strip ANSI escape codes from output
   */
  stripAnsi(str) {
    const withSpaces = str.replace(/\x1b\[\d*C/g, " ");
    const withoutOsc = withSpaces.replace(
      /\x1b\](?:[^\x07\x1b]|\x1b[^\\])*(?:\x07|\x1b\\)/g,
      ""
    );
    const withoutDcs = withoutOsc.replace(
      /\x1bP(?:[^\x1b]|\x1b[^\\])*\x1b\\/g,
      ""
    );
    return withoutDcs.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
  }
};

// src/adapter-factory.ts
function createAdapter(config) {
  return new ConfiguredAdapter(config);
}
var ConfiguredAdapter = class extends BaseCLIAdapter {
  constructor(adapterConfig) {
    super();
    this.adapterConfig = adapterConfig;
    this.adapterType = adapterConfig.command.replace(/[^a-zA-Z0-9]/g, "-");
    this.displayName = adapterConfig.command;
    this.autoResponseRules = this.buildAutoResponseRules();
  }
  adapterType;
  displayName;
  autoResponseRules;
  buildAutoResponseRules() {
    if (!this.adapterConfig.blockingPrompts) {
      return [];
    }
    return this.adapterConfig.blockingPrompts.filter((p) => p.autoResponse !== void 0).map((p) => ({
      pattern: p.pattern,
      type: p.type,
      response: p.autoResponse,
      description: p.description || `Auto-respond to ${p.type} prompt`,
      safe: p.safe !== false
    }));
  }
  getCommand() {
    return this.adapterConfig.command;
  }
  getArgs(config) {
    if (typeof this.adapterConfig.args === "function") {
      return this.adapterConfig.args(config);
    }
    return this.adapterConfig.args || [];
  }
  getEnv(config) {
    if (typeof this.adapterConfig.env === "function") {
      return this.adapterConfig.env(config);
    }
    return this.adapterConfig.env || {};
  }
  detectLogin(output) {
    if (!this.adapterConfig.loginDetection) {
      return { required: false };
    }
    const { patterns, extractUrl, extractInstructions } = this.adapterConfig.loginDetection;
    const stripped = this.stripAnsi(output);
    for (const pattern of patterns) {
      if (pattern.test(stripped)) {
        return {
          required: true,
          type: "browser",
          url: extractUrl?.(stripped) || void 0,
          instructions: extractInstructions?.(stripped) || "Authentication required"
        };
      }
    }
    return { required: false };
  }
  detectBlockingPrompt(output) {
    if (this.adapterConfig.blockingPrompts) {
      const stripped = this.stripAnsi(output);
      for (const prompt of this.adapterConfig.blockingPrompts) {
        if (prompt.pattern.test(stripped)) {
          return {
            detected: true,
            type: prompt.type,
            prompt: stripped.slice(-200),
            suggestedResponse: prompt.autoResponse,
            canAutoRespond: prompt.autoResponse !== void 0 && prompt.safe !== false,
            instructions: prompt.description
          };
        }
      }
    }
    return super.detectBlockingPrompt(output);
  }
  detectReady(output) {
    if (!this.adapterConfig.readyIndicators || this.adapterConfig.readyIndicators.length === 0) {
      return output.length > 10;
    }
    const stripped = this.stripAnsi(output);
    return this.adapterConfig.readyIndicators.some(
      (pattern) => pattern.test(stripped)
    );
  }
  detectExit(output) {
    if (this.adapterConfig.exitIndicators) {
      for (const indicator of this.adapterConfig.exitIndicators) {
        const match = output.match(indicator.pattern);
        if (match) {
          const code = indicator.codeExtractor?.(match) ?? 1;
          return { exited: true, code };
        }
      }
    }
    return super.detectExit(output);
  }
  parseOutput(output) {
    if (this.adapterConfig.parseOutput) {
      return this.adapterConfig.parseOutput(output);
    }
    const cleaned = this.stripAnsi(output).trim();
    if (!cleaned) return null;
    return {
      type: "response",
      content: cleaned,
      isComplete: true,
      isQuestion: this.containsQuestion(cleaned)
    };
  }
  formatInput(message) {
    if (this.adapterConfig.formatInput) {
      return this.adapterConfig.formatInput(message);
    }
    return message;
  }
  getPromptPattern() {
    return this.adapterConfig.promptPattern || /[$#>]\s*$/m;
  }
};

// src/adapter-registry.ts
var AdapterRegistry = class {
  adapters = /* @__PURE__ */ new Map();
  /**
   * Register an adapter
   */
  register(adapter) {
    this.adapters.set(adapter.adapterType, adapter);
  }
  /**
   * Get adapter for type
   */
  get(adapterType) {
    return this.adapters.get(adapterType);
  }
  /**
   * Check if adapter exists for type
   */
  has(adapterType) {
    return this.adapters.has(adapterType);
  }
  /**
   * Unregister an adapter
   */
  unregister(adapterType) {
    return this.adapters.delete(adapterType);
  }
  /**
   * List all registered adapter types
   */
  list() {
    return Array.from(this.adapters.keys());
  }
  /**
   * Get all adapters
   */
  all() {
    return Array.from(this.adapters.values());
  }
  /**
   * Clear all adapters
   */
  clear() {
    this.adapters.clear();
  }
};

// src/output-sanitizer.ts
var DEFAULT_OPTIONS = {
  stripAnsi: true,
  stripTuiChrome: true,
  stripOsc: true,
  collapseBlankLines: true,
  maxLength: 0
};
function sanitizeOutput(raw, options) {
  const opts = { ...DEFAULT_OPTIONS, ...options };
  let result = raw;
  if (opts.stripOsc) {
    result = result.replace(
      /\x1b\](?:[^\x07\x1b]|\x1b[^\\])*(?:\x07|\x1b\\)/g,
      ""
    );
    result = result.replace(/\x1bP(?:[^\x1b]|\x1b[^\\])*\x1b\\/g, "");
  }
  if (opts.stripAnsi) {
    result = result.replace(/\x1b\[\d*[CDABGdEF]/g, " ");
    result = result.replace(/\x1b\[\d*(?:;\d+)?[Hf]/g, " ");
    result = result.replace(/\x1b\[\d*[JK]/g, " ");
    result = result.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
    result = result.replace(/\\u001b\[[0-9;]*[a-zA-Z]/g, "");
    result = result.replace(/[\x00-\x08\x0b-\x1f\x7f]/g, "");
  }
  if (opts.stripTuiChrome) {
    result = result.replace(
      /[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❯❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⣾⣽⣻⢿⡿⣟⣯⣷✻✶✳✢⏺←→↑↓⬆⬇◆◇▪▫■□▲△▼▽◈⟨⟩⌘⏎⏏⌫⌦⇧⇪⌥▐▛▜▝▘]/g,
      " "
    );
    result = result.replace(/\xa0/g, " ");
    result = result.replace(/ {2,}/g, " ");
  }
  if (opts.collapseBlankLines) {
    result = result.replace(/\n{3,}/g, "\n\n");
  }
  if (opts.maxLength > 0 && result.length > opts.maxLength) {
    result = result.slice(-opts.maxLength);
  }
  return result.trim();
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  AdapterRegistry,
  BaseCLIAdapter,
  createAdapter,
  sanitizeOutput
});
//# sourceMappingURL=index.js.map