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 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: "skills/extraRoots/set" } } }, { properties: { method: { const: "hooks/list" } } }, { 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.deepEqual(manifest.methods, [ "hooks/list", "skills/extraRoots/set", "thread/inject_items", "thread/start", "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 }); } });