@routstr/sdk 0.2.6 → 0.2.8
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/client/index.d.mts +16 -2
- package/dist/client/index.d.ts +16 -2
- package/dist/client/index.js +342 -87
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +342 -87
- package/dist/client/index.mjs.map +1 -1
- package/dist/discovery/index.js +1 -1
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +1 -1
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/index.d.mts +9 -5
- package/dist/index.d.ts +9 -5
- package/dist/index.js +347 -91
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +347 -91
- package/dist/index.mjs.map +1 -1
- package/dist/storage/index.d.mts +5 -2
- package/dist/storage/index.d.ts +5 -2
- package/dist/storage/index.js +95 -4
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +95 -4
- package/dist/storage/index.mjs.map +1 -1
- package/dist/{store-C5lnyX8k.d.mts → store-DGeLPv9E.d.mts} +21 -0
- package/dist/{store-BJlwiDX5.d.ts → store-h7m23ffq.d.ts} +21 -0
- package/dist/wallet/index.d.mts +11 -4
- package/dist/wallet/index.d.ts +11 -4
- package/dist/wallet/index.js +83 -41
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +83 -41
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var applesauceRelay = require('applesauce-relay');
|
|
4
4
|
var applesauceCore = require('applesauce-core');
|
|
5
5
|
var rxjs = require('rxjs');
|
|
6
|
+
var cashuTs = require('@cashu/cashu-ts');
|
|
6
7
|
var vanilla = require('zustand/vanilla');
|
|
7
8
|
var stream = require('stream');
|
|
8
9
|
|
|
@@ -468,7 +469,7 @@ var ModelManager = class _ModelManager {
|
|
|
468
469
|
}
|
|
469
470
|
}
|
|
470
471
|
const DEFAULT_RELAYS = [
|
|
471
|
-
"wss://relay.
|
|
472
|
+
"wss://relay.damus.io",
|
|
472
473
|
"wss://nos.lol",
|
|
473
474
|
"wss://relay.routstr.com"
|
|
474
475
|
];
|
|
@@ -735,8 +736,6 @@ function selectMintWithBalance(balances, units, amount, excludeMints = []) {
|
|
|
735
736
|
}
|
|
736
737
|
return { selectedMintUrl: null, selectedMintBalance: 0 };
|
|
737
738
|
}
|
|
738
|
-
|
|
739
|
-
// wallet/CashuSpender.ts
|
|
740
739
|
var CashuSpender = class {
|
|
741
740
|
constructor(walletAdapter, storageAdapter, _providerRegistry, balanceManager) {
|
|
742
741
|
this.walletAdapter = walletAdapter;
|
|
@@ -747,23 +746,43 @@ var CashuSpender = class {
|
|
|
747
746
|
_isBusy = false;
|
|
748
747
|
debugLevel = "WARN";
|
|
749
748
|
async receiveToken(token) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
749
|
+
try {
|
|
750
|
+
const result = await this.walletAdapter.receiveToken(token);
|
|
751
|
+
return result;
|
|
752
|
+
} catch (error) {
|
|
753
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
754
|
+
if (errorMessage.includes("Failed to fetch mint")) {
|
|
755
|
+
const cachedTokens = this.storageAdapter.getCachedReceiveTokens();
|
|
756
|
+
const existingIndex = cachedTokens.findIndex((t) => t.token === token);
|
|
757
|
+
if (existingIndex === -1) {
|
|
758
|
+
const { amount: amount2, unit: unit2 } = this._decodeTokenAmount(token);
|
|
759
|
+
this.storageAdapter.setCachedReceiveTokens([
|
|
760
|
+
...cachedTokens,
|
|
761
|
+
{
|
|
762
|
+
token,
|
|
763
|
+
amount: amount2,
|
|
764
|
+
unit: unit2,
|
|
765
|
+
createdAt: Date.now()
|
|
766
|
+
}
|
|
767
|
+
]);
|
|
768
|
+
}
|
|
764
769
|
}
|
|
770
|
+
const { amount, unit } = this._decodeTokenAmount(token);
|
|
771
|
+
return { success: false, amount, unit, message: errorMessage };
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
_decodeTokenAmount(token) {
|
|
775
|
+
try {
|
|
776
|
+
const decoded = cashuTs.getDecodedToken(token);
|
|
777
|
+
const amount = decoded.proofs.reduce(
|
|
778
|
+
(acc, proof) => acc + proof.amount,
|
|
779
|
+
0
|
|
780
|
+
);
|
|
781
|
+
const unit = decoded.unit || "sat";
|
|
782
|
+
return { amount, unit };
|
|
783
|
+
} catch {
|
|
784
|
+
return { amount: 0, unit: "sat" };
|
|
765
785
|
}
|
|
766
|
-
return result;
|
|
767
786
|
}
|
|
768
787
|
async _getBalanceState() {
|
|
769
788
|
if (this.balanceManager) {
|
|
@@ -1083,8 +1102,9 @@ var CashuSpender = class {
|
|
|
1083
1102
|
return null;
|
|
1084
1103
|
}
|
|
1085
1104
|
/**
|
|
1086
|
-
* Refund all xcashu tokens from storage
|
|
1087
|
-
*
|
|
1105
|
+
* Refund all xcashu tokens from storage by calling the provider's refund endpoint.
|
|
1106
|
+
* The xcashu token acts as an API key to claim the refund, and the response contains
|
|
1107
|
+
* the actual refunded Cashu token which is then received into the wallet.
|
|
1088
1108
|
* @param mintUrl - The mint URL for receiving tokens
|
|
1089
1109
|
* @param excludeBaseUrls - Base URLs to exclude from refund (optional)
|
|
1090
1110
|
* @returns Results for each xcashu token refund attempt
|
|
@@ -1097,7 +1117,20 @@ var CashuSpender = class {
|
|
|
1097
1117
|
if (excludedUrls.has(baseUrl)) continue;
|
|
1098
1118
|
for (const xcashuToken of tokens) {
|
|
1099
1119
|
try {
|
|
1100
|
-
|
|
1120
|
+
if (!this.balanceManager) {
|
|
1121
|
+
throw new Error("BalanceManager not available for xcashu refund");
|
|
1122
|
+
}
|
|
1123
|
+
const fetchResult = await this.balanceManager.fetchRefundToken(
|
|
1124
|
+
baseUrl,
|
|
1125
|
+
xcashuToken.token,
|
|
1126
|
+
true
|
|
1127
|
+
);
|
|
1128
|
+
if (!fetchResult.success || !fetchResult.token) {
|
|
1129
|
+
throw new Error(
|
|
1130
|
+
fetchResult.error || "Failed to fetch refund token from provider"
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
const receiveResult = await this.receiveToken(fetchResult.token);
|
|
1101
1134
|
if (receiveResult.success) {
|
|
1102
1135
|
this.storageAdapter.removeXcashuToken(baseUrl, xcashuToken.token);
|
|
1103
1136
|
results.push({
|
|
@@ -1112,7 +1145,10 @@ var CashuSpender = class {
|
|
|
1112
1145
|
} else {
|
|
1113
1146
|
const currentTryCount = xcashuToken.tryCount ?? 0;
|
|
1114
1147
|
const newTryCount = currentTryCount + 1;
|
|
1115
|
-
this.storageAdapter.updateXcashuTokenTryCount(
|
|
1148
|
+
this.storageAdapter.updateXcashuTokenTryCount(
|
|
1149
|
+
xcashuToken.token,
|
|
1150
|
+
newTryCount
|
|
1151
|
+
);
|
|
1116
1152
|
results.push({
|
|
1117
1153
|
baseUrl,
|
|
1118
1154
|
token: xcashuToken.token,
|
|
@@ -1121,13 +1157,16 @@ var CashuSpender = class {
|
|
|
1121
1157
|
});
|
|
1122
1158
|
this._log(
|
|
1123
1159
|
"DEBUG",
|
|
1124
|
-
`[CashuSpender] refundXcashuTokens: Failed to refund
|
|
1160
|
+
`[CashuSpender] refundXcashuTokens: Failed to receive refund token for ${baseUrl}, incremented tryCount to ${newTryCount}: ${receiveResult.message}`
|
|
1125
1161
|
);
|
|
1126
1162
|
}
|
|
1127
1163
|
} catch (error) {
|
|
1128
1164
|
const currentTryCount = xcashuToken.tryCount ?? 0;
|
|
1129
1165
|
const newTryCount = currentTryCount + 1;
|
|
1130
|
-
this.storageAdapter.updateXcashuTokenTryCount(
|
|
1166
|
+
this.storageAdapter.updateXcashuTokenTryCount(
|
|
1167
|
+
xcashuToken.token,
|
|
1168
|
+
newTryCount
|
|
1169
|
+
);
|
|
1131
1170
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1132
1171
|
results.push({
|
|
1133
1172
|
baseUrl,
|
|
@@ -1164,7 +1203,10 @@ var CashuSpender = class {
|
|
|
1164
1203
|
if (refundResult.success) {
|
|
1165
1204
|
this.storageAdapter.removeApiKey(apiKeyEntry.baseUrl);
|
|
1166
1205
|
} else {
|
|
1167
|
-
this.storageAdapter.updateApiKeyBalance(
|
|
1206
|
+
this.storageAdapter.updateApiKeyBalance(
|
|
1207
|
+
apiKeyEntry.baseUrl,
|
|
1208
|
+
apiKeyEntry.amount
|
|
1209
|
+
);
|
|
1168
1210
|
}
|
|
1169
1211
|
results.push({
|
|
1170
1212
|
baseUrl: apiKeyEntry.baseUrl,
|
|
@@ -1302,7 +1344,7 @@ var BalanceManager = class {
|
|
|
1302
1344
|
}
|
|
1303
1345
|
let fetchResult;
|
|
1304
1346
|
try {
|
|
1305
|
-
fetchResult = await this.
|
|
1347
|
+
fetchResult = await this.fetchRefundToken(baseUrl, apiKey);
|
|
1306
1348
|
if (!fetchResult.success) {
|
|
1307
1349
|
return {
|
|
1308
1350
|
success: false,
|
|
@@ -1330,6 +1372,7 @@ var BalanceManager = class {
|
|
|
1330
1372
|
return {
|
|
1331
1373
|
success: receiveResult.success,
|
|
1332
1374
|
refundedAmount: totalAmountMsat,
|
|
1375
|
+
message: receiveResult.message,
|
|
1333
1376
|
requestId: fetchResult.requestId
|
|
1334
1377
|
};
|
|
1335
1378
|
} catch (error) {
|
|
@@ -1338,9 +1381,9 @@ var BalanceManager = class {
|
|
|
1338
1381
|
}
|
|
1339
1382
|
}
|
|
1340
1383
|
/**
|
|
1341
|
-
* Fetch refund token from provider API using API key authentication
|
|
1384
|
+
* Fetch refund token from provider API using API key (or xcashu token) authentication
|
|
1342
1385
|
*/
|
|
1343
|
-
async
|
|
1386
|
+
async fetchRefundToken(baseUrl, apiKeyOrToken, xCashu = false) {
|
|
1344
1387
|
if (!baseUrl) {
|
|
1345
1388
|
return {
|
|
1346
1389
|
success: false,
|
|
@@ -1354,12 +1397,17 @@ var BalanceManager = class {
|
|
|
1354
1397
|
controller.abort();
|
|
1355
1398
|
}, 6e4);
|
|
1356
1399
|
try {
|
|
1400
|
+
const headers = {
|
|
1401
|
+
"Content-Type": "application/json"
|
|
1402
|
+
};
|
|
1403
|
+
if (xCashu) {
|
|
1404
|
+
headers["X-Cashu"] = apiKeyOrToken;
|
|
1405
|
+
} else {
|
|
1406
|
+
headers["Authorization"] = `Bearer ${apiKeyOrToken}`;
|
|
1407
|
+
}
|
|
1357
1408
|
const response = await fetch(url, {
|
|
1358
1409
|
method: "POST",
|
|
1359
|
-
headers
|
|
1360
|
-
Authorization: `Bearer ${apiKey}`,
|
|
1361
|
-
"Content-Type": "application/json"
|
|
1362
|
-
},
|
|
1410
|
+
headers,
|
|
1363
1411
|
signal: controller.signal
|
|
1364
1412
|
});
|
|
1365
1413
|
clearTimeout(timeoutId);
|
|
@@ -1380,10 +1428,7 @@ var BalanceManager = class {
|
|
|
1380
1428
|
};
|
|
1381
1429
|
} catch (error) {
|
|
1382
1430
|
clearTimeout(timeoutId);
|
|
1383
|
-
console.error(
|
|
1384
|
-
"[BalanceManager._fetchRefundTokenWithApiKey] Fetch error",
|
|
1385
|
-
error
|
|
1386
|
-
);
|
|
1431
|
+
console.error("[BalanceManager.fetchRefundToken] Fetch error", error);
|
|
1387
1432
|
if (error instanceof Error) {
|
|
1388
1433
|
if (error.name === "AbortError") {
|
|
1389
1434
|
return {
|
|
@@ -1430,11 +1475,7 @@ var BalanceManager = class {
|
|
|
1430
1475
|
};
|
|
1431
1476
|
}
|
|
1432
1477
|
cashuToken = tokenResult.token;
|
|
1433
|
-
const topUpResult = await this._postTopUp(
|
|
1434
|
-
baseUrl,
|
|
1435
|
-
apiKey,
|
|
1436
|
-
cashuToken
|
|
1437
|
-
);
|
|
1478
|
+
const topUpResult = await this._postTopUp(baseUrl, apiKey, cashuToken);
|
|
1438
1479
|
requestId = topUpResult.requestId;
|
|
1439
1480
|
console.log(topUpResult);
|
|
1440
1481
|
if (!topUpResult.success) {
|
|
@@ -1800,7 +1841,7 @@ var BalanceManager = class {
|
|
|
1800
1841
|
console.log(response.status);
|
|
1801
1842
|
const data = await response.json();
|
|
1802
1843
|
console.log("FAILED ", data);
|
|
1803
|
-
const isInvalidApiKey = response.status === 401 && data?.code === "invalid_api_key" && data?.message?.includes("proofs already spent");
|
|
1844
|
+
const isInvalidApiKey = response.status === 401 && data?.detail?.error?.code === "invalid_api_key" && data?.detail?.error?.message?.includes("proofs already spent");
|
|
1804
1845
|
return {
|
|
1805
1846
|
amount: -1,
|
|
1806
1847
|
reserved: data.reserved ?? 0,
|
|
@@ -2298,8 +2339,13 @@ function isInsecureHttpUrl(url) {
|
|
|
2298
2339
|
return url.startsWith("http://");
|
|
2299
2340
|
}
|
|
2300
2341
|
var ProviderManager = class _ProviderManager {
|
|
2301
|
-
constructor(providerRegistry) {
|
|
2342
|
+
constructor(providerRegistry, store) {
|
|
2302
2343
|
this.providerRegistry = providerRegistry;
|
|
2344
|
+
this.instanceId = `pm_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2345
|
+
if (store) {
|
|
2346
|
+
this.store = store;
|
|
2347
|
+
this.hydrateFromStore();
|
|
2348
|
+
}
|
|
2303
2349
|
}
|
|
2304
2350
|
failedProviders = /* @__PURE__ */ new Set();
|
|
2305
2351
|
/** Track when each provider last failed (provider URL -> timestamp) */
|
|
@@ -2308,14 +2354,57 @@ var ProviderManager = class _ProviderManager {
|
|
|
2308
2354
|
providersOnCoolDown = [];
|
|
2309
2355
|
/** Cooldown duration in milliseconds (5 minutes) */
|
|
2310
2356
|
static COOLDOWN_DURATION_MS = 5 * 60 * 1e3;
|
|
2357
|
+
/** Optional persistent store for failure tracking */
|
|
2358
|
+
store = null;
|
|
2359
|
+
/** Instance ID for debugging */
|
|
2360
|
+
instanceId;
|
|
2361
|
+
/**
|
|
2362
|
+
* Hydrate in-memory state from persistent store
|
|
2363
|
+
*/
|
|
2364
|
+
hydrateFromStore() {
|
|
2365
|
+
if (!this.store) return;
|
|
2366
|
+
const state = this.store.getState();
|
|
2367
|
+
this.failedProviders = new Set(state.failedProviders);
|
|
2368
|
+
this.lastFailed = new Map(Object.entries(state.lastFailed));
|
|
2369
|
+
const now = Date.now();
|
|
2370
|
+
this.providersOnCoolDown = state.providersOnCooldown.filter(
|
|
2371
|
+
(entry) => now - entry.timestamp < _ProviderManager.COOLDOWN_DURATION_MS
|
|
2372
|
+
).map((entry) => [entry.baseUrl, entry.timestamp]);
|
|
2373
|
+
console.log(`[ProviderManager:${this.instanceId}] Hydrated from store:`);
|
|
2374
|
+
console.log(` failedProviders: ${this.failedProviders.size}`);
|
|
2375
|
+
console.log(` lastFailed: ${this.lastFailed.size}`);
|
|
2376
|
+
console.log(` providersOnCooldown: ${this.providersOnCoolDown.length}`);
|
|
2377
|
+
}
|
|
2378
|
+
/**
|
|
2379
|
+
* Get instance ID for debugging
|
|
2380
|
+
*/
|
|
2381
|
+
getInstanceId() {
|
|
2382
|
+
return this.instanceId;
|
|
2383
|
+
}
|
|
2311
2384
|
/**
|
|
2312
2385
|
* Clean up expired cooldown entries
|
|
2313
2386
|
*/
|
|
2314
2387
|
cleanupExpiredCooldowns() {
|
|
2315
2388
|
const now = Date.now();
|
|
2389
|
+
const before = this.providersOnCoolDown.length;
|
|
2316
2390
|
this.providersOnCoolDown = this.providersOnCoolDown.filter(
|
|
2317
|
-
([, timestamp]) =>
|
|
2391
|
+
([url, timestamp]) => {
|
|
2392
|
+
const age = now - timestamp;
|
|
2393
|
+
const isExpired = age >= _ProviderManager.COOLDOWN_DURATION_MS;
|
|
2394
|
+
if (isExpired) {
|
|
2395
|
+
console.log(
|
|
2396
|
+
`[cleanupExpiredCooldowns:${this.instanceId}] Removing expired cooldown for ${url} (age: ${age}ms, cooldown: ${_ProviderManager.COOLDOWN_DURATION_MS}ms)`
|
|
2397
|
+
);
|
|
2398
|
+
}
|
|
2399
|
+
return !isExpired;
|
|
2400
|
+
}
|
|
2318
2401
|
);
|
|
2402
|
+
const after = this.providersOnCoolDown.length;
|
|
2403
|
+
if (before !== after) {
|
|
2404
|
+
console.log(
|
|
2405
|
+
`[cleanupExpiredCooldowns:${this.instanceId}] Cleaned up ${before - after} expired cooldown(s), ${after} remaining`
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2319
2408
|
}
|
|
2320
2409
|
/**
|
|
2321
2410
|
* Get the cooldown duration in milliseconds
|
|
@@ -2328,7 +2417,8 @@ var ProviderManager = class _ProviderManager {
|
|
|
2328
2417
|
*/
|
|
2329
2418
|
isOnCooldown(baseUrl) {
|
|
2330
2419
|
this.cleanupExpiredCooldowns();
|
|
2331
|
-
|
|
2420
|
+
const result = this.providersOnCoolDown.some(([url]) => url === baseUrl);
|
|
2421
|
+
return result;
|
|
2332
2422
|
}
|
|
2333
2423
|
/**
|
|
2334
2424
|
* Get all providers currently on cooldown
|
|
@@ -2342,6 +2432,9 @@ var ProviderManager = class _ProviderManager {
|
|
|
2342
2432
|
*/
|
|
2343
2433
|
resetFailedProviders() {
|
|
2344
2434
|
this.failedProviders.clear();
|
|
2435
|
+
if (this.store) {
|
|
2436
|
+
this.store.getState().setFailedProviders([]);
|
|
2437
|
+
}
|
|
2345
2438
|
}
|
|
2346
2439
|
/**
|
|
2347
2440
|
* Get the last failed timestamp for a provider
|
|
@@ -2362,13 +2455,62 @@ var ProviderManager = class _ProviderManager {
|
|
|
2362
2455
|
markFailed(baseUrl) {
|
|
2363
2456
|
const now = Date.now();
|
|
2364
2457
|
const lastFailure = this.lastFailed.get(baseUrl);
|
|
2458
|
+
console.log(`[markFailed:${this.instanceId}] baseUrl: ${baseUrl}`);
|
|
2459
|
+
console.log(
|
|
2460
|
+
`[markFailed:${this.instanceId}] lastFailure from map: ${lastFailure}`
|
|
2461
|
+
);
|
|
2462
|
+
console.log(
|
|
2463
|
+
`[markFailed:${this.instanceId}] current timestamp (now): ${now}`
|
|
2464
|
+
);
|
|
2465
|
+
console.log(
|
|
2466
|
+
`[markFailed:${this.instanceId}] COOLDOWN_DURATION_MS: ${_ProviderManager.COOLDOWN_DURATION_MS}`
|
|
2467
|
+
);
|
|
2468
|
+
if (lastFailure !== void 0) {
|
|
2469
|
+
const timeSinceLastFailure = now - lastFailure;
|
|
2470
|
+
console.log(
|
|
2471
|
+
`[markFailed:${this.instanceId}] timeSinceLastFailure: ${timeSinceLastFailure}ms`
|
|
2472
|
+
);
|
|
2473
|
+
console.log(
|
|
2474
|
+
`[markFailed:${this.instanceId}] isWithinCooldownWindow: ${timeSinceLastFailure < _ProviderManager.COOLDOWN_DURATION_MS}`
|
|
2475
|
+
);
|
|
2476
|
+
}
|
|
2365
2477
|
this.lastFailed.set(baseUrl, now);
|
|
2366
2478
|
this.failedProviders.add(baseUrl);
|
|
2479
|
+
if (this.store) {
|
|
2480
|
+
this.store.getState().setLastFailedTimestamp(baseUrl, now);
|
|
2481
|
+
this.store.getState().addFailedProvider(baseUrl);
|
|
2482
|
+
}
|
|
2483
|
+
console.log(
|
|
2484
|
+
`[markFailed:${this.instanceId}] Updated lastFailed map for ${baseUrl} to ${now}`
|
|
2485
|
+
);
|
|
2486
|
+
console.log(
|
|
2487
|
+
`[markFailed:${this.instanceId}] failedProviders set size: ${this.failedProviders.size}`
|
|
2488
|
+
);
|
|
2367
2489
|
if (lastFailure !== void 0 && now - lastFailure < _ProviderManager.COOLDOWN_DURATION_MS) {
|
|
2490
|
+
console.log(
|
|
2491
|
+
`[markFailed:${this.instanceId}] Second failure detected within cooldown window for ${baseUrl}`
|
|
2492
|
+
);
|
|
2368
2493
|
if (!this.isOnCooldown(baseUrl)) {
|
|
2369
2494
|
this.providersOnCoolDown.push([baseUrl, now]);
|
|
2495
|
+
if (this.store) {
|
|
2496
|
+
this.store.getState().addProviderOnCooldown(baseUrl, now);
|
|
2497
|
+
}
|
|
2498
|
+
console.log(
|
|
2499
|
+
`[markFailed:${this.instanceId}] Provider ${baseUrl} added to cooldown after second failure within 5 minutes`
|
|
2500
|
+
);
|
|
2501
|
+
} else {
|
|
2502
|
+
console.log(
|
|
2503
|
+
`[markFailed:${this.instanceId}] Provider ${baseUrl} is already on cooldown`
|
|
2504
|
+
);
|
|
2505
|
+
}
|
|
2506
|
+
} else {
|
|
2507
|
+
if (lastFailure === void 0) {
|
|
2508
|
+
console.log(
|
|
2509
|
+
`[markFailed:${this.instanceId}] First failure for ${baseUrl} - not adding to cooldown yet`
|
|
2510
|
+
);
|
|
2511
|
+
} else {
|
|
2370
2512
|
console.log(
|
|
2371
|
-
`
|
|
2513
|
+
`[markFailed:${this.instanceId}] Failure outside cooldown window for ${baseUrl} (timeSinceLastFailure: ${now - lastFailure}ms)`
|
|
2372
2514
|
);
|
|
2373
2515
|
}
|
|
2374
2516
|
}
|
|
@@ -2380,18 +2522,27 @@ var ProviderManager = class _ProviderManager {
|
|
|
2380
2522
|
this.providersOnCoolDown = this.providersOnCoolDown.filter(
|
|
2381
2523
|
([url]) => url !== baseUrl
|
|
2382
2524
|
);
|
|
2525
|
+
if (this.store) {
|
|
2526
|
+
this.store.getState().removeProviderFromCooldown(baseUrl);
|
|
2527
|
+
}
|
|
2383
2528
|
}
|
|
2384
2529
|
/**
|
|
2385
2530
|
* Clear all cooldown tracking
|
|
2386
2531
|
*/
|
|
2387
2532
|
clearCooldowns() {
|
|
2388
2533
|
this.providersOnCoolDown = [];
|
|
2534
|
+
if (this.store) {
|
|
2535
|
+
this.store.getState().clearProvidersOnCooldown();
|
|
2536
|
+
}
|
|
2389
2537
|
}
|
|
2390
2538
|
/**
|
|
2391
2539
|
* Clear all failure tracking (lastFailed timestamps)
|
|
2392
2540
|
*/
|
|
2393
2541
|
clearFailureHistory() {
|
|
2394
2542
|
this.lastFailed.clear();
|
|
2543
|
+
if (this.store) {
|
|
2544
|
+
this.store.getState().setLastFailed({});
|
|
2545
|
+
}
|
|
2395
2546
|
}
|
|
2396
2547
|
/**
|
|
2397
2548
|
* Check if a provider has failed
|
|
@@ -2960,7 +3111,10 @@ var SDK_STORAGE_KEYS = {
|
|
|
2960
3111
|
LAST_ROUTSTR21_MODELS_UPDATE: "lastRoutstr21ModelsUpdate",
|
|
2961
3112
|
CACHED_RECEIVE_TOKENS: "cached_receive_tokens",
|
|
2962
3113
|
USAGE_TRACKING: "usage_tracking",
|
|
2963
|
-
CLIENT_IDS: "client_ids"
|
|
3114
|
+
CLIENT_IDS: "client_ids",
|
|
3115
|
+
FAILED_PROVIDERS: "failed_providers",
|
|
3116
|
+
LAST_FAILED: "last_failed",
|
|
3117
|
+
PROVIDERS_ON_COOLDOWN: "providers_on_cooldown"
|
|
2964
3118
|
};
|
|
2965
3119
|
|
|
2966
3120
|
// storage/usageTracking/indexedDB.ts
|
|
@@ -3607,6 +3761,9 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3607
3761
|
lastRoutstr21ModelsUpdate: null,
|
|
3608
3762
|
cachedReceiveTokens: [],
|
|
3609
3763
|
clientIds: [],
|
|
3764
|
+
failedProviders: [],
|
|
3765
|
+
lastFailed: {},
|
|
3766
|
+
providersOnCooldown: [],
|
|
3610
3767
|
setModelsFromAllProviders: (value) => {
|
|
3611
3768
|
const normalized = {};
|
|
3612
3769
|
for (const [baseUrl, models] of Object.entries(value)) {
|
|
@@ -3746,6 +3903,71 @@ var createEmptyStore = (driver) => vanilla.createStore((set, get) => ({
|
|
|
3746
3903
|
void driver.setItem(SDK_STORAGE_KEYS.CLIENT_IDS, normalized);
|
|
3747
3904
|
return { clientIds: normalized };
|
|
3748
3905
|
});
|
|
3906
|
+
},
|
|
3907
|
+
// ========== Failure Tracking ==========
|
|
3908
|
+
setFailedProviders: (value) => {
|
|
3909
|
+
const normalized = value.map((url) => normalizeBaseUrl5(url));
|
|
3910
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, normalized);
|
|
3911
|
+
set({ failedProviders: normalized });
|
|
3912
|
+
},
|
|
3913
|
+
addFailedProvider: (baseUrl) => {
|
|
3914
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3915
|
+
const current = get().failedProviders;
|
|
3916
|
+
if (!current.includes(normalized)) {
|
|
3917
|
+
const updated = [...current, normalized];
|
|
3918
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, updated);
|
|
3919
|
+
set({ failedProviders: updated });
|
|
3920
|
+
}
|
|
3921
|
+
},
|
|
3922
|
+
removeFailedProvider: (baseUrl) => {
|
|
3923
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3924
|
+
const current = get().failedProviders;
|
|
3925
|
+
const updated = current.filter((url) => url !== normalized);
|
|
3926
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, updated);
|
|
3927
|
+
set({ failedProviders: updated });
|
|
3928
|
+
},
|
|
3929
|
+
setLastFailed: (value) => {
|
|
3930
|
+
const normalized = {};
|
|
3931
|
+
for (const [baseUrl, timestamp] of Object.entries(value)) {
|
|
3932
|
+
normalized[normalizeBaseUrl5(baseUrl)] = timestamp;
|
|
3933
|
+
}
|
|
3934
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_FAILED, normalized);
|
|
3935
|
+
set({ lastFailed: normalized });
|
|
3936
|
+
},
|
|
3937
|
+
setLastFailedTimestamp: (baseUrl, timestamp) => {
|
|
3938
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3939
|
+
const current = get().lastFailed;
|
|
3940
|
+
const updated = { ...current, [normalized]: timestamp };
|
|
3941
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_FAILED, updated);
|
|
3942
|
+
set({ lastFailed: updated });
|
|
3943
|
+
},
|
|
3944
|
+
setProvidersOnCooldown: (value) => {
|
|
3945
|
+
const normalized = value.map((entry) => ({
|
|
3946
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
3947
|
+
timestamp: entry.timestamp
|
|
3948
|
+
}));
|
|
3949
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, normalized);
|
|
3950
|
+
set({ providersOnCooldown: normalized });
|
|
3951
|
+
},
|
|
3952
|
+
addProviderOnCooldown: (baseUrl, timestamp) => {
|
|
3953
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3954
|
+
const current = get().providersOnCooldown;
|
|
3955
|
+
if (!current.some((entry) => entry.baseUrl === normalized)) {
|
|
3956
|
+
const updated = [...current, { baseUrl: normalized, timestamp }];
|
|
3957
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, updated);
|
|
3958
|
+
set({ providersOnCooldown: updated });
|
|
3959
|
+
}
|
|
3960
|
+
},
|
|
3961
|
+
removeProviderFromCooldown: (baseUrl) => {
|
|
3962
|
+
const normalized = normalizeBaseUrl5(baseUrl);
|
|
3963
|
+
const current = get().providersOnCooldown;
|
|
3964
|
+
const updated = current.filter((entry) => entry.baseUrl !== normalized);
|
|
3965
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, updated);
|
|
3966
|
+
set({ providersOnCooldown: updated });
|
|
3967
|
+
},
|
|
3968
|
+
clearProvidersOnCooldown: () => {
|
|
3969
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, []);
|
|
3970
|
+
set({ providersOnCooldown: [] });
|
|
3749
3971
|
}
|
|
3750
3972
|
}));
|
|
3751
3973
|
var hydrateStoreFromDriver = async (store, driver) => {
|
|
@@ -3764,7 +3986,10 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3764
3986
|
rawRoutstr21Models,
|
|
3765
3987
|
rawLastRoutstr21ModelsUpdate,
|
|
3766
3988
|
rawCachedReceiveTokens,
|
|
3767
|
-
rawClientIds
|
|
3989
|
+
rawClientIds,
|
|
3990
|
+
rawFailedProviders,
|
|
3991
|
+
rawLastFailed,
|
|
3992
|
+
rawProvidersOnCooldown
|
|
3768
3993
|
] = await Promise.all([
|
|
3769
3994
|
driver.getItem(
|
|
3770
3995
|
SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
|
|
@@ -3795,7 +4020,10 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3795
4020
|
null
|
|
3796
4021
|
),
|
|
3797
4022
|
driver.getItem(SDK_STORAGE_KEYS.CACHED_RECEIVE_TOKENS, []),
|
|
3798
|
-
driver.getItem(SDK_STORAGE_KEYS.CLIENT_IDS, [])
|
|
4023
|
+
driver.getItem(SDK_STORAGE_KEYS.CLIENT_IDS, []),
|
|
4024
|
+
driver.getItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, []),
|
|
4025
|
+
driver.getItem(SDK_STORAGE_KEYS.LAST_FAILED, {}),
|
|
4026
|
+
driver.getItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, [])
|
|
3799
4027
|
]);
|
|
3800
4028
|
const modelsFromAllProviders = Object.fromEntries(
|
|
3801
4029
|
Object.entries(rawModels).map(([baseUrl, models]) => [
|
|
@@ -3863,6 +4091,17 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3863
4091
|
createdAt: entry.createdAt ?? Date.now(),
|
|
3864
4092
|
lastUsed: entry.lastUsed ?? null
|
|
3865
4093
|
}));
|
|
4094
|
+
const failedProviders = rawFailedProviders.map((url) => normalizeBaseUrl5(url));
|
|
4095
|
+
const lastFailed = Object.fromEntries(
|
|
4096
|
+
Object.entries(rawLastFailed).map(([baseUrl, timestamp]) => [
|
|
4097
|
+
normalizeBaseUrl5(baseUrl),
|
|
4098
|
+
timestamp
|
|
4099
|
+
])
|
|
4100
|
+
);
|
|
4101
|
+
const providersOnCooldown = rawProvidersOnCooldown.map((entry) => ({
|
|
4102
|
+
baseUrl: normalizeBaseUrl5(entry.baseUrl),
|
|
4103
|
+
timestamp: entry.timestamp
|
|
4104
|
+
}));
|
|
3866
4105
|
store.setState({
|
|
3867
4106
|
modelsFromAllProviders,
|
|
3868
4107
|
lastUsedModel,
|
|
@@ -3878,7 +4117,10 @@ var hydrateStoreFromDriver = async (store, driver) => {
|
|
|
3878
4117
|
routstr21Models,
|
|
3879
4118
|
lastRoutstr21ModelsUpdate,
|
|
3880
4119
|
cachedReceiveTokens,
|
|
3881
|
-
clientIds
|
|
4120
|
+
clientIds,
|
|
4121
|
+
failedProviders,
|
|
4122
|
+
lastFailed,
|
|
4123
|
+
providersOnCooldown
|
|
3882
4124
|
});
|
|
3883
4125
|
};
|
|
3884
4126
|
var createSdkStore = ({
|
|
@@ -4294,11 +4536,11 @@ var RoutstrClient = class {
|
|
|
4294
4536
|
this.balanceManager
|
|
4295
4537
|
);
|
|
4296
4538
|
this.streamProcessor = new StreamProcessor();
|
|
4297
|
-
this.providerManager = new ProviderManager(providerRegistry);
|
|
4298
4539
|
this.alertLevel = alertLevel;
|
|
4299
4540
|
this.mode = mode;
|
|
4300
4541
|
this.usageTrackingDriver = options.usageTrackingDriver;
|
|
4301
4542
|
this.sdkStore = options.sdkStore;
|
|
4543
|
+
this.providerManager = options.providerManager ?? new ProviderManager(providerRegistry, this.sdkStore);
|
|
4302
4544
|
}
|
|
4303
4545
|
cashuSpender;
|
|
4304
4546
|
balanceManager;
|
|
@@ -4761,19 +5003,19 @@ var RoutstrClient = class {
|
|
|
4761
5003
|
`[RoutstrClient] _handleErrorResponse: Attempting to receive/restore token for ${baseUrl}`
|
|
4762
5004
|
);
|
|
4763
5005
|
if (params.token.startsWith("cashu")) {
|
|
4764
|
-
const
|
|
5006
|
+
const receiveResult = await this.cashuSpender.receiveToken(
|
|
4765
5007
|
params.token
|
|
4766
5008
|
);
|
|
4767
|
-
if (
|
|
5009
|
+
if (receiveResult.success) {
|
|
4768
5010
|
this._log(
|
|
4769
5011
|
"DEBUG",
|
|
4770
|
-
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${
|
|
5012
|
+
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${receiveResult.amount}`
|
|
4771
5013
|
);
|
|
4772
5014
|
tryNextProvider = true;
|
|
4773
5015
|
} else {
|
|
4774
5016
|
this._log(
|
|
4775
5017
|
"DEBUG",
|
|
4776
|
-
`[RoutstrClient] _handleErrorResponse: Failed to receive token.
|
|
5018
|
+
`[RoutstrClient] _handleErrorResponse: Failed to receive token: ${receiveResult.message}`
|
|
4777
5019
|
);
|
|
4778
5020
|
}
|
|
4779
5021
|
}
|
|
@@ -4783,23 +5025,18 @@ var RoutstrClient = class {
|
|
|
4783
5025
|
"DEBUG",
|
|
4784
5026
|
`[RoutstrClient] _handleErrorResponse: Attempting to receive xcashu refund token, preview=${xCashuRefundToken.substring(0, 20)}...`
|
|
4785
5027
|
);
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
"xcashu refund failed",
|
|
4799
|
-
requestId
|
|
4800
|
-
);
|
|
4801
|
-
} catch (error) {
|
|
4802
|
-
this._log("ERROR", "[xcashu] Failed to receive refund token:", error);
|
|
5028
|
+
const receiveResult = await this.cashuSpender.receiveToken(xCashuRefundToken);
|
|
5029
|
+
if (receiveResult.success) {
|
|
5030
|
+
this._log(
|
|
5031
|
+
"DEBUG",
|
|
5032
|
+
`[RoutstrClient] _handleErrorResponse: xcashu refund received, amount=${receiveResult.amount}`
|
|
5033
|
+
);
|
|
5034
|
+
tryNextProvider = true;
|
|
5035
|
+
} else {
|
|
5036
|
+
this._log(
|
|
5037
|
+
"ERROR",
|
|
5038
|
+
`[xcashu] Failed to receive refund token: ${receiveResult.message}`
|
|
5039
|
+
);
|
|
4803
5040
|
throw new ProviderError(
|
|
4804
5041
|
baseUrl,
|
|
4805
5042
|
status,
|
|
@@ -4828,6 +5065,10 @@ var RoutstrClient = class {
|
|
|
4828
5065
|
const currentBalance = currentBalanceInfo.unit === "msat" ? currentBalanceInfo.amount / 1e3 : currentBalanceInfo.amount;
|
|
4829
5066
|
const shortfall = Math.max(0, params.requiredSats - currentBalance);
|
|
4830
5067
|
topupAmount = shortfall > 0 ? shortfall : params.requiredSats;
|
|
5068
|
+
this._log(
|
|
5069
|
+
"DEBUG",
|
|
5070
|
+
`The shortfall is: ${shortfall}. requiredSats: ${params.requiredSats}. Current Balance: ${currentBalance} `
|
|
5071
|
+
);
|
|
4831
5072
|
} catch (e) {
|
|
4832
5073
|
this._log(
|
|
4833
5074
|
"WARN",
|
|
@@ -4957,6 +5198,20 @@ var RoutstrClient = class {
|
|
|
4957
5198
|
tryNextProvider = true;
|
|
4958
5199
|
}
|
|
4959
5200
|
}
|
|
5201
|
+
if (status === 401 && this.mode === "apikeys") {
|
|
5202
|
+
this._log(
|
|
5203
|
+
"DEBUG",
|
|
5204
|
+
`[RoutstrClient] _handleErrorResponse: Checking balance for ${baseUrl}, key preview=${token}`
|
|
5205
|
+
);
|
|
5206
|
+
const latestBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
5207
|
+
token,
|
|
5208
|
+
baseUrl
|
|
5209
|
+
);
|
|
5210
|
+
if (latestBalanceInfo.isInvalidApiKey) {
|
|
5211
|
+
this.storageAdapter.removeApiKey(baseUrl);
|
|
5212
|
+
tryNextProvider = true;
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
4960
5215
|
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
|
|
4961
5216
|
this._log(
|
|
4962
5217
|
"DEBUG",
|
|
@@ -4967,13 +5222,13 @@ var RoutstrClient = class {
|
|
|
4967
5222
|
"DEBUG",
|
|
4968
5223
|
`[RoutstrClient] _handleErrorResponse: Attempting API key refund for ${baseUrl}, key preview=${token}`
|
|
4969
5224
|
);
|
|
4970
|
-
const
|
|
5225
|
+
const latestBalanceInfo = await this.balanceManager.getTokenBalance(
|
|
4971
5226
|
token,
|
|
4972
5227
|
baseUrl
|
|
4973
5228
|
);
|
|
4974
5229
|
this._log(
|
|
4975
5230
|
"DEBUG",
|
|
4976
|
-
`[RoutstrClient] _handleErrorResponse: Initial API key balance: ${
|
|
5231
|
+
`[RoutstrClient] _handleErrorResponse: Initial API key balance: ${latestBalanceInfo.amount}`
|
|
4977
5232
|
);
|
|
4978
5233
|
const refundResult = await this.balanceManager.refundApiKey({
|
|
4979
5234
|
mintUrl,
|
|
@@ -4985,7 +5240,7 @@ var RoutstrClient = class {
|
|
|
4985
5240
|
"DEBUG",
|
|
4986
5241
|
`[RoutstrClient] _handleErrorResponse: API key refund result: success=${refundResult.success}, message=${refundResult.message}`
|
|
4987
5242
|
);
|
|
4988
|
-
if (!refundResult.success &&
|
|
5243
|
+
if (!refundResult.success && latestBalanceInfo.amount > 0) {
|
|
4989
5244
|
throw new ProviderError(
|
|
4990
5245
|
baseUrl,
|
|
4991
5246
|
status,
|
|
@@ -5074,14 +5329,15 @@ var RoutstrClient = class {
|
|
|
5074
5329
|
if (this.mode === "xcashu" && response) {
|
|
5075
5330
|
const refundToken = response.headers.get("x-cashu") ?? void 0;
|
|
5076
5331
|
if (refundToken) {
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5332
|
+
const receiveResult = await this.cashuSpender.receiveToken(refundToken);
|
|
5333
|
+
if (receiveResult.success) {
|
|
5334
|
+
this.storageAdapter.removeXcashuToken(baseUrl, token);
|
|
5335
|
+
satsSpent = initialTokenBalance - receiveResult.amount * (receiveResult.unit == "sat" ? 1 : 1e3);
|
|
5336
|
+
} else {
|
|
5337
|
+
this._log(
|
|
5338
|
+
"ERROR",
|
|
5339
|
+
`[xcashu] Failed to receive refund token: ${receiveResult.message}`
|
|
5340
|
+
);
|
|
5085
5341
|
}
|
|
5086
5342
|
}
|
|
5087
5343
|
} else if (this.mode === "apikeys") {
|
|
@@ -5125,7 +5381,6 @@ var RoutstrClient = class {
|
|
|
5125
5381
|
try {
|
|
5126
5382
|
const xcashuResults = await this.cashuSpender.refundXcashuTokens(mintUrl);
|
|
5127
5383
|
this._log("DEBUG", "Refund xcashu tokens results:", xcashuResults);
|
|
5128
|
-
const results = await this.cashuSpender.refundProviders(mintUrl);
|
|
5129
5384
|
} catch (error) {
|
|
5130
5385
|
this._log("ERROR", "Failed to refund providers:", error);
|
|
5131
5386
|
}
|
|
@@ -5334,18 +5589,18 @@ var RoutstrClient = class {
|
|
|
5334
5589
|
this.storageAdapter.setApiKey(baseUrl, spendResult2.token);
|
|
5335
5590
|
} catch (error) {
|
|
5336
5591
|
if (error instanceof Error && error.message.includes("ApiKey already exists")) {
|
|
5337
|
-
const
|
|
5592
|
+
const receiveResult = await this.cashuSpender.receiveToken(
|
|
5338
5593
|
spendResult2.token
|
|
5339
5594
|
);
|
|
5340
|
-
if (
|
|
5595
|
+
if (receiveResult.success) {
|
|
5341
5596
|
this._log(
|
|
5342
5597
|
"DEBUG",
|
|
5343
|
-
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${
|
|
5598
|
+
`[RoutstrClient] _handleErrorResponse: Token restored successfully, amount=${receiveResult.amount}`
|
|
5344
5599
|
);
|
|
5345
5600
|
} else {
|
|
5346
5601
|
this._log(
|
|
5347
5602
|
"DEBUG",
|
|
5348
|
-
`[RoutstrClient] _handleErrorResponse: Token restore failed
|
|
5603
|
+
`[RoutstrClient] _handleErrorResponse: Token restore failed: ${receiveResult.message}`
|
|
5349
5604
|
);
|
|
5350
5605
|
}
|
|
5351
5606
|
this._log(
|
|
@@ -5466,7 +5721,8 @@ async function resolveRouteRequestContext(options) {
|
|
|
5466
5721
|
debugLevel,
|
|
5467
5722
|
mode = "apikeys",
|
|
5468
5723
|
usageTrackingDriver,
|
|
5469
|
-
sdkStore
|
|
5724
|
+
sdkStore,
|
|
5725
|
+
providerManager: providedProviderManager
|
|
5470
5726
|
} = options;
|
|
5471
5727
|
let modelManager;
|
|
5472
5728
|
let providers;
|
|
@@ -5486,7 +5742,7 @@ async function resolveRouteRequestContext(options) {
|
|
|
5486
5742
|
}
|
|
5487
5743
|
await modelManager.fetchModels(providers, forceRefresh);
|
|
5488
5744
|
}
|
|
5489
|
-
const providerManager = new ProviderManager(providerRegistry);
|
|
5745
|
+
const providerManager = providedProviderManager ?? new ProviderManager(providerRegistry, sdkStore);
|
|
5490
5746
|
let baseUrl;
|
|
5491
5747
|
let selectedModel;
|
|
5492
5748
|
if (forcedProvider) {
|
|
@@ -5531,7 +5787,7 @@ async function resolveRouteRequestContext(options) {
|
|
|
5531
5787
|
providerRegistry,
|
|
5532
5788
|
"min",
|
|
5533
5789
|
mode,
|
|
5534
|
-
{ usageTrackingDriver, sdkStore }
|
|
5790
|
+
{ usageTrackingDriver, sdkStore, providerManager }
|
|
5535
5791
|
);
|
|
5536
5792
|
if (debugLevel) {
|
|
5537
5793
|
client.setDebugLevel(debugLevel);
|