#!/usr/bin/env node
import {
  getErrnoCode,
  getErrorMessage,
  probeProcess,
  unlinkIfPresent
} from "./chunk-NSTB3QRJ.js";
import {
  daemonRelayArgs,
  setDesiredDaemonRelay
} from "./chunk-3HJM2NFD.js";
import {
  spawnScript
} from "./chunk-IHUQNJF6.js";
import {
  createIpcReader,
  serializeIpc
} from "./chunk-OU3TG45P.js";
import {
  CONFIG_PATH,
  PID_PATH,
  PROFILE_NAME,
  SERVICE_LOG_PATH,
  SOCK_PATH,
  STOPPED_PATH,
  ensureProfileWorkspace,
  initWorkspace,
  isInitialized
} from "./chunk-7RSBFN2G.js";

// src/index.ts
import { existsSync, readFileSync, writeFileSync } from "fs";
import { connect } from "net";
import { setTimeout as sleep } from "timers/promises";
import { fileURLToPath } from "url";
import { dirname, join } from "path";
import { Command } from "commander";

// src/cli-args.ts
function normalizeCliArgs(args) {
  const normalized = [...args];
  while (normalized[0] === "--") {
    normalized.shift();
  }
  return normalized;
}
function stripProxyProfileArgs(args) {
  const result = [];
  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    if (arg === "claude" || arg === "codex") {
      result.push(...args.slice(i));
      break;
    }
    if (arg === "--profile") {
      i++;
      continue;
    }
    if (arg.startsWith("--profile=")) {
      continue;
    }
    result.push(arg);
  }
  return result;
}
function extractAgentInvocation(args) {
  const [agent, ...providerArgs] = args;
  if (agent !== "claude" && agent !== "codex") {
    throw new Error(
      'Missing Agent CLI. Use "dev-anywhere claude ..." or "dev-anywhere codex ...".'
    );
  }
  return { provider: agent, args: providerArgs };
}

