diff --git a/extensions/irc/src/monitor.ts b/extensions/irc/src/monitor.ts index e4fb64deb56..d4dbec89db8 100644 --- a/extensions/irc/src/monitor.ts +++ b/extensions/irc/src/monitor.ts @@ -40,8 +40,8 @@ export async function monitorIrcProvider(opts: IrcMonitorOptions): Promise<{ sto }); const runtime: RuntimeEnv = opts.runtime ?? { - log: (message: string) => core.logging.getChildLogger().info(message), - error: (message: string) => core.logging.getChildLogger().error(message), + log: (...args: unknown[]) => core.logging.getChildLogger().info(args.map(String).join(" ")), + error: (...args: unknown[]) => core.logging.getChildLogger().error(args.map(String).join(" ")), exit: () => { throw new Error("Runtime exit not available"); }, diff --git a/extensions/nextcloud-talk/src/monitor.ts b/extensions/nextcloud-talk/src/monitor.ts index ecf7b86139f..ca9214fa600 100644 --- a/extensions/nextcloud-talk/src/monitor.ts +++ b/extensions/nextcloud-talk/src/monitor.ts @@ -213,8 +213,8 @@ export async function monitorNextcloudTalkProvider( accountId: opts.accountId, }); const runtime: RuntimeEnv = opts.runtime ?? { - log: (message: string) => core.logging.getChildLogger().info(message), - error: (message: string) => core.logging.getChildLogger().error(message), + log: (...args: unknown[]) => core.logging.getChildLogger().info(args.map(String).join(" ")), + error: (...args: unknown[]) => core.logging.getChildLogger().error(args.map(String).join(" ")), exit: () => { throw new Error("Runtime exit not available"); }, diff --git a/src/auto-reply/status.ts b/src/auto-reply/status.ts index 56d8eabc598..5ad02e40bb5 100644 --- a/src/auto-reply/status.ts +++ b/src/auto-reply/status.ts @@ -261,7 +261,7 @@ const formatUsagePair = (input?: number | null, output?: number | null) => { return `🧮 Tokens: ${inputLabel} in / ${outputLabel} out`; }; -const formatMediaUnderstandingLine = (decisions?: MediaUnderstandingDecision[]) => { +const formatMediaUnderstandingLine = (decisions?: ReadonlyArray) => { if (!decisions || decisions.length === 0) { return null; } diff --git a/src/cli/browser-cli-extension.ts b/src/cli/browser-cli-extension.ts index 2cc404626eb..a04059dfda6 100644 --- a/src/cli/browser-cli-extension.ts +++ b/src/cli/browser-cli-extension.ts @@ -84,6 +84,7 @@ export function registerBrowserExtensionCommands( } catch (err) { defaultRuntime.error(danger(String(err))); defaultRuntime.exit(1); + return; } if (parent?.json) { diff --git a/src/commands/models/scan.ts b/src/commands/models/scan.ts index 3726bf86143..fd5b48bbfa2 100644 --- a/src/commands/models/scan.ts +++ b/src/commands/models/scan.ts @@ -24,6 +24,15 @@ const multiselect = (params: Parameters>[0]) => ), }); +function guardPromptCancel(value: T | symbol, runtime: RuntimeEnv): T { + if (isCancel(value)) { + cancel(stylePromptTitle("Model scan cancelled.") ?? "Model scan cancelled."); + runtime.exit(0); + throw new Error("unreachable"); + } + return value; +} + const pad = (value: string, size: number) => value.padEnd(size); const truncate = (value: string, max: number) => { @@ -262,12 +271,7 @@ export async function modelsScanCommand( initialValues: preselected, }); - if (isCancel(selection)) { - cancel(stylePromptTitle("Model scan cancelled.") ?? "Model scan cancelled."); - runtime.exit(0); - } - - selected = selection; + selected = guardPromptCancel(selection, runtime); if (imageSorted.length > 0) { const imageSelection = await multiselect({ message: "Select image fallback models (ordered)", @@ -279,12 +283,7 @@ export async function modelsScanCommand( initialValues: imagePreselected, }); - if (isCancel(imageSelection)) { - cancel(stylePromptTitle("Model scan cancelled.") ?? "Model scan cancelled."); - runtime.exit(0); - } - - selectedImages = imageSelection; + selectedImages = guardPromptCancel(imageSelection, runtime); } } else if (!process.stdin.isTTY && !opts.yes && !noInput && !opts.json) { throw new Error("Non-interactive scan: pass --yes to apply defaults."); diff --git a/src/commands/onboard-helpers.ts b/src/commands/onboard-helpers.ts index 4da787b0e10..48f9e87c31e 100644 --- a/src/commands/onboard-helpers.ts +++ b/src/commands/onboard-helpers.ts @@ -31,6 +31,7 @@ export function guardCancel(value: T | symbol, runtime: RuntimeEnv): T { if (isCancel(value)) { cancel(stylePromptTitle("Setup cancelled.") ?? "Setup cancelled."); runtime.exit(0); + throw new Error("unreachable"); } return value; } diff --git a/src/commands/onboard-non-interactive.test-helpers.ts b/src/commands/onboard-non-interactive.test-helpers.ts index 67ecaa682e0..6fb5aa24e33 100644 --- a/src/commands/onboard-non-interactive.test-helpers.ts +++ b/src/commands/onboard-non-interactive.test-helpers.ts @@ -19,8 +19,8 @@ const NON_INTERACTIVE_DEFAULT_OPTIONS = { export function createThrowingRuntime(): NonInteractiveRuntime { return { log: () => {}, - error: (msg: string) => { - throw new Error(msg); + error: (...args: unknown[]) => { + throw new Error(args.map(String).join(" ")); }, exit: (code: number) => { throw new Error(`exit:${code}`); diff --git a/src/infra/ports.ts b/src/infra/ports.ts index 42ea12c0af2..cd8c21eaa48 100644 --- a/src/infra/ports.ts +++ b/src/infra/ports.ts @@ -88,7 +88,8 @@ export async function handlePortError( logDebug(`stderr: ${stderr.trim()}`); } } - return runtime.exit(1); + runtime.exit(1); + throw new Error("unreachable"); } export { PortInUseError }; diff --git a/src/logging/subsystem.ts b/src/logging/subsystem.ts index 60c427bd9db..088f173aa54 100644 --- a/src/logging/subsystem.ts +++ b/src/logging/subsystem.ts @@ -1,3 +1,4 @@ +import { inspect } from "node:util"; import { Chalk } from "chalk"; import type { Logger as TsLogger } from "tslog"; import { CHAT_CHANNEL_ORDER } from "../channels/registry.js"; @@ -320,9 +321,14 @@ export function runtimeForLogger( logger: SubsystemLogger, exit: RuntimeEnv["exit"] = defaultRuntime.exit, ): RuntimeEnv { + const formatArgs = (...args: unknown[]) => + args + .map((arg) => (typeof arg === "string" ? arg : inspect(arg))) + .join(" ") + .trim(); return { - log: (message: string) => logger.info(message), - error: (message: string) => logger.error(message), + log: (...args: unknown[]) => logger.info(formatArgs(...args)), + error: (...args: unknown[]) => logger.error(formatArgs(...args)), exit, }; }