mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-19 13:42:09 +03:00
- canonical executable manifest (bin/cli/cli-manifest.mjs): run/configure/completion derive targets, aliases and --model wiring from one table; drift test cross-checks manifest x cliRuntime x UI catalog (tests/unit/cli/cli-manifest-drift.test.ts) - dashboard Codex generator converged to ~/.codex/config.toml (modern Codex v0.137+, verified against codex-cli 0.147.0): conservative merge, env_key auth (key never written), refuses invalid TOML, reports legacy config.yaml as migration note - omniroute run gemini: launcher over OmniRoute's /v1beta surface via GOOGLE_GEMINI_BASE_URL + isolated GEMINI_CLI_HOME forcing gemini-api-key auth (contract proven against @google/gemini-cli 0.50.0); ACP registration kept distinct - opt-in real smoke harness for upstream CLIs (RUN_CLI_SMOKE=1, credential by env NAME, redacted output): tests/integration/upstream-cli-smoke.int.test.ts - container-guard homologation for POST /api/cli-tools/apply (422 in container, dry-run preview allowed, host write passes) + docs; guard untouched - typecheck: omniglyphAdapter union narrowing, usageTracking typed signatures (UsageLike, no any), models.ts isValidModel params — typecheck:core and typecheck:noimplicit:core now clean - relay core (prior session of this effort): omniroute run for 6 CLIs, configure picker with per-context favorites/recents, contexts with optional keychain + 0600 fallback, provider CRUD with recursive redaction, completion updates, docs
108 lines
4.2 KiB
TypeScript
108 lines
4.2 KiB
TypeScript
import { describe, it, before } from "node:test";
|
|
import assert from "node:assert";
|
|
import * as toolDetector from "../../../src/lib/cli-helper/tool-detector.ts";
|
|
|
|
describe("tool-detector", () => {
|
|
before(() => {
|
|
// Install mock exec implementation for deterministic testing
|
|
// @ts-expect-error - internal test hook
|
|
toolDetector.__setExecFileImpl(async (cmd) => {
|
|
if (cmd === "opencode") {
|
|
return { stdout: "v1.0.0\n" };
|
|
}
|
|
if (cmd === "hermes") {
|
|
return { stdout: "v0.75.3\n" };
|
|
}
|
|
if (cmd === "openclaw") {
|
|
return { stdout: "v0.3.1\n" };
|
|
}
|
|
if (cmd === "which") {
|
|
return { stdout: "/usr/local/bin/opencode\n" };
|
|
}
|
|
throw new Error("Command not found");
|
|
});
|
|
});
|
|
|
|
describe("detectTool", () => {
|
|
it("returns null for unknown tool id", async () => {
|
|
const result = await toolDetector.detectTool("unknown-tool-xyz");
|
|
assert.strictEqual(result, null);
|
|
});
|
|
|
|
it("returns DetectedTool object for installed tool", async () => {
|
|
const result = await toolDetector.detectTool("opencode");
|
|
assert.ok(result !== null);
|
|
assert.strictEqual(result!.id, "opencode");
|
|
assert.strictEqual(result!.name, "OpenCode");
|
|
assert.strictEqual(result!.installed, true);
|
|
assert.strictEqual(result!.version, "1.0.0");
|
|
assert.ok(result!.configPath.includes(".config/opencode"));
|
|
assert.strictEqual(typeof result!.configured, "boolean");
|
|
});
|
|
|
|
it("returns DetectedTool object for Hermes with the Hermes config path", async () => {
|
|
const result = await toolDetector.detectTool("hermes");
|
|
assert.ok(result !== null);
|
|
assert.strictEqual(result!.id, "hermes");
|
|
assert.strictEqual(result!.name, "Hermes");
|
|
assert.strictEqual(result!.installed, true);
|
|
assert.strictEqual(result!.version, "0.75.3");
|
|
assert.ok(result!.configPath.includes(".hermes/config.yaml"));
|
|
assert.strictEqual(typeof result!.configured, "boolean");
|
|
});
|
|
|
|
// Regression test for #2833 — openclaw was missing from TOOLS array
|
|
it("returns DetectedTool object for openclaw with the openclaw config path", async () => {
|
|
const result = await toolDetector.detectTool("openclaw");
|
|
assert.ok(result !== null, "detectTool('openclaw') must not return null");
|
|
assert.strictEqual(result!.id, "openclaw");
|
|
assert.strictEqual(result!.name, "OpenClaw");
|
|
assert.strictEqual(result!.installed, true);
|
|
assert.strictEqual(result!.version, "0.3.1");
|
|
assert.ok(
|
|
result!.configPath.includes(".openclaw/openclaw.json"),
|
|
`expected configPath to include '.openclaw/openclaw.json', got: ${result!.configPath}`
|
|
);
|
|
assert.strictEqual(typeof result!.configured, "boolean");
|
|
});
|
|
|
|
it("normalizes the legacy kilocode id to the canonical kilo target", async () => {
|
|
const result = await toolDetector.detectTool("kilocode");
|
|
assert.ok(result !== null);
|
|
assert.strictEqual(result!.id, "kilo");
|
|
assert.strictEqual(result!.name, "Kilo Code");
|
|
assert.ok(result!.configPath.includes(".local/share/kilo/auth.json"));
|
|
});
|
|
});
|
|
|
|
describe("detectAllTools", () => {
|
|
it("returns array (may be empty if tools not installed)", async () => {
|
|
const tools = await toolDetector.detectAllTools();
|
|
assert.ok(Array.isArray(tools));
|
|
// All items must pass shape check
|
|
for (const t of tools) {
|
|
assert.ok(t.id);
|
|
assert.ok(t.name);
|
|
assert.strictEqual(typeof t.installed, "boolean");
|
|
assert.ok("configPath" in t);
|
|
assert.ok("configured" in t);
|
|
}
|
|
});
|
|
|
|
// Regression test for #2833 — openclaw must appear in detectAllTools()
|
|
it("includes openclaw in the detected tools list", async () => {
|
|
const tools = await toolDetector.detectAllTools();
|
|
const openclaw = tools.find((t) => t.id === "openclaw");
|
|
assert.ok(
|
|
openclaw !== undefined,
|
|
"detectAllTools() must include an entry with id='openclaw'"
|
|
);
|
|
assert.strictEqual(openclaw!.name, "OpenClaw");
|
|
assert.ok(
|
|
openclaw!.configPath.includes(".openclaw/openclaw.json"),
|
|
`expected configPath to include '.openclaw/openclaw.json', got: ${openclaw!.configPath}`
|
|
);
|
|
});
|
|
});
|
|
});
|