feat: add host commander skeleton
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { commanderContract } from "../src/components/microservices/host-codex-commander/src/contract";
|
||||
import { createCommanderRequestHandler, type RuntimeConfig } from "../src/components/microservices/host-codex-commander/src/index";
|
||||
import {
|
||||
buildCommanderApprovalDraft,
|
||||
commanderApprovalPreview,
|
||||
commanderHealth,
|
||||
commanderSessionPreview,
|
||||
commanderStatePaths,
|
||||
listCommanderSessions,
|
||||
readCommanderApproval,
|
||||
readCommanderSession,
|
||||
summarizeCommanderTrace,
|
||||
writeCommanderApproval,
|
||||
writeCommanderSession,
|
||||
} from "../src/components/microservices/host-codex-commander/src/state";
|
||||
|
||||
type JsonRecord = Record<string, unknown>;
|
||||
|
||||
function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
|
||||
if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
|
||||
}
|
||||
|
||||
function asRecord(value: unknown, label: string): JsonRecord {
|
||||
assertCondition(typeof value === "object" && value !== null && !Array.isArray(value), `${label} must be an object`, value);
|
||||
return value as JsonRecord;
|
||||
}
|
||||
|
||||
function dataOf(response: JsonRecord): JsonRecord {
|
||||
return asRecord(response.body, "body");
|
||||
}
|
||||
|
||||
async function readJson(response: Response): Promise<JsonRecord> {
|
||||
const body = await response.json();
|
||||
return asRecord(body, "response body");
|
||||
}
|
||||
|
||||
const tmp = mkdtempSync(join(tmpdir(), "host-codex-commander-"));
|
||||
const runtime: RuntimeConfig = {
|
||||
rootDir: tmp,
|
||||
host: "127.0.0.1",
|
||||
port: 4261,
|
||||
logFile: join(tmp, "logs", "commander.jsonl"),
|
||||
serviceId: "host-codex-commander",
|
||||
stateRoot: tmp,
|
||||
sessionId: "primary",
|
||||
};
|
||||
const handler = createCommanderRequestHandler(runtime);
|
||||
|
||||
try {
|
||||
const contract = commanderContract();
|
||||
assertCondition(contract.ok === true, "contract must be ok", contract);
|
||||
assertCondition(contract.serviceId === "host-codex-commander", "contract must expose service id", contract);
|
||||
assertCondition(contract.daemonImplemented === false, "contract must remain skeleton only", contract);
|
||||
assertCondition(contract.currentImplementation === "host-codex-commander-skeleton", "contract must identify skeleton implementation", contract);
|
||||
|
||||
const session = writeCommanderSession(runtime, {
|
||||
sessionId: "primary",
|
||||
state: "running",
|
||||
promptState: "planned",
|
||||
approvalState: "draft",
|
||||
pid: 321,
|
||||
cwd: "/workspace/unidesk",
|
||||
lastSeq: 7,
|
||||
heartbeatAt: "2026-05-21T00:00:00.000Z",
|
||||
updatedAt: "2026-05-21T00:00:00.000Z",
|
||||
notes: ["token=ghp_abcdef1234567890", "trace-summary:running"],
|
||||
});
|
||||
assertCondition(session.notes[0] === "<redacted>", "session notes must be redacted", session);
|
||||
assertCondition(readCommanderSession(runtime, "primary").state === "running", "session read must round-trip", readCommanderSession(runtime, "primary"));
|
||||
assertCondition(listCommanderSessions(runtime).length >= 1, "session listing must include stored session", listCommanderSessions(runtime));
|
||||
assertCondition(commanderSessionPreview(session).notes.includes("<redacted>"), "session preview must redact notes", commanderSessionPreview(session));
|
||||
|
||||
const trace = summarizeCommanderTrace({
|
||||
taskId: "task-123",
|
||||
sessionId: "primary",
|
||||
traceJsonl: [
|
||||
JSON.stringify({ seq: 1, kind: "message", status: "running", summary: "prompt token=ghp_1234567890abcdef" }),
|
||||
JSON.stringify({ seq: 4, kind: "command", status: "attention_required", command: "ask-for-approval", output: "reason=https://user:secret@example.com" }),
|
||||
JSON.stringify({ seq: 8, kind: "event", status: "completed", text: "done" }),
|
||||
].join("\n"),
|
||||
taskSummary: "task summary token=ghp_aaaaaaaaaaaaaaaa",
|
||||
});
|
||||
assertCondition(trace.taskId === "task-123", "trace summary must preserve task id", trace);
|
||||
assertCondition(trace.lastSeq === 8, "trace summary must preserve last seq", trace);
|
||||
assertCondition(trace.status === "terminal", "trace summary should reach terminal status", trace);
|
||||
assertCondition(trace.redactionsApplied >= 2, "trace summary must redact secrets", trace);
|
||||
assertCondition(trace.taskSummaryPreview?.includes("<redacted>") === true, "task summary preview must redact", trace);
|
||||
assertCondition(trace.keyEvents.length > 0, "trace summary must include key events", trace);
|
||||
|
||||
const approval = buildCommanderApprovalDraft({
|
||||
approvalId: "draft-1",
|
||||
action: "code-queue-task-interrupt",
|
||||
taskId: "task-123",
|
||||
reason: "token=ghp_1234567890abcdef https://user:secret@example.com",
|
||||
sessionId: "primary",
|
||||
});
|
||||
assertCondition(approval.reason.includes("<redacted>"), "approval reason must redact", approval);
|
||||
assertCondition(approval.previewMarkdown.includes("<redacted>"), "approval preview must redact", approval);
|
||||
assertCondition(approval.previewJson["sendImplemented"] === false, "approval preview must not imply sending", approval.previewJson);
|
||||
writeCommanderApproval(runtime, approval);
|
||||
assertCondition(readCommanderApproval(runtime, "draft-1").reason.includes("<redacted>"), "approval round-trip must preserve redaction", readCommanderApproval(runtime, "draft-1"));
|
||||
|
||||
const health = commanderHealth(runtime, "2026-05-21T00:00:00.000Z");
|
||||
assertCondition(health.ok === true && health.service === "host-codex-commander", "health must expose service metadata", health);
|
||||
assertCondition(health.stateRoot === tmp, "health must point at temp state root", health);
|
||||
|
||||
const healthBody = await readJson(await handler(new Request("http://localhost/health")));
|
||||
assertCondition(healthBody.ok === true, "health route must succeed", healthBody);
|
||||
|
||||
const contractBody = await readJson(await handler(new Request("http://localhost/api/commander/contract")));
|
||||
assertCondition(contractBody.serviceId === "host-codex-commander", "HTTP contract route must expose service id", contractBody);
|
||||
|
||||
const sessionsBody = await readJson(await handler(new Request("http://localhost/api/commander/sessions")));
|
||||
assertCondition(Array.isArray(sessionsBody.sessions) && sessionsBody.sessions.length >= 1, "sessions route must list sessions", sessionsBody);
|
||||
|
||||
const traceBody = await readJson(await handler(new Request(`http://localhost/api/commander/trace-summary?taskId=task-123&traceJsonl=${encodeURIComponent(JSON.stringify({ seq: 1, status: "running", summary: "hello token=ghp_1234567890abcdef" }))}`)));
|
||||
assertCondition(traceBody.ok === true && asRecord(traceBody.summary, "summary").redactionsApplied >= 1, "trace route must redact and summarize", traceBody);
|
||||
|
||||
const approvalBody = await readJson(await handler(new Request("http://localhost/api/commander/approvals", {
|
||||
method: "POST",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({ action: "code-queue-task-cancel", reason: "cookie=session=secret", taskId: "task-123" }),
|
||||
})));
|
||||
assertCondition(approvalBody.ok === true, "approval route must succeed", approvalBody);
|
||||
assertCondition(String(JSON.stringify(approvalBody)).includes("<redacted>"), "approval route must redact sensitive text", approvalBody);
|
||||
|
||||
const statePath = commanderStatePaths(runtime);
|
||||
assertCondition(readFileSync(statePath.stateFile, "utf8").length > 0, "state file must be written", statePath);
|
||||
assertCondition(readFileSync(statePath.approvalFile, "utf8").length > 0, "approval file must be written", statePath);
|
||||
|
||||
process.stdout.write(`${JSON.stringify({
|
||||
ok: true,
|
||||
checks: [
|
||||
"commander contract exposes skeleton contract boundaries",
|
||||
"state files round-trip and redact secrets",
|
||||
"trace summary aggregates mock jsonl input",
|
||||
"approval draft preview stays preview-only and redacted",
|
||||
"HTTP handler serves /health, /api/commander/contract, /api/commander/sessions, /api/commander/trace-summary, and /api/commander/approvals",
|
||||
],
|
||||
}, null, 2)}\n`);
|
||||
} finally {
|
||||
rmSync(tmp, { recursive: true, force: true });
|
||||
}
|
||||
Reference in New Issue
Block a user