179 lines
7.5 KiB
JavaScript
179 lines
7.5 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: "plugin/install" } } },
|
|
{ properties: { method: { const: "plugin/uninstall" } } },
|
|
{ properties: { method: { const: "plugin/read" } } },
|
|
{ properties: { method: { const: "plugin/skill/read" } } },
|
|
{ properties: { method: { const: "plugin/share/save" } } },
|
|
{ properties: { method: { const: "plugin/share/checkout" } } },
|
|
{ properties: { method: { const: "plugin/share/delete" } } },
|
|
{ properties: { method: { const: "plugin/share/updateTargets" } } },
|
|
{ properties: { method: { const: "plugin/share/list" } } },
|
|
{ properties: { method: { const: "account/login/start" } } },
|
|
{ properties: { method: { const: "account/login/cancel" } } },
|
|
{ properties: { method: { const: "account/login/completed" } } },
|
|
{ properties: { method: { const: "account/logout" } } },
|
|
{ properties: { method: { const: "account/chatgptAuthTokens/refresh" } } },
|
|
{ properties: { method: { const: "account/sendAddCreditsNudgeEmail" } } },
|
|
{ properties: { method: { const: "config/value/write" } } },
|
|
{ properties: { method: { const: "config/batchWrite" } } },
|
|
{ properties: { method: { const: "config/mcpServer/reload" } } },
|
|
{ properties: { method: { const: "skills/config/write" } } },
|
|
{ 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.equal(manifest.supports.pluginInstall, true);
|
|
assert.equal(manifest.supports.pluginUninstall, true);
|
|
assert.equal(manifest.supports.pluginRead, true);
|
|
assert.equal(manifest.supports.pluginSkillRead, true);
|
|
assert.equal(manifest.supports.pluginShare, true);
|
|
assert.equal(manifest.supports.accountLogin, true);
|
|
assert.equal(manifest.supports.accountLogout, true);
|
|
assert.equal(manifest.supports.accountTokenRefresh, true);
|
|
assert.equal(manifest.supports.accountAddCreditsNudge, true);
|
|
assert.equal(manifest.supports.configValueWrite, true);
|
|
assert.equal(manifest.supports.configBatchWrite, true);
|
|
assert.equal(manifest.supports.configMcpServerReload, true);
|
|
assert.equal(manifest.supports.skillsConfigWrite, true);
|
|
assert.deepEqual(manifest.methods, [
|
|
"account/chatgptAuthTokens/refresh",
|
|
"account/login/cancel",
|
|
"account/login/completed",
|
|
"account/login/start",
|
|
"account/logout",
|
|
"account/sendAddCreditsNudgeEmail",
|
|
"config/batchWrite",
|
|
"config/mcpServer/reload",
|
|
"config/value/write",
|
|
"hooks/list",
|
|
"plugin/install",
|
|
"plugin/read",
|
|
"plugin/share/checkout",
|
|
"plugin/share/delete",
|
|
"plugin/share/list",
|
|
"plugin/share/save",
|
|
"plugin/share/updateTargets",
|
|
"plugin/skill/read",
|
|
"plugin/uninstall",
|
|
"skills/config/write",
|
|
"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 });
|
|
}
|
|
});
|