UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

282 lines (281 loc) 10.1 kB
import { d as normalizeSecretInputString, m as resolveSecretInputRef } from "./types.secrets-_0JOMGE5.js"; import { a as findTailscaleBinary } from "./tailscale-BOFw04AY.js"; import { t as randomToken } from "./random-token-B1woZa_H.js"; import { o as formatPortRangeHint } from "./error-format-COoNML-C.js"; import { t as resolveSecretInputModeForEnvSelection } from "./provider-auth-mode-7FOSjRoY.js"; import { n as promptSecretRefForSetup } from "./provider-auth-ref-yqvdWH30.js"; import { n as t } from "./i18n-7g_f4oaD.js"; import { t as DEFAULT_DANGEROUS_NODE_COMMANDS } from "./node-command-policy-DYPdfWjH.js"; import { t as maskApiKey } from "./mask-api-key-D2MLa8WN.js"; import { c as normalizeGatewayTokenInput, p as validateGatewayPasswordInput } from "./onboard-helpers-DXyUiHQ-.js"; import { t as resolveSetupSecretInputString } from "./setup.secret-input-BOdMUWYa.js"; import { a as validateIPv4AddressInput, i as maybeAddTailnetOriginToControlUiAllowedOrigins, n as TAILSCALE_EXPOSURE_OPTIONS } from "./gateway-config-prompts.shared-Bx9Y06Mk.js"; import { n as ensureControlUiAllowedOriginsForNonLoopbackBind } from "./gateway-control-ui-origins-DdvpUKq8.js"; //#region src/wizard/setup.gateway-config.ts function getLocalizedTailscaleExposureOptions() { return TAILSCALE_EXPOSURE_OPTIONS.map((option) => ({ hint: t(`wizard.gatewayTailscale.${option.value}Hint`), label: t(`wizard.gatewayTailscale.${option.value}`), value: option.value })); } function normalizeWizardTextInput(value) { return typeof value === "string" ? value.trim() : ""; } function validateGatewayPortInput(value) { const port = Number(normalizeWizardTextInput(value)); if (!Number.isInteger(port) || port < 1 || port > 65535) return formatPortRangeHint(); } async function configureGatewayForSetup(opts) { const { flow, localPort, quickstartGateway, prompter } = opts; let { nextConfig } = opts; const port = flow === "quickstart" ? quickstartGateway.port : Number.parseInt(normalizeWizardTextInput(await prompter.text({ message: t("wizard.gateway.port"), initialValue: String(localPort), validate: validateGatewayPortInput })), 10); let bind = flow === "quickstart" ? quickstartGateway.bind : await prompter.select({ message: t("wizard.gateway.bindAddress"), options: [ { value: "loopback", label: t("wizard.gateway.bindLoopback"), hint: t("wizard.gateway.bindLoopbackHint") }, { value: "lan", label: t("wizard.gateway.bindLan"), hint: t("wizard.gateway.bindLanHint") }, { value: "tailnet", label: t("wizard.gateway.bindTailnet"), hint: t("wizard.gateway.bindTailnetHint") }, { value: "auto", label: t("wizard.gateway.bindAuto"), hint: t("wizard.gateway.bindAutoHint") }, { value: "custom", label: t("wizard.gateway.bindCustom"), hint: t("wizard.gateway.bindCustomHint") } ] }); let customBindHost = quickstartGateway.customBindHost; if (bind === "custom") { if (flow !== "quickstart" || !customBindHost) { const input = await prompter.text({ message: t("wizard.gateway.bindCustomIp"), placeholder: "192.168.1.100", initialValue: customBindHost ?? "", validate: validateIPv4AddressInput }); customBindHost = typeof input === "string" ? input.trim() : void 0; } } let authMode = flow === "quickstart" ? quickstartGateway.authMode : await prompter.select({ message: t("wizard.gateway.accessProtection"), options: [{ value: "token", label: t("common.tokenRecommended"), hint: t("wizard.gateway.plaintextTokenHint") }, { value: "password", label: t("common.password") }], initialValue: "token" }); const tailscaleMode = flow === "quickstart" ? quickstartGateway.tailscaleMode : await prompter.select({ message: t("wizard.gateway.tailscaleExposure"), options: getLocalizedTailscaleExposureOptions() }); let tailscaleBin = null; if (tailscaleMode !== "off") { tailscaleBin = await findTailscaleBinary(); if (!tailscaleBin) await prompter.note(t("wizard.gatewayTailscale.missingBinNote"), t("wizard.gatewayTailscale.warningTitle")); } let tailscaleResetOnExit = flow === "quickstart" ? quickstartGateway.tailscaleResetOnExit : false; if (tailscaleMode !== "off" && flow !== "quickstart") { await prompter.note(t("wizard.gatewayTailscale.docsNote"), "Tailscale"); tailscaleResetOnExit = await prompter.confirm({ message: t("wizard.gateway.tailscaleReset"), initialValue: false }); } if (tailscaleMode !== "off" && bind !== "loopback") { await prompter.note(t("wizard.gatewayNotes.tailscaleBindLoopback"), t("wizard.gatewayNotes.bindTitle")); bind = "loopback"; customBindHost = void 0; } if (tailscaleMode === "funnel" && authMode !== "password") { await prompter.note(t("wizard.gatewayNotes.tailscaleFunnelPassword"), t("wizard.gateway.auth")); authMode = "password"; } let gatewayToken; let gatewayTokenInput; if (authMode === "token") { const quickstartTokenString = normalizeSecretInputString(quickstartGateway.token); const quickstartTokenRef = resolveSecretInputRef({ value: quickstartGateway.token, defaults: nextConfig.secrets?.defaults }).ref; if ((flow === "quickstart" && opts.secretInputMode !== "ref" ? quickstartTokenRef ? "ref" : "plaintext" : await resolveSecretInputModeForEnvSelection({ prompter, explicitMode: opts.secretInputMode, copy: { modeMessage: t("wizard.gateway.authTokenMode"), plaintextLabel: t("wizard.gateway.plaintextTokenLabel"), plaintextHint: t("wizard.gateway.plaintextTokenHint"), refLabel: t("wizard.gateway.refLabel"), refHint: t("wizard.gateway.refHint") } })) === "ref") if (flow === "quickstart" && quickstartTokenRef) { gatewayTokenInput = quickstartTokenRef; gatewayToken = await resolveSetupSecretInputString({ config: nextConfig, value: quickstartTokenRef, path: "gateway.auth.token", env: process.env }); } else { const resolved = await promptSecretRefForSetup({ provider: "gateway-auth-token", config: nextConfig, prompter, preferredEnvVar: "OPENCLAW_GATEWAY_TOKEN", copy: { sourceMessage: t("wizard.gateway.authTokenStoredMessage"), envVarPlaceholder: "OPENCLAW_GATEWAY_TOKEN" } }); gatewayTokenInput = resolved.ref; gatewayToken = resolved.resolvedValue; } else if (flow === "quickstart") { gatewayToken = (quickstartTokenString ?? normalizeGatewayTokenInput(process.env.OPENCLAW_GATEWAY_TOKEN)) || randomToken(); gatewayTokenInput = gatewayToken; } else { const existingToken = quickstartTokenString ?? normalizeGatewayTokenInput(process.env.OPENCLAW_GATEWAY_TOKEN); let tokenInput; if (existingToken) tokenInput = await prompter.confirm({ message: t("wizard.gateway.existingTokenConfirm", { token: maskApiKey(existingToken) }), initialValue: true }) ? existingToken : await prompter.text({ message: t("wizard.gateway.tokenPromptGenerate"), placeholder: t("wizard.gateway.tokenPlaceholder"), sensitive: true }); else tokenInput = await prompter.text({ message: t("wizard.gateway.tokenPromptGenerate"), placeholder: t("wizard.gateway.tokenPlaceholder"), sensitive: true }); gatewayToken = normalizeGatewayTokenInput(tokenInput) || randomToken(); gatewayTokenInput = gatewayToken; } } if (authMode === "password") { let password = flow === "quickstart" && quickstartGateway.password ? quickstartGateway.password : void 0; if (!password) if (await resolveSecretInputModeForEnvSelection({ prompter, explicitMode: opts.secretInputMode, copy: { modeMessage: t("wizard.gateway.authPasswordMode"), plaintextLabel: t("wizard.gateway.plaintextPasswordLabel"), plaintextHint: t("wizard.gateway.plaintextPasswordHint") } }) === "ref") password = (await promptSecretRefForSetup({ provider: "gateway-auth-password", config: nextConfig, prompter, preferredEnvVar: "OPENCLAW_GATEWAY_PASSWORD", copy: { sourceMessage: t("wizard.gateway.authPasswordStoredMessage"), envVarPlaceholder: "OPENCLAW_GATEWAY_PASSWORD" } })).ref; else password = normalizeWizardTextInput(await prompter.text({ message: t("wizard.gateway.passwordPrompt"), validate: validateGatewayPasswordInput, sensitive: true })); nextConfig = { ...nextConfig, gateway: { ...nextConfig.gateway, auth: { ...nextConfig.gateway?.auth, mode: "password", password } } }; } else if (authMode === "token") nextConfig = { ...nextConfig, gateway: { ...nextConfig.gateway, auth: { ...nextConfig.gateway?.auth, mode: "token", token: gatewayTokenInput } } }; nextConfig = { ...nextConfig, gateway: { ...nextConfig.gateway, port, bind, ...bind === "custom" && customBindHost ? { customBindHost } : {}, tailscale: { ...nextConfig.gateway?.tailscale, mode: tailscaleMode, resetOnExit: tailscaleResetOnExit } } }; if (flow === "quickstart" && bind === "loopback" && nextConfig.gateway?.controlUi?.allowInsecureAuth === void 0) nextConfig = { ...nextConfig, gateway: { ...nextConfig.gateway, controlUi: { ...nextConfig.gateway?.controlUi, allowInsecureAuth: true } } }; nextConfig = ensureControlUiAllowedOriginsForNonLoopbackBind(nextConfig, { requireControlUiEnabled: true }).config; nextConfig = await maybeAddTailnetOriginToControlUiAllowedOrigins({ config: nextConfig, tailscaleMode, tailscaleBin }); if (!quickstartGateway.hasExisting && nextConfig.gateway?.nodes?.denyCommands === void 0 && nextConfig.gateway?.nodes?.allowCommands === void 0 && nextConfig.gateway?.nodes?.browser === void 0) nextConfig = { ...nextConfig, gateway: { ...nextConfig.gateway, nodes: { ...nextConfig.gateway?.nodes, denyCommands: [...DEFAULT_DANGEROUS_NODE_COMMANDS] } } }; return { nextConfig, settings: { port, bind, customBindHost: bind === "custom" ? customBindHost : void 0, authMode, gatewayToken, tailscaleMode, tailscaleResetOnExit } }; } //#endregion export { configureGatewayForSetup };