diff --git a/src/cli/daemon-cli/install.test.ts b/src/cli/daemon-cli/install.test.ts index dad1497b0d9..fb7e3255cb4 100644 --- a/src/cli/daemon-cli/install.test.ts +++ b/src/cli/daemon-cli/install.test.ts @@ -68,9 +68,12 @@ vi.mock("../../bootstrap/node-startup-env.js", () => ({ vi.mock("../../config/config.js", () => ({ loadConfig: loadConfigMock, readBestEffortConfig: loadConfigMock, + resolveGatewayPort: resolveGatewayPortMock, +})); + +vi.mock("../../commands/gateway-install-token.persist.runtime.js", () => ({ readConfigFileSnapshot: readConfigFileSnapshotMock, replaceConfigFile: replaceConfigFileMock, - resolveGatewayPort: resolveGatewayPortMock, })); vi.mock("../../config/paths.js", () => ({ @@ -90,7 +93,7 @@ vi.mock("../../secrets/resolve.js", () => ({ resolveSecretRefValues: resolveSecretRefValuesMock, })); -vi.mock("../../commands/onboard-helpers.js", () => ({ +vi.mock("../../commands/random-token.js", () => ({ randomToken: randomTokenMock, })); diff --git a/src/commands/gateway-install-token.persist.runtime.ts b/src/commands/gateway-install-token.persist.runtime.ts new file mode 100644 index 00000000000..5d819e66d92 --- /dev/null +++ b/src/commands/gateway-install-token.persist.runtime.ts @@ -0,0 +1,2 @@ +export { readConfigFileSnapshot } from "../config/io.js"; +export { replaceConfigFile } from "../config/mutate.js"; diff --git a/src/commands/gateway-install-token.test.ts b/src/commands/gateway-install-token.test.ts index 436338e8efd..c12f70a0c12 100644 --- a/src/commands/gateway-install-token.test.ts +++ b/src/commands/gateway-install-token.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -import type { OpenClawConfig } from "../config/config.js"; +import type { OpenClawConfig } from "../config/types.js"; import { resolveGatewayInstallToken } from "./gateway-install-token.js"; const readConfigFileSnapshotMock = vi.hoisted(() => vi.fn()); @@ -28,7 +28,7 @@ const resolveSecretRefValuesMock = vi.hoisted(() => vi.fn()); const secretRefKeyMock = vi.hoisted(() => vi.fn(() => "env:default:OPENCLAW_GATEWAY_TOKEN")); const randomTokenMock = vi.hoisted(() => vi.fn(() => "generated-token")); -vi.mock("../config/config.js", () => ({ +vi.mock("./gateway-install-token.persist.runtime.js", () => ({ readConfigFileSnapshot: readConfigFileSnapshotMock, replaceConfigFile: replaceConfigFileMock, })); @@ -54,7 +54,7 @@ vi.mock("../secrets/resolve.js", () => ({ resolveSecretRefValues: resolveSecretRefValuesMock, })); -vi.mock("./onboard-helpers.js", () => ({ +vi.mock("./random-token.js", () => ({ randomToken: randomTokenMock, })); diff --git a/src/commands/gateway-install-token.ts b/src/commands/gateway-install-token.ts index 8039001291f..0c66d492bcc 100644 --- a/src/commands/gateway-install-token.ts +++ b/src/commands/gateway-install-token.ts @@ -1,16 +1,12 @@ import { formatCliCommand } from "../cli/command-format.js"; -import { - readConfigFileSnapshot, - replaceConfigFile, - type OpenClawConfig, -} from "../config/config.js"; +import type { OpenClawConfig } from "../config/types.js"; import { resolveSecretInputRef } from "../config/types.secrets.js"; import { shouldRequireGatewayTokenForInstall } from "../gateway/auth-install-policy.js"; import { hasAmbiguousGatewayAuthModeConfig } from "../gateway/auth-mode-policy.js"; import { resolveGatewayAuthToken } from "../gateway/auth-token-resolution.js"; import { resolveGatewayAuth } from "../gateway/auth.js"; import { normalizeOptionalString } from "../shared/string-coerce.js"; -import { randomToken } from "./onboard-helpers.js"; +import { randomToken } from "./random-token.js"; type GatewayInstallTokenOptions = { config: OpenClawConfig; @@ -27,12 +23,23 @@ export type GatewayInstallTokenResolution = { warnings: string[]; }; +let gatewayInstallTokenPersistRuntimePromise: + | Promise + | undefined; + +async function loadGatewayInstallTokenPersistRuntime() { + gatewayInstallTokenPersistRuntimePromise ??= import("./gateway-install-token.persist.runtime.js"); + return gatewayInstallTokenPersistRuntimePromise; +} + async function maybePersistAutoGeneratedGatewayInstallToken(params: { token: string; config: OpenClawConfig; warnings: string[]; }): Promise { try { + const { readConfigFileSnapshot, replaceConfigFile } = + await loadGatewayInstallTokenPersistRuntime(); const snapshot = await readConfigFileSnapshot(); if (snapshot.exists && !snapshot.valid) { params.warnings.push( diff --git a/src/commands/onboard-helpers.ts b/src/commands/onboard-helpers.ts index 11cae4dc164..b2fdff3be95 100644 --- a/src/commands/onboard-helpers.ts +++ b/src/commands/onboard-helpers.ts @@ -1,4 +1,3 @@ -import crypto from "node:crypto"; import fs from "node:fs/promises"; import path from "node:path"; import { inspect } from "node:util"; @@ -25,6 +24,7 @@ import { stylePromptTitle } from "../terminal/prompt-style.js"; import { CONFIG_DIR, shortenHomeInString, shortenHomePath, sleep } from "../utils.js"; import { VERSION } from "../version.js"; import type { NodeManagerChoice, OnboardMode, ResetScope } from "./onboard-types.js"; +export { randomToken } from "./random-token.js"; export { detectBinary }; export { detectBrowserOpenSupport, openUrl, openUrlInBackground, resolveBrowserOpenCommand }; @@ -69,10 +69,6 @@ export function summarizeExistingConfig(config: OpenClawConfig): string { return rows.length ? rows.join("\n") : "No key settings detected."; } -export function randomToken(): string { - return crypto.randomBytes(24).toString("hex"); -} - export function normalizeGatewayTokenInput(value: unknown): string { if (typeof value !== "string") { return ""; diff --git a/src/commands/random-token.ts b/src/commands/random-token.ts new file mode 100644 index 00000000000..c38c7a57d4c --- /dev/null +++ b/src/commands/random-token.ts @@ -0,0 +1,5 @@ +import crypto from "node:crypto"; + +export function randomToken(): string { + return crypto.randomBytes(24).toString("hex"); +}