/**
 * @license
 * Copyright 2026 HopCode Team
 * SPDX-License-Identifier: Apache-2.0
 */
// Type-only imports — no runtime cost. The serve module pulls in express +
// body-parser + qs + the daemon transport stack; static-importing it from
// here would tax every `hopcode` invocation (interactive, mcp, channel, etc.)
// with ~50ms of cold ESM resolution. The runtime import is deferred to the
// handler below so it only loads when the user actually runs `hopcode serve`.
import { writeStderrLine } from '../utils/stdioHelpers.js';
/**
 * Pause the current async function indefinitely. Used after the daemon
 * listener is up so yargs `parse()` never resolves — if it did, the
 * top-level CLI would fall through to the interactive (TUI) entry point
 * in `gemini.tsx`. SIGINT / SIGTERM in `runHopCodeServe` is the sole exit
 * route. Named so a future maintainer doesn't read the bare
 * `new Promise<never>(() => {})` as a bug (BRQQZ).
 */
function blockForever() {
    return new Promise(() => { });
}
export const serveCommand = {
    command: 'serve',
    describe: 'Run HopCode as a local HTTP daemon (Stage 1 experimental: --http-bridge)',
    builder: (yargs) => yargs
        .option('port', {
        type: 'number',
        default: 4170,
        description: 'TCP port to bind (use 0 for an OS-assigned ephemeral port)',
    })
        .option('hostname', {
        type: 'string',
        default: '127.0.0.1',
        description: 'Interface to bind. Loopback (127.0.0.1, localhost, ::1, [::1]) is auth-free; anything else requires a token.',
    })
        .option('token', {
        type: 'string',
        description: 'Bearer token required on every request. Falls back to the HOPCODE_SERVER_TOKEN env var.',
    })
        .option('max-sessions', {
        type: 'number',
        default: 20,
        description: 'Cap on concurrent live sessions. New spawn requests beyond this return 503; ' +
            'attach to existing sessions still works. Set to 0 to disable.',
    })
        .option('workspace', {
        type: 'string',
        description: 'Absolute workspace path this daemon binds to. ' +
            'POST /session requests with a mismatched cwd return 400 workspace_mismatch. ' +
            'Defaults to process.cwd() when omitted. ' +
            'For multi-workspace deployments, run one `qwen serve` per workspace ' +
            'on separate ports (or behind an external orchestrator).',
    })
        .option('max-connections', {
        type: 'number',
        default: 256,
        description: 'Listener-level TCP connection cap (server.maxConnections). Bounds raw ' +
            'sockets — slow/phantom SSE clients get rejected at accept time once full. ' +
            'Set to 0 to disable.',
    })
        .option('http-bridge', {
        type: 'boolean',
        default: true,
        description: 'Stage 1 mode: one `hopcode --acp` child per daemon (the daemon binds to ' +
            'one workspace at boot, multiplexing N sessions onto that child via ' +
            "the agent's native `newSession()`). Stage 2 native in-process mode " +
            'is not yet implemented; this flag will become opt-in then.',
    }),
    handler: async (argv) => {
        if (!argv['http-bridge']) {
            writeStderrLine('hopcode serve: --no-http-bridge (native mode) is not yet implemented; ' +
                'falling back to http-bridge.');
        }
        if (argv.token) {
            // `--token` is visible to any local user via `/proc/<pid>/cmdline`
            // (Linux default; only suppressed under `hidepid=2`). Steer
            // operators toward the env-var path which uses
            // `/proc/<pid>/environ` (owner-only).
            writeStderrLine('hopcode serve: --token is visible in the process command line; ' +
                'prefer the HOPCODE_SERVER_TOKEN env var for any non-trivial ' +
                'deployment.');
        }
        // Lazy-load the serve module so non-serve invocations don't pay for
        // express + body-parser + qs in their startup path.
        const { runHopCodeServe } = await import('../serve/index.js');
        try {
            await runHopCodeServe({
                port: argv.port,
                hostname: argv.hostname,
                token: argv.token,
                mode: 'http-bridge',
                maxSessions: argv['max-sessions'],
                maxConnections: argv['max-connections'],
                workspace: argv.workspace,
            });
        }
        catch (err) {
            writeStderrLine(`hopcode serve: ${err instanceof Error ? err.message : String(err)}`);
            process.exit(1);
        }
        await blockForever();
    },
};
//# sourceMappingURL=serve.js.map