feat: improve API configuration and script execution

- Added API_HOST variable to .env.example for enhanced host configuration.
- Updated package.json scripts to utilize a new run-next.mjs script for development and production.
- Introduced run-next.mjs to manage Next.js server execution with dynamic port handling.
- Enhanced route.ts files to normalize API base URLs and improve configuration checks.
- Updated apiBridgeServer.ts to use API_HOST for server initialization.
- Expanded global TypeScript definitions to include API_HOST.
This commit is contained in:
Steven Rafferty
2026-02-26 15:15:35 +00:00
parent d0138a5037
commit fb597c677e
7 changed files with 76 additions and 9 deletions

View File

@@ -27,6 +27,7 @@ SQLITE_CLEAN_LEGACY_FILES=true
PORT=20128
# Optional split ports:
# API_PORT=20128
# API_HOST=0.0.0.0
# DASHBOARD_PORT=20128
NODE_ENV=production
INSTANCE_NAME=omniroute

View File

@@ -42,10 +42,10 @@
},
"homepage": "https://omniroute.online",
"scripts": {
"dev": "OMNIROUTE_PORT=${PORT:-20128} next dev --webpack --port ${DASHBOARD_PORT:-${PORT:-20128}}",
"dev": "node scripts/run-next.mjs dev",
"build": "next build --webpack",
"build:cli": "node scripts/prepublish.mjs",
"start": "OMNIROUTE_PORT=${PORT:-20128} next start --port ${DASHBOARD_PORT:-${PORT:-20128}}",
"start": "node scripts/run-next.mjs start",
"lint": "eslint .",
"test": "node --test tests/unit/*.test.mjs",
"test:unit": "node --import tsx/esm --test tests/unit/*.test.mjs",

41
scripts/run-next.mjs Normal file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env node
import { spawn } from "node:child_process";
function parsePort(value, fallback) {
const parsed = Number.parseInt(String(value), 10);
return Number.isFinite(parsed) && parsed > 0 && parsed <= 65535 ? parsed : fallback;
}
const mode = process.argv[2] === "start" ? "start" : "dev";
const basePort = parsePort(process.env.PORT || "20128", 20128);
const apiPort = parsePort(process.env.API_PORT || String(basePort), basePort);
const dashboardPort = parsePort(process.env.DASHBOARD_PORT || String(basePort), basePort);
const args = ["./node_modules/next/dist/bin/next", mode, "--port", String(dashboardPort)];
if (mode === "dev") {
args.splice(2, 0, "--webpack");
}
const child = spawn(process.execPath, args, {
stdio: "inherit",
env: {
...process.env,
OMNIROUTE_PORT: String(basePort),
PORT: String(dashboardPort),
DASHBOARD_PORT: String(dashboardPort),
API_PORT: String(apiPort),
},
});
child.on("exit", (code, signal) => {
if (signal) {
process.kill(process.pid, signal);
return;
}
process.exit(code ?? 0);
});
process.on("SIGINT", () => child.kill("SIGINT"));
process.on("SIGTERM", () => child.kill("SIGTERM"));

View File

@@ -53,22 +53,40 @@ async function saveContinueConfig({ baseUrl, apiKey, model }) {
}
// Build the OmniRoute model entry
const normalizedBaseUrl = String(baseUrl || "")
.trim()
.replace(/\/+$/, "");
const routerModel = {
apiBase: baseUrl,
apiBase: normalizedBaseUrl,
title: model,
model: model,
provider: "openai",
apiKey: apiKey || "sk_omniroute",
omnirouteManaged: true,
};
// Merge into existing models array
const models = existingConfig.models || [];
function normalizeApiBase(value: unknown): string {
return String(value || "")
.trim()
.replace(/\/+$/, "")
.toLowerCase();
}
// Check if OmniRoute entry already exists and update it, or add new
const existingIdx = models.findIndex(
(m) =>
m.apiBase &&
(m.apiBase.includes("localhost") || m.apiBase.includes("omniroute") || m.title === model)
m &&
(m.omnirouteManaged === true ||
normalizeApiBase(m.apiBase) === normalizedBaseUrl.toLowerCase() ||
normalizeApiBase(m.apiBase).includes("omniroute") ||
normalizeApiBase(m.apiBase).includes("localhost:20128") ||
normalizeApiBase(m.apiBase).includes("127.0.0.1:20128") ||
String(m.apiKey || "")
.toLowerCase()
.includes("sk_omniroute"))
);
if (existingIdx >= 0) {

View File

@@ -8,6 +8,9 @@ import {
getCliPrimaryConfigPath,
} from "@/shared/services/cliRuntime";
import { getAllCliToolLastConfigured } from "@/lib/db/cliToolState";
import { getRuntimePorts } from "@/lib/runtime/ports";
const { apiPort } = getRuntimePorts();
// Check if a tool has OmniRoute configured by reading its config file directly
// This replaces the expensive self-referential HTTP calls to /api/cli-tools/*-settings
@@ -31,9 +34,12 @@ async function checkToolConfigStatus(toolId: string): Promise<string> {
case "openclaw":
case "cline":
case "kilo":
// Generic check: look for any OmniRoute-related URL in the config
// Generic check: look for OmniRoute-specific markers in the config
const configStr = JSON.stringify(config).toLowerCase();
return configStr.includes("omniroute") || configStr.includes("localhost")
return configStr.includes("omniroute") ||
configStr.includes("sk_omniroute") ||
configStr.includes(`localhost:${apiPort}`) ||
configStr.includes(`127.0.0.1:${apiPort}`)
? "configured"
: "not_configured";
default:

View File

@@ -44,7 +44,7 @@ function proxyRequest(req: IncomingMessage, res: ServerResponse, dashboardPort:
}
declare global {
// eslint-disable-next-line no-var
var __omnirouteApiBridgeStarted: boolean | undefined;
}
@@ -54,7 +54,7 @@ export function initApiBridgeServer(): void {
const { apiPort, dashboardPort } = getRuntimePorts();
if (apiPort === dashboardPort) return;
const host = process.env.HOSTNAME || "0.0.0.0";
const host = process.env.API_HOST || "0.0.0.0";
const server = http.createServer((req, res) => {
const rawUrl = req.url || "/";

View File

@@ -14,6 +14,7 @@ declare namespace NodeJS {
PROMPT_CACHE_TTL_MS?: string;
NEXT_PUBLIC_CLOUD_URL?: string;
API_PORT?: string;
API_HOST?: string;
DASHBOARD_PORT?: string;
OMNIROUTE_PORT?: string;
NODE_ENV?: "development" | "production" | "test";