Files
grok-glance/bin/glance-up.mjs
T
2026-08-09 04:00:13 +00:00

69 lines
1.7 KiB
JavaScript
Executable File

#!/usr/bin/env node
/**
* SessionStart hook: make sure the glance daemon is running, then record the event.
*
* This is the only hook that spawns anything. It always exits 0 — a monitoring
* dashboard must never be the reason a Grok Build session fails to start.
*/
import fs from "node:fs";
import path from "node:path";
import { spawn } from "node:child_process";
import {
PLUGIN_ROOT,
baseUrl,
envEnvelope,
glanceHome,
isDaemonUp,
postJson,
readConfig,
readStdinJson,
sleep,
} from "./glance-lib.mjs";
const SERVER_ENTRY = path.join(PLUGIN_ROOT, "dist", "server", "index.js");
async function ensureDaemon(cfg) {
if (await isDaemonUp(cfg)) return true;
if (!fs.existsSync(SERVER_ENTRY)) {
// Not built yet. Say so once, on stderr, where it is recorded but harmless.
process.stderr.write(
`[grok-glance] not built yet - run \`npm install && npm run build\` in ${PLUGIN_ROOT}\n`,
);
return false;
}
const home = glanceHome();
fs.mkdirSync(home, { recursive: true });
const logFd = fs.openSync(path.join(home, "daemon.log"), "a");
const child = spawn(process.execPath, [SERVER_ENTRY], {
detached: true,
stdio: ["ignore", logFd, logFd],
env: { ...process.env, GLANCE_STARTED_BY: "hook" },
});
child.unref();
// Give it a moment to bind before the first http hook fires.
for (let i = 0; i < 40; i++) {
await sleep(200);
if (await isDaemonUp(cfg, 300)) return true;
}
return false;
}
const payload = envEnvelope(await readStdinJson());
const cfg = readConfig();
try {
const up = await ensureDaemon(cfg);
if (up) {
await postJson(`${baseUrl(cfg)}/hook/record`, payload, 2500);
}
} catch {
// Fail open, always.
}
process.exit(0);