feat: ship enterprise control and desktop governance
This commit is contained in:
183
scripts/codex-desktop-refresh-bridge-daemon.mjs
Normal file
183
scripts/codex-desktop-refresh-bridge-daemon.mjs
Normal file
@@ -0,0 +1,183 @@
|
||||
#!/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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user