@sumeru/adapter-codex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 shazhou
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
16
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1 @@
1
+ 3d31558a2ce75d22c9b27b613d0d15d224876652c74e2b7bfd612eca9c41b451
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Codex adapter — implements the `Adapter` contract from `@sumeru/core`
3
+ * by shelling out to `codex exec <prompt> --json
4
+ * --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check`
5
+ * for create/send and parsing the resulting JSONL stream into `Turn[]`.
6
+ *
7
+ * Codex supports session resume via `codex exec resume <id> <prompt>`.
8
+ * The adapter caches parsed turns in an in-memory `Map<string, Turn[]>`
9
+ * keyed by `nativeId` and is the sole authority on history for the
10
+ * lifetime of the adapter instance.
11
+ *
12
+ * The factory:
13
+ * - createSession spawns `codex exec "ping" --json ...` and parses the
14
+ * JSONL stream for the session id. Accepts `SessionConfig` with
15
+ * `model` and `cwd` fields.
16
+ * - send is an async generator that spawns `codex exec resume <id>
17
+ * <prompt> --json ...`, parses the JSONL output, and yields each
18
+ * delta turn as `{ type: "turn", turn }` followed by
19
+ * `{ type: "done", durationMs, tokens }`. On error yields
20
+ * `{ type: "error", error }` instead of throwing.
21
+ * - close is a logical close — adds the nativeId to a per-instance Set;
22
+ * no Codex-side notification, no cache eviction.
23
+ * - getTurns returns a defensive copy of the in-memory cache.
24
+ */
25
+ import type { Adapter } from "@sumeru/core";
26
+ import type { CodexAdapterOptions } from "./types.js";
27
+ export declare function createCodexAdapter(options?: Partial<CodexAdapterOptions>): Adapter;
28
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EACX,OAAO,EAMP,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EACX,mBAAmB,EAOnB,MAAM,YAAY,CAAC;AAsBpB,wBAAgB,kBAAkB,CACjC,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAM,GACxC,OAAO,CA6ST"}
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Codex adapter — implements the `Adapter` contract from `@sumeru/core`
3
+ * by shelling out to `codex exec <prompt> --json
4
+ * --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check`
5
+ * for create/send and parsing the resulting JSONL stream into `Turn[]`.
6
+ *
7
+ * Codex supports session resume via `codex exec resume <id> <prompt>`.
8
+ * The adapter caches parsed turns in an in-memory `Map<string, Turn[]>`
9
+ * keyed by `nativeId` and is the sole authority on history for the
10
+ * lifetime of the adapter instance.
11
+ *
12
+ * The factory:
13
+ * - createSession spawns `codex exec "ping" --json ...` and parses the
14
+ * JSONL stream for the session id. Accepts `SessionConfig` with
15
+ * `model` and `cwd` fields.
16
+ * - send is an async generator that spawns `codex exec resume <id>
17
+ * <prompt> --json ...`, parses the JSONL output, and yields each
18
+ * delta turn as `{ type: "turn", turn }` followed by
19
+ * `{ type: "done", durationMs, tokens }`. On error yields
20
+ * `{ type: "error", error }` instead of throwing.
21
+ * - close is a logical close — adds the nativeId to a per-instance Set;
22
+ * no Codex-side notification, no cache eviction.
23
+ * - getTurns returns a defensive copy of the in-memory cache.
24
+ */
25
+ import { defaultSpawn, defaultStreamingSpawn } from "./spawn.js";
26
+ import { parseCodexJson, parseCodexJsonIncremental } from "./stream-parser.js";
27
+ const DEFAULT_CODEX_BIN = "codex";
28
+ const DEFAULT_CREATE_TIMEOUT_MS = 5 * 60_000;
29
+ /**
30
+ * Default `send` timeout — 30 minutes.
31
+ *
32
+ * Consistent with adapter-claude-code. Operators may further override via
33
+ * the `gateways.<name>.config.sendTimeoutMs` field in `sumeru.yaml`.
34
+ */
35
+ const DEFAULT_SEND_TIMEOUT_MS = 30 * 60_000;
36
+ const STDERR_TRUNCATE_LIMIT = 500;
37
+ const API_KEY_ERROR_MESSAGE = "codex API key error. Check your OPENAI_API_KEY configuration.";
38
+ const API_KEY_PATTERNS = [
39
+ /invalid api key/i,
40
+ /OPENAI_API_KEY/i,
41
+ /authentication/i,
42
+ /unauthorized/i,
43
+ /api.?key/i,
44
+ ];
45
+ export function createCodexAdapter(options = {}) {
46
+ const codexBin = options.codexBin ?? DEFAULT_CODEX_BIN;
47
+ const defaultModel = options.model ?? null;
48
+ const cwd = options.cwd ?? null;
49
+ const createSessionTimeoutMs = options.createSessionTimeoutMs ?? DEFAULT_CREATE_TIMEOUT_MS;
50
+ const sendTimeoutMs = options.sendTimeoutMs ?? DEFAULT_SEND_TIMEOUT_MS;
51
+ const spawnFn = options.spawnFn ?? defaultSpawn;
52
+ const streamingSpawnFn = options.streamingSpawnFn ?? defaultStreamingSpawn;
53
+ const dangerouslyBypassApprovals = options.dangerouslyBypassApprovals ?? true;
54
+ const skipGitRepoCheck = options.skipGitRepoCheck ?? true;
55
+ const turnsCache = new Map();
56
+ const closedRefs = new Set();
57
+ const sendLocks = new Map();
58
+ function resolveCwd() {
59
+ return cwd ?? process.cwd();
60
+ }
61
+ function buildArgs(prompt, resumeId, model, spawnCwd) {
62
+ const args = ["exec"];
63
+ // Resume mode: `codex exec resume <id> "<prompt>"`
64
+ if (resumeId !== null) {
65
+ args.push("resume", resumeId);
66
+ }
67
+ // Add the prompt
68
+ args.push(prompt);
69
+ // Add --json for JSONL output
70
+ args.push("--json");
71
+ // Add permission bypass flags if enabled
72
+ if (dangerouslyBypassApprovals) {
73
+ args.push("--dangerously-bypass-approvals-and-sandbox");
74
+ }
75
+ if (skipGitRepoCheck) {
76
+ args.push("--skip-git-repo-check");
77
+ }
78
+ // Add working directory
79
+ args.push("-C", spawnCwd);
80
+ // Add model if specified
81
+ if (model !== null) {
82
+ args.push("-m", model);
83
+ }
84
+ return args;
85
+ }
86
+ async function runCodex(prompt, resumeId, model, timeoutMs, spawnCwd) {
87
+ const args = buildArgs(prompt, resumeId, model, spawnCwd);
88
+ const result = await spawnFn({
89
+ command: codexBin,
90
+ args,
91
+ timeoutMs,
92
+ cwd: spawnCwd,
93
+ }).catch((err) => {
94
+ const detail = err instanceof Error ? err.message : String(err);
95
+ throw new Error(`codex adapter failed to spawn '${codexBin}': ${detail}`);
96
+ });
97
+ const parsed = parseCodexJson(result.stdout);
98
+ return { result, parsed };
99
+ }
100
+ async function createSession(config) {
101
+ const model = config.model ?? defaultModel;
102
+ const spawnCwd = config.cwd ?? resolveCwd();
103
+ const { result, parsed } = await runCodex("ping", null, model, createSessionTimeoutMs, spawnCwd);
104
+ if (result.timedOut) {
105
+ throw new Error(`createSession timed out after ${createSessionTimeoutMs}ms`);
106
+ }
107
+ if (parsed === null) {
108
+ throw makeUnparseableOrExitError(result, codexBin);
109
+ }
110
+ // Parsed but no session id — treat as unparseable.
111
+ if (parsed.sessionId === "") {
112
+ throw makeUnparseableOrExitError(result, codexBin);
113
+ }
114
+ // Adapter rewrites indices to be globally monotonic from 0.
115
+ const rewritten = rewriteIndices(parsed.turns, -1);
116
+ turnsCache.set(parsed.sessionId, rewritten);
117
+ const meta = {
118
+ cwd: spawnCwd,
119
+ model: parsed.model !== "" ? parsed.model : model,
120
+ createdAt: new Date().toISOString(),
121
+ subtype: parsed.subtype,
122
+ };
123
+ return { nativeId: parsed.sessionId, meta };
124
+ }
125
+ function send(ref, content) {
126
+ assertRef(ref, "send");
127
+ if (closedRefs.has(ref.nativeId)) {
128
+ throw new Error(`codex session ${ref.nativeId} is closed`);
129
+ }
130
+ if (typeof content !== "string" || content.length === 0) {
131
+ throw new Error("send: content must be a non-empty string");
132
+ }
133
+ const nativeId = ref.nativeId;
134
+ async function* generate() {
135
+ // Acquire the lock — it stays held until this generator finishes.
136
+ const prev = sendLocks.get(nativeId) ?? Promise.resolve();
137
+ let release = () => { };
138
+ const next = new Promise((resolve) => {
139
+ release = resolve;
140
+ });
141
+ const chain = prev.then(() => next);
142
+ sendLocks.set(nativeId, chain);
143
+ try {
144
+ await prev;
145
+ yield* streamSend(nativeId, ref, content);
146
+ }
147
+ finally {
148
+ release();
149
+ if (sendLocks.get(nativeId) === chain) {
150
+ sendLocks.delete(nativeId);
151
+ }
152
+ }
153
+ }
154
+ return generate();
155
+ }
156
+ async function* streamSend(nativeId, ref, content) {
157
+ if (closedRefs.has(nativeId)) {
158
+ yield {
159
+ type: "error",
160
+ error: new Error(`codex session ${nativeId} is closed`),
161
+ };
162
+ return;
163
+ }
164
+ const before = turnsCache.get(nativeId) ?? [];
165
+ const highWater = before.length === 0
166
+ ? -1
167
+ : before.reduce((m, t) => (t.index > m ? t.index : m), -1);
168
+ let nextIndex = highWater + 1;
169
+ const refModel = typeof ref.meta.model === "string" && ref.meta.model.length > 0
170
+ ? ref.meta.model
171
+ : defaultModel;
172
+ const refCwd = typeof ref.meta.cwd === "string" && ref.meta.cwd.length > 0
173
+ ? ref.meta.cwd
174
+ : resolveCwd();
175
+ const args = buildArgs(content, nativeId, refModel, refCwd);
176
+ const startedAt = Date.now();
177
+ let streamResult;
178
+ try {
179
+ streamResult = streamingSpawnFn({
180
+ command: codexBin,
181
+ args,
182
+ timeoutMs: sendTimeoutMs,
183
+ cwd: refCwd,
184
+ });
185
+ }
186
+ catch (err) {
187
+ const detail = err instanceof Error ? err.message : String(err);
188
+ yield {
189
+ type: "error",
190
+ error: new Error(`codex adapter failed to spawn '${codexBin}': ${detail}`),
191
+ };
192
+ return;
193
+ }
194
+ let resultLine = null;
195
+ try {
196
+ for await (const event of parseCodexJsonIncremental(streamResult.lines)) {
197
+ if (event.type === "turn") {
198
+ const turn = event.turn;
199
+ turn.index = nextIndex++;
200
+ const existing = turnsCache.get(nativeId) ?? [];
201
+ turnsCache.set(nativeId, [...existing, turn]);
202
+ yield { type: "turn", turn };
203
+ }
204
+ else if (event.type === "result") {
205
+ resultLine = event.resultLine;
206
+ }
207
+ }
208
+ }
209
+ catch (err) {
210
+ yield {
211
+ type: "error",
212
+ error: err instanceof Error
213
+ ? err
214
+ : new Error(`stream read error: ${String(err)}`),
215
+ };
216
+ return;
217
+ }
218
+ let exitInfo;
219
+ try {
220
+ exitInfo = await streamResult.waitForExit();
221
+ }
222
+ catch (err) {
223
+ yield {
224
+ type: "error",
225
+ error: err instanceof Error
226
+ ? err
227
+ : new Error(`process exit error: ${String(err)}`),
228
+ };
229
+ return;
230
+ }
231
+ if (exitInfo.timedOut) {
232
+ yield {
233
+ type: "error",
234
+ error: new Error(`send timed out after ${sendTimeoutMs}ms`),
235
+ };
236
+ return;
237
+ }
238
+ if (exitInfo.exitCode !== null && exitInfo.exitCode !== 0) {
239
+ const stderrTrimmed = exitInfo.stderr.trim();
240
+ const snippet = stderrTrimmed === ""
241
+ ? ""
242
+ : `: ${tail(stderrTrimmed, STDERR_TRUNCATE_LIMIT)}`;
243
+ yield {
244
+ type: "error",
245
+ error: new Error(`codex exited with code ${String(exitInfo.exitCode)}${snippet}`),
246
+ };
247
+ return;
248
+ }
249
+ const tokens = deriveTokensFromResultLine(resultLine);
250
+ yield {
251
+ type: "done",
252
+ durationMs: Date.now() - startedAt,
253
+ tokens,
254
+ };
255
+ }
256
+ async function close(ref) {
257
+ assertRef(ref, "close");
258
+ closedRefs.add(ref.nativeId);
259
+ }
260
+ async function getTurns(ref) {
261
+ assertRef(ref, "getTurns");
262
+ const cached = turnsCache.get(ref.nativeId);
263
+ if (cached === undefined)
264
+ return [];
265
+ return [...cached];
266
+ }
267
+ return {
268
+ name: "codex",
269
+ createSession,
270
+ send,
271
+ close,
272
+ getTurns,
273
+ };
274
+ }
275
+ function assertRef(ref, op) {
276
+ if (ref === null ||
277
+ ref === undefined ||
278
+ typeof ref !== "object" ||
279
+ typeof ref.nativeId !== "string" ||
280
+ ref.nativeId.length === 0) {
281
+ throw new Error(`${op}: invalid NativeSessionRef`);
282
+ }
283
+ }
284
+ function rewriteIndices(turns, highWater) {
285
+ let nextIndex = highWater + 1;
286
+ return turns.map((turn) => ({
287
+ ...turn,
288
+ index: nextIndex++,
289
+ }));
290
+ }
291
+ function isRecord(value) {
292
+ return typeof value === "object" && value !== null && !Array.isArray(value);
293
+ }
294
+ function safeNumber(v, fallback = 0) {
295
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
296
+ }
297
+ function deriveTokensFromResultLine(resultLine) {
298
+ if (resultLine === null)
299
+ return null;
300
+ const usage = isRecord(resultLine.usage) ? resultLine.usage : resultLine;
301
+ const input = safeNumber(usage.input_tokens ?? usage.inputTokens ?? usage.prompt_tokens);
302
+ const output = safeNumber(usage.output_tokens ?? usage.outputTokens ?? usage.completion_tokens);
303
+ if (input === 0 && output === 0)
304
+ return null;
305
+ return { input, output };
306
+ }
307
+ function makeUnparseableOrExitError(result, codexBin, nativeId = null) {
308
+ const stderr = result.stderr ?? "";
309
+ const stdout = result.stdout ?? "";
310
+ const stderrTrimmed = stderr.trim();
311
+ // API key errors take precedence over generic exit errors.
312
+ for (const pattern of API_KEY_PATTERNS) {
313
+ if (pattern.test(stderrTrimmed)) {
314
+ const codeText = result.exitCode === null ? "null" : String(result.exitCode);
315
+ return new Error(`codex exited with code ${codeText}: ${API_KEY_ERROR_MESSAGE}`);
316
+ }
317
+ }
318
+ // Session-not-found heuristic for resume failures.
319
+ if (nativeId !== null && /not found|no such session/i.test(stderrTrimmed)) {
320
+ return new Error(`codex session ${nativeId} not found: ${tail(stderrTrimmed, STDERR_TRUNCATE_LIMIT)}`);
321
+ }
322
+ if (result.exitCode !== null && result.exitCode !== 0) {
323
+ const codeText = String(result.exitCode);
324
+ const snippet = stderrTrimmed === ""
325
+ ? ""
326
+ : `: ${tail(stderrTrimmed, STDERR_TRUNCATE_LIMIT)}`;
327
+ return new Error(`codex exited with code ${codeText}${snippet}`);
328
+ }
329
+ // Unparseable but exit was 0 (or null) — generic parse error referencing
330
+ // codexBin so callers can debug a misconfigured PATH.
331
+ const head = stdout.slice(0, 500);
332
+ const stderrTail = tail(stderrTrimmed, STDERR_TRUNCATE_LIMIT);
333
+ return new Error(`codex returned unparseable json output (bin=${codexBin}, first 500 chars: ${head}, stderr tail: ${stderrTail})`);
334
+ }
335
+ function tail(s, n) {
336
+ if (s.length <= n)
337
+ return s;
338
+ return s.slice(s.length - n);
339
+ }
340
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Public surface of `@sumeru/adapter-codex`.
3
+ *
4
+ * The factory `createCodexAdapter` returns an `Adapter` (from
5
+ * `@sumeru/core`) that drives the OpenAI Codex CLI via `codex exec --json
6
+ * --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check` mode.
7
+ * See `adapter.ts` for the implementation.
8
+ */
9
+ export { createCodexAdapter } from "./adapter.js";
10
+ export { parseCodexJson, parseCodexJsonIncremental, } from "./stream-parser.js";
11
+ export type { CodexAdapterOptions, CodexParsedResult, CodexResultSubtype, SpawnArgs, SpawnExitInfo, SpawnFn, SpawnResult, SpawnStreamResult, StreamingSpawnFn, StreamParseEvent, } from "./types.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACN,cAAc,EACd,yBAAyB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACX,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,aAAa,EACb,OAAO,EACP,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Public surface of `@sumeru/adapter-codex`.
3
+ *
4
+ * The factory `createCodexAdapter` returns an `Adapter` (from
5
+ * `@sumeru/core`) that drives the OpenAI Codex CLI via `codex exec --json
6
+ * --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check` mode.
7
+ * See `adapter.ts` for the implementation.
8
+ */
9
+ export { createCodexAdapter } from "./adapter.js";
10
+ export { parseCodexJson, parseCodexJsonIncremental, } from "./stream-parser.js";
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EACN,cAAc,EACd,yBAAyB,GACzB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Default `SpawnFn` for the Codex adapter — wraps
3
+ * `node:child_process.spawn` with a timeout.
4
+ *
5
+ * Returns `{stdout, stderr, exitCode, signal, timedOut, durationMs}`. On
6
+ * timeout the child receives `SIGTERM`; if it is still alive after 5 s a
7
+ * `SIGKILL` follows. `timedOut` is set to `true`.
8
+ *
9
+ * Argv is passed as an explicit array — never via shell — so embedded
10
+ * quotes, backslashes, newlines, and emoji round-trip without corruption.
11
+ */
12
+ import type { SpawnFn, StreamingSpawnFn } from "./types.js";
13
+ export declare const defaultSpawn: SpawnFn;
14
+ /**
15
+ * Streaming variant of `defaultSpawn` — returns synchronously with
16
+ * line-by-line stdout access via `lines` (an AsyncIterable<string>).
17
+ */
18
+ export declare const defaultStreamingSpawn: StreamingSpawnFn;
19
+ //# sourceMappingURL=spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.d.ts","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAGX,OAAO,EAGP,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAIpB,eAAO,MAAM,YAAY,EAAE,OAyD1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,gBA4DnC,CAAC"}
package/dist/spawn.js ADDED
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Default `SpawnFn` for the Codex adapter — wraps
3
+ * `node:child_process.spawn` with a timeout.
4
+ *
5
+ * Returns `{stdout, stderr, exitCode, signal, timedOut, durationMs}`. On
6
+ * timeout the child receives `SIGTERM`; if it is still alive after 5 s a
7
+ * `SIGKILL` follows. `timedOut` is set to `true`.
8
+ *
9
+ * Argv is passed as an explicit array — never via shell — so embedded
10
+ * quotes, backslashes, newlines, and emoji round-trip without corruption.
11
+ */
12
+ import { spawn } from "node:child_process";
13
+ import { createInterface } from "node:readline";
14
+ const FORCE_KILL_GRACE_MS = 5_000;
15
+ export const defaultSpawn = async ({ command, args, timeoutMs, cwd, }) => {
16
+ const startedAt = Date.now();
17
+ return new Promise((resolve, reject) => {
18
+ let child;
19
+ try {
20
+ child = spawn(command, args, {
21
+ stdio: ["ignore", "pipe", "pipe"],
22
+ windowsHide: true,
23
+ cwd,
24
+ env: process.env,
25
+ shell: false,
26
+ });
27
+ }
28
+ catch (err) {
29
+ reject(err instanceof Error ? err : new Error(String(err)));
30
+ return;
31
+ }
32
+ let timedOut = false;
33
+ const stdoutChunks = [];
34
+ const stderrChunks = [];
35
+ const timer = setTimeout(() => {
36
+ timedOut = true;
37
+ child.kill("SIGTERM");
38
+ setTimeout(() => {
39
+ if (child.exitCode === null && child.signalCode === null) {
40
+ child.kill("SIGKILL");
41
+ }
42
+ }, FORCE_KILL_GRACE_MS).unref();
43
+ }, timeoutMs);
44
+ timer.unref();
45
+ child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
46
+ child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
47
+ child.once("error", (err) => {
48
+ clearTimeout(timer);
49
+ reject(err);
50
+ });
51
+ child.once("close", (code, signal) => {
52
+ clearTimeout(timer);
53
+ resolve({
54
+ stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
55
+ stderr: Buffer.concat(stderrChunks).toString("utf-8"),
56
+ exitCode: code,
57
+ signal: signal ?? null,
58
+ timedOut,
59
+ durationMs: Date.now() - startedAt,
60
+ });
61
+ });
62
+ });
63
+ };
64
+ /**
65
+ * Streaming variant of `defaultSpawn` — returns synchronously with
66
+ * line-by-line stdout access via `lines` (an AsyncIterable<string>).
67
+ */
68
+ export const defaultStreamingSpawn = ({ command, args, timeoutMs, cwd, }) => {
69
+ const startedAt = Date.now();
70
+ const child = spawn(command, args, {
71
+ stdio: ["ignore", "pipe", "pipe"],
72
+ windowsHide: true,
73
+ cwd,
74
+ env: process.env,
75
+ shell: false,
76
+ });
77
+ let timedOut = false;
78
+ const stderrChunks = [];
79
+ const timer = setTimeout(() => {
80
+ timedOut = true;
81
+ child.kill("SIGTERM");
82
+ setTimeout(() => {
83
+ if (child.exitCode === null && child.signalCode === null) {
84
+ child.kill("SIGKILL");
85
+ }
86
+ }, FORCE_KILL_GRACE_MS).unref();
87
+ }, timeoutMs);
88
+ timer.unref();
89
+ // stdio: ["ignore", "pipe", "pipe"] guarantees child.stdout is non-null
90
+ const stdout = child.stdout;
91
+ if (stdout === null) {
92
+ throw new Error("child.stdout is null despite pipe stdio configuration");
93
+ }
94
+ child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
95
+ const rl = createInterface({ input: stdout, crlfDelay: Infinity });
96
+ const exitPromise = new Promise((resolve, reject) => {
97
+ child.once("error", (err) => {
98
+ clearTimeout(timer);
99
+ reject(err);
100
+ });
101
+ child.once("close", (code, signal) => {
102
+ clearTimeout(timer);
103
+ resolve({
104
+ exitCode: code,
105
+ signal: signal ?? null,
106
+ timedOut,
107
+ durationMs: Date.now() - startedAt,
108
+ stderr: Buffer.concat(stderrChunks).toString("utf-8"),
109
+ });
110
+ });
111
+ });
112
+ return {
113
+ lines: rl,
114
+ waitForExit: () => exitPromise,
115
+ };
116
+ };
117
+ //# sourceMappingURL=spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn.js","sourceRoot":"","sources":["../src/spawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAUhD,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAElC,MAAM,CAAC,MAAM,YAAY,GAAY,KAAK,EAAE,EAC3C,OAAO,EACP,IAAI,EACJ,SAAS,EACT,GAAG,GACQ,EAAwB,EAAE;IACrC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,OAAO,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnD,IAAI,KAA+B,CAAC;QACpC,IAAI,CAAC;YACJ,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;gBAC5B,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;gBACjC,WAAW,EAAE,IAAI;gBACjB,GAAG;gBACH,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,KAAK,EAAE,KAAK;aACZ,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC5D,OAAO;QACR,CAAC;QAED,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,MAAM,YAAY,GAAa,EAAE,CAAC;QAElC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,QAAQ,GAAG,IAAI,CAAC;YAChB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,UAAU,CAAC,GAAG,EAAE;gBACf,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;oBAC1D,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACvB,CAAC;YACF,CAAC,EAAE,mBAAmB,CAAC,CAAC,KAAK,EAAE,CAAC;QACjC,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAEtE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC3B,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,GAAG,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACpC,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC;gBACP,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACrD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACrD,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,MAAM,IAAI,IAAI;gBACtB,QAAQ;gBACR,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;aAClC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAqB,CAAC,EACvD,OAAO,EACP,IAAI,EACJ,SAAS,EACT,GAAG,GACQ,EAAqB,EAAE;IAClC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;QAClC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,WAAW,EAAE,IAAI;QACjB,GAAG;QACH,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,KAAK,EAAE,KAAK;KACZ,CAAC,CAAC;IAEH,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,YAAY,GAAa,EAAE,CAAC;IAElC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;QAC7B,QAAQ,GAAG,IAAI,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACtB,UAAU,CAAC,GAAG,EAAE;YACf,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;gBAC1D,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACvB,CAAC;QACF,CAAC,EAAE,mBAAmB,CAAC,CAAC,KAAK,EAAE,CAAC;IACjC,CAAC,EAAE,SAAS,CAAC,CAAC;IACd,KAAK,CAAC,KAAK,EAAE,CAAC;IAEd,wEAAwE;IACxE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC5B,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC1E,CAAC;IAED,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAEtE,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEnE,MAAM,WAAW,GAAG,IAAI,OAAO,CAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC3B,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,GAAG,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACpC,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC;gBACP,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,MAAM,IAAI,IAAI;gBACtB,QAAQ;gBACR,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;gBAClC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;aACrD,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO;QACN,KAAK,EAAE,EAAE;QACT,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW;KAC9B,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * JSONL parser for Codex CLI's `codex exec --json` output.
3
+ *
4
+ * Codex emits JSONL to stdout. Each line is a JSON object with a `type` field.
5
+ * Based on Codex CLI documentation and expected behavior:
6
+ *
7
+ * - `"session.start"` — first line; carries `session_id` and initial config.
8
+ * - `"message"` — user or assistant messages with content.
9
+ * - `"function_call"` / `"tool_call"` — tool invocations.
10
+ * - `"function_call_output"` / `"tool_call_output"` — tool results.
11
+ * - `"session.end"` / `"done"` — final event with summary/usage.
12
+ *
13
+ * NOTE: This parser is based on expected Codex JSONL structure. The exact
14
+ * schema depends on the spike to capture real output. The parser is designed
15
+ * to be tolerant and handle variations.
16
+ *
17
+ * See `specs/adapter-codex-spike-jsonl-capture.md` for spike requirements.
18
+ */
19
+ import type { CodexParsedResult, StreamParseEvent } from "./types.js";
20
+ /**
21
+ * Parse Codex JSONL output into an ordered Turn[] plus a result summary.
22
+ *
23
+ * Behavior:
24
+ * - Pure: same input → same output (modulo the per-call timestamp).
25
+ * - Tolerant: malformed lines and lines without a recognized type are
26
+ * silently skipped.
27
+ * - Returns `null` when neither a session start/ID NOR a result line was
28
+ * parsed — the adapter caller maps this to a hard error.
29
+ *
30
+ * @param stdout Raw JSONL text (the full captured stdout of `codex exec`).
31
+ */
32
+ export declare function parseCodexJson(stdout: string): CodexParsedResult | null;
33
+ /**
34
+ * Incremental async-generator parser for Codex JSONL output.
35
+ *
36
+ * Yields `StreamParseEvent` as each line is consumed:
37
+ * - `{ type: "meta" }` after the first session-start event sets session + model.
38
+ * - `{ type: "turn" }` for each new Turn added (assistant or user messages).
39
+ * - `{ type: "result" }` when a session.end / done / result event is encountered.
40
+ *
41
+ * Tool output events fill in `ToolCall.output` on previously-yielded Turn
42
+ * objects via reference sharing — no new event for those.
43
+ */
44
+ export declare function parseCodexJsonIncremental(lines: AsyncIterable<string>): AsyncGenerator<StreamParseEvent>;
45
+ //# sourceMappingURL=stream-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-parser.d.ts","sourceRoot":"","sources":["../src/stream-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EACX,iBAAiB,EAEjB,gBAAgB,EAChB,MAAM,YAAY,CAAC;AAiZpB;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,GAAG,IAAI,CAiBvE;AAED;;;;;;;;;;GAUG;AACH,wBAAuB,yBAAyB,CAC/C,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAC1B,cAAc,CAAC,gBAAgB,CAAC,CAuClC"}
@@ -0,0 +1,416 @@
1
+ /**
2
+ * JSONL parser for Codex CLI's `codex exec --json` output.
3
+ *
4
+ * Codex emits JSONL to stdout. Each line is a JSON object with a `type` field.
5
+ * Based on Codex CLI documentation and expected behavior:
6
+ *
7
+ * - `"session.start"` — first line; carries `session_id` and initial config.
8
+ * - `"message"` — user or assistant messages with content.
9
+ * - `"function_call"` / `"tool_call"` — tool invocations.
10
+ * - `"function_call_output"` / `"tool_call_output"` — tool results.
11
+ * - `"session.end"` / `"done"` — final event with summary/usage.
12
+ *
13
+ * NOTE: This parser is based on expected Codex JSONL structure. The exact
14
+ * schema depends on the spike to capture real output. The parser is designed
15
+ * to be tolerant and handle variations.
16
+ *
17
+ * See `specs/adapter-codex-spike-jsonl-capture.md` for spike requirements.
18
+ */
19
+ function isRecord(value) {
20
+ return typeof value === "object" && value !== null && !Array.isArray(value);
21
+ }
22
+ function safeNumber(v, fallback = 0) {
23
+ return typeof v === "number" && Number.isFinite(v) ? v : fallback;
24
+ }
25
+ function safeString(v, fallback = "") {
26
+ return typeof v === "string" ? v : fallback;
27
+ }
28
+ function extractTextContent(message) {
29
+ // Codex may use different content formats
30
+ const content = message.content;
31
+ if (typeof content === "string") {
32
+ return content;
33
+ }
34
+ if (Array.isArray(content)) {
35
+ const texts = [];
36
+ for (const item of content) {
37
+ if (isRecord(item) &&
38
+ item.type === "text" &&
39
+ typeof item.text === "string") {
40
+ texts.push(item.text);
41
+ }
42
+ else if (typeof item === "string") {
43
+ texts.push(item);
44
+ }
45
+ }
46
+ return texts.join("\n");
47
+ }
48
+ return "";
49
+ }
50
+ function extractToolCalls(message) {
51
+ const calls = [];
52
+ // Check for tool_calls array (OpenAI format)
53
+ const toolCalls = message.tool_calls;
54
+ if (Array.isArray(toolCalls)) {
55
+ for (const tc of toolCalls) {
56
+ if (!isRecord(tc))
57
+ continue;
58
+ const fn = isRecord(tc.function) ? tc.function : tc;
59
+ const name = safeString(fn.name ?? tc.name);
60
+ if (name === "")
61
+ continue;
62
+ let input;
63
+ const args = fn.arguments ?? fn.input ?? tc.arguments ?? tc.input;
64
+ if (typeof args === "string") {
65
+ try {
66
+ const parsed = JSON.parse(args);
67
+ input = isRecord(parsed) ? parsed : { raw: args };
68
+ }
69
+ catch {
70
+ input = { raw: args };
71
+ }
72
+ }
73
+ else if (isRecord(args)) {
74
+ input = args;
75
+ }
76
+ else {
77
+ input = {};
78
+ }
79
+ calls.push({
80
+ tool: name,
81
+ input,
82
+ output: null,
83
+ durationMs: null,
84
+ exitCode: null,
85
+ });
86
+ }
87
+ }
88
+ // Also check for function_call (older format)
89
+ const functionCall = message.function_call;
90
+ if (isRecord(functionCall) && typeof functionCall.name === "string") {
91
+ let input;
92
+ const args = functionCall.arguments;
93
+ if (typeof args === "string") {
94
+ try {
95
+ const parsed = JSON.parse(args);
96
+ input = isRecord(parsed) ? parsed : { raw: args };
97
+ }
98
+ catch {
99
+ input = { raw: args };
100
+ }
101
+ }
102
+ else if (isRecord(args)) {
103
+ input = args;
104
+ }
105
+ else {
106
+ input = {};
107
+ }
108
+ calls.push({
109
+ tool: functionCall.name,
110
+ input,
111
+ output: null,
112
+ durationMs: null,
113
+ exitCode: null,
114
+ });
115
+ }
116
+ return calls;
117
+ }
118
+ function extractToolCallIds(message) {
119
+ const ids = [];
120
+ const toolCalls = message.tool_calls;
121
+ if (Array.isArray(toolCalls)) {
122
+ for (const tc of toolCalls) {
123
+ if (isRecord(tc) && typeof tc.id === "string") {
124
+ ids.push(tc.id);
125
+ }
126
+ }
127
+ }
128
+ return ids;
129
+ }
130
+ function processSessionStart(parsed, state) {
131
+ // Look for session_id in various places Codex might put it
132
+ const sessionId = safeString(parsed.session_id) ||
133
+ safeString(parsed.sessionId) ||
134
+ safeString(parsed.id);
135
+ if (sessionId !== "") {
136
+ state.sessionId = sessionId;
137
+ }
138
+ const model = safeString(parsed.model);
139
+ if (model !== "") {
140
+ state.model = model;
141
+ }
142
+ }
143
+ function processMessage(parsed, state) {
144
+ const role = safeString(parsed.role);
145
+ const message = isRecord(parsed.message)
146
+ ? parsed.message
147
+ : isRecord(parsed.content)
148
+ ? { content: parsed.content }
149
+ : parsed;
150
+ // Determine the actual role
151
+ let turnRole;
152
+ if (role === "user" || parsed.type === "user") {
153
+ turnRole = "user";
154
+ }
155
+ else if (role === "assistant" || parsed.type === "assistant") {
156
+ turnRole = "assistant";
157
+ }
158
+ else if (role === "system" || parsed.type === "system") {
159
+ turnRole = "system";
160
+ }
161
+ else {
162
+ // Default to assistant for messages without explicit role
163
+ turnRole = "assistant";
164
+ }
165
+ const textContent = extractTextContent(message);
166
+ const toolCalls = turnRole === "assistant" ? extractToolCalls(message) : [];
167
+ // Skip empty turns
168
+ if (textContent === "" && toolCalls.length === 0) {
169
+ return;
170
+ }
171
+ const turn = {
172
+ index: state.turnIndex++,
173
+ role: turnRole,
174
+ content: textContent,
175
+ timestamp: state.now,
176
+ toolCalls: toolCalls.length > 0 ? toolCalls : null,
177
+ tokens: null,
178
+ hash: null,
179
+ };
180
+ state.turns.push(turn);
181
+ // Register tool call IDs for later matching with outputs
182
+ if (turnRole === "assistant") {
183
+ const ids = extractToolCallIds(message);
184
+ for (let i = 0; i < ids.length; i++) {
185
+ const id = ids[i];
186
+ const call = toolCalls[i];
187
+ if (id !== undefined && call !== undefined) {
188
+ state.pendingToolCalls.set(id, call);
189
+ }
190
+ }
191
+ }
192
+ }
193
+ function processToolOutput(parsed, state) {
194
+ const toolCallId = safeString(parsed.tool_call_id ?? parsed.function_call_id ?? parsed.id);
195
+ const output = safeString(parsed.output ?? parsed.content ?? parsed.result);
196
+ if (toolCallId !== "") {
197
+ const target = state.pendingToolCalls.get(toolCallId);
198
+ if (target !== undefined) {
199
+ target.output = output;
200
+ state.pendingToolCalls.delete(toolCallId);
201
+ }
202
+ }
203
+ }
204
+ function processResult(parsed, state) {
205
+ state.resultLine = parsed;
206
+ // Extract session_id from result if not already set
207
+ const sessionId = safeString(parsed.session_id) || safeString(parsed.sessionId);
208
+ if (sessionId !== "" && state.sessionId === "") {
209
+ state.sessionId = sessionId;
210
+ }
211
+ // Extract model from result if not already set
212
+ const model = safeString(parsed.model);
213
+ if (model !== "" && state.model === "") {
214
+ state.model = model;
215
+ }
216
+ }
217
+ function processLine(line, state) {
218
+ const trimmed = line.trim();
219
+ if (trimmed === "")
220
+ return;
221
+ let parsed;
222
+ try {
223
+ parsed = JSON.parse(trimmed);
224
+ }
225
+ catch {
226
+ return;
227
+ }
228
+ if (!isRecord(parsed))
229
+ return;
230
+ const type = safeString(parsed.type);
231
+ // Session start events
232
+ if (type === "session.start" ||
233
+ type === "session_start" ||
234
+ type === "init" ||
235
+ type === "system") {
236
+ processSessionStart(parsed, state);
237
+ return;
238
+ }
239
+ // Message events
240
+ if (type === "message" || type === "user" || type === "assistant") {
241
+ processMessage(parsed, state);
242
+ return;
243
+ }
244
+ // Tool call output events
245
+ if (type === "function_call_output" ||
246
+ type === "tool_call_output" ||
247
+ type === "tool_output" ||
248
+ type === "tool_result") {
249
+ processToolOutput(parsed, state);
250
+ return;
251
+ }
252
+ // Result/done events
253
+ if (type === "session.end" ||
254
+ type === "session_end" ||
255
+ type === "done" ||
256
+ type === "result" ||
257
+ type === "complete") {
258
+ processResult(parsed, state);
259
+ return;
260
+ }
261
+ // If it has a role field, treat as a message
262
+ if (parsed.role !== undefined) {
263
+ processMessage(parsed, state);
264
+ }
265
+ }
266
+ function extractLastAssistantContent(turns) {
267
+ for (let i = turns.length - 1; i >= 0; i--) {
268
+ const turn = turns[i];
269
+ if (turn !== undefined &&
270
+ turn.role === "assistant" &&
271
+ turn.content !== "") {
272
+ return turn.content;
273
+ }
274
+ }
275
+ return "";
276
+ }
277
+ function coerceSubtype(raw) {
278
+ if (raw === "success" || raw === "error" || raw === "incomplete") {
279
+ return raw;
280
+ }
281
+ // Map Codex-specific subtypes
282
+ if (raw === "completed" || raw === "done" || raw === "end_turn") {
283
+ return "success";
284
+ }
285
+ if (raw === "error_max_turns" ||
286
+ raw === "error_budget" ||
287
+ (typeof raw === "string" && raw.startsWith("error"))) {
288
+ return "error";
289
+ }
290
+ return "incomplete";
291
+ }
292
+ function assembleResult(state) {
293
+ // If we have no result line but have a session ID, return an incomplete result
294
+ if (state.resultLine === null) {
295
+ if (state.sessionId === "")
296
+ return null;
297
+ return {
298
+ type: "result",
299
+ subtype: "incomplete",
300
+ result: extractLastAssistantContent(state.turns),
301
+ sessionId: state.sessionId,
302
+ numTurns: state.turns.length,
303
+ durationMs: 0,
304
+ model: state.model,
305
+ stopReason: "incomplete_no_result_line",
306
+ usage: {
307
+ inputTokens: 0,
308
+ outputTokens: 0,
309
+ },
310
+ turns: state.turns,
311
+ };
312
+ }
313
+ const subtype = state.resultLine.subtype ?? state.resultLine.status;
314
+ const sessionIdFromResult = safeString(state.resultLine.session_id) ||
315
+ safeString(state.resultLine.sessionId) ||
316
+ state.sessionId;
317
+ // Extract usage - check various field names Codex might use
318
+ const usage = isRecord(state.resultLine.usage)
319
+ ? state.resultLine.usage
320
+ : state.resultLine;
321
+ const inputTokens = safeNumber(usage.input_tokens ?? usage.inputTokens ?? usage.prompt_tokens);
322
+ const outputTokens = safeNumber(usage.output_tokens ?? usage.outputTokens ?? usage.completion_tokens);
323
+ return {
324
+ type: safeString(state.resultLine.type, "result"),
325
+ subtype: coerceSubtype(subtype),
326
+ result: typeof state.resultLine.result === "string"
327
+ ? state.resultLine.result
328
+ : extractLastAssistantContent(state.turns),
329
+ sessionId: sessionIdFromResult,
330
+ numTurns: state.turns.length,
331
+ durationMs: safeNumber(state.resultLine.duration_ms ?? state.resultLine.durationMs),
332
+ model: state.model,
333
+ stopReason: safeString(state.resultLine.stop_reason ??
334
+ state.resultLine.stopReason ??
335
+ state.resultLine.finish_reason),
336
+ usage: {
337
+ inputTokens,
338
+ outputTokens,
339
+ },
340
+ turns: state.turns,
341
+ };
342
+ }
343
+ /**
344
+ * Parse Codex JSONL output into an ordered Turn[] plus a result summary.
345
+ *
346
+ * Behavior:
347
+ * - Pure: same input → same output (modulo the per-call timestamp).
348
+ * - Tolerant: malformed lines and lines without a recognized type are
349
+ * silently skipped.
350
+ * - Returns `null` when neither a session start/ID NOR a result line was
351
+ * parsed — the adapter caller maps this to a hard error.
352
+ *
353
+ * @param stdout Raw JSONL text (the full captured stdout of `codex exec`).
354
+ */
355
+ export function parseCodexJson(stdout) {
356
+ const lines = stdout.split("\n");
357
+ const state = {
358
+ turns: [],
359
+ pendingToolCalls: new Map(),
360
+ resultLine: null,
361
+ model: "",
362
+ sessionId: "",
363
+ turnIndex: 0,
364
+ now: new Date().toISOString(),
365
+ };
366
+ for (const line of lines) {
367
+ processLine(line, state);
368
+ }
369
+ return assembleResult(state);
370
+ }
371
+ /**
372
+ * Incremental async-generator parser for Codex JSONL output.
373
+ *
374
+ * Yields `StreamParseEvent` as each line is consumed:
375
+ * - `{ type: "meta" }` after the first session-start event sets session + model.
376
+ * - `{ type: "turn" }` for each new Turn added (assistant or user messages).
377
+ * - `{ type: "result" }` when a session.end / done / result event is encountered.
378
+ *
379
+ * Tool output events fill in `ToolCall.output` on previously-yielded Turn
380
+ * objects via reference sharing — no new event for those.
381
+ */
382
+ export async function* parseCodexJsonIncremental(lines) {
383
+ const state = {
384
+ turns: [],
385
+ pendingToolCalls: new Map(),
386
+ resultLine: null,
387
+ model: "",
388
+ sessionId: "",
389
+ turnIndex: 0,
390
+ now: new Date().toISOString(),
391
+ };
392
+ let metaYielded = false;
393
+ for await (const line of lines) {
394
+ const turnsBefore = state.turns.length;
395
+ const hadResult = state.resultLine !== null;
396
+ const hadSession = state.sessionId !== "";
397
+ processLine(line, state);
398
+ // Yield meta event once session info is available
399
+ if (!metaYielded && !hadSession && state.sessionId !== "") {
400
+ metaYielded = true;
401
+ yield { type: "meta", sessionId: state.sessionId, model: state.model };
402
+ }
403
+ // Yield new turns
404
+ for (let i = turnsBefore; i < state.turns.length; i++) {
405
+ const turn = state.turns[i];
406
+ if (turn !== undefined) {
407
+ yield { type: "turn", turn };
408
+ }
409
+ }
410
+ // Yield result event
411
+ if (!hadResult && state.resultLine !== null) {
412
+ yield { type: "result", resultLine: state.resultLine };
413
+ }
414
+ }
415
+ }
416
+ //# sourceMappingURL=stream-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-parser.js","sourceRoot":"","sources":["../src/stream-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Public types for `@sumeru/adapter-codex`.
3
+ *
4
+ * Most of the adapter contract lives in `@sumeru/core` (`Adapter`,
5
+ * `NativeSessionRef`, `SendEvent`, `SessionConfig`, `Turn`, `ToolCall`,
6
+ * `TokenUsage`). This module only declares package-local options, the
7
+ * parser's intermediate shape, and the `child_process.spawn` test seam.
8
+ */
9
+ import type { Turn } from "@sumeru/core";
10
+ /** Post-exit metadata from a streaming spawn. */
11
+ export type SpawnExitInfo = {
12
+ exitCode: number | null;
13
+ signal: NodeJS.Signals | null;
14
+ timedOut: boolean;
15
+ durationMs: number;
16
+ stderr: string;
17
+ };
18
+ /** Return value of `StreamingSpawnFn` — lines + exit promise. */
19
+ export type SpawnStreamResult = {
20
+ lines: AsyncIterable<string>;
21
+ waitForExit(): Promise<SpawnExitInfo>;
22
+ };
23
+ /** Streaming spawn test seam — returns synchronously with incremental stdout access. */
24
+ export type StreamingSpawnFn = (args: SpawnArgs) => SpawnStreamResult;
25
+ /** Events yielded by the incremental stream parser. */
26
+ export type StreamParseEvent = {
27
+ type: "turn";
28
+ turn: Turn;
29
+ } | {
30
+ type: "meta";
31
+ sessionId: string;
32
+ model: string;
33
+ } | {
34
+ type: "result";
35
+ resultLine: Record<string, unknown>;
36
+ };
37
+ /**
38
+ * Optional configuration for `createCodexAdapter`. Every field accepts
39
+ * `null` (or absence) to fall through to the defaults — no optional `?:`
40
+ * properties on this surface.
41
+ */
42
+ export type CodexAdapterOptions = {
43
+ /** Path to the `codex` executable. Defaults to `"codex"` (rely on $PATH). */
44
+ codexBin: string | null;
45
+ /**
46
+ * `-m, --model` value passed on every spawn. Defaults to `null`, which means
47
+ * the adapter does NOT pass `--model` and lets Codex use its default.
48
+ */
49
+ model: string | null;
50
+ /** Working directory for the spawned process (`-C, --cd <DIR>`). Defaults to `process.cwd()`. */
51
+ cwd: string | null;
52
+ /** Default 5-minute timeout for `createSession`. */
53
+ createSessionTimeoutMs: number | null;
54
+ /** Default 30-minute timeout for `send` (consistent with adapter-claude-code). */
55
+ sendTimeoutMs: number | null;
56
+ /**
57
+ * Test-only override for `child_process.spawn`. Production code never
58
+ * passes this — the integration tests inject a fake to avoid spawning a
59
+ * real `codex` binary.
60
+ */
61
+ spawnFn: SpawnFn | null;
62
+ /**
63
+ * Test-only override for the streaming spawn used in `send()`. Inject a
64
+ * mock to control line timing in tests without spawning a real process.
65
+ */
66
+ streamingSpawnFn: StreamingSpawnFn | null;
67
+ /**
68
+ * Whether to pass `--dangerously-bypass-approvals-and-sandbox` to Codex.
69
+ * Defaults to `true` for unattended Sumeru/uwf runs (parallel to
70
+ * `--dangerously-skip-permissions` in adapter-claude-code).
71
+ */
72
+ dangerouslyBypassApprovals: boolean | null;
73
+ /**
74
+ * Whether to pass `--skip-git-repo-check` to Codex. Defaults to `true`
75
+ * because Sumeru cwds may not always be git repos, and Codex refuses to
76
+ * run outside a git repo by default.
77
+ */
78
+ skipGitRepoCheck: boolean | null;
79
+ };
80
+ /** Argument shape mirroring `child_process.spawn` minus the irrelevant overloads. */
81
+ export type SpawnArgs = {
82
+ command: string;
83
+ args: string[];
84
+ timeoutMs: number;
85
+ cwd: string;
86
+ };
87
+ /** Result of a spawned `codex` invocation. */
88
+ export type SpawnResult = {
89
+ stdout: string;
90
+ stderr: string;
91
+ exitCode: number | null;
92
+ signal: NodeJS.Signals | null;
93
+ timedOut: boolean;
94
+ durationMs: number;
95
+ };
96
+ /** Test seam for `child_process.spawn`. */
97
+ export type SpawnFn = (args: SpawnArgs) => Promise<SpawnResult>;
98
+ /**
99
+ * Subtype of a parsed Codex result — string-literal union, no widening to
100
+ * `string`. The `"incomplete"` variant is synthesized by the parser when no
101
+ * result line was emitted (Codex was killed or its stream truncated).
102
+ */
103
+ export type CodexResultSubtype = "success" | "error" | "incomplete";
104
+ /**
105
+ * Intermediate parsed result from Codex's `--json` JSONL output. Unlike the
106
+ * uwf reference, Sumeru does NOT persist this — the server layer handles ocas
107
+ * writes. The adapter consumes `turns`, `sessionId`, `subtype`, and `usage`.
108
+ */
109
+ export type CodexParsedResult = {
110
+ type: string;
111
+ subtype: CodexResultSubtype;
112
+ result: string;
113
+ sessionId: string;
114
+ numTurns: number;
115
+ durationMs: number;
116
+ model: string;
117
+ stopReason: string;
118
+ usage: {
119
+ inputTokens: number;
120
+ outputTokens: number;
121
+ };
122
+ turns: Turn[];
123
+ };
124
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Public types for `@sumeru/adapter-codex`.
3
+ *
4
+ * Most of the adapter contract lives in `@sumeru/core` (`Adapter`,
5
+ * `NativeSessionRef`, `SendEvent`, `SessionConfig`, `Turn`, `ToolCall`,
6
+ * `TokenUsage`). This module only declares package-local options, the
7
+ * parser's intermediate shape, and the `child_process.spawn` test seam.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@sumeru/adapter-codex",
3
+ "description": "Sumeru adapter for OpenAI Codex CLI",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "license": "MIT",
18
+ "dependencies": {
19
+ "@sumeru/core": "0.1.0"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc -b",
23
+ "test:ci": "npx vitest run"
24
+ }
25
+ }