@relayplane/proxy 1.8.39 → 1.9.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/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/provider-limits.d.ts +24 -0
- package/dist/provider-limits.d.ts.map +1 -0
- package/dist/provider-limits.js +42 -0
- package/dist/provider-limits.js.map +1 -0
- package/dist/standalone-proxy.d.ts.map +1 -1
- package/dist/standalone-proxy.js +107 -6
- package/dist/standalone-proxy.js.map +1 -1
- package/dist/token-pool.d.ts +104 -0
- package/dist/token-pool.d.ts.map +1 -0
- package/dist/token-pool.js +197 -0
- package/dist/token-pool.js.map +1 -0
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -26,9 +26,47 @@ export interface ProviderRateLimitConfig {
|
|
|
26
26
|
*/
|
|
27
27
|
rpm: number;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* A single named account (API key or OAT token) for a provider.
|
|
31
|
+
* Used to build the multi-account token pool.
|
|
32
|
+
*
|
|
33
|
+
* Example ~/.relayplane/config.json:
|
|
34
|
+
* ```json
|
|
35
|
+
* {
|
|
36
|
+
* "providers": {
|
|
37
|
+
* "anthropic": {
|
|
38
|
+
* "accounts": [
|
|
39
|
+
* { "label": "newmax", "apiKey": "sk-ant-oat01-...", "priority": 0 },
|
|
40
|
+
* { "label": "default", "apiKey": "sk-ant-oat01-...", "priority": 1 }
|
|
41
|
+
* ]
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export interface ProviderAccountConfig {
|
|
48
|
+
/** Human-readable label shown in the dashboard */
|
|
49
|
+
label: string;
|
|
50
|
+
/** API key or OAT token */
|
|
51
|
+
apiKey: string;
|
|
52
|
+
/**
|
|
53
|
+
* Selection priority — lower number = tried first.
|
|
54
|
+
* Default: 0.
|
|
55
|
+
*/
|
|
56
|
+
priority?: number;
|
|
57
|
+
}
|
|
29
58
|
export interface ProviderConfig {
|
|
30
59
|
/** Provider-level rate limit. Applies to all models for this provider unless overridden per-model. */
|
|
31
60
|
rateLimit?: ProviderRateLimitConfig;
|
|
61
|
+
/**
|
|
62
|
+
* Multi-account token pool. When present, the proxy will pool these
|
|
63
|
+
* tokens and select the best available one per request. Tokens with
|
|
64
|
+
* lower priority numbers are preferred. Rate-limited tokens are skipped.
|
|
65
|
+
*
|
|
66
|
+
* Backward compatible: if absent, the proxy falls back to the single-token
|
|
67
|
+
* flow (ANTHROPIC_API_KEY env var or incoming Authorization header).
|
|
68
|
+
*/
|
|
69
|
+
accounts?: ProviderAccountConfig[];
|
|
32
70
|
}
|
|
33
71
|
/**
|
|
34
72
|
* Cross-provider cascade configuration (GH #38).
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,sGAAsG;IACtG,SAAS,CAAC,EAAE,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider rate-limit static defaults.
|
|
3
|
+
*
|
|
4
|
+
* These are conservative best-known values used when no live header data has
|
|
5
|
+
* been received yet. The token pool will update them as real
|
|
6
|
+
* `anthropic-ratelimit-*` / `x-ratelimit-*` response headers are observed.
|
|
7
|
+
*/
|
|
8
|
+
export interface ProviderLimitDefaults {
|
|
9
|
+
/** Requests per minute (RPM) */
|
|
10
|
+
rpm: number;
|
|
11
|
+
/** Input tokens per minute */
|
|
12
|
+
tpm: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Keyed by `"provider:tier"` strings so different subscription tiers can have
|
|
16
|
+
* different defaults. The pool uses the key `"anthropic:default"` for
|
|
17
|
+
* standard API keys and `"anthropic:max"` for Claude Max (OAT) tokens.
|
|
18
|
+
*/
|
|
19
|
+
export declare const PROVIDER_LIMIT_DEFAULTS: Record<string, ProviderLimitDefaults>;
|
|
20
|
+
/**
|
|
21
|
+
* Return the best-known RPM default for a given provider + token type.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getDefaultRpm(provider: string, isMaxToken: boolean): number;
|
|
24
|
+
//# sourceMappingURL=provider-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-limits.d.ts","sourceRoot":"","sources":["../src/provider-limits.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,qBAAqB;IACpC,gCAAgC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAezE,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,MAAM,CAO3E"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Provider rate-limit static defaults.
|
|
4
|
+
*
|
|
5
|
+
* These are conservative best-known values used when no live header data has
|
|
6
|
+
* been received yet. The token pool will update them as real
|
|
7
|
+
* `anthropic-ratelimit-*` / `x-ratelimit-*` response headers are observed.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.PROVIDER_LIMIT_DEFAULTS = void 0;
|
|
11
|
+
exports.getDefaultRpm = getDefaultRpm;
|
|
12
|
+
/**
|
|
13
|
+
* Keyed by `"provider:tier"` strings so different subscription tiers can have
|
|
14
|
+
* different defaults. The pool uses the key `"anthropic:default"` for
|
|
15
|
+
* standard API keys and `"anthropic:max"` for Claude Max (OAT) tokens.
|
|
16
|
+
*/
|
|
17
|
+
exports.PROVIDER_LIMIT_DEFAULTS = {
|
|
18
|
+
// Anthropic — standard API key (Tier 1 / Free)
|
|
19
|
+
'anthropic:default': { rpm: 50, tpm: 40_000 },
|
|
20
|
+
// Anthropic — Claude Max subscription (OAT token)
|
|
21
|
+
'anthropic:max': { rpm: 60, tpm: 80_000 },
|
|
22
|
+
// OpenAI
|
|
23
|
+
'openai:default': { rpm: 60, tpm: 90_000 },
|
|
24
|
+
// OpenRouter
|
|
25
|
+
'openrouter:default': { rpm: 60, tpm: 100_000 },
|
|
26
|
+
// Google Gemini
|
|
27
|
+
'google:default': { rpm: 60, tpm: 100_000 },
|
|
28
|
+
// xAI Grok
|
|
29
|
+
'xai:default': { rpm: 60, tpm: 100_000 },
|
|
30
|
+
// Groq
|
|
31
|
+
'groq:default': { rpm: 30, tpm: 100_000 },
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Return the best-known RPM default for a given provider + token type.
|
|
35
|
+
*/
|
|
36
|
+
function getDefaultRpm(provider, isMaxToken) {
|
|
37
|
+
const tier = isMaxToken ? 'max' : 'default';
|
|
38
|
+
return (exports.PROVIDER_LIMIT_DEFAULTS[`${provider}:${tier}`]?.rpm ??
|
|
39
|
+
exports.PROVIDER_LIMIT_DEFAULTS[`${provider}:default`]?.rpm ??
|
|
40
|
+
50);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=provider-limits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-limits.js","sourceRoot":"","sources":["../src/provider-limits.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAkCH,sCAOC;AAhCD;;;;GAIG;AACU,QAAA,uBAAuB,GAA0C;IAC5E,+CAA+C;IAC/C,mBAAmB,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;IAC7C,kDAAkD;IAClD,eAAe,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;IACzC,SAAS;IACT,gBAAgB,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE;IAC1C,aAAa;IACb,oBAAoB,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;IAC/C,gBAAgB;IAChB,gBAAgB,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;IAC3C,WAAW;IACX,aAAa,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;IACxC,OAAO;IACP,cAAc,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE;CAC1C,CAAC;AAEF;;GAEG;AACH,SAAgB,aAAa,CAAC,QAAgB,EAAE,UAAmB;IACjE,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5C,OAAO,CACL,+BAAuB,CAAC,GAAG,QAAQ,IAAI,IAAI,EAAE,CAAC,EAAE,GAAG;QACnD,+BAAuB,CAAC,GAAG,QAAQ,UAAU,CAAC,EAAE,GAAG;QACnD,EAAE,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standalone-proxy.d.ts","sourceRoot":"","sources":["../src/standalone-proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAOlC,OAAO,KAAK,EAAE,QAAQ,IAAI,YAAY,EAAY,MAAM,kBAAkB,CAAC;AAE3E,KAAK,QAAQ,GAAG,YAAY,GACxB,YAAY,GACZ,UAAU,GACV,MAAM,GACN,SAAS,GACT,UAAU,GACV,WAAW,GACX,YAAY,GACZ,QAAQ,CAAC;AAOb,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"standalone-proxy.d.ts","sourceRoot":"","sources":["../src/standalone-proxy.ts"],"names":[],"mappings":"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"}
|
package/dist/standalone-proxy.js
CHANGED
|
@@ -98,6 +98,7 @@ const episode_writer_js_1 = require("./episode-writer.js");
|
|
|
98
98
|
const session_tracker_js_1 = require("./session-tracker.js");
|
|
99
99
|
const trace_writer_js_1 = require("./trace-writer.js");
|
|
100
100
|
const tool_router_js_1 = require("./tool-router.js");
|
|
101
|
+
const token_pool_js_1 = require("./token-pool.js");
|
|
101
102
|
const node_crypto_1 = require("node:crypto");
|
|
102
103
|
const PROXY_VERSION = (() => {
|
|
103
104
|
try {
|
|
@@ -2421,7 +2422,18 @@ function resolveProviderApiKey(provider, ctx, envApiKey) {
|
|
|
2421
2422
|
},
|
|
2422
2423
|
};
|
|
2423
2424
|
}
|
|
2424
|
-
|
|
2425
|
+
// Prefer env key when available; fall back to incoming auth (x-api-key or Authorization header).
|
|
2426
|
+
// This handles local proxy setups where ANTHROPIC_API_KEY is not set but the caller
|
|
2427
|
+
// forwards their token via x-api-key (e.g. OpenClaw relayplane provider).
|
|
2428
|
+
if (envApiKey)
|
|
2429
|
+
return { apiKey: envApiKey };
|
|
2430
|
+
if (ctx.apiKeyHeader)
|
|
2431
|
+
return { apiKey: ctx.apiKeyHeader };
|
|
2432
|
+
if (ctx.authHeader) {
|
|
2433
|
+
const token = ctx.authHeader.replace(/^Bearer\s+/i, '');
|
|
2434
|
+
return { apiKey: token };
|
|
2435
|
+
}
|
|
2436
|
+
return { apiKey: undefined };
|
|
2425
2437
|
}
|
|
2426
2438
|
// Ollama doesn't need an API key — it's local
|
|
2427
2439
|
if (provider === 'ollama') {
|
|
@@ -2575,9 +2587,10 @@ td{padding:8px 12px;border-bottom:1px solid #111318}
|
|
|
2575
2587
|
<table><thead><tr><th>Agent</th><th>Requests</th><th>Total Cost</th><th>Last Active</th><th></th></tr></thead><tbody id="agents"></tbody></table></div>
|
|
2576
2588
|
<div class="section"><h2>Provider Status</h2><div class="prov" id="providers"></div></div>
|
|
2577
2589
|
<div class="section collapsible collapsed"><h2>Learning</h2><div id="learning-panel" style="display:flex;flex-direction:column;gap:12px"><div id="learning-stats" style="display:flex;gap:12px;flex-wrap:wrap"></div><div id="learning-recent"></div></div></div>
|
|
2578
|
-
<div class="section collapsible
|
|
2590
|
+
<div class="section collapsible" id="sessions-section"><h2>Sessions <span id="sessionsLabel" style="font-size:.75rem;color:#64748b;font-weight:400">(last 7d)</span></h2>
|
|
2579
2591
|
<table><thead><tr><th>Session ID</th><th>Source</th><th>Started</th><th>Duration</th><th>Requests</th><th>Tokens In</th><th>Tokens Out</th><th>Cost</th><th>Models</th><th>Status</th></tr></thead><tbody id="sessions"></tbody></table>
|
|
2580
2592
|
</div>
|
|
2593
|
+
<div class="section collapsible collapsed" id="token-pool-section"><h2>Token Pool</h2><div id="token-pool-panel"></div></div>
|
|
2581
2594
|
<div class="section"><h2>Recent Runs <span id="historyLabel" style="font-size:.75rem;color:#64748b;font-weight:400">(7d window, history-capped)</span></h2>
|
|
2582
2595
|
<table><thead><tr><th>Time</th><th>Agent</th><th>Model</th><th class="col-tt">Task Type</th><th class="col-cx">Complexity</th><th>Tokens In</th><th>Tokens Out</th><th class="col-cache">Cache Create</th><th class="col-cache">Cache Read</th><th>Cost</th><th>Latency</th><th>Status</th></tr></thead><tbody id="runs"></tbody></table></div>
|
|
2583
2596
|
<script>
|
|
@@ -2752,7 +2765,28 @@ async function loadLearning(){
|
|
|
2752
2765
|
}
|
|
2753
2766
|
}catch(e){console.error('learning load error',e)}
|
|
2754
2767
|
}
|
|
2755
|
-
|
|
2768
|
+
async function loadTokenPool(){
|
|
2769
|
+
try{
|
|
2770
|
+
const data=await fetch('/v1/token-pool/status').then(r=>r.json()).catch(()=>null);
|
|
2771
|
+
const el=$('token-pool-panel');
|
|
2772
|
+
if(!el)return;
|
|
2773
|
+
if(!data||!data.accounts||data.accounts.length===0){
|
|
2774
|
+
el.innerHTML='<div style="color:#64748b;font-size:.85rem">No accounts registered. Add accounts under <code style="background:#1e293b;padding:2px 6px;border-radius:4px">providers.anthropic.accounts[]</code> in ~/.relayplane/config.json for multi-account pooling.</div>';
|
|
2775
|
+
return;
|
|
2776
|
+
}
|
|
2777
|
+
el.innerHTML='<table><thead><tr><th>Label</th><th>Source</th><th>Priority</th><th>Type</th><th>Req/min</th><th>RPM Limit</th><th>Status</th></tr></thead><tbody>'+
|
|
2778
|
+
data.accounts.map(function(a){
|
|
2779
|
+
const rl=a.rateLimitedUntil?'<span class="badge err">rate-limited until '+new Date(a.rateLimitedUntil).toLocaleTimeString()+'</span>':
|
|
2780
|
+
a.available?'<span class="badge ok">available</span>':'<span class="badge err-rate">throttled</span>';
|
|
2781
|
+
const type=a.isOat?'<span style="color:#60a5fa;font-size:.75rem">OAT/Max</span>':'<span style="color:#94a3b8;font-size:.75rem">API key</span>';
|
|
2782
|
+
const src=a.source==='config'?'<span style="color:#34d399;font-size:.75rem">config</span>':'<span style="color:#64748b;font-size:.75rem">auto</span>';
|
|
2783
|
+
const pct=a.knownRpmLimit>0?Math.round(a.requestsThisMinute/a.knownRpmLimit*100):0;
|
|
2784
|
+
const bar='<div style="background:#1e293b;border-radius:4px;height:6px;width:80px;display:inline-block;vertical-align:middle"><div style="background:'+(pct>=90?'#ef4444':pct>=70?'#fbbf24':'#34d399')+';height:100%;border-radius:4px;width:'+Math.min(pct,100)+'%"></div></div>';
|
|
2785
|
+
return '<tr><td>'+esc(a.label)+'</td><td>'+src+'</td><td>'+a.priority+'</td><td>'+type+'</td><td>'+a.requestsThisMinute+' '+bar+'</td><td>'+a.knownRpmLimit+' rpm</td><td>'+rl+'</td></tr>';
|
|
2786
|
+
}).join('')+'</tbody></table>';
|
|
2787
|
+
}catch(e){console.error('token pool load error',e)}
|
|
2788
|
+
}
|
|
2789
|
+
load();loadLearning();loadSessions();loadTokenPool();setInterval(load,5000);setInterval(loadLearning,30000);setInterval(loadSessions,10000);setInterval(loadTokenPool,10000);
|
|
2756
2790
|
</script><footer style="text-align:center;padding:20px 0;color:#475569;font-size:.75rem;border-top:1px solid #1e293b;margin-top:20px">🔒 Request content stays on your machine. Never sent to cloud.</footer></body></html>`;
|
|
2757
2791
|
}
|
|
2758
2792
|
async function getKnowledgeStats() {
|
|
@@ -3028,6 +3062,20 @@ async function startProxy(config = {}) {
|
|
|
3028
3062
|
_activeProxyConfig = proxyConfig;
|
|
3029
3063
|
_activeOllamaConfig = proxyConfig.ollama;
|
|
3030
3064
|
const cooldownManager = new CooldownManager(getCooldownConfig(proxyConfig));
|
|
3065
|
+
// === Token pool: register explicit config accounts ===
|
|
3066
|
+
{
|
|
3067
|
+
const userCfg = (0, config_js_1.loadConfig)();
|
|
3068
|
+
const anthropicAccounts = userCfg.providers?.['anthropic']?.accounts;
|
|
3069
|
+
if (anthropicAccounts && anthropicAccounts.length > 0) {
|
|
3070
|
+
const poolAccounts = anthropicAccounts.map((a) => ({
|
|
3071
|
+
label: a.label,
|
|
3072
|
+
apiKey: a.apiKey,
|
|
3073
|
+
priority: a.priority ?? 0,
|
|
3074
|
+
}));
|
|
3075
|
+
(0, token_pool_js_1.getTokenPool)().registerConfigAccounts(poolAccounts);
|
|
3076
|
+
console.log(`[RelayPlane] Token pool: ${anthropicAccounts.length} configured account(s) registered`);
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3031
3079
|
// === Ollama provider initialization ===
|
|
3032
3080
|
if (_activeOllamaConfig?.enabled !== false && _activeOllamaConfig?.models?.length) {
|
|
3033
3081
|
const ollamaUrl = _activeOllamaConfig.baseUrl ?? ollama_js_1.OLLAMA_DEFAULTS.baseUrl;
|
|
@@ -3893,6 +3941,12 @@ async function startProxy(config = {}) {
|
|
|
3893
3941
|
res.end(getConfigDashboardHTML());
|
|
3894
3942
|
return;
|
|
3895
3943
|
}
|
|
3944
|
+
// === Token pool status endpoint ===
|
|
3945
|
+
if (req.method === 'GET' && pathname === '/v1/token-pool/status') {
|
|
3946
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
3947
|
+
res.end(JSON.stringify((0, token_pool_js_1.getTokenPool)().getStatus()));
|
|
3948
|
+
return;
|
|
3949
|
+
}
|
|
3896
3950
|
// === Mesh stats endpoint ===
|
|
3897
3951
|
// === Ollama status endpoint ===
|
|
3898
3952
|
if (req.method === 'GET' && pathname === '/v1/ollama/status') {
|
|
@@ -4180,9 +4234,32 @@ async function startProxy(config = {}) {
|
|
|
4180
4234
|
const headerModelOverride = getHeaderValue(req, 'x-relayplane-model');
|
|
4181
4235
|
const relayplaneEnabled = proxyConfig.enabled !== false;
|
|
4182
4236
|
const recordTelemetry = relayplaneEnabled && !relayplaneBypass;
|
|
4183
|
-
//
|
|
4237
|
+
// === Token pool: auto-detect incoming token ===
|
|
4238
|
+
{
|
|
4239
|
+
const incomingToken = ctx.authHeader
|
|
4240
|
+
? ctx.authHeader.replace(/^Bearer\s+/i, '')
|
|
4241
|
+
: ctx.apiKeyHeader;
|
|
4242
|
+
if (incomingToken) {
|
|
4243
|
+
(0, token_pool_js_1.getTokenPool)().autoDetect(incomingToken);
|
|
4244
|
+
}
|
|
4245
|
+
}
|
|
4246
|
+
// Determine which Anthropic auth to use based on mode.
|
|
4247
|
+
// When the token pool has registered accounts, select the best token from
|
|
4248
|
+
// the pool and use it as the effective key (overrides env and passthrough).
|
|
4184
4249
|
let useAnthropicEnvKey;
|
|
4185
|
-
|
|
4250
|
+
let _poolSelectedToken; // tracks the token chosen from the pool for this request
|
|
4251
|
+
if ((0, token_pool_js_1.getTokenPool)().size() > 0) {
|
|
4252
|
+
const poolToken = (0, token_pool_js_1.getTokenPool)().selectToken();
|
|
4253
|
+
if (poolToken) {
|
|
4254
|
+
_poolSelectedToken = poolToken.apiKey;
|
|
4255
|
+
useAnthropicEnvKey = poolToken.apiKey;
|
|
4256
|
+
}
|
|
4257
|
+
else {
|
|
4258
|
+
// All tokens exhausted — fall back to normal resolution
|
|
4259
|
+
useAnthropicEnvKey = anthropicAuthMode === 'passthrough' ? undefined : anthropicEnvKey;
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
else if (anthropicAuthMode === 'env') {
|
|
4186
4263
|
useAnthropicEnvKey = anthropicEnvKey;
|
|
4187
4264
|
}
|
|
4188
4265
|
else if (anthropicAuthMode === 'passthrough') {
|
|
@@ -4693,7 +4770,31 @@ async function startProxy(config = {}) {
|
|
|
4693
4770
|
if (isRerouted) {
|
|
4694
4771
|
log(`Rerouted: ${originalModel} → ${finalModel} (auth fallback enabled)`);
|
|
4695
4772
|
}
|
|
4696
|
-
|
|
4773
|
+
// Build pool-aware context: when the pool is managing auth, clear incoming
|
|
4774
|
+
// auth headers so buildAnthropicHeadersWithAuth uses the pool token instead.
|
|
4775
|
+
const _nativeReqCtx = _poolSelectedToken
|
|
4776
|
+
? { ...ctx, authHeader: undefined, apiKeyHeader: undefined }
|
|
4777
|
+
: ctx;
|
|
4778
|
+
let providerResponse = await forwardNativeAnthropicRequest({ ...requestBody, model: finalModel }, _nativeReqCtx, modelAuth.apiKey, modelAuth.isMax, isRerouted);
|
|
4779
|
+
// Token pool: on 429, record and retry with next available token
|
|
4780
|
+
if (providerResponse.status === 429 && _poolSelectedToken) {
|
|
4781
|
+
const _poolRetryAfterHeader = providerResponse.headers.get('retry-after');
|
|
4782
|
+
const _poolRetryAfterS = _poolRetryAfterHeader ? parseInt(_poolRetryAfterHeader, 10) : undefined;
|
|
4783
|
+
(0, token_pool_js_1.getTokenPool)().record429(_poolSelectedToken, _poolRetryAfterS !== undefined && !isNaN(_poolRetryAfterS) ? _poolRetryAfterS : undefined);
|
|
4784
|
+
const _nextPoolToken = (0, token_pool_js_1.getTokenPool)().selectToken();
|
|
4785
|
+
if (_nextPoolToken) {
|
|
4786
|
+
log(`[TokenPool] 429 on token …${_poolSelectedToken.slice(-8)} — retrying with "${_nextPoolToken.label}"`);
|
|
4787
|
+
_poolSelectedToken = _nextPoolToken.apiKey;
|
|
4788
|
+
const _retryCtx = { ...ctx, authHeader: undefined, apiKeyHeader: undefined };
|
|
4789
|
+
providerResponse = await forwardNativeAnthropicRequest({ ...requestBody, model: finalModel }, _retryCtx, _nextPoolToken.apiKey, _nextPoolToken.isOat, isRerouted);
|
|
4790
|
+
}
|
|
4791
|
+
}
|
|
4792
|
+
// Token pool: learn rate limits from upstream response headers
|
|
4793
|
+
if (_poolSelectedToken && providerResponse.ok) {
|
|
4794
|
+
const _upstreamHeaders = {};
|
|
4795
|
+
providerResponse.headers.forEach((v, k) => { _upstreamHeaders[k] = v; });
|
|
4796
|
+
(0, token_pool_js_1.getTokenPool)().recordResponseHeaders(_poolSelectedToken, _upstreamHeaders);
|
|
4797
|
+
}
|
|
4697
4798
|
if (!providerResponse.ok) {
|
|
4698
4799
|
const errorPayload = (await providerResponse.json());
|
|
4699
4800
|
if (proxyConfig.reliability?.cooldowns?.enabled) {
|