ai-sdk-provider-codex-cli 2.0.0 → 2.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/README.md +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +92 -24
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ npm i ai@^6 ai-sdk-provider-codex-cli@ai-sdk-v6
|
|
|
64
64
|
npm i ai@^5.0.0 ai-sdk-provider-codex-cli@ai-sdk-v5
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
> **⚠️ Codex CLI Version**: Requires the current stable Codex CLI **0.
|
|
67
|
+
> **⚠️ Codex CLI Version**: Requires the current stable Codex CLI **0.144.x** for full support of both provider modes (`codexExec` and `codexAppServer`). This package pins its optional `@openai/codex` dependency to `^0.144.0`, the latest non-alpha release line validated for this release line. If you supply your own Codex CLI (global install or custom `codexPath`), check it with `codex --version` and upgrade if needed.
|
|
68
68
|
>
|
|
69
69
|
> ```bash
|
|
70
70
|
> npm i -g @openai/codex@latest
|
|
@@ -100,7 +100,7 @@ import { createCodexAppServer } from 'ai-sdk-provider-codex-cli';
|
|
|
100
100
|
|
|
101
101
|
const provider = createCodexAppServer({
|
|
102
102
|
defaultSettings: {
|
|
103
|
-
minCodexVersion: '0.
|
|
103
|
+
minCodexVersion: '0.144.0',
|
|
104
104
|
autoApprove: false,
|
|
105
105
|
personality: 'pragmatic',
|
|
106
106
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -854,7 +854,7 @@ interface CodexAppServerProvider extends ProviderV4 {
|
|
|
854
854
|
* @example
|
|
855
855
|
* ```ts
|
|
856
856
|
* const provider = createCodexAppServer({
|
|
857
|
-
* defaultSettings: { minCodexVersion: '0.
|
|
857
|
+
* defaultSettings: { minCodexVersion: '0.144.0' },
|
|
858
858
|
* });
|
|
859
859
|
*
|
|
860
860
|
* try {
|
package/dist/index.js
CHANGED
|
@@ -4827,6 +4827,7 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
4827
4827
|
activeRequestContextsByTurn = /* @__PURE__ */ new Map();
|
|
4828
4828
|
completedTurnIds = /* @__PURE__ */ new Set();
|
|
4829
4829
|
lastStderr = "";
|
|
4830
|
+
lastCrashHadStderr = false;
|
|
4830
4831
|
idleTimer;
|
|
4831
4832
|
serverCapabilities;
|
|
4832
4833
|
expectedExitSignal;
|
|
@@ -4921,7 +4922,7 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
4921
4922
|
if (this.serverCapabilities?.modelList === false) {
|
|
4922
4923
|
throw new UnsupportedFeatureError({
|
|
4923
4924
|
feature: "model/list",
|
|
4924
|
-
minCodexVersion: this.settings.minCodexVersion ?? "0.
|
|
4925
|
+
minCodexVersion: this.settings.minCodexVersion ?? "0.144.0",
|
|
4925
4926
|
serverVersion: this.serverVersion
|
|
4926
4927
|
});
|
|
4927
4928
|
}
|
|
@@ -4934,7 +4935,7 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
4934
4935
|
if (error instanceof JsonRpcRequestError && error.code === -32601) {
|
|
4935
4936
|
throw new UnsupportedFeatureError({
|
|
4936
4937
|
feature: "model/list",
|
|
4937
|
-
minCodexVersion: this.settings.minCodexVersion ?? "0.
|
|
4938
|
+
minCodexVersion: this.settings.minCodexVersion ?? "0.144.0",
|
|
4938
4939
|
serverVersion: this.serverVersion
|
|
4939
4940
|
});
|
|
4940
4941
|
}
|
|
@@ -5033,6 +5034,7 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
5033
5034
|
const base = resolveCodexPath2(this.settings.codexPath);
|
|
5034
5035
|
const args = [...base.args, "app-server", "--listen", "stdio://"];
|
|
5035
5036
|
this.lastStderr = "";
|
|
5037
|
+
this.lastCrashHadStderr = false;
|
|
5036
5038
|
this.expectedExitSignal = void 0;
|
|
5037
5039
|
this.child = spawn(base.cmd, args, {
|
|
5038
5040
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -5043,18 +5045,23 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
5043
5045
|
},
|
|
5044
5046
|
cwd: this.settings.cwd
|
|
5045
5047
|
});
|
|
5046
|
-
this.child
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5048
|
+
const child = this.child;
|
|
5049
|
+
let stderrBuf = "";
|
|
5050
|
+
child.stderr.setEncoding("utf8");
|
|
5051
|
+
child.stderr.on("data", (chunk) => {
|
|
5052
|
+
stderrBuf = (stderrBuf + String(chunk)).slice(-4e3);
|
|
5053
|
+
if (this.child === child) {
|
|
5054
|
+
this.lastStderr = stderrBuf;
|
|
5051
5055
|
}
|
|
5052
5056
|
});
|
|
5053
|
-
|
|
5057
|
+
child.on("error", (error) => {
|
|
5054
5058
|
this.logger.error(`[codex-app-server] process error: ${String(error)}`);
|
|
5055
|
-
|
|
5059
|
+
const base2 = String(error);
|
|
5060
|
+
const message = this.withStderrTail(base2, stderrBuf);
|
|
5061
|
+
this.lastCrashHadStderr = message !== base2;
|
|
5062
|
+
this.handleCrash(new Error(message));
|
|
5056
5063
|
});
|
|
5057
|
-
|
|
5064
|
+
child.on("exit", (code, signal) => {
|
|
5058
5065
|
const message = `codex app-server exited (code=${String(code)}, signal=${String(signal)})`;
|
|
5059
5066
|
const expected = this.state === "closed" || signal !== null && signal === this.expectedExitSignal;
|
|
5060
5067
|
this.expectedExitSignal = void 0;
|
|
@@ -5062,11 +5069,29 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
5062
5069
|
this.logger.info(`[codex-app-server] ${message}`);
|
|
5063
5070
|
return;
|
|
5064
5071
|
}
|
|
5065
|
-
this.
|
|
5066
|
-
|
|
5072
|
+
const crashedPending = this.markCrashed();
|
|
5073
|
+
if (!crashedPending) return;
|
|
5074
|
+
let settled = false;
|
|
5075
|
+
const finish = () => {
|
|
5076
|
+
if (settled) return;
|
|
5077
|
+
settled = true;
|
|
5078
|
+
child.off("close", finish);
|
|
5079
|
+
clearTimeout(timer);
|
|
5080
|
+
const base2 = `codex app-server exited (code=${String(code)}, signal=${String(signal)})`;
|
|
5081
|
+
const crashMessage = this.withStderrTail(base2, stderrBuf);
|
|
5082
|
+
if (this.child === void 0) {
|
|
5083
|
+
this.lastStderr = stderrBuf;
|
|
5084
|
+
this.lastCrashHadStderr = crashMessage !== base2;
|
|
5085
|
+
}
|
|
5086
|
+
this.logger.warn(`[codex-app-server] ${crashMessage}`);
|
|
5087
|
+
this.rejectCrashedPending(crashedPending, new Error(crashMessage));
|
|
5088
|
+
};
|
|
5089
|
+
child.once("close", finish);
|
|
5090
|
+
const timer = setTimeout(finish, 120);
|
|
5091
|
+
timer.unref?.();
|
|
5067
5092
|
});
|
|
5068
5093
|
this.stdoutReader = readline.createInterface({
|
|
5069
|
-
input:
|
|
5094
|
+
input: child.stdout,
|
|
5070
5095
|
crlfDelay: Infinity
|
|
5071
5096
|
});
|
|
5072
5097
|
this.stdoutReader.on("line", (line) => this.handleLine(line));
|
|
@@ -5088,12 +5113,22 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
5088
5113
|
this.settings.connectionTimeoutMs ?? this.requestTimeoutMs
|
|
5089
5114
|
);
|
|
5090
5115
|
} catch (error) {
|
|
5091
|
-
const
|
|
5092
|
-
if (
|
|
5116
|
+
const raw = String(error?.message ?? error);
|
|
5117
|
+
if (raw.includes("unknown subcommand") || this.lastStderr.includes("unknown subcommand")) {
|
|
5118
|
+
throw new Error(
|
|
5119
|
+
this.withStderrTail(
|
|
5120
|
+
"codex app-server requires codex CLI >= 0.144.0. Run 'codex --version' to check."
|
|
5121
|
+
)
|
|
5122
|
+
);
|
|
5123
|
+
}
|
|
5124
|
+
if (raw.includes("ENOENT") || this.lastStderr.includes("ENOENT")) {
|
|
5093
5125
|
throw new Error(
|
|
5094
|
-
|
|
5126
|
+
this.withStderrTail(
|
|
5127
|
+
"codex app-server failed to start: codex executable not found (ENOENT). Check that the codex CLI is installed and its native binary is intact \u2014 a corrupted @openai/codex npm install can cause this. Run 'codex --version' to verify."
|
|
5128
|
+
)
|
|
5095
5129
|
);
|
|
5096
5130
|
}
|
|
5131
|
+
const message = this.lastCrashHadStderr ? raw : this.withStderrTail(raw);
|
|
5097
5132
|
throw createAPICallError({
|
|
5098
5133
|
message: `Failed to initialize codex app-server: ${message}`,
|
|
5099
5134
|
stderr: this.lastStderr,
|
|
@@ -5113,7 +5148,7 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
5113
5148
|
return;
|
|
5114
5149
|
}
|
|
5115
5150
|
this.serverVersion = detected;
|
|
5116
|
-
const minVersion = this.settings.minCodexVersion ?? "0.
|
|
5151
|
+
const minVersion = this.settings.minCodexVersion ?? "0.144.0";
|
|
5117
5152
|
const compared = compareSemver(detected, minVersion);
|
|
5118
5153
|
if (compared === void 0) {
|
|
5119
5154
|
this.logger.warn(
|
|
@@ -5155,8 +5190,8 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
5155
5190
|
}
|
|
5156
5191
|
this.writeQueue = Promise.resolve();
|
|
5157
5192
|
}
|
|
5158
|
-
|
|
5159
|
-
if (this.state === "closed") return;
|
|
5193
|
+
markCrashed() {
|
|
5194
|
+
if (this.state === "closed" || this.state === "error") return void 0;
|
|
5160
5195
|
this.state = "error";
|
|
5161
5196
|
this.clearIdleTimer();
|
|
5162
5197
|
this.stdoutReader?.close();
|
|
@@ -5166,11 +5201,9 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
5166
5201
|
this.child.kill("SIGTERM");
|
|
5167
5202
|
this.child = void 0;
|
|
5168
5203
|
}
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
new Error(`Request ${String(id)} failed after app-server crash: ${String(error)}`)
|
|
5173
|
-
);
|
|
5204
|
+
const pending = new Map(this.pending);
|
|
5205
|
+
for (const [, entry] of pending) {
|
|
5206
|
+
clearTimeout(entry.timer);
|
|
5174
5207
|
}
|
|
5175
5208
|
this.pending.clear();
|
|
5176
5209
|
this.threadLocks.clear();
|
|
@@ -5180,6 +5213,41 @@ var AppServerRpcClient = class extends EventEmitter {
|
|
|
5180
5213
|
this.completedTurnIds.clear();
|
|
5181
5214
|
this.serverCapabilities = void 0;
|
|
5182
5215
|
this.writeQueue = Promise.resolve();
|
|
5216
|
+
return pending;
|
|
5217
|
+
}
|
|
5218
|
+
rejectCrashedPending(pending, error) {
|
|
5219
|
+
for (const [id, entry] of pending) {
|
|
5220
|
+
entry.reject(
|
|
5221
|
+
new Error(`Request ${String(id)} failed after app-server crash: ${String(error)}`)
|
|
5222
|
+
);
|
|
5223
|
+
}
|
|
5224
|
+
}
|
|
5225
|
+
handleCrash(error) {
|
|
5226
|
+
const pending = this.markCrashed();
|
|
5227
|
+
if (!pending) return;
|
|
5228
|
+
this.rejectCrashedPending(pending, error);
|
|
5229
|
+
}
|
|
5230
|
+
stderrExcerpt(raw) {
|
|
5231
|
+
if (!raw) return "";
|
|
5232
|
+
const escape = String.fromCharCode(27);
|
|
5233
|
+
const ansiEscapeSequence = new RegExp(
|
|
5234
|
+
`${escape}(?:\\[[0-?]*[ -/]*[@-~]|\\][^\\u0007]*(?:\\u0007|${escape}\\\\))`,
|
|
5235
|
+
"g"
|
|
5236
|
+
);
|
|
5237
|
+
const withoutAnsi = raw.replace(ansiEscapeSequence, "");
|
|
5238
|
+
const withoutControls = Array.from(withoutAnsi).filter((character) => {
|
|
5239
|
+
const code = character.charCodeAt(0);
|
|
5240
|
+
return character === "\n" || code >= 32 && (code < 127 || code > 159);
|
|
5241
|
+
}).join("");
|
|
5242
|
+
const excerpt = withoutControls.split(/\r?\n/).map((line) => line.trim()).filter(Boolean).slice(-5).join("; ");
|
|
5243
|
+
if (excerpt.length > 600) {
|
|
5244
|
+
return `\u2026${excerpt.slice(-600)}`;
|
|
5245
|
+
}
|
|
5246
|
+
return excerpt;
|
|
5247
|
+
}
|
|
5248
|
+
withStderrTail(message, raw = this.lastStderr) {
|
|
5249
|
+
const excerpt = this.stderrExcerpt(raw);
|
|
5250
|
+
return excerpt ? `${message} | stderr (tail): ${excerpt}` : message;
|
|
5183
5251
|
}
|
|
5184
5252
|
handleLine(line) {
|
|
5185
5253
|
const trimmed = line.trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-sdk-provider-codex-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "AI SDK v7 provider for OpenAI Codex CLI (use ChatGPT Plus/Pro subscription)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-sdk",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"jsonc-parser": "^3.3.1"
|
|
62
62
|
},
|
|
63
63
|
"optionalDependencies": {
|
|
64
|
-
"@openai/codex": "^0.
|
|
64
|
+
"@openai/codex": "^0.144.0"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@eslint/js": "^9.14.0",
|