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