Files
boss/scripts/codex-desktop-refresh-bridge-daemon.mjs

184 lines
5.0 KiB
JavaScript

#!/usr/bin/env node
import { createServer } from "node:http";
import { executeCodexDesktopRefreshHint } from "./codex-desktop-refresh-hint.mjs";
import { detectCodexDesktopIntegration } from "./codex-desktop-integration-probe.mjs";
const subscribers = new Set();
const recentEvents = [];
let nextEventId = 1;
function parsePort(value) {
const parsed = Number.parseInt(String(value ?? ""), 10);
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 4318;
}
function readRequestBody(request) {
return new Promise((resolve, reject) => {
let raw = "";
request.setEncoding("utf8");
request.on("data", (chunk) => {
raw += chunk;
if (raw.length > 64 * 1024) {
reject(new Error("CODEX_DESKTOP_REFRESH_HINT_TOO_LARGE"));
request.destroy();
}
});
request.on("end", () => {
resolve(raw);
});
request.on("error", reject);
});
}
function writeJson(response, statusCode, payload) {
response.writeHead(statusCode, {
"Content-Type": "application/json",
"Cache-Control": "no-store",
});
response.end(`${JSON.stringify(payload)}\n`);
}
function writeSse(response, event) {
if (event.id !== undefined) {
response.write(`id: ${event.id}\n`);
}
response.write(`event: ${event.event}\n`);
response.write(`data: ${JSON.stringify(event.data)}\n\n`);
}
function buildSafeRefreshEvent(payload, result) {
return {
eventId: nextEventId++,
eventType: "codex_desktop_refresh",
receivedAt: new Date().toISOString(),
targetThreadRef: String(payload?.targetThreadRef || "").trim() || undefined,
sourceMessageId: String(payload?.sourceMessageId || "").trim() || undefined,
appName: String(result?.appName || payload?.appName || "Codex").trim() || "Codex",
refreshMode: String(payload?.refreshMode || "deeplink-reload").trim() || "deeplink-reload",
status: result?.status,
deepLink: result?.deepLink,
detail: result?.detail || result?.error,
};
}
function publishRefreshEvent(eventData) {
recentEvents.push(eventData);
while (recentEvents.length > 50) {
recentEvents.shift();
}
for (const subscriber of subscribers) {
writeSse(subscriber, {
id: eventData.eventId,
event: "codex_desktop_refresh",
data: eventData,
});
}
}
function handleEvents(request, response) {
if (request.method !== "GET") {
writeJson(response, 405, { status: "failed", error: "METHOD_NOT_ALLOWED" });
return;
}
response.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-store",
Connection: "keep-alive",
"X-Accel-Buffering": "no",
});
subscribers.add(response);
writeSse(response, {
event: "ready",
data: {
ok: true,
service: "boss-codex-desktop-refresh-bridge",
},
});
const keepAlive = setInterval(() => {
response.write(": keepalive\n\n");
}, 15000);
request.on("close", () => {
clearInterval(keepAlive);
subscribers.delete(response);
});
}
async function handleRefresh(request, response) {
if (request.method !== "POST") {
writeJson(response, 405, { status: "failed", error: "METHOD_NOT_ALLOWED" });
return;
}
try {
const raw = await readRequestBody(request);
const payload = JSON.parse(raw || "{}");
const result = await executeCodexDesktopRefreshHint(payload);
publishRefreshEvent(buildSafeRefreshEvent(payload, result));
writeJson(response, result.status === "failed" ? 422 : 200, result);
} catch (error) {
writeJson(response, 400, {
status: "failed",
error: error instanceof Error ? error.message : String(error),
});
}
}
const host = process.env.BOSS_CODEX_DESKTOP_BRIDGE_HOST || "127.0.0.1";
const port = parsePort(process.env.BOSS_CODEX_DESKTOP_BRIDGE_PORT);
const server = createServer(async (request, response) => {
if (request.url === "/health") {
writeJson(response, 200, {
ok: true,
service: "boss-codex-desktop-refresh-bridge",
});
return;
}
if (request.url === "/api/v1/codex-desktop/events") {
handleEvents(request, response);
return;
}
if (request.url === "/api/v1/codex-desktop/events/recent") {
writeJson(response, 200, {
ok: true,
events: recentEvents,
});
return;
}
if (request.url === "/api/v1/codex-desktop/capabilities") {
try {
writeJson(response, 200, await detectCodexDesktopIntegration());
} catch (error) {
writeJson(response, 500, {
ok: false,
error: error instanceof Error ? error.message : String(error),
});
}
return;
}
if (request.url === "/api/v1/codex-desktop/refresh") {
await handleRefresh(request, response);
return;
}
writeJson(response, 404, { status: "failed", error: "NOT_FOUND" });
});
server.listen(port, host, () => {
const address = server.address();
process.stdout.write(
`${JSON.stringify({
status: "ready",
service: "boss-codex-desktop-refresh-bridge",
host: address.address,
port: address.port,
})}\n`,
);
});
process.on("SIGTERM", () => {
server.close(() => {
process.exit(0);
});
});