mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-01 04:42:10 +03:00
* feat(cli): Codex CLI launcher + setup commands Two new CLI subcommands mirroring the `launch`/`configure` pattern, for driving the OpenAI Codex CLI against OmniRoute: - `omniroute launch-codex` — boots OmniRoute (if needed) and launches Codex CLI pointed at it (local or remote VPS), with no manual env/config editing. - `omniroute setup-codex` — generates ~/.codex profile files from OmniRoute's live model catalog. Registered in the command registry; en.json + pt-BR.json locale sections added (keeps the cli-i18n-catalog top-level parity gate green). CODEX-CLI-CONFIGURATION.md refreshed. Consolidated from work-in-progress that was uncommitted on the shared checkout; reconstructed on release/v3.8.30. * chore(vscode): reduce git repo-detection overhead for nested worktrees Disable VS Code's git auto-repository-detection / submodule scan / autofetch so the Source Control view stops indexing the ~44 nested repos (worktrees + _references/* + _mono_repo/*), which caused constant "validating" churn. Only the root repo is tracked. Editor-only settings; no runtime impact.
104 lines
3.5 KiB
JavaScript
104 lines
3.5 KiB
JavaScript
import { spawn } from "node:child_process";
|
|
import { t } from "../i18n.mjs";
|
|
|
|
/**
|
|
* Health-check an OmniRoute endpoint (local or remote) before launching Codex.
|
|
* @param {string} baseUrl
|
|
* @param {number} timeoutMs
|
|
* @returns {Promise<boolean>}
|
|
*/
|
|
async function healthCheck(baseUrl, timeoutMs = 3000) {
|
|
try {
|
|
const res = await fetch(`${baseUrl.replace(/\/v1$/, "")}/api/monitoring/health`, {
|
|
signal: AbortSignal.timeout(timeoutMs),
|
|
});
|
|
return res.ok;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build the env for the Codex child process.
|
|
* Injects OMNIROUTE_API_KEY if an explicit api-key was provided on the command line
|
|
* (useful when launching against a remote VPS whose key differs from ~/.bashrc).
|
|
* @param {Record<string,string>} baseEnv
|
|
* @param {string|undefined} apiKey
|
|
* @returns {Record<string,string>}
|
|
*/
|
|
export function buildCodexEnv(baseEnv, apiKey) {
|
|
const env = { ...baseEnv };
|
|
if (apiKey) env.OMNIROUTE_API_KEY = apiKey;
|
|
return env;
|
|
}
|
|
|
|
/**
|
|
* @param {{port?:string, remote?:string, profile?:string, apiKey?:string}} opts
|
|
* @param {string[]} codexArgs pass-through args for the codex binary
|
|
* @returns {Promise<number>} exit code
|
|
*/
|
|
export async function runLaunchCodexCommand(opts = {}, codexArgs = []) {
|
|
const port = Number(opts.port ?? process.env.PORT ?? 20128) || 20128;
|
|
const baseUrl = opts.remote ?? `http://localhost:${port}/v1`;
|
|
|
|
const ok = await healthCheck(baseUrl);
|
|
if (!ok) {
|
|
const location = opts.remote ?? `port ${port}`;
|
|
console.error(
|
|
(t("launch.notRunning") || "OmniRoute is not running on port {port}. Start it with 'omniroute serve'.")
|
|
.replace("{port}", String(location))
|
|
);
|
|
return 1;
|
|
}
|
|
|
|
const profile = opts.profile;
|
|
const extraArgs = profile ? ["--profile", profile, ...codexArgs] : codexArgs;
|
|
const env = buildCodexEnv(process.env, opts.apiKey ?? opts["api-key"]);
|
|
|
|
return await new Promise((resolve) => {
|
|
const child = spawn("codex", extraArgs, { env, stdio: "inherit" });
|
|
child.on("error", (err) => {
|
|
if (err?.code === "ENOENT") {
|
|
console.error(
|
|
"The 'codex' CLI was not found in PATH. Install with:\n" +
|
|
" npm install -g @openai/codex"
|
|
);
|
|
resolve(127);
|
|
} else {
|
|
console.error(String(err?.message || err));
|
|
resolve(1);
|
|
}
|
|
});
|
|
child.on("exit", (code) => resolve(code ?? 0));
|
|
});
|
|
}
|
|
|
|
export function registerLaunchCodex(program) {
|
|
program
|
|
.command("launch-codex")
|
|
.description(
|
|
t("launchCodex.description") ||
|
|
"Launch Codex CLI pointed at OmniRoute (local or remote VPS)"
|
|
)
|
|
.option("--port <port>", "Local OmniRoute port (ignored when --remote is set)", "20128")
|
|
.option(
|
|
"--remote <url>",
|
|
"Remote OmniRoute base URL, e.g. http://100.67.86.91:20128/v1 (overrides --port)"
|
|
)
|
|
.option("--profile <name>", "Codex profile to activate (passed as --profile <name>)")
|
|
.option("-p, --p <name>", "Alias for --profile")
|
|
.option(
|
|
"--api-key <key>",
|
|
"OmniRoute API key (overrides OMNIROUTE_API_KEY env var for this invocation)"
|
|
)
|
|
.allowUnknownOption(true)
|
|
.allowExcessArguments(true)
|
|
.argument("[codexArgs...]", "arguments passed through to the codex binary")
|
|
.action(async (codexArgs, opts) => {
|
|
// -p is an alias for --profile
|
|
const merged = { ...opts, profile: opts.profile ?? opts.p };
|
|
const exitCode = await runLaunchCodexCommand(merged, codexArgs ?? []);
|
|
if (exitCode !== 0) process.exit(exitCode);
|
|
});
|
|
}
|