@christiandoxa/prodex 0.212.0 → 0.214.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/README.md +4 -1
- package/lib/codex-shim.cjs +316 -115
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -127,7 +127,7 @@ Runtime proxy design contract:
|
|
|
127
127
|
npm install -g @christiandoxa/prodex
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
The npm package uses its bundled `@openai/codex@latest` dependency by default. To deliberately
|
|
130
|
+
The npm package uses its bundled `@openai/codex@latest` dependency by default. If the bundled native Codex optional package is missing or not executable, Prodex falls back to an executable external `codex` on `PATH` and prints a notice before launch. This includes nvm-managed global Codex installs when the active nvm version's `bin` directory is on `PATH`. If neither bundled nor external Codex is usable, set `PRODEX_CODEX_AUTO_INSTALL=1` to let Prodex run `npm install -g @openai/codex@latest` once before retrying PATH resolution. To deliberately pin a separate Codex CLI from your machine, set `PRODEX_CODEX_BIN=/path/to/codex` or `PRODEX_CODEX_RESOLUTION=external`.
|
|
131
131
|
|
|
132
132
|
</details>
|
|
133
133
|
|
|
@@ -898,6 +898,7 @@ prodex run --rollout-budget-tokens 100000 --rollout-budget-reminders 75000,50000
|
|
|
898
898
|
|
|
899
899
|
prodex run --current-time-reminder
|
|
900
900
|
prodex run --current-time-reminder --current-time-reminder-interval 2
|
|
901
|
+
prodex run --respect-system-proxy
|
|
901
902
|
```
|
|
902
903
|
|
|
903
904
|
`--web-search` maps to Codex's top-level `web_search = "disabled" | "cached" | "indexed" | "live"` setting. In Super provider mode, an explicit `--web-search` is appended after the provider default, so it overrides the default bridge choice.
|
|
@@ -906,6 +907,8 @@ prodex run --current-time-reminder --current-time-reminder-interval 2
|
|
|
906
907
|
|
|
907
908
|
`--current-time-reminder` enables Codex's `[features.current_time_reminder]` config. The default system clock source is owned by Codex. `--current-time-clock-source external` is intended for Codex app-server clients that implement the upstream `currentTime/read` request.
|
|
908
909
|
|
|
910
|
+
`--respect-system-proxy` enables Codex's `[features.respect_system_proxy]` config when the bundled/upstream Codex supports it. Codex 0.142.1 uses this opt-in feature for Windows auth clients so PAC, WPAD, static system proxy, and bypass decisions can be honored. `--no-respect-system-proxy` renders an explicit false override for sessions that need the upstream default direct/env-proxy behavior.
|
|
911
|
+
|
|
909
912
|
Codex `multiAgentMode` is an app-server/thread setting, not a normal TUI `config.toml` launch override. Prodex therefore does not invent a competing CLI config flag. Launch `prodex app-server` or `prodex run app-server` and pass upstream `multiAgentMode` values (`none`, `explicitRequestOnly`, or `proactive`) through the Codex app-server API.
|
|
910
913
|
|
|
911
914
|
Codex plugin catalog commands are managed passthrough by default:
|
package/lib/codex-shim.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
const fs = require("node:fs");
|
|
5
5
|
const path = require("node:path");
|
|
6
|
-
const { spawn } = require("node:child_process");
|
|
6
|
+
const { spawn, spawnSync } = require("node:child_process");
|
|
7
7
|
const { createRequire } = require("node:module");
|
|
8
8
|
|
|
9
9
|
const requireFromHere = createRequire(__filename);
|
|
@@ -47,169 +47,370 @@ const PLATFORM_TARGETS = {
|
|
|
47
47
|
},
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
function
|
|
51
|
-
return PLATFORM_TARGETS[process.platform]?.[process.arch]
|
|
50
|
+
function platformSpec() {
|
|
51
|
+
return PLATFORM_TARGETS[process.platform]?.[process.arch] || null;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
function
|
|
55
|
-
let packageJsonPath;
|
|
54
|
+
function isExecutableFile(filePath) {
|
|
56
55
|
try {
|
|
57
|
-
|
|
56
|
+
const stats = fs.statSync(filePath);
|
|
57
|
+
if (!stats.isFile()) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
fs.accessSync(filePath, fs.constants.X_OK);
|
|
61
|
+
return true;
|
|
58
62
|
} catch {
|
|
59
|
-
return
|
|
63
|
+
return false;
|
|
60
64
|
}
|
|
61
|
-
return path.dirname(packageJsonPath);
|
|
62
65
|
}
|
|
63
66
|
|
|
64
|
-
function
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
function tryMakeExecutable(filePath) {
|
|
68
|
+
if (process.platform === "win32") {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const stats = fs.statSync(filePath);
|
|
73
|
+
if (stats.isFile()) {
|
|
74
|
+
fs.chmodSync(filePath, (stats.mode & 0o777) | 0o755);
|
|
75
|
+
}
|
|
76
|
+
} catch {
|
|
77
|
+
// The explicit executable check below reports the actionable failure.
|
|
68
78
|
}
|
|
69
|
-
return {
|
|
70
|
-
...process.env,
|
|
71
|
-
CODEX_MANAGED_BY_NPM: "1",
|
|
72
|
-
CODEX_MANAGED_PACKAGE_ROOT: fs.realpathSync(packageRoot),
|
|
73
|
-
};
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
function
|
|
81
|
+
function managedCodexPackageRoot(fallbackRoot) {
|
|
77
82
|
try {
|
|
78
|
-
fs.
|
|
79
|
-
return;
|
|
83
|
+
return fs.realpathSync(path.dirname(requireFromHere.resolve("@openai/codex/package.json")));
|
|
80
84
|
} catch {
|
|
81
|
-
|
|
85
|
+
return fs.realpathSync(fallbackRoot);
|
|
82
86
|
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function nativePackagePaths(spec) {
|
|
90
|
+
const packageJsonPath = requireFromHere.resolve(`${spec.packageName}/package.json`);
|
|
91
|
+
const packageRoot = path.dirname(packageJsonPath);
|
|
92
|
+
return {
|
|
93
|
+
packageRoot,
|
|
94
|
+
managedPackageRoot: managedCodexPackageRoot(packageRoot),
|
|
95
|
+
binaryPath: path.join(
|
|
96
|
+
packageRoot,
|
|
97
|
+
"vendor",
|
|
98
|
+
spec.targetTriple,
|
|
99
|
+
"bin",
|
|
100
|
+
spec.binaryFileName,
|
|
101
|
+
),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
83
104
|
|
|
105
|
+
function resolveNativeCodexCommand() {
|
|
106
|
+
const spec = platformSpec();
|
|
107
|
+
if (!spec) {
|
|
108
|
+
return {
|
|
109
|
+
ok: false,
|
|
110
|
+
reason: `Unsupported Codex platform ${process.platform}/${process.arch}.`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
let binaryPath;
|
|
115
|
+
let packageRoot;
|
|
116
|
+
let managedPackageRoot;
|
|
84
117
|
try {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
[
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
118
|
+
({ binaryPath, packageRoot, managedPackageRoot } = nativePackagePaths(spec));
|
|
119
|
+
} catch (error) {
|
|
120
|
+
return {
|
|
121
|
+
ok: false,
|
|
122
|
+
reason: [
|
|
123
|
+
"Unable to locate bundled Codex native package for this platform.",
|
|
124
|
+
`Missing bundled Codex native package ${spec.packageName}.`,
|
|
125
|
+
`Original error: ${error && error.message ? error.message : String(error)}`,
|
|
93
126
|
].join("\n"),
|
|
94
|
-
|
|
95
|
-
process.exit(126);
|
|
127
|
+
};
|
|
96
128
|
}
|
|
129
|
+
|
|
130
|
+
tryMakeExecutable(binaryPath);
|
|
131
|
+
|
|
132
|
+
if (!isExecutableFile(binaryPath)) {
|
|
133
|
+
return {
|
|
134
|
+
ok: false,
|
|
135
|
+
reason: `Bundled Codex native binary is not executable: ${binaryPath}`,
|
|
136
|
+
binaryPath,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
ok: true,
|
|
142
|
+
command: binaryPath,
|
|
143
|
+
args: process.argv.slice(2),
|
|
144
|
+
env: {
|
|
145
|
+
CODEX_MANAGED_BY_NPM: "1",
|
|
146
|
+
CODEX_MANAGED_PACKAGE_ROOT: managedPackageRoot,
|
|
147
|
+
},
|
|
148
|
+
};
|
|
97
149
|
}
|
|
98
150
|
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
|
|
151
|
+
function pathEntries() {
|
|
152
|
+
return (process.env.PATH || "")
|
|
153
|
+
.split(path.delimiter)
|
|
154
|
+
.filter((entry) => entry.length > 0);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function commandNames(command) {
|
|
158
|
+
if (process.platform !== "win32") {
|
|
159
|
+
return [command];
|
|
160
|
+
}
|
|
161
|
+
const pathext = (process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM")
|
|
162
|
+
.split(";")
|
|
163
|
+
.filter(Boolean);
|
|
164
|
+
const lower = command.toLowerCase();
|
|
165
|
+
if (pathext.some((ext) => lower.endsWith(ext.toLowerCase()))) {
|
|
166
|
+
return [command];
|
|
102
167
|
}
|
|
168
|
+
return [command, ...pathext.map((ext) => `${command}${ext}`)];
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function isSelfShim(candidate) {
|
|
103
172
|
try {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
return;
|
|
173
|
+
if (fs.realpathSync(candidate) === fs.realpathSync(__filename)) {
|
|
174
|
+
return true;
|
|
107
175
|
}
|
|
108
|
-
fs.chmodSync(nativeBinaryPath, (stats.mode & 0o777) | 0o755);
|
|
109
176
|
} catch {
|
|
110
|
-
//
|
|
177
|
+
// Continue with the lightweight content check.
|
|
111
178
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return null;
|
|
179
|
+
try {
|
|
180
|
+
const prefix = fs.readFileSync(candidate, "utf8").slice(0, 4096);
|
|
181
|
+
return prefix.includes(__filename);
|
|
182
|
+
} catch {
|
|
183
|
+
return false;
|
|
118
184
|
}
|
|
185
|
+
}
|
|
119
186
|
|
|
120
|
-
|
|
187
|
+
function candidateKey(candidate) {
|
|
121
188
|
try {
|
|
122
|
-
|
|
189
|
+
return fs.realpathSync(candidate).toLowerCase();
|
|
123
190
|
} catch {
|
|
124
|
-
return
|
|
191
|
+
return path.resolve(candidate).toLowerCase();
|
|
125
192
|
}
|
|
193
|
+
}
|
|
126
194
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
].join("\n"),
|
|
141
|
-
);
|
|
142
|
-
process.exit(1);
|
|
195
|
+
function externalCodexCandidates() {
|
|
196
|
+
const seen = new Set();
|
|
197
|
+
const candidates = [];
|
|
198
|
+
for (const dir of pathEntries()) {
|
|
199
|
+
for (const name of commandNames("codex")) {
|
|
200
|
+
const candidate = path.join(dir, name);
|
|
201
|
+
const key = candidateKey(candidate);
|
|
202
|
+
if (seen.has(key)) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
seen.add(key);
|
|
206
|
+
candidates.push(candidate);
|
|
207
|
+
}
|
|
143
208
|
}
|
|
144
|
-
|
|
209
|
+
return candidates;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function summarizeSkippedExternalCandidates(skipped) {
|
|
213
|
+
if (skipped.length === 0) {
|
|
214
|
+
return "No codex candidates were found on PATH.";
|
|
215
|
+
}
|
|
216
|
+
const shown = skipped.slice(0, 8).map(({ candidate, reason }) => `- ${candidate} (${reason})`);
|
|
217
|
+
if (skipped.length > shown.length) {
|
|
218
|
+
shown.push(`- ... ${skipped.length - shown.length} more skipped candidates`);
|
|
219
|
+
}
|
|
220
|
+
return ["Searched PATH for external codex candidates:", ...shown].join("\n");
|
|
221
|
+
}
|
|
145
222
|
|
|
223
|
+
function resolveExternalCodexCommand() {
|
|
224
|
+
const skipped = [];
|
|
225
|
+
for (const candidate of externalCodexCandidates()) {
|
|
226
|
+
if (isSelfShim(candidate)) {
|
|
227
|
+
skipped.push({ candidate, reason: "Prodex Codex shim" });
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
if (!isExecutableFile(candidate)) {
|
|
231
|
+
skipped.push({ candidate, reason: "not executable" });
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
ok: true,
|
|
236
|
+
command: candidate,
|
|
237
|
+
args: process.argv.slice(2),
|
|
238
|
+
searched: skipped,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
146
241
|
return {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
242
|
+
ok: false,
|
|
243
|
+
reason: [
|
|
244
|
+
"No executable external codex was found on PATH.",
|
|
245
|
+
summarizeSkippedExternalCandidates(skipped),
|
|
246
|
+
].join("\n"),
|
|
247
|
+
searched: skipped,
|
|
150
248
|
};
|
|
151
249
|
}
|
|
152
250
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
process.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
251
|
+
|
|
252
|
+
function autoInstallCodexEnabled() {
|
|
253
|
+
return ["1", "true", "yes"].includes(
|
|
254
|
+
(process.env.PRODEX_CODEX_AUTO_INSTALL || "").toLowerCase(),
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function npmCommandNames() {
|
|
259
|
+
return commandNames("npm");
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function resolveNpmCommand() {
|
|
263
|
+
const skipped = [];
|
|
264
|
+
for (const dir of pathEntries()) {
|
|
265
|
+
for (const name of npmCommandNames()) {
|
|
266
|
+
const candidate = path.join(dir, name);
|
|
267
|
+
if (!isExecutableFile(candidate)) {
|
|
268
|
+
skipped.push({ candidate, reason: "not executable" });
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
return { ok: true, command: candidate, searched: skipped };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return { ok: false, reason: "No executable npm was found on PATH.", searched: skipped };
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function installExternalCodexWithNpm() {
|
|
278
|
+
if (!autoInstallCodexEnabled()) {
|
|
279
|
+
return { ok: false, reason: "PRODEX_CODEX_AUTO_INSTALL is not enabled." };
|
|
160
280
|
}
|
|
161
|
-
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
162
281
|
|
|
163
|
-
const
|
|
164
|
-
if (
|
|
282
|
+
const npmCommand = resolveNpmCommand();
|
|
283
|
+
if (!npmCommand.ok) {
|
|
284
|
+
return npmCommand;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
process.stderr.write(
|
|
288
|
+
[
|
|
289
|
+
"No executable external codex was found; attempting npm install because PRODEX_CODEX_AUTO_INSTALL=1.",
|
|
290
|
+
"Running: npm install -g @openai/codex@latest",
|
|
291
|
+
"",
|
|
292
|
+
].join("\n"),
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
const result = spawnSync(npmCommand.command, ["install", "-g", "@openai/codex@latest"], {
|
|
296
|
+
stdio: "inherit",
|
|
297
|
+
env: process.env,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
if (result.error) {
|
|
165
301
|
return {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
env: process.env,
|
|
302
|
+
ok: false,
|
|
303
|
+
reason: `npm install failed to start: ${result.error.message}`,
|
|
169
304
|
};
|
|
170
305
|
}
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
args: [path.resolve(packageRoot, candidate), ...process.argv.slice(2)],
|
|
177
|
-
env: process.env,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
306
|
+
if (result.status !== 0) {
|
|
307
|
+
return {
|
|
308
|
+
ok: false,
|
|
309
|
+
reason: `npm install exited with status ${result.status}`,
|
|
310
|
+
};
|
|
180
311
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
args: [path.resolve(packageRoot, "bin", "codex.js"), ...process.argv.slice(2)],
|
|
184
|
-
env: process.env,
|
|
185
|
-
};
|
|
312
|
+
|
|
313
|
+
return resolveExternalCodexCommand();
|
|
186
314
|
}
|
|
187
315
|
|
|
188
316
|
function resolveCodexCommand() {
|
|
189
|
-
|
|
190
|
-
|
|
317
|
+
const nativeCommand = resolveNativeCodexCommand();
|
|
318
|
+
if (nativeCommand.ok) {
|
|
319
|
+
return nativeCommand;
|
|
320
|
+
}
|
|
191
321
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
322
|
+
let externalCommand = resolveExternalCodexCommand();
|
|
323
|
+
if (!externalCommand.ok && autoInstallCodexEnabled()) {
|
|
324
|
+
const installCommand = installExternalCodexWithNpm();
|
|
325
|
+
if (installCommand.ok) {
|
|
326
|
+
externalCommand = installCommand;
|
|
327
|
+
} else {
|
|
328
|
+
externalCommand = {
|
|
329
|
+
...externalCommand,
|
|
330
|
+
reason: [externalCommand.reason, installCommand.reason].filter(Boolean).join("\n"),
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
}
|
|
197
334
|
|
|
198
|
-
|
|
199
|
-
if (error && error.code === "EACCES") {
|
|
335
|
+
if (externalCommand.ok) {
|
|
200
336
|
process.stderr.write(
|
|
201
|
-
|
|
337
|
+
[
|
|
338
|
+
"Bundled Codex is unavailable; falling back to external codex from PATH.",
|
|
339
|
+
nativeCommand.reason,
|
|
340
|
+
summarizeSkippedExternalCandidates(externalCommand.searched || []),
|
|
341
|
+
`External codex: ${externalCommand.command}`,
|
|
342
|
+
"Set PRODEX_CODEX_BIN to pin a specific Codex executable.",
|
|
343
|
+
"",
|
|
344
|
+
].join("\n"),
|
|
202
345
|
);
|
|
203
|
-
|
|
204
|
-
process.stderr.write(`${error.message}\n`);
|
|
346
|
+
return externalCommand;
|
|
205
347
|
}
|
|
348
|
+
|
|
349
|
+
process.stderr.write(
|
|
350
|
+
[
|
|
351
|
+
nativeCommand.reason || "Unable to locate bundled Codex native package for this platform.",
|
|
352
|
+
"Reinstall @christiandoxa/prodex with optional dependencies enabled, set PRODEX_CODEX_BIN to an existing Codex CLI, or set PRODEX_CODEX_AUTO_INSTALL=1 to let Prodex run npm install -g @openai/codex@latest.",
|
|
353
|
+
"Prodex does not fall back to @openai/codex/bin/codex.js because npm/Node version skew can make Codex load the wrong optional native package.",
|
|
354
|
+
externalCommand.reason,
|
|
355
|
+
"",
|
|
356
|
+
].join("\n"),
|
|
357
|
+
);
|
|
206
358
|
process.exit(1);
|
|
207
|
-
}
|
|
359
|
+
}
|
|
208
360
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
361
|
+
function spawnCodex(codexCommand, retriedExternalFallback = false) {
|
|
362
|
+
const child = spawn(codexCommand.command, codexCommand.args, {
|
|
363
|
+
stdio: "inherit",
|
|
364
|
+
env: {
|
|
365
|
+
...process.env,
|
|
366
|
+
...(codexCommand.env || {}),
|
|
367
|
+
},
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
child.on("error", (error) => {
|
|
371
|
+
if (error && error.code === "EACCES" && !retriedExternalFallback) {
|
|
372
|
+
let externalCommand = resolveExternalCodexCommand();
|
|
373
|
+
if (!externalCommand.ok && autoInstallCodexEnabled()) {
|
|
374
|
+
const installCommand = installExternalCodexWithNpm();
|
|
375
|
+
if (installCommand.ok) {
|
|
376
|
+
externalCommand = installCommand;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (externalCommand.ok && externalCommand.command !== codexCommand.command) {
|
|
380
|
+
process.stderr.write(
|
|
381
|
+
[
|
|
382
|
+
`${error.message}`,
|
|
383
|
+
"Bundled Codex could not be executed; falling back to external codex from PATH.",
|
|
384
|
+
summarizeSkippedExternalCandidates(externalCommand.searched || []),
|
|
385
|
+
`External codex: ${externalCommand.command}`,
|
|
386
|
+
"Set PRODEX_CODEX_BIN to pin a specific Codex executable.",
|
|
387
|
+
"",
|
|
388
|
+
].join("\n"),
|
|
389
|
+
);
|
|
390
|
+
spawnCodex(externalCommand, true);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (error && error.code === "EACCES") {
|
|
396
|
+
process.stderr.write(
|
|
397
|
+
`${error.message}\nSet PRODEX_CODEX_BIN to an existing Codex CLI, set PRODEX_CODEX_AUTO_INSTALL=1 to let Prodex run npm install -g @openai/codex@latest, or reinstall @christiandoxa/prodex.\n`,
|
|
398
|
+
);
|
|
399
|
+
process.exit(126);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
process.stderr.write(`${error && error.message ? error.message : String(error)}\n`);
|
|
404
|
+
process.exit(1);
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
child.on("exit", (code, signal) => {
|
|
408
|
+
if (signal) {
|
|
409
|
+
process.kill(process.pid, signal);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
process.exit(code ?? 1);
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
spawnCodex(resolveCodexCommand());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@christiandoxa/prodex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.214.0",
|
|
4
4
|
"description": "Multi-provider Codex wrapper with OpenAI quota-aware routing and Claude Code support",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
@@ -16,12 +16,12 @@
|
|
|
16
16
|
"@openai/codex": "latest"
|
|
17
17
|
},
|
|
18
18
|
"optionalDependencies": {
|
|
19
|
-
"@christiandoxa/prodex-linux-x64": "0.
|
|
20
|
-
"@christiandoxa/prodex-linux-arm64": "0.
|
|
21
|
-
"@christiandoxa/prodex-darwin-x64": "0.
|
|
22
|
-
"@christiandoxa/prodex-darwin-arm64": "0.
|
|
23
|
-
"@christiandoxa/prodex-win32-x64": "0.
|
|
24
|
-
"@christiandoxa/prodex-win32-arm64": "0.
|
|
19
|
+
"@christiandoxa/prodex-linux-x64": "0.214.0",
|
|
20
|
+
"@christiandoxa/prodex-linux-arm64": "0.214.0",
|
|
21
|
+
"@christiandoxa/prodex-darwin-x64": "0.214.0",
|
|
22
|
+
"@christiandoxa/prodex-darwin-arm64": "0.214.0",
|
|
23
|
+
"@christiandoxa/prodex-win32-x64": "0.214.0",
|
|
24
|
+
"@christiandoxa/prodex-win32-arm64": "0.214.0",
|
|
25
25
|
"@openai/codex-linux-x64": "npm:@openai/codex@linux-x64",
|
|
26
26
|
"@openai/codex-linux-arm64": "npm:@openai/codex@linux-arm64",
|
|
27
27
|
"@openai/codex-darwin-x64": "npm:@openai/codex@darwin-x64",
|