Files
boss/tests/codex-app-server-protocol-snapshot-script.test.mjs
2026-06-03 11:14:12 +08:00

128 lines
4.9 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { spawnSync } from "node:child_process";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
test("codex app-server protocol snapshot script records schema, help and method inventory", async () => {
const runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-codex-protocol-snapshot-"));
const fakeBin = path.join(runtimeRoot, "codex");
const outDir = path.join(runtimeRoot, "snapshot");
await writeFile(
fakeBin,
`#!/usr/bin/env node
const fs = require("node:fs");
const path = require("node:path");
const args = process.argv.slice(2);
function writeGenerated(out, name, content) {
fs.mkdirSync(out, { recursive: true });
fs.writeFileSync(path.join(out, name), content);
}
if (args.includes("--version")) {
console.log("codex-cli 0.135.0-alpha.1");
process.exit(0);
}
if (args[0] === "app-server" && args.includes("--help")) {
console.log("Usage: codex app-server [OPTIONS]");
console.log("--listen <URL> stdio:// unix:// ws://IP:PORT off");
process.exit(0);
}
if (args[0] === "app-server" && args[1] === "generate-json-schema") {
const out = args[args.indexOf("--out") + 1];
writeGenerated(out, "codex_app_server_protocol.schemas.json", JSON.stringify({
anyOf: [
{ properties: { method: { const: "thread/start" } } },
{ properties: { method: { const: "thread/inject_items" } } },
{ properties: { method: { const: "thread/archive" } } },
{ properties: { method: { const: "thread/unarchive" } } },
{ properties: { method: { const: "thread/fork" } } },
{ properties: { method: { const: "thread/compact/start" } } },
{ properties: { method: { const: "thread/rollback" } } },
{ properties: { method: { const: "thread/name/set" } } },
{ properties: { method: { const: "thread/metadata/update" } } },
{ properties: { method: { const: "thread/shellCommand" } } },
{ properties: { method: { const: "thread/unsubscribe" } } },
{ properties: { method: { const: "skills/extraRoots/set" } } },
{ properties: { method: { const: "hooks/list" } } },
{ properties: { method: { const: "turn/interrupt" } } },
{ properties: { method: { const: "turn/start" } } }
]
}, null, 2));
process.exit(0);
}
if (args[0] === "app-server" && args[1] === "generate-ts") {
const out = args[args.indexOf("--out") + 1];
writeGenerated(out, "ClientRequest.ts", 'export type ClientRequest = { "method": "thread/start" } | { "method": "skills/extraRoots/set" } | { "method": "hooks/list" } | { "method": "turn/start" };\\n');
process.exit(0);
}
console.error("unexpected args " + args.join(" "));
process.exit(2);
`,
"utf8",
);
await chmod(fakeBin, 0o755);
try {
const result = spawnSync(
process.execPath,
[
"scripts/codex-app-server-protocol-snapshot.mjs",
"--codex-bin",
fakeBin,
"--out-dir",
outDir,
],
{
cwd: repoRoot,
encoding: "utf8",
},
);
assert.equal(result.status, 0, result.stderr);
const manifest = JSON.parse(await readFile(path.join(outDir, "0.135.0-alpha.1", "manifest.json"), "utf8"));
assert.equal(manifest.codexVersion, "0.135.0-alpha.1");
assert.equal(manifest.supports.wsTransport, true);
assert.equal(manifest.supports.unixTransport, true);
assert.equal(manifest.supports.threadInjectItems, true);
assert.equal(manifest.supports.skillsExtraRoots, true);
assert.equal(manifest.supports.hooksList, true);
assert.equal(manifest.supports.threadArchive, true);
assert.equal(manifest.supports.threadUnarchive, true);
assert.equal(manifest.supports.threadFork, true);
assert.equal(manifest.supports.threadCompactStart, true);
assert.equal(manifest.supports.threadRollback, true);
assert.equal(manifest.supports.threadNameSet, true);
assert.equal(manifest.supports.threadMetadataUpdate, true);
assert.equal(manifest.supports.threadShellCommand, true);
assert.equal(manifest.supports.threadUnsubscribe, true);
assert.equal(manifest.supports.turnInterrupt, true);
assert.deepEqual(manifest.methods, [
"hooks/list",
"skills/extraRoots/set",
"thread/archive",
"thread/compact/start",
"thread/fork",
"thread/inject_items",
"thread/metadata/update",
"thread/name/set",
"thread/rollback",
"thread/shellCommand",
"thread/start",
"thread/unarchive",
"thread/unsubscribe",
"turn/interrupt",
"turn/start",
]);
assert.match(
await readFile(path.join(outDir, "0.135.0-alpha.1", "app-server-help.txt"), "utf8"),
/ws:\/\/IP:PORT/,
);
} finally {
await rm(runtimeRoot, { recursive: true, force: true });
}
});