#!/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 __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 __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
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/index.ts
var index_exports = {};
__export(index_exports, {
  SessionHostServer: () => SessionHostServer
});
module.exports = __toCommonJS(index_exports);
var import_crypto = require("crypto");
var import_session_host_core2 = require("@adhdev/session-host-core");

// src/server.ts
var import_events = require("events");
var fs2 = __toESM(require("fs"));
var net = __toESM(require("net"));
var import_session_host_core = require("@adhdev/session-host-core");

// src/runtime.ts
var os = __toESM(require("os"));
var path = __toESM(require("path"));
var pty = __toESM(require("node-pty"));
if (os.platform() !== "win32") {
  try {
    const fs3 = require("fs");
    const ptyDir = path.resolve(path.dirname(require.resolve("node-pty")), "..");
    const platformArch = `${os.platform()}-${os.arch()}`;
    const helper = path.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
    if (fs3.existsSync(helper)) {
      const stat = fs3.statSync(helper);
      if (!(stat.mode & 73)) {
        fs3.chmodSync(helper, stat.mode | 493);
      }
    }
  } catch {
  }
}
var PtySessionRuntime = class {
  sessionId;
  payload;
  cols;
  rows;
  ptyProcess = null;
  onDataCallback;
  onExitCallback;
  constructor(options) {
    this.sessionId = options.sessionId;
    this.payload = options.payload;
    this.cols = options.payload.cols || 120;
    this.rows = options.payload.rows || 40;
    this.onDataCallback = options.onData;
    this.onExitCallback = options.onExit;
  }
  start() {
    if (this.ptyProcess) return this.ptyProcess.pid;
    const command = this.payload.launchCommand.command;
    const args = this.payload.launchCommand.args || [];
    const cwd = this.payload.workspace || process.cwd();
    const env = {
      ...process.env,
      ...this.payload.launchCommand.env || {}
    };
    this.ptyProcess = pty.spawn(command, args, {
      name: os.platform() === "win32" ? "xterm-color" : "xterm-256color",
      cols: this.cols,
      rows: this.rows,
      cwd,
      env
    });
    this.ptyProcess.onData((data) => {
      this.onDataCallback(data);
    });
    this.ptyProcess.onExit(({ exitCode }) => {
      this.ptyProcess = null;
      this.onExitCallback(exitCode ?? null);
    });
    return this.ptyProcess.pid;
  }
  write(data) {
    if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);
    this.ptyProcess.write(data);
  }
  resize(cols, rows) {
    if (!this.ptyProcess) throw new Error(`Session not running: ${this.sessionId}`);
    this.ptyProcess.resize(cols, rows);
  }
  stop() {
    if (!this.ptyProcess) return;
    this.ptyProcess.kill();
  }
};

// src/storage.ts
var fs = __toESM(require("fs"));
var os2 = __toESM(require("os"));
var path2 = __toESM(require("path"));
var SessionHostStorage = class {
  rootDir;
  runtimesDir;
  constructor(options = {}) {
    const appName = options.appName || "adhdev";
    this.rootDir = path2.join(os2.homedir(), ".adhdev", "session-host", appName);
    this.runtimesDir = path2.join(this.rootDir, "runtimes");
  }
  loadAll() {
    if (!fs.existsSync(this.runtimesDir)) return [];
    const entries = fs.readdirSync(this.runtimesDir, { withFileTypes: true });
    const states = [];
    for (const entry of entries) {
      if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
      const fullPath = path2.join(this.runtimesDir, entry.name);
      try {
        const parsed = JSON.parse(fs.readFileSync(fullPath, "utf8"));
        if (parsed?.record?.sessionId) {
          states.push(parsed);
        }
      } catch {
      }
    }
    return states.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
  }
  save(record, snapshot) {
    fs.mkdirSync(this.runtimesDir, { recursive: true });
    const filePath = path2.join(this.runtimesDir, `${record.sessionId}.json`);
    const payload = {
      record,
      snapshot,
      updatedAt: Date.now()
    };
    fs.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
  }
};

