#!/usr/bin/env node
import { spawn, execSync, execFileSync } from "child_process";
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
import { program } from "commander";
import { v4 as uuidv4 } from "uuid";
import chalk from "chalk";
import { initializeTracing, trace } from "../core/trace/index.js";
class ClaudeSM {
  config;
  stackmemoryPath;
  worktreeScriptPath;
  claudeConfigDir;
  constructor() {
    this.config = {
      instanceId: this.generateInstanceId(),
      useSandbox: false,
      useChrome: false,
      useWorktree: false,
      contextEnabled: true,
      tracingEnabled: true,
      // Enable tracing by default for claude-sm
      verboseTracing: false
    };
    this.stackmemoryPath = this.findStackMemory();
    this.worktreeScriptPath = path.join(
      __dirname,
      "../../scripts/claude-worktree-manager.sh"
    );
    this.claudeConfigDir = path.join(os.homedir(), ".claude");
    if (!fs.existsSync(this.claudeConfigDir)) {
      fs.mkdirSync(this.claudeConfigDir, { recursive: true });
    }
  }
  generateInstanceId() {
    return uuidv4().substring(0, 8);
  }
  findStackMemory() {
    const possiblePaths = [
      path.join(os.homedir(), ".stackmemory", "bin", "stackmemory"),
      "/usr/local/bin/stackmemory",
      "/opt/homebrew/bin/stackmemory",
      "stackmemory"
      // Rely on PATH
    ];
    for (const smPath of possiblePaths) {
      try {
        execFileSync("which", [smPath], { stdio: "ignore" });
        return smPath;
      } catch {
      }
    }
    return "stackmemory";
  }
  isGitRepo() {
    try {
      execSync("git rev-parse --git-dir", { stdio: "ignore" });
      return true;
    } catch {
      return false;
    }
  }
  getCurrentBranch() {
    try {
      return execSync("git rev-parse --abbrev-ref HEAD", {
        encoding: "utf8"
      }).trim();
    } catch {
      return "main";
    }
  }
  hasUncommittedChanges() {
    try {
      const status = execSync("git status --porcelain", { encoding: "utf8" });
      return status.length > 0;
    } catch {
      return false;
    }
  }
  setupWorktree() {
    if (!this.config.useWorktree || !this.isGitRepo()) {
      return null;
    }
    console.log(chalk.blue("\u{1F333} Setting up isolated worktree..."));
    const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
    const branch = this.config.branch || `claude-${this.config.task || "work"}-${timestamp}-${this.config.instanceId}`;
    const repoName = path.basename(process.cwd());
    const worktreePath = path.join(
      path.dirname(process.cwd()),
      `${repoName}--${branch}`
    );
    try {
      const flags = [];
      if (this.config.useSandbox) flags.push("--sandbox");
      if (this.config.useChrome) flags.push("--chrome");
      const cmd = `git worktree add -b "${branch}" "${worktreePath}"`;
      execSync(cmd, { stdio: "inherit" });
      console.log(chalk.green(`\u2705 Worktree created: ${worktreePath}`));
      console.log(chalk.gray(`   Branch: ${branch}`));
      const configPath = path.join(worktreePath, ".claude-instance.json");
      const configData = {
        instanceId: this.config.instanceId,
        worktreePath,
        branch,
        task: this.config.task,
        sandboxEnabled: this.config.useSandbox,
        chromeEnabled: this.config.useChrome,
        created: (/* @__PURE__ */ new Date()).toISOString(),
        parentRepo: process.cwd()
      };
      fs.writeFileSync(configPath, JSON.stringify(configData, null, 2));
      const envFiles = [".env", ".env.local", ".mise.toml", ".tool-versions"];
      for (const file of envFiles) {
        const srcPath = path.join(process.cwd(), file);
        if (fs.existsSync(srcPath)) {
          fs.copyFileSync(srcPath, path.join(worktreePath, file));
        }
      }
      return worktreePath;
    } catch (err) {
      console.error(chalk.red("\u274C Failed to create worktree:"), err);
      return null;
    }
  }
  saveContext(message, metadata = {}) {
    if (!this.config.contextEnabled) return;
    try {
      const contextData = {
        message,
        metadata: {
          ...metadata,
          instanceId: this.config.instanceId,
          worktree: this.config.worktreePath,
          timestamp: (/* @__PURE__ */ new Date()).toISOString()
        }
      };
      const cmd = `${this.stackmemoryPath} context save --json '${JSON.stringify(contextData)}'`;
      execSync(cmd, { stdio: "ignore" });
    } catch {
    }
  }
  loadContext() {
    if (!this.config.contextEnabled) return;
    try {
      console.log(chalk.blue("\u{1F4DA} Loading previous context..."));
      const cmd = `${this.stackmemoryPath} context list --limit 5 --format json`;
      const output = execSync(cmd, { encoding: "utf8" });
      const contexts = JSON.parse(output);
      if (contexts.length > 0) {
        console.log(chalk.gray("Recent context loaded:"));
        contexts.forEach(
          (ctx) => {
            console.log(
              chalk.gray(`  - ${ctx.message} (${ctx.metadata?.timestamp})`)
            );
          }
        );
      }
    } catch {
    }
  }
  detectMultipleInstances() {
    try {
      const lockDir = path.join(process.cwd(), ".claude-worktree-locks");
      if (!fs.existsSync(lockDir)) return false;
      const locks = fs.readdirSync(lockDir).filter((f) => f.endsWith(".lock"));
      const activeLocks = locks.filter((lockFile) => {
        const lockPath = path.join(lockDir, lockFile);
        const lockData = JSON.parse(fs.readFileSync(lockPath, "utf8"));
        const lockAge = Date.now() - new Date(lockData.created).getTime();
        return lockAge < 24 * 60 * 60 * 1e3;
      });
      return activeLocks.length > 0;
    } catch {
      return false;
    }
  }
  suggestWorktreeMode() {
    if (this.hasUncommittedChanges()) {
      console.log(chalk.yellow("\u26A0\uFE0F  Uncommitted changes detected"));
      console.log(
        chalk.gray("   Consider using --worktree to work in isolation")
      );
    }
    if (this.detectMultipleInstances()) {
      console.log(chalk.yellow("\u26A0\uFE0F  Other Claude instances detected"));
      console.log(
        chalk.gray("   Using --worktree is recommended to avoid conflicts")
      );
    }
  }
  async run(args) {
    const claudeArgs = [];
    let i = 0;
    while (i < args.length) {
      const arg = args[i];
      switch (arg) {
        case "--worktree":
        case "-w":
          this.config.useWorktree = true;
          break;
        case "--sandbox":
        case "-s":
          this.config.useSandbox = true;
          claudeArgs.push("--sandbox");
          break;
        case "--chrome":
        case "-c":
          this.config.useChrome = true;
          claudeArgs.push("--chrome");
          break;
        case "--no-context":
          this.config.contextEnabled = false;
          break;
        case "--no-trace":
          this.config.tracingEnabled = false;
          break;
        case "--verbose-trace":
          this.config.verboseTracing = true;
          break;
        case "--branch":
        case "-b":
          i++;
          this.config.branch = args[i];
          break;
        case "--task":
        case "-t":
          i++;
          this.config.task = args[i];
          break;
        case "--auto":
        case "-a":
          if (this.isGitRepo()) {
            this.config.useWorktree = this.hasUncommittedChanges() || this.detectMultipleInstances();
          }
          break;
        default:
          claudeArgs.push(arg);
      }
      i++;
    }
    if (this.config.tracingEnabled) {
      process.env["DEBUG_TRACE"] = "true";
      process.env["STACKMEMORY_DEBUG"] = "true";
      process.env["TRACE_OUTPUT"] = "file";
      process.env["TRACE_MASK_SENSITIVE"] = "true";
      if (this.config.verboseTracing) {
        process.env["TRACE_VERBOSITY"] = "full";
        process.env["TRACE_PARAMS"] = "true";
        process.env["TRACE_RESULTS"] = "true";
        process.env["TRACE_MEMORY"] = "true";
      } else {
        process.env["TRACE_VERBOSITY"] = "summary";
        process.env["TRACE_PARAMS"] = "true";
        process.env["TRACE_RESULTS"] = "false";
      }
      initializeTracing();
      trace.command(
        "claude-sm",
        {
          instanceId: this.config.instanceId,
          worktree: this.config.useWorktree,
          sandbox: this.config.useSandbox,
          task: this.config.task
        },
        async () => {
        }
      );
    }
    console.log(chalk.blue("\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\u2557"));
    console.log(chalk.blue("\u2551     Claude + StackMemory + Worktree   \u2551"));
    console.log(chalk.blue("\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\u255D"));
    console.log();
    if (this.isGitRepo()) {
      const branch = this.getCurrentBranch();
      console.log(chalk.gray(`\u{1F4CD} Current branch: ${branch}`));
      if (!this.config.useWorktree) {
        this.suggestWorktreeMode();
      }
    }
    if (this.config.useWorktree) {
      const worktreePath = this.setupWorktree();
      if (worktreePath) {
        this.config.worktreePath = worktreePath;
        process.chdir(worktreePath);
        this.saveContext("Created worktree for Claude instance", {
          action: "worktree_created",
          path: worktreePath,
          branch: this.config.branch
        });
      }
    }
    this.loadContext();
    process.env["CLAUDE_INSTANCE_ID"] = this.config.instanceId;
    if (this.config.worktreePath) {
      process.env["CLAUDE_WORKTREE_PATH"] = this.config.worktreePath;
    }
    console.log(chalk.gray(`\u{1F916} Instance ID: ${this.config.instanceId}`));
    console.log(chalk.gray(`\u{1F4C1} Working in: ${process.cwd()}`));
    if (this.config.useSandbox) {
      console.log(chalk.yellow("\u{1F512} Sandbox mode enabled"));
    }
    if (this.config.useChrome) {
      console.log(chalk.yellow("\u{1F310} Chrome automation enabled"));
    }
    if (this.config.tracingEnabled) {
      console.log(
        chalk.gray(`\u{1F50D} Debug tracing enabled (logs to ~/.stackmemory/traces/)`)
      );
      if (this.config.verboseTracing) {
        console.log(
          chalk.gray(`   Verbose mode: capturing all execution details`)
        );
      }
    }
    console.log();
    console.log(chalk.gray("Starting Claude..."));
    console.log(chalk.gray("\u2500".repeat(42)));
    const claude = spawn("claude", claudeArgs, {
      stdio: "inherit",
      env: process.env
    });
    claude.on("exit", (code) => {
      this.saveContext("Claude session ended", {
        action: "session_end",
        exitCode: code
      });
      if (this.config.tracingEnabled) {
        const summary = trace.getExecutionSummary();
        console.log();
        console.log(chalk.gray("\u2500".repeat(42)));
        console.log(chalk.blue("Debug Trace Summary:"));
        console.log(chalk.gray(summary));
      }
      if (this.config.worktreePath) {
        console.log();
        console.log(chalk.gray("\u2500".repeat(42)));
        console.log(chalk.blue("Session ended in worktree:"));
        console.log(chalk.gray(`  ${this.config.worktreePath}`));
        console.log();
        console.log(chalk.gray("To remove worktree: gd_claude"));
        console.log(chalk.gray("To merge to main: cwm"));
      }
      process.exit(code || 0);
    });
    process.on("SIGINT", () => {
      this.saveContext("Claude session interrupted", {
        action: "session_interrupt"
      });
      claude.kill("SIGINT");
    });
    process.on("SIGTERM", () => {
      this.saveContext("Claude session terminated", {
        action: "session_terminate"
      });
      claude.kill("SIGTERM");
    });
  }
}
program.name("claude-sm").description("Claude with StackMemory context and worktree isolation").version("1.0.0").option("-w, --worktree", "Create isolated worktree for this instance").option("-s, --sandbox", "Enable sandbox mode (file/network restrictions)").option("-c, --chrome", "Enable Chrome automation").option("-a, --auto", "Automatically detect and apply best settings").option("-b, --branch <name>", "Specify branch name for worktree").option("-t, --task <desc>", "Task description for context").option("--no-context", "Disable StackMemory context integration").option("--no-trace", "Disable debug tracing (enabled by default)").option("--verbose-trace", "Enable verbose debug tracing with full details").helpOption("-h, --help", "Display help").allowUnknownOption(true).action(async (_options) => {
  const claudeSM = new ClaudeSM();
  const args = process.argv.slice(2);
  await claudeSM.run(args);
});
if (require.main === module) {
  program.parse(process.argv);
}
//# sourceMappingURL=claude-sm.js.map
