@christiandoxa/prodex 0.190.0 → 0.192.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 +27 -3
- package/lib/codex-shim.cjs +107 -27
- package/package.json +13 -7
package/README.md
CHANGED
|
@@ -41,6 +41,9 @@ If you only use one Codex account and do not need quota rotation, you probably d
|
|
|
41
41
|
|
|
42
42
|
You need at least one logged-in Prodex profile.
|
|
43
43
|
|
|
44
|
+
<details>
|
|
45
|
+
<summary>Tool requirements</summary>
|
|
46
|
+
|
|
44
47
|
| Tool | Used by |
|
|
45
48
|
|---|---|
|
|
46
49
|
| Codex CLI | `prodex`, `prodex run`, `prodex caveman`, `prodex super` |
|
|
@@ -48,6 +51,8 @@ You need at least one logged-in Prodex profile.
|
|
|
48
51
|
| Claude-Mem | `mem` variants |
|
|
49
52
|
| RTK | `rtk` variants and `prodex s` / `prodex super` |
|
|
50
53
|
|
|
54
|
+
</details>
|
|
55
|
+
|
|
51
56
|
## Supported providers
|
|
52
57
|
|
|
53
58
|
Prodex supports two provider paths:
|
|
@@ -55,6 +60,9 @@ Prodex supports two provider paths:
|
|
|
55
60
|
- **Profile-backed routing**: persisted profiles that Prodex can select, rotate, and inspect where provider APIs allow it.
|
|
56
61
|
- **Runtime provider launch**: `prodex s gemini`, `prodex s deepseek`, or `prodex s --provider ...` starts Codex with a temporary provider bridge for that session.
|
|
57
62
|
|
|
63
|
+
<details>
|
|
64
|
+
<summary>Supported provider matrix</summary>
|
|
65
|
+
|
|
58
66
|
| Provider | Launch to Codex | Auth path | Quota view | Notes |
|
|
59
67
|
|---|---:|---|---:|---|
|
|
60
68
|
| OpenAI / Codex | `prodex`, `prodex run`, `prodex s` | ChatGPT OAuth, device code, or OpenAI/API-compatible key via `prodex login` | Yes | Full quota preflight and profile auto-rotation. |
|
|
@@ -65,8 +73,13 @@ Prodex supports two provider paths:
|
|
|
65
73
|
| Local OpenAI-compatible | `prodex super --url http://127.0.0.1:8131` | Local server auth/config | Health snapshot | `prodex quota --all --provider local --base-url ...` checks the local `/models` endpoint. |
|
|
66
74
|
| Bedrock / custom Codex `model_provider` | `prodex run` / `prodex caveman` direct pass-through | Codex-owned config | Config snapshot | Prodex reports configured provider metadata; provider-side quota stays owned by Codex/upstream. |
|
|
67
75
|
|
|
76
|
+
</details>
|
|
77
|
+
|
|
68
78
|
`prodex gateway` exposes the provider bridge as a standalone OpenAI-compatible service for non-Codex clients:
|
|
69
79
|
|
|
80
|
+
<details>
|
|
81
|
+
<summary>Gateway quickstart</summary>
|
|
82
|
+
|
|
70
83
|
```bash
|
|
71
84
|
PRODEX_GATEWAY_TOKEN=change-me GEMINI_API_KEY=... prodex gateway --provider gemini
|
|
72
85
|
auth_header="Authorization: Bearer $PRODEX_GATEWAY_TOKEN"
|
|
@@ -76,10 +89,17 @@ curl http://127.0.0.1:4000/v1/responses \
|
|
|
76
89
|
-d '{"model":"prodex-fast","input":"hello"}'
|
|
77
90
|
```
|
|
78
91
|
|
|
79
|
-
|
|
92
|
+
</details>
|
|
93
|
+
|
|
94
|
+
<details>
|
|
95
|
+
<summary>Gateway capabilities</summary>
|
|
96
|
+
|
|
97
|
+
The gateway serves `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, `/v1/images/*`, `/v1/audio/*`, `/v1/batches`, `/v1/rerank`, `/v1/a2a`, `/v1/messages`, and `/v1/models` where the selected upstream supports them. It adds `x-prodex-call-id` to responses, writes local request detail plus `gateway_spend` events for both `request` and `response` phases to runtime logs, can export those events to JSONL or HTTP using generic, OTel, Datadog, or Langfuse-shaped payloads, supports catalog-backed policy routing strategies (`fallback`, `round-robin`, `least-busy`, `lowest-cost`, `lowest-latency`, `rpm`, `tpm`, `first`) for model aliases/fallback chains, can enforce static virtual keys with persisted request/spend usage plus model/budget/RPM/TPM limits, supports file, SQLite, Postgres, or Redis-backed gateway admin/usage/ledger/SCIM state, and can apply keyword/model, local PII redaction, Presidio, and external webhook guardrails before calls and on outputs. Admin-token, trusted-proxy SSO, or OIDC/JWT bearer requests can list usage, create generated-token keys, rotate/disable/update/delete admin-managed keys, provision SSO users through SCIM-compatible `/v1/prodex/gateway/scim/v2/Users`, inspect usage at `/v1/prodex/gateway/keys` and `/v1/prodex/gateway/usage`, read recent billing ledger records with response-status/output-token reconciliation at `/v1/prodex/gateway/ledger`, read aggregated billing totals at `/v1/prodex/gateway/ledger/summary`, export billing CSV from `/v1/prodex/gateway/ledger.csv` and `/v1/prodex/gateway/ledger/summary.csv`, scrape Prometheus text metrics at `/v1/prodex/gateway/metrics`, inspect provider adapter contracts at `/v1/prodex/gateway/providers`, inspect active observability and guardrail configuration at `/v1/prodex/gateway/observability` and `/v1/prodex/gateway/guardrails`, fetch the machine-readable gateway contract at `/v1/prodex/gateway/openapi.json`, and open the built-in gateway admin dashboard at `/v1/prodex/gateway/admin`; policy/env-backed keys remain read-only, SCIM users can carry tenant/team/project/user/budget scopes for SSO/OIDC fallback, admin-managed key and SCIM user mutations are recorded in `prodex audit`, and additional admin-plane tokens can be `admin` or read-only `viewer` with optional virtual-key prefix plus tenant/team/project/user/budget scopes. Configure defaults under `[gateway]` in `policy.toml`; validate provider catalog edits with `npm run catalog:providers`.
|
|
80
98
|
|
|
81
99
|
JavaScript clients can use `@christiandoxa/prodex-gateway-sdk` for `/v1/responses` plus gateway key, usage, billing ledger, metrics, and OpenAPI admin calls.
|
|
82
100
|
|
|
101
|
+
</details>
|
|
102
|
+
|
|
83
103
|
<details>
|
|
84
104
|
<summary>Provider behavior details</summary>
|
|
85
105
|
|
|
@@ -550,10 +570,14 @@ Use `prodex s expose` when you need to reach the live Super terminal from a brow
|
|
|
550
570
|
|
|
551
571
|
Super's built-in optimization stack is deliberately local and deterministic. It preloads the existing Caveman and Claude-Mem pieces, exposes an overlay `rtk` wrapper plus RTK auto-wrappers for common noisy commands when RTK is installed, auto-registers `sqz-mcp` and `token-savior` MCP servers when those binaries are already on `PATH` or in a managed `prodex-optimizers` checkout, exposes `sqz` and `claw-compactor` wrappers when those commands/checkouts are discoverable, invokes a trusted one-shot `prodex-claw-compactor-sessionstart` SessionStart benchmark probe when Claw-Compactor is available, falls back to a temporary shadow `MEMORY.md` when the workspace has no Markdown memory files, then uses Smart Context Autopilot through a dedicated runtime proxy for lower-token request shaping. The probe delegates to `prodex-claw-compactor-auto "$(pwd)"` and uses a marker under `CODEX_HOME` so Codex conversation restarts do not replay it. Presidio redaction is added to that proxy only when you opt in at the prompt. Prodex passes token-savior cache and stats paths under `PRODEX_HOME` (default `~/.prodex`) so compatible token-savior versions keep generated state out of worktrees.
|
|
552
572
|
|
|
553
|
-
|
|
573
|
+
Super instructs Codex to use the whole local optimizer stack where it fits the task, not just RTK:
|
|
554
574
|
|
|
575
|
+
- Claude-Mem handles prior-session/project recall through the active Prodex session watch.
|
|
555
576
|
- RTK works upstream/input-side. Use visible `rtk <cmd>` for noisy terminal commands before their output enters the model context, such as `git diff`, `cargo test`, `npm test`, build logs, and package-manager output. Prodex also auto-wraps common noisy commands as a fallback when RTK is installed, but that fallback does not make the TUI show an `rtk` prefix.
|
|
556
|
-
- SQZ works downstream/context-side through the auto-registered `prodex-sqz` MCP server. Use it for repeated workspace reads, large text blobs, and long-session context
|
|
577
|
+
- SQZ works downstream/context-side through the auto-registered `prodex-sqz` MCP server. Use it for repeated workspace reads, large text blobs, long command outputs that need reuse, and long-session context compression instead of emitting the same full content again.
|
|
578
|
+
- token-savior handles symbol lookup, caller/context navigation, duplicate/dead-code checks, and API-impact searches before broad source reads.
|
|
579
|
+
- claw-compactor handles workspace-level summary or benchmark requests through `prodex-claw-compactor` / `prodex-claw-compactor-auto`; treat its output as overview context and reread exact source before edits.
|
|
580
|
+
- Presidio stays optional and only runs when you opt in with the Super prompt or `--presidio`.
|
|
557
581
|
|
|
558
582
|
Managed optimizer checkouts are discovered from `PRODEX_OPTIMIZERS_HOME`, `$XDG_DATA_HOME/prodex-optimizers`, then `~/.local/share/prodex-optimizers`.
|
|
559
583
|
|
package/lib/codex-shim.cjs
CHANGED
|
@@ -47,41 +47,81 @@ const PLATFORM_TARGETS = {
|
|
|
47
47
|
},
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
function
|
|
50
|
+
function currentPlatformTarget() {
|
|
51
|
+
return PLATFORM_TARGETS[process.platform]?.[process.arch] ?? null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function resolveOpenAiCodexPackageRoot() {
|
|
51
55
|
let packageJsonPath;
|
|
52
56
|
try {
|
|
53
57
|
packageJsonPath = requireFromHere.resolve("@openai/codex/package.json");
|
|
58
|
+
} catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return path.dirname(packageJsonPath);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function codexManagedEnv() {
|
|
65
|
+
const packageRoot = resolveOpenAiCodexPackageRoot();
|
|
66
|
+
if (!packageRoot) {
|
|
67
|
+
return process.env;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
...process.env,
|
|
71
|
+
CODEX_MANAGED_BY_NPM: "1",
|
|
72
|
+
CODEX_MANAGED_PACKAGE_ROOT: fs.realpathSync(packageRoot),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function ensureNativeCodexExecutable(nativeBinaryPath) {
|
|
77
|
+
try {
|
|
78
|
+
fs.accessSync(nativeBinaryPath, fs.constants.X_OK);
|
|
79
|
+
return;
|
|
80
|
+
} catch {
|
|
81
|
+
repairNativeCodexExecutablePermissionBestEffort(nativeBinaryPath);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
fs.accessSync(nativeBinaryPath, fs.constants.X_OK);
|
|
86
|
+
return;
|
|
54
87
|
} catch {
|
|
55
88
|
process.stderr.write(
|
|
56
|
-
|
|
89
|
+
[
|
|
90
|
+
`Bundled Codex native binary is not executable: ${nativeBinaryPath}`,
|
|
91
|
+
"Reinstall @christiandoxa/prodex with optional dependencies enabled, or set PRODEX_CODEX_BIN to an existing Codex CLI.",
|
|
92
|
+
"",
|
|
93
|
+
].join("\n"),
|
|
57
94
|
);
|
|
58
|
-
process.exit(
|
|
95
|
+
process.exit(126);
|
|
59
96
|
}
|
|
97
|
+
}
|
|
60
98
|
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
return
|
|
99
|
+
function repairNativeCodexExecutablePermissionBestEffort(nativeBinaryPath) {
|
|
100
|
+
if (process.platform === "win32") {
|
|
101
|
+
return;
|
|
64
102
|
}
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
if (
|
|
68
|
-
return
|
|
103
|
+
try {
|
|
104
|
+
const stats = fs.statSync(nativeBinaryPath);
|
|
105
|
+
if (!stats.isFile()) {
|
|
106
|
+
return;
|
|
69
107
|
}
|
|
108
|
+
fs.chmodSync(nativeBinaryPath, (stats.mode & 0o777) | 0o755);
|
|
109
|
+
} catch {
|
|
110
|
+
// The explicit executable check below reports the actionable failure.
|
|
70
111
|
}
|
|
71
|
-
return path.resolve(path.dirname(packageJsonPath), "bin", "codex.js");
|
|
72
112
|
}
|
|
73
113
|
|
|
74
|
-
function
|
|
75
|
-
const platformTarget =
|
|
76
|
-
if (!platformTarget
|
|
77
|
-
return;
|
|
114
|
+
function resolveNativeCodexCommand() {
|
|
115
|
+
const platformTarget = currentPlatformTarget();
|
|
116
|
+
if (!platformTarget) {
|
|
117
|
+
return null;
|
|
78
118
|
}
|
|
79
119
|
|
|
80
120
|
let platformPackageJsonPath;
|
|
81
121
|
try {
|
|
82
122
|
platformPackageJsonPath = requireFromHere.resolve(`${platformTarget.packageName}/package.json`);
|
|
83
123
|
} catch {
|
|
84
|
-
return;
|
|
124
|
+
return null;
|
|
85
125
|
}
|
|
86
126
|
|
|
87
127
|
const nativeBinaryPath = path.join(
|
|
@@ -92,26 +132,66 @@ function explainBundledNativeCodexPermissionIssue() {
|
|
|
92
132
|
platformTarget.binaryFileName,
|
|
93
133
|
);
|
|
94
134
|
if (!fs.existsSync(nativeBinaryPath)) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
try {
|
|
98
|
-
fs.accessSync(nativeBinaryPath, fs.constants.X_OK);
|
|
99
|
-
} catch {
|
|
100
135
|
process.stderr.write(
|
|
101
136
|
[
|
|
102
|
-
`
|
|
137
|
+
`Missing bundled Codex native binary at ${nativeBinaryPath}`,
|
|
103
138
|
"Reinstall @christiandoxa/prodex with optional dependencies enabled, or set PRODEX_CODEX_BIN to an existing Codex CLI.",
|
|
104
139
|
"",
|
|
105
140
|
].join("\n"),
|
|
106
141
|
);
|
|
107
|
-
process.exit(
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
ensureNativeCodexExecutable(nativeBinaryPath);
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
command: nativeBinaryPath,
|
|
148
|
+
args: process.argv.slice(2),
|
|
149
|
+
env: codexManagedEnv(),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function resolveCodexJsCommand() {
|
|
154
|
+
const packageRoot = resolveOpenAiCodexPackageRoot();
|
|
155
|
+
if (!packageRoot) {
|
|
156
|
+
process.stderr.write(
|
|
157
|
+
"Unable to locate @openai/codex. Reinstall @christiandoxa/prodex so its runtime dependency is present.\n",
|
|
158
|
+
);
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
162
|
+
|
|
163
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
164
|
+
if (typeof packageJson.bin === "string") {
|
|
165
|
+
return {
|
|
166
|
+
command: process.execPath,
|
|
167
|
+
args: [path.resolve(packageRoot, packageJson.bin), ...process.argv.slice(2)],
|
|
168
|
+
env: process.env,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (packageJson.bin && typeof packageJson.bin === "object") {
|
|
172
|
+
const candidate = packageJson.bin.codex ?? Object.values(packageJson.bin)[0];
|
|
173
|
+
if (typeof candidate === "string") {
|
|
174
|
+
return {
|
|
175
|
+
command: process.execPath,
|
|
176
|
+
args: [path.resolve(packageRoot, candidate), ...process.argv.slice(2)],
|
|
177
|
+
env: process.env,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
108
180
|
}
|
|
181
|
+
return {
|
|
182
|
+
command: process.execPath,
|
|
183
|
+
args: [path.resolve(packageRoot, "bin", "codex.js"), ...process.argv.slice(2)],
|
|
184
|
+
env: process.env,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function resolveCodexCommand() {
|
|
189
|
+
return resolveNativeCodexCommand() ?? resolveCodexJsCommand();
|
|
109
190
|
}
|
|
110
191
|
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
env: process.env,
|
|
192
|
+
const codexCommand = resolveCodexCommand();
|
|
193
|
+
const child = spawn(codexCommand.command, codexCommand.args, {
|
|
194
|
+
env: codexCommand.env,
|
|
115
195
|
stdio: "inherit",
|
|
116
196
|
});
|
|
117
197
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@christiandoxa/prodex",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.192.0",
|
|
4
4
|
"description": "Safe multi-account auto-rotate for Codex CLI with isolated CODEX_HOME profiles",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
@@ -16,12 +16,18 @@
|
|
|
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.192.0",
|
|
20
|
+
"@christiandoxa/prodex-linux-arm64": "0.192.0",
|
|
21
|
+
"@christiandoxa/prodex-darwin-x64": "0.192.0",
|
|
22
|
+
"@christiandoxa/prodex-darwin-arm64": "0.192.0",
|
|
23
|
+
"@christiandoxa/prodex-win32-x64": "0.192.0",
|
|
24
|
+
"@christiandoxa/prodex-win32-arm64": "0.192.0",
|
|
25
|
+
"@openai/codex-linux-x64": "npm:@openai/codex@linux-x64",
|
|
26
|
+
"@openai/codex-linux-arm64": "npm:@openai/codex@linux-arm64",
|
|
27
|
+
"@openai/codex-darwin-x64": "npm:@openai/codex@darwin-x64",
|
|
28
|
+
"@openai/codex-darwin-arm64": "npm:@openai/codex@darwin-arm64",
|
|
29
|
+
"@openai/codex-win32-x64": "npm:@openai/codex@win32-x64",
|
|
30
|
+
"@openai/codex-win32-arm64": "npm:@openai/codex@win32-arm64"
|
|
25
31
|
},
|
|
26
32
|
"engines": {
|
|
27
33
|
"node": ">=18"
|