diff --git a/extensions/browser/src/cli/browser-cli-actions-input/register.files-downloads.ts b/extensions/browser/src/cli/browser-cli-actions-input/register.files-downloads.ts index 3d4c96abdef..1f61d1fd85e 100644 --- a/extensions/browser/src/cli/browser-cli-actions-input/register.files-downloads.ts +++ b/extensions/browser/src/cli/browser-cli-actions-input/register.files-downloads.ts @@ -103,24 +103,29 @@ export function registerBrowserFilesAndDownloadsCommands( (v: string) => Number(v), ) .action(async (paths: string[], opts, cmd) => { - const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); - const normalizedPaths = await normalizeUploadPaths(paths); - const { timeoutMs, targetId } = resolveTimeoutAndTarget(opts); - await runBrowserPostAction({ - parent, - profile, - path: "/hooks/file-chooser", - body: { - paths: normalizedPaths, - ref: normalizeOptionalString(opts.ref), - inputRef: normalizeOptionalString(opts.inputRef), - element: normalizeOptionalString(opts.element), - targetId, - timeoutMs, - }, - timeoutMs: timeoutMs ?? DEFAULT_BROWSER_HOOK_TIMEOUT_MS, - describeSuccess: () => `upload armed for ${paths.length} file(s)`, - }); + try { + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); + const normalizedPaths = await normalizeUploadPaths(paths); + const { timeoutMs, targetId } = resolveTimeoutAndTarget(opts); + await runBrowserPostAction({ + parent, + profile, + path: "/hooks/file-chooser", + body: { + paths: normalizedPaths, + ref: normalizeOptionalString(opts.ref), + inputRef: normalizeOptionalString(opts.inputRef), + element: normalizeOptionalString(opts.element), + targetId, + timeoutMs, + }, + timeoutMs: timeoutMs ?? DEFAULT_BROWSER_HOOK_TIMEOUT_MS, + describeSuccess: () => `upload armed for ${paths.length} file(s)`, + }); + } catch (err) { + defaultRuntime.error(danger(String(err))); + defaultRuntime.exit(1); + } }); browser diff --git a/src/cli/argv.ts b/src/cli/argv.ts index 816ff7b52fe..903200e1a5d 100644 --- a/src/cli/argv.ts +++ b/src/cli/argv.ts @@ -117,7 +117,7 @@ export function hasRootVersionAlias(argv: string[]): boolean { continue; } if (arg.startsWith("-")) { - continue; + return false; } return false; } diff --git a/src/cli/daemon-cli/test-helpers/lifecycle-core-harness.ts b/src/cli/daemon-cli/test-helpers/lifecycle-core-harness.ts index 792cea69785..a2c3b580fe8 100644 --- a/src/cli/daemon-cli/test-helpers/lifecycle-core-harness.ts +++ b/src/cli/daemon-cli/test-helpers/lifecycle-core-harness.ts @@ -39,14 +39,14 @@ export function resetLifecycleRuntimeLogs() { } export function resetLifecycleServiceMocks() { - service.stage.mockClear(); - service.install.mockClear(); - service.uninstall.mockClear(); - service.stop.mockClear(); - service.isLoaded.mockClear(); - service.readCommand.mockClear(); - service.readRuntime.mockClear(); - service.restart.mockClear(); + service.stage.mockReset(); + service.install.mockReset(); + service.uninstall.mockReset(); + service.stop.mockReset(); + service.isLoaded.mockReset(); + service.readCommand.mockReset(); + service.readRuntime.mockReset(); + service.restart.mockReset(); service.isLoaded.mockResolvedValue(true); service.readCommand.mockResolvedValue({ programArguments: [], environment: {} }); service.readRuntime.mockResolvedValue({ status: "running" }); diff --git a/src/cli/gateway-run-argv.ts b/src/cli/gateway-run-argv.ts index 5c915283a95..394c8cbac6a 100644 --- a/src/cli/gateway-run-argv.ts +++ b/src/cli/gateway-run-argv.ts @@ -4,6 +4,7 @@ const GATEWAY_RUN_VALUE_FLAGS = new Set([ "--port", "--bind", "--token", + "--token-file", "--auth", "--password", "--password-file", diff --git a/src/cli/node-cli/register.ts b/src/cli/node-cli/register.ts index 784852e5130..1e2dd161e40 100644 --- a/src/cli/node-cli/register.ts +++ b/src/cli/node-cli/register.ts @@ -48,7 +48,7 @@ export function registerNodeCli(program: Command) { .description("Run the headless node host (foreground)") .option("--host ", "Gateway host") .option("--port ", "Gateway port") - .option("--tls", "Use TLS for the gateway connection", false) + .option("--tls", "Use TLS for the gateway connection") .option("--tls-fingerprint ", "Expected TLS certificate fingerprint (sha256)") .option("--node-id ", "Override node id (clears pairing token)") .option("--display-name ", "Override node display name") @@ -67,8 +67,12 @@ export function registerNodeCli(program: Command) { await runNodeHost({ gatewayHost: host, gatewayPort: port, - gatewayTls: Boolean(opts.tls) || Boolean(opts.tlsFingerprint), - gatewayTlsFingerprint: opts.tlsFingerprint, + gatewayTls: + typeof opts.tls === "boolean" + ? opts.tls + : Boolean(opts.tlsFingerprint ?? existing?.gateway?.tlsFingerprint) || + existing?.gateway?.tls, + gatewayTlsFingerprint: opts.tlsFingerprint ?? existing?.gateway?.tlsFingerprint, nodeId: opts.nodeId, displayName: opts.displayName, }); diff --git a/src/cli/profile.test.ts b/src/cli/profile.test.ts index 617eee78b41..02f55797b7a 100644 --- a/src/cli/profile.test.ts +++ b/src/cli/profile.test.ts @@ -168,6 +168,7 @@ describe("applyCliProfileEnv", () => { it("does not override explicit env values", () => { const env: Record = { + OPENCLAW_PROFILE: "prod", OPENCLAW_STATE_DIR: "/custom", OPENCLAW_GATEWAY_PORT: "19099", }; @@ -176,6 +177,7 @@ describe("applyCliProfileEnv", () => { env, homedir: () => "/home/peter", }); + expect(env.OPENCLAW_PROFILE).toBe("dev"); expect(env.OPENCLAW_STATE_DIR).toBe("/custom"); expect(env.OPENCLAW_GATEWAY_PORT).toBe("19099"); expect(env.OPENCLAW_CONFIG_PATH).toBe(path.join("/custom", "openclaw.json")); diff --git a/src/cli/program/message/helpers.ts b/src/cli/program/message/helpers.ts index 8f950ccff51..def381c726f 100644 --- a/src/cli/program/message/helpers.ts +++ b/src/cli/program/message/helpers.ts @@ -35,7 +35,7 @@ function normalizeMessageOptions(opts: Record): Record { expect(writes).toStrictEqual([]); }); + + it("unregisters a delayed tty progress line when done before start", () => { + const firstWrites: string[] = []; + const firstStream = { + isTTY: true, + write: vi.fn((chunk: string) => { + firstWrites.push(chunk); + }), + } as unknown as NodeJS.WriteStream; + const secondStream = { + isTTY: true, + write: vi.fn(), + } as unknown as NodeJS.WriteStream; + + const delayed = createCliProgress({ + label: "Delayed", + stream: firstStream, + fallback: "line", + delayMs: 10_000, + }); + delayed.done(); + + const next = createCliProgress({ + label: "Next", + stream: secondStream, + fallback: "line", + }); + next.done(); + + expect(firstWrites).toStrictEqual([]); + }); }); diff --git a/src/cli/progress.ts b/src/cli/progress.ts index 742bb958752..9df04412b14 100644 --- a/src/cli/progress.ts +++ b/src/cli/progress.ts @@ -197,6 +197,9 @@ export function createCliProgress(options: ProgressOptions): ProgressReporter { timer = null; } if (!started) { + if (isTty) { + unregisterActiveProgressLine(stream); + } activeProgress = Math.max(0, activeProgress - 1); return; } diff --git a/src/cli/secrets-cli.ts b/src/cli/secrets-cli.ts index 1d42ec394ef..6bf110fb46b 100644 --- a/src/cli/secrets-cli.ts +++ b/src/cli/secrets-cli.ts @@ -213,7 +213,7 @@ export function registerSecretsCli(program: Command): void { } } - let shouldApply = Boolean(opts.apply); + let shouldApply = Boolean(opts.apply || opts.yes); if (!shouldApply && !opts.json) { const { confirm } = await import("@clack/prompts"); const approved = await confirm({