feat(cli): consolidar CLI_TOOLS — listCliTools/getCliTool + setup --list (Fase 1.6)

This commit is contained in:
diegosouzapw
2026-05-14 23:48:12 -03:00
parent ab911265ed
commit 9da0e704a7
3 changed files with 104 additions and 0 deletions

View File

@@ -1,3 +1,5 @@
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
import { createPrompt, printHeading, printInfo, printSuccess } from "../io.mjs";
import { openOmniRouteDb } from "../sqlite.mjs";
import { getSettings, hashManagementPassword, updateSettings } from "../settings-store.mjs";
@@ -10,6 +12,13 @@ import {
} from "../provider-catalog.mjs";
import { t } from "../i18n.mjs";
const PROJECT_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../../..");
async function getListCliTools() {
const { listCliTools } = await import(`${PROJECT_ROOT}/src/shared/constants/cliTools.ts`);
return listCliTools;
}
function wantsProviderSetup(opts) {
return opts.addProvider || Boolean(opts.provider) || Boolean(opts.apiKey);
}
@@ -135,6 +144,7 @@ export function registerSetup(program) {
.option("--provider-base-url <url>", "Optional OpenAI-compatible base URL override")
.option("--test-provider", "Test the provider after saving it")
.option("--non-interactive", "Read all inputs from flags/env and do not prompt")
.option("--list", "List all supported CLI tools")
.action(async (opts, cmd) => {
const globalOpts = cmd.optsWithGlobals();
const exitCode = await runSetupCommand({ ...opts, output: globalOpts.output });
@@ -143,6 +153,22 @@ export function registerSetup(program) {
}
export async function runSetupCommand(opts = {}) {
if (opts.list) {
const listCliTools = await getListCliTools();
const tools = listCliTools();
if (opts.json || opts.output === "json") {
console.log(JSON.stringify(tools, null, 2));
} else {
printHeading("Supported CLI Tools");
for (const tool of tools) {
const cmd = tool.defaultCommand || tool.defaultCommands?.[0] || "";
const cmdStr = cmd ? ` \x1b[2m(${cmd})\x1b[0m` : "";
console.log(`${tool.name}${cmdStr}`);
}
}
return 0;
}
const nonInteractive = opts.nonInteractive ?? false;
const prompt = createPrompt();

View File

@@ -526,6 +526,22 @@ amp --model "{{model}}"
},
};
// ─── Registry helpers ────────────────────────────────────────────────────────
export type CliToolEntry = (typeof CLI_TOOLS)[keyof typeof CLI_TOOLS];
/** Returns an ordered list of all registered CLI tools. */
export function listCliTools(): CliToolEntry[] {
return Object.values(CLI_TOOLS) as CliToolEntry[];
}
/** Returns a single tool by id, or undefined if not found. */
export function getCliTool(id: string): CliToolEntry | undefined {
return (CLI_TOOLS as Record<string, CliToolEntry>)[id];
}
// ─── Provider model mapping helper ───────────────────────────────────────────
// Get all provider models for mapping dropdown
export const getProviderModelsForMapping = (providers) => {
const result = [];

View File

@@ -0,0 +1,62 @@
import test from "node:test";
import assert from "node:assert/strict";
test("CLI_TOOLS registry contains all 17 expected tools", async () => {
const { CLI_TOOLS } = await import("../../src/shared/constants/cliTools.ts");
const expected = [
"claude",
"codex",
"opencode",
"cline",
"kilo",
"continue",
"qwen",
"windsurf",
"hermes",
"amp",
"kiro",
"cursor",
"droid",
"antigravity",
"copilot",
"openclaw",
"custom",
];
for (const id of expected) {
assert.ok(id in CLI_TOOLS, `Missing tool: ${id}`);
}
assert.equal(Object.keys(CLI_TOOLS).length, expected.length);
});
test("Every tool has required fields: id, name, description, configType", async () => {
const { CLI_TOOLS } = await import("../../src/shared/constants/cliTools.ts");
for (const [key, tool] of Object.entries(CLI_TOOLS)) {
assert.equal(typeof tool.id, "string", `${key}.id must be string`);
assert.equal(tool.id, key, `${key}.id must match its registry key`);
assert.equal(typeof tool.name, "string", `${key}.name must be string`);
assert.ok(tool.name.length > 0, `${key}.name must be non-empty`);
assert.equal(typeof tool.description, "string", `${key}.description must be string`);
assert.equal(typeof tool.configType, "string", `${key}.configType must be string`);
}
});
test("listCliTools returns all tools as an array", async () => {
const { listCliTools, CLI_TOOLS } = await import("../../src/shared/constants/cliTools.ts");
const tools = listCliTools();
assert.ok(Array.isArray(tools));
assert.equal(tools.length, Object.keys(CLI_TOOLS).length);
for (const tool of tools) {
assert.equal(typeof tool.id, "string");
}
});
test("getCliTool returns correct tool by id", async () => {
const { getCliTool } = await import("../../src/shared/constants/cliTools.ts");
const claude = getCliTool("claude");
assert.ok(claude);
assert.equal(claude.id, "claude");
assert.equal(claude.name, "Claude Code");
const missing = getCliTool("nonexistent");
assert.equal(missing, undefined);
});