108 lines
3.7 KiB
JavaScript
108 lines
3.7 KiB
JavaScript
#!/usr/bin/env node
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
|
|
const codexHome = process.env.CODEX_HOME ?? path.join(os.homedir(), ".codex");
|
|
const controlRoot = process.env.GH_CODEX_CONTROL_ROOT ?? path.join(
|
|
codexHome,
|
|
"runtime",
|
|
"guanghu-codex-host-bridge",
|
|
"state",
|
|
"control",
|
|
);
|
|
const controllerPath = path.join(controlRoot, "current-controller.json");
|
|
const leasePath = path.join(controlRoot, "write-lease.json");
|
|
const categories = new Set(["remote_git", "external_publish", "destructive_cleanup"]);
|
|
|
|
function atomicWrite(file, value) {
|
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
const temporary = `${file}.${process.pid}.tmp`;
|
|
fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, {
|
|
encoding: "utf8",
|
|
mode: 0o600,
|
|
});
|
|
fs.renameSync(temporary, file);
|
|
}
|
|
|
|
function readJson(file) {
|
|
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
}
|
|
|
|
function parseArgs(argv) {
|
|
const [action = "status", ...rest] = argv;
|
|
const values = {};
|
|
for (let index = 0; index < rest.length; index += 2) {
|
|
if (!rest[index]?.startsWith("--") || rest[index + 1] === undefined) {
|
|
throw new Error("INVALID_ARGUMENTS");
|
|
}
|
|
values[rest[index].slice(2)] = rest[index + 1];
|
|
}
|
|
return { action, values };
|
|
}
|
|
|
|
function assertEvidence(controller) {
|
|
if (
|
|
controller?.schema !== "guanghu.codex-current-controller/v1" ||
|
|
controller.direct_human_natural_language !== true ||
|
|
!controller.numbered_event_path ||
|
|
!fs.existsSync(controller.numbered_event_path)
|
|
) throw new Error("CURRENT_CONTROLLER_EVIDENCE_INVALID");
|
|
const event = readJson(controller.numbered_event_path);
|
|
if (
|
|
event.raw_text_sha256 !== controller.raw_text_sha256 ||
|
|
event.source_kind !== "DIRECT_HUMAN_NATURAL_LANGUAGE"
|
|
) throw new Error("CURRENT_CONTROLLER_SOURCE_MISMATCH");
|
|
}
|
|
|
|
const { action, values } = parseArgs(process.argv.slice(2));
|
|
if (action === "status") {
|
|
process.stdout.write(`${JSON.stringify({
|
|
controller: fs.existsSync(controllerPath) ? readJson(controllerPath) : null,
|
|
lease: fs.existsSync(leasePath) ? readJson(leasePath) : null,
|
|
}, null, 2)}\n`);
|
|
process.exit(0);
|
|
}
|
|
if (action === "revoke") {
|
|
try {
|
|
fs.unlinkSync(leasePath);
|
|
} catch (error) {
|
|
if (error?.code !== "ENOENT") throw error;
|
|
}
|
|
process.stdout.write(`${JSON.stringify({ decision: "REVOKED" })}\n`);
|
|
process.exit(0);
|
|
}
|
|
if (action !== "issue") throw new Error("UNKNOWN_ACTION");
|
|
|
|
const controller = readJson(controllerPath);
|
|
assertEvidence(controller);
|
|
if (
|
|
values["session-id"] !== controller.session_id ||
|
|
values["turn-id"] !== controller.turn_id
|
|
) throw new Error("LEASE_REQUEST_IS_NOT_CURRENT_CONTROLLER_TURN");
|
|
if (!categories.has(values.category)) throw new Error("LEASE_CATEGORY_INVALID");
|
|
if (!values.reason || !values.target) throw new Error("LEASE_REASON_OR_TARGET_MISSING");
|
|
const ttlSeconds = Number(values["ttl-seconds"] ?? 600);
|
|
if (!Number.isInteger(ttlSeconds) || ttlSeconds < 30 || ttlSeconds > 900) {
|
|
throw new Error("LEASE_TTL_INVALID");
|
|
}
|
|
const issuedAt = Date.now();
|
|
const lease = {
|
|
schema: "guanghu.codex-one-shot-write-lease/v1",
|
|
lease_id: crypto.randomUUID(),
|
|
control_epoch: controller.control_epoch,
|
|
session_id: controller.session_id,
|
|
turn_id: controller.turn_id,
|
|
category: values.category,
|
|
cwd: path.resolve(values.cwd ?? process.cwd()),
|
|
target: values.target,
|
|
reason: values.reason,
|
|
evidence_event_number: controller.numbered_event_number,
|
|
evidence_raw_text_sha256: controller.raw_text_sha256,
|
|
issued_at: new Date(issuedAt).toISOString(),
|
|
expires_at_unix_ms: issuedAt + ttlSeconds * 1000,
|
|
one_shot: true,
|
|
};
|
|
atomicWrite(leasePath, lease);
|
|
process.stdout.write(`${JSON.stringify({ decision: "ISSUED", lease }, null, 2)}\n`);
|