mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-14 10:52:17 +03:00
Landed with the design call resolved per the owner's pick — **option 1**: the synced store is now endpoint-agnostic (persistDiscoveredModels and managedModelImport no longer drop non-chat models at write time), and chat selectability moved to read time (auto-pool expansion in autoStrategy applies filterChatSelectableModels; the models-route projection already had its chatOnly filter). Your discovery test now passes end-to-end (3/3): /api/show capabilities persist per connection and image/embedding requests route through the advertising host. Reconciliation notes: conflicted areas merged onto the current tip (adobe discovery import, requestedModel preflight signature, resolvedProvider fast-path coexists with the synced-route override — explicit resolution wins); carried base-red drains (#10055 memoization, #11071 test variants) dropped as already-landed; the managed-model-import exclusion test was propagated to the new contract (image/video models persist; the read filter still hides them from chat pickers — pinned by a new assertion). Full battery: 205/206 focused (the one red is a confirmed periodic-timer timing flake on the loaded devbox — 20/20 isolated), autoCombo vitest 30/30, combo suites 46/46, gates + typecheck clean. Thank you @yourspraveen — the capability probe + routing design was right; it just needed the store contract opened up. Fixes #11087.
139 lines
4.6 KiB
JavaScript
139 lines
4.6 KiB
JavaScript
/**
|
|
* Canonical executable manifest for the OmniRoute CLI command surfaces.
|
|
*
|
|
* One entry per canonical target id. `run.mjs`, `configure.mjs` and
|
|
* `completion.mjs` derive their target lists, alias resolution and model-flag
|
|
* wiring from this table instead of keeping private copies, so a new target
|
|
* (or a renamed alias) is declared exactly once.
|
|
*
|
|
* The server-side runtime catalog (`src/shared/services/cliRuntime.ts`) stays
|
|
* the source of truth for binaries, config paths and health checks; the drift
|
|
* test `tests/unit/cli/cli-manifest-drift.test.ts` asserts the two worlds and
|
|
* every consumer surface stay in sync.
|
|
*
|
|
* Capability semantics:
|
|
* - `run`: launchable through `omniroute run <target>`.
|
|
* - `configure`: supported by the `omniroute configure <target>` picker.
|
|
* - `runModel`: how `run` injects `--model` for the target (`null` when the
|
|
* model travels via env/provider args instead of a CLI flag).
|
|
*/
|
|
|
|
export const CLI_TARGET_MANIFEST = Object.freeze({
|
|
claude: Object.freeze({
|
|
description: "Claude Code",
|
|
aliases: Object.freeze(["claude-code", "cc", "anthropic"]),
|
|
run: true,
|
|
configure: true,
|
|
runModel: null, // injected via ANTHROPIC_MODEL env by the launcher
|
|
}),
|
|
codex: Object.freeze({
|
|
description: "OpenAI Codex CLI",
|
|
aliases: Object.freeze(["codex-cli", "openai-codex", "openai"]),
|
|
run: true,
|
|
configure: true,
|
|
runModel: null, // injected via -c model_providers.omniroute.* args
|
|
}),
|
|
aider: Object.freeze({
|
|
description: "Aider",
|
|
aliases: Object.freeze([]),
|
|
run: true,
|
|
configure: true,
|
|
runModel: Object.freeze({ flag: "--model", prefix: "openai/" }),
|
|
}),
|
|
goose: Object.freeze({
|
|
description: "Goose",
|
|
aliases: Object.freeze(["goose-cli"]),
|
|
run: true,
|
|
configure: true,
|
|
runModel: null, // injected via GOOSE_MODEL env
|
|
}),
|
|
opencode: Object.freeze({
|
|
description: "OpenCode",
|
|
aliases: Object.freeze(["open-code"]),
|
|
run: true,
|
|
configure: true,
|
|
runModel: Object.freeze({ flag: "--model", prefix: "omniroute/" }),
|
|
}),
|
|
qwen: Object.freeze({
|
|
description: "Qwen Code",
|
|
aliases: Object.freeze(["qwen-code"]),
|
|
run: true,
|
|
configure: true,
|
|
runModel: Object.freeze({ flag: "--model", prefix: "", required: true }),
|
|
}),
|
|
gemini: Object.freeze({
|
|
// Launch contract verified against @google/gemini-cli 0.50.0:
|
|
// GOOGLE_GEMINI_BASE_URL points the SDK at OmniRoute's /v1beta surface,
|
|
// GEMINI_API_KEY + isolated GEMINI_CLI_HOME (settings selectedType
|
|
// "gemini-api-key") force API-key auth over any stored OAuth session.
|
|
description: "Google Gemini CLI",
|
|
aliases: Object.freeze(["gemini-cli"]),
|
|
run: true,
|
|
configure: false,
|
|
runModel: Object.freeze({ flag: "--model", prefix: "" }),
|
|
}),
|
|
cline: Object.freeze({
|
|
description: "Cline",
|
|
aliases: Object.freeze([]),
|
|
run: false,
|
|
configure: true,
|
|
runModel: null,
|
|
}),
|
|
continue: Object.freeze({
|
|
description: "Continue",
|
|
aliases: Object.freeze(["cn"]),
|
|
run: false,
|
|
configure: true,
|
|
runModel: null,
|
|
}),
|
|
kilo: Object.freeze({
|
|
description: "Kilo Code",
|
|
aliases: Object.freeze(["kilocode", "kilo-code", "kilo_cli"]),
|
|
run: false,
|
|
configure: true,
|
|
runModel: null,
|
|
}),
|
|
});
|
|
|
|
/**
|
|
* List canonical target ids, optionally filtered by capability
|
|
* (`"run"` or `"configure"`). Order follows manifest declaration order.
|
|
*/
|
|
export function listManifestTargets(capability) {
|
|
return Object.entries(CLI_TARGET_MANIFEST)
|
|
.filter(([, entry]) => !capability || entry[capability])
|
|
.map(([id]) => id);
|
|
}
|
|
|
|
/**
|
|
* Resolve a user-supplied target (canonical id or alias) to its canonical id.
|
|
* Returns `undefined` when the target is unknown or lacks the capability.
|
|
*/
|
|
export function resolveManifestTarget(rawTarget, capability) {
|
|
const normalized = String(rawTarget || "")
|
|
.trim()
|
|
.toLowerCase();
|
|
if (!normalized) return undefined;
|
|
for (const [id, entry] of Object.entries(CLI_TARGET_MANIFEST)) {
|
|
if (id === normalized || entry.aliases.includes(normalized)) {
|
|
if (capability && !entry[capability]) return undefined;
|
|
return id;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
/** Model CLI-flag arguments for a `run` target, derived from the manifest. */
|
|
export function manifestModelArgs(targetId, model) {
|
|
if (!model) return [];
|
|
const spec = CLI_TARGET_MANIFEST[targetId]?.runModel;
|
|
if (!spec) return [];
|
|
const value = spec.prefix && !model.startsWith(spec.prefix) ? `${spec.prefix}${model}` : model;
|
|
return [spec.flag, value];
|
|
}
|
|
|
|
/** Whether a `run` target refuses to launch without an explicit model. */
|
|
export function manifestRequiresModel(targetId) {
|
|
return Boolean(CLI_TARGET_MANIFEST[targetId]?.runModel?.required);
|
|
}
|