#!/usr/bin/env node
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));

// src/index.ts
var import_http = require("http");
var import_ws = require("ws");
var path = __toESM(require("path"));
var fs = __toESM(require("fs"));
var os = __toESM(require("os"));
var import_daemon_core = require("@adhdev/daemon-core");
var DEFAULT_PORT = 3847;
var STATUS_INTERVAL = 2e3;
var StandaloneServer = class {
  httpServer = null;
  wss = null;
  clients = /* @__PURE__ */ new Set();
  authToken = null;
  statusTimer = null;
  running = false;
  components = null;
  devServer = null;
  async start(options = {}) {
    const port = options.port || DEFAULT_PORT;
    const host = options.host || "127.0.0.1";
    this.authToken = options.token || process.env.ADHDEV_TOKEN || null;
    this.components = await (0, import_daemon_core.initDaemonComponents)({
      cliManagerDeps: {
        getServerConn: () => null,
        getP2p: () => null,
        onStatusChange: () => this.broadcastStatus(),
        removeAgentTracking: () => {
        }
      },
      onStatusChange: () => this.broadcastStatus(),
      onStreamsUpdated: (ideType, streams) => {
        const ideInstance = this.components?.instanceManager?.getInstance(`ide:${ideType}`);
        if (ideInstance?.onEvent) {
          for (const stream of streams) {
            ideInstance.onEvent("stream_update", {
              extensionType: stream.agentType,
              streams: [stream],
              messages: stream.messages || [],
              status: stream.status || "idle",
              activeModal: stream.activeModal || null,
              model: stream.model || void 0,
              mode: stream.mode || void 0
            });
          }
        }
        this.broadcastStatus();
      },
      tickIntervalMs: 3e3,
      cdpScanIntervalMs: 15e3
    });
    if (options.dev) {
      this.devServer = new import_daemon_core.DevServer({
        providerLoader: this.components.providerLoader,
        cdpManagers: this.components.cdpManagers,
        logFn: (msg) => console.log(msg)
      });
      await this.devServer.start();
    }
    this.httpServer = (0, import_http.createServer)((req, res) => {
      this.handleHttp(req, res, options.publicDir);
    });
    this.wss = new import_ws.WebSocketServer({ noServer: true });
    this.httpServer.on("upgrade", (req, socket, head) => {
      const wsUrl = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
      if (wsUrl.pathname === "/ws") {
        if (this.authToken) {
          const urlToken = wsUrl.searchParams.get("token");
          if (urlToken !== this.authToken) {
            socket.write("HTTP/1.1 401 Unauthorized\r\n\r\n");
            socket.destroy();
            return;
          }
        }
        this.wss.handleUpgrade(req, socket, head, (ws) => {
          this.handleWsConnection(ws);
        });
      } else {
        socket.destroy();
      }
    });
    this.statusTimer = setInterval(() => {
      this.broadcastStatus();
    }, STATUS_INTERVAL);
    this.running = true;
    await new Promise((resolve) => {
      this.httpServer.listen(port, host, () => {
        resolve();
      });
    });
    console.log("");
    console.log("\u{1F680} ADHDev Standalone Server");
    console.log(`   http://${host === "0.0.0.0" ? "localhost" : host}:${port}`);
    console.log(`   ws://${host === "0.0.0.0" ? "localhost" : host}:${port}/ws`);
    if (host === "0.0.0.0") {
      const lanIps = this.getLanIPs();
      for (const ip of lanIps) {
        console.log(`   http://${ip}:${port}  (LAN)`);
      }
    }
    if (this.authToken) {
      console.log(`   \u{1F511} Token: ${this.authToken}`);
    }
    console.log("");
    const cdpCount = [...this.components.cdpManagers.values()].filter((m) => m.isConnected).length;
    console.log(`   CDP: ${cdpCount > 0 ? `\u2705 ${cdpCount} connected` : "\u274C none"}`);
    console.log(`   Providers: ${this.components.providerLoader.getAll().length} loaded`);
    if (options.dev) {
      console.log(`   \u{1F6E0}\uFE0F  DevConsole: http://127.0.0.1:19280`);
    }
    console.log("");
    console.log("   Press Ctrl+C to stop.");
    console.log("");
    if (options.open !== false) {
      try {
        const open = (await import("open")).default;
        await open(`http://localhost:${port}`);
      } catch {
      }
    }
    process.on("SIGINT", () => this.stop());
    process.on("SIGTERM", () => this.stop());
  }
  // ─── HTTP Handler ───
  handleHttp(req, res, publicDir) {
    const url = req.url || "/";
    const method = req.method || "GET";
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
    if (method === "OPTIONS") {
      res.writeHead(204);
      res.end();
      return;
    }
    if (this.authToken && url.startsWith("/api/")) {
      const authHeader = req.headers["authorization"];
      const bearerToken = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
      const queryToken = new URL(url, `http://${req.headers.host || "localhost"}`).searchParams.get("token");
      if (bearerToken !== this.authToken && queryToken !== this.authToken) {
        res.writeHead(401, { "Content-Type": "application/json" });
        res.end(JSON.stringify({ error: "Unauthorized. Provide token via Authorization header or ?token= query." }));
        return;
      }
    }
    const apiPath = url.startsWith("/api/v1/") ? url.slice(7) : null;
    if (apiPath === "/status" && method === "GET") {
      const status = this.getStatus();
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify(status));
      return;
    }
    if (apiPath === "/ides" && method === "GET") {
      const ides = this.getIdes();
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify({ ides }));
      return;
    }
    if (apiPath === "/clis" && method === "GET") {
      const clis = this.getClis();
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify({ clis }));
      return;
    }
    if (apiPath === "/agents" && method === "GET") {
      const ides = this.getIdes();
      const agents = [];
      for (const ide of ides) {
        if (ide.activeChat) {
          agents.push({
            ideId: ide.instanceId,
            type: ide.ideType,
            name: ide.ideType,
            status: ide.activeChat.status || "idle",
            source: "native"
          });
        }
        for (const stream of ide.agentStreams || []) {
          agents.push({
            ideId: ide.instanceId,
            type: stream.agentType,
            name: stream.agentName,
            status: stream.status || "idle",
            source: "extension"
          });
        }
      }
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify({ agents }));
      return;
    }
    if (apiPath === "/command" && method === "POST") {
      let body = "";
      req.on("data", (chunk) => {
        body += chunk;
      });
      req.on("end", async () => {
        try {
          const { type, payload, target } = JSON.parse(body);
          const args = { ...payload, _targetInstance: target };
          const result = await this.executeCommand(type, args);
          res.writeHead(200, { "Content-Type": "application/json" });
          res.end(JSON.stringify(result));
        } catch (e) {
          res.writeHead(400, { "Content-Type": "application/json" });
          res.end(JSON.stringify({ success: false, error: e.message }));
        }
      });
      return;
    }
    if (publicDir) {
      const filePath = url === "/" ? "/index.html" : url;
      const fullPath = path.join(publicDir, filePath);
      if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
        const ext = path.extname(fullPath);
        const mimeTypes = {
          ".html": "text/html",
          ".js": "application/javascript",
          ".css": "text/css",
          ".json": "application/json",
          ".png": "image/png",
          ".svg": "image/svg+xml",
          ".ico": "image/x-icon",
          ".woff2": "font/woff2"
        };
        res.writeHead(200, { "Content-Type": mimeTypes[ext] || "application/octet-stream" });
        fs.createReadStream(fullPath).pipe(res);
        return;
      }
      const indexPath = path.join(publicDir, "index.html");
      if (fs.existsSync(indexPath) && !url.startsWith("/api/")) {
        res.writeHead(200, { "Content-Type": "text/html" });
        fs.createReadStream(indexPath).pipe(res);
        return;
      }
    }
    res.writeHead(404, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ error: "Not found" }));
  }
  // ─── WebSocket Handler ───
  handleWsConnection(ws) {
    const MAX_WS_CLIENTS = 10;
    if (this.clients.size >= MAX_WS_CLIENTS) {
      const oldest = this.clients.values().next().value;
      if (oldest) {
        try {
          oldest.close(1e3, "Too many connections");
        } catch {
        }
        this.clients.delete(oldest);
      }
    }
    this.clients.add(ws);
    console.log(`[WS] Client connected (total: ${this.clients.size})`);
    const status = this.getStatus();
    ws.send(JSON.stringify({ type: "status", data: status }));
    ws.on("message", async (raw) => {
      try {
        const msg = JSON.parse(raw.toString());
        if (msg.type === "command" && msg.data) {
          const { type, payload, target } = msg.data;
          const requestId = msg.requestId;
          const args = { ...payload, _targetInstance: target };
          const result = await this.executeCommand(type, args);
          ws.send(JSON.stringify({ type: "command_result", requestId, data: result }));
        }
      } catch (e) {
        const requestId = (() => {
          try {
            return JSON.parse(raw.toString()).requestId;
          } catch {
            return void 0;
          }
        })();
        ws.send(JSON.stringify({ type: "error", requestId, data: { message: e.message } }));
      }
    });
    ws.on("close", () => {
      this.clients.delete(ws);
      console.log(`[WS] Client disconnected (total: ${this.clients.size})`);
    });
    ws.on("error", () => {
      this.clients.delete(ws);
    });
  }
  // ─── Core Logic ───
  getStatus() {
    const cfgSnap = (0, import_daemon_core.loadConfig)();
    const machineId = cfgSnap.machineId || os.hostname().replace(/[^a-zA-Z0-9]/g, "_");
    const ides = this.getIdes();
    const clis = this.getClis();
    const acps = this.getAcps();
    const cpus2 = os.cpus();
    const memSnap = (0, import_daemon_core.getHostMemorySnapshot)();
    const loadavg2 = os.loadavg();
    const wsState = (0, import_daemon_core.getWorkspaceState)(cfgSnap);
    return {
      id: `standalone_${machineId}`,
      instanceId: `standalone_${machineId}`,
      version: "1.0.0",
      // Standalone static version
      daemonMode: false,
      type: "standalone",
      platform: os.platform(),
      hostname: os.hostname(),
      machine: {
        hostname: os.hostname(),
        platform: os.platform(),
        arch: os.arch(),
        cpus: cpus2.length,
        totalMem: memSnap.totalMem,
        freeMem: memSnap.freeMem,
        availableMem: memSnap.availableMem,
        loadavg: loadavg2,
        uptime: os.uptime(),
        release: os.release()
      },
      timestamp: Date.now(),
      userName: cfgSnap.userName || void 0,
      managedIdes: ides,
      managedClis: clis,
      managedAcps: acps,
      workspaces: wsState.workspaces,
      defaultWorkspaceId: wsState.defaultWorkspaceId,
      defaultWorkspacePath: wsState.defaultWorkspacePath,
      workspaceActivity: (0, import_daemon_core.getWorkspaceActivity)(cfgSnap, 15),
      detectedIdes: this.components.detectedIdes.value.filter((i) => i.installed).map((i) => ({
        id: i.id,
        type: i.id,
        name: i.displayName || i.name,
        installed: true,
        running: (0, import_daemon_core.isCdpConnected)(this.components.cdpManagers, i.id)
      })),
      availableProviders: this.components.providerLoader.getAll().map((p) => ({
        type: p.type,
        icon: p.icon || "\u{1F4BB}",
        displayName: p.displayName || p.type,
        category: p.category
      })),
      system: {
        cpus: cpus2.length,
        totalMem: memSnap.totalMem,
        freeMem: memSnap.freeMem,
        availableMem: memSnap.availableMem,
        loadavg: loadavg2,
        uptime: os.uptime(),
        arch: os.arch()
      }
    };
  }
  getIdes() {
    const allStates = this.components.instanceManager.collectAllStates();
    const ideStates = allStates.filter((s) => s.category === "ide");
    return (0, import_daemon_core.buildManagedIdes)(ideStates, this.components.cdpManagers, {
      detectedIdes: this.components.detectedIdes.value
    });
  }
  getClis() {
    const result = [];
    for (const [key, adapter] of this.components.cliManager.adapters.entries()) {
      if (adapter._acpInstance) continue;
      const state = this.components.instanceManager.getInstance(key)?.getState();
      result.push({
        id: key,
        instanceId: key,
        cliType: adapter.cliType || key,
        cliName: adapter.cliName || key,
        status: state?.status || "running",
        mode: "terminal",
        workspace: adapter.workingDir || "",
        activeChat: state?.activeChat || null
      });
    }
    return result;
  }
  getAcps() {
    const result = [];
    for (const [key, adapter] of this.components.cliManager.adapters.entries()) {
      const acpInstance = adapter._acpInstance;
      if (!acpInstance) continue;
      const state = acpInstance.getState();
      result.push({
        id: key,
        acpType: adapter.cliType || state?.type || key,
        acpName: state?.name || adapter.cliType || key,
        status: state?.status || "running",
        mode: "chat",
        workspace: adapter.workingDir || "",
        activeChat: state?.activeChat || null,
        currentModel: state?.currentModel,
        currentPlan: state?.currentPlan,
        acpConfigOptions: state?.acpConfigOptions,
        acpModes: state?.acpModes,
        errorMessage: state?.errorMessage,
        errorReason: state?.errorReason
      });
    }
    return result;
  }
  async executeCommand(type, args) {
    if (!this.components) {
      return { success: false, error: "Components not initialized" };
    }
    const result = await this.components.router.execute(type, args, "standalone");
    if (type.startsWith("workspace_")) this.broadcastStatus();
    return result;
  }
  broadcastStatus() {
    if (this.clients.size === 0) return;
    const status = this.getStatus();
    const msg = JSON.stringify({ type: "status", data: status });
    const cdpCount = [...this.components.cdpManagers.values()].filter((m) => m.isConnected).length;
    import_daemon_core.LOG.debug("Broadcast", `status \u2192 ${this.clients.size} client(s), ${status.ides?.length || 0} IDE(s), ${cdpCount} CDP`);
    for (const client of this.clients) {
      if (client.readyState === import_ws.WebSocket.OPEN) {
        client.send(msg);
      }
    }
  }
  // ─── Network ───
  getLanIPs() {
    const interfaces = os.networkInterfaces();
    const ips = [];
    for (const iface of Object.values(interfaces)) {
      if (!iface) continue;
      for (const info of iface) {
        if (info.family === "IPv4" && !info.internal) {
          ips.push(info.address);
        }
      }
    }
    return ips;
  }
  // ─── Lifecycle ───
  async stop() {
    if (!this.running) return;
    this.running = false;
    console.log("\n   Shutting down...");
    if (this.statusTimer) {
      clearInterval(this.statusTimer);
      this.statusTimer = null;
    }
    for (const ws of this.clients) {
      try {
        ws.close();
      } catch {
      }
    }
    this.clients.clear();
    if (this.wss) {
      this.wss.close();
      this.wss = null;
    }
    if (this.components) {
      await (0, import_daemon_core.shutdownDaemonComponents)(this.components);
    }
    if (this.httpServer) {
      this.httpServer.close();
      this.httpServer = null;
    }
    console.log("   \u2713 ADHDev Standalone stopped.\n");
    process.exit(0);
  }
};
async function main() {
  const args = process.argv.slice(2);
  const options = {};
  for (let i = 0; i < args.length; i++) {
    if ((args[i] === "--port" || args[i] === "-p") && args[i + 1]) {
      options.port = parseInt(args[i + 1]);
      i++;
    }
    if (args[i] === "--host" || args[i] === "-H") {
      options.host = "0.0.0.0";
    }
    if (args[i] === "--public" && args[i + 1]) {
      options.publicDir = args[i + 1];
      i++;
    }
    if (args[i] === "--no-open") {
      options.open = false;
    }
    if (args[i] === "--dev") {
      options.dev = true;
    }
    if (args[i] === "--token" && args[i + 1]) {
      options.token = args[i + 1];
      i++;
    }
  }
  if (!options.publicDir) {
    const candidates = [
      path.join(__dirname, "../../web-standalone/dist"),
      path.join(__dirname, "../public"),
      path.join(process.cwd(), "public")
    ];
    for (const candidate of candidates) {
      if (fs.existsSync(path.join(candidate, "index.html"))) {
        options.publicDir = candidate;
        break;
      }
    }
  }
  const server = new StandaloneServer();
  await server.start(options);
  await new Promise(() => {
  });
}
main().catch((e) => {
  console.error("Fatal error:", e);
  process.exit(1);
});
//# sourceMappingURL=index.js.map