Compare commits

...

2 Commits

Author SHA1 Message Date
diegosouzapw
8dad2d32b6 fix(cli-tools): add opencode to cliRuntime, increase timeouts for slow-start CLIs
- opencode: add to CLI_TOOLS registry with 15s healthcheck timeout
- openclaw/cursor: increase from 12s → 15s (cold-start on VPS)
- continue: add healthcheckTimeoutMs 15s
- VPS: activated CLI_EXTRA_PATHS=/root/.local/bin for kiro-cli visibility
- VPS: installed droid and openclaw npm packages
2026-03-12 16:42:43 -03:00
diegosouzapw
d07a5f0df7 fix(cli-tools): increase kilocode healthcheck timeout from 4s to 15s
kilocode renders ASCII logo banner on startup causing false healthcheck_failed
timeouts on cold-start or low-resource environments (VPS, CI, dashboard)
2026-03-12 16:34:39 -03:00
3 changed files with 53 additions and 8 deletions

View File

@@ -1,5 +1,21 @@
# Changelog
## [2.3.12] - 2026-03-12
### Fixed
- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11
- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout
- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants
- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli
- **cliRuntime**: Add opencode tool registration and increase timeout for continue
## [2.3.11] - 2026-03-12
### Fixed
- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments
## [2.3.10] - 2026-03-12
### Fixed

View File

@@ -1,6 +1,6 @@
{
"name": "omniroute",
"version": "2.3.10",
"version": "2.3.12",
"description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",
"type": "module",
"bin": {

View File

@@ -41,7 +41,7 @@ const CLI_TOOLS: Record<string, any> = {
envBinKey: "CLI_OPENCLAW_BIN",
requiresBinary: true,
// openclaw CLI may take >4s on cold start in containers.
healthcheckTimeoutMs: 12000,
healthcheckTimeoutMs: 15000,
paths: {
settings: ".openclaw/openclaw.json",
},
@@ -51,7 +51,7 @@ const CLI_TOOLS: Record<string, any> = {
envBinKey: "CLI_CURSOR_BIN",
requiresBinary: true,
// Cursor startup can be slower on first run in containerized host-mount mode.
healthcheckTimeoutMs: 12000,
healthcheckTimeoutMs: 15000,
paths: {
config: ".cursor/cli-config.json",
auth: ".config/cursor/auth.json",
@@ -73,7 +73,10 @@ const CLI_TOOLS: Record<string, any> = {
defaultCommand: "kilocode",
envBinKey: "CLI_KILO_BIN",
requiresBinary: true,
healthcheckTimeoutMs: 4000,
// kilocode renders an ASCII logo banner on startup which can take >4s
// on cold-start or low-resource environments (VPS, CI). Increase timeout
// to avoid false healthcheck_failed results.
healthcheckTimeoutMs: 15000,
paths: {
auth: ".local/share/kilo/auth.json",
},
@@ -82,10 +85,22 @@ const CLI_TOOLS: Record<string, any> = {
defaultCommand: null,
envBinKey: "CLI_CONTINUE_BIN",
requiresBinary: false,
// opencode and continue may take up to 15s on first run / cold start on VPS
healthcheckTimeoutMs: 15000,
paths: {
settings: ".continue/config.json",
},
},
opencode: {
defaultCommand: "opencode",
envBinKey: "CLI_OPENCODE_BIN",
requiresBinary: true,
// opencode takes several seconds on cold start environments
healthcheckTimeoutMs: 15000,
paths: {
config: ".config/opencode/config.toml",
},
},
};
const isWindows = () => process.platform === "win32";
@@ -95,7 +110,11 @@ const parseBoolean = (value: unknown, defaultValue = true) => {
return !FALSE_VALUES.has(String(value).trim().toLowerCase());
};
const runProcess = (command: string, args: string[], { env, timeoutMs = 3000 }: { env?: Record<string, string | undefined>; timeoutMs?: number } = {}): Promise<any> =>
const runProcess = (
command: string,
args: string[],
{ env, timeoutMs = 3000 }: { env?: Record<string, string | undefined>; timeoutMs?: number } = {}
): Promise<any> =>
new Promise((resolve) => {
let stdout = "";
let stderr = "";
@@ -231,7 +250,10 @@ const locateCommand = async (command: string, env: Record<string, string | undef
return { installed: !!first, commandPath: first, reason: first ? null : "not_found" };
};
const locateCommandCandidate = async (commands: string[], env: Record<string, string | undefined>) => {
const locateCommandCandidate = async (
commands: string[],
env: Record<string, string | undefined>
) => {
if (!Array.isArray(commands) || commands.length === 0) {
return { command: null, installed: false, commandPath: null, reason: "missing_command" };
}
@@ -246,7 +268,11 @@ const locateCommandCandidate = async (commands: string[], env: Record<string, st
return { command: commands[0], installed: false, commandPath: null, reason: "not_found" };
};
const checkRunnable = async (commandPath: string, env: Record<string, string | undefined>, timeoutMs = 4000) => {
const checkRunnable = async (
commandPath: string,
env: Record<string, string | undefined>,
timeoutMs = 4000
) => {
for (const args of [["--version"], ["-v"]]) {
const result = await runProcess(commandPath, args, { env, timeoutMs });
if (result.ok) {
@@ -272,7 +298,10 @@ export const getCliConfigPaths = (toolId: string) => {
if (!tool) return null;
const home = getCliConfigHome();
return Object.fromEntries(
Object.entries(tool.paths).map(([key, relativePath]) => [key, path.join(home, relativePath as string)])
Object.entries(tool.paths).map(([key, relativePath]) => [
key,
path.join(home, relativePath as string),
])
);
};