openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
197 lines (196 loc) • 8.34 kB
JavaScript
import { M as markCommanderLazyCommand, t as buildParseArgv } from "./argv-DNjh_yaF.js";
import { t as removeCommandByName } from "./command-tree-CA1ToIBK.js";
//#region src/cli/program/action-reparse.ts
function getCommandPathFromRoot(command) {
const path = [];
let current = command;
while (current?.parent) {
if (current.name()) path.unshift(current);
current = current.parent;
}
return path;
}
function findRootCommand(cmd) {
let current = cmd;
while (current.parent) current = current.parent;
return current;
}
function findOption(command, token) {
const equalsIndex = token.indexOf("=");
const flag = equalsIndex === -1 ? token : token.slice(0, equalsIndex);
const exactOption = command.options.find((candidate) => (candidate.short === flag || candidate.long === flag) && (equalsIndex === -1 || candidate.required || candidate.optional));
if (exactOption || !token.startsWith("-") || token.startsWith("--") || token.length <= 2) return exactOption;
let claimedOption;
for (let index = 1; index < token.length; index += 1) {
const option = command.options.find((candidate) => candidate.short === `-${token[index]}`);
if (!option) return claimedOption;
claimedOption ??= option;
if (option.required || option.optional || index === token.length - 1) return option;
}
}
function findNearestOption(commands, token) {
for (let index = commands.length - 1; index >= 0; index -= 1) {
const command = commands[index];
const option = command ? findOption(command, token) : void 0;
if (option) return option;
}
}
function matchesCommandName(command, token) {
return command.name() === token || command.aliases().includes(token);
}
function optionTokenCount(option, argv, index) {
const token = argv[index] ?? "";
const shortFlagIndex = option.short !== void 0 && !token.startsWith("--") ? token.indexOf(option.short.slice(1), 1) : -1;
const hasAttachedShortValue = shortFlagIndex !== -1 && shortFlagIndex < token.length - 1;
if (token.includes("=") || hasAttachedShortValue || !option.required && !option.optional) return 1;
const next = argv[index + 1];
if (option.required) return next === void 0 ? 0 : 2;
return next && (!next.startsWith("-") || /^-\d/.test(next)) ? 2 : 1;
}
function findCommandPathEnd(argv, command) {
const path = getCommandPathFromRoot(command);
const root = path[0]?.parent;
if (!root) return -1;
const selectedCommands = [root];
let pathIndex = 0;
for (let index = 2; index < argv.length; index += 1) {
const token = argv[index] ?? "";
const option = findNearestOption(selectedCommands, token);
if (option) {
const count = optionTokenCount(option, argv, index);
if (count === 0) return -1;
index += count - 1;
continue;
}
const nextCommand = path[pathIndex];
if (!nextCommand || !matchesCommandName(nextCommand, token)) return -1;
selectedCommands.push(nextCommand);
pathIndex += 1;
if (pathIndex === path.length) return index + 1;
}
return -1;
}
/** Restore parent-option placement without stealing options owned by the loaded child command. */
function hoistLazyParentOptions(argv, parentCommand, lazyCommandName) {
let lazyCommandIndex = findCommandPathEnd(argv, parentCommand);
if (lazyCommandIndex === -1) return argv;
while (lazyCommandIndex < argv.length) {
const option = findOption(parentCommand, argv[lazyCommandIndex] ?? "");
if (!option) break;
const count = optionTokenCount(option, argv, lazyCommandIndex);
if (count === 0) return argv;
lazyCommandIndex += count;
}
if (argv[lazyCommandIndex] !== lazyCommandName) return argv;
const lazyCommand = parentCommand.commands.find((command) => matchesCommandName(command, lazyCommandName));
if (!lazyCommand) return argv;
let selectedCommand = lazyCommand;
const selectedCommands = [selectedCommand];
const hoisted = [];
const remaining = [];
let acceptsSubcommands = true;
for (let index = lazyCommandIndex + 1; index < argv.length; index += 1) {
const token = argv[index] ?? "";
if (token === "--") {
remaining.push(...argv.slice(index));
break;
}
const childOption = findNearestOption(selectedCommands, token);
const parentOption = findOption(parentCommand, token);
const option = childOption ?? parentOption;
if (option) {
const count = optionTokenCount(option, argv, index);
if (count === 0) return argv;
const tokens = argv.slice(index, index + count);
(childOption ? remaining : hoisted).push(...tokens);
index += count - 1;
continue;
}
if (acceptsSubcommands && !token.startsWith("-")) {
const nextCommand = selectedCommand.commands.find((command) => matchesCommandName(command, token));
if (nextCommand) {
selectedCommand = nextCommand;
selectedCommands.push(nextCommand);
} else acceptsSubcommands = false;
}
remaining.push(token);
}
return hoisted.length === 0 ? argv : [
...argv.slice(0, lazyCommandIndex),
...hoisted,
lazyCommandName,
...remaining
];
}
/** Re-run parsing after replacing a lazy command placeholder. */
async function reparseProgramFromActionCommand(program, actionCommand) {
const rootProgram = findRootCommand(actionCommand);
const normalizedArgv = hoistLazyParentOptions(buildParseArgv(rootProgram.rawArgs, rootProgram.name()), program, actionCommand.name());
await rootProgram.parseAsync(normalizedArgv);
}
//#endregion
//#region src/cli/program/register-lazy-command.ts
/** Register a placeholder that loads the real command and reparses the original invocation. */
function registerLazyCommand({ program, name, description, options, removeNames, register }) {
const placeholder = program.command(name).description(description);
markCommanderLazyCommand(placeholder);
for (const option of options ?? []) placeholder.option(option.flags, option.description);
placeholder.allowUnknownOption(true).allowExcessArguments(true);
placeholder.action(async (...actionArgs) => {
const actionCommand = actionArgs.at(-1);
for (const commandName of new Set(removeNames ?? [name])) removeCommandByName(program, commandName);
await register();
await reparseProgramFromActionCommand(program, actionCommand);
});
}
//#endregion
//#region src/cli/program/register-command-groups.ts
/** Return every command name owned by a lazy command group. */
function getCommandGroupNames(entry) {
return entry.names ?? entry.placeholders.map((placeholder) => placeholder.name);
}
/** Find the group that owns a command name. */
function findCommandGroupEntry(entries, name) {
return entries.find((entry) => getCommandGroupNames(entry).includes(name));
}
/** Remove all placeholder/loaded commands owned by a group before replacing it. */
function removeCommandGroupNames(program, entry) {
for (const name of new Set(getCommandGroupNames(entry))) removeCommandByName(program, name);
}
/** Eagerly register one lazy command group by command name. */
async function registerCommandGroupByName(program, entries, name) {
const entry = findCommandGroupEntry(entries, name);
if (!entry) return false;
removeCommandGroupNames(program, entry);
await entry.register(program);
return true;
}
/** Register one placeholder that loads and replaces its whole command group on demand. */
function registerLazyCommandGroup(program, entry, placeholder) {
registerLazyCommand({
program,
name: placeholder.name,
description: placeholder.description,
options: placeholder.options,
removeNames: getCommandGroupNames(entry),
register: () => entry.register(program)
});
}
/** Register command groups either eagerly or as lazy placeholders for startup speed. */
function registerCommandGroups(program, entries, params) {
if (params.eager) {
for (const entry of entries) entry.register(program);
return;
}
if (params.primary && params.registerPrimaryOnly) {
const entry = findCommandGroupEntry(entries, params.primary);
if (entry) {
const placeholder = entry.placeholders.find((candidate) => candidate.name === params.primary);
if (placeholder) registerLazyCommandGroup(program, entry, placeholder);
return;
}
}
for (const entry of entries) for (const placeholder of entry.placeholders) registerLazyCommandGroup(program, entry, placeholder);
}
//#endregion
export { registerLazyCommandGroup as a, registerCommandGroups as i, getCommandGroupNames as n, removeCommandGroupNames as o, registerCommandGroupByName as r, findCommandGroupEntry as t };