Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion bin/omniroute.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ if (portIdx !== -1 && args[portIdx + 1]) {

const apiPort = parsePort(process.env.API_PORT || String(port), port);
const dashboardPort = parsePort(process.env.DASHBOARD_PORT || String(port), port);
const noOpen = args.includes("--no-open");
const isAndroid = process.platform === 'android';
let noOpen = args.includes("--no-open") || isAndroid;

console.log(`
\x1b[36m ____ _ ____ _
Expand All @@ -256,6 +257,16 @@ console.log(`
\\\\____/|_| |_| |_|_| |_|_|_| \\\\_\\\\___/ \\\\__,_|\\\\__\\\\___|
\x1b[0m`);

if (isAndroid) {
console.log(`\x1b[33m[OmniRoute] Running on Android/Termux — headless mode enabled automatically\x1b[0m`);
console.log(`\x1b[33m[OmniRoute] Platform: android/arm64 — unsupported features:\x1b[0m
- Codex Responses WebSocket (wreq-js unavailable)
- ChatGPT Web TLS impersonation (tls-client-node unavailable)
- Electron desktop app
- MITM proxy / system certificate install
`);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The platform log message hardcodes arm64. While this is the most common architecture for Android/Termux, it is better to use process.arch to accurately reflect the actual environment (e.g., when running on x86_64 emulators or other ARM variants).

  console.log("\x1b[33m[OmniRoute] Platform: android/" + process.arch + " — unsupported features:\x1b[0m\n  - Codex Responses WebSocket (wreq-js unavailable)\n  - ChatGPT Web TLS impersonation (tls-client-node unavailable)\n  - Electron desktop app\n  - MITM proxy / system certificate install\n");

}

const nodeSupport = getNodeRuntimeSupport();
if (!nodeSupport.nodeCompatible) {
const runtimeWarning = getNodeRuntimeWarning() || "Unsupported Node.js runtime detected.";
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,18 @@
"react-markdown": "^10.1.0",
"recharts": "^3.7.0",
"selfsigned": "^5.5.0",
"tls-client-node": "^0.1.13",
"tsx": "^4.21.0",
"undici": "^8.2.0",
"uuid": "^14.0.0",
"wreq-js": "^2.0.1",
"xxhash-wasm": "^1.1.0",
"yazl": "^3.3.1",
"zod": "^4.4.3",
"zustand": "^5.0.10"
},
"optionalDependencies": {
"keytar": "^7.9.0"
"keytar": "^7.9.0",
"tls-client-node": "^0.1.13",
"wreq-js": "^2.0.1"
},
"devDependencies": {
"@playwright/test": "^1.58.2",
Expand Down
22 changes: 19 additions & 3 deletions scripts/postinstall.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,20 @@ async function fixBetterSqliteBinary() {
? "npm install better-sqlite3 --build-from-source --force"
: "npm rebuild better-sqlite3";

const env = { ...process.env };
if (isAndroid) {
env.GYP_DEFINES = "android_ndk_path=''";
}

// app/ may not exist when running from source (before `npm run build`)
const appDir = join(ROOT, "app");
const rebuildCwd = existsSync(appDir) ? appDir : ROOT;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The ternary operator existsSync(appDir) ? appDir : ROOT is redundant here. The early return at line 55 already ensures that app/node_modules/better-sqlite3 exists, which implies the app/ directory must exist. If the intention is to support source builds where the app/ directory is missing (as suggested by the comment on line 149), the early return at line 55 should be adjusted to allow the root directory as well.

    const rebuildCwd = appDir;


execSync(rebuildCmd, {
cwd: join(ROOT, "app"),
cwd: rebuildCwd,
stdio: "inherit",
timeout: 300_000, // 5 minutes for source builds
timeout: isAndroid ? 600_000 : 300_000, // ARM compilation is slower
env,
});

process.dlopen({ exports: {} }, appBinary);
Expand All @@ -153,7 +163,8 @@ async function fixBetterSqliteBinary() {
} catch (err) {
const isTimeout = err.killed || err.signal === "SIGTERM";
if (isTimeout) {
console.warn(" ⚠️ npm rebuild timed out after 300s.");
const secs = process.platform === "android" ? 600 : 300;
console.warn(` ⚠️ npm rebuild timed out after ${secs}s.`);
} else {
console.warn(` ⚠️ npm rebuild failed: ${err.message}`);
}
Expand Down Expand Up @@ -189,6 +200,11 @@ async function fixBetterSqliteBinary() {
* Fixes: https://github.com/diegosouzapw/OmniRoute/issues/1634
*/
async function fixWreqJsBinary() {
if (process.platform === "android") {
console.log(" [postinstall] wreq-js: skipped on android (unsupported platform)");
return;
}

const appWreqDir = join(ROOT, "app", "node_modules", "wreq-js", "rust");
const rootWreqDir = join(ROOT, "node_modules", "wreq-js", "rust");

Expand Down
36 changes: 34 additions & 2 deletions scripts/responses-ws-proxy.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
import { createHash, randomUUID } from "node:crypto";
import { createRequire } from "node:module";
import { STATUS_CODES } from "node:http";
import { websocket } from "wreq-js";

const _wreqRequire = createRequire(import.meta.url);

let _websocketFn = null;
let _wreqChecked = false;

function getWebSocketTransport() {
if (_wreqChecked) return _websocketFn;
_wreqChecked = true;
try {
const mod = _wreqRequire("wreq-js");
_websocketFn = typeof mod.websocket === "function" ? mod.websocket : null;
} catch {
_websocketFn = null;
}
return _websocketFn;
}

export const RESPONSES_WS_PUBLIC_PATHS = new Set([
"/responses",
Expand Down Expand Up @@ -562,7 +579,7 @@ export function createResponsesWsProxy({
baseUrl,
bridgeSecret,
fetchImpl = fetch,
wsFactory = websocket,
wsFactory = getWebSocketTransport(),
pingIntervalMs = 25000,
idleTimeoutMs = 90000,
maxBufferBytes = DEFAULT_MAX_WS_BUFFER_BYTES,
Expand All @@ -583,6 +600,21 @@ export function createResponsesWsProxy({
return false;
}

if (!wsFactory) {
writeHttpError(
socket,
503,
JSON.stringify({
error: {
message:
"Responses WebSocket proxy unavailable: wreq-js is not installed on this platform",
code: "wreq_js_unavailable",
},
})
);
return true;
}

const upgradeHeader = String(req.headers.upgrade || "").toLowerCase();
if (upgradeHeader !== "websocket") {
writeHttpError(
Expand Down