feat: embed daemon JS in binary, eliminate npm install of camoufox-browser

The daemon JS files (daemon.js, server.js, browser.js, protocol.js,
snapshot.js, ipc.js) are now EMBEDDED in the compiled Rust binary via
include_dir! and extracted to ~/.gyandoot/daemon/ on first run.

This eliminates the need to npm install -g camoufox-browser@0.1.0,
which bundles an incompatible camoufox-js@0.9.3 that caused:
- 'Cannot open database' errors
- Re-downloading 298MB browser on every navigation
- Circular install/remove/install loops

Now the daemon imports camoufox-js from the global npm install (v0.11.0)
which is installed by install.sh. Clean, no bundled deps, no conflicts.

Also removed: is_npm_package_installed(), install_npm_package(),
find_daemon_js() — all replaced by gyandoot_browser::daemon::extract_daemon()
This commit is contained in:
2026-06-13 23:22:15 +05:30
parent 57308e7805
commit d5cab65099
12 changed files with 2063 additions and 197 deletions

View File

@@ -0,0 +1,76 @@
import * as os from "node:os";
import * as path from "node:path";
import * as fs from "node:fs";
export const isWindows = process.platform === "win32";
export function isValidSessionName(name) {
if (!name)
return false;
if (name.length > 64)
return false;
if (name.includes(".."))
return false;
return /^[a-zA-Z0-9._-]+$/.test(name);
}
/**
* Get the base directory for socket/pid files.
* Priority: CAMOUFOX_BROWSER_SOCKET_DIR > AGENT_BROWSER_SOCKET_DIR > XDG_RUNTIME_DIR > ~/.camoufox-browser > tmpdir
*/
export function getSocketDir() {
const explicit = process.env.CAMOUFOX_BROWSER_SOCKET_DIR || process.env.AGENT_BROWSER_SOCKET_DIR;
if (explicit && explicit.length > 0)
return explicit;
if (process.env.XDG_RUNTIME_DIR && process.env.XDG_RUNTIME_DIR.length > 0) {
return path.join(process.env.XDG_RUNTIME_DIR, "camoufox-browser");
}
const home = os.homedir();
if (home)
return path.join(home, ".camoufox-browser");
return path.join(os.tmpdir(), "camoufox-browser");
}
export function ensureSocketDir() {
const dir = getSocketDir();
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
}
}
export function getPidFile(session) {
return path.join(getSocketDir(), `${session}.pid`);
}
export function getUnixSocketPath(session) {
return path.join(getSocketDir(), `${session}.sock`);
}
export function getPortFile(session) {
return path.join(getSocketDir(), `${session}.port`);
}
export function cleanupIpcFiles(session) {
const pidFile = getPidFile(session);
const portFile = getPortFile(session);
const sockPath = getUnixSocketPath(session);
try {
if (fs.existsSync(pidFile))
fs.unlinkSync(pidFile);
}
catch { }
try {
if (fs.existsSync(portFile))
fs.unlinkSync(portFile);
}
catch { }
try {
if (fs.existsSync(sockPath))
fs.unlinkSync(sockPath);
}
catch { }
}
/**
* Get port number for TCP mode (Windows).
* Uses a hash of the session name to get a consistent port.
*/
export function getPortForSession(session) {
let hash = 0;
for (let i = 0; i < session.length; i++) {
hash = (hash << 5) - hash + session.charCodeAt(i);
hash |= 0;
}
return 49152 + (Math.abs(hash) % 16383);
}