@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 +18 -0
- package/dist/.build-fingerprint +1 -0
- package/dist/adapter.d.ts +28 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +340 -0
- package/dist/adapter.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/spawn.d.ts +19 -0
- package/dist/spawn.d.ts.map +1 -0
- package/dist/spawn.js +117 -0
- package/dist/spawn.js.map +1 -0
- package/dist/stream-parser.d.ts +45 -0
- package/dist/stream-parser.d.ts.map +1 -0
- package/dist/stream-parser.js +416 -0
- package/dist/stream-parser.js.map +1 -0
- package/dist/types.d.ts +124 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +25 -0
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"}
|
package/dist/adapter.js
ADDED
|
@@ -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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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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"}
|
package/dist/spawn.d.ts
ADDED
|
@@ -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":"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"}
|
|
@@ -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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"}
|
package/dist/types.d.ts
ADDED
|
@@ -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
|
+
}
|