From e1da792deaac141dcc8eaf344a65295423cbdb94 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza Date: Wed, 15 Jul 2026 11:58:54 -0300 Subject: [PATCH] fix(cli): shrink cliTools.ts/cliRuntime.ts under the file-size ratchet + fix stale catalog counts The grok-build registry/runtime entries pushed cliTools.ts (916->932) and cliRuntime.ts (1128->1137) past their frozen file-size caps. Extract the grok-build entries into cliToolsGrokBuild.ts (registry, typed) and cliRuntimeGrokBuild.ts (runtime metadata, deliberately untyped/no cliCatalog import so it doesn't drag that schema file into the typecheck:core curated allowlist's transitive graph). The amp runtime entry rides along in the same runtime file for the extra headroom needed to clear cliRuntime.ts's cap with zero slack. Also update the two catalog-cardinality canaries (cli-tools-schema.test.ts, cli-catalog-counts.test.ts) and EXPECTED_CODE_COUNT to include grok-build: 20->21 visible code entries, 24->25 total code entries, 32->33 grand total. Fixes CI reds on #7241 surviving a release/v3.8.49 merge: Fast Quality Gates (check:file-size) and Unit Tests fast-path (1/4, 2/4). --- src/shared/constants/cliTools.ts | 20 ++--------------- src/shared/constants/cliToolsGrokBuild.ts | 19 ++++++++++++++++ src/shared/schemas/cliCatalog.ts | 3 ++- src/shared/services/cliRuntime.ts | 19 +++------------- src/shared/services/cliRuntimeGrokBuild.ts | 26 ++++++++++++++++++++++ tests/unit/cli-catalog-counts.test.ts | 11 ++++----- tests/unit/cli-tools-schema.test.ts | 4 +++- 7 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 src/shared/constants/cliToolsGrokBuild.ts create mode 100644 src/shared/services/cliRuntimeGrokBuild.ts diff --git a/src/shared/constants/cliTools.ts b/src/shared/constants/cliTools.ts index 172a9597f5..644c8999d2 100644 --- a/src/shared/constants/cliTools.ts +++ b/src/shared/constants/cliTools.ts @@ -1,6 +1,7 @@ // CLI Tools configuration import { getClaudeCodeDefaultModels } from "@omniroute/open-sse/config/providerRegistry"; import type { CliCatalogEntry } from "@/shared/schemas/cliCatalog"; +import { GROK_BUILD_CLI_TOOL } from "@/shared/constants/cliToolsGrokBuild"; const _cc = getClaudeCodeDefaultModels(); @@ -540,7 +541,6 @@ export const CLI_TOOLS: Record = { acpSpawnable: false, baseUrlSupport: "full", }, - // ── Code entries — aider ────────────────────────────────────────────────── aider: { id: "aider", @@ -567,7 +567,6 @@ export const CLI_TOOLS: Record = { aider --openai-api-base "{{baseUrl}}" --model "{{model}}"`, }, }, - // ── Code entries — forge ────────────────────────────────────────────────── forge: { id: "forge", @@ -584,22 +583,7 @@ aider --openai-api-base "{{baseUrl}}" --model "{{model}}"`, defaultCommand: "forge", }, - // ── Code entries — grok-build ───────────────────────────────────────────── - "grok-build": { - id: "grok-build", - name: "Grok Build", - icon: "terminal", - color: "#1DA1F2", - description: "xAI Grok Build TUI coding agent — custom provider via ~/.grok/config.toml", - docsUrl: "https://x.ai/cli", - configType: "custom", - category: "code", - vendor: "xAI", - acpSpawnable: false, - baseUrlSupport: "full", - defaultCommand: "grok", - }, - + "grok-build": GROK_BUILD_CLI_TOOL, // ── Code entries — cursor-cli ───────────────────────────────────────────── "cursor-cli": { id: "cursor-cli", diff --git a/src/shared/constants/cliToolsGrokBuild.ts b/src/shared/constants/cliToolsGrokBuild.ts new file mode 100644 index 0000000000..e766295892 --- /dev/null +++ b/src/shared/constants/cliToolsGrokBuild.ts @@ -0,0 +1,19 @@ +// Grok Build CLI tool registry entry — extracted from cliTools.ts to keep the +// frozen registry file under its file-size ratchet cap (config/quality/file-size-baseline.json). +import type { CliCatalogEntry } from "@/shared/schemas/cliCatalog"; + +/** xAI Grok Build TUI coding agent — custom provider via ~/.grok/config.toml */ +export const GROK_BUILD_CLI_TOOL: CliCatalogEntry = { + id: "grok-build", + name: "Grok Build", + icon: "terminal", + color: "#1DA1F2", + description: "xAI Grok Build TUI coding agent — custom provider via ~/.grok/config.toml", + docsUrl: "https://x.ai/cli", + configType: "custom", + category: "code", + vendor: "xAI", + acpSpawnable: false, + baseUrlSupport: "full", + defaultCommand: "grok", +}; diff --git a/src/shared/schemas/cliCatalog.ts b/src/shared/schemas/cliCatalog.ts index d5b43a55bc..27ab19e3c9 100644 --- a/src/shared/schemas/cliCatalog.ts +++ b/src/shared/schemas/cliCatalog.ts @@ -62,7 +62,8 @@ export const CliCatalogSchema = z.record(CliCatalogEntrySchema); /** Cardinalidade obrigatória (Plano §3.1/§3.2 + D15). +1 (crush, decolua/9router#1233). */ // +1 (2026-07-02): "codewhale" added as a dual entry alongside "deepseek-tui" // (CodeWhale is the actively-maintained successor to DeepSeek TUI). -export const EXPECTED_CODE_COUNT = 20; +// +1 (grok-build, decolua/9router#2571): xAI Grok Build TUI coding agent. +export const EXPECTED_CODE_COUNT = 21; // +2 (#6318): "omp" (Oh My Pi) and "letta" (Letta CLI) added as agent entries. // Note: #6318 originally also shipped duplicate "pi"/"jcode"/"codewhale" entries — // those tools were already delivered by a separate PR, so only omp+letta landed here. diff --git a/src/shared/services/cliRuntime.ts b/src/shared/services/cliRuntime.ts index 84fd0d34c8..f1f50c0b3f 100644 --- a/src/shared/services/cliRuntime.ts +++ b/src/shared/services/cliRuntime.ts @@ -6,6 +6,7 @@ import { spawn, execFileSync } from "child_process"; import { getHermesHome } from "@/lib/cli-helper/config-generator/hermesHome"; import { getCachedLoginShellPath, mergeShellPath } from "./loginShellPath"; import { withSettingsFallback } from "./cliInstallFallback"; +import { GROK_BUILD_RUNTIME_ENTRY, AMP_RUNTIME_ENTRY } from "./cliRuntimeGrokBuild"; const VALID_RUNTIME_MODES = new Set(["auto", "host", "container"]); const FALSE_VALUES = new Set(["0", "false", "no", "off"]); @@ -155,13 +156,7 @@ const CLI_TOOLS: Record = { config: "config.yaml", }, }, - amp: { - defaultCommand: "amp", - envBinKey: "CLI_AMP_BIN", - requiresBinary: true, - healthcheckTimeoutMs: 12000, - paths: {}, - }, + amp: AMP_RUNTIME_ENTRY, qoder: { defaultCommand: "qodercli", envBinKey: "CLI_QODER_BIN", @@ -201,15 +196,7 @@ const CLI_TOOLS: Record = { config: ".jcode/config.json", }, }, - "grok-build": { - defaultCommand: "grok", - envBinKey: "CLI_GROK_BUILD_BIN", - requiresBinary: true, - healthcheckTimeoutMs: 8000, - paths: { - config: ".grok/config.toml", - }, - }, + "grok-build": GROK_BUILD_RUNTIME_ENTRY, "deepseek-tui": { defaultCommand: "deepseek-tui", envBinKey: "CLI_DEEPSEEK_TUI_BIN", diff --git a/src/shared/services/cliRuntimeGrokBuild.ts b/src/shared/services/cliRuntimeGrokBuild.ts new file mode 100644 index 0000000000..e219d6ffce --- /dev/null +++ b/src/shared/services/cliRuntimeGrokBuild.ts @@ -0,0 +1,26 @@ +// Runtime-detection metadata entries extracted from cliRuntime.ts to keep that +// frozen file under its file-size ratchet cap (config/quality/file-size-baseline.json). +// Deliberately untyped (matches cliRuntime.ts's own `Record` CLI_TOOLS +// shape) and has NO import of the CliCatalogEntry schema — keep it that way, so this +// module never drags src/shared/schemas/cliCatalog.ts into the typecheck-core +// transitive graph (that file is not on typecheck:core's curated allowlist). + +/** Grok Build runtime-detection metadata (binary lookup + healthcheck). */ +export const GROK_BUILD_RUNTIME_ENTRY = { + defaultCommand: "grok", + envBinKey: "CLI_GROK_BUILD_BIN", + requiresBinary: true, + healthcheckTimeoutMs: 8000, + paths: { + config: ".grok/config.toml", + }, +}; + +/** Amp runtime-detection metadata (extracted alongside grok-build for file-size headroom). */ +export const AMP_RUNTIME_ENTRY = { + defaultCommand: "amp", + envBinKey: "CLI_AMP_BIN", + requiresBinary: true, + healthcheckTimeoutMs: 12000, + paths: {}, +}; diff --git a/tests/unit/cli-catalog-counts.test.ts b/tests/unit/cli-catalog-counts.test.ts index 681993eccb..c6f203d928 100644 --- a/tests/unit/cli-catalog-counts.test.ts +++ b/tests/unit/cli-catalog-counts.test.ts @@ -30,7 +30,7 @@ test(`CLI_TOOLS has exactly ${EXPECTED_AGENT_COUNT} agent entries`, () => { ); }); -test("CLI_TOOLS total code entries (including none) equals 24 (20 visible + 4 none)", () => { +test("CLI_TOOLS total code entries (including none) equals 25 (21 visible + 4 none)", () => { // code-none entries: antigravity, kiro, cursor (app), hermes (simple guide) const codeNone = codeAll.filter((t) => t.baseUrlSupport === "none"); assert.equal( @@ -38,11 +38,11 @@ test("CLI_TOOLS total code entries (including none) equals 24 (20 visible + 4 no 4, `Expected 4 code entries with baseUrlSupport='none', got ${codeNone.length}: ${codeNone.map((t) => t.id).join(", ")}` ); - assert.equal(codeAll.length, 24, `Expected 24 total code entries, got ${codeAll.length}`); + assert.equal(codeAll.length, 25, `Expected 25 total code entries, got ${codeAll.length}`); }); -test("CLI_TOOLS total (code + agent) = 32", () => { - assert.equal(all.length, 32, `Expected 32 total entries, got ${all.length}`); +test("CLI_TOOLS total (code + agent) = 33", () => { + assert.equal(all.length, 33, `Expected 33 total entries, got ${all.length}`); }); test("All code-none entries have configType mitm OR are legacy excluded entries", () => { @@ -66,7 +66,7 @@ test("All agent entries have baseUrlSupport 'full' or 'partial' (no agent is 'no } }); -test("The 20 visible code entries match D15 list exactly (+ crush + codewhale)", () => { +test("The 21 visible code entries match D15 list exactly (+ crush + codewhale + grok-build)", () => { const d15List = new Set([ "claude", "codex", @@ -88,6 +88,7 @@ test("The 20 visible code entries match D15 list exactly (+ crush + codewhale)", "pi", "custom", "crush", + "grok-build", ]); const visibleIds = new Set(codeVisible.map((t) => t.id)); for (const id of d15List) { diff --git a/tests/unit/cli-tools-schema.test.ts b/tests/unit/cli-tools-schema.test.ts index 4648f448ee..85841732cb 100644 --- a/tests/unit/cli-tools-schema.test.ts +++ b/tests/unit/cli-tools-schema.test.ts @@ -1,7 +1,7 @@ import test from "node:test"; import assert from "node:assert/strict"; -test("CLI_TOOLS registry contains all expected tools (plan 14 — 32 total + crush + codewhale + omp + letta)", async () => { +test("CLI_TOOLS registry contains all expected tools (plan 14 — 33 total + crush + codewhale + omp + letta + grok-build)", async () => { const { CLI_TOOLS } = await import("../../src/shared/constants/cliTools.ts"); // windsurf and amp removed per plan 14 D17 (MITM backlog plan 11) // New entries added: roo, jcode, deepseek-tui, smelt, pi, aider, forge, @@ -10,6 +10,7 @@ test("CLI_TOOLS registry contains all expected tools (plan 14 — 32 total + cru // codewhale added 2026-07-02 as a dual entry alongside deepseek-tui // (CodeWhale is the actively-maintained successor to DeepSeek TUI). // omp + letta added by #6318 (agent-category CLI integrations). + // grok-build added — xAI Grok Build TUI coding agent (ported from upstream decolua/9router#2571). const expected = [ "claude", "codex", @@ -43,6 +44,7 @@ test("CLI_TOOLS registry contains all expected tools (plan 14 — 32 total + cru "letta", "agent-deck", "crush", + "grok-build", ]; for (const id of expected) { assert.ok(id in CLI_TOOLS, `Missing tool: ${id}`);