File size: 3,797 Bytes
f778c12 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | // Gateway run command option registration and lazy handoff to runtime startup.
import { Option, type Command } from "commander";
import {
WINDOWS_TASK_SUPERVISOR_CHILD_FLAG,
WINDOWS_TASK_SUPERVISOR_FLAG,
} from "../../daemon/windows-task-supervisor-contract.js";
import type { GatewayRunOpts } from "./run-options.js";
import { resolveGatewayRunOptions } from "./run-options.js";
import { getGatewayRunRuntimeHooks } from "./runtime-hooks.js";
const GATEWAY_AUTH_MODES = ["none", "token", "password", "trusted-proxy"] as const;
const GATEWAY_TAILSCALE_MODES = ["off", "serve", "funnel"] as const;
function formatModeChoices(modes: readonly string[]): string {
return modes.map((mode) => `"${mode}"`).join("|");
}
type GatewayRunCommandHooks = {
beforeRun?: (opts: Pick<GatewayRunOpts, "force" | "reset">) => Promise<void> | void;
};
export function addGatewayRunCommand(cmd: Command, hooks: GatewayRunCommandHooks = {}): Command {
return cmd
.option("--port <port>", "Port for the gateway WebSocket")
.option(
"--bind <mode>",
'Bind mode ("loopback"|"lan"|"tailnet"|"auto"|"custom"). Defaults to config gateway.bind (or loopback).',
)
.option(
"--token <token>",
"Shared token required in connect.params.auth.token (default: OPENCLAW_GATEWAY_TOKEN env if set)",
)
.option("--auth <mode>", `Gateway auth mode (${formatModeChoices(GATEWAY_AUTH_MODES)})`)
.option("--password <password>", "Password for auth mode=password")
.option("--password-file <path>", "Read gateway password from file")
.option(
"--tailscale <mode>",
`Tailscale exposure mode (${formatModeChoices(GATEWAY_TAILSCALE_MODES)})`,
)
.addOption(new Option("--tailscale-reset-on-exit").hideHelp())
.option(
"--allow-unconfigured",
"Allow gateway start without enforcing gateway.mode=local in config (does not repair config)",
false,
)
.option("--dev", "Create a dev config + workspace if missing (no BOOTSTRAP.md)", false)
.option(
"--ambient-channels",
"Allow the gateway to auto-configure channels from ambient environment variables",
false,
)
.option("--dev-ambient-channels", "Deprecated alias for --ambient-channels", false)
.option(
"--reset",
"Reset dev config + credentials + sessions + workspace (requires --dev)",
false,
)
.addOption(new Option(WINDOWS_TASK_SUPERVISOR_FLAG).hideHelp())
.addOption(new Option(`${WINDOWS_TASK_SUPERVISOR_CHILD_FLAG} <restart-code>`).hideHelp())
.addOption(new Option("--update-canary").hideHelp())
.option("--force", "Kill any existing listener on the target port before starting", false)
.option("--verbose", "Verbose logging to stdout/stderr", false)
.option(
"--cli-backend-logs",
"Only show CLI backend logs in the console (includes stdout/stderr)",
false,
)
.option("--claude-cli-logs", "Deprecated alias for --cli-backend-logs", false)
.option("--ws-log <style>", 'WebSocket log style ("auto"|"full"|"compact")', "auto")
.option("--compact", 'Alias for "--ws-log compact"', false)
.option("--raw-stream", "Log raw model stream events to jsonl", false)
.option("--raw-stream-path <path>", "Raw stream jsonl path")
.action(async (opts, command) => {
const resolved = resolveGatewayRunOptions(opts, command);
try {
await hooks.beforeRun?.(resolved);
const { runGatewayCommand } = await import("./run.js");
await runGatewayCommand(resolved, getGatewayRunRuntimeHooks());
} catch (error) {
const { handleGatewayStartupMaintenance } = await import("./startup-maintenance.js");
if (!(await handleGatewayStartupMaintenance(error))) {
throw error;
}
}
});
}
|