codex-multi-auth 2.16.0 → 2.17.2
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/.codex-plugin/plugin.json +9 -9
- package/LICENSE +21 -21
- package/README.md +487 -463
- package/assets/codex-multi-auth-icon.svg +39 -39
- package/assets/readme-hero.svg +31 -31
- package/config/README.md +31 -31
- package/config/codex-legacy.json +1221 -1221
- package/config/codex-modern.json +423 -423
- package/config/minimal-codex.json +15 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/lib/account-policy.d.ts +4 -0
- package/dist/lib/account-policy.d.ts.map +1 -1
- package/dist/lib/account-policy.js +8 -0
- package/dist/lib/accounts/rate-limits.d.ts.map +1 -1
- package/dist/lib/accounts/rate-limits.js +2 -0
- package/dist/lib/accounts.d.ts +15 -3
- package/dist/lib/accounts.d.ts.map +1 -1
- package/dist/lib/accounts.js +231 -30
- package/dist/lib/api-route-store.d.ts +24 -0
- package/dist/lib/api-route-store.d.ts.map +1 -0
- package/dist/lib/api-route-store.js +145 -0
- package/dist/lib/auth/account-access.d.ts +115 -0
- package/dist/lib/auth/account-access.d.ts.map +1 -0
- package/dist/lib/auth/account-access.js +214 -0
- package/dist/lib/auth/token-utils.d.ts +54 -1
- package/dist/lib/auth/token-utils.d.ts.map +1 -1
- package/dist/lib/auth/token-utils.js +92 -7
- package/dist/lib/cli.d.ts +1 -1
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +4 -0
- package/dist/lib/codex-cli/state.d.ts +7 -0
- package/dist/lib/codex-cli/state.d.ts.map +1 -1
- package/dist/lib/codex-cli/state.js +18 -0
- package/dist/lib/codex-cli/writer.d.ts.map +1 -1
- package/dist/lib/codex-cli/writer.js +60 -8
- package/dist/lib/codex-manager/account-manager-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/account-manager-commands.js +1 -0
- package/dist/lib/codex-manager/account-pool-write.d.ts +3 -1
- package/dist/lib/codex-manager/account-pool-write.d.ts.map +1 -1
- package/dist/lib/codex-manager/account-pool-write.js +4 -0
- package/dist/lib/codex-manager/api-login-menu.d.ts +14 -0
- package/dist/lib/codex-manager/api-login-menu.d.ts.map +1 -0
- package/dist/lib/codex-manager/api-login-menu.js +224 -0
- package/dist/lib/codex-manager/commands/account.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/account.js +27 -0
- package/dist/lib/codex-manager/commands/best.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/best.js +6 -2
- package/dist/lib/codex-manager/commands/check.d.ts +7 -1
- package/dist/lib/codex-manager/commands/check.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/check.js +24 -3
- package/dist/lib/codex-manager/commands/forecast.d.ts +1 -1
- package/dist/lib/codex-manager/commands/forecast.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/forecast.js +7 -3
- package/dist/lib/codex-manager/commands/report.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/report.js +5 -1
- package/dist/lib/codex-manager/commands/resets.d.ts +2 -0
- package/dist/lib/codex-manager/commands/resets.d.ts.map +1 -0
- package/dist/lib/codex-manager/commands/resets.js +67 -0
- package/dist/lib/codex-manager/commands/rotation.d.ts +2 -2
- package/dist/lib/codex-manager/commands/rotation.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/rotation.js +63 -12
- package/dist/lib/codex-manager/commands/status.d.ts +12 -1
- package/dist/lib/codex-manager/commands/status.d.ts.map +1 -1
- package/dist/lib/codex-manager/commands/status.js +166 -22
- package/dist/lib/codex-manager/commands/uninstall.js +1 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.d.ts.map +1 -1
- package/dist/lib/codex-manager/formatters/quota-formatters.js +3 -2
- package/dist/lib/codex-manager/health-check.d.ts +3 -0
- package/dist/lib/codex-manager/health-check.d.ts.map +1 -1
- package/dist/lib/codex-manager/health-check.js +57 -7
- package/dist/lib/codex-manager/help.d.ts.map +1 -1
- package/dist/lib/codex-manager/help.js +4 -2
- package/dist/lib/codex-manager/login-flow.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-flow.js +69 -7
- package/dist/lib/codex-manager/login-menu-data.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-menu-data.js +21 -8
- package/dist/lib/codex-manager/login-oauth.d.ts +3 -0
- package/dist/lib/codex-manager/login-oauth.d.ts.map +1 -1
- package/dist/lib/codex-manager/login-oauth.js +6 -1
- package/dist/lib/codex-manager/login-workspace-choice.d.ts +11 -0
- package/dist/lib/codex-manager/login-workspace-choice.d.ts.map +1 -0
- package/dist/lib/codex-manager/login-workspace-choice.js +37 -0
- package/dist/lib/codex-manager/persist-selected-account.d.ts.map +1 -1
- package/dist/lib/codex-manager/persist-selected-account.js +2 -1
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts +7 -1
- package/dist/lib/codex-manager/quota-cache-helpers.d.ts.map +1 -1
- package/dist/lib/codex-manager/quota-cache-helpers.js +34 -19
- package/dist/lib/codex-manager/repair-commands.d.ts +13 -0
- package/dist/lib/codex-manager/repair-commands.d.ts.map +1 -1
- package/dist/lib/codex-manager/repair-commands.js +144 -9
- package/dist/lib/codex-manager.d.ts.map +1 -1
- package/dist/lib/codex-manager.js +25 -6
- package/dist/lib/concurrency.d.ts +3 -0
- package/dist/lib/concurrency.d.ts.map +1 -0
- package/dist/lib/concurrency.js +31 -0
- package/dist/lib/context-budget-response.js +8 -8
- package/dist/lib/context-overflow.js +10 -10
- package/dist/lib/model-route-policy.d.ts +52 -0
- package/dist/lib/model-route-policy.d.ts.map +1 -0
- package/dist/lib/model-route-policy.js +159 -0
- package/dist/lib/oauth-success.html +125 -125
- package/dist/lib/policy/runtime-policy.d.ts +1 -0
- package/dist/lib/policy/runtime-policy.d.ts.map +1 -1
- package/dist/lib/policy/runtime-policy.js +3 -0
- package/dist/lib/preemptive-quota-scheduler.d.ts +2 -0
- package/dist/lib/preemptive-quota-scheduler.d.ts.map +1 -1
- package/dist/lib/preemptive-quota-scheduler.js +4 -0
- package/dist/lib/prompts/codex-host-bridge.js +138 -138
- package/dist/lib/prompts/codex.js +79 -79
- package/dist/lib/quota-cache.d.ts +7 -3
- package/dist/lib/quota-cache.d.ts.map +1 -1
- package/dist/lib/quota-cache.js +91 -59
- package/dist/lib/quota-probe.d.ts +5 -0
- package/dist/lib/quota-probe.d.ts.map +1 -1
- package/dist/lib/quota-probe.js +26 -2
- package/dist/lib/quota-readiness.d.ts +7 -2
- package/dist/lib/quota-readiness.d.ts.map +1 -1
- package/dist/lib/quota-readiness.js +25 -4
- package/dist/lib/request/client-cancellation.d.ts +5 -0
- package/dist/lib/request/client-cancellation.d.ts.map +1 -0
- package/dist/lib/request/client-cancellation.js +7 -0
- package/dist/lib/request/response-outcome.d.ts +25 -0
- package/dist/lib/request/response-outcome.d.ts.map +1 -0
- package/dist/lib/request/response-outcome.js +49 -0
- package/dist/lib/request/stream-failover-runtime.d.ts +2 -1
- package/dist/lib/request/stream-failover-runtime.d.ts.map +1 -1
- package/dist/lib/request/stream-failover-runtime.js +29 -10
- package/dist/lib/runtime/account-check.d.ts.map +1 -1
- package/dist/lib/runtime/account-check.js +2 -8
- package/dist/lib/runtime/account-model-catalog.d.ts +64 -0
- package/dist/lib/runtime/account-model-catalog.d.ts.map +1 -0
- package/dist/lib/runtime/account-model-catalog.js +154 -0
- package/dist/lib/runtime/account-pool.d.ts +3 -1
- package/dist/lib/runtime/account-pool.d.ts.map +1 -1
- package/dist/lib/runtime/account-pool.js +4 -0
- package/dist/lib/runtime/account-reset-credits.d.ts +42 -0
- package/dist/lib/runtime/account-reset-credits.d.ts.map +1 -0
- package/dist/lib/runtime/account-reset-credits.js +82 -0
- package/dist/lib/runtime/api-model-capabilities.d.ts +30 -0
- package/dist/lib/runtime/api-model-capabilities.d.ts.map +1 -0
- package/dist/lib/runtime/api-model-capabilities.js +434 -0
- package/dist/lib/runtime/api-model-runtime.d.ts +42 -0
- package/dist/lib/runtime/api-model-runtime.d.ts.map +1 -0
- package/dist/lib/runtime/api-model-runtime.js +358 -0
- package/dist/lib/runtime/app-bind.d.ts +19 -1
- package/dist/lib/runtime/app-bind.d.ts.map +1 -1
- package/dist/lib/runtime/app-bind.js +89 -11
- package/dist/lib/runtime/automatic-account-checks.d.ts +35 -0
- package/dist/lib/runtime/automatic-account-checks.d.ts.map +1 -0
- package/dist/lib/runtime/automatic-account-checks.js +140 -0
- package/dist/lib/runtime/automatic-subscription-checks.d.ts +7 -0
- package/dist/lib/runtime/automatic-subscription-checks.d.ts.map +1 -0
- package/dist/lib/runtime/automatic-subscription-checks.js +54 -0
- package/dist/lib/runtime/catalog-capabilities.d.ts +8 -0
- package/dist/lib/runtime/catalog-capabilities.d.ts.map +1 -0
- package/dist/lib/runtime/catalog-capabilities.js +61 -0
- package/dist/lib/runtime/inference-activity.d.ts +15 -0
- package/dist/lib/runtime/inference-activity.d.ts.map +1 -0
- package/dist/lib/runtime/inference-activity.js +95 -0
- package/dist/lib/runtime/model-discovery-status.d.ts +100 -0
- package/dist/lib/runtime/model-discovery-status.d.ts.map +1 -0
- package/dist/lib/runtime/model-discovery-status.js +387 -0
- package/dist/lib/runtime/native-account-storage.d.ts +11 -0
- package/dist/lib/runtime/native-account-storage.d.ts.map +1 -0
- package/dist/lib/runtime/native-account-storage.js +50 -0
- package/dist/lib/runtime/native-account-sync.d.ts +19 -0
- package/dist/lib/runtime/native-account-sync.d.ts.map +1 -0
- package/dist/lib/runtime/native-account-sync.js +62 -0
- package/dist/lib/runtime/native-binding-lock.d.ts +3 -0
- package/dist/lib/runtime/native-binding-lock.d.ts.map +1 -0
- package/dist/lib/runtime/native-binding-lock.js +5 -0
- package/dist/lib/runtime/native-client-auth.d.ts +3 -0
- package/dist/lib/runtime/native-client-auth.d.ts.map +1 -0
- package/dist/lib/runtime/native-client-auth.js +42 -0
- package/dist/lib/runtime/native-provider-config.d.ts +4 -0
- package/dist/lib/runtime/native-provider-config.d.ts.map +1 -0
- package/dist/lib/runtime/native-provider-config.js +52 -0
- package/dist/lib/runtime/native-rate-limits.d.ts +18 -0
- package/dist/lib/runtime/native-rate-limits.d.ts.map +1 -0
- package/dist/lib/runtime/native-rate-limits.js +135 -0
- package/dist/lib/runtime/reset-credit-routing.d.ts +41 -0
- package/dist/lib/runtime/reset-credit-routing.d.ts.map +1 -0
- package/dist/lib/runtime/reset-credit-routing.js +66 -0
- package/dist/lib/runtime/reset-credits.d.ts +101 -0
- package/dist/lib/runtime/reset-credits.d.ts.map +1 -0
- package/dist/lib/runtime/reset-credits.js +162 -0
- package/dist/lib/runtime/response-output-history.d.ts +17 -0
- package/dist/lib/runtime/response-output-history.d.ts.map +1 -0
- package/dist/lib/runtime/response-output-history.js +85 -0
- package/dist/lib/runtime/responses-websocket.d.ts +31 -0
- package/dist/lib/runtime/responses-websocket.d.ts.map +1 -0
- package/dist/lib/runtime/responses-websocket.js +636 -0
- package/dist/lib/runtime/resume-picker.d.ts +41 -0
- package/dist/lib/runtime/resume-picker.d.ts.map +1 -0
- package/dist/lib/runtime/resume-picker.js +169 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts +6 -0
- package/dist/lib/runtime/rotation-account-selection.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-account-selection.js +63 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts +33 -0
- package/dist/lib/runtime/rotation-proxy-state.d.ts.map +1 -1
- package/dist/lib/runtime/rotation-server-types.d.ts +18 -0
- package/dist/lib/runtime/rotation-server-types.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-capability-failures.d.ts +14 -0
- package/dist/lib/runtime/runtime-capability-failures.d.ts.map +1 -0
- package/dist/lib/runtime/runtime-capability-failures.js +76 -0
- package/dist/lib/runtime/runtime-observability.d.ts +7 -0
- package/dist/lib/runtime/runtime-observability.d.ts.map +1 -1
- package/dist/lib/runtime/runtime-observability.js +42 -2
- package/dist/lib/runtime/subscription-first-use.d.ts +10 -0
- package/dist/lib/runtime/subscription-first-use.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-first-use.js +64 -0
- package/dist/lib/runtime/subscription-quota-event.d.ts +6 -0
- package/dist/lib/runtime/subscription-quota-event.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-quota-event.js +31 -0
- package/dist/lib/runtime/subscription-quota-order.d.ts +17 -0
- package/dist/lib/runtime/subscription-quota-order.d.ts.map +1 -0
- package/dist/lib/runtime/subscription-quota-order.js +31 -0
- package/dist/lib/runtime/workspace-model-scopes.d.ts +15 -0
- package/dist/lib/runtime/workspace-model-scopes.d.ts.map +1 -0
- package/dist/lib/runtime/workspace-model-scopes.js +34 -0
- package/dist/lib/runtime-constants.d.ts +3 -0
- package/dist/lib/runtime-constants.d.ts.map +1 -1
- package/dist/lib/runtime-constants.js +5 -0
- package/dist/lib/runtime-paths.d.ts.map +1 -1
- package/dist/lib/runtime-paths.js +4 -1
- package/dist/lib/runtime-rotation-proxy.d.ts.map +1 -1
- package/dist/lib/runtime-rotation-proxy.js +852 -42
- package/dist/lib/schemas.d.ts +20 -0
- package/dist/lib/schemas.d.ts.map +1 -1
- package/dist/lib/schemas.js +3 -0
- package/dist/lib/storage/credential-sidecars.d.ts +13 -0
- package/dist/lib/storage/credential-sidecars.d.ts.map +1 -0
- package/dist/lib/storage/credential-sidecars.js +52 -0
- package/dist/lib/storage/file-lock.d.ts +9 -0
- package/dist/lib/storage/file-lock.d.ts.map +1 -0
- package/dist/lib/storage/file-lock.js +186 -0
- package/dist/lib/storage/flagged-storage.d.ts.map +1 -1
- package/dist/lib/storage/flagged-storage.js +12 -0
- package/dist/lib/storage/path-state.d.ts +2 -0
- package/dist/lib/storage/path-state.d.ts.map +1 -1
- package/dist/lib/storage/path-state.js +9 -0
- package/dist/lib/storage/paths.js +4 -4
- package/dist/lib/storage/pending-auth.d.ts +18 -0
- package/dist/lib/storage/pending-auth.d.ts.map +1 -0
- package/dist/lib/storage/pending-auth.js +155 -0
- package/dist/lib/storage/public-types.d.ts +13 -0
- package/dist/lib/storage/public-types.d.ts.map +1 -1
- package/dist/lib/storage/record-identity.d.ts +16 -0
- package/dist/lib/storage/record-identity.d.ts.map +1 -0
- package/dist/lib/storage/record-identity.js +16 -0
- package/dist/lib/storage/snapshot-merge.d.ts +16 -0
- package/dist/lib/storage/snapshot-merge.d.ts.map +1 -0
- package/dist/lib/storage/snapshot-merge.js +206 -0
- package/dist/lib/storage/transactions.d.ts.map +1 -1
- package/dist/lib/storage/transactions.js +5 -4
- package/dist/lib/storage.d.ts +6 -0
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/storage.js +77 -7
- package/dist/lib/ui/auth-menu-builder.d.ts +2 -0
- package/dist/lib/ui/auth-menu-builder.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu-builder.js +1 -0
- package/dist/lib/ui/auth-menu.d.ts.map +1 -1
- package/dist/lib/ui/auth-menu.js +1 -0
- package/dist/lib/ui/check-progress.d.ts +8 -0
- package/dist/lib/ui/check-progress.d.ts.map +1 -0
- package/dist/lib/ui/check-progress.js +30 -0
- package/dist/lib/ui/format.d.ts +3 -1
- package/dist/lib/ui/format.d.ts.map +1 -1
- package/dist/lib/ui/format.js +8 -0
- package/dist/lib/ui/ui-copy.d.ts +2 -2
- package/dist/lib/ui/ui-copy.js +2 -2
- package/dist/lib/usage/pricing.js +2 -2
- package/dist/lib/usage/usage-extraction.d.ts +3 -1
- package/dist/lib/usage/usage-extraction.d.ts.map +1 -1
- package/dist/lib/usage/usage-extraction.js +46 -9
- package/node_modules/@codex-ai/plugin/dist/index.d.ts +2 -2
- package/node_modules/@codex-ai/plugin/dist/index.js +2 -2
- package/node_modules/@codex-ai/plugin/dist/tool.d.ts +42 -42
- package/node_modules/@codex-ai/plugin/dist/tool.js +29 -29
- package/node_modules/@codex-ai/plugin/package.json +9 -9
- package/node_modules/@codex-ai/sdk/dist/index.d.ts +4 -4
- package/node_modules/@codex-ai/sdk/dist/index.js +2 -2
- package/node_modules/@codex-ai/sdk/package.json +8 -8
- package/package.json +200 -197
- package/scripts/codex-app-launcher.js +653 -653
- package/scripts/codex-app-router.js +373 -366
- package/scripts/codex-bin-resolver.js +313 -281
- package/scripts/codex-multi-auth.js +59 -59
- package/scripts/codex-routing.js +62 -61
- package/scripts/codex.js +6642 -6564
- package/scripts/install-codex-auth-utils.js +213 -213
- package/scripts/mcodex.js +367 -367
- package/scripts/postinstall.js +114 -114
- package/scripts/preuninstall.js +265 -265
- package/vendor/codex-ai-plugin/dist/index.d.ts +2 -2
- package/vendor/codex-ai-plugin/dist/index.js +2 -2
- package/vendor/codex-ai-plugin/dist/tool.d.ts +42 -42
- package/vendor/codex-ai-plugin/dist/tool.js +29 -29
- package/vendor/codex-ai-plugin/package.json +9 -9
- package/vendor/codex-ai-sdk/dist/index.d.ts +4 -4
- package/vendor/codex-ai-sdk/dist/index.js +2 -2
- package/vendor/codex-ai-sdk/package.json +8 -8
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
import { select } from "../ui/select.js";
|
|
4
|
+
/** Read the canonical index through Codex, rather than depending on SQLite schemas. */
|
|
5
|
+
export function createResumeCatalog(options) {
|
|
6
|
+
const args = [...options.configArgs, "app-server", "--listen", "stdio://"];
|
|
7
|
+
const child = spawn(options.codexBin.launchWithNode ? process.execPath : options.codexBin.path, options.codexBin.launchWithNode ? [options.codexBin.path, ...args] : args, { cwd: options.cwd, env: options.env ?? process.env, stdio: ["pipe", "pipe", "pipe"] });
|
|
8
|
+
const lines = createInterface({ input: child.stdout });
|
|
9
|
+
// Drain diagnostics, but never print arbitrary child output (which may contain secrets).
|
|
10
|
+
child.stderr.resume();
|
|
11
|
+
let nextId = 0;
|
|
12
|
+
let closed = false;
|
|
13
|
+
let failure = null;
|
|
14
|
+
const pending = new Map();
|
|
15
|
+
function fail(error) {
|
|
16
|
+
failure = error;
|
|
17
|
+
for (const request of pending.values()) {
|
|
18
|
+
clearTimeout(request.timer);
|
|
19
|
+
request.reject(error);
|
|
20
|
+
}
|
|
21
|
+
pending.clear();
|
|
22
|
+
}
|
|
23
|
+
child.on("error", () => fail(new Error("Could not start Codex session discovery.")));
|
|
24
|
+
child.on("exit", () => fail(new Error("Codex session discovery stopped.")));
|
|
25
|
+
child.stdin.on("error", () => fail(new Error("Codex session discovery disconnected.")));
|
|
26
|
+
lines.on("line", (line) => {
|
|
27
|
+
let message;
|
|
28
|
+
try {
|
|
29
|
+
message = JSON.parse(line);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (!message || typeof message.id !== "number")
|
|
35
|
+
return;
|
|
36
|
+
const request = pending.get(message.id);
|
|
37
|
+
if (!request)
|
|
38
|
+
return;
|
|
39
|
+
pending.delete(message.id);
|
|
40
|
+
clearTimeout(request.timer);
|
|
41
|
+
if (message.error)
|
|
42
|
+
request.reject(new Error("Codex rejected the session discovery request."));
|
|
43
|
+
else
|
|
44
|
+
request.resolve(message.result);
|
|
45
|
+
});
|
|
46
|
+
function request(method, params) {
|
|
47
|
+
if (failure || closed)
|
|
48
|
+
return Promise.reject(failure ?? new Error("Session catalog is closed."));
|
|
49
|
+
return new Promise((resolve, reject) => {
|
|
50
|
+
const id = ++nextId;
|
|
51
|
+
const timer = setTimeout(() => {
|
|
52
|
+
pending.delete(id);
|
|
53
|
+
reject(new Error("Codex session discovery timed out."));
|
|
54
|
+
}, options.timeoutMs ?? 15_000);
|
|
55
|
+
pending.set(id, { resolve, reject, timer });
|
|
56
|
+
child.stdin.write(`${JSON.stringify({ id, method, params })}\n`);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
let initialized = false;
|
|
60
|
+
return {
|
|
61
|
+
async page(cursor = null) {
|
|
62
|
+
if (!initialized) {
|
|
63
|
+
await request("initialize", {
|
|
64
|
+
clientInfo: { name: "codex-multi-auth-resume", version: "1" },
|
|
65
|
+
capabilities: { experimentalApi: true },
|
|
66
|
+
});
|
|
67
|
+
child.stdin.write(`${JSON.stringify({ method: "initialized" })}\n`);
|
|
68
|
+
initialized = true;
|
|
69
|
+
}
|
|
70
|
+
const result = await request("thread/list", {
|
|
71
|
+
limit: 50, cursor, sortKey: "updated_at", archived: false,
|
|
72
|
+
// An empty list explicitly disables the server's current-provider filter.
|
|
73
|
+
modelProviders: [],
|
|
74
|
+
// Omitted or empty means interactive-only, so name the resumable non-interactive kinds (as Codex does).
|
|
75
|
+
sourceKinds: options.includeNonInteractive ? ["cli", "vscode", "exec", "appServer"] : ["cli", "vscode"],
|
|
76
|
+
...(options.showAll ? {} : { cwd: options.cwd }),
|
|
77
|
+
});
|
|
78
|
+
if (!result || typeof result !== "object" || !("data" in result) || !Array.isArray(result.data)) {
|
|
79
|
+
throw new Error("Codex returned an invalid session list.");
|
|
80
|
+
}
|
|
81
|
+
const data = result.data.filter((thread) => thread && typeof thread.id === "string" && typeof thread.cwd === "string");
|
|
82
|
+
const cursorValue = "nextCursor" in result ? result.nextCursor : null;
|
|
83
|
+
return { data, nextCursor: typeof cursorValue === "string" ? cursorValue : null };
|
|
84
|
+
},
|
|
85
|
+
close() {
|
|
86
|
+
if (closed)
|
|
87
|
+
return;
|
|
88
|
+
closed = true;
|
|
89
|
+
fail(new Error("Session catalog is closed."));
|
|
90
|
+
lines.close();
|
|
91
|
+
child.stdin.end();
|
|
92
|
+
child.kill("SIGTERM");
|
|
93
|
+
// Only terminate the discovery child we own, never an existing Codex server.
|
|
94
|
+
const timer = setTimeout(() => {
|
|
95
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
96
|
+
child.kill("SIGKILL");
|
|
97
|
+
}, 1_000);
|
|
98
|
+
timer.unref();
|
|
99
|
+
child.once("exit", () => clearTimeout(timer));
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function displayText(value) {
|
|
104
|
+
// Session titles and directory names are untrusted terminal output.
|
|
105
|
+
return String(value).replace(/[\x00-\x1f\x7f-\x9f]/g, " ").slice(0, 180);
|
|
106
|
+
}
|
|
107
|
+
export async function pickResumeThread(options, deps = { createCatalog: createResumeCatalog, select: (select) }) {
|
|
108
|
+
const catalog = deps.createCatalog(options);
|
|
109
|
+
const pages = [];
|
|
110
|
+
let pageIndex = 0;
|
|
111
|
+
let interrupted = false;
|
|
112
|
+
const onInterrupt = () => {
|
|
113
|
+
interrupted = true;
|
|
114
|
+
catalog.close();
|
|
115
|
+
};
|
|
116
|
+
process.once("SIGINT", onInterrupt);
|
|
117
|
+
process.once("SIGTERM", onInterrupt);
|
|
118
|
+
try {
|
|
119
|
+
pages.push(await catalog.page());
|
|
120
|
+
for (;;) {
|
|
121
|
+
const page = pages[pageIndex];
|
|
122
|
+
if (!page)
|
|
123
|
+
throw new Error("Session page is unavailable.");
|
|
124
|
+
const items = page.data.map((thread) => ({
|
|
125
|
+
label: displayText(thread.name || thread.preview || thread.id),
|
|
126
|
+
hint: displayText(`${thread.cwd} · ${thread.modelProvider ?? "unknown provider"} · ${thread.id}`),
|
|
127
|
+
value: { kind: "thread", id: thread.id },
|
|
128
|
+
}));
|
|
129
|
+
if (pageIndex > 0)
|
|
130
|
+
items.push({ label: "Previous page", value: { kind: "previous" } });
|
|
131
|
+
if (page.nextCursor)
|
|
132
|
+
items.push({ label: "Next page", value: { kind: "next" } });
|
|
133
|
+
// select() returns a sole choice without rendering, so an empty list would exit silently.
|
|
134
|
+
if (items.length === 0) {
|
|
135
|
+
process.stdout.write("No saved Codex sessions found.\n");
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
// Also prevents the shared select UI from auto-opening a single session.
|
|
139
|
+
items.push({ label: "Cancel", value: { kind: "cancel" } });
|
|
140
|
+
const choice = await deps.select(items, {
|
|
141
|
+
message: "Resume a Codex session",
|
|
142
|
+
subtitle: page.data.length ? "All providers · resumes through multi-auth" : "No saved sessions found",
|
|
143
|
+
allowEscape: true,
|
|
144
|
+
});
|
|
145
|
+
if (!choice || choice.kind === "cancel")
|
|
146
|
+
return null;
|
|
147
|
+
if (choice.kind === "thread")
|
|
148
|
+
return choice.id;
|
|
149
|
+
if (choice.kind === "previous") {
|
|
150
|
+
pageIndex -= 1;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (!pages[pageIndex + 1])
|
|
154
|
+
pages.push(await catalog.page(page.nextCursor));
|
|
155
|
+
pageIndex += 1;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
// Closing the catalog on Ctrl+C rejects the pending request; that is a cancel, not a failure.
|
|
160
|
+
if (interrupted)
|
|
161
|
+
return null;
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
process.removeListener("SIGINT", onInterrupt);
|
|
166
|
+
process.removeListener("SIGTERM", onInterrupt);
|
|
167
|
+
catalog.close();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type SubscriptionQuotaPreference } from "./subscription-quota-order.js";
|
|
1
2
|
import type { AccountManager, ManagedAccount } from "../accounts.js";
|
|
2
3
|
import type { ModelFamily } from "../prompts/codex.js";
|
|
3
4
|
import type { RuntimePolicyDecision } from "../policy/runtime-policy.js";
|
|
@@ -30,6 +31,11 @@ export declare function chooseAccount(params: {
|
|
|
30
31
|
now: number;
|
|
31
32
|
policy: RuntimePolicyDecision | null;
|
|
32
33
|
pinnedIndex: number | null;
|
|
34
|
+
/** Soft preference, used only within the first eligible priority tier. */
|
|
35
|
+
preferredIndex?: number | null;
|
|
36
|
+
/** Soft pin: first eligible attempt across tiers, then normal fallback. Ignored whenever `pinnedIndex` is set, which is how the proxy applies a stored `switch` pin. */
|
|
37
|
+
fallbackPinnedIndex?: number | null;
|
|
38
|
+
subscriptionQuotaByAccount?: Record<number, SubscriptionQuotaPreference>;
|
|
33
39
|
skipReasons?: Map<number, string>;
|
|
34
40
|
stickyBoostByAccount?: Record<number, number>;
|
|
35
41
|
pidOffsetEnabled?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation-account-selection.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-account-selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAWnE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACrC,cAAc,EAAE,cAAc,CAAC;IAC/B,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC7C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B,GAAG,cAAc,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"rotation-account-selection.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-account-selection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqD,KAAK,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACpI,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACzE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAWnE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACrC,cAAc,EAAE,cAAc,CAAC;IAC/B,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACrC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,wKAAwK;IACxK,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,0BAA0B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IACzE,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kBAAkB,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC7C;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B,GAAG,cAAc,GAAG,IAAI,CAqNxB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { compareSubscriptionQuota, usesSubscriptionReserve } from "./subscription-quota-order.js";
|
|
1
2
|
/**
|
|
2
3
|
* Whether a runtime skip reason is a cooldown, the one blocker a pinned
|
|
3
4
|
* retry may waive. `getManagedAccountRuntimeSkipReason` emits either the
|
|
@@ -26,6 +27,68 @@ function isCooldownReason(reason) {
|
|
|
26
27
|
*/
|
|
27
28
|
export function chooseAccount(params) {
|
|
28
29
|
const { accountManager, sessionAffinityStore, sessionKey, family, model, attemptedIndexes, now, policy, pinnedIndex, skipReasons, stickyBoostByAccount, pidOffsetEnabled, schedulingStrategy, allowPinnedCooldown, } = params;
|
|
30
|
+
const fallbackPin = params.fallbackPinnedIndex;
|
|
31
|
+
const quotaByAccount = params.subscriptionQuotaByAccount;
|
|
32
|
+
const hasNonReserve = quotaByAccount && accountManager.getAccountsSnapshot().some(a => a.enabled !== false && !attemptedIndexes.has(a.index) && !policy?.blockedAccountIndexes.has(a.index) &&
|
|
33
|
+
!accountManager.getAccountRuntimeSkipReason(a.index, family, model) && !quotaByAccount[a.index]?.exhausted && !usesSubscriptionReserve(quotaByAccount[a.index]));
|
|
34
|
+
if (pinnedIndex === null && typeof fallbackPin === "number" && !attemptedIndexes.has(fallbackPin) &&
|
|
35
|
+
!quotaByAccount?.[fallbackPin]?.exhausted && !(hasNonReserve && usesSubscriptionReserve(quotaByAccount?.[fallbackPin]))) {
|
|
36
|
+
const selected = chooseAccount({ ...params, pinnedIndex: fallbackPin, allowPinnedCooldown: false });
|
|
37
|
+
if (selected)
|
|
38
|
+
return selected;
|
|
39
|
+
}
|
|
40
|
+
if (pinnedIndex === null && policy?.priorityByAccount) {
|
|
41
|
+
const priorities = policy.priorityByAccount;
|
|
42
|
+
let candidates = accountManager.getAccountsSnapshot().filter(account => {
|
|
43
|
+
if (account.enabled === false || attemptedIndexes.has(account.index) || policy.blockedAccountIndexes.has(account.index))
|
|
44
|
+
return false;
|
|
45
|
+
const reason = accountManager.getAccountRuntimeSkipReason(account.index, family, model);
|
|
46
|
+
if (reason)
|
|
47
|
+
skipReasons?.set(account.index, reason);
|
|
48
|
+
return !reason;
|
|
49
|
+
});
|
|
50
|
+
if (!candidates.length)
|
|
51
|
+
return null;
|
|
52
|
+
if (quotaByAccount) {
|
|
53
|
+
const usable = candidates.filter(a => !quotaByAccount[a.index]?.exhausted);
|
|
54
|
+
if (!usable.length)
|
|
55
|
+
return null;
|
|
56
|
+
const nonReserve = usable.filter(a => !usesSubscriptionReserve(quotaByAccount[a.index]));
|
|
57
|
+
candidates = nonReserve.length ? nonReserve : usable;
|
|
58
|
+
}
|
|
59
|
+
const tier = Math.min(...candidates.map(a => priorities[a.index] ?? 1));
|
|
60
|
+
const tierIndexes = new Set(candidates.filter(a => (priorities[a.index] ?? 1) === tier).map(a => a.index));
|
|
61
|
+
let preferred = params.preferredIndex;
|
|
62
|
+
if (quotaByAccount) {
|
|
63
|
+
// Rank only measured accounts: "no data" compares equal to everything, which
|
|
64
|
+
// is not transitive and would make the winner depend on storage order.
|
|
65
|
+
const ranked = candidates.flatMap(a => {
|
|
66
|
+
const quota = quotaByAccount[a.index];
|
|
67
|
+
return tierIndexes.has(a.index) && quota ? [{ account: a, quota }] : [];
|
|
68
|
+
}).sort((a, b) => compareSubscriptionQuota(a.quota, b.quota)).map(entry => entry.account);
|
|
69
|
+
const best = ranked[0];
|
|
70
|
+
const bestQuota = best && quotaByAccount[best.index];
|
|
71
|
+
if (best && bestQuota && (bestQuota.resetAtMs !== null || bestQuota.remainingPercent !== null)) {
|
|
72
|
+
const preferredQuota = typeof preferred === "number" ? quotaByAccount[preferred] : undefined;
|
|
73
|
+
if (!preferredQuota || !tierIndexes.has(preferred ?? -1) || compareSubscriptionQuota(bestQuota, preferredQuota) < 0)
|
|
74
|
+
preferred = best.index;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Re-evaluate tiers on every attempt. Never persist a temporary tier block.
|
|
78
|
+
return chooseAccount({
|
|
79
|
+
...params,
|
|
80
|
+
policy: {
|
|
81
|
+
...policy,
|
|
82
|
+
priorityByAccount: undefined,
|
|
83
|
+
blockedAccountIndexes: new Set([
|
|
84
|
+
...policy.blockedAccountIndexes,
|
|
85
|
+
...accountManager.getAccountsSnapshot().filter(a => !tierIndexes.has(a.index)).map(a => a.index),
|
|
86
|
+
]),
|
|
87
|
+
},
|
|
88
|
+
fallbackPinnedIndex: null,
|
|
89
|
+
pinnedIndex: typeof preferred === "number" && tierIndexes.has(preferred) ? preferred : null,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
29
92
|
// Manual pin (from `codex-multi-auth switch <n>`) overrides every other
|
|
30
93
|
// selection signal. We do NOT call markSwitched here — the proxy must not
|
|
31
94
|
// clobber the pin set by the CLI. See issue #474.
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
import type { NativeAccountSnapshot } from "./native-account-storage.js";
|
|
2
|
+
import type { QuotaCacheData, QuotaCacheEntry } from "../quota-cache.js";
|
|
3
|
+
import type { RuntimeCapabilityFailures } from "./runtime-capability-failures.js";
|
|
4
|
+
import type { RouteModel } from "../model-route-policy.js";
|
|
5
|
+
import type { ModelInventory } from "./model-discovery-status.js";
|
|
6
|
+
import type { ApiModelCapabilities } from "./api-model-capabilities.js";
|
|
7
|
+
import type { ApiModelRuntime } from "./api-model-runtime.js";
|
|
8
|
+
import type { ApiRouteCredential } from "../api-route-store.js";
|
|
9
|
+
import type { AccountModelCatalog } from "./account-model-catalog.js";
|
|
1
10
|
import { AccountManager } from "../accounts.js";
|
|
2
11
|
import type { ContextBudgetGuard } from "../context-budget-guard.js";
|
|
3
12
|
import type { PreemptiveQuotaScheduler } from "../preemptive-quota-scheduler.js";
|
|
@@ -11,6 +20,14 @@ import type { SessionAffinityStore } from "../session-affinity.js";
|
|
|
11
20
|
* @internal
|
|
12
21
|
*/
|
|
13
22
|
export interface RotationProxyStateInit {
|
|
23
|
+
nativeOpenai?: boolean;
|
|
24
|
+
readNativeAccountStorage?: () => Promise<NativeAccountSnapshot>;
|
|
25
|
+
readApiRoutes?: () => Promise<ApiRouteCredential[]>;
|
|
26
|
+
readSubscriptionQuota?: () => Promise<QuotaCacheData | null>;
|
|
27
|
+
catalogAccount?: {
|
|
28
|
+
email: string;
|
|
29
|
+
accountId: string;
|
|
30
|
+
};
|
|
14
31
|
activeAccountManager: AccountManager;
|
|
15
32
|
routingMutexMode: "enabled" | "legacy";
|
|
16
33
|
schedulingStrategy: "hybrid" | "sequential";
|
|
@@ -58,6 +75,22 @@ export interface RotationProxyStateInit {
|
|
|
58
75
|
export interface RotationProxyState extends RotationProxyStateInit {
|
|
59
76
|
readonly knownAccountManagers: Set<AccountManager>;
|
|
60
77
|
readonly status: RuntimeRotationProxyStatus;
|
|
78
|
+
modelCatalog?: AccountModelCatalog;
|
|
79
|
+
modelCatalogs?: Map<string, AccountModelCatalog>;
|
|
80
|
+
catalogBackoff?: Map<string, number>;
|
|
81
|
+
/** Short-lived per-request file reads (quota cache, reset credits), keyed by source. */
|
|
82
|
+
readCache?: Map<string, {
|
|
83
|
+
at: number;
|
|
84
|
+
value: Promise<unknown>;
|
|
85
|
+
}>;
|
|
86
|
+
capabilityFailures?: RuntimeCapabilityFailures;
|
|
87
|
+
apiModelRuntime?: ApiModelRuntime;
|
|
88
|
+
apiModelCapabilities?: ApiModelCapabilities;
|
|
89
|
+
catalogEtag?: string;
|
|
90
|
+
catalogOAuthModels?: RouteModel[];
|
|
91
|
+
catalogApiRoutes?: ApiRouteCredential[];
|
|
92
|
+
catalogInventory?: ModelInventory;
|
|
93
|
+
subscriptionQuotaObservations?: Map<string, QuotaCacheEntry>;
|
|
61
94
|
readonly threadGoalFallbacks: Map<string, string | null>;
|
|
62
95
|
lastGlobalAccountIndex: number | null;
|
|
63
96
|
lastGlobalSwitchAt: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation-proxy-state.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-proxy-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAKjF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACtC,oBAAoB,EAAE,cAAc,CAAC;IACrC,gBAAgB,EAAE,SAAS,GAAG,QAAQ,CAAC;IACvC,kBAAkB,EAAE,QAAQ,GAAG,YAAY,CAAC;IAC5C,SAAS,EAAE,OAAO,KAAK,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,qBAAqB,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2BAA2B,EAAE,MAAM,CAAC;IACpC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,yBAAyB,EAAE,MAAM,CAAC;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,8BAA8B,EAAE,MAAM,CAAC;IACvC,wBAAwB,EAAE,wBAAwB,CAAC;IACnD,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAClD,8BAA8B,EAAE,MAAM,CAAC;IACvC;;;;;OAKG;IACH,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAmB,SAAQ,sBAAsB;IACjE,QAAQ,CAAC,oBAAoB,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC;IAC5C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACzD,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yBAAyB,EAAE,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IACjE,wBAAwB,EAAE,MAAM,CAAC;CACjC;AAID,gBAAgB;AAChB,wBAAgB,wBAAwB,CACvC,IAAI,EAAE,sBAAsB,GAC1B,kBAAkB,CAuBpB;AAED,gBAAgB;AAChB,wBAAsB,wBAAwB,CAC7C,KAAK,EAAE,kBAAkB,GACvB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAkDhC"}
|
|
1
|
+
{"version":3,"file":"rotation-proxy-state.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-proxy-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { QuotaCacheData } from "../quota-cache.js";
|
|
2
|
+
import type { ApiRouteCredential } from "../api-route-store.js";
|
|
3
|
+
import type { AccountStorageV3 } from "../storage.js";
|
|
1
4
|
import type { AccountManager } from "../accounts.js";
|
|
2
5
|
import type { ModelFamily } from "../prompts/codex.js";
|
|
3
6
|
export interface RuntimeRotationProxyServer {
|
|
@@ -15,6 +18,10 @@ export interface RuntimeRotationProxyServer {
|
|
|
15
18
|
getOpenConnectionCount?: () => number;
|
|
16
19
|
}
|
|
17
20
|
export interface RuntimeRotationProxyStatus {
|
|
21
|
+
streamQuotaUpdates?: number;
|
|
22
|
+
lastStreamQuotaUpdateAt?: number;
|
|
23
|
+
websocketConnections?: number;
|
|
24
|
+
websocketUpstreamRequests?: number;
|
|
18
25
|
startedAt: number;
|
|
19
26
|
totalRequests: number;
|
|
20
27
|
upstreamRequests: number;
|
|
@@ -25,9 +32,20 @@ export interface RuntimeRotationProxyStatus {
|
|
|
25
32
|
lastAccountIndex: number | null;
|
|
26
33
|
lastAccountLabel: string | null;
|
|
27
34
|
lastAccountId: string | null;
|
|
35
|
+
/** Outgoing ChatGPT-Account-ID; distinct from the saved account binding. */
|
|
36
|
+
lastRequestedWorkspaceId?: string | null;
|
|
28
37
|
lastAccountUpdatedAt: number | null;
|
|
29
38
|
}
|
|
30
39
|
export interface RuntimeRotationProxyOptions {
|
|
40
|
+
nativeOpenai?: boolean;
|
|
41
|
+
/** Override the native credential reader for embedded hosts and tests. */
|
|
42
|
+
readNativeAccountStorage?: () => Promise<AccountStorageV3 | null>;
|
|
43
|
+
readApiRoutes?: () => Promise<ApiRouteCredential[]>;
|
|
44
|
+
readSubscriptionQuota?: () => Promise<QuotaCacheData | null>;
|
|
45
|
+
catalogAccount?: {
|
|
46
|
+
email: string;
|
|
47
|
+
accountId: string;
|
|
48
|
+
};
|
|
31
49
|
host?: string;
|
|
32
50
|
port?: number;
|
|
33
51
|
upstreamBaseUrl?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rotation-server-types.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-server-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,WAAW,0BAA0B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,SAAS,EAAE,MAAM,0BAA0B,CAAC;IAC5C;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,MAAM,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,0BAA0B;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,2BAA2B;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACxC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;;;;;OASG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,MAAM,gBAAgB,GACzB,YAAY,GACZ,cAAc,GACd,eAAe,GACf,cAAc,GACd,QAAQ,GACR,aAAa,GACb,YAAY,CAAC;AAChB,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,WAAW,8BAA8B;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CAClB"}
|
|
1
|
+
{"version":3,"file":"rotation-server-types.d.ts","sourceRoot":"","sources":["../../../lib/runtime/rotation-server-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type CapabilityFailure = "model" | "effort" | "tier";
|
|
2
|
+
/** Narrow structured rejections only: malformed input, authentication and capacity are not entitlements. */
|
|
3
|
+
export declare function classifyCapabilityFailure(status: number, body: unknown): CapabilityFailure | null;
|
|
4
|
+
/** Bounded short-lived negative evidence; never persisted with credentials or user content. */
|
|
5
|
+
export declare class RuntimeCapabilityFailures {
|
|
6
|
+
private readonly now;
|
|
7
|
+
private readonly ttlMs;
|
|
8
|
+
private readonly denied;
|
|
9
|
+
constructor(now?: () => number, ttlMs?: number);
|
|
10
|
+
private key;
|
|
11
|
+
record(credential: string, model: string, kind: CapabilityFailure, effort?: string, tier?: string): void;
|
|
12
|
+
supports(credential: string, model: string, effort?: string, tier?: string): boolean;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=runtime-capability-failures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-capability-failures.d.ts","sourceRoot":"","sources":["../../../lib/runtime/runtime-capability-failures.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAC5D,4GAA4G;AAC5G,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACX,iBAAiB,GAAG,IAAI,CA2B1B;AACD,+FAA+F;AAC/F,qBAAa,yBAAyB;IAGpC,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;gBAElC,GAAG,GAAE,MAAM,MAAiB,EAC5B,KAAK,SAAU;IAEjC,OAAO,CAAC,GAAG;IAQX,MAAM,CACL,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,iBAAiB,EACvB,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM;IAkBd,QAAQ,CACP,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,MAAM,GACX,OAAO;CAkBV"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { canonicalServiceTier } from "../model-route-policy.js";
|
|
2
|
+
import { isRecord } from "../utils.js";
|
|
3
|
+
/** Narrow structured rejections only: malformed input, authentication and capacity are not entitlements. */
|
|
4
|
+
export function classifyCapabilityFailure(status, body) {
|
|
5
|
+
if (![400, 403, 404].includes(status) ||
|
|
6
|
+
!isRecord(body) ||
|
|
7
|
+
!isRecord(body.error))
|
|
8
|
+
return null;
|
|
9
|
+
const { code, param } = body.error;
|
|
10
|
+
if ([
|
|
11
|
+
"model_not_found",
|
|
12
|
+
"model_not_supported",
|
|
13
|
+
"unsupported_model",
|
|
14
|
+
"model_access_denied",
|
|
15
|
+
].includes(String(code)))
|
|
16
|
+
return "model";
|
|
17
|
+
if (status !== 400 ||
|
|
18
|
+
!["invalid_value", "unsupported_value", "unsupported_parameter"].includes(String(code)))
|
|
19
|
+
return null;
|
|
20
|
+
if (param === "reasoning.effort")
|
|
21
|
+
return "effort";
|
|
22
|
+
if (param === "service_tier")
|
|
23
|
+
return "tier";
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
/** Bounded short-lived negative evidence; never persisted with credentials or user content. */
|
|
27
|
+
export class RuntimeCapabilityFailures {
|
|
28
|
+
now;
|
|
29
|
+
ttlMs;
|
|
30
|
+
denied = new Map();
|
|
31
|
+
constructor(now = Date.now, ttlMs = 300_000) {
|
|
32
|
+
this.now = now;
|
|
33
|
+
this.ttlMs = ttlMs;
|
|
34
|
+
}
|
|
35
|
+
key(credential, model, kind, value = "") {
|
|
36
|
+
return JSON.stringify([credential, model, kind, value]);
|
|
37
|
+
}
|
|
38
|
+
record(credential, model, kind, effort, tier) {
|
|
39
|
+
if ((kind === "effort" && !effort) || (kind === "tier" && !tier))
|
|
40
|
+
return;
|
|
41
|
+
const value = kind === "model"
|
|
42
|
+
? ""
|
|
43
|
+
: JSON.stringify([
|
|
44
|
+
effort ?? null,
|
|
45
|
+
canonicalServiceTier(tier ?? "default"),
|
|
46
|
+
]);
|
|
47
|
+
const key = this.key(credential, model, kind, value);
|
|
48
|
+
this.denied.delete(key);
|
|
49
|
+
this.denied.set(key, this.now() + this.ttlMs);
|
|
50
|
+
while (this.denied.size > 4096) {
|
|
51
|
+
const first = this.denied.keys().next().value;
|
|
52
|
+
if (first)
|
|
53
|
+
this.denied.delete(first);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
supports(credential, model, effort, tier) {
|
|
57
|
+
const combination = JSON.stringify([
|
|
58
|
+
effort ?? null,
|
|
59
|
+
canonicalServiceTier(tier ?? "default"),
|
|
60
|
+
]);
|
|
61
|
+
const keys = [
|
|
62
|
+
this.key(credential, model, "model"),
|
|
63
|
+
this.key(credential, model, "effort", combination),
|
|
64
|
+
this.key(credential, model, "tier", combination),
|
|
65
|
+
];
|
|
66
|
+
return keys.every((key) => {
|
|
67
|
+
const expiry = this.denied.get(key);
|
|
68
|
+
if (expiry === undefined)
|
|
69
|
+
return true;
|
|
70
|
+
if (expiry > this.now())
|
|
71
|
+
return false;
|
|
72
|
+
this.denied.delete(key);
|
|
73
|
+
return true;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -41,7 +41,11 @@ export interface RuntimeObservabilitySnapshot {
|
|
|
41
41
|
lastAccountLabel?: string | null;
|
|
42
42
|
lastAccountEmail?: string | null;
|
|
43
43
|
lastAccountId?: string | null;
|
|
44
|
+
/** Outgoing request scope, not proof of the upstream billing plan. */
|
|
45
|
+
lastRequestedWorkspaceId?: string | null;
|
|
44
46
|
lastAccountUpdatedAt?: number | null;
|
|
47
|
+
/** Actual inference dispatches, keyed by hashed credential identity (not selection or health checks). */
|
|
48
|
+
lastInferenceRequestAtByAccount?: Record<string, number>;
|
|
45
49
|
lastPoolExhaustionReason?: string | null;
|
|
46
50
|
lastPoolExhaustionRetryAfterMs?: number | null;
|
|
47
51
|
lastPoolExhaustionSkipReasons?: Record<string, string>;
|
|
@@ -54,6 +58,9 @@ export interface RuntimeObservabilitySnapshot {
|
|
|
54
58
|
policyBlockedReasons?: Record<string, string>;
|
|
55
59
|
runtimeMetrics: RuntimeMetricsSnapshot;
|
|
56
60
|
}
|
|
61
|
+
/** Write pending inference times now (proxy shutdown). */
|
|
62
|
+
export declare function flushRuntimeInferenceActivity(): Promise<void>;
|
|
63
|
+
export declare function recordRuntimeInferenceRequest(accountKey: string, at: number): void;
|
|
57
64
|
export declare function getRuntimeObservabilitySnapshot(): RuntimeObservabilitySnapshot;
|
|
58
65
|
export declare function mutateRuntimeObservabilitySnapshot(mutator: (snapshot: RuntimeObservabilitySnapshot) => void): void;
|
|
59
66
|
export declare function recordRuntimePoolExhaustion(params: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-observability.d.ts","sourceRoot":"","sources":["../../../lib/runtime/runtime-observability.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime-observability.d.ts","sourceRoot":"","sources":["../../../lib/runtime/runtime-observability.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createInferenceActivityWriter } from "./inference-activity.js";
|
|
2
|
+
import { createLogger } from "../logger.js";
|
|
1
3
|
import { existsSync, readFileSync, promises as fs } from "node:fs";
|
|
2
4
|
import { join } from "node:path";
|
|
3
5
|
import { getCodexMultiAuthDir } from "../runtime-paths.js";
|
|
@@ -7,6 +9,13 @@ const RUNTIME_OBSERVABILITY_SNAPSHOT_VERSION = 1;
|
|
|
7
9
|
const RETRYABLE_SNAPSHOT_ERRORS = new Set(["EBUSY", "EPERM"]);
|
|
8
10
|
let snapshotState = null;
|
|
9
11
|
let pendingWrite = null;
|
|
12
|
+
/** Latest snapshot waiting behind the in-flight write; newer mutations replace it. */
|
|
13
|
+
let queuedSnapshot = null;
|
|
14
|
+
const inferenceActivity = createInferenceActivityWriter(undefined, 1000, () => createLogger("runtime-observability").warn("Inference activity could not be saved"));
|
|
15
|
+
/** Write pending inference times now (proxy shutdown). */
|
|
16
|
+
export function flushRuntimeInferenceActivity() {
|
|
17
|
+
return inferenceActivity.flush();
|
|
18
|
+
}
|
|
10
19
|
function getSnapshotPath() {
|
|
11
20
|
return join(getCodexMultiAuthDir(), SNAPSHOT_FILE_NAME);
|
|
12
21
|
}
|
|
@@ -24,7 +33,9 @@ function createDefaultSnapshot() {
|
|
|
24
33
|
lastAccountLabel: null,
|
|
25
34
|
lastAccountEmail: null,
|
|
26
35
|
lastAccountId: null,
|
|
36
|
+
lastRequestedWorkspaceId: null,
|
|
27
37
|
lastAccountUpdatedAt: null,
|
|
38
|
+
lastInferenceRequestAtByAccount: {},
|
|
28
39
|
lastPoolExhaustionReason: null,
|
|
29
40
|
lastPoolExhaustionRetryAfterMs: null,
|
|
30
41
|
lastPoolExhaustionSkipReasons: {},
|
|
@@ -67,6 +78,24 @@ function createDefaultSnapshot() {
|
|
|
67
78
|
},
|
|
68
79
|
};
|
|
69
80
|
}
|
|
81
|
+
function normalizeInferenceTimes(value) {
|
|
82
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
83
|
+
return {};
|
|
84
|
+
return Object.fromEntries(Object.entries(value)
|
|
85
|
+
.filter((entry) => /^sha256:[a-f0-9]{64}$/.test(entry[0]) && typeof entry[1] === "number" && Number.isFinite(entry[1]) && entry[1] > 0)
|
|
86
|
+
.sort((a, b) => b[1] - a[1]).slice(0, 1000));
|
|
87
|
+
}
|
|
88
|
+
export function recordRuntimeInferenceRequest(accountKey, at) {
|
|
89
|
+
if (!/^sha256:[a-f0-9]{64}$/.test(accountKey) || !Number.isFinite(at) || at <= 0)
|
|
90
|
+
return;
|
|
91
|
+
mutateRuntimeObservabilitySnapshot(snapshot => {
|
|
92
|
+
const times = normalizeInferenceTimes(snapshot.lastInferenceRequestAtByAccount);
|
|
93
|
+
times[accountKey] = Math.max(times[accountKey] ?? 0, at);
|
|
94
|
+
snapshot.lastInferenceRequestAtByAccount = normalizeInferenceTimes(times);
|
|
95
|
+
});
|
|
96
|
+
if (PERSIST_RUNTIME_SNAPSHOT)
|
|
97
|
+
inferenceActivity.record(accountKey, at);
|
|
98
|
+
}
|
|
70
99
|
function normalizePersistedSnapshot(parsed) {
|
|
71
100
|
if (!parsed || typeof parsed !== "object") {
|
|
72
101
|
return null;
|
|
@@ -80,6 +109,8 @@ function normalizePersistedSnapshot(parsed) {
|
|
|
80
109
|
...base,
|
|
81
110
|
...parsed,
|
|
82
111
|
version: RUNTIME_OBSERVABILITY_SNAPSHOT_VERSION,
|
|
112
|
+
lastInferenceRequestAtByAccount: normalizeInferenceTimes(parsed.lastInferenceRequestAtByAccount),
|
|
113
|
+
lastRequestedWorkspaceId: typeof parsed.lastRequestedWorkspaceId === "string" && parsed.lastRequestedWorkspaceId.length <= 256 ? parsed.lastRequestedWorkspaceId : null,
|
|
83
114
|
runtimeMetrics: {
|
|
84
115
|
...base.runtimeMetrics,
|
|
85
116
|
...(parsed.runtimeMetrics ?? {}),
|
|
@@ -189,10 +220,19 @@ export function mutateRuntimeObservabilitySnapshot(mutator) {
|
|
|
189
220
|
if (!PERSIST_RUNTIME_SNAPSHOT) {
|
|
190
221
|
return;
|
|
191
222
|
}
|
|
192
|
-
|
|
223
|
+
// At most one write in flight and one queued: a burst of per-request
|
|
224
|
+
// mutations collapses into the latest snapshot instead of an unbounded chain.
|
|
225
|
+
const alreadyQueued = queuedSnapshot !== null;
|
|
226
|
+
queuedSnapshot = structuredClone(snapshot);
|
|
227
|
+
if (alreadyQueued)
|
|
228
|
+
return;
|
|
193
229
|
pendingWrite = (pendingWrite ?? Promise.resolve())
|
|
194
230
|
.catch(() => undefined)
|
|
195
|
-
.then(() =>
|
|
231
|
+
.then(() => {
|
|
232
|
+
const next = queuedSnapshot;
|
|
233
|
+
queuedSnapshot = null;
|
|
234
|
+
return next ? writeSnapshot(next) : undefined;
|
|
235
|
+
})
|
|
196
236
|
.catch(() => undefined);
|
|
197
237
|
}
|
|
198
238
|
export function recordRuntimePoolExhaustion(params) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CodexQuotaSnapshot } from "../quota-probe.js";
|
|
2
|
+
/** Only personal included subscriptions may receive an automatic first-use probe. */
|
|
3
|
+
export declare function needsSubscriptionFirstUse(snapshot: Omit<CodexQuotaSnapshot, "model">, now: number): boolean;
|
|
4
|
+
export declare class FirstUseProbeError extends Error {
|
|
5
|
+
readonly reason: "timed out" | "stream ended early" | "upstream failed" | "response too large" | "network error";
|
|
6
|
+
constructor(reason?: "timed out" | "stream ended early" | "upstream failed" | "response too large" | "network error");
|
|
7
|
+
}
|
|
8
|
+
/** Consume the already-open tiny response, never start a second request. */
|
|
9
|
+
export declare function finishSubscriptionFirstUse(response: Response, timeoutMs: number): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=subscription-first-use.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-first-use.d.ts","sourceRoot":"","sources":["../../../lib/runtime/subscription-first-use.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,qFAAqF;AACrF,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,IAAI,CAAC,kBAAkB,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAW3G;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAChC,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,oBAAoB,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,eAAe;gBAAvG,MAAM,GAAE,WAAW,GAAG,oBAAoB,GAAG,iBAAiB,GAAG,oBAAoB,GAAG,eAAsC;CAGnJ;AAED,4EAA4E;AAC5E,wBAAsB,0BAA0B,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBrG"}
|