@bitkyc08/opencodex 2.7.9 → 2.7.10
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/gui/dist/assets/index-BU5WLK6k.js +40 -0
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/providers/key-failover.ts +26 -0
- package/src/providers/registry.ts +3 -0
- package/src/router.ts +7 -2
- package/src/server/responses.ts +15 -9
- package/gui/dist/assets/index-BAAFKwsh.js +0 -40
package/gui/dist/index.html
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
} catch (e) {}
|
|
17
17
|
})();
|
|
18
18
|
</script>
|
|
19
|
-
<script type="module" crossorigin src="/assets/index-
|
|
19
|
+
<script type="module" crossorigin src="/assets/index-BU5WLK6k.js"></script>
|
|
20
20
|
<link rel="stylesheet" crossorigin href="/assets/index-Cq8maiJf.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
package/package.json
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { saveConfig } from "../config";
|
|
12
12
|
import type { OcxConfig, OcxProviderConfig } from "../types";
|
|
13
|
+
import { resolveProviderTransport } from "./xai-transport";
|
|
13
14
|
|
|
14
15
|
// ---- cooldown state (in-memory, same as codex/routing.ts) ----
|
|
15
16
|
|
|
@@ -125,6 +126,31 @@ export function rotateKeyOn429(
|
|
|
125
126
|
return null;
|
|
126
127
|
}
|
|
127
128
|
|
|
129
|
+
interface RotateProviderTransportOptions {
|
|
130
|
+
retryAfter?: string | null;
|
|
131
|
+
now?: number;
|
|
132
|
+
attemptedKey?: string;
|
|
133
|
+
promptCacheKey?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Rotate a failed key and re-apply provider-specific transport metadata to the replacement. */
|
|
137
|
+
export function rotateProviderTransportOn429(
|
|
138
|
+
config: OcxConfig,
|
|
139
|
+
providerName: string,
|
|
140
|
+
options: RotateProviderTransportOptions = {},
|
|
141
|
+
): OcxProviderConfig | null {
|
|
142
|
+
const rotated = rotateKeyOn429(
|
|
143
|
+
config,
|
|
144
|
+
providerName,
|
|
145
|
+
options.retryAfter,
|
|
146
|
+
options.now,
|
|
147
|
+
options.attemptedKey,
|
|
148
|
+
);
|
|
149
|
+
return rotated
|
|
150
|
+
? resolveProviderTransport(providerName, rotated, options.promptCacheKey)
|
|
151
|
+
: null;
|
|
152
|
+
}
|
|
153
|
+
|
|
128
154
|
/** Clear cooldown state for a provider (e.g. after manual key management). */
|
|
129
155
|
export function clearKeyCooldowns(providerName?: string): void {
|
|
130
156
|
if (!providerName) {
|
|
@@ -18,6 +18,8 @@ export interface ProviderRegistryEntry {
|
|
|
18
18
|
adapter: string;
|
|
19
19
|
baseUrl: string;
|
|
20
20
|
authKind: ProviderAuthKind;
|
|
21
|
+
/** OAuth preset may explicitly honor a persisted API-key billing mode. */
|
|
22
|
+
allowKeyAuthOverride?: boolean;
|
|
21
23
|
allowPrivateNetworkByDefault?: boolean;
|
|
22
24
|
keyOptional?: boolean;
|
|
23
25
|
allowBaseUrlOverride?: boolean;
|
|
@@ -219,6 +221,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
219
221
|
adapter: "openai-chat",
|
|
220
222
|
baseUrl: "https://api.x.ai/v1",
|
|
221
223
|
authKind: "oauth",
|
|
224
|
+
allowKeyAuthOverride: true,
|
|
222
225
|
featured: true,
|
|
223
226
|
oauthId: "xai",
|
|
224
227
|
jawcodeBundle: "xai",
|
package/src/router.ts
CHANGED
|
@@ -84,8 +84,13 @@ function routedProviderConfig(providerName: string, provider: OcxProviderConfig)
|
|
|
84
84
|
assertProviderDestinationAllowed(providerName, provider);
|
|
85
85
|
return { ...provider, apiKey: resolveEnvValue(provider.apiKey) };
|
|
86
86
|
}
|
|
87
|
-
const
|
|
88
|
-
|
|
87
|
+
const explicitKeyOverride = registryEntry.authKind === "oauth"
|
|
88
|
+
&& registryEntry.allowKeyAuthOverride === true
|
|
89
|
+
&& provider.authMode === "key";
|
|
90
|
+
const canonicalAuthMode = explicitKeyOverride
|
|
91
|
+
? "key"
|
|
92
|
+
: registryEntry.authKind === "forward" || registryEntry.authKind === "oauth"
|
|
93
|
+
? registryEntry.authKind
|
|
89
94
|
: provider.authMode === "forward" ? undefined : provider.authMode;
|
|
90
95
|
const reasoningEffortMap = mergeRecord(registryEntry.reasoningEffortMap, provider.reasoningEffortMap);
|
|
91
96
|
const modelReasoningEffortMap = mergeNestedRecord(registryEntry.modelReasoningEffortMap, provider.modelReasoningEffortMap);
|
package/src/server/responses.ts
CHANGED
|
@@ -40,7 +40,7 @@ import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
|
40
40
|
import { isUsageDebugEnabled } from "../usage/debug";
|
|
41
41
|
import { readJsonRequestBody, DecompressedBodyTooLargeError, UnsupportedContentEncodingError } from "./request-decompress";
|
|
42
42
|
import { resolveAdapter, resolveWireProtocolOverride } from "./adapter-resolve";
|
|
43
|
-
import { hasKeyPoolFailover,
|
|
43
|
+
import { hasKeyPoolFailover, rotateProviderTransportOn429 } from "../providers/key-failover";
|
|
44
44
|
import { resolveProviderTransport } from "../providers/xai-transport";
|
|
45
45
|
import type { WsData } from "./ws-bridge";
|
|
46
46
|
import { registerTurn, trackStreamLifetime, unregisterTurn } from "./lifecycle";
|
|
@@ -886,11 +886,14 @@ export async function handleResponses(
|
|
|
886
886
|
routedModelStallTimeoutMs: wsPlan.routedModelStallTimeoutMs,
|
|
887
887
|
stallTimeoutSec: wsPlan.stallTimeoutSec,
|
|
888
888
|
on429: retryAfter => {
|
|
889
|
-
const rotated =
|
|
889
|
+
const rotated = rotateProviderTransportOn429(config, route.providerName, {
|
|
890
|
+
retryAfter,
|
|
891
|
+
now: Date.now(),
|
|
892
|
+
attemptedKey: route.provider.apiKey,
|
|
893
|
+
promptCacheKey: parsed.options.promptCacheKey,
|
|
894
|
+
});
|
|
890
895
|
if (!rotated) return null;
|
|
891
|
-
|
|
892
|
-
// line ~616 survive the key rotation (rotated providers come from raw config).
|
|
893
|
-
route.provider = resolveProviderTransport(route.providerName, rotated, parsed.options.promptCacheKey);
|
|
896
|
+
route.provider = rotated;
|
|
894
897
|
return resolveAdapter(
|
|
895
898
|
resolveWireProtocolOverride(route.providerName, route.modelId, route.provider),
|
|
896
899
|
config.cacheRetention,
|
|
@@ -941,14 +944,17 @@ export async function handleResponses(
|
|
|
941
944
|
// request once per remaining key. OAuth/forward providers and single-key pools return null
|
|
942
945
|
// immediately, so this stays a no-op for them (src/providers/key-failover.ts).
|
|
943
946
|
while (upstreamResponse.status === 429 && hasKeyPoolFailover(route.provider)) {
|
|
944
|
-
const rotated =
|
|
947
|
+
const rotated = rotateProviderTransportOn429(config, route.providerName, {
|
|
948
|
+
retryAfter: upstreamResponse.headers.get("retry-after"),
|
|
949
|
+
now: Date.now(),
|
|
950
|
+
attemptedKey: route.provider.apiKey,
|
|
951
|
+
promptCacheKey: parsed.options.promptCacheKey,
|
|
952
|
+
});
|
|
945
953
|
if (!rotated) break;
|
|
946
954
|
// Release the failed response's socket before retrying; unread bodies otherwise linger
|
|
947
955
|
// until runtime cleanup (one per rotated key under a rate-limit storm).
|
|
948
956
|
try { void upstreamResponse.body?.cancel().catch(() => {}); } catch { /* already consumed/closed */ }
|
|
949
|
-
|
|
950
|
-
// headers on the retried request instead of silently reverting to the raw config provider.
|
|
951
|
-
route.provider = resolveProviderTransport(route.providerName, rotated, parsed.options.promptCacheKey);
|
|
957
|
+
route.provider = rotated;
|
|
952
958
|
const retryAdapter = resolveAdapter(
|
|
953
959
|
resolveWireProtocolOverride(route.providerName, route.modelId, route.provider),
|
|
954
960
|
config.cacheRetention,
|