@essentialai/cogent-bridge
Version:
Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.
94 lines (82 loc) • 3.91 kB
JavaScript
/**
* All-in-one installer for `npm install -g @essentialai/cogent-bridge`.
*
* Goal (operator spec): the INSTALLER installs EVERYTHING, so the user's only step
* is running `cogent-codex`. This runs on a GLOBAL install and provisions:
* 1. codex's managed build (the app-server daemon needs it — additive, lives
* at ~/.codex/packages/standalone, coexists with any
* existing Homebrew/npm codex);
* 2. the `cogent@cogent` codex plugin (the cogent tools inside codex);
* (the `cogent-codex` command itself is the package's own bin → already on PATH after
* the global install; the daemon starts at run time.)
*
* HARD RULES:
* - Runs ONLY on a global install (`npm install -g`) and never on a dependency/npx
* install — guarded by npm_config_global. Skips CI and Windows (unix-socket rail).
* - NEVER throws / never non-zero: a setup hiccup must not fail `npm install`. Every
* step is best-effort with a clear log line; the run-time `cogent-codex` wrapper is
* the safety net for anything that didn't complete here.
*/
import { spawnSync } from "node:child_process";
import { existsSync } from "node:fs";
import os from "node:os";
import path from "node:path";
const log = (m) => process.stdout.write(`[cogent-install] ${m}\n`);
function shouldRun() {
if (process.env.COGENT_SKIP_SETUP === "1") return false;
if (process.env.COGENT_FORCE_SETUP === "1") return true; // for testing
if (process.env.CI) return false;
if (process.platform === "win32") return false; // app-server rail is unix-socket only
// npm sets npm_config_global="true" during `npm install -g`. Only then.
return String(process.env.npm_config_global).toLowerCase() === "true";
}
/** Run a command, inheriting the terminal; return true on exit 0. Never throws. */
function run(cmd, args, opts = {}) {
try {
const res = spawnSync(cmd, args, { stdio: "inherit", timeout: 300000, ...opts });
return res.status === 0;
} catch {
return false;
}
}
/** True if the command exists (via `command -v`, best-effort). */
function has(cmd) {
try {
return spawnSync("sh", ["-c", `command -v ${cmd}`], { stdio: "ignore" }).status === 0;
} catch {
return false;
}
}
function managedCodexPresent() {
return existsSync(path.join(os.homedir(), ".codex", "packages", "standalone", "current", "codex"));
}
function main() {
if (!shouldRun()) return; // dependency/npx/CI/Windows → silently do nothing
log("setting up Cogent for Codex — installing all components (one-time)…");
// 1) codex's managed build (needed for real-time wake's app-server daemon).
if (managedCodexPresent()) {
log("✓ codex managed build already present");
} else {
log("installing codex's managed build…");
const ok = run("sh", ["-c", "curl -fsSL https://chatgpt.com/codex/install.sh | sh"]);
log(ok && managedCodexPresent() ? "✓ codex managed build installed" : "… managed build not completed (cogent-codex will offer it on first run)");
}
// 2) the cogent@cogent codex plugin (the cogent tools inside codex). Idempotent.
if (has("codex")) {
log("installing the cogent@cogent codex plugin…");
run("codex", ["plugin", "marketplace", "add", "https://github.com/eaisdevelopment/cogent.git"]);
const ok = run("codex", ["plugin", "add", "cogent@cogent"]);
log(ok ? "✓ cogent@cogent plugin installed" : "… plugin add not completed (re-run `codex plugin add cogent@cogent` if needed)");
} else {
log("… `codex` not on PATH yet — open a new terminal, then run `cogent-codex` (it finishes setup).");
}
log("done. Start codex with: cogent-codex");
}
try {
main();
} catch (e) {
// Absolutely never fail the npm install.
log(`setup skipped (${e?.message ?? e}); run \`cogent-codex\` to finish.`);
}
process.exit(0);