Skip to content

Commit 10b2cac

Browse files
authored
Add codex app-server e2e verification script (#29)
Add test/verify-codex.ts to drive the real `codex app-server` binary end to end through CodexAppServerAdapter, verifying the JSON-RPC handshake, turn streaming, and event mapping. Wire it up as the `pnpm e2e:verify-codex` script.
1 parent a196b84 commit 10b2cac

2 files changed

Lines changed: 81 additions & 0 deletions

File tree

server/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"test": "node --import tsx --test \"src/**/*.test.ts\" \"test/**/*.test.ts\"",
2323
"test:watch": "node --import tsx --test --watch \"src/**/*.test.ts\" \"test/**/*.test.ts\"",
2424
"e2e:verify-pi": "tsx test/fake-model/verify-pi.ts",
25+
"e2e:verify-codex": "tsx test/verify-codex.ts",
2526
"secure:install": "pnpm install --frozen-lockfile",
2627
"secure:audit": "pnpm audit --prod"
2728
},

server/test/verify-codex.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* Manual verification (not a unit test): drive the REAL `codex app-server`
3+
* binary end to end through makit's `CodexAppServerAdapter`. Confirms the
4+
* JSON-RPC handshake (initialize → initialized → thread/start), turn streaming,
5+
* and event mapping all line up against the installed codex CLI.
6+
*
7+
* Requires codex to be on PATH (or MAKIT_CODEX_BIN) and authenticated. Costs a
8+
* real (tiny) model call. Run: pnpm exec tsx test/verify-codex.ts
9+
*/
10+
import { CodexAppServerAdapter } from "../src/adapters/codex.js";
11+
import type { AdapterEvent } from "../src/adapters/adapter.js";
12+
13+
const PROMPT = "Reply with exactly this and nothing else: makit e2e ok";
14+
const EXPECT = "makit e2e ok";
15+
const TIMEOUT_MS = 60_000;
16+
17+
async function main(): Promise<void> {
18+
const command = process.env.MAKIT_CODEX_BIN || "codex";
19+
const model = process.env.MAKIT_CODEX_MODEL; // undefined → codex default
20+
const adapter = new CodexAppServerAdapter({ command, ...(model ? { model } : {}) });
21+
22+
let streamed = "";
23+
let finalText = "";
24+
let sawError = "";
25+
26+
adapter.on("event", (e: AdapterEvent) => {
27+
switch (e.kind) {
28+
case "agent.message.delta":
29+
streamed += String((e.payload as { chunk?: string }).chunk ?? "");
30+
break;
31+
case "agent.message":
32+
finalText = String((e.payload as { text?: string }).text ?? "");
33+
break;
34+
case "session.error":
35+
sawError = String((e.payload as { message?: string }).message ?? "error");
36+
break;
37+
default:
38+
break;
39+
}
40+
if (process.env.VERIFY_DUMP) console.log("EV:", e.kind, JSON.stringify(e.payload).slice(0, 200));
41+
});
42+
43+
const done = new Promise<void>((resolve) => {
44+
adapter.on("status", (s) => {
45+
// The turn is over when the adapter returns to idle after running.
46+
if (s === "idle" && (streamed || finalText || sawError)) resolve();
47+
});
48+
});
49+
50+
const deadline = new Promise<never>((_, reject) =>
51+
setTimeout(() => reject(new Error(`TIMEOUT — no completed turn within ${TIMEOUT_MS / 1000}s`)), TIMEOUT_MS),
52+
);
53+
54+
console.log(`[verify] launching ${command} app-server${model ? ` (model ${model})` : ""}`);
55+
await adapter.start({ cwd: process.cwd(), sessionId: "verify-codex" });
56+
console.log("[verify] thread started; sending prompt");
57+
await adapter.send({ text: PROMPT });
58+
59+
try {
60+
await Promise.race([done, deadline]);
61+
} finally {
62+
await adapter.kill().catch(() => {});
63+
}
64+
65+
const got = (finalText || streamed).toLowerCase();
66+
console.log("[verify] streamed:", JSON.stringify(streamed));
67+
console.log("[verify] final: ", JSON.stringify(finalText));
68+
if (sawError) {
69+
console.error("[verify] FAIL ✗ session.error:", sawError);
70+
process.exit(1);
71+
}
72+
const ok = got.includes(EXPECT);
73+
console.log(ok ? "[verify] PASS ✓" : `[verify] FAIL ✗ (expected to contain '${EXPECT}')`);
74+
process.exit(ok ? 0 : 1);
75+
}
76+
77+
main().catch((err) => {
78+
console.error("[verify] FAIL ✗", err?.message ?? err);
79+
process.exit(1);
80+
});

0 commit comments

Comments
 (0)