refactor: share cli startup and routing helpers

This commit is contained in:
Peter Steinberger
2026-04-06 13:51:27 +01:00
parent 6ed33d29c8
commit a21709d041
15 changed files with 1189 additions and 336 deletions

View File

@@ -1,13 +1,15 @@
import type { Command } from "commander";
import { setVerbose } from "../../globals.js";
import { isTruthyEnvValue } from "../../infra/env.js";
import { routeLogsToStderr } from "../../logging/console.js";
import type { LogLevel } from "../../logging/levels.js";
import { loggingState } from "../../logging/state.js";
import { defaultRuntime } from "../../runtime.js";
import { getCommandPathWithRootOptions, getVerboseFlag, hasHelpOrVersion } from "../argv.js";
import { emitCliBanner } from "../banner.js";
import { getVerboseFlag, hasHelpOrVersion } from "../argv.js";
import { resolveCliName } from "../cli-name.js";
import {
applyCliExecutionStartupPresentation,
ensureCliExecutionBootstrap,
resolveCliExecutionStartupContext,
} from "../command-execution-startup.js";
import { shouldBypassConfigGuardForCommandPath } from "../command-startup-policy.js";
import {
resolvePluginInstallInvalidConfigPolicy,
resolvePluginInstallPreactionRequest,
@@ -27,63 +29,6 @@ function setProcessTitleForCommand(actionCommand: Command) {
process.title = `${cliName}-${name}`;
}
// Commands that need plugins loaded before execution.
const PLUGIN_REQUIRED_COMMANDS = new Set([
"agent",
"message",
"channels",
"directory",
"agents",
"configure",
"status",
"health",
]);
const CONFIG_GUARD_BYPASS_COMMANDS = new Set(["backup", "doctor", "completion", "secrets"]);
let configGuardModulePromise: Promise<typeof import("./config-guard.js")> | undefined;
let pluginRegistryModulePromise: Promise<typeof import("../plugin-registry.js")> | undefined;
function shouldBypassConfigGuard(commandPath: string[]): boolean {
const [primary, secondary] = commandPath;
if (!primary) {
return false;
}
if (CONFIG_GUARD_BYPASS_COMMANDS.has(primary)) {
return true;
}
if (primary === "config" && (secondary === "validate" || secondary === "schema")) {
return true;
}
return false;
}
function loadConfigGuardModule() {
configGuardModulePromise ??= import("./config-guard.js");
return configGuardModulePromise;
}
function loadPluginRegistryModule() {
pluginRegistryModulePromise ??= import("../plugin-registry.js");
return pluginRegistryModulePromise;
}
function resolvePluginRegistryScope(commandPath: string[]): "channels" | "all" {
return commandPath[0] === "status" || commandPath[0] === "health" ? "channels" : "all";
}
function shouldLoadPluginsForCommand(commandPath: string[], jsonOutputMode: boolean): boolean {
const [primary, secondary] = commandPath;
if (!primary || !PLUGIN_REQUIRED_COMMANDS.has(primary)) {
return false;
}
if ((primary === "status" || primary === "health") && jsonOutputMode) {
return false;
}
// Setup wizard and channels add should stay manifest-first and load selected plugins on demand.
if (primary === "onboard" || (primary === "channels" && secondary === "add")) {
return false;
}
return true;
}
function shouldAllowInvalidConfigForAction(actionCommand: Command, commandPath: string[]): boolean {
return (
resolvePluginInstallInvalidConfigPolicy(
@@ -123,19 +68,16 @@ export function registerPreActionHooks(program: Command, programVersion: string)
if (hasHelpOrVersion(argv)) {
return;
}
const commandPath = getCommandPathWithRootOptions(argv, 2);
const jsonOutputMode = isCommandJsonOutputMode(actionCommand, argv);
if (jsonOutputMode) {
routeLogsToStderr();
}
const hideBanner =
isTruthyEnvValue(process.env.OPENCLAW_HIDE_BANNER) ||
commandPath[0] === "update" ||
commandPath[0] === "completion" ||
(commandPath[0] === "plugins" && commandPath[1] === "update");
if (!hideBanner) {
emitCliBanner(programVersion);
}
const { commandPath, startupPolicy } = resolveCliExecutionStartupContext({
argv,
jsonOutputMode,
env: process.env,
});
await applyCliExecutionStartupPresentation({
startupPolicy,
version: programVersion,
});
const verbose = getVerboseFlag(argv, { includeDebug: true });
setVerbose(verbose);
const cliLogLevel = getCliLogLevel(actionCommand);
@@ -145,31 +87,14 @@ export function registerPreActionHooks(program: Command, programVersion: string)
if (!verbose) {
process.env.NODE_NO_WARNINGS ??= "1";
}
if (shouldBypassConfigGuard(commandPath)) {
if (shouldBypassConfigGuardForCommandPath(commandPath)) {
return;
}
const allowInvalid = shouldAllowInvalidConfigForAction(actionCommand, commandPath);
const { ensureConfigReady } = await loadConfigGuardModule();
await ensureConfigReady({
await ensureCliExecutionBootstrap({
runtime: defaultRuntime,
commandPath,
...(allowInvalid ? { allowInvalid: true } : {}),
...(jsonOutputMode ? { suppressDoctorStdout: true } : {}),
startupPolicy,
allowInvalid: shouldAllowInvalidConfigForAction(actionCommand, commandPath),
});
// Load plugins for commands that need channel access.
// When --json output is active, temporarily route logs to stderr so plugin
// registration messages don't corrupt the JSON payload on stdout.
if (shouldLoadPluginsForCommand(commandPath, jsonOutputMode)) {
const { ensurePluginRegistryLoaded } = await loadPluginRegistryModule();
const prev = loggingState.forceConsoleToStderr;
if (jsonOutputMode) {
loggingState.forceConsoleToStderr = true;
}
try {
ensurePluginRegistryLoaded({ scope: resolvePluginRegistryScope(commandPath) });
} finally {
loggingState.forceConsoleToStderr = prev;
}
}
});
}

View File

@@ -0,0 +1,210 @@
import { describe, expect, it } from "vitest";
import {
parseAgentsListRouteArgs,
parseConfigGetRouteArgs,
parseConfigUnsetRouteArgs,
parseGatewayStatusRouteArgs,
parseHealthRouteArgs,
parseModelsListRouteArgs,
parseModelsStatusRouteArgs,
parseSessionsRouteArgs,
parseStatusRouteArgs,
} from "./route-args.js";
describe("route-args", () => {
it("parses health and status route args", () => {
expect(
parseHealthRouteArgs(["node", "openclaw", "health", "--json", "--timeout", "5000"]),
).toEqual({
json: true,
verbose: false,
timeoutMs: 5000,
});
expect(
parseStatusRouteArgs([
"node",
"openclaw",
"status",
"--json",
"--deep",
"--all",
"--usage",
"--timeout",
"5000",
]),
).toEqual({
json: true,
deep: true,
all: true,
usage: true,
verbose: false,
timeoutMs: 5000,
});
expect(parseStatusRouteArgs(["node", "openclaw", "status", "--timeout"])).toBeNull();
});
it("parses gateway status route args and rejects probe-only ssh flags", () => {
expect(
parseGatewayStatusRouteArgs([
"node",
"openclaw",
"gateway",
"status",
"--url",
"ws://127.0.0.1:18789",
"--token",
"abc",
"--password",
"def",
"--timeout",
"5000",
"--deep",
"--require-rpc",
"--json",
]),
).toEqual({
rpc: {
url: "ws://127.0.0.1:18789",
token: "abc",
password: "def",
timeout: "5000",
},
probe: true,
requireRpc: true,
deep: true,
json: true,
});
expect(
parseGatewayStatusRouteArgs(["node", "openclaw", "gateway", "status", "--ssh", "host"]),
).toBeNull();
expect(
parseGatewayStatusRouteArgs(["node", "openclaw", "gateway", "status", "--ssh-auto"]),
).toBeNull();
});
it("parses sessions and agents list route args", () => {
expect(
parseSessionsRouteArgs([
"node",
"openclaw",
"sessions",
"--json",
"--all-agents",
"--agent",
"default",
"--store",
"sqlite",
"--active",
"true",
]),
).toEqual({
json: true,
allAgents: true,
agent: "default",
store: "sqlite",
active: "true",
});
expect(parseSessionsRouteArgs(["node", "openclaw", "sessions", "--agent"])).toBeNull();
expect(
parseAgentsListRouteArgs(["node", "openclaw", "agents", "list", "--json", "--bindings"]),
).toEqual({
json: true,
bindings: true,
});
});
it("parses config routes", () => {
expect(
parseConfigGetRouteArgs([
"node",
"openclaw",
"--log-level",
"debug",
"config",
"get",
"update.channel",
"--json",
]),
).toEqual({
path: "update.channel",
json: true,
});
expect(
parseConfigUnsetRouteArgs([
"node",
"openclaw",
"config",
"unset",
"--profile",
"work",
"update.channel",
]),
).toEqual({
path: "update.channel",
});
expect(parseConfigGetRouteArgs(["node", "openclaw", "config", "get", "--json"])).toBeNull();
});
it("parses models list and models status route args", () => {
expect(
parseModelsListRouteArgs([
"node",
"openclaw",
"models",
"list",
"--provider",
"openai",
"--all",
"--local",
"--json",
"--plain",
]),
).toEqual({
provider: "openai",
all: true,
local: true,
json: true,
plain: true,
});
expect(
parseModelsStatusRouteArgs([
"node",
"openclaw",
"models",
"status",
"--probe-provider",
"openai",
"--probe-timeout",
"5000",
"--probe-concurrency",
"2",
"--probe-max-tokens",
"64",
"--probe-profile",
"fast",
"--probe-profile",
"safe",
"--agent",
"default",
"--json",
"--plain",
"--check",
"--probe",
]),
).toEqual({
probeProvider: "openai",
probeTimeout: "5000",
probeConcurrency: "2",
probeMaxTokens: "64",
probeProfile: ["fast", "safe"],
agent: "default",
json: true,
plain: true,
check: true,
probe: true,
});
expect(
parseModelsStatusRouteArgs(["node", "openclaw", "models", "status", "--probe-profile"]),
).toBeNull();
});
});

View File

@@ -0,0 +1,244 @@
import { isValueToken } from "../../infra/cli-root-options.js";
import {
getCommandPositionalsWithRootOptions,
getFlagValue,
getPositiveIntFlagValue,
getVerboseFlag,
hasFlag,
} from "../argv.js";
type OptionalFlagParse = {
ok: boolean;
value?: string;
};
function parseOptionalFlagValue(argv: string[], name: string): OptionalFlagParse {
const value = getFlagValue(argv, name);
if (value === null) {
return { ok: false };
}
return { ok: true, value };
}
function parseRepeatedFlagValues(argv: string[], name: string): string[] | null {
const values: string[] = [];
const args = argv.slice(2);
for (let i = 0; i < args.length; i += 1) {
const arg = args[i];
if (!arg || arg === "--") {
break;
}
if (arg === name) {
const next = args[i + 1];
if (!isValueToken(next)) {
return null;
}
values.push(next);
i += 1;
continue;
}
if (arg.startsWith(`${name}=`)) {
const value = arg.slice(name.length + 1).trim();
if (!value) {
return null;
}
values.push(value);
}
}
return values;
}
function parseSinglePositional(
argv: string[],
params: {
commandPath: string[];
booleanFlags?: string[];
},
): string | null {
const positionals = getCommandPositionalsWithRootOptions(argv, params);
if (!positionals || positionals.length !== 1) {
return null;
}
return positionals[0] ?? null;
}
export function parseHealthRouteArgs(argv: string[]) {
const timeoutMs = getPositiveIntFlagValue(argv, "--timeout");
if (timeoutMs === null) {
return null;
}
return {
json: hasFlag(argv, "--json"),
verbose: getVerboseFlag(argv, { includeDebug: true }),
timeoutMs,
};
}
export function parseStatusRouteArgs(argv: string[]) {
const timeoutMs = getPositiveIntFlagValue(argv, "--timeout");
if (timeoutMs === null) {
return null;
}
return {
json: hasFlag(argv, "--json"),
deep: hasFlag(argv, "--deep"),
all: hasFlag(argv, "--all"),
usage: hasFlag(argv, "--usage"),
verbose: getVerboseFlag(argv, { includeDebug: true }),
timeoutMs,
};
}
export function parseGatewayStatusRouteArgs(argv: string[]) {
const url = parseOptionalFlagValue(argv, "--url");
if (!url.ok) {
return null;
}
const token = parseOptionalFlagValue(argv, "--token");
if (!token.ok) {
return null;
}
const password = parseOptionalFlagValue(argv, "--password");
if (!password.ok) {
return null;
}
const timeout = parseOptionalFlagValue(argv, "--timeout");
if (!timeout.ok) {
return null;
}
const ssh = parseOptionalFlagValue(argv, "--ssh");
if (!ssh.ok || ssh.value !== undefined) {
return null;
}
const sshIdentity = parseOptionalFlagValue(argv, "--ssh-identity");
if (!sshIdentity.ok || sshIdentity.value !== undefined) {
return null;
}
if (hasFlag(argv, "--ssh-auto")) {
return null;
}
return {
rpc: {
url: url.value,
token: token.value,
password: password.value,
timeout: timeout.value,
},
deep: hasFlag(argv, "--deep"),
json: hasFlag(argv, "--json"),
requireRpc: hasFlag(argv, "--require-rpc"),
probe: !hasFlag(argv, "--no-probe"),
};
}
export function parseSessionsRouteArgs(argv: string[]) {
const agent = parseOptionalFlagValue(argv, "--agent");
if (!agent.ok) {
return null;
}
const store = parseOptionalFlagValue(argv, "--store");
if (!store.ok) {
return null;
}
const active = parseOptionalFlagValue(argv, "--active");
if (!active.ok) {
return null;
}
return {
json: hasFlag(argv, "--json"),
allAgents: hasFlag(argv, "--all-agents"),
agent: agent.value,
store: store.value,
active: active.value,
};
}
export function parseAgentsListRouteArgs(argv: string[]) {
return {
json: hasFlag(argv, "--json"),
bindings: hasFlag(argv, "--bindings"),
};
}
export function parseConfigGetRouteArgs(argv: string[]) {
const path = parseSinglePositional(argv, {
commandPath: ["config", "get"],
booleanFlags: ["--json"],
});
if (!path) {
return null;
}
return {
path,
json: hasFlag(argv, "--json"),
};
}
export function parseConfigUnsetRouteArgs(argv: string[]) {
const path = parseSinglePositional(argv, {
commandPath: ["config", "unset"],
});
if (!path) {
return null;
}
return { path };
}
export function parseModelsListRouteArgs(argv: string[]) {
const provider = parseOptionalFlagValue(argv, "--provider");
if (!provider.ok) {
return null;
}
return {
provider: provider.value,
all: hasFlag(argv, "--all"),
local: hasFlag(argv, "--local"),
json: hasFlag(argv, "--json"),
plain: hasFlag(argv, "--plain"),
};
}
export function parseModelsStatusRouteArgs(argv: string[]) {
const probeProvider = parseOptionalFlagValue(argv, "--probe-provider");
if (!probeProvider.ok) {
return null;
}
const probeTimeout = parseOptionalFlagValue(argv, "--probe-timeout");
if (!probeTimeout.ok) {
return null;
}
const probeConcurrency = parseOptionalFlagValue(argv, "--probe-concurrency");
if (!probeConcurrency.ok) {
return null;
}
const probeMaxTokens = parseOptionalFlagValue(argv, "--probe-max-tokens");
if (!probeMaxTokens.ok) {
return null;
}
const agent = parseOptionalFlagValue(argv, "--agent");
if (!agent.ok) {
return null;
}
const probeProfileValues = parseRepeatedFlagValues(argv, "--probe-profile");
if (probeProfileValues === null) {
return null;
}
const probeProfile =
probeProfileValues.length === 0
? undefined
: probeProfileValues.length === 1
? probeProfileValues[0]
: probeProfileValues;
return {
probeProvider: probeProvider.value,
probeTimeout: probeTimeout.value,
probeConcurrency: probeConcurrency.value,
probeMaxTokens: probeMaxTokens.value,
agent: agent.value,
probeProfile,
json: hasFlag(argv, "--json"),
plain: hasFlag(argv, "--plain"),
check: hasFlag(argv, "--check"),
probe: hasFlag(argv, "--probe"),
};
}

View File

@@ -1,12 +1,17 @@
import { isValueToken } from "../../infra/cli-root-options.js";
import { defaultRuntime } from "../../runtime.js";
import { hasFlag } from "../argv.js";
import { shouldLoadPluginsForCommandPath } from "../command-startup-policy.js";
import {
getCommandPositionalsWithRootOptions,
getFlagValue,
getPositiveIntFlagValue,
getVerboseFlag,
hasFlag,
} from "../argv.js";
parseAgentsListRouteArgs,
parseConfigGetRouteArgs,
parseConfigUnsetRouteArgs,
parseGatewayStatusRouteArgs,
parseHealthRouteArgs,
parseModelsListRouteArgs,
parseModelsStatusRouteArgs,
parseSessionsRouteArgs,
parseStatusRouteArgs,
} from "./route-args.js";
export type RouteSpec = {
match: (path: string[]) => boolean;
@@ -18,16 +23,18 @@ const routeHealth: RouteSpec = {
match: (path) => path[0] === "health",
// `health --json` only relays gateway RPC output and does not need local plugin metadata.
// Keep plugin preload for text output where channel diagnostics/logSelfId are rendered.
loadPlugins: (argv) => !hasFlag(argv, "--json"),
loadPlugins: (argv) =>
shouldLoadPluginsForCommandPath({
commandPath: ["health"],
jsonOutputMode: hasFlag(argv, "--json"),
}),
run: async (argv) => {
const json = hasFlag(argv, "--json");
const verbose = getVerboseFlag(argv, { includeDebug: true });
const timeoutMs = getPositiveIntFlagValue(argv, "--timeout");
if (timeoutMs === null) {
const args = parseHealthRouteArgs(argv);
if (!args) {
return false;
}
const { healthCommand } = await import("../../commands/health.js");
await healthCommand({ json, timeoutMs, verbose }, defaultRuntime);
await healthCommand(args, defaultRuntime);
return true;
},
};
@@ -36,24 +43,31 @@ const routeStatus: RouteSpec = {
match: (path) => path[0] === "status",
// `status --json` can defer channel plugin loading until config/env inspection
// proves it is needed, which keeps the fast-path startup lightweight.
loadPlugins: (argv) => !hasFlag(argv, "--json"),
loadPlugins: (argv) =>
shouldLoadPluginsForCommandPath({
commandPath: ["status"],
jsonOutputMode: hasFlag(argv, "--json"),
}),
run: async (argv) => {
const json = hasFlag(argv, "--json");
const deep = hasFlag(argv, "--deep");
const all = hasFlag(argv, "--all");
const usage = hasFlag(argv, "--usage");
const verbose = getVerboseFlag(argv, { includeDebug: true });
const timeoutMs = getPositiveIntFlagValue(argv, "--timeout");
if (timeoutMs === null) {
const args = parseStatusRouteArgs(argv);
if (!args) {
return false;
}
if (json) {
if (args.json) {
const { statusJsonCommand } = await import("../../commands/status-json.js");
await statusJsonCommand({ deep, all, usage, timeoutMs }, defaultRuntime);
await statusJsonCommand(
{
deep: args.deep,
all: args.all,
usage: args.usage,
timeoutMs: args.timeoutMs,
},
defaultRuntime,
);
return true;
}
const { statusCommand } = await import("../../commands/status.js");
await statusCommand({ json, deep, all, usage, timeoutMs, verbose }, defaultRuntime);
await statusCommand(args, defaultRuntime);
return true;
},
};
@@ -61,56 +75,12 @@ const routeStatus: RouteSpec = {
const routeGatewayStatus: RouteSpec = {
match: (path) => path[0] === "gateway" && path[1] === "status",
run: async (argv) => {
const url = getFlagValue(argv, "--url");
if (url === null) {
const args = parseGatewayStatusRouteArgs(argv);
if (!args) {
return false;
}
const token = getFlagValue(argv, "--token");
if (token === null) {
return false;
}
const password = getFlagValue(argv, "--password");
if (password === null) {
return false;
}
const timeout = getFlagValue(argv, "--timeout");
if (timeout === null) {
return false;
}
const ssh = getFlagValue(argv, "--ssh");
if (ssh === null) {
return false;
}
if (ssh !== undefined) {
return false;
}
const sshIdentity = getFlagValue(argv, "--ssh-identity");
if (sshIdentity === null) {
return false;
}
if (sshIdentity !== undefined) {
return false;
}
if (hasFlag(argv, "--ssh-auto")) {
return false;
}
const deep = hasFlag(argv, "--deep");
const json = hasFlag(argv, "--json");
const requireRpc = hasFlag(argv, "--require-rpc");
const probe = !hasFlag(argv, "--no-probe");
const { runDaemonStatus } = await import("../daemon-cli/status.js");
await runDaemonStatus({
rpc: {
url: url ?? undefined,
token: token ?? undefined,
password: password ?? undefined,
timeout: timeout ?? undefined,
},
probe,
requireRpc,
deep,
json,
});
await runDaemonStatus(args);
return true;
},
};
@@ -120,22 +90,12 @@ const routeSessions: RouteSpec = {
// must fall through to Commander so nested handlers run.
match: (path) => path[0] === "sessions" && !path[1],
run: async (argv) => {
const json = hasFlag(argv, "--json");
const allAgents = hasFlag(argv, "--all-agents");
const agent = getFlagValue(argv, "--agent");
if (agent === null) {
return false;
}
const store = getFlagValue(argv, "--store");
if (store === null) {
return false;
}
const active = getFlagValue(argv, "--active");
if (active === null) {
const args = parseSessionsRouteArgs(argv);
if (!args) {
return false;
}
const { sessionsCommand } = await import("../../commands/sessions.js");
await sessionsCommand({ json, store, agent, allAgents, active }, defaultRuntime);
await sessionsCommand(args, defaultRuntime);
return true;
},
};
@@ -143,59 +103,21 @@ const routeSessions: RouteSpec = {
const routeAgentsList: RouteSpec = {
match: (path) => path[0] === "agents" && path[1] === "list",
run: async (argv) => {
const json = hasFlag(argv, "--json");
const bindings = hasFlag(argv, "--bindings");
const { agentsListCommand } = await import("../../commands/agents.js");
await agentsListCommand({ json, bindings }, defaultRuntime);
await agentsListCommand(parseAgentsListRouteArgs(argv), defaultRuntime);
return true;
},
};
function getFlagValues(argv: string[], name: string): string[] | null {
const values: string[] = [];
const args = argv.slice(2);
for (let i = 0; i < args.length; i += 1) {
const arg = args[i];
if (!arg || arg === "--") {
break;
}
if (arg === name) {
const next = args[i + 1];
if (!isValueToken(next)) {
return null;
}
values.push(next);
i += 1;
continue;
}
if (arg.startsWith(`${name}=`)) {
const value = arg.slice(name.length + 1).trim();
if (!value) {
return null;
}
values.push(value);
}
}
return values;
}
const routeConfigGet: RouteSpec = {
match: (path) => path[0] === "config" && path[1] === "get",
run: async (argv) => {
const positionals = getCommandPositionalsWithRootOptions(argv, {
commandPath: ["config", "get"],
booleanFlags: ["--json"],
});
if (!positionals || positionals.length !== 1) {
const args = parseConfigGetRouteArgs(argv);
if (!args) {
return false;
}
const pathArg = positionals[0];
if (!pathArg) {
return false;
}
const json = hasFlag(argv, "--json");
const { runConfigGet } = await import("../config-cli.js");
await runConfigGet({ path: pathArg, json });
await runConfigGet(args);
return true;
},
};
@@ -203,18 +125,12 @@ const routeConfigGet: RouteSpec = {
const routeConfigUnset: RouteSpec = {
match: (path) => path[0] === "config" && path[1] === "unset",
run: async (argv) => {
const positionals = getCommandPositionalsWithRootOptions(argv, {
commandPath: ["config", "unset"],
});
if (!positionals || positionals.length !== 1) {
return false;
}
const pathArg = positionals[0];
if (!pathArg) {
const args = parseConfigUnsetRouteArgs(argv);
if (!args) {
return false;
}
const { runConfigUnset } = await import("../config-cli.js");
await runConfigUnset({ path: pathArg });
await runConfigUnset(args);
return true;
},
};
@@ -222,16 +138,12 @@ const routeConfigUnset: RouteSpec = {
const routeModelsList: RouteSpec = {
match: (path) => path[0] === "models" && path[1] === "list",
run: async (argv) => {
const provider = getFlagValue(argv, "--provider");
if (provider === null) {
const args = parseModelsListRouteArgs(argv);
if (!args) {
return false;
}
const all = hasFlag(argv, "--all");
const local = hasFlag(argv, "--local");
const json = hasFlag(argv, "--json");
const plain = hasFlag(argv, "--plain");
const { modelsListCommand } = await import("../../commands/models.js");
await modelsListCommand({ all, local, provider, json, plain }, defaultRuntime);
await modelsListCommand(args, defaultRuntime);
return true;
},
};
@@ -239,56 +151,12 @@ const routeModelsList: RouteSpec = {
const routeModelsStatus: RouteSpec = {
match: (path) => path[0] === "models" && path[1] === "status",
run: async (argv) => {
const probeProvider = getFlagValue(argv, "--probe-provider");
if (probeProvider === null) {
const args = parseModelsStatusRouteArgs(argv);
if (!args) {
return false;
}
const probeTimeout = getFlagValue(argv, "--probe-timeout");
if (probeTimeout === null) {
return false;
}
const probeConcurrency = getFlagValue(argv, "--probe-concurrency");
if (probeConcurrency === null) {
return false;
}
const probeMaxTokens = getFlagValue(argv, "--probe-max-tokens");
if (probeMaxTokens === null) {
return false;
}
const agent = getFlagValue(argv, "--agent");
if (agent === null) {
return false;
}
const probeProfileValues = getFlagValues(argv, "--probe-profile");
if (probeProfileValues === null) {
return false;
}
const probeProfile =
probeProfileValues.length === 0
? undefined
: probeProfileValues.length === 1
? probeProfileValues[0]
: probeProfileValues;
const json = hasFlag(argv, "--json");
const plain = hasFlag(argv, "--plain");
const check = hasFlag(argv, "--check");
const probe = hasFlag(argv, "--probe");
const { modelsStatusCommand } = await import("../../commands/models.js");
await modelsStatusCommand(
{
json,
plain,
check,
probe,
probeProvider,
probeProfile,
probeTimeout,
probeConcurrency,
probeMaxTokens,
agent,
},
defaultRuntime,
);
await modelsStatusCommand(args, defaultRuntime);
return true;
},
};