diff --git a/src/entry.ts b/src/entry.ts index e066432893b..5d0ceeb2e59 100644 --- a/src/entry.ts +++ b/src/entry.ts @@ -1,108 +1,119 @@ #!/usr/bin/env node import { spawn } from "node:child_process"; import process from "node:process"; +import { fileURLToPath } from "node:url"; import { applyCliProfileEnv, parseCliProfileArgs } from "./cli/profile.js"; import { shouldSkipRespawnForArgv } from "./cli/respawn-policy.js"; import { normalizeWindowsArgv } from "./cli/windows-argv.js"; import { isTruthyEnvValue, normalizeEnv } from "./infra/env.js"; +import { isMainModule } from "./infra/is-main.js"; import { installProcessWarningFilter } from "./infra/warning-filter.js"; import { attachChildProcessBridge } from "./process/child-process-bridge.js"; -process.title = "openclaw"; -installProcessWarningFilter(); -normalizeEnv(); +// Guard: only run entry-point logic when this file is the main module. +// The bundler may import entry.js as a shared dependency when dist/index.js +// is the actual entry point; without this guard the top-level code below +// would call runCli a second time, starting a duplicate gateway that fails +// on the lock / port and crashes the process. +if (!isMainModule({ currentFile: fileURLToPath(import.meta.url) })) { + // Imported as a dependency — skip all entry-point side effects. +} else { + process.title = "openclaw"; + installProcessWarningFilter(); + normalizeEnv(); -if (process.argv.includes("--no-color")) { - process.env.NO_COLOR = "1"; - process.env.FORCE_COLOR = "0"; -} - -const EXPERIMENTAL_WARNING_FLAG = "--disable-warning=ExperimentalWarning"; - -function hasExperimentalWarningSuppressed(): boolean { - const nodeOptions = process.env.NODE_OPTIONS ?? ""; - if (nodeOptions.includes(EXPERIMENTAL_WARNING_FLAG) || nodeOptions.includes("--no-warnings")) { - return true; + if (process.argv.includes("--no-color")) { + process.env.NO_COLOR = "1"; + process.env.FORCE_COLOR = "0"; } - for (const arg of process.execArgv) { - if (arg === EXPERIMENTAL_WARNING_FLAG || arg === "--no-warnings") { + + const EXPERIMENTAL_WARNING_FLAG = "--disable-warning=ExperimentalWarning"; + + function hasExperimentalWarningSuppressed(): boolean { + const nodeOptions = process.env.NODE_OPTIONS ?? ""; + if (nodeOptions.includes(EXPERIMENTAL_WARNING_FLAG) || nodeOptions.includes("--no-warnings")) { return true; } - } - return false; -} - -function ensureExperimentalWarningSuppressed(): boolean { - if (shouldSkipRespawnForArgv(process.argv)) { - return false; - } - if (isTruthyEnvValue(process.env.OPENCLAW_NO_RESPAWN)) { - return false; - } - if (isTruthyEnvValue(process.env.OPENCLAW_NODE_OPTIONS_READY)) { - return false; - } - if (hasExperimentalWarningSuppressed()) { - return false; - } - - // Respawn guard (and keep recursion bounded if something goes wrong). - process.env.OPENCLAW_NODE_OPTIONS_READY = "1"; - // Pass flag as a Node CLI option, not via NODE_OPTIONS (--disable-warning is disallowed in NODE_OPTIONS). - const child = spawn( - process.execPath, - [EXPERIMENTAL_WARNING_FLAG, ...process.execArgv, ...process.argv.slice(1)], - { - stdio: "inherit", - env: process.env, - }, - ); - - attachChildProcessBridge(child); - - child.once("exit", (code, signal) => { - if (signal) { - process.exitCode = 1; - return; + for (const arg of process.execArgv) { + if (arg === EXPERIMENTAL_WARNING_FLAG || arg === "--no-warnings") { + return true; + } } - process.exit(code ?? 1); - }); + return false; + } - child.once("error", (error) => { - console.error( - "[openclaw] Failed to respawn CLI:", - error instanceof Error ? (error.stack ?? error.message) : error, + function ensureExperimentalWarningSuppressed(): boolean { + if (shouldSkipRespawnForArgv(process.argv)) { + return false; + } + if (isTruthyEnvValue(process.env.OPENCLAW_NO_RESPAWN)) { + return false; + } + if (isTruthyEnvValue(process.env.OPENCLAW_NODE_OPTIONS_READY)) { + return false; + } + if (hasExperimentalWarningSuppressed()) { + return false; + } + + // Respawn guard (and keep recursion bounded if something goes wrong). + process.env.OPENCLAW_NODE_OPTIONS_READY = "1"; + // Pass flag as a Node CLI option, not via NODE_OPTIONS (--disable-warning is disallowed in NODE_OPTIONS). + const child = spawn( + process.execPath, + [EXPERIMENTAL_WARNING_FLAG, ...process.execArgv, ...process.argv.slice(1)], + { + stdio: "inherit", + env: process.env, + }, ); - process.exit(1); - }); - // Parent must not continue running the CLI. - return true; -} + attachChildProcessBridge(child); -process.argv = normalizeWindowsArgv(process.argv); + child.once("exit", (code, signal) => { + if (signal) { + process.exitCode = 1; + return; + } + process.exit(code ?? 1); + }); -if (!ensureExperimentalWarningSuppressed()) { - const parsed = parseCliProfileArgs(process.argv); - if (!parsed.ok) { - // Keep it simple; Commander will handle rich help/errors after we strip flags. - console.error(`[openclaw] ${parsed.error}`); - process.exit(2); - } - - if (parsed.profile) { - applyCliProfileEnv({ profile: parsed.profile }); - // Keep Commander and ad-hoc argv checks consistent. - process.argv = parsed.argv; - } - - import("./cli/run-main.js") - .then(({ runCli }) => runCli(process.argv)) - .catch((error) => { + child.once("error", (error) => { console.error( - "[openclaw] Failed to start CLI:", + "[openclaw] Failed to respawn CLI:", error instanceof Error ? (error.stack ?? error.message) : error, ); - process.exitCode = 1; + process.exit(1); }); + + // Parent must not continue running the CLI. + return true; + } + + process.argv = normalizeWindowsArgv(process.argv); + + if (!ensureExperimentalWarningSuppressed()) { + const parsed = parseCliProfileArgs(process.argv); + if (!parsed.ok) { + // Keep it simple; Commander will handle rich help/errors after we strip flags. + console.error(`[openclaw] ${parsed.error}`); + process.exit(2); + } + + if (parsed.profile) { + applyCliProfileEnv({ profile: parsed.profile }); + // Keep Commander and ad-hoc argv checks consistent. + process.argv = parsed.argv; + } + + import("./cli/run-main.js") + .then(({ runCli }) => runCli(process.argv)) + .catch((error) => { + console.error( + "[openclaw] Failed to start CLI:", + error instanceof Error ? (error.stack ?? error.message) : error, + ); + process.exitCode = 1; + }); + } }