mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-29 17:53:39 +00:00
116 lines
3.6 KiB
TypeScript
116 lines
3.6 KiB
TypeScript
// Route-first CLI entry point for commands that can run before full Commander setup.
|
|
import { FLAG_TERMINATOR, isValueToken } from "../infra/cli-root-options.js";
|
|
import { isTruthyEnvValue } from "../infra/env.js";
|
|
import { type LogLevel, tryParseLogLevel } from "../logging/levels.js";
|
|
import { defaultRuntime } from "../runtime.js";
|
|
import { resolveCliArgvInvocation } from "./argv-invocation.js";
|
|
import { hasFlag } from "./argv.js";
|
|
import {
|
|
applyCliExecutionStartupPresentation,
|
|
ensureCliExecutionBootstrap,
|
|
resolveCliExecutionStartupContext,
|
|
} from "./command-execution-startup.js";
|
|
import { findRoutedCommand } from "./program/routes.js";
|
|
|
|
const LOG_LEVEL_FLAG = "--log-level";
|
|
const LOG_LEVEL_EQUALS_PREFIX = `${LOG_LEVEL_FLAG}=`;
|
|
|
|
function resolveRoutedCliLogLevel(argv: string[]): LogLevel | null | undefined {
|
|
const args = argv.slice(2);
|
|
let logLevel: LogLevel | undefined;
|
|
|
|
for (let index = 0; index < args.length; index += 1) {
|
|
const arg = args[index];
|
|
if (!arg || arg === FLAG_TERMINATOR) {
|
|
break;
|
|
}
|
|
if (arg === LOG_LEVEL_FLAG) {
|
|
const value = args[index + 1];
|
|
if (!isValueToken(value)) {
|
|
return null;
|
|
}
|
|
const parsed = tryParseLogLevel(value);
|
|
if (!parsed) {
|
|
return null;
|
|
}
|
|
logLevel = parsed;
|
|
index += 1;
|
|
continue;
|
|
}
|
|
if (arg.startsWith(LOG_LEVEL_EQUALS_PREFIX)) {
|
|
const parsed = tryParseLogLevel(arg.slice(LOG_LEVEL_EQUALS_PREFIX.length));
|
|
if (!parsed) {
|
|
return null;
|
|
}
|
|
logLevel = parsed;
|
|
}
|
|
}
|
|
|
|
return logLevel;
|
|
}
|
|
|
|
async function prepareRoutedCommand(params: {
|
|
argv: string[];
|
|
commandPath: string[];
|
|
loadPlugins?: boolean | ((argv: string[]) => boolean);
|
|
}) {
|
|
const { startupPolicy } = resolveCliExecutionStartupContext({
|
|
argv: params.argv,
|
|
jsonOutputMode: hasFlag(params.argv, "--json"),
|
|
env: process.env,
|
|
routeMode: true,
|
|
});
|
|
const { VERSION } = await import("../version.js");
|
|
await applyCliExecutionStartupPresentation({
|
|
argv: params.argv,
|
|
startupPolicy,
|
|
showBanner: process.stdout.isTTY && !startupPolicy.suppressDoctorStdout,
|
|
version: VERSION,
|
|
});
|
|
const shouldLoadPlugins =
|
|
typeof params.loadPlugins === "function" ? params.loadPlugins(params.argv) : params.loadPlugins;
|
|
// Routed commands still honor config guards, logging policy, and plugin loading decisions.
|
|
await ensureCliExecutionBootstrap({
|
|
runtime: defaultRuntime,
|
|
commandPath: params.commandPath,
|
|
startupPolicy,
|
|
loadPlugins: shouldLoadPlugins ?? startupPolicy.loadPlugins,
|
|
});
|
|
}
|
|
|
|
/** Try a lightweight route-first command before falling back to the full CLI program. */
|
|
export async function tryRouteCli(argv: string[]): Promise<boolean> {
|
|
if (isTruthyEnvValue(process.env.OPENCLAW_DISABLE_ROUTE_FIRST)) {
|
|
return false;
|
|
}
|
|
const invocation = resolveCliArgvInvocation(argv);
|
|
if (invocation.hasHelpOrVersion) {
|
|
return false;
|
|
}
|
|
if (!invocation.commandPath[0]) {
|
|
return false;
|
|
}
|
|
const route = findRoutedCommand(invocation.commandPath, argv);
|
|
if (!route) {
|
|
return false;
|
|
}
|
|
if (route.canRun && !route.canRun(argv)) {
|
|
// Let Commander own unsupported argv shapes so user-facing validation stays centralized.
|
|
return false;
|
|
}
|
|
const logLevel = resolveRoutedCliLogLevel(argv);
|
|
if (logLevel === null) {
|
|
// Let Commander own the existing user-facing --log-level validation errors.
|
|
return false;
|
|
}
|
|
if (logLevel) {
|
|
process.env.OPENCLAW_LOG_LEVEL = logLevel;
|
|
}
|
|
await prepareRoutedCommand({
|
|
argv,
|
|
commandPath: invocation.commandPath,
|
|
loadPlugins: route.loadPlugins,
|
|
});
|
|
return route.run(argv);
|
|
}
|