UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

355 lines (354 loc) 14.2 kB
import { n as consumeRootOptionToken } from "./cli-root-options-CgExE0zj.js"; import { f as isSimpleCommandHelpInvocation, n as getCommandPathWithRootOptions } from "./argv-DNjh_yaF.js"; import { l as normalizeOptionalString } from "./string-coerce-CIXf7egm.js"; import { t as resolveCliArgvInvocation } from "./argv-invocation-C1WhAkJL.js"; import { a as scanCliRootOptions, i as takeCliRootOptionValue } from "./container-target-yd6OnwF_.js"; import { a as GATEWAY_SERVICE_SELECTOR_ENV_KEYS, c as isGatewayServiceEnv, l as resolveGatewayLaunchAgentLabel, m as resolveGatewayWindowsTaskName, p as resolveGatewaySystemdServiceName } from "./constants-ChqKLfPp.js"; import { r as resolveHomeRelativePath } from "./home-dir-BPhrG-aM.js"; import { r as resolveProfileStateDir, t as isValidProfileName } from "./profile-utils-Bkq2PPxE.js"; import { n as isTruthyEnvValue } from "./env-M3R40TOb.js"; import process$1 from "node:process"; import path from "node:path"; import os from "node:os"; //#region src/cli/precomputed-help.ts const PRECOMPUTED_COMMAND_HELP_NAMES = /* @__PURE__ */ new Set([ "browser", "secrets", "nodes" ]); const PRECOMPUTED_SUBCOMMAND_HELP_COMMANDS = /* @__PURE__ */ new Set([ "config", "doctor", "gateway", "models", "plugins", "sessions", "tasks" ]); const HELP_FLAGS = /* @__PURE__ */ new Set(["-h", "--help"]); const VERSION_FLAGS = /* @__PURE__ */ new Set(["-V", "--version"]); const loadRootHelpLiveConfigModule = async () => await import("./root-help-live-config-DLFpCf-w.js"); const loadRootHelpMetadataModule = async () => await import("./root-help-metadata-BCFFf7h3.js"); function isPrecomputedSubcommandHelpName(value) { return PRECOMPUTED_SUBCOMMAND_HELP_COMMANDS.has(value); } function resolvePrecomputedSubcommandHelpCommand(argv) { const args = argv.slice(2); let commandName = null; let sawHelp = false; for (let index = 0; index < args.length; index += 1) { const arg = args[index]; if (!arg || arg === "--") return null; if (VERSION_FLAGS.has(arg)) return null; if (!commandName) { const consumed = consumeRootOptionToken(args, index); if (consumed > 0) { index += consumed - 1; continue; } if (arg.startsWith("-") || !isPrecomputedSubcommandHelpName(arg)) return null; commandName = arg; continue; } if (HELP_FLAGS.has(arg)) { sawHelp = true; continue; } return null; } return commandName && sawHelp ? commandName : null; } function resolvePrecomputedCommandHelpName(argv) { if (!isSimpleCommandHelpInvocation(argv, PRECOMPUTED_COMMAND_HELP_NAMES)) return null; const commandPath = getCommandPathWithRootOptions(argv, 2); if (commandPath.length !== 1) return null; const [commandName] = commandPath; return commandName === "browser" || commandName === "secrets" || commandName === "nodes" ? commandName : null; } async function tryOutputPrecomputedCommandHelp(argv, deps = {}) { const env = deps.env ?? process.env; if (env.OPENCLAW_DISABLE_CLI_STARTUP_HELP_FAST_PATH === "1") return false; const commandName = resolvePrecomputedCommandHelpName(argv); const subcommandName = commandName ? null : resolvePrecomputedSubcommandHelpCommand(argv); if (subcommandName) return (deps.outputPrecomputedSubcommandHelpText ?? (await loadRootHelpMetadataModule()).outputPrecomputedSubcommandHelpText)(subcommandName); if (!commandName) return false; if (commandName === "nodes") { if (await (deps.loadRootHelpRenderOptionsForConfigSensitivePlugins ?? (await loadRootHelpLiveConfigModule()).loadRootHelpRenderOptionsForConfigSensitivePlugins)(env)) return false; } if (commandName === "browser") return (deps.outputPrecomputedBrowserHelpText ?? (await loadRootHelpMetadataModule()).outputPrecomputedBrowserHelpText)(); if (commandName === "secrets") return (deps.outputPrecomputedSecretsHelpText ?? (await loadRootHelpMetadataModule()).outputPrecomputedSecretsHelpText)(); return (deps.outputPrecomputedNodesHelpText ?? (await loadRootHelpMetadataModule()).outputPrecomputedNodesHelpText)(); } //#endregion //#region src/cli/profile.ts function parseCliProfileArgs(argv) { let profile = null; let sawDev = false; const scanned = scanCliRootOptions(argv, ({ arg, args, index, out }) => { if (arg === "--dev") { if (resolveCliArgvInvocation(out).primary === "gateway") { out.push(arg); return { kind: "handled" }; } if (profile && profile !== "dev") return { kind: "error", error: "Cannot combine --dev with --profile" }; sawDev = true; profile = "dev"; return { kind: "handled" }; } if (arg === "--profile" || arg.startsWith("--profile=")) { const next = args[index + 1]; const { value, consumedNext } = takeCliRootOptionValue(arg, next); const [primary, secondary] = resolveCliArgvInvocation(out).commandPath; if (primary === "qa" && secondary === "matrix") { out.push(arg); if (consumedNext && next !== void 0) out.push(next); return { kind: "handled", consumedNext }; } if (sawDev) return { kind: "error", error: "Cannot combine --dev with --profile" }; if (!value) return { kind: "error", error: "--profile requires a value" }; if (!isValidProfileName(value)) return { kind: "error", error: "Invalid --profile (use letters, numbers, \"_\", \"-\" only)" }; profile = value; return { kind: "handled", consumedNext }; } return { kind: "pass" }; }); if (!scanned.ok) return scanned; return { ok: true, profile, argv: scanned.argv }; } function applyCliProfileEnv(params) { const env = params.env ?? process.env; const homedir = params.homedir ?? os.homedir; const profile = params.profile.trim(); if (!profile) return; const inheritedProfile = normalizeOptionalString(env.OPENCLAW_PROFILE) ?? "default"; const existingStateDir = normalizeOptionalString(env.OPENCLAW_STATE_DIR); const existingConfigPath = normalizeOptionalString(env.OPENCLAW_CONFIG_PATH); const profileEnv = env; const inheritedProfileStateDir = resolveProfileStateDir(inheritedProfile, profileEnv, homedir); const selectedProfileStateDir = resolveProfileStateDir(profile, profileEnv, homedir); const switchesInheritedProfile = inheritedProfileStateDir !== selectedProfileStateDir; const inheritedSystemdServiceName = resolveGatewaySystemdServiceName(inheritedProfile); const inheritedServiceSelectors = { OPENCLAW_LAUNCHD_LABEL: [resolveGatewayLaunchAgentLabel(inheritedProfile)], OPENCLAW_SYSTEMD_UNIT: [inheritedSystemdServiceName, `${inheritedSystemdServiceName}.service`], OPENCLAW_WINDOWS_TASK_NAME: [resolveGatewayWindowsTaskName(inheritedProfile)] }; const switchesInheritedProfileState = Boolean(existingStateDir && switchesInheritedProfile && resolveHomeRelativePath(existingStateDir, { env, homedir }) === inheritedProfileStateDir); const replacesInheritedProfileConfig = Boolean(switchesInheritedProfile && (!existingStateDir || switchesInheritedProfileState) && existingConfigPath && resolveHomeRelativePath(existingConfigPath, { env, homedir }) === path.join(inheritedProfileStateDir, "openclaw.json")); const inheritedManagedServiceSelectors = switchesInheritedProfile && isGatewayServiceEnv(env) && switchesInheritedProfileState && replacesInheritedProfileConfig; if (inheritedManagedServiceSelectors) for (const key of GATEWAY_SERVICE_SELECTOR_ENV_KEYS) delete env[key]; env.OPENCLAW_PROFILE = profile; const retainedStateDir = inheritedManagedServiceSelectors ? void 0 : existingStateDir; const stateDir = retainedStateDir && !switchesInheritedProfileState ? retainedStateDir : selectedProfileStateDir; if (!retainedStateDir || switchesInheritedProfileState) env.OPENCLAW_STATE_DIR = stateDir; if (!inheritedManagedServiceSelectors && (!existingConfigPath || replacesInheritedProfileConfig)) env.OPENCLAW_CONFIG_PATH = path.join(stateDir, "openclaw.json"); if (switchesInheritedProfile && !inheritedManagedServiceSelectors) for (const [key, inheritedValues] of Object.entries(inheritedServiceSelectors)) { const activeValue = normalizeOptionalString(env[key]); if (activeValue && inheritedValues.includes(activeValue)) delete env[key]; } if (profile === "dev" && !env.OPENCLAW_GATEWAY_PORT?.trim()) env.OPENCLAW_GATEWAY_PORT = "19001"; } //#endregion //#region src/cli/startup-trace.ts const CLI_STARTUP_TIMELINE_PHASE = "cli.startup"; function hasDiagnosticsTimelinePath(env) { return Boolean(env.OPENCLAW_DIAGNOSTICS_TIMELINE_PATH?.trim()); } function createGatewayDispatchStartupTrace(argv, source) { const enabled = isTruthyEnvValue(process$1.env.OPENCLAW_GATEWAY_STARTUP_TRACE) && argv.slice(2).includes("gateway"); const started = performance.now(); let last = started; let lineFormatter = null; let pendingMessages = []; const timelineModule = hasDiagnosticsTimelinePath(process$1.env) ? import("./diagnostics-timeline-DHELrNVe.js").catch(() => null) : null; let timelineActivation = timelineModule ? "unknown" : "disabled"; let timelineConfig; let timelineConfigResolved = false; const pendingTimelineEvents = []; let pendingTimelineWrites = Promise.resolve(); const timelineName = (name) => `${source}.${name}`; const resolveTimelineActivation = async () => { if (timelineActivation !== "unknown" || !timelineModule) return timelineActivation; const module = await timelineModule; if (!module) { timelineActivation = "disabled"; return timelineActivation; } if (module.isDiagnosticsTimelineEnabled({ env: process$1.env })) { timelineActivation = "enabled"; return timelineActivation; } if (timelineConfigResolved) timelineActivation = module.isDiagnosticsTimelineEnabled({ config: timelineConfig, env: process$1.env }) ? "enabled" : "disabled"; return timelineActivation; }; const writeTimelineEvent = (module, event) => { const commonOptions = { ...timelineConfig ? { config: timelineConfig } : {}, env: process$1.env }; if (event.type === "mark") { module.emitDiagnosticsTimelineEvent({ type: "mark", name: event.name, phase: CLI_STARTUP_TIMELINE_PHASE, durationMs: event.durationMs, attributes: { totalMs: event.totalMs } }, commonOptions); return; } module.emitCompletedDiagnosticsTimelineSpan(event.name, event.durationMs, { phase: CLI_STARTUP_TIMELINE_PHASE, ...commonOptions }); }; const flushPendingTimelineEvents = async () => { const activation = await resolveTimelineActivation(); if (activation === "unknown") return; if (activation === "disabled") { pendingTimelineEvents.length = 0; return; } const module = await timelineModule; if (!module) { pendingTimelineEvents.length = 0; return; } const events = pendingTimelineEvents.splice(0); for (const event of events) writeTimelineEvent(module, event); }; const enqueueTimelineEvent = (event) => { if (!timelineModule || timelineActivation === "disabled") return; if (timelineActivation === "unknown") { pendingTimelineEvents.push(event); return; } pendingTimelineWrites = pendingTimelineWrites.then(async () => { const module = await timelineModule; if (module) writeTimelineEvent(module, event); }); }; const flushPending = (formatter) => { const queued = pendingMessages; pendingMessages = []; for (const message of queued) process$1.stderr.write(`${formatter(message)}\n`); }; const flushPendingPlainOnExit = () => { if (!lineFormatter) flushPending((message) => message); }; if (enabled) process$1.once("exit", flushPendingPlainOnExit); const writeMessage = (message) => { if (!lineFormatter) { pendingMessages.push(message); return; } process$1.stderr.write(`${lineFormatter(message)}\n`); }; const emit = (name, durationMs, totalMs) => { if (!enabled) return; writeMessage(`[gateway] startup trace: ${source}.${name} ${durationMs.toFixed(1)}ms total=${totalMs.toFixed(1)}ms`); }; return { enabled, async requiresDiagnosticsConfig() { await flushPendingTimelineEvents(); return timelineActivation === "unknown"; }, async configureDiagnosticsTimeline(config) { timelineConfig = config; timelineConfigResolved = true; await flushPendingTimelineEvents(); await pendingTimelineWrites; }, setLineFormatter(formatter) { lineFormatter = formatter; process$1.off("exit", flushPendingPlainOnExit); flushPending(formatter); }, mark(name) { const now = performance.now(); const durationMs = now - last; const totalMs = now - started; emit(name, durationMs, totalMs); enqueueTimelineEvent({ type: "mark", name: timelineName(name), durationMs, totalMs }); last = now; }, async measure(name, run, options = {}) { const before = performance.now(); let bufferCompletedTimelineSpan = false; let completed = false; try { if (timelineModule && options.timeline !== false) { await flushPendingTimelineEvents(); const module = await timelineModule; if (module && timelineActivation === "enabled") { await pendingTimelineWrites; return await module.measureDiagnosticsTimelineSpan(timelineName(name), () => Promise.resolve(run()), { phase: CLI_STARTUP_TIMELINE_PHASE, ...timelineConfig ? { config: timelineConfig } : {}, env: process$1.env }); } bufferCompletedTimelineSpan = timelineActivation === "unknown"; } const result = await run(); completed = true; return result; } finally { const now = performance.now(); if (bufferCompletedTimelineSpan && completed) enqueueTimelineEvent({ type: "span", name: timelineName(name), durationMs: now - before }); emit(name, now - before, now - started); last = now; } } }; } async function configureGatewayStartupTraceConsoleFormatting(trace) { if (!trace.enabled) return; const { formatConsoleDiagnosticLine } = await import("./json-console-line-kiRP3hor.js"); trace.setLineFormatter((message) => formatConsoleDiagnosticLine({ level: "info", message })); } //#endregion export { tryOutputPrecomputedCommandHelp as a, parseCliProfileArgs as i, createGatewayDispatchStartupTrace as n, applyCliProfileEnv as r, configureGatewayStartupTraceConsoleFormatting as t };