@glubean/port 0.1.0 → 0.1.1
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/dist/providers/codex.d.ts.map +1 -1
- package/dist/providers/codex.js +109 -20
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/providers/codex.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,cAAc,EAEd,aAAa,EAEb,kBAAkB,EAElB,SAAS,EACT,IAAI,EACJ,WAAW,EAGZ,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,KAAK,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAEpD,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,OAAO,CAwCpD,CAAC;AAEF,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAEvF;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAIrG;
|
|
1
|
+
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/providers/codex.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,cAAc,EAEd,aAAa,EAEb,kBAAkB,EAElB,SAAS,EACT,IAAI,EACJ,WAAW,EAGZ,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,KAAK,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAEpD,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,OAAO,CAwCpD,CAAC;AAEF,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAEvF;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAIrG;AAuUD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACpC,GAAG,SAAS,CAYZ"}
|
package/dist/providers/codex.js
CHANGED
|
@@ -55,6 +55,13 @@ export async function createCodexAdapter(options) {
|
|
|
55
55
|
await runtime.start();
|
|
56
56
|
return runtime.adapter;
|
|
57
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Cap stderr buffer to a bounded number of lines so a chatty codex
|
|
60
|
+
* process cannot grow memory unbounded over a long-lived session. The
|
|
61
|
+
* tail (most recent N lines) is what we surface in error messages —
|
|
62
|
+
* head lines from a healthy startup are rarely useful for diagnosis.
|
|
63
|
+
*/
|
|
64
|
+
const STDERR_BUFFER_MAX_LINES = 200;
|
|
58
65
|
class CodexRuntime {
|
|
59
66
|
#options;
|
|
60
67
|
#process;
|
|
@@ -62,6 +69,17 @@ class CodexRuntime {
|
|
|
62
69
|
#normalizer = new CodexEventNormalizer();
|
|
63
70
|
#events = new EventEmitter();
|
|
64
71
|
#closed = false;
|
|
72
|
+
/**
|
|
73
|
+
* Bounded ring buffer of recent codex stderr lines, surfaced in
|
|
74
|
+
* augmented error messages so a 30ms "JSON-RPC input closed" failure
|
|
75
|
+
* carries the actual codex stderr (auth error, bad flag, missing
|
|
76
|
+
* config, etc.) instead of disappearing into the void.
|
|
77
|
+
*/
|
|
78
|
+
#stderrBuffer = [];
|
|
79
|
+
/** Captured at process 'exit' so subsequent rpc.request rejections can cite it. */
|
|
80
|
+
#exitInfo = null;
|
|
81
|
+
/** Captured at process 'error' (e.g. spawn ENOENT) for the same reason. */
|
|
82
|
+
#spawnError = null;
|
|
65
83
|
constructor(options) {
|
|
66
84
|
this.#options = options;
|
|
67
85
|
}
|
|
@@ -104,27 +122,84 @@ class CodexRuntime {
|
|
|
104
122
|
shell: false,
|
|
105
123
|
});
|
|
106
124
|
this.#process.stderr.on("data", (chunk) => {
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
125
|
+
const text = chunk.toString("utf8");
|
|
126
|
+
// Buffer stderr line-by-line so #augmentError can surface a
|
|
127
|
+
// bounded tail. We still emit the chunk as an error event so
|
|
128
|
+
// existing event-stream consumers aren't broken.
|
|
129
|
+
for (const line of text.split(/\r?\n/)) {
|
|
130
|
+
if (!line)
|
|
131
|
+
continue;
|
|
132
|
+
this.#stderrBuffer.push(line);
|
|
133
|
+
if (this.#stderrBuffer.length > STDERR_BUFFER_MAX_LINES) {
|
|
134
|
+
this.#stderrBuffer.splice(0, this.#stderrBuffer.length - STDERR_BUFFER_MAX_LINES);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const trimmed = text.trim();
|
|
138
|
+
if (trimmed)
|
|
139
|
+
this.#emit({ type: "error", message: trimmed });
|
|
110
140
|
});
|
|
111
141
|
this.#process.on("exit", (code, signal) => {
|
|
142
|
+
this.#exitInfo = { code, signal };
|
|
112
143
|
if (!this.#closed) {
|
|
113
144
|
this.#emit({ type: "error", message: `Codex app-server exited: code=${code ?? "null"} signal=${signal ?? "null"}` });
|
|
114
145
|
}
|
|
115
146
|
});
|
|
147
|
+
// 'error' fires on spawn failures (e.g. ENOENT when codex binary is
|
|
148
|
+
// missing from PATH). Without a listener Node would crash the
|
|
149
|
+
// process on the unhandled emit; instead capture and let the
|
|
150
|
+
// pending rpc.request rejection surface the spawn error.
|
|
151
|
+
this.#process.on("error", (err) => {
|
|
152
|
+
this.#spawnError = err;
|
|
153
|
+
if (!this.#closed) {
|
|
154
|
+
this.#emit({ type: "error", message: `Codex app-server spawn error: ${err.message}` });
|
|
155
|
+
}
|
|
156
|
+
});
|
|
116
157
|
this.#rpc = new JsonRpcLineConnection(this.#process.stdout, this.#process.stdin);
|
|
117
158
|
this.#rpc.onNotification((notification) => {
|
|
118
159
|
for (const event of this.#normalizer.normalize(notification)) {
|
|
119
160
|
this.#emit(event);
|
|
120
161
|
}
|
|
121
162
|
});
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
163
|
+
try {
|
|
164
|
+
await this.#rpc.request("initialize", {
|
|
165
|
+
clientInfo: { name: "glubean-port", version: "0.0.0" },
|
|
166
|
+
capabilities: { experimentalApi: true },
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
throw await this.#augmentError(err);
|
|
171
|
+
}
|
|
126
172
|
this.#rpc.notify("initialized", {});
|
|
127
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Wrap an rpc rejection with codex process diagnostics so callers see
|
|
176
|
+
* (a) why the process closed if it did, (b) any spawn 'error' (e.g.
|
|
177
|
+
* ENOENT), and (c) the most recent stderr lines. The original error
|
|
178
|
+
* is preserved as `cause` for callers that introspect it.
|
|
179
|
+
*
|
|
180
|
+
* Awaits a microtask so any racing `process.on("exit")` fires before
|
|
181
|
+
* we read `#exitInfo` — JsonRpcLineConnection rejects synchronously
|
|
182
|
+
* from `input.on("close")`, but Node may fire stream 'close' before
|
|
183
|
+
* the matching process 'exit' on some versions.
|
|
184
|
+
*/
|
|
185
|
+
async #augmentError(err) {
|
|
186
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
187
|
+
const original = err instanceof Error ? err : new Error(String(err));
|
|
188
|
+
const parts = [original.message];
|
|
189
|
+
if (this.#spawnError) {
|
|
190
|
+
parts.push(`(codex spawn error: ${this.#spawnError.message})`);
|
|
191
|
+
}
|
|
192
|
+
if (this.#exitInfo) {
|
|
193
|
+
parts.push(`(codex process exited: code=${this.#exitInfo.code ?? "null"} signal=${this.#exitInfo.signal ?? "null"})`);
|
|
194
|
+
}
|
|
195
|
+
if (this.#stderrBuffer.length > 0) {
|
|
196
|
+
const tail = this.#stderrBuffer.slice(-20).join("\n");
|
|
197
|
+
parts.push(`(codex stderr tail:\n${tail})`);
|
|
198
|
+
}
|
|
199
|
+
const augmented = new Error(parts.join(" "));
|
|
200
|
+
augmented.cause = original;
|
|
201
|
+
return augmented;
|
|
202
|
+
}
|
|
128
203
|
async close() {
|
|
129
204
|
this.#closed = true;
|
|
130
205
|
this.#rpc?.close();
|
|
@@ -152,7 +227,14 @@ class CodexRuntime {
|
|
|
152
227
|
});
|
|
153
228
|
if (method === "thread/resume")
|
|
154
229
|
params.threadId = input.id ?? "";
|
|
155
|
-
|
|
230
|
+
let rawResult;
|
|
231
|
+
try {
|
|
232
|
+
rawResult = await rpc.request(method, params);
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
throw await this.#augmentError(err);
|
|
236
|
+
}
|
|
237
|
+
const result = asRecord(rawResult);
|
|
156
238
|
const thread = asRecord(result.thread);
|
|
157
239
|
const id = asString(thread.id) ?? input.id;
|
|
158
240
|
if (!id)
|
|
@@ -183,18 +265,25 @@ class CodexRuntime {
|
|
|
183
265
|
const runtimeOptions = resolveRuntimeOptions(input, this.#options.options);
|
|
184
266
|
const codexOptions = providerRuntimeOptions(runtimeOptions);
|
|
185
267
|
const effort = toCodexReasoningEffort(codexOptions.effort);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
268
|
+
let rawResult;
|
|
269
|
+
try {
|
|
270
|
+
rawResult = await rpc.request("turn/start", {
|
|
271
|
+
threadId: input.sessionId,
|
|
272
|
+
input: normalizeInput(input.input),
|
|
273
|
+
...(runtimeOptions.cwd ? { cwd: runtimeOptions.cwd } : {}),
|
|
274
|
+
...(runtimeOptions.model ? { model: runtimeOptions.model } : {}),
|
|
275
|
+
...(runtimeOptions.approvalPolicy ? { approvalPolicy: runtimeOptions.approvalPolicy } : {}),
|
|
276
|
+
...(runtimeOptions.sandbox ? { sandboxPolicy: toCodexSandboxPolicy(runtimeOptions.sandbox) } : {}),
|
|
277
|
+
...(effort ? { effort } : {}),
|
|
278
|
+
...(codexOptions?.reasoningSummary ? { summary: codexOptions.reasoningSummary } : {}),
|
|
279
|
+
...(codexOptions?.serviceTier ? { serviceTier: codexOptions.serviceTier } : {}),
|
|
280
|
+
...(input.outputSchema ? { outputSchema: input.outputSchema } : {}),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
catch (err) {
|
|
284
|
+
throw await this.#augmentError(err);
|
|
285
|
+
}
|
|
286
|
+
const result = asRecord(rawResult);
|
|
198
287
|
expectedTurnId = readTurnId(result);
|
|
199
288
|
for await (const event of queue) {
|
|
200
289
|
yield event;
|