codex-multi-auth 2.0.2 → 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 +17 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/account-policy.d.ts +22 -0
- package/dist/lib/account-policy.d.ts.map +1 -0
- package/dist/lib/account-policy.js +159 -0
- package/dist/lib/account-policy.js.map +1 -0
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +2 -1
- package/dist/lib/accounts.js.map +1 -1
- package/dist/lib/budget-guard.d.ts +39 -0
- package/dist/lib/budget-guard.d.ts.map +1 -0
- package/dist/lib/budget-guard.js +201 -0
- package/dist/lib/budget-guard.js.map +1 -0
- package/dist/lib/codex-manager/commands/account.d.ts +13 -0
- package/dist/lib/codex-manager/commands/account.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/account.js +156 -0
- package/dist/lib/codex-manager/commands/account.js.map +1 -0
- package/dist/lib/codex-manager/commands/bridge.d.ts +6 -0
- package/dist/lib/codex-manager/commands/bridge.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/bridge.js +167 -0
- package/dist/lib/codex-manager/commands/bridge.js.map +1 -0
- package/dist/lib/codex-manager/commands/budget.d.ts +12 -0
- package/dist/lib/codex-manager/commands/budget.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/budget.js +123 -0
- package/dist/lib/codex-manager/commands/budget.js.map +1 -0
- package/dist/lib/codex-manager/commands/integrations.d.ts +6 -0
- package/dist/lib/codex-manager/commands/integrations.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/integrations.js +78 -0
- package/dist/lib/codex-manager/commands/integrations.js.map +1 -0
- package/dist/lib/codex-manager/commands/models.d.ts +14 -0
- package/dist/lib/codex-manager/commands/models.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/models.js +74 -0
- package/dist/lib/codex-manager/commands/models.js.map +1 -0
- package/dist/lib/codex-manager/commands/monitor.d.ts +22 -0
- package/dist/lib/codex-manager/commands/monitor.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/monitor.js +94 -0
- package/dist/lib/codex-manager/commands/monitor.js.map +1 -0
- package/dist/lib/codex-manager/commands/rotation.d.ts +1 -0
- package/dist/lib/codex-manager/commands/rotation.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/rotation.js +293 -10
- package/dist/lib/codex-manager/commands/rotation.js.map +1 -1
- package/dist/lib/codex-manager/commands/usage.d.ts +13 -0
- package/dist/lib/codex-manager/commands/usage.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/usage.js +347 -0
- package/dist/lib/codex-manager/commands/usage.js.map +1 -0
- package/dist/lib/codex-manager/help.d.ts.map +1 -1
- package/dist/lib/codex-manager/help.js +8 -0
- package/dist/lib/codex-manager/help.js.map +1 -1
- package/dist/lib/codex-manager.d.ts.map +1 -1
- package/dist/lib/codex-manager.js +42 -2
- package/dist/lib/codex-manager.js.map +1 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +2 -22
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +1 -0
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/env-parsing.d.ts +21 -0
- package/dist/lib/env-parsing.d.ts.map +1 -0
- package/dist/lib/env-parsing.js +34 -0
- package/dist/lib/env-parsing.js.map +1 -0
- package/dist/lib/index.d.ts +9 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/integration-generators.d.ts +14 -0
- package/dist/lib/integration-generators.d.ts.map +1 -0
- package/dist/lib/integration-generators.js +93 -0
- package/dist/lib/integration-generators.js.map +1 -0
- package/dist/lib/local-bridge.d.ts +17 -0
- package/dist/lib/local-bridge.d.ts.map +1 -0
- package/dist/lib/local-bridge.js +249 -0
- package/dist/lib/local-bridge.js.map +1 -0
- package/dist/lib/local-client-tokens.d.ts +37 -0
- package/dist/lib/local-client-tokens.d.ts.map +1 -0
- package/dist/lib/local-client-tokens.js +200 -0
- package/dist/lib/local-client-tokens.js.map +1 -0
- package/dist/lib/model-capability-matrix.d.ts +38 -0
- package/dist/lib/model-capability-matrix.d.ts.map +1 -0
- package/dist/lib/model-capability-matrix.js +89 -0
- package/dist/lib/model-capability-matrix.js.map +1 -0
- package/dist/lib/policy/runtime-policy.d.ts +59 -0
- package/dist/lib/policy/runtime-policy.d.ts.map +1 -0
- package/dist/lib/policy/runtime-policy.js +156 -0
- package/dist/lib/policy/runtime-policy.js.map +1 -0
- package/dist/lib/proactive-refresh.js +4 -4
- package/dist/lib/proactive-refresh.js.map +1 -1
- package/dist/lib/refresh-lease.d.ts.map +1 -1
- package/dist/lib/refresh-lease.js +1 -10
- package/dist/lib/refresh-lease.js.map +1 -1
- package/dist/lib/routing-profiles.d.ts +36 -0
- package/dist/lib/routing-profiles.d.ts.map +1 -0
- package/dist/lib/routing-profiles.js +203 -0
- package/dist/lib/routing-profiles.js.map +1 -0
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +96 -6
- package/dist/lib/runtime-rotation-proxy.js.map +1 -1
- package/dist/lib/usage/index.d.ts +5 -0
- package/dist/lib/usage/index.d.ts.map +1 -0
- package/dist/lib/usage/index.js +5 -0
- package/dist/lib/usage/index.js.map +1 -0
- package/dist/lib/usage/ledger.d.ts +12 -0
- package/dist/lib/usage/ledger.d.ts.map +1 -0
- package/dist/lib/usage/ledger.js +493 -0
- package/dist/lib/usage/ledger.js.map +1 -0
- package/dist/lib/usage/pricing.d.ts +11 -0
- package/dist/lib/usage/pricing.d.ts.map +1 -0
- package/dist/lib/usage/pricing.js +67 -0
- package/dist/lib/usage/pricing.js.map +1 -0
- package/dist/lib/usage/redaction.d.ts +10 -0
- package/dist/lib/usage/redaction.d.ts.map +1 -0
- package/dist/lib/usage/redaction.js +129 -0
- package/dist/lib/usage/redaction.js.map +1 -0
- package/dist/lib/usage/types.d.ts +89 -0
- package/dist/lib/usage/types.d.ts.map +1 -0
- package/dist/lib/usage/types.js +2 -0
- package/dist/lib/usage/types.js.map +1 -0
- package/package.json +1 -1
- package/scripts/codex-routing.js +19 -12
package/README.md
CHANGED
|
@@ -22,8 +22,10 @@ Codex CLI-first multi-account OAuth manager for the official Codex CLI. The inst
|
|
|
22
22
|
- Interactive dashboard for account actions and settings
|
|
23
23
|
- Experimental settings tab for staged sync, backup, and refresh-guard controls
|
|
24
24
|
- Forecast, report, fix, and doctor commands for operational safety
|
|
25
|
+
- Local usage ledger, budgets, account policy controls, routing profiles, and monitor views for local governance
|
|
25
26
|
- Runtime counters, budget/cooldown state, and multi-auth probe visibility in `codex auth status` / `codex auth report`
|
|
26
27
|
- Default-on runtime Responses proxy for live account rotation inside forwarded Codex CLI/app sessions
|
|
28
|
+
- Optional loopback-only local bridge for `/health`, `/v1/models`, and `/v1/responses`, protected by hashed local client tokens
|
|
27
29
|
- Reversible packaged Codex app bind and user-level launcher routing helpers
|
|
28
30
|
- Flagged account verification and restore flow
|
|
29
31
|
- Session affinity and live account sync controls
|
|
@@ -173,6 +175,10 @@ For remote or headless shells, prefer `codex auth login --device-auth`.
|
|
|
173
175
|
| `codex auth report --live --json` | How do I get the full machine-readable health report? |
|
|
174
176
|
| `codex auth fix --live --model gpt-5.3-codex` | How do I run live repair probes with a chosen model? |
|
|
175
177
|
| `codex auth why-selected --json` | Which account does the selector pick now, and why? |
|
|
178
|
+
| `codex auth usage --since 24h --by project` | What local usage has been recorded recently? |
|
|
179
|
+
| `codex auth monitor --json` | What is the combined usage, policy, quota, runtime, and project state? |
|
|
180
|
+
| `codex auth bridge token create --label local-client` | How do I create a local bridge bearer token? |
|
|
181
|
+
| `codex auth integrations --kind python` | How do I generate local bridge client snippets? |
|
|
176
182
|
| `codex auth rotation status` | Is live runtime account rotation enabled for forwarded Codex sessions? |
|
|
177
183
|
|
|
178
184
|
### Reliability behavior
|
|
@@ -216,8 +222,13 @@ For remote or headless shells, prefer `codex auth login --device-auth`.
|
|
|
216
222
|
| Settings | `~/.codex/multi-auth/settings.json` |
|
|
217
223
|
| Accounts | `~/.codex/multi-auth/openai-codex-accounts.json` |
|
|
218
224
|
| Flagged accounts | `~/.codex/multi-auth/openai-codex-flagged-accounts.json` |
|
|
219
|
-
| Quota cache | `~/.codex/multi-auth/quota-cache.json` |
|
|
225
|
+
| Quota cache | `~/.codex/multi-auth/quota-cache.json` |
|
|
220
226
|
| Runtime observability | `~/.codex/multi-auth/runtime-observability.json` |
|
|
227
|
+
| Usage ledger | `~/.codex/multi-auth/usage/usage-ledger.jsonl` |
|
|
228
|
+
| Account policies | `~/.codex/multi-auth/account-policies.json` |
|
|
229
|
+
| Routing profiles | `~/.codex/multi-auth/routing-profiles.json` |
|
|
230
|
+
| Budget guards | `~/.codex/multi-auth/budget-guards.json` |
|
|
231
|
+
| Local client tokens | `~/.codex/multi-auth/local-client-tokens.json` |
|
|
221
232
|
| Runtime app helper status | `~/.codex/multi-auth/runtime-rotation-app-helper.json` |
|
|
222
233
|
| Persistent app bind state/logs | `~/.codex/multi-auth/app-bind/` |
|
|
223
234
|
| Logs | `~/.codex/multi-auth/logs/codex-plugin/` |
|
|
@@ -346,10 +357,11 @@ codex auth doctor --json
|
|
|
346
357
|
|
|
347
358
|
---
|
|
348
359
|
|
|
349
|
-
## Release Notes
|
|
350
|
-
|
|
351
|
-
- Current stable: [docs/releases/v2.
|
|
352
|
-
- Previous stable: [docs/releases/v2.0.
|
|
360
|
+
## Release Notes
|
|
361
|
+
|
|
362
|
+
- Current stable: [docs/releases/v2.1.1.md](docs/releases/v2.1.1.md)
|
|
363
|
+
- Previous stable: [docs/releases/v2.1.0.md](docs/releases/v2.1.0.md)
|
|
364
|
+
- Earlier stable: [docs/releases/v2.0.2.md](docs/releases/v2.0.2.md)
|
|
353
365
|
- Earlier stable: [docs/releases/v1.3.2.md](docs/releases/v1.3.2.md)
|
|
354
366
|
- Stable archive: [docs/releases/v1.3.1.md](docs/releases/v1.3.1.md)
|
|
355
367
|
- Full release archive: [docs/README.md#release-history](docs/README.md#release-history)
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,kBAAkB,CAAC;AA2V5D;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,iBAAiB,EAAE,MAquI/B,CAAC;AAEF,eAAO,MAAM,gBAAgB,KAAoB,CAAC;AAElD,eAAe,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ import { EntitlementCache, resolveEntitlementAccountKey, } from "./lib/entitleme
|
|
|
37
37
|
import { LiveAccountSync } from "./lib/live-account-sync.js";
|
|
38
38
|
import { clearCorrelationId, initLogger, logDebug, logError, logInfo, logRequest, logWarn, setCorrelationId, } from "./lib/logger.js";
|
|
39
39
|
import { PreemptiveQuotaScheduler, readQuotaSchedulerSnapshot, } from "./lib/preemptive-quota-scheduler.js";
|
|
40
|
+
import { createRuntimeUsageRecorder, evaluateRuntimePolicy, loadRuntimePolicyState, } from "./lib/policy/runtime-policy.js";
|
|
40
41
|
import { getModelFamily, MODEL_FAMILIES, prewarmCodexInstructions, } from "./lib/prompts/codex.js";
|
|
41
42
|
import { prewarmHostCodexPrompt } from "./lib/prompts/host-codex-prompt.js";
|
|
42
43
|
import { fetchCodexQuotaSnapshot, formatQuotaSnapshotLine, } from "./lib/quota-probe.js";
|
|
@@ -543,6 +544,8 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
|
|
|
543
544
|
* @returns Response from Codex API
|
|
544
545
|
*/
|
|
545
546
|
async fetch(input, init) {
|
|
547
|
+
let usageRecorder = null;
|
|
548
|
+
let usageCompletion = null;
|
|
546
549
|
try {
|
|
547
550
|
if (cachedAccountManager &&
|
|
548
551
|
cachedAccountManager !== accountManager) {
|
|
@@ -608,6 +611,59 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
|
|
|
608
611
|
const requestTraceId = requestCorrelationId;
|
|
609
612
|
runtimeMetrics.lastRequestAt = Date.now();
|
|
610
613
|
syncRuntimeObservability(requestTraceId);
|
|
614
|
+
let runtimePolicyDecision = null;
|
|
615
|
+
try {
|
|
616
|
+
const runtimePolicyState = await loadRuntimePolicyState();
|
|
617
|
+
runtimePolicyDecision = await evaluateRuntimePolicy({
|
|
618
|
+
state: runtimePolicyState,
|
|
619
|
+
accounts: accountManager.getAccountsSnapshot(),
|
|
620
|
+
model: model ?? null,
|
|
621
|
+
capabilityPolicy: capabilityPolicyStore,
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
catch (policyError) {
|
|
625
|
+
logWarn("Runtime policy evaluation failed open.", {
|
|
626
|
+
error: policyError instanceof Error
|
|
627
|
+
? policyError.message
|
|
628
|
+
: String(policyError),
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
usageRecorder = createRuntimeUsageRecorder({
|
|
632
|
+
source: "plugin-host",
|
|
633
|
+
operation: "responses",
|
|
634
|
+
model: model ?? null,
|
|
635
|
+
projectKey: runtimePolicyDecision?.projectKey ?? null,
|
|
636
|
+
requestId: requestTraceId,
|
|
637
|
+
startedAt: Date.now(),
|
|
638
|
+
});
|
|
639
|
+
usageCompletion = {
|
|
640
|
+
outcome: "failure",
|
|
641
|
+
statusCode: null,
|
|
642
|
+
errorCode: "plugin_host_request_failed",
|
|
643
|
+
};
|
|
644
|
+
if (runtimePolicyDecision && !runtimePolicyDecision.allowed) {
|
|
645
|
+
runtimeMetrics.failedRequests += 1;
|
|
646
|
+
runtimeMetrics.lastError = "Runtime policy blocked request";
|
|
647
|
+
syncRuntimeObservability(requestTraceId);
|
|
648
|
+
usageCompletion = {
|
|
649
|
+
outcome: "blocked",
|
|
650
|
+
statusCode: runtimePolicyDecision.statusCode,
|
|
651
|
+
errorCode: runtimePolicyDecision.errorCode,
|
|
652
|
+
};
|
|
653
|
+
return new Response(JSON.stringify({
|
|
654
|
+
error: {
|
|
655
|
+
message: "Runtime policy blocked this local request.",
|
|
656
|
+
code: runtimePolicyDecision.errorCode ??
|
|
657
|
+
"policy_blocked",
|
|
658
|
+
reasons: runtimePolicyDecision.reasons,
|
|
659
|
+
},
|
|
660
|
+
}), {
|
|
661
|
+
status: runtimePolicyDecision.statusCode,
|
|
662
|
+
headers: {
|
|
663
|
+
"content-type": "application/json; charset=utf-8",
|
|
664
|
+
},
|
|
665
|
+
});
|
|
666
|
+
}
|
|
611
667
|
const abortSignal = requestInit?.signal ?? init?.signal ?? null;
|
|
612
668
|
const sleep = createAbortableSleep(abortSignal);
|
|
613
669
|
const poolCooldownRemainingMs = getPoolExhaustionCooldownRemaining();
|
|
@@ -616,6 +672,11 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
|
|
|
616
672
|
runtimeMetrics.poolExhaustionFastFails += 1;
|
|
617
673
|
runtimeMetrics.lastError = "Pool exhaustion cooldown active";
|
|
618
674
|
syncRuntimeObservability(requestTraceId);
|
|
675
|
+
usageCompletion = {
|
|
676
|
+
outcome: "failure",
|
|
677
|
+
statusCode: 429,
|
|
678
|
+
errorCode: "pool_exhaustion_cooldown",
|
|
679
|
+
};
|
|
619
680
|
return new Response(JSON.stringify({
|
|
620
681
|
error: {
|
|
621
682
|
message: `The account pool is cooling down after recent rate-limit exhaustion. Try again in ${formatWaitTime(poolCooldownRemainingMs)} or inspect \`codex auth status\`.`,
|
|
@@ -633,6 +694,11 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
|
|
|
633
694
|
runtimeMetrics.serverBurstFastFails += 1;
|
|
634
695
|
runtimeMetrics.lastError = "Server burst cooldown active";
|
|
635
696
|
syncRuntimeObservability(requestTraceId);
|
|
697
|
+
usageCompletion = {
|
|
698
|
+
outcome: "failure",
|
|
699
|
+
statusCode: 503,
|
|
700
|
+
errorCode: "server_burst_cooldown",
|
|
701
|
+
};
|
|
636
702
|
return new Response(JSON.stringify({
|
|
637
703
|
error: {
|
|
638
704
|
message: `Multiple accounts recently failed with upstream server errors. Try again in ${formatWaitTime(serverBurstCooldownRemainingMs)} or inspect \`codex auth report --json\`.`,
|
|
@@ -713,12 +779,20 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
|
|
|
713
779
|
capabilityBoostByAccount[candidate.index] =
|
|
714
780
|
capabilityPolicyStore.getBoost(accountKey, model ?? modelFamily);
|
|
715
781
|
}
|
|
782
|
+
for (const [rawIndex, boost] of Object.entries(runtimePolicyDecision?.scoreBoostByAccount ?? {})) {
|
|
783
|
+
const index = Number(rawIndex);
|
|
784
|
+
if (!Number.isInteger(index))
|
|
785
|
+
continue;
|
|
786
|
+
capabilityBoostByAccount[index] =
|
|
787
|
+
(capabilityBoostByAccount[index] ?? 0) + boost;
|
|
788
|
+
}
|
|
716
789
|
accountAttemptLoop: while (attempted.size < Math.max(1, accountCount)) {
|
|
717
790
|
let account = null;
|
|
718
791
|
if (!usedPreferredSessionAccount &&
|
|
719
792
|
typeof preferredSessionAccountIndex === "number") {
|
|
720
793
|
usedPreferredSessionAccount = true;
|
|
721
|
-
if (accountManager.isAccountAvailableForFamily(preferredSessionAccountIndex, modelFamily, model)
|
|
794
|
+
if (accountManager.isAccountAvailableForFamily(preferredSessionAccountIndex, modelFamily, model) &&
|
|
795
|
+
!runtimePolicyDecision?.blockedAccountIndexes.has(preferredSessionAccountIndex)) {
|
|
722
796
|
account = accountManager.getAccountByIndex(preferredSessionAccountIndex);
|
|
723
797
|
if (account) {
|
|
724
798
|
account.lastUsed = Date.now();
|
|
@@ -739,6 +813,9 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
|
|
|
739
813
|
break;
|
|
740
814
|
}
|
|
741
815
|
attempted.add(account.index);
|
|
816
|
+
if (runtimePolicyDecision?.blockedAccountIndexes.has(account.index)) {
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
742
819
|
// Log account selection for debugging rotation
|
|
743
820
|
logDebug(`Using account ${account.index + 1}/${accountCount}: ${account.email ?? "unknown"} for ${modelFamily}`);
|
|
744
821
|
let accountAuth = accountManager.toAuthDetails(account);
|
|
@@ -1587,6 +1664,16 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
|
|
|
1587
1664
|
}
|
|
1588
1665
|
runtimeMetrics.successfulRequests++;
|
|
1589
1666
|
runtimeMetrics.lastError = null;
|
|
1667
|
+
usageCompletion = {
|
|
1668
|
+
outcome: "success",
|
|
1669
|
+
statusCode: successResponse.status,
|
|
1670
|
+
errorCode: null,
|
|
1671
|
+
account: {
|
|
1672
|
+
index: successAccountForResponse.index,
|
|
1673
|
+
accountId: successAccountForResponse.accountId ?? null,
|
|
1674
|
+
email: successAccountForResponse.email ?? null,
|
|
1675
|
+
},
|
|
1676
|
+
};
|
|
1590
1677
|
if (lastCodexCliActiveSyncIndex !==
|
|
1591
1678
|
successAccountForResponse.index) {
|
|
1592
1679
|
void accountManager.syncCodexCliActiveSelectionForIndex(successAccountForResponse.index);
|
|
@@ -1657,6 +1744,9 @@ export const OpenAIOAuthPlugin = async ({ client }) => {
|
|
|
1657
1744
|
}
|
|
1658
1745
|
}
|
|
1659
1746
|
finally {
|
|
1747
|
+
if (usageRecorder && usageCompletion) {
|
|
1748
|
+
await usageRecorder.record(usageCompletion);
|
|
1749
|
+
}
|
|
1660
1750
|
syncRuntimeObservability(null);
|
|
1661
1751
|
clearCorrelationId();
|
|
1662
1752
|
}
|