// src/server.ts
var SessionHostServer = class extends import_events.EventEmitter {
  endpoint;
  registry = new import_session_host_core.SessionHostRegistry();
  runtimes = /* @__PURE__ */ new Map();
  storage;
  ipcServer = null;
  sockets = /* @__PURE__ */ new Set();
  persistTimers = /* @__PURE__ */ new Map();
  constructor(options = {}) {
    super();
    this.endpoint = options.endpoint || (0, import_session_host_core.getDefaultSessionHostEndpoint)(options.appName || "adhdev");
    this.storage = new SessionHostStorage({ appName: options.appName || "adhdev" });
  }
  async start() {
    this.restorePersistedRuntimes();
    if (this.endpoint.kind === "unix") {
      try {
        fs2.unlinkSync(this.endpoint.path);
      } catch {
      }
    }
    this.ipcServer = net.createServer((socket) => {
      this.sockets.add(socket);
      socket.on("close", () => {
        this.sockets.delete(socket);
      });
      socket.on("data", (0, import_session_host_core.createLineParser)((envelope) => {
        if (envelope.kind !== "request") return;
        void this.handleIncomingRequest(socket, envelope);
      }));
    });
    await new Promise((resolve2, reject) => {
      this.ipcServer?.once("listening", () => resolve2());
      this.ipcServer?.once("error", reject);
      this.ipcServer?.listen(this.endpoint.path);
    });
    this.emit("log", `session host endpoint ready: ${this.endpoint.path}`);
  }
  async stop() {
    this.flushAllPersistence();
    for (const runtime of this.runtimes.values()) {
      try {
        runtime.stop();
      } catch {
      }
    }
    this.runtimes.clear();
    for (const timer of this.persistTimers.values()) {
      clearTimeout(timer);
    }
    this.persistTimers.clear();
    for (const socket of this.sockets) {
      socket.destroy();
    }
    this.sockets.clear();
    if (this.ipcServer) {
      const server = this.ipcServer;
      this.ipcServer = null;
      await new Promise((resolve2) => server.close(() => resolve2()));
    }
    if (this.endpoint.kind === "unix") {
      try {
        fs2.unlinkSync(this.endpoint.path);
      } catch {
      }
    }
    this.removeAllListeners();
  }
  async handleRequest(request) {
    try {
      switch (request.type) {
        case "create_session": {
          const record = this.registry.createSession(request.payload);
          this.schedulePersist(record.sessionId);
          this.emitEvent({ type: "session_created", sessionId: record.sessionId, record });
          try {
            const startedRecord = this.startRuntime(record, request.payload, "session_started");
            return { success: true, result: startedRecord };
          } catch (error) {
            this.registry.markStopped(record.sessionId, "failed");
            this.persistNow(record.sessionId);
            return { success: false, error: error?.message || String(error) };
          }
        }
        case "list_sessions":
          return { success: true, result: this.registry.listSessions() };
        case "attach_session": {
          const record = this.registry.attachClient(request.payload);
          this.schedulePersist(record.sessionId);
          const client = record.attachedClients.find((item) => item.clientId === request.payload.clientId);
          if (client) {
            this.emitEvent({ type: "client_attached", sessionId: record.sessionId, client });
          }
          return { success: true, result: record };
        }
        case "detach_session": {
          const record = this.registry.detachClient(request.payload);
          this.schedulePersist(record.sessionId);
          this.emitEvent({ type: "client_detached", sessionId: record.sessionId, clientId: request.payload.clientId });
          return { success: true, result: record };
        }
        case "acquire_write": {
          const record = this.registry.acquireWrite(request.payload);
          this.persistNow(record.sessionId);
          this.emitEvent({ type: "write_owner_changed", sessionId: record.sessionId, owner: record.writeOwner });
          return { success: true, result: record };
        }
        case "release_write": {
          const record = this.registry.releaseWrite(request.payload);
          this.persistNow(record.sessionId);
          this.emitEvent({ type: "write_owner_changed", sessionId: record.sessionId, owner: record.writeOwner });
          return { success: true, result: record };
        }
        case "get_snapshot":
          return { success: true, result: this.registry.getSnapshot(request.payload.sessionId, request.payload.sinceSeq) };
        case "clear_session_buffer": {
          const record = this.registry.clearBuffer(request.payload.sessionId);
          this.persistNow(record.sessionId);
          this.emitEvent({ type: "session_cleared", sessionId: record.sessionId });
          return { success: true, result: record };
        }
        case "send_input": {
          const client = this.getAttachedClient(request.payload.sessionId, request.payload.clientId);
          if (client?.readOnly) {
            return { success: false, error: `Client ${request.payload.clientId} is read-only` };
          }
          const session = this.registry.getSession(request.payload.sessionId);
          if (session?.writeOwner && session.writeOwner.clientId !== request.payload.clientId) {
            return { success: false, error: `Write owned by ${session.writeOwner.clientId}` };
          }
          this.requireRuntime(request.payload.sessionId).write(request.payload.data);
          return { success: true, result: this.registry.getSession(request.payload.sessionId) };
        }
        case "resize_session": {
          this.requireRuntime(request.payload.sessionId).resize(request.payload.cols, request.payload.rows);
          const record = this.registry.getSession(request.payload.sessionId);
          if (record) {
            this.registry.restoreSession(
              {
                ...record,
                meta: {
                  ...record.meta || {},
                  sessionHostCols: request.payload.cols,
                  sessionHostRows: request.payload.rows
                }
              },
              this.registry.getSnapshot(request.payload.sessionId)
            );
          }
          this.schedulePersist(request.payload.sessionId);
          this.emitEvent({
            type: "session_resized",
            sessionId: request.payload.sessionId,
            cols: request.payload.cols,
            rows: request.payload.rows
          });
          return { success: true, result: this.registry.getSession(request.payload.sessionId) };
        }
        case "stop_session": {
          this.registry.setLifecycle(request.payload.sessionId, "stopping");
          this.persistNow(request.payload.sessionId);
          this.requireRuntime(request.payload.sessionId).stop();
          this.emitEvent({ type: "session_stopped", sessionId: request.payload.sessionId });
          return { success: true, result: this.registry.getSession(request.payload.sessionId) };
        }
        case "resume_session": {
          const existing = this.registry.getSession(request.payload.sessionId);
          if (!existing) {
            return { success: false, error: `Unknown session: ${request.payload.sessionId}` };
          }
          if (this.runtimes.has(request.payload.sessionId)) {
            return { success: true, result: existing };
          }
          const resumed = this.startRuntime(existing, this.buildPayloadFromRecord(existing), "session_resumed");
          return { success: true, result: resumed };
        }
      }
    } catch (error) {
      return { success: false, error: error?.message || String(error) };
    }
  }
  requireRuntime(sessionId) {
    const runtime = this.runtimes.get(sessionId);
    if (!runtime) throw new Error(`Runtime not found for session: ${sessionId}`);
    return runtime;
  }
  getAttachedClient(sessionId, clientId) {
    const session = this.registry.getSession(sessionId);
    return session?.attachedClients.find((client) => client.clientId === clientId) || null;
  }
  emitEvent(event) {
    for (const socket of this.sockets) {
      (0, import_session_host_core.writeEnvelope)(socket, {
        kind: "event",
        event
      });
    }
    this.emit("event", event);
  }
  async handleIncomingRequest(socket, envelope) {
    const response = await this.handleRequest(envelope.request);
    (0, import_session_host_core.writeEnvelope)(socket, (0, import_session_host_core.createResponseEnvelope)(envelope.requestId, response));
  }
  schedulePersist(sessionId) {
    const existing = this.persistTimers.get(sessionId);
    if (existing) clearTimeout(existing);
    this.persistTimers.set(sessionId, setTimeout(() => {
      this.persistTimers.delete(sessionId);
      this.persistNow(sessionId);
    }, 200));
  }
  persistNow(sessionId) {
    const record = this.registry.getSession(sessionId);
    if (!record) return;
    const snapshot = this.registry.getSnapshot(sessionId);
    this.storage.save(record, snapshot);
  }
  flushAllPersistence() {
    for (const sessionId of this.runtimes.keys()) {
      this.persistNow(sessionId);
    }
    for (const record of this.registry.listSessions()) {
      this.persistNow(record.sessionId);
    }
  }
  restorePersistedRuntimes() {
    const states = this.storage.loadAll();
    for (const persisted of states) {
      const wasLiveRuntime = !["stopped", "failed"].includes(persisted.record.lifecycle);
      const recoveredRecord = {
        ...persisted.record,
        attachedClients: [],
        writeOwner: null,
        lifecycle: wasLiveRuntime ? "interrupted" : persisted.record.lifecycle,
        lastActivityAt: Date.now(),
        meta: {
          ...persisted.record.meta || {},
          restoredFromStorage: true,
          runtimeRecoveryState: wasLiveRuntime ? "host_restart_interrupted" : "snapshot"
        }
      };
      this.registry.restoreSession(recoveredRecord, persisted.snapshot);
      this.storage.save(recoveredRecord, persisted.snapshot);
      if (wasLiveRuntime) {
        try {
          const resumed = this.startRuntime(
            recoveredRecord,
            this.buildPayloadFromRecord(recoveredRecord),
            "session_resumed"
          );
          const resumedMeta = {
            ...resumed.meta || {},
            restoredFromStorage: true,
            runtimeRecoveryState: "auto_resumed"
          };
          this.registry.restoreSession(
            { ...resumed, meta: resumedMeta },
            this.registry.getSnapshot(resumed.sessionId)
          );
          this.persistNow(resumed.sessionId);
        } catch (error) {
          const interrupted = this.registry.setLifecycle(recoveredRecord.sessionId, "interrupted");
          this.registry.restoreSession({
            ...interrupted,
            meta: {
              ...interrupted.meta || {},
              restoredFromStorage: true,
              runtimeRecoveryState: "resume_failed",
              runtimeRecoveryError: error?.message || String(error)
            }
          }, persisted.snapshot);
          this.persistNow(recoveredRecord.sessionId);
        }
      }
    }
  }
  buildPayloadFromRecord(record) {
    return {
      sessionId: record.sessionId,
      runtimeKey: record.runtimeKey,
      displayName: record.displayName,
      providerType: record.providerType,
      category: record.category,
      workspace: record.workspace,
      launchCommand: record.launchCommand,
      cols: typeof record.meta?.sessionHostCols === "number" ? record.meta.sessionHostCols : 120,
      rows: typeof record.meta?.sessionHostRows === "number" ? record.meta.sessionHostRows : 40,
      meta: record.meta
    };
  }
  startRuntime(record, payload, startEventType) {
    const runtime = new PtySessionRuntime({
      sessionId: record.sessionId,
      payload,
      onData: (data) => {
        const { seq } = this.registry.appendOutput(record.sessionId, data);
        this.schedulePersist(record.sessionId);
        this.emitEvent({ type: "session_output", sessionId: record.sessionId, seq, data });
      },
      onExit: (exitCode) => {
        this.registry.markStopped(record.sessionId, exitCode === 0 ? "stopped" : "failed");
        this.runtimes.delete(record.sessionId);
        this.persistNow(record.sessionId);
        this.emitEvent({ type: "session_exit", sessionId: record.sessionId, exitCode });
      }
    });
    this.registry.setLifecycle(record.sessionId, "starting");
    const pid = runtime.start();
    this.runtimes.set(record.sessionId, runtime);
    const startedRecord = this.registry.markStarted(record.sessionId, pid);
    this.persistNow(record.sessionId);
    this.emitEvent({ type: startEventType, sessionId: record.sessionId, pid });
    return startedRecord;
  }
};