// src/index.ts
var __dirname = dirname(fileURLToPath(import.meta.url));
var pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
function stopService() {
  if (!existsSync(PID_PATH)) {
    console.error("Service is not running (no PID file)");
    return false;
  }
  const pid = parseInt(readFileSync(PID_PATH, "utf-8").trim(), 10);
  try {
    process.kill(pid, "SIGTERM");
    console.log(`Service stopped (PID ${pid})`);
  } catch (err) {
    const code = getErrnoCode(err);
    if (code === "ESRCH") {
      console.error(`Process ${pid} not found, cleaning up stale files`);
    } else if (code === "EPERM") {
      console.error(`Cannot stop service PID ${pid}: permission denied`);
      return false;
    } else {
      console.error(
        `Cannot stop service PID ${pid}: ${code ? `${code}: ` : ""}${getErrorMessage(err)}`
      );
      return false;
    }
  }
  unlinkIfPresent(PID_PATH);
  unlinkIfPresent(SOCK_PATH);
  writeFileSync(STOPPED_PATH, String(Date.now()));
  return true;
}
function showStatus() {
  return new Promise((resolve) => {
    let lines = 0;
    const log = (s) => {
      console.log(s);
      lines++;
    };
    if (!existsSync(PID_PATH)) {
      log(`Profile: ${PROFILE_NAME}`);
      log("Service: not running");
      resolve(lines);
      return;
    }
    const pid = parseInt(readFileSync(PID_PATH, "utf-8").trim(), 10);
    const probe = probeProcess(pid);
    if (probe.status === "not-found") {
      log("Service: dead (stale PID file)");
      resolve(lines);
      return;
    }
    log(`Profile: ${PROFILE_NAME}`);
    if (probe.status === "permission-denied") {
      log(`Service: running (PID ${pid}, permission denied while probing)`);
    } else if (probe.status === "unknown") {
      log(`Service: unknown (PID ${pid}, ${probe.code ?? "unknown"}: ${probe.message})`);
    } else {
      log(`Service: running (PID ${pid})`);
    }
    log(`Socket:  ${SOCK_PATH}`);
    log(`Log:     ${SERVICE_LOG_PATH}`);
    const sock = connect(SOCK_PATH);
    sock.on("error", (err) => {
      const code = getErrnoCode(err);
      log(`Sessions: unable to connect${code ? ` (${code})` : ""}`);
      sock.destroy();
      resolve(lines);
    });
    sock.on("connect", () => {
      createIpcReader(sock, (msg) => {
        if (msg.type === "service_status_response") {
          const config = msg.config;
          log(`Daemon:  profile ${config.profile ?? PROFILE_NAME}`);
          log(`Relay:   ${config.relayName} (${config.relayNameSource})`);
          log(`Config:  relay ${config.relayUrl ?? "(unset)"} (${config.relayUrlSource})`);
          const relay2 = msg.relay;
          if (!relay2) {
            log("Relay:   not configured");
          } else if (relay2.connected) {
            log(`Relay:   connected (proxy: ${relay2.proxyId})`);
            log(
              `         queue depth: ${relay2.queueDepth}, reconnect attempts: ${relay2.reconnectAttempt}`
            );
          } else {
            log(
              `Relay:   disconnected (proxy: ${relay2.proxyId}, reconnecting: attempt ${relay2.reconnectAttempt}, queued: ${relay2.queueDepth})`
            );
          }
          log("");
          const sessions = msg.sessions;
          if (sessions.length === 0) {
            log("Sessions: none");
          } else {
            log(`Sessions: ${sessions.length}`);
            for (const s of sessions) {
              log(`  ${s.id}  ${s.mode}  ${s.state}  worker: ${s.hasWorker ? "yes" : "no"}`);
            }
          }
          sock.destroy();
          resolve(lines);
        }
      });
      sock.write(serializeIpc({ type: "service_status_request" }));
    });
  });
}
var DAEMON_STARTUP_TIMEOUT_MS = 3e4;
var DAEMON_STARTUP_POLL_MS = 200;
async function waitForServeReady(timeoutMs) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const connected = await new Promise((resolve) => {
      const sock = connect(SOCK_PATH);
      sock.once("connect", () => {
        sock.destroy();
        resolve(true);
      });
      sock.once("error", () => resolve(false));
    });
    if (connected) return true;
    await sleep(DAEMON_STARTUP_POLL_MS);
  }
  return false;
}
async function startDaemon(options) {
  ensureProfileWorkspace();
  if (existsSync(PID_PATH)) {
    const pid = parseInt(readFileSync(PID_PATH, "utf-8").trim(), 10);
    const probe = probeProcess(pid);
    if (probe.status === "alive") {
      console.error(`Service is already running (PID ${pid})`);
      return;
    }
    if (probe.status === "permission-denied" || probe.status === "unknown") {
      const reason = probe.status === "permission-denied" ? "permission denied while probing" : `${probe.code ?? "unknown"}: ${probe.message}`;
      console.error(`Service may already be running (PID ${pid}); cannot verify it: ${reason}`);
      return;
    }
  }
  unlinkIfPresent(STOPPED_PATH);
  const serveArgs = ["--profile", PROFILE_NAME, ...daemonRelayArgs(options?.relayName)];
  const child = spawnScript("serve", serveArgs, {
    env: { ...process.env },
    stdio: ["ignore", "ignore", "pipe"],
    unref: false
  });
  const stderrChunks = [];
  child.stderr.on("data", (chunk) => {
    stderrChunks.push(chunk);
  });
  const readyOutcome = waitForServeReady(DAEMON_STARTUP_TIMEOUT_MS).then(
    (ok) => ok ? { kind: "ready" } : { kind: "timeout" }
  );
  const exitOutcome = new Promise((resolve) => {
    if (child.exitCode !== null) {
      resolve({ kind: "exited", code: child.exitCode, signal: child.signalCode });
      return;
    }
    child.once("exit", (code, signal) => resolve({ kind: "exited", code, signal }));
  });
  const result = await Promise.race([readyOutcome, exitOutcome]);
  if (result.kind === "ready") {
    console.log(`Service started in background (PID ${child.pid})`);
    child.stderr.removeAllListeners("data");
    child.stderr.destroy();
    child.unref();
    return;
  }
  const stderrOutput = Buffer.concat(stderrChunks).toString("utf-8").trim();
  if (result.kind === "exited") {
    console.error(`Service exited during startup (code=${result.code}, signal=${result.signal}).`);
  } else {
    console.error(`Service failed to become ready within ${DAEMON_STARTUP_TIMEOUT_MS / 1e3}s.`);
    try {
      process.kill(child.pid, "SIGTERM");
    } catch {
    }
  }
  if (stderrOutput) {
    console.error("--- child stderr ---");
    console.error(stderrOutput);
  }
  process.exit(1);
}
var program = new Command("dev-anywhere").description("Dev Anywhere - transparent local AI CLI proxy with remote control").version(pkg.version, "-v, --version").option("--profile <name>", "Use an isolated local proxy profile").allowUnknownOption().allowExcessArguments().action(async () => {
  if (!isInitialized()) {
    console.error(`Dev Anywhere is not initialized. Run "dev-anywhere init" first.`);
    process.exit(1);
  }
  let invocation;
  try {
    invocation = extractAgentInvocation(cliArgsWithoutProfile);
  } catch (err) {
    console.error(err instanceof Error ? err.message : String(err));
    process.exit(1);
  }
  const { startTerminal } = await import("./terminal-DIIMRERW.js");
  const { provider, args } = invocation;
  await startTerminal(args, provider);
});
var serve = new Command("serve").description("Manage the dev-anywhere background service").option("--profile <name>", "Use an isolated local proxy profile").option("-d, --daemon", "Run in background").action(async (opts) => {
  if (!isInitialized()) {
    console.error(`Dev Anywhere is not initialized. Run "dev-anywhere init" first.`);
    process.exit(1);
  }
  if (opts.daemon) {
    setDesiredDaemonRelay(void 0);
    await startDaemon();
  } else {
    const { startService } = await import("./serve.js");
    await startService();
  }
});
serve.command("start").description("Start the background service").option("--relay <name>", "Use a named relay from config").action(async (opts) => {
  if (!isInitialized()) {
    console.error(`Dev Anywhere is not initialized. Run "dev-anywhere init" first.`);
    process.exit(1);
  }
  setDesiredDaemonRelay(opts.relay);
  await startDaemon({ relayName: opts.relay });
});
serve.command("status").description("Show service status and active sessions").option("-w, --watch", "Continuous monitoring mode").option("-n, --interval <seconds>", "Refresh interval in seconds", "2").action(async (opts) => {
  if (opts.watch) {
    const intervalMs = Number(opts.interval) * 1e3;
    let lastLines = await showStatus();
    setInterval(async () => {
      if (lastLines > 0) {
        process.stdout.write(`\x1B[${lastLines}A\x1B[J`);
      }
      lastLines = await showStatus();
    }, intervalMs);
  } else {
    await showStatus();
  }
});
serve.command("stop").description("Stop the background service").action(() => {
  stopService();
});
serve.command("restart").description("Restart the background service").option("--relay <name>", "Use a named relay from config").action(async (opts) => {
  setDesiredDaemonRelay(opts.relay);
  stopService();
  await startDaemon({ relayName: opts.relay });
});
program.addCommand(serve);
var relay = new Command("relay").description("Inspect and manage relay configuration");
relay.command("token").description("Print the relay's current client token (auth: proxy token)").option("--relay <name>", "Use a named relay from config").action(async (opts) => {
  if (!isInitialized()) {
    console.error(`Dev Anywhere is not initialized. Run "dev-anywhere init" first.`);
    process.exit(1);
  }
  const { runRelayTokenCommand } = await import("./relay-token-AANHZIGJ.js");
  await runRelayTokenCommand({ relayName: opts.relay });
});
program.addCommand(relay);
program.command("init").description("Initialize dev-anywhere workspace (~/.dev-anywhere)").action(() => {
  if (isInitialized()) {
    console.log(`Already initialized. Config at ${CONFIG_PATH}`);
    return;
  }
  initWorkspace();
  console.log("Initialized ~/.dev-anywhere/");
  console.log(`Edit ${CONFIG_PATH} to configure relay server URL.`);
});
var cliArgs = normalizeCliArgs(process.argv.slice(2));
var cliArgsWithoutProfile = stripProxyProfileArgs(cliArgs);
program.parse(cliArgsWithoutProfile, { from: "user" });
//# sourceMappingURL=index.js.map