This commit is contained in:
Hongpeng Jin 2026-01-30 11:55:31 +00:00 committed by GitHub
commit ab2a54275e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 51 additions and 3 deletions

View File

@ -9,6 +9,8 @@ read_when:
Open the terminal UI connected to the Gateway.
Tip: If you pass `--url`, Moltbot treats this as client-only mode and wont block on local config validation.
Related:
- TUI guide: [TUI](/tui)
@ -19,4 +21,3 @@ openclaw tui
openclaw tui --url ws://127.0.0.1:18789 --token <token>
openclaw tui --session main --deliver
```

View File

@ -1,7 +1,7 @@
import type { Command } from "commander";
import { defaultRuntime } from "../../runtime.js";
import { emitCliBanner } from "../banner.js";
import { getCommandPath, getVerboseFlag, hasHelpOrVersion } from "../argv.js";
import { getCommandPath, getFlagValue, getVerboseFlag, hasHelpOrVersion } from "../argv.js";
import { ensureConfigReady } from "./config-guard.js";
import { ensurePluginRegistryLoaded } from "../plugin-registry.js";
import { isTruthyEnvValue } from "../../infra/env.js";
@ -41,7 +41,12 @@ export function registerPreActionHooks(program: Command, programVersion: string)
process.env.NODE_NO_WARNINGS ??= "1";
}
if (commandPath[0] === "doctor") return;
await ensureConfigReady({ runtime: defaultRuntime, commandPath });
// `tui --url` is client-only, so it should not require a valid local config (e.g. local plugins).
const url = commandPath[0] === "tui" ? getFlagValue(argv, "--url") : undefined;
const shouldBypassConfigGuardForTui = typeof url === "string" && url.trim().length > 0;
if (!shouldBypassConfigGuardForTui) {
await ensureConfigReady({ runtime: defaultRuntime, commandPath });
}
// Load plugins for commands that need channel access
if (PLUGIN_REQUIRED_COMMANDS.has(commandPath[0])) {
ensurePluginRegistryLoaded();

View File

@ -0,0 +1,42 @@
import { Command } from "commander";
import { afterEach, describe, expect, it, vi } from "vitest";
const ensureConfigReady = vi.fn(async () => undefined);
vi.mock("./config-guard.js", () => ({ ensureConfigReady }));
const { registerPreActionHooks } = await import("./preaction.js");
describe("cli preAction config guard", () => {
const originalArgv = process.argv.slice();
afterEach(() => {
process.argv = originalArgv.slice();
vi.clearAllMocks();
});
it("bypasses config guard for tui --url (client mode)", async () => {
process.argv = ["node", "moltbot", "tui", "--url", "ws://example"];
const program = new Command();
registerPreActionHooks(program, "test");
const tuiAction = vi.fn(async () => undefined);
program.command("tui").option("--url <url>").action(tuiAction);
await program.parseAsync(["tui", "--url", "ws://example"], { from: "user" });
expect(ensureConfigReady).not.toHaveBeenCalled();
expect(tuiAction).toHaveBeenCalled();
});
it("runs config guard for tui without --url", async () => {
process.argv = ["node", "moltbot", "tui"];
const program = new Command();
registerPreActionHooks(program, "test");
program.command("tui").action(async () => undefined);
await program.parseAsync(["tui"], { from: "user" });
expect(ensureConfigReady).toHaveBeenCalled();
});
});