// src/index.ts
var SESSION_HOST_APP_NAME = process.env.ADHDEV_SESSION_HOST_NAME || "adhdev";
function parseArgs(argv) {
  const [command, ...rest] = argv;
  const readOnly = rest.includes("--read-only");
  const takeover = rest.includes("--takeover");
  const showAll = rest.includes("--all");
  const positional = rest.filter((arg) => arg !== "--read-only" && arg !== "--takeover" && arg !== "--all");
  return {
    command: command || "serve",
    positional,
    readOnly,
    takeover,
    showAll
  };
}
async function runServer() {
  const server = new SessionHostServer({ appName: SESSION_HOST_APP_NAME });
  await server.start();
  process.on("SIGINT", async () => {
    await server.stop();
    process.exit(0);
  });
  process.on("SIGTERM", async () => {
    await server.stop();
    process.exit(0);
  });
  await new Promise(() => {
  });
}
async function listRuntimes(showAll = false) {
  const client = new import_session_host_core2.SessionHostClient({ endpoint: (0, import_session_host_core2.getDefaultSessionHostEndpoint)(SESSION_HOST_APP_NAME) });
  try {
    const response = await client.request({
      type: "list_sessions",
      payload: {}
    });
    if (!response.success) {
      throw new Error(response.error || "Failed to list runtimes");
    }
    const runtimes = (response.result || []).filter((runtime) => showAll || runtime.lifecycle !== "stopped");
    if (runtimes.length === 0) {
      console.log("No runtimes.");
      return;
    }
    console.log("runtimeKey	lifecycle	owner	workspace	id	displayName");
    for (const runtime of runtimes) {
      console.log([
        runtime.runtimeKey,
        runtime.lifecycle,
        (0, import_session_host_core2.formatRuntimeOwner)(runtime),
        runtime.workspaceLabel,
        runtime.sessionId,
        runtime.displayName
      ].join("	"));
    }
  } finally {
    await client.close().catch(() => {
    });
  }
}
async function attachRuntime(target, readOnly = false, takeover = false) {
  const client = new import_session_host_core2.SessionHostClient({ endpoint: (0, import_session_host_core2.getDefaultSessionHostEndpoint)(SESSION_HOST_APP_NAME) });
  const clientId = `local-terminal-${process.pid}-${(0, import_crypto.randomUUID)().slice(0, 8)}`;
  let lastSeq = 0;
  let restoredRawMode = false;
  let runtimeId = "";
  let localReadOnly = readOnly;
  const cleanup = async () => {
    process.stdout.off("resize", handleResize);
    process.stdin.off("data", handleInput);
    process.stdin.pause();
    if (process.stdin.isTTY && restoredRawMode) {
      process.stdin.setRawMode(false);
    }
    await client.request({
      type: "release_write",
      payload: {
        sessionId: runtimeId,
        clientId
      }
    }).catch(() => ({ success: false }));
    await client.request({
      type: "detach_session",
      payload: {
        sessionId: runtimeId,
        clientId
      }
    }).catch(() => ({ success: false }));
    await client.close().catch(() => {
    });
  };
  const handleResize = () => {
    void client.request({
      type: "resize_session",
      payload: {
        sessionId: runtimeId,
        cols: process.stdout.columns || 120,
        rows: process.stdout.rows || 40
      }
    }).catch(() => ({ success: false }));
  };
  const sendInputWithTakeover = async (data) => {
    let response = await client.request({
      type: "send_input",
      payload: {
        sessionId: runtimeId,
        clientId,
        data
      }
    });
    if (!response.success && response.error?.startsWith("Write owned by ")) {
      const ownerResponse = await client.request({
        type: "acquire_write",
        payload: {
          sessionId: runtimeId,
          clientId,
          ownerType: "user",
          force: true
        }
      });
      if (ownerResponse.success && ownerResponse.result) {
        response = await client.request({
          type: "send_input",
          payload: {
            sessionId: runtimeId,
            clientId,
            data
          }
        });
        if (response.success) {
          process.stderr.write(`Took control of ${ownerResponse.result.runtimeKey}.
`);
        }
      }
    }
    return response;
  };
  const handleInput = (chunk) => {
    if (!localReadOnly && chunk.length === 1 && chunk[0] === 29) {
      void cleanup().finally(() => process.exit(0));
      return;
    }
    if (localReadOnly) return;
    void sendInputWithTakeover(chunk.toString("utf8")).catch(() => ({ success: false }));
  };
  try {
    if (readOnly && takeover) {
      throw new Error("Use either --read-only or --takeover, not both");
    }
    const listResponse = await client.request({
      type: "list_sessions",
      payload: {}
    });
    if (!listResponse.success || !listResponse.result) {
      throw new Error(listResponse.error || "Failed to list runtimes");
    }
    let runtimeRecord = (0, import_session_host_core2.resolveRuntimeRecord)(listResponse.result, target);
    runtimeId = runtimeRecord.sessionId;
    if (runtimeRecord.lifecycle === "interrupted" && !readOnly) {
      const resumeResponse = await client.request({
        type: "resume_session",
        payload: {
          sessionId: runtimeId
        }
      });
      if (resumeResponse.success && resumeResponse.result) {
        runtimeRecord = resumeResponse.result;
      } else {
        process.stderr.write(
          `Runtime ${runtimeRecord.runtimeKey} could not be resumed automatically: ${resumeResponse.error || "unknown error"}
`
        );
      }
    }
    let effectiveReadOnly = readOnly;
    if (!effectiveReadOnly && runtimeRecord.writeOwner && runtimeRecord.writeOwner.clientId !== clientId && !takeover) {
      process.stderr.write(
        `Runtime ${runtimeRecord.runtimeKey} is currently owned by ${runtimeRecord.writeOwner.clientId}; first input will take control here.
`
      );
    }
    localReadOnly = effectiveReadOnly;
    const attachResponse = await client.request({
      type: "attach_session",
      payload: {
        sessionId: runtimeId,
        clientId,
        clientType: "local-terminal",
        readOnly: effectiveReadOnly
      }
    });
    if (!attachResponse.success) {
      throw new Error(attachResponse.error || `Failed to attach runtime ${runtimeId}`);
    }
    const attachedRecord = attachResponse.result || null;
    if (!effectiveReadOnly && takeover) {
      const ownerResponse = await client.request({
        type: "acquire_write",
        payload: {
          sessionId: runtimeId,
          clientId,
          ownerType: "user",
          force: takeover
        }
      });
      if (!ownerResponse.success) {
        throw new Error(ownerResponse.error || `Failed to acquire write owner for runtime ${runtimeId}`);
      }
    }
    const snapshotResponse = await client.request({
      type: "get_snapshot",
      payload: { sessionId: runtimeId }
    });
    if (!snapshotResponse.success) {
      throw new Error(snapshotResponse.error || `Failed to read runtime snapshot ${runtimeId}`);
    }
    lastSeq = snapshotResponse.result?.seq || 0;
    if (snapshotResponse.result?.text) {
      process.stdout.write(snapshotResponse.result.text);
    }
    if (attachedRecord?.lifecycle === "stopped" || attachedRecord?.lifecycle === "failed" || attachedRecord?.lifecycle === "interrupted") {
      process.stderr.write(`Runtime ${attachedRecord.runtimeKey} is already ${attachedRecord.lifecycle}. Detached after snapshot.
`);
      await cleanup();
      return;
    }
    const stopSignals = ["SIGINT", "SIGTERM", "SIGHUP"];
    const signalHandlers = stopSignals.map((signal) => {
      const handler = () => {
        void cleanup().finally(() => process.exit(0));
      };
      process.on(signal, handler);
      return { signal, handler };
    });
    const unsubscribe = client.onEvent((event) => {
      if (event.sessionId !== runtimeId) return;
      if (event.type === "session_output") {
        if (event.seq <= lastSeq) return;
        lastSeq = event.seq;
        process.stdout.write(event.data);
        return;
      }
      if (event.type === "session_exit") {
        void cleanup().finally(() => {
          for (const { signal, handler } of signalHandlers) {
            process.off(signal, handler);
          }
          unsubscribe();
          process.exit(event.exitCode ?? 0);
        });
      }
    });
    process.stdout.on("resize", handleResize);
    process.stdin.on("data", handleInput);
    process.stdin.resume();
    if (process.stdin.isTTY) {
      process.stdin.setRawMode(true);
      restoredRawMode = true;
    }
    handleResize();
    if (!effectiveReadOnly) {
      process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId}. Press Ctrl+] to detach.
`);
    } else {
      process.stderr.write(`Attached to runtime ${attachedRecord?.runtimeKey || runtimeId} (read-only).
`);
    }
    await new Promise(() => {
    });
  } catch (error) {
    await cleanup().catch(() => {
    });
    throw error;
  }
}
async function main() {
  const { command, positional, readOnly, takeover, showAll } = parseArgs(process.argv.slice(2));
  if (command === "serve") {
    await runServer();
    return;
  }
  if (command === "list") {
    await listRuntimes(showAll);
    return;
  }
  if (command === "attach") {
    const target = positional[0];
    if (!target) {
      throw new Error("runtime target is required: adhdev-sessiond attach <runtimeId|runtimeKey>");
    }
    await attachRuntime(target, readOnly, takeover);
    return;
  }
  if (command === "resume") {
    const target = positional[0];
    if (!target) {
      throw new Error("runtime target is required: adhdev-sessiond resume <runtimeId|runtimeKey>");
    }
    const client = new import_session_host_core2.SessionHostClient({ endpoint: (0, import_session_host_core2.getDefaultSessionHostEndpoint)(SESSION_HOST_APP_NAME) });
    try {
      const listResponse = await client.request({ type: "list_sessions", payload: {} });
      if (!listResponse.success || !listResponse.result) {
        throw new Error(listResponse.error || "Failed to list runtimes");
      }
      const runtimeRecord = (0, import_session_host_core2.resolveRuntimeRecord)(listResponse.result, target);
      const resumeResponse = await client.request({
        type: "resume_session",
        payload: {
          sessionId: runtimeRecord.sessionId
        }
      });
      if (!resumeResponse.success || !resumeResponse.result) {
        throw new Error(resumeResponse.error || `Failed to resume runtime ${runtimeRecord.runtimeKey}`);
      }
      console.log(`Resumed ${resumeResponse.result.runtimeKey} (${resumeResponse.result.sessionId})`);
    } finally {
      await client.close().catch(() => {
      });
    }
    return;
  }
  throw new Error(`Unknown command: ${command}`);
}
if (require.main === module) {
  void main().catch((error) => {
    console.error(error instanceof Error ? error.message : error);
    process.exit(1);
  });
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  SessionHostServer
});
//# sourceMappingURL=index.js.map