@routstr/sdk 0.3.9 → 0.3.11
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/browser.d.mts +12 -0
- package/dist/browser.d.ts +12 -0
- package/dist/browser.js +6413 -0
- package/dist/browser.js.map +1 -0
- package/dist/browser.mjs +6361 -0
- package/dist/browser.mjs.map +1 -0
- package/dist/bun.d.mts +29 -0
- package/dist/bun.d.ts +29 -0
- package/dist/bun.js +6791 -0
- package/dist/bun.js.map +1 -0
- package/dist/bun.mjs +6733 -0
- package/dist/bun.mjs.map +1 -0
- package/dist/bunSqlite-BmXWNc25.d.ts +18 -0
- package/dist/bunSqlite-Bro9efsl.d.mts +18 -0
- package/dist/client/index.d.mts +85 -42
- package/dist/client/index.d.ts +85 -42
- package/dist/client/index.js +1243 -1584
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +1239 -1585
- package/dist/client/index.mjs.map +1 -1
- package/dist/discovery/index.d.mts +33 -3
- package/dist/discovery/index.d.ts +33 -3
- package/dist/discovery/index.js +30 -31
- package/dist/discovery/index.js.map +1 -1
- package/dist/discovery/index.mjs +30 -31
- package/dist/discovery/index.mjs.map +1 -1
- package/dist/index.d.mts +9 -7
- package/dist/index.d.ts +9 -7
- package/dist/index.js +1264 -1648
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1260 -1645
- package/dist/index.mjs.map +1 -1
- package/dist/node.d.mts +22 -0
- package/dist/node.d.ts +22 -0
- package/dist/node.js +6857 -0
- package/dist/node.js.map +1 -0
- package/dist/node.mjs +6801 -0
- package/dist/node.mjs.map +1 -0
- package/dist/storage/bun.d.mts +16 -0
- package/dist/storage/bun.d.ts +16 -0
- package/dist/storage/bun.js +1970 -0
- package/dist/storage/bun.js.map +1 -0
- package/dist/storage/bun.mjs +1946 -0
- package/dist/storage/bun.mjs.map +1 -0
- package/dist/storage/index.d.mts +4 -30
- package/dist/storage/index.d.ts +4 -30
- package/dist/storage/index.js +238 -650
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/index.mjs +239 -647
- package/dist/storage/index.mjs.map +1 -1
- package/dist/storage/node.d.mts +22 -0
- package/dist/storage/node.d.ts +22 -0
- package/dist/storage/node.js +2034 -0
- package/dist/storage/node.js.map +1 -0
- package/dist/storage/node.mjs +2012 -0
- package/dist/storage/node.mjs.map +1 -0
- package/dist/{store-58VcEUoA.d.ts → store-CAQLSbEj.d.ts} +52 -1
- package/dist/{store-C6dfj1cc.d.mts → store-CuXwe5Rg.d.mts} +52 -1
- package/dist/wallet/index.js +38 -24
- package/dist/wallet/index.js.map +1 -1
- package/dist/wallet/index.mjs +38 -24
- package/dist/wallet/index.mjs.map +1 -1
- package/package.json +26 -1
|
@@ -0,0 +1,2012 @@
|
|
|
1
|
+
import { createStore } from 'zustand/vanilla';
|
|
2
|
+
|
|
3
|
+
// storage/drivers/localStorage.ts
|
|
4
|
+
var canUseLocalStorage = () => {
|
|
5
|
+
return typeof window !== "undefined" && typeof window.localStorage !== "undefined";
|
|
6
|
+
};
|
|
7
|
+
var isQuotaExceeded = (error) => {
|
|
8
|
+
const e = error;
|
|
9
|
+
return !!e && (e?.name === "QuotaExceededError" || e?.code === 22 || e?.code === 1014);
|
|
10
|
+
};
|
|
11
|
+
var NON_CRITICAL_KEYS = /* @__PURE__ */ new Set(["modelsFromAllProviders"]);
|
|
12
|
+
var localStorageDriver = {
|
|
13
|
+
async getItem(key, defaultValue) {
|
|
14
|
+
if (!canUseLocalStorage()) return defaultValue;
|
|
15
|
+
try {
|
|
16
|
+
const item = window.localStorage.getItem(key);
|
|
17
|
+
if (item === null) return defaultValue;
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(item);
|
|
20
|
+
} catch (parseError) {
|
|
21
|
+
if (typeof defaultValue === "string") {
|
|
22
|
+
return item;
|
|
23
|
+
}
|
|
24
|
+
throw parseError;
|
|
25
|
+
}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error(`Error retrieving item with key "${key}":`, error);
|
|
28
|
+
if (canUseLocalStorage()) {
|
|
29
|
+
try {
|
|
30
|
+
window.localStorage.removeItem(key);
|
|
31
|
+
} catch (removeError) {
|
|
32
|
+
console.error(
|
|
33
|
+
`Error removing corrupted item with key "${key}":`,
|
|
34
|
+
removeError
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return defaultValue;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
async setItem(key, value) {
|
|
42
|
+
if (!canUseLocalStorage()) return;
|
|
43
|
+
try {
|
|
44
|
+
window.localStorage.setItem(key, JSON.stringify(value));
|
|
45
|
+
} catch (error) {
|
|
46
|
+
if (isQuotaExceeded(error)) {
|
|
47
|
+
if (NON_CRITICAL_KEYS.has(key)) {
|
|
48
|
+
console.warn(
|
|
49
|
+
`Storage quota exceeded; skipping non-critical key "${key}".`
|
|
50
|
+
);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
window.localStorage.removeItem("modelsFromAllProviders");
|
|
55
|
+
} catch {
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
window.localStorage.setItem(key, JSON.stringify(value));
|
|
59
|
+
return;
|
|
60
|
+
} catch (retryError) {
|
|
61
|
+
console.warn(
|
|
62
|
+
`Storage quota exceeded; unable to persist key "${key}" after cleanup attempt.`,
|
|
63
|
+
retryError
|
|
64
|
+
);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
console.error(`Error storing item with key "${key}":`, error);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
async removeItem(key) {
|
|
72
|
+
if (!canUseLocalStorage()) return;
|
|
73
|
+
try {
|
|
74
|
+
window.localStorage.removeItem(key);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(`Error removing item with key "${key}":`, error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// storage/drivers/memory.ts
|
|
82
|
+
var createMemoryDriver = (seed) => {
|
|
83
|
+
const store = /* @__PURE__ */ new Map();
|
|
84
|
+
if (seed) {
|
|
85
|
+
for (const [key, value] of Object.entries(seed)) {
|
|
86
|
+
store.set(key, value);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
async getItem(key, defaultValue) {
|
|
91
|
+
const item = store.get(key);
|
|
92
|
+
if (item === void 0) return defaultValue;
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse(item);
|
|
95
|
+
} catch (parseError) {
|
|
96
|
+
if (typeof defaultValue === "string") {
|
|
97
|
+
return item;
|
|
98
|
+
}
|
|
99
|
+
throw parseError;
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
async setItem(key, value) {
|
|
103
|
+
store.set(key, JSON.stringify(value));
|
|
104
|
+
},
|
|
105
|
+
async removeItem(key) {
|
|
106
|
+
store.delete(key);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// storage/drivers/indexedDB.ts
|
|
112
|
+
var isBrowser = typeof indexedDB !== "undefined";
|
|
113
|
+
var openDatabase = (dbName, storeName) => {
|
|
114
|
+
if (!isBrowser) {
|
|
115
|
+
return Promise.reject(new Error("IndexedDB is not available"));
|
|
116
|
+
}
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
118
|
+
const request = indexedDB.open(dbName, 2);
|
|
119
|
+
request.onupgradeneeded = () => {
|
|
120
|
+
const db = request.result;
|
|
121
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
122
|
+
db.createObjectStore(storeName);
|
|
123
|
+
}
|
|
124
|
+
if (storeName !== "usage_tracking" && !db.objectStoreNames.contains("usage_tracking")) {
|
|
125
|
+
const utStore = db.createObjectStore("usage_tracking", { keyPath: "id" });
|
|
126
|
+
utStore.createIndex("timestamp", "timestamp", { unique: false });
|
|
127
|
+
utStore.createIndex("modelId", "modelId", { unique: false });
|
|
128
|
+
utStore.createIndex("baseUrl", "baseUrl", { unique: false });
|
|
129
|
+
utStore.createIndex("sessionId", "sessionId", { unique: false });
|
|
130
|
+
utStore.createIndex("client", "client", { unique: false });
|
|
131
|
+
}
|
|
132
|
+
if (storeName !== "sdk_storage" && !db.objectStoreNames.contains("sdk_storage")) {
|
|
133
|
+
db.createObjectStore("sdk_storage");
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
request.onsuccess = () => resolve(request.result);
|
|
137
|
+
request.onerror = () => reject(request.error);
|
|
138
|
+
request.onblocked = () => {
|
|
139
|
+
console.warn(
|
|
140
|
+
`[IndexedDB driver] open blocked for "${dbName}" (store: "${storeName}") \u2014 close other tabs using this DB`
|
|
141
|
+
);
|
|
142
|
+
reject(new Error(`IndexedDB "${dbName}" blocked by another connection`));
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
var createIndexedDBDriver = (options = {}) => {
|
|
147
|
+
const dbName = options.dbName || "routstr-sdk";
|
|
148
|
+
const storeName = options.storeName || "sdk_storage";
|
|
149
|
+
let dbPromise = null;
|
|
150
|
+
const getDb = () => {
|
|
151
|
+
if (!dbPromise) {
|
|
152
|
+
dbPromise = openDatabase(dbName, storeName);
|
|
153
|
+
}
|
|
154
|
+
return dbPromise;
|
|
155
|
+
};
|
|
156
|
+
return {
|
|
157
|
+
async getItem(key, defaultValue) {
|
|
158
|
+
try {
|
|
159
|
+
const db = await getDb();
|
|
160
|
+
return new Promise((resolve, reject) => {
|
|
161
|
+
const tx = db.transaction(storeName, "readonly");
|
|
162
|
+
const store = tx.objectStore(storeName);
|
|
163
|
+
const request = store.get(key);
|
|
164
|
+
request.onsuccess = () => {
|
|
165
|
+
const raw = request.result;
|
|
166
|
+
if (raw === void 0) {
|
|
167
|
+
resolve(defaultValue);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (typeof raw === "string") {
|
|
171
|
+
try {
|
|
172
|
+
resolve(JSON.parse(raw));
|
|
173
|
+
} catch {
|
|
174
|
+
if (typeof defaultValue === "string") {
|
|
175
|
+
resolve(raw);
|
|
176
|
+
} else {
|
|
177
|
+
resolve(defaultValue);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
resolve(raw);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
request.onerror = () => reject(request.error);
|
|
185
|
+
});
|
|
186
|
+
} catch (error) {
|
|
187
|
+
console.error(`IndexedDB getItem failed for key "${key}":`, error);
|
|
188
|
+
return defaultValue;
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
async setItem(key, value) {
|
|
192
|
+
try {
|
|
193
|
+
const db = await getDb();
|
|
194
|
+
return new Promise((resolve, reject) => {
|
|
195
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
196
|
+
const store = tx.objectStore(storeName);
|
|
197
|
+
store.put(JSON.stringify(value), key);
|
|
198
|
+
tx.oncomplete = () => resolve();
|
|
199
|
+
tx.onerror = () => reject(tx.error);
|
|
200
|
+
});
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error(`IndexedDB setItem failed for key "${key}":`, error);
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
async removeItem(key) {
|
|
206
|
+
try {
|
|
207
|
+
const db = await getDb();
|
|
208
|
+
return new Promise((resolve, reject) => {
|
|
209
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
210
|
+
const store = tx.objectStore(storeName);
|
|
211
|
+
store.delete(key);
|
|
212
|
+
tx.oncomplete = () => resolve();
|
|
213
|
+
tx.onerror = () => reject(tx.error);
|
|
214
|
+
});
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.error(`IndexedDB removeItem failed for key "${key}":`, error);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// storage/keys.ts
|
|
223
|
+
var SDK_STORAGE_KEYS = {
|
|
224
|
+
MODELS_FROM_ALL_PROVIDERS: "modelsFromAllProviders",
|
|
225
|
+
LAST_USED_MODEL: "lastUsedModel",
|
|
226
|
+
BASE_URLS_LIST: "base_urls_list",
|
|
227
|
+
DISABLED_PROVIDERS: "disabled_providers",
|
|
228
|
+
MINTS_FROM_ALL_PROVIDERS: "mints_from_all_providers",
|
|
229
|
+
INFO_FROM_ALL_PROVIDERS: "info_from_all_providers",
|
|
230
|
+
LAST_MODELS_UPDATE: "lastModelsUpdate",
|
|
231
|
+
LAST_BASE_URLS_UPDATE: "lastBaseUrlsUpdate",
|
|
232
|
+
API_KEYS: "api_keys",
|
|
233
|
+
CHILD_KEYS: "child_keys",
|
|
234
|
+
XCASHU_TOKENS: "xcashu_tokens",
|
|
235
|
+
ROUTSTR21_MODELS: "routstr21Models",
|
|
236
|
+
LAST_ROUTSTR21_MODELS_UPDATE: "lastRoutstr21ModelsUpdate",
|
|
237
|
+
CACHED_RECEIVE_TOKENS: "cached_receive_tokens",
|
|
238
|
+
USAGE_TRACKING: "usage_tracking",
|
|
239
|
+
CLIENT_IDS: "client_ids",
|
|
240
|
+
FAILED_PROVIDERS: "failed_providers",
|
|
241
|
+
LAST_FAILED: "last_failed",
|
|
242
|
+
PROVIDERS_ON_COOLDOWN: "providers_on_cooldown"
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// storage/usageTracking/aggregate.ts
|
|
246
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
247
|
+
var aggregateColumns = "COUNT(*) AS requests, COALESCE(SUM(prompt_tokens), 0) AS promptTokens, COALESCE(SUM(completion_tokens), 0) AS completionTokens, COALESCE(SUM(total_tokens), 0) AS totalTokens, COALESCE(SUM(cost), 0) AS cost, COALESCE(SUM(sats_cost), 0) AS satsCost, COALESCE(SUM(base_msats), 0) AS baseMsats, COALESCE(SUM(input_msats), 0) AS inputMsats, COALESCE(SUM(output_msats), 0) AS outputMsats, COALESCE(SUM(total_msats), 0) AS totalMsats, COALESCE(SUM(total_usd), 0) AS totalUsd, COALESCE(SUM(cache_read_input_tokens), 0) AS cacheReadInputTokens, COALESCE(SUM(cache_creation_input_tokens), 0) AS cacheCreationInputTokens, COALESCE(SUM(cache_read_msats), 0) AS cacheReadMsats, COALESCE(SUM(cache_creation_msats), 0) AS cacheCreationMsats";
|
|
248
|
+
var sqlGroupExpr = (groupBy) => {
|
|
249
|
+
switch (groupBy) {
|
|
250
|
+
case "modelId":
|
|
251
|
+
return { expr: "model_id", usesTz: false };
|
|
252
|
+
case "baseUrl":
|
|
253
|
+
return { expr: "base_url", usesTz: false };
|
|
254
|
+
case "client":
|
|
255
|
+
return { expr: "client", usesTz: false };
|
|
256
|
+
case "sessionId":
|
|
257
|
+
return { expr: "session_id", usesTz: false };
|
|
258
|
+
case "provider":
|
|
259
|
+
return { expr: "provider", usesTz: false };
|
|
260
|
+
case "day":
|
|
261
|
+
return {
|
|
262
|
+
expr: "strftime('%Y-%m-%d', (timestamp - ? * 60000) / 1000, 'unixepoch')",
|
|
263
|
+
usesTz: true
|
|
264
|
+
};
|
|
265
|
+
case "hour":
|
|
266
|
+
return {
|
|
267
|
+
expr: "strftime('%H', (timestamp - ? * 60000) / 1000, 'unixepoch')",
|
|
268
|
+
usesTz: true
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
var buildAggregateSql = (tableName, where, options = {}) => {
|
|
273
|
+
if (!options.groupBy) {
|
|
274
|
+
return {
|
|
275
|
+
sql: `SELECT NULL AS grp, ${aggregateColumns} FROM ${tableName} ${where.sql}`,
|
|
276
|
+
params: where.params
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
const { expr, usesTz } = sqlGroupExpr(options.groupBy);
|
|
280
|
+
const tzParams = usesTz ? [options.tzOffsetMinutes ?? 0] : [];
|
|
281
|
+
const orderBy = options.groupBy === "day" || options.groupBy === "hour" ? "ORDER BY grp ASC" : "ORDER BY satsCost DESC";
|
|
282
|
+
return {
|
|
283
|
+
sql: `SELECT ${expr} AS grp, ${aggregateColumns} FROM ${tableName} ${where.sql} GROUP BY grp ${orderBy}`,
|
|
284
|
+
params: [...tzParams, ...where.params]
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
var mapAggregateRow = (row) => ({
|
|
288
|
+
group: row.grp == null ? null : String(row.grp),
|
|
289
|
+
requests: Number(row.requests ?? 0),
|
|
290
|
+
promptTokens: Number(row.promptTokens ?? 0),
|
|
291
|
+
completionTokens: Number(row.completionTokens ?? 0),
|
|
292
|
+
totalTokens: Number(row.totalTokens ?? 0),
|
|
293
|
+
cost: Number(row.cost ?? 0),
|
|
294
|
+
satsCost: Number(row.satsCost ?? 0),
|
|
295
|
+
baseMsats: Number(row.baseMsats ?? 0),
|
|
296
|
+
inputMsats: Number(row.inputMsats ?? 0),
|
|
297
|
+
outputMsats: Number(row.outputMsats ?? 0),
|
|
298
|
+
totalMsats: Number(row.totalMsats ?? 0),
|
|
299
|
+
totalUsd: Number(row.totalUsd ?? 0),
|
|
300
|
+
cacheReadInputTokens: Number(row.cacheReadInputTokens ?? 0),
|
|
301
|
+
cacheCreationInputTokens: Number(row.cacheCreationInputTokens ?? 0),
|
|
302
|
+
cacheReadMsats: Number(row.cacheReadMsats ?? 0),
|
|
303
|
+
cacheCreationMsats: Number(row.cacheCreationMsats ?? 0)
|
|
304
|
+
});
|
|
305
|
+
var jsGroupKey = (entry, groupBy, tzOffsetMinutes) => {
|
|
306
|
+
switch (groupBy) {
|
|
307
|
+
case "modelId":
|
|
308
|
+
return entry.modelId ?? null;
|
|
309
|
+
case "baseUrl":
|
|
310
|
+
return entry.baseUrl ?? null;
|
|
311
|
+
case "client":
|
|
312
|
+
return entry.client ?? null;
|
|
313
|
+
case "sessionId":
|
|
314
|
+
return entry.sessionId ?? null;
|
|
315
|
+
case "provider":
|
|
316
|
+
return entry.provider ?? null;
|
|
317
|
+
case "day": {
|
|
318
|
+
const d = new Date(entry.timestamp - tzOffsetMinutes * 6e4);
|
|
319
|
+
return `${d.getUTCFullYear()}-${pad2(d.getUTCMonth() + 1)}-${pad2(d.getUTCDate())}`;
|
|
320
|
+
}
|
|
321
|
+
case "hour": {
|
|
322
|
+
const d = new Date(entry.timestamp - tzOffsetMinutes * 6e4);
|
|
323
|
+
return pad2(d.getUTCHours());
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
var reduceAggregate = (entries, options = {}) => {
|
|
328
|
+
const emptyRow = (group) => ({
|
|
329
|
+
group,
|
|
330
|
+
requests: 0,
|
|
331
|
+
promptTokens: 0,
|
|
332
|
+
completionTokens: 0,
|
|
333
|
+
totalTokens: 0,
|
|
334
|
+
cost: 0,
|
|
335
|
+
satsCost: 0,
|
|
336
|
+
baseMsats: 0,
|
|
337
|
+
inputMsats: 0,
|
|
338
|
+
outputMsats: 0,
|
|
339
|
+
totalMsats: 0,
|
|
340
|
+
totalUsd: 0,
|
|
341
|
+
cacheReadInputTokens: 0,
|
|
342
|
+
cacheCreationInputTokens: 0,
|
|
343
|
+
cacheReadMsats: 0,
|
|
344
|
+
cacheCreationMsats: 0
|
|
345
|
+
});
|
|
346
|
+
const accumulate = (row, entry) => {
|
|
347
|
+
row.requests += 1;
|
|
348
|
+
row.promptTokens += entry.promptTokens;
|
|
349
|
+
row.completionTokens += entry.completionTokens;
|
|
350
|
+
row.totalTokens += entry.totalTokens;
|
|
351
|
+
row.cost += entry.cost;
|
|
352
|
+
row.satsCost += entry.satsCost;
|
|
353
|
+
row.baseMsats += entry.baseMsats ?? 0;
|
|
354
|
+
row.inputMsats += entry.inputMsats ?? 0;
|
|
355
|
+
row.outputMsats += entry.outputMsats ?? 0;
|
|
356
|
+
row.totalMsats += entry.totalMsats ?? 0;
|
|
357
|
+
row.totalUsd += entry.totalUsd ?? 0;
|
|
358
|
+
row.cacheReadInputTokens += entry.cacheReadInputTokens ?? 0;
|
|
359
|
+
row.cacheCreationInputTokens += entry.cacheCreationInputTokens ?? 0;
|
|
360
|
+
row.cacheReadMsats += entry.cacheReadMsats ?? 0;
|
|
361
|
+
row.cacheCreationMsats += entry.cacheCreationMsats ?? 0;
|
|
362
|
+
};
|
|
363
|
+
if (!options.groupBy) {
|
|
364
|
+
const total = emptyRow(null);
|
|
365
|
+
for (const entry of entries) accumulate(total, entry);
|
|
366
|
+
return [total];
|
|
367
|
+
}
|
|
368
|
+
const tz = options.tzOffsetMinutes ?? 0;
|
|
369
|
+
const groups = /* @__PURE__ */ new Map();
|
|
370
|
+
for (const entry of entries) {
|
|
371
|
+
const key = jsGroupKey(entry, options.groupBy, tz);
|
|
372
|
+
let row = groups.get(key);
|
|
373
|
+
if (!row) {
|
|
374
|
+
row = emptyRow(key);
|
|
375
|
+
groups.set(key, row);
|
|
376
|
+
}
|
|
377
|
+
accumulate(row, entry);
|
|
378
|
+
}
|
|
379
|
+
const rows = [...groups.values()];
|
|
380
|
+
if (options.groupBy === "day" || options.groupBy === "hour") {
|
|
381
|
+
rows.sort((a, b) => (a.group ?? "").localeCompare(b.group ?? ""));
|
|
382
|
+
} else {
|
|
383
|
+
rows.sort((a, b) => b.satsCost - a.satsCost);
|
|
384
|
+
}
|
|
385
|
+
return rows;
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
// storage/usageTracking/indexedDB.ts
|
|
389
|
+
var DEFAULT_DB_NAME = "routstr-sdk";
|
|
390
|
+
var DEFAULT_STORE_NAME = "usage_tracking";
|
|
391
|
+
var MIGRATION_MARKER_KEY = "usage_tracking_migration_v1";
|
|
392
|
+
var isBrowser2 = typeof indexedDB !== "undefined";
|
|
393
|
+
var normalizeBaseUrl = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
394
|
+
var openDatabase2 = (dbName, storeName) => {
|
|
395
|
+
if (!isBrowser2) {
|
|
396
|
+
return Promise.reject(new Error("IndexedDB is not available"));
|
|
397
|
+
}
|
|
398
|
+
return new Promise((resolve, reject) => {
|
|
399
|
+
const request = indexedDB.open(dbName, 3);
|
|
400
|
+
request.onupgradeneeded = () => {
|
|
401
|
+
const db = request.result;
|
|
402
|
+
const tx = request.transaction;
|
|
403
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
404
|
+
const store = db.createObjectStore(storeName, { keyPath: "id" });
|
|
405
|
+
store.createIndex("timestamp", "timestamp", { unique: false });
|
|
406
|
+
store.createIndex("modelId", "modelId", { unique: false });
|
|
407
|
+
store.createIndex("baseUrl", "baseUrl", { unique: false });
|
|
408
|
+
store.createIndex("sessionId", "sessionId", { unique: false });
|
|
409
|
+
store.createIndex("client", "client", { unique: false });
|
|
410
|
+
store.createIndex("provider", "provider", { unique: false });
|
|
411
|
+
} else if (tx) {
|
|
412
|
+
const store = tx.objectStore(storeName);
|
|
413
|
+
if (!store.indexNames.contains("provider")) {
|
|
414
|
+
store.createIndex("provider", "provider", { unique: false });
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (storeName !== "sdk_storage" && !db.objectStoreNames.contains("sdk_storage")) {
|
|
418
|
+
db.createObjectStore("sdk_storage");
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
request.onsuccess = () => resolve(request.result);
|
|
422
|
+
request.onerror = () => reject(request.error);
|
|
423
|
+
request.onblocked = () => {
|
|
424
|
+
console.warn(
|
|
425
|
+
`[usageTracking IndexedDB] open blocked for "${dbName}" \u2014 close other tabs using this DB`
|
|
426
|
+
);
|
|
427
|
+
reject(new Error(`IndexedDB "${dbName}" blocked by another connection`));
|
|
428
|
+
};
|
|
429
|
+
});
|
|
430
|
+
};
|
|
431
|
+
var matchesFilters = (entry, options = {}) => {
|
|
432
|
+
if (typeof options.before === "number" && entry.timestamp >= options.before) {
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
435
|
+
if (typeof options.after === "number" && entry.timestamp <= options.after) {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
if (options.modelId && entry.modelId !== options.modelId) {
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
if (options.baseUrl && normalizeBaseUrl(entry.baseUrl) !== normalizeBaseUrl(options.baseUrl)) {
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
if (options.sessionId && entry.sessionId !== options.sessionId) {
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
if (options.client && entry.client !== options.client) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
if (options.clients && options.clients.length > 0 && (entry.client == null || !options.clients.includes(entry.client))) {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
if (options.provider && entry.provider !== options.provider) {
|
|
454
|
+
return false;
|
|
455
|
+
}
|
|
456
|
+
return true;
|
|
457
|
+
};
|
|
458
|
+
var createIndexedDBUsageTrackingDriver = (options = {}) => {
|
|
459
|
+
const dbName = options.dbName || DEFAULT_DB_NAME;
|
|
460
|
+
const storeName = options.storeName || DEFAULT_STORE_NAME;
|
|
461
|
+
const legacyStorageDriver = options.legacyStorageDriver;
|
|
462
|
+
let dbPromise = null;
|
|
463
|
+
let migrationPromise = null;
|
|
464
|
+
const getDb = () => {
|
|
465
|
+
if (!dbPromise) {
|
|
466
|
+
dbPromise = openDatabase2(dbName, storeName);
|
|
467
|
+
}
|
|
468
|
+
return dbPromise;
|
|
469
|
+
};
|
|
470
|
+
const putMany = async (entries) => {
|
|
471
|
+
if (entries.length === 0) return;
|
|
472
|
+
const db = await getDb();
|
|
473
|
+
await new Promise((resolve, reject) => {
|
|
474
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
475
|
+
const store = tx.objectStore(storeName);
|
|
476
|
+
for (const entry of entries) {
|
|
477
|
+
store.put({ ...entry, baseUrl: normalizeBaseUrl(entry.baseUrl) });
|
|
478
|
+
}
|
|
479
|
+
tx.oncomplete = () => resolve();
|
|
480
|
+
tx.onerror = () => reject(tx.error);
|
|
481
|
+
});
|
|
482
|
+
};
|
|
483
|
+
const ensureMigrated = async () => {
|
|
484
|
+
if (!legacyStorageDriver) return;
|
|
485
|
+
if (!migrationPromise) {
|
|
486
|
+
migrationPromise = (async () => {
|
|
487
|
+
const migrated = await legacyStorageDriver.getItem(
|
|
488
|
+
MIGRATION_MARKER_KEY,
|
|
489
|
+
false
|
|
490
|
+
);
|
|
491
|
+
if (migrated) return;
|
|
492
|
+
const legacyEntries = await legacyStorageDriver.getItem(
|
|
493
|
+
SDK_STORAGE_KEYS.USAGE_TRACKING,
|
|
494
|
+
[]
|
|
495
|
+
);
|
|
496
|
+
if (legacyEntries.length > 0) {
|
|
497
|
+
await putMany(legacyEntries);
|
|
498
|
+
await legacyStorageDriver.removeItem(SDK_STORAGE_KEYS.USAGE_TRACKING);
|
|
499
|
+
}
|
|
500
|
+
await legacyStorageDriver.setItem(MIGRATION_MARKER_KEY, true);
|
|
501
|
+
})();
|
|
502
|
+
}
|
|
503
|
+
await migrationPromise;
|
|
504
|
+
};
|
|
505
|
+
return {
|
|
506
|
+
async migrate() {
|
|
507
|
+
await ensureMigrated();
|
|
508
|
+
},
|
|
509
|
+
async append(entry) {
|
|
510
|
+
await ensureMigrated();
|
|
511
|
+
await putMany([entry]);
|
|
512
|
+
},
|
|
513
|
+
async appendMany(entries) {
|
|
514
|
+
await ensureMigrated();
|
|
515
|
+
await putMany(entries);
|
|
516
|
+
},
|
|
517
|
+
async list(options2 = {}) {
|
|
518
|
+
await ensureMigrated();
|
|
519
|
+
const db = await getDb();
|
|
520
|
+
return new Promise((resolve, reject) => {
|
|
521
|
+
const tx = db.transaction(storeName, "readonly");
|
|
522
|
+
const store = tx.objectStore(storeName);
|
|
523
|
+
const index = store.index("timestamp");
|
|
524
|
+
const direction = "prev";
|
|
525
|
+
const request = index.openCursor(null, direction);
|
|
526
|
+
const results = [];
|
|
527
|
+
const limit = options2.limit;
|
|
528
|
+
request.onsuccess = () => {
|
|
529
|
+
const cursor = request.result;
|
|
530
|
+
if (!cursor) {
|
|
531
|
+
resolve(results);
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const value = cursor.value;
|
|
535
|
+
if (matchesFilters(value, options2)) {
|
|
536
|
+
results.push(value);
|
|
537
|
+
if (typeof limit === "number" && results.length >= limit) {
|
|
538
|
+
resolve(results);
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
cursor.continue();
|
|
543
|
+
};
|
|
544
|
+
request.onerror = () => reject(request.error);
|
|
545
|
+
});
|
|
546
|
+
},
|
|
547
|
+
async count(options2 = {}) {
|
|
548
|
+
const results = await this.list(options2);
|
|
549
|
+
return results.length;
|
|
550
|
+
},
|
|
551
|
+
async aggregate(options2 = {}) {
|
|
552
|
+
const entries = await this.list(options2);
|
|
553
|
+
return reduceAggregate(entries, options2);
|
|
554
|
+
},
|
|
555
|
+
async deleteOlderThan(timestamp) {
|
|
556
|
+
await ensureMigrated();
|
|
557
|
+
const db = await getDb();
|
|
558
|
+
return new Promise((resolve, reject) => {
|
|
559
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
560
|
+
const store = tx.objectStore(storeName);
|
|
561
|
+
const index = store.index("timestamp");
|
|
562
|
+
const range = IDBKeyRange.upperBound(timestamp, true);
|
|
563
|
+
const request = index.openCursor(range);
|
|
564
|
+
let deleted = 0;
|
|
565
|
+
request.onsuccess = () => {
|
|
566
|
+
const cursor = request.result;
|
|
567
|
+
if (!cursor) {
|
|
568
|
+
resolve(deleted);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
deleted += 1;
|
|
572
|
+
cursor.delete();
|
|
573
|
+
cursor.continue();
|
|
574
|
+
};
|
|
575
|
+
request.onerror = () => reject(request.error);
|
|
576
|
+
});
|
|
577
|
+
},
|
|
578
|
+
async clear() {
|
|
579
|
+
await ensureMigrated();
|
|
580
|
+
const db = await getDb();
|
|
581
|
+
await new Promise((resolve, reject) => {
|
|
582
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
583
|
+
tx.objectStore(storeName).clear();
|
|
584
|
+
tx.oncomplete = () => resolve();
|
|
585
|
+
tx.onerror = () => reject(tx.error);
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
// storage/usageTracking/memory.ts
|
|
592
|
+
var normalizeBaseUrl2 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
593
|
+
var matchesFilters2 = (entry, options = {}) => {
|
|
594
|
+
if (typeof options.before === "number" && entry.timestamp >= options.before) {
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
if (typeof options.after === "number" && entry.timestamp <= options.after) {
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
if (options.modelId && entry.modelId !== options.modelId) {
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
if (options.baseUrl && normalizeBaseUrl2(entry.baseUrl) !== normalizeBaseUrl2(options.baseUrl)) {
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
if (options.sessionId && entry.sessionId !== options.sessionId) {
|
|
607
|
+
return false;
|
|
608
|
+
}
|
|
609
|
+
if (options.client && entry.client !== options.client) {
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
if (options.clients && options.clients.length > 0 && (entry.client == null || !options.clients.includes(entry.client))) {
|
|
613
|
+
return false;
|
|
614
|
+
}
|
|
615
|
+
if (options.provider && entry.provider !== options.provider) {
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
return true;
|
|
619
|
+
};
|
|
620
|
+
var createMemoryUsageTrackingDriver = (seed = []) => {
|
|
621
|
+
const store = /* @__PURE__ */ new Map();
|
|
622
|
+
for (const entry of seed) {
|
|
623
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl2(entry.baseUrl) });
|
|
624
|
+
}
|
|
625
|
+
return {
|
|
626
|
+
async migrate() {
|
|
627
|
+
return;
|
|
628
|
+
},
|
|
629
|
+
async append(entry) {
|
|
630
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl2(entry.baseUrl) });
|
|
631
|
+
},
|
|
632
|
+
async appendMany(entries) {
|
|
633
|
+
for (const entry of entries) {
|
|
634
|
+
store.set(entry.id, { ...entry, baseUrl: normalizeBaseUrl2(entry.baseUrl) });
|
|
635
|
+
}
|
|
636
|
+
},
|
|
637
|
+
async list(options = {}) {
|
|
638
|
+
const entries = [...store.values()].filter((entry) => matchesFilters2(entry, options)).sort((a, b) => b.timestamp - a.timestamp);
|
|
639
|
+
if (typeof options.limit === "number") {
|
|
640
|
+
return entries.slice(0, options.limit);
|
|
641
|
+
}
|
|
642
|
+
return entries;
|
|
643
|
+
},
|
|
644
|
+
async count(options = {}) {
|
|
645
|
+
return (await this.list(options)).length;
|
|
646
|
+
},
|
|
647
|
+
async aggregate(options = {}) {
|
|
648
|
+
const entries = [...store.values()].filter((entry) => matchesFilters2(entry, options));
|
|
649
|
+
return reduceAggregate(entries, options);
|
|
650
|
+
},
|
|
651
|
+
async deleteOlderThan(timestamp) {
|
|
652
|
+
let deleted = 0;
|
|
653
|
+
for (const [id, entry] of store.entries()) {
|
|
654
|
+
if (entry.timestamp < timestamp) {
|
|
655
|
+
store.delete(id);
|
|
656
|
+
deleted += 1;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return deleted;
|
|
660
|
+
},
|
|
661
|
+
async clear() {
|
|
662
|
+
store.clear();
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
// core/types.ts
|
|
668
|
+
function makeConsoleLogger(prefix) {
|
|
669
|
+
const fmt = (args) => prefix ? [prefix, ...args] : args;
|
|
670
|
+
return {
|
|
671
|
+
log: (...args) => console.log(...fmt(args)),
|
|
672
|
+
warn: (...args) => console.warn(...fmt(args)),
|
|
673
|
+
error: (...args) => console.error(...fmt(args)),
|
|
674
|
+
debug: (...args) => console.log(...fmt(args)),
|
|
675
|
+
child: (p) => makeConsoleLogger(prefix ? `${prefix}:${p}` : p)
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
var consoleLogger = makeConsoleLogger();
|
|
679
|
+
|
|
680
|
+
// storage/store.ts
|
|
681
|
+
var normalizeBaseUrl3 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
682
|
+
var createEmptyStore = (driver) => createStore((set, get) => ({
|
|
683
|
+
modelsFromAllProviders: {},
|
|
684
|
+
lastUsedModel: null,
|
|
685
|
+
baseUrlsList: [],
|
|
686
|
+
lastBaseUrlsUpdate: null,
|
|
687
|
+
disabledProviders: [],
|
|
688
|
+
mintsFromAllProviders: {},
|
|
689
|
+
infoFromAllProviders: {},
|
|
690
|
+
lastModelsUpdate: {},
|
|
691
|
+
apiKeys: [],
|
|
692
|
+
childKeys: [],
|
|
693
|
+
xcashuTokens: {},
|
|
694
|
+
routstr21Models: [],
|
|
695
|
+
lastRoutstr21ModelsUpdate: null,
|
|
696
|
+
cachedReceiveTokens: [],
|
|
697
|
+
clientIds: [],
|
|
698
|
+
failedProviders: [],
|
|
699
|
+
lastFailed: {},
|
|
700
|
+
providersOnCooldown: [],
|
|
701
|
+
setModelsFromAllProviders: (value) => {
|
|
702
|
+
const normalized = {};
|
|
703
|
+
for (const [baseUrl, models] of Object.entries(value)) {
|
|
704
|
+
normalized[normalizeBaseUrl3(baseUrl)] = models;
|
|
705
|
+
}
|
|
706
|
+
void driver.setItem(
|
|
707
|
+
SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
|
|
708
|
+
normalized
|
|
709
|
+
);
|
|
710
|
+
set({ modelsFromAllProviders: normalized });
|
|
711
|
+
},
|
|
712
|
+
setLastUsedModel: (value) => {
|
|
713
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_USED_MODEL, value);
|
|
714
|
+
set({ lastUsedModel: value });
|
|
715
|
+
},
|
|
716
|
+
setBaseUrlsList: (value) => {
|
|
717
|
+
const normalized = value.map((url) => normalizeBaseUrl3(url));
|
|
718
|
+
void driver.setItem(SDK_STORAGE_KEYS.BASE_URLS_LIST, normalized);
|
|
719
|
+
set({ baseUrlsList: normalized });
|
|
720
|
+
},
|
|
721
|
+
setBaseUrlsLastUpdate: (value) => {
|
|
722
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_BASE_URLS_UPDATE, value);
|
|
723
|
+
set({ lastBaseUrlsUpdate: value });
|
|
724
|
+
},
|
|
725
|
+
setDisabledProviders: (value) => {
|
|
726
|
+
const normalized = value.map((url) => normalizeBaseUrl3(url));
|
|
727
|
+
void driver.setItem(SDK_STORAGE_KEYS.DISABLED_PROVIDERS, normalized);
|
|
728
|
+
set({ disabledProviders: normalized });
|
|
729
|
+
},
|
|
730
|
+
setMintsFromAllProviders: (value) => {
|
|
731
|
+
const normalized = {};
|
|
732
|
+
for (const [baseUrl, mints] of Object.entries(value)) {
|
|
733
|
+
normalized[normalizeBaseUrl3(baseUrl)] = mints.map(
|
|
734
|
+
(mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
void driver.setItem(
|
|
738
|
+
SDK_STORAGE_KEYS.MINTS_FROM_ALL_PROVIDERS,
|
|
739
|
+
normalized
|
|
740
|
+
);
|
|
741
|
+
set({ mintsFromAllProviders: normalized });
|
|
742
|
+
},
|
|
743
|
+
setInfoFromAllProviders: (value) => {
|
|
744
|
+
const normalized = {};
|
|
745
|
+
for (const [baseUrl, info] of Object.entries(value)) {
|
|
746
|
+
normalized[normalizeBaseUrl3(baseUrl)] = info;
|
|
747
|
+
}
|
|
748
|
+
void driver.setItem(SDK_STORAGE_KEYS.INFO_FROM_ALL_PROVIDERS, normalized);
|
|
749
|
+
set({ infoFromAllProviders: normalized });
|
|
750
|
+
},
|
|
751
|
+
setLastModelsUpdate: (value) => {
|
|
752
|
+
const normalized = {};
|
|
753
|
+
for (const [baseUrl, timestamp] of Object.entries(value)) {
|
|
754
|
+
normalized[normalizeBaseUrl3(baseUrl)] = timestamp;
|
|
755
|
+
}
|
|
756
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_MODELS_UPDATE, normalized);
|
|
757
|
+
set({ lastModelsUpdate: normalized });
|
|
758
|
+
},
|
|
759
|
+
setApiKeys: (value) => {
|
|
760
|
+
set((state) => {
|
|
761
|
+
const updates = typeof value === "function" ? value(state.apiKeys) : value;
|
|
762
|
+
const normalized = updates.map((entry) => ({
|
|
763
|
+
...entry,
|
|
764
|
+
baseUrl: normalizeBaseUrl3(entry.baseUrl),
|
|
765
|
+
balance: entry.balance ?? 0,
|
|
766
|
+
lastUsed: entry.lastUsed ?? null
|
|
767
|
+
}));
|
|
768
|
+
void driver.setItem(SDK_STORAGE_KEYS.API_KEYS, normalized);
|
|
769
|
+
return { apiKeys: normalized };
|
|
770
|
+
});
|
|
771
|
+
},
|
|
772
|
+
setChildKeys: (value) => {
|
|
773
|
+
set((state) => {
|
|
774
|
+
const updates = typeof value === "function" ? value(state.childKeys) : value;
|
|
775
|
+
const normalized = updates.map((entry) => ({
|
|
776
|
+
parentBaseUrl: normalizeBaseUrl3(entry.parentBaseUrl),
|
|
777
|
+
childKey: entry.childKey,
|
|
778
|
+
balance: entry.balance ?? 0,
|
|
779
|
+
balanceLimit: entry.balanceLimit,
|
|
780
|
+
validityDate: entry.validityDate,
|
|
781
|
+
createdAt: entry.createdAt ?? Date.now()
|
|
782
|
+
}));
|
|
783
|
+
void driver.setItem(SDK_STORAGE_KEYS.CHILD_KEYS, normalized);
|
|
784
|
+
return { childKeys: normalized };
|
|
785
|
+
});
|
|
786
|
+
},
|
|
787
|
+
setXcashuTokens: (value) => {
|
|
788
|
+
const normalized = {};
|
|
789
|
+
for (const [baseUrl, tokens] of Object.entries(value)) {
|
|
790
|
+
normalized[normalizeBaseUrl3(baseUrl)] = tokens.map((entry) => ({
|
|
791
|
+
...entry,
|
|
792
|
+
baseUrl: normalizeBaseUrl3(entry.baseUrl),
|
|
793
|
+
createdAt: entry.createdAt ?? Date.now(),
|
|
794
|
+
tryCount: entry.tryCount ?? 0
|
|
795
|
+
}));
|
|
796
|
+
}
|
|
797
|
+
void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, normalized);
|
|
798
|
+
set({ xcashuTokens: normalized });
|
|
799
|
+
},
|
|
800
|
+
updateXcashuTokenTryCount: (token, tryCount) => {
|
|
801
|
+
const currentTokens = get().xcashuTokens;
|
|
802
|
+
const updatedTokens = {};
|
|
803
|
+
for (const [baseUrl, tokens] of Object.entries(currentTokens)) {
|
|
804
|
+
updatedTokens[baseUrl] = tokens.map(
|
|
805
|
+
(entry) => entry.token === token ? { ...entry, tryCount } : entry
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
void driver.setItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, updatedTokens);
|
|
809
|
+
set({ xcashuTokens: updatedTokens });
|
|
810
|
+
},
|
|
811
|
+
setRoutstr21Models: (value) => {
|
|
812
|
+
void driver.setItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, value);
|
|
813
|
+
set({ routstr21Models: value });
|
|
814
|
+
},
|
|
815
|
+
setRoutstr21ModelsLastUpdate: (value) => {
|
|
816
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE, value);
|
|
817
|
+
set({ lastRoutstr21ModelsUpdate: value });
|
|
818
|
+
},
|
|
819
|
+
setCachedReceiveTokens: (value) => {
|
|
820
|
+
const normalized = value.map((entry) => ({
|
|
821
|
+
token: entry.token,
|
|
822
|
+
amount: entry.amount,
|
|
823
|
+
unit: entry.unit || "sat",
|
|
824
|
+
createdAt: entry.createdAt ?? Date.now()
|
|
825
|
+
}));
|
|
826
|
+
void driver.setItem(SDK_STORAGE_KEYS.CACHED_RECEIVE_TOKENS, normalized);
|
|
827
|
+
set({ cachedReceiveTokens: normalized });
|
|
828
|
+
},
|
|
829
|
+
setClientIds: (value) => {
|
|
830
|
+
set((state) => {
|
|
831
|
+
const updates = typeof value === "function" ? value(state.clientIds) : value;
|
|
832
|
+
const normalized = updates.map((entry) => ({
|
|
833
|
+
...entry,
|
|
834
|
+
createdAt: entry.createdAt ?? Date.now(),
|
|
835
|
+
lastUsed: entry.lastUsed ?? null
|
|
836
|
+
}));
|
|
837
|
+
void driver.setItem(SDK_STORAGE_KEYS.CLIENT_IDS, normalized);
|
|
838
|
+
return { clientIds: normalized };
|
|
839
|
+
});
|
|
840
|
+
},
|
|
841
|
+
// ========== Failure Tracking ==========
|
|
842
|
+
setFailedProviders: (value) => {
|
|
843
|
+
const normalized = value.map((url) => normalizeBaseUrl3(url));
|
|
844
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, normalized);
|
|
845
|
+
set({ failedProviders: normalized });
|
|
846
|
+
},
|
|
847
|
+
addFailedProvider: (baseUrl) => {
|
|
848
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
849
|
+
const current = get().failedProviders;
|
|
850
|
+
if (!current.includes(normalized)) {
|
|
851
|
+
const updated = [...current, normalized];
|
|
852
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, updated);
|
|
853
|
+
set({ failedProviders: updated });
|
|
854
|
+
}
|
|
855
|
+
},
|
|
856
|
+
removeFailedProvider: (baseUrl) => {
|
|
857
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
858
|
+
const current = get().failedProviders;
|
|
859
|
+
const updated = current.filter((url) => url !== normalized);
|
|
860
|
+
void driver.setItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, updated);
|
|
861
|
+
set({ failedProviders: updated });
|
|
862
|
+
},
|
|
863
|
+
setLastFailed: (value) => {
|
|
864
|
+
const normalized = {};
|
|
865
|
+
for (const [baseUrl, timestamp] of Object.entries(value)) {
|
|
866
|
+
normalized[normalizeBaseUrl3(baseUrl)] = timestamp;
|
|
867
|
+
}
|
|
868
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_FAILED, normalized);
|
|
869
|
+
set({ lastFailed: normalized });
|
|
870
|
+
},
|
|
871
|
+
setLastFailedTimestamp: (baseUrl, timestamp) => {
|
|
872
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
873
|
+
const current = get().lastFailed;
|
|
874
|
+
const updated = { ...current, [normalized]: timestamp };
|
|
875
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_FAILED, updated);
|
|
876
|
+
set({ lastFailed: updated });
|
|
877
|
+
},
|
|
878
|
+
setProvidersOnCooldown: (value) => {
|
|
879
|
+
const normalized = value.map((entry) => ({
|
|
880
|
+
baseUrl: normalizeBaseUrl3(entry.baseUrl),
|
|
881
|
+
timestamp: entry.timestamp
|
|
882
|
+
}));
|
|
883
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, normalized);
|
|
884
|
+
set({ providersOnCooldown: normalized });
|
|
885
|
+
},
|
|
886
|
+
addProviderOnCooldown: (baseUrl, timestamp) => {
|
|
887
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
888
|
+
const current = get().providersOnCooldown;
|
|
889
|
+
if (!current.some((entry) => entry.baseUrl === normalized)) {
|
|
890
|
+
const updated = [...current, { baseUrl: normalized, timestamp }];
|
|
891
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, updated);
|
|
892
|
+
set({ providersOnCooldown: updated });
|
|
893
|
+
}
|
|
894
|
+
},
|
|
895
|
+
removeProviderFromCooldown: (baseUrl) => {
|
|
896
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
897
|
+
const current = get().providersOnCooldown;
|
|
898
|
+
const updated = current.filter((entry) => entry.baseUrl !== normalized);
|
|
899
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, updated);
|
|
900
|
+
set({ providersOnCooldown: updated });
|
|
901
|
+
},
|
|
902
|
+
clearProvidersOnCooldown: () => {
|
|
903
|
+
void driver.setItem(SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN, []);
|
|
904
|
+
set({ providersOnCooldown: [] });
|
|
905
|
+
}
|
|
906
|
+
}));
|
|
907
|
+
var hydrateStoreFromDriver = async (store, driver) => {
|
|
908
|
+
const [
|
|
909
|
+
rawModels,
|
|
910
|
+
lastUsedModel,
|
|
911
|
+
rawBaseUrls,
|
|
912
|
+
lastBaseUrlsUpdate,
|
|
913
|
+
rawDisabledProviders,
|
|
914
|
+
rawMints,
|
|
915
|
+
rawInfo,
|
|
916
|
+
rawLastModelsUpdate,
|
|
917
|
+
rawApiKeys,
|
|
918
|
+
rawChildKeys,
|
|
919
|
+
rawXcashuTokens,
|
|
920
|
+
rawRoutstr21Models,
|
|
921
|
+
rawLastRoutstr21ModelsUpdate,
|
|
922
|
+
rawCachedReceiveTokens,
|
|
923
|
+
rawClientIds,
|
|
924
|
+
rawFailedProviders,
|
|
925
|
+
rawLastFailed,
|
|
926
|
+
rawProvidersOnCooldown
|
|
927
|
+
] = await Promise.all([
|
|
928
|
+
driver.getItem(
|
|
929
|
+
SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS,
|
|
930
|
+
{}
|
|
931
|
+
),
|
|
932
|
+
driver.getItem(SDK_STORAGE_KEYS.LAST_USED_MODEL, null),
|
|
933
|
+
driver.getItem(SDK_STORAGE_KEYS.BASE_URLS_LIST, []),
|
|
934
|
+
driver.getItem(SDK_STORAGE_KEYS.LAST_BASE_URLS_UPDATE, null),
|
|
935
|
+
driver.getItem(SDK_STORAGE_KEYS.DISABLED_PROVIDERS, []),
|
|
936
|
+
driver.getItem(
|
|
937
|
+
SDK_STORAGE_KEYS.MINTS_FROM_ALL_PROVIDERS,
|
|
938
|
+
{}
|
|
939
|
+
),
|
|
940
|
+
driver.getItem(
|
|
941
|
+
SDK_STORAGE_KEYS.INFO_FROM_ALL_PROVIDERS,
|
|
942
|
+
{}
|
|
943
|
+
),
|
|
944
|
+
driver.getItem(
|
|
945
|
+
SDK_STORAGE_KEYS.LAST_MODELS_UPDATE,
|
|
946
|
+
{}
|
|
947
|
+
),
|
|
948
|
+
driver.getItem(SDK_STORAGE_KEYS.API_KEYS, []),
|
|
949
|
+
driver.getItem(SDK_STORAGE_KEYS.CHILD_KEYS, []),
|
|
950
|
+
driver.getItem(SDK_STORAGE_KEYS.XCASHU_TOKENS, {}),
|
|
951
|
+
driver.getItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, []),
|
|
952
|
+
driver.getItem(
|
|
953
|
+
SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE,
|
|
954
|
+
null
|
|
955
|
+
),
|
|
956
|
+
driver.getItem(SDK_STORAGE_KEYS.CACHED_RECEIVE_TOKENS, []),
|
|
957
|
+
driver.getItem(SDK_STORAGE_KEYS.CLIENT_IDS, []),
|
|
958
|
+
driver.getItem(SDK_STORAGE_KEYS.FAILED_PROVIDERS, []),
|
|
959
|
+
driver.getItem(SDK_STORAGE_KEYS.LAST_FAILED, {}),
|
|
960
|
+
driver.getItem(
|
|
961
|
+
SDK_STORAGE_KEYS.PROVIDERS_ON_COOLDOWN,
|
|
962
|
+
[]
|
|
963
|
+
)
|
|
964
|
+
]);
|
|
965
|
+
const modelsFromAllProviders = Object.fromEntries(
|
|
966
|
+
Object.entries(rawModels).map(([baseUrl, models]) => [
|
|
967
|
+
normalizeBaseUrl3(baseUrl),
|
|
968
|
+
models
|
|
969
|
+
])
|
|
970
|
+
);
|
|
971
|
+
const baseUrlsList = rawBaseUrls.map((url) => normalizeBaseUrl3(url));
|
|
972
|
+
const disabledProviders = rawDisabledProviders.map(
|
|
973
|
+
(url) => normalizeBaseUrl3(url)
|
|
974
|
+
);
|
|
975
|
+
const mintsFromAllProviders = Object.fromEntries(
|
|
976
|
+
Object.entries(rawMints).map(([baseUrl, mints]) => [
|
|
977
|
+
normalizeBaseUrl3(baseUrl),
|
|
978
|
+
mints.map((mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint)
|
|
979
|
+
])
|
|
980
|
+
);
|
|
981
|
+
const infoFromAllProviders = Object.fromEntries(
|
|
982
|
+
Object.entries(rawInfo).map(([baseUrl, info]) => [
|
|
983
|
+
normalizeBaseUrl3(baseUrl),
|
|
984
|
+
info
|
|
985
|
+
])
|
|
986
|
+
);
|
|
987
|
+
const lastModelsUpdate = Object.fromEntries(
|
|
988
|
+
Object.entries(rawLastModelsUpdate).map(([baseUrl, timestamp]) => [
|
|
989
|
+
normalizeBaseUrl3(baseUrl),
|
|
990
|
+
timestamp
|
|
991
|
+
])
|
|
992
|
+
);
|
|
993
|
+
const apiKeys = rawApiKeys.map((entry) => ({
|
|
994
|
+
...entry,
|
|
995
|
+
baseUrl: normalizeBaseUrl3(entry.baseUrl),
|
|
996
|
+
balance: entry.balance ?? 0,
|
|
997
|
+
lastUsed: entry.lastUsed ?? null
|
|
998
|
+
}));
|
|
999
|
+
const childKeys = rawChildKeys.map((entry) => ({
|
|
1000
|
+
parentBaseUrl: normalizeBaseUrl3(entry.parentBaseUrl),
|
|
1001
|
+
childKey: entry.childKey,
|
|
1002
|
+
balance: entry.balance ?? 0,
|
|
1003
|
+
balanceLimit: entry.balanceLimit,
|
|
1004
|
+
validityDate: entry.validityDate,
|
|
1005
|
+
createdAt: entry.createdAt ?? Date.now()
|
|
1006
|
+
}));
|
|
1007
|
+
const xcashuTokens = Object.fromEntries(
|
|
1008
|
+
Object.entries(rawXcashuTokens).map(([baseUrl, tokens]) => [
|
|
1009
|
+
normalizeBaseUrl3(baseUrl),
|
|
1010
|
+
tokens.map((entry) => ({
|
|
1011
|
+
baseUrl: normalizeBaseUrl3(entry.baseUrl),
|
|
1012
|
+
token: entry.token,
|
|
1013
|
+
createdAt: entry.createdAt ?? Date.now(),
|
|
1014
|
+
tryCount: entry.tryCount ?? 0
|
|
1015
|
+
}))
|
|
1016
|
+
])
|
|
1017
|
+
);
|
|
1018
|
+
const routstr21Models = rawRoutstr21Models;
|
|
1019
|
+
const lastRoutstr21ModelsUpdate = rawLastRoutstr21ModelsUpdate;
|
|
1020
|
+
const cachedReceiveTokens = rawCachedReceiveTokens?.map((entry) => ({
|
|
1021
|
+
token: entry.token,
|
|
1022
|
+
amount: entry.amount,
|
|
1023
|
+
unit: entry.unit || "sat",
|
|
1024
|
+
createdAt: entry.createdAt ?? Date.now()
|
|
1025
|
+
}));
|
|
1026
|
+
const clientIds = rawClientIds.map((entry) => ({
|
|
1027
|
+
...entry,
|
|
1028
|
+
createdAt: entry.createdAt ?? Date.now(),
|
|
1029
|
+
lastUsed: entry.lastUsed ?? null
|
|
1030
|
+
}));
|
|
1031
|
+
const failedProviders = rawFailedProviders.map(
|
|
1032
|
+
(url) => normalizeBaseUrl3(url)
|
|
1033
|
+
);
|
|
1034
|
+
const lastFailed = Object.fromEntries(
|
|
1035
|
+
Object.entries(rawLastFailed).map(([baseUrl, timestamp]) => [
|
|
1036
|
+
normalizeBaseUrl3(baseUrl),
|
|
1037
|
+
timestamp
|
|
1038
|
+
])
|
|
1039
|
+
);
|
|
1040
|
+
const providersOnCooldown = rawProvidersOnCooldown.map((entry) => ({
|
|
1041
|
+
baseUrl: normalizeBaseUrl3(entry.baseUrl),
|
|
1042
|
+
timestamp: entry.timestamp
|
|
1043
|
+
}));
|
|
1044
|
+
store.setState({
|
|
1045
|
+
modelsFromAllProviders,
|
|
1046
|
+
lastUsedModel,
|
|
1047
|
+
baseUrlsList,
|
|
1048
|
+
lastBaseUrlsUpdate,
|
|
1049
|
+
disabledProviders,
|
|
1050
|
+
mintsFromAllProviders,
|
|
1051
|
+
infoFromAllProviders,
|
|
1052
|
+
lastModelsUpdate,
|
|
1053
|
+
apiKeys,
|
|
1054
|
+
childKeys,
|
|
1055
|
+
xcashuTokens,
|
|
1056
|
+
routstr21Models,
|
|
1057
|
+
lastRoutstr21ModelsUpdate,
|
|
1058
|
+
cachedReceiveTokens,
|
|
1059
|
+
clientIds,
|
|
1060
|
+
failedProviders,
|
|
1061
|
+
lastFailed,
|
|
1062
|
+
providersOnCooldown
|
|
1063
|
+
});
|
|
1064
|
+
};
|
|
1065
|
+
var createSdkStore = ({
|
|
1066
|
+
driver
|
|
1067
|
+
}) => {
|
|
1068
|
+
const store = createEmptyStore(driver);
|
|
1069
|
+
return {
|
|
1070
|
+
store,
|
|
1071
|
+
hydrate: hydrateStoreFromDriver(store, driver)
|
|
1072
|
+
};
|
|
1073
|
+
};
|
|
1074
|
+
var createDiscoveryAdapterFromStore = (store) => ({
|
|
1075
|
+
getCachedModels: () => store.getState().modelsFromAllProviders,
|
|
1076
|
+
setCachedModels: (models) => store.getState().setModelsFromAllProviders(models),
|
|
1077
|
+
getCachedMints: () => store.getState().mintsFromAllProviders,
|
|
1078
|
+
setCachedMints: (mints) => store.getState().setMintsFromAllProviders(mints),
|
|
1079
|
+
getCachedProviderInfo: () => store.getState().infoFromAllProviders,
|
|
1080
|
+
setCachedProviderInfo: (info) => store.getState().setInfoFromAllProviders(info),
|
|
1081
|
+
getProviderLastUpdate: (baseUrl) => {
|
|
1082
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1083
|
+
const timestamps = store.getState().lastModelsUpdate;
|
|
1084
|
+
return timestamps[normalized] || null;
|
|
1085
|
+
},
|
|
1086
|
+
setProviderLastUpdate: (baseUrl, timestamp) => {
|
|
1087
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1088
|
+
const timestamps = { ...store.getState().lastModelsUpdate };
|
|
1089
|
+
timestamps[normalized] = timestamp;
|
|
1090
|
+
store.getState().setLastModelsUpdate(timestamps);
|
|
1091
|
+
},
|
|
1092
|
+
getLastUsedModel: () => store.getState().lastUsedModel,
|
|
1093
|
+
setLastUsedModel: (modelId) => store.getState().setLastUsedModel(modelId),
|
|
1094
|
+
getDisabledProviders: () => store.getState().disabledProviders,
|
|
1095
|
+
setDisabledProviders: (urls) => store.getState().setDisabledProviders(urls),
|
|
1096
|
+
getBaseUrlsList: () => store.getState().baseUrlsList,
|
|
1097
|
+
setBaseUrlsList: (urls) => store.getState().setBaseUrlsList(urls),
|
|
1098
|
+
getBaseUrlsLastUpdate: () => store.getState().lastBaseUrlsUpdate,
|
|
1099
|
+
setBaseUrlsLastUpdate: (timestamp) => store.getState().setBaseUrlsLastUpdate(timestamp),
|
|
1100
|
+
getRoutstr21Models: () => store.getState().routstr21Models,
|
|
1101
|
+
setRoutstr21Models: (models) => store.getState().setRoutstr21Models(models),
|
|
1102
|
+
getRoutstr21ModelsLastUpdate: () => store.getState().lastRoutstr21ModelsUpdate,
|
|
1103
|
+
setRoutstr21ModelsLastUpdate: (timestamp) => store.getState().setRoutstr21ModelsLastUpdate(timestamp)
|
|
1104
|
+
});
|
|
1105
|
+
var createStorageAdapterFromStore = (store) => ({
|
|
1106
|
+
getApiKeyDistribution: () => {
|
|
1107
|
+
const apiKeys = store.getState().apiKeys;
|
|
1108
|
+
const distributionMap = {};
|
|
1109
|
+
for (const entry of apiKeys) {
|
|
1110
|
+
const sum = entry.balance || 0;
|
|
1111
|
+
distributionMap[entry.baseUrl] = (distributionMap[entry.baseUrl] || 0) + sum;
|
|
1112
|
+
}
|
|
1113
|
+
return Object.entries(distributionMap).map(([baseUrl, amt]) => ({ baseUrl, amount: amt })).sort((a, b) => b.amount - a.amount);
|
|
1114
|
+
},
|
|
1115
|
+
saveProviderInfo: (baseUrl, info) => {
|
|
1116
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1117
|
+
const next = { ...store.getState().infoFromAllProviders };
|
|
1118
|
+
next[normalized] = info;
|
|
1119
|
+
store.getState().setInfoFromAllProviders(next);
|
|
1120
|
+
},
|
|
1121
|
+
getProviderInfo: (baseUrl) => {
|
|
1122
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1123
|
+
return store.getState().infoFromAllProviders[normalized] || null;
|
|
1124
|
+
},
|
|
1125
|
+
// ========== API Keys (for apikeys mode) ==========
|
|
1126
|
+
getApiKey: (baseUrl) => {
|
|
1127
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1128
|
+
const entry = store.getState().apiKeys.find((key) => key.baseUrl === normalized);
|
|
1129
|
+
if (!entry) return null;
|
|
1130
|
+
return entry;
|
|
1131
|
+
},
|
|
1132
|
+
setApiKey: (baseUrl, key) => {
|
|
1133
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1134
|
+
const keys = store.getState().apiKeys;
|
|
1135
|
+
const existingIndex = keys.findIndex(
|
|
1136
|
+
(entry) => entry.baseUrl === normalized
|
|
1137
|
+
);
|
|
1138
|
+
if (existingIndex !== -1) {
|
|
1139
|
+
throw new Error(`ApiKey already exists for baseUrl: ${normalized}`);
|
|
1140
|
+
}
|
|
1141
|
+
const next = [...keys];
|
|
1142
|
+
next.push({
|
|
1143
|
+
baseUrl: normalized,
|
|
1144
|
+
key,
|
|
1145
|
+
balance: 0,
|
|
1146
|
+
lastUsed: Date.now()
|
|
1147
|
+
});
|
|
1148
|
+
store.getState().setApiKeys(next);
|
|
1149
|
+
},
|
|
1150
|
+
updateApiKeyBalance: (baseUrl, balance) => {
|
|
1151
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1152
|
+
const keys = store.getState().apiKeys;
|
|
1153
|
+
const next = keys.map(
|
|
1154
|
+
(entry) => entry.baseUrl === normalized ? { ...entry, balance, lastUsed: Date.now() } : entry
|
|
1155
|
+
);
|
|
1156
|
+
store.getState().setApiKeys(next);
|
|
1157
|
+
},
|
|
1158
|
+
removeApiKey: (baseUrl) => {
|
|
1159
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1160
|
+
const next = store.getState().apiKeys.filter((entry) => entry.baseUrl !== normalized);
|
|
1161
|
+
store.getState().setApiKeys(next);
|
|
1162
|
+
},
|
|
1163
|
+
getAllApiKeys: () => {
|
|
1164
|
+
return store.getState().apiKeys.map((entry) => ({
|
|
1165
|
+
baseUrl: entry.baseUrl,
|
|
1166
|
+
key: entry.key,
|
|
1167
|
+
balance: entry.balance,
|
|
1168
|
+
lastUsed: entry.lastUsed
|
|
1169
|
+
}));
|
|
1170
|
+
},
|
|
1171
|
+
// ========== Child Keys ==========
|
|
1172
|
+
getChildKey: (parentBaseUrl) => {
|
|
1173
|
+
const normalized = normalizeBaseUrl3(parentBaseUrl);
|
|
1174
|
+
const entry = store.getState().childKeys.find((key) => key.parentBaseUrl === normalized);
|
|
1175
|
+
if (!entry) return null;
|
|
1176
|
+
return {
|
|
1177
|
+
parentBaseUrl: entry.parentBaseUrl,
|
|
1178
|
+
childKey: entry.childKey,
|
|
1179
|
+
balance: entry.balance,
|
|
1180
|
+
balanceLimit: entry.balanceLimit,
|
|
1181
|
+
validityDate: entry.validityDate,
|
|
1182
|
+
createdAt: entry.createdAt
|
|
1183
|
+
};
|
|
1184
|
+
},
|
|
1185
|
+
setChildKey: (parentBaseUrl, childKey, balance, validityDate, balanceLimit) => {
|
|
1186
|
+
const normalized = normalizeBaseUrl3(parentBaseUrl);
|
|
1187
|
+
const keys = store.getState().childKeys;
|
|
1188
|
+
const existingIndex = keys.findIndex(
|
|
1189
|
+
(entry) => entry.parentBaseUrl === normalized
|
|
1190
|
+
);
|
|
1191
|
+
if (existingIndex !== -1) {
|
|
1192
|
+
const next = keys.map(
|
|
1193
|
+
(entry) => entry.parentBaseUrl === normalized ? {
|
|
1194
|
+
...entry,
|
|
1195
|
+
childKey,
|
|
1196
|
+
balance: balance ?? 0,
|
|
1197
|
+
validityDate,
|
|
1198
|
+
balanceLimit,
|
|
1199
|
+
createdAt: Date.now()
|
|
1200
|
+
} : entry
|
|
1201
|
+
);
|
|
1202
|
+
store.getState().setChildKeys(next);
|
|
1203
|
+
} else {
|
|
1204
|
+
const next = [...keys];
|
|
1205
|
+
next.push({
|
|
1206
|
+
parentBaseUrl: normalized,
|
|
1207
|
+
childKey,
|
|
1208
|
+
balance: balance ?? 0,
|
|
1209
|
+
validityDate,
|
|
1210
|
+
balanceLimit,
|
|
1211
|
+
createdAt: Date.now()
|
|
1212
|
+
});
|
|
1213
|
+
store.getState().setChildKeys(next);
|
|
1214
|
+
}
|
|
1215
|
+
},
|
|
1216
|
+
updateChildKeyBalance: (parentBaseUrl, balance) => {
|
|
1217
|
+
const normalized = normalizeBaseUrl3(parentBaseUrl);
|
|
1218
|
+
const keys = store.getState().childKeys;
|
|
1219
|
+
const next = keys.map(
|
|
1220
|
+
(entry) => entry.parentBaseUrl === normalized ? { ...entry, balance } : entry
|
|
1221
|
+
);
|
|
1222
|
+
store.getState().setChildKeys(next);
|
|
1223
|
+
},
|
|
1224
|
+
removeChildKey: (parentBaseUrl) => {
|
|
1225
|
+
const normalized = normalizeBaseUrl3(parentBaseUrl);
|
|
1226
|
+
const next = store.getState().childKeys.filter((entry) => entry.parentBaseUrl !== normalized);
|
|
1227
|
+
store.getState().setChildKeys(next);
|
|
1228
|
+
},
|
|
1229
|
+
getAllChildKeys: () => {
|
|
1230
|
+
return store.getState().childKeys.map((entry) => ({
|
|
1231
|
+
parentBaseUrl: entry.parentBaseUrl,
|
|
1232
|
+
childKey: entry.childKey,
|
|
1233
|
+
balance: entry.balance,
|
|
1234
|
+
balanceLimit: entry.balanceLimit,
|
|
1235
|
+
validityDate: entry.validityDate,
|
|
1236
|
+
createdAt: entry.createdAt
|
|
1237
|
+
}));
|
|
1238
|
+
},
|
|
1239
|
+
getCachedReceiveTokens: () => {
|
|
1240
|
+
return store.getState().cachedReceiveTokens;
|
|
1241
|
+
},
|
|
1242
|
+
setCachedReceiveTokens: (tokens) => {
|
|
1243
|
+
store.getState().setCachedReceiveTokens(tokens);
|
|
1244
|
+
},
|
|
1245
|
+
// ========== XCashu Tokens (multiple tokens per baseUrl) ==========
|
|
1246
|
+
getXcashuTokens: () => {
|
|
1247
|
+
return store.getState().xcashuTokens;
|
|
1248
|
+
},
|
|
1249
|
+
getXcashuTokensForBaseUrl: (baseUrl) => {
|
|
1250
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1251
|
+
return store.getState().xcashuTokens[normalized] || [];
|
|
1252
|
+
},
|
|
1253
|
+
addXcashuToken: (baseUrl, token) => {
|
|
1254
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1255
|
+
const tokens = store.getState().xcashuTokens;
|
|
1256
|
+
const existing = tokens[normalized] || [];
|
|
1257
|
+
const next = { ...tokens };
|
|
1258
|
+
next[normalized] = [
|
|
1259
|
+
...existing,
|
|
1260
|
+
{ baseUrl: normalized, token, createdAt: Date.now(), tryCount: 0 }
|
|
1261
|
+
];
|
|
1262
|
+
store.getState().setXcashuTokens(next);
|
|
1263
|
+
},
|
|
1264
|
+
removeXcashuToken: (baseUrl, token) => {
|
|
1265
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1266
|
+
const tokens = store.getState().xcashuTokens;
|
|
1267
|
+
const existing = tokens[normalized] || [];
|
|
1268
|
+
const next = { ...tokens };
|
|
1269
|
+
next[normalized] = existing.filter((entry) => entry.token !== token);
|
|
1270
|
+
if (next[normalized].length === 0) {
|
|
1271
|
+
delete next[normalized];
|
|
1272
|
+
}
|
|
1273
|
+
store.getState().setXcashuTokens(next);
|
|
1274
|
+
},
|
|
1275
|
+
clearXcashuTokensForBaseUrl: (baseUrl) => {
|
|
1276
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1277
|
+
const tokens = store.getState().xcashuTokens;
|
|
1278
|
+
const next = { ...tokens };
|
|
1279
|
+
delete next[normalized];
|
|
1280
|
+
store.getState().setXcashuTokens(next);
|
|
1281
|
+
},
|
|
1282
|
+
updateXcashuTokenTryCount: (token, tryCount) => {
|
|
1283
|
+
store.getState().updateXcashuTokenTryCount(token, tryCount);
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
var createProviderRegistryFromStore = (store, logger) => {
|
|
1287
|
+
const log = (logger ?? consoleLogger).child("ProviderRegistry");
|
|
1288
|
+
return {
|
|
1289
|
+
getModelsForProvider: (baseUrl) => {
|
|
1290
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1291
|
+
return store.getState().modelsFromAllProviders[normalized] || [];
|
|
1292
|
+
},
|
|
1293
|
+
getDisabledProviders: () => store.getState().disabledProviders,
|
|
1294
|
+
getProviderMints: (baseUrl) => {
|
|
1295
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1296
|
+
return store.getState().mintsFromAllProviders[normalized] || [];
|
|
1297
|
+
},
|
|
1298
|
+
getProviderInfo: async (baseUrl) => {
|
|
1299
|
+
const normalized = normalizeBaseUrl3(baseUrl);
|
|
1300
|
+
const cached = store.getState().infoFromAllProviders[normalized];
|
|
1301
|
+
if (cached) return cached;
|
|
1302
|
+
try {
|
|
1303
|
+
const response = await fetch(`${normalized}v1/info`);
|
|
1304
|
+
if (!response.ok) {
|
|
1305
|
+
throw new Error(`Failed ${response.status}`);
|
|
1306
|
+
}
|
|
1307
|
+
const info = await response.json();
|
|
1308
|
+
const next = { ...store.getState().infoFromAllProviders };
|
|
1309
|
+
next[normalized] = info;
|
|
1310
|
+
store.getState().setInfoFromAllProviders(next);
|
|
1311
|
+
return info;
|
|
1312
|
+
} catch (error) {
|
|
1313
|
+
log.warn(`Failed to fetch provider info from ${normalized}:`, error);
|
|
1314
|
+
return null;
|
|
1315
|
+
}
|
|
1316
|
+
},
|
|
1317
|
+
getAllProvidersModels: () => store.getState().modelsFromAllProviders
|
|
1318
|
+
};
|
|
1319
|
+
};
|
|
1320
|
+
|
|
1321
|
+
// storage/shardedDiscoveryAdapter.ts
|
|
1322
|
+
var MODEL_KEY_PREFIX = "models:provider:";
|
|
1323
|
+
var MODEL_TS_KEY_PREFIX = "models:provider_timestamp:";
|
|
1324
|
+
var PROVIDER_INDEX_KEY = "models:provider_index";
|
|
1325
|
+
var MIGRATION_MARKER_KEY2 = "models_sharded_migration_v1";
|
|
1326
|
+
var encodeBaseUrl = (baseUrl) => encodeURIComponent(baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
1327
|
+
var modelKey = (baseUrl) => `${MODEL_KEY_PREFIX}${encodeBaseUrl(baseUrl)}`;
|
|
1328
|
+
var modelTsKey = (baseUrl) => `${MODEL_TS_KEY_PREFIX}${encodeBaseUrl(baseUrl)}`;
|
|
1329
|
+
var normalizeBaseUrl4 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
1330
|
+
var createShardedDiscoveryAdapter = async (options) => {
|
|
1331
|
+
const { driver } = options;
|
|
1332
|
+
const legacyModels = await driver.getItem(SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS, {});
|
|
1333
|
+
const legacyTimestamps = await driver.getItem(SDK_STORAGE_KEYS.LAST_MODELS_UPDATE, {});
|
|
1334
|
+
if (Object.keys(legacyModels).length > 0) {
|
|
1335
|
+
const migratedProviders = [];
|
|
1336
|
+
for (const [baseUrl, models] of Object.entries(legacyModels)) {
|
|
1337
|
+
const normalized = normalizeBaseUrl4(baseUrl);
|
|
1338
|
+
await driver.setItem(modelKey(normalized), models);
|
|
1339
|
+
const ts = legacyTimestamps[normalized] ?? Date.now();
|
|
1340
|
+
await driver.setItem(modelTsKey(normalized), ts);
|
|
1341
|
+
migratedProviders.push(normalized);
|
|
1342
|
+
}
|
|
1343
|
+
const existingIndex = await driver.getItem(
|
|
1344
|
+
PROVIDER_INDEX_KEY,
|
|
1345
|
+
[]
|
|
1346
|
+
);
|
|
1347
|
+
const merged = [.../* @__PURE__ */ new Set([...existingIndex, ...migratedProviders])];
|
|
1348
|
+
await driver.setItem(PROVIDER_INDEX_KEY, merged);
|
|
1349
|
+
await driver.removeItem(SDK_STORAGE_KEYS.MODELS_FROM_ALL_PROVIDERS);
|
|
1350
|
+
await driver.removeItem(SDK_STORAGE_KEYS.LAST_MODELS_UPDATE);
|
|
1351
|
+
}
|
|
1352
|
+
await driver.setItem(MIGRATION_MARKER_KEY2, true);
|
|
1353
|
+
const [
|
|
1354
|
+
rawMints,
|
|
1355
|
+
rawInfo,
|
|
1356
|
+
lastUsedModel,
|
|
1357
|
+
rawDisabled,
|
|
1358
|
+
rawBaseUrls,
|
|
1359
|
+
lastBaseUrlsUpdate,
|
|
1360
|
+
rawRoutstr21Models,
|
|
1361
|
+
lastRoutstr21ModelsUpdate
|
|
1362
|
+
] = await Promise.all([
|
|
1363
|
+
driver.getItem(
|
|
1364
|
+
SDK_STORAGE_KEYS.MINTS_FROM_ALL_PROVIDERS,
|
|
1365
|
+
{}
|
|
1366
|
+
),
|
|
1367
|
+
driver.getItem(
|
|
1368
|
+
SDK_STORAGE_KEYS.INFO_FROM_ALL_PROVIDERS,
|
|
1369
|
+
{}
|
|
1370
|
+
),
|
|
1371
|
+
driver.getItem(SDK_STORAGE_KEYS.LAST_USED_MODEL, null),
|
|
1372
|
+
driver.getItem(SDK_STORAGE_KEYS.DISABLED_PROVIDERS, []),
|
|
1373
|
+
driver.getItem(SDK_STORAGE_KEYS.BASE_URLS_LIST, []),
|
|
1374
|
+
driver.getItem(SDK_STORAGE_KEYS.LAST_BASE_URLS_UPDATE, null),
|
|
1375
|
+
driver.getItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, []),
|
|
1376
|
+
driver.getItem(
|
|
1377
|
+
SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE,
|
|
1378
|
+
null
|
|
1379
|
+
)
|
|
1380
|
+
]);
|
|
1381
|
+
const modelsByBaseUrl = /* @__PURE__ */ new Map();
|
|
1382
|
+
const timestampsByBaseUrl = /* @__PURE__ */ new Map();
|
|
1383
|
+
const providerIndex = /* @__PURE__ */ new Set();
|
|
1384
|
+
const knownProviders = /* @__PURE__ */ new Set();
|
|
1385
|
+
for (const baseUrl of Object.keys(rawInfo)) {
|
|
1386
|
+
knownProviders.add(normalizeBaseUrl4(baseUrl));
|
|
1387
|
+
}
|
|
1388
|
+
for (const baseUrl of Object.keys(rawMints)) {
|
|
1389
|
+
knownProviders.add(normalizeBaseUrl4(baseUrl));
|
|
1390
|
+
}
|
|
1391
|
+
for (const baseUrl of rawBaseUrls) {
|
|
1392
|
+
knownProviders.add(normalizeBaseUrl4(baseUrl));
|
|
1393
|
+
}
|
|
1394
|
+
for (const baseUrl of rawDisabled) {
|
|
1395
|
+
knownProviders.add(normalizeBaseUrl4(baseUrl));
|
|
1396
|
+
}
|
|
1397
|
+
for (const baseUrl of Object.keys(legacyModels)) {
|
|
1398
|
+
knownProviders.add(normalizeBaseUrl4(baseUrl));
|
|
1399
|
+
}
|
|
1400
|
+
const indexProviders = await driver.getItem(
|
|
1401
|
+
PROVIDER_INDEX_KEY,
|
|
1402
|
+
[]
|
|
1403
|
+
);
|
|
1404
|
+
for (const baseUrl of indexProviders) {
|
|
1405
|
+
const normalized = normalizeBaseUrl4(baseUrl);
|
|
1406
|
+
providerIndex.add(normalized);
|
|
1407
|
+
knownProviders.add(normalized);
|
|
1408
|
+
}
|
|
1409
|
+
for (const baseUrl of knownProviders) {
|
|
1410
|
+
const normalized = normalizeBaseUrl4(baseUrl);
|
|
1411
|
+
const models = await driver.getItem(
|
|
1412
|
+
modelKey(normalized),
|
|
1413
|
+
null
|
|
1414
|
+
);
|
|
1415
|
+
const ts = await driver.getItem(
|
|
1416
|
+
modelTsKey(normalized),
|
|
1417
|
+
null
|
|
1418
|
+
);
|
|
1419
|
+
if (models !== null) {
|
|
1420
|
+
modelsByBaseUrl.set(normalized, models);
|
|
1421
|
+
}
|
|
1422
|
+
if (ts !== null) {
|
|
1423
|
+
timestampsByBaseUrl.set(normalized, ts);
|
|
1424
|
+
}
|
|
1425
|
+
if (models !== null || ts !== null) {
|
|
1426
|
+
providerIndex.add(normalized);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
let mints = Object.fromEntries(
|
|
1430
|
+
Object.entries(rawMints).map(([baseUrl, mintList]) => [
|
|
1431
|
+
normalizeBaseUrl4(baseUrl),
|
|
1432
|
+
mintList.map((mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint)
|
|
1433
|
+
])
|
|
1434
|
+
);
|
|
1435
|
+
let info = Object.fromEntries(
|
|
1436
|
+
Object.entries(rawInfo).map(([baseUrl, entry]) => [
|
|
1437
|
+
normalizeBaseUrl4(baseUrl),
|
|
1438
|
+
entry
|
|
1439
|
+
])
|
|
1440
|
+
);
|
|
1441
|
+
let _lastUsedModel = lastUsedModel;
|
|
1442
|
+
let _disabledProviders = rawDisabled.map(normalizeBaseUrl4);
|
|
1443
|
+
let _baseUrlsList = rawBaseUrls.map(normalizeBaseUrl4);
|
|
1444
|
+
let _lastBaseUrlsUpdate = lastBaseUrlsUpdate;
|
|
1445
|
+
let _routstr21Models = rawRoutstr21Models;
|
|
1446
|
+
let _lastRoutstr21ModelsUpdate = lastRoutstr21ModelsUpdate;
|
|
1447
|
+
const persistProviderIndex = () => {
|
|
1448
|
+
void driver.setItem(PROVIDER_INDEX_KEY, [...providerIndex]);
|
|
1449
|
+
};
|
|
1450
|
+
return {
|
|
1451
|
+
// -- Models (sharded kv) --
|
|
1452
|
+
getCachedModels: () => {
|
|
1453
|
+
const result = {};
|
|
1454
|
+
for (const [baseUrl, models] of modelsByBaseUrl.entries()) {
|
|
1455
|
+
result[baseUrl] = models;
|
|
1456
|
+
}
|
|
1457
|
+
return result;
|
|
1458
|
+
},
|
|
1459
|
+
setCachedModels: (models) => {
|
|
1460
|
+
const nextKeys = new Set(
|
|
1461
|
+
Object.keys(models).map((baseUrl) => normalizeBaseUrl4(baseUrl))
|
|
1462
|
+
);
|
|
1463
|
+
for (const baseUrl of [...modelsByBaseUrl.keys()]) {
|
|
1464
|
+
if (!nextKeys.has(normalizeBaseUrl4(baseUrl))) {
|
|
1465
|
+
providerIndex.delete(baseUrl);
|
|
1466
|
+
modelsByBaseUrl.delete(baseUrl);
|
|
1467
|
+
timestampsByBaseUrl.delete(baseUrl);
|
|
1468
|
+
void driver.removeItem(modelKey(baseUrl));
|
|
1469
|
+
void driver.removeItem(modelTsKey(baseUrl));
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
for (const [baseUrl, modelList] of Object.entries(models)) {
|
|
1473
|
+
const normalized = normalizeBaseUrl4(baseUrl);
|
|
1474
|
+
providerIndex.add(normalized);
|
|
1475
|
+
modelsByBaseUrl.set(normalized, modelList);
|
|
1476
|
+
const ts = timestampsByBaseUrl.get(normalized) ?? Date.now();
|
|
1477
|
+
timestampsByBaseUrl.set(normalized, ts);
|
|
1478
|
+
void driver.setItem(modelKey(normalized), modelList);
|
|
1479
|
+
void driver.setItem(modelTsKey(normalized), ts);
|
|
1480
|
+
}
|
|
1481
|
+
persistProviderIndex();
|
|
1482
|
+
},
|
|
1483
|
+
getProviderLastUpdate: (baseUrl) => {
|
|
1484
|
+
return timestampsByBaseUrl.get(normalizeBaseUrl4(baseUrl)) ?? null;
|
|
1485
|
+
},
|
|
1486
|
+
setProviderLastUpdate: (baseUrl, timestamp) => {
|
|
1487
|
+
const normalized = normalizeBaseUrl4(baseUrl);
|
|
1488
|
+
providerIndex.add(normalized);
|
|
1489
|
+
timestampsByBaseUrl.set(normalized, timestamp);
|
|
1490
|
+
void driver.setItem(modelTsKey(normalized), timestamp);
|
|
1491
|
+
persistProviderIndex();
|
|
1492
|
+
},
|
|
1493
|
+
// -- Mints (kv) --
|
|
1494
|
+
getCachedMints: () => mints,
|
|
1495
|
+
setCachedMints: (value) => {
|
|
1496
|
+
const normalized = {};
|
|
1497
|
+
for (const [baseUrl, mintList] of Object.entries(value)) {
|
|
1498
|
+
normalized[normalizeBaseUrl4(baseUrl)] = mintList.map(
|
|
1499
|
+
(mint) => mint.endsWith("/") ? mint.slice(0, -1) : mint
|
|
1500
|
+
);
|
|
1501
|
+
}
|
|
1502
|
+
mints = normalized;
|
|
1503
|
+
void driver.setItem(SDK_STORAGE_KEYS.MINTS_FROM_ALL_PROVIDERS, normalized);
|
|
1504
|
+
},
|
|
1505
|
+
// -- Provider info (kv) --
|
|
1506
|
+
getCachedProviderInfo: () => info,
|
|
1507
|
+
setCachedProviderInfo: (value) => {
|
|
1508
|
+
const normalized = {};
|
|
1509
|
+
for (const [baseUrl, entry] of Object.entries(value)) {
|
|
1510
|
+
normalized[normalizeBaseUrl4(baseUrl)] = entry;
|
|
1511
|
+
}
|
|
1512
|
+
info = normalized;
|
|
1513
|
+
void driver.setItem(SDK_STORAGE_KEYS.INFO_FROM_ALL_PROVIDERS, normalized);
|
|
1514
|
+
},
|
|
1515
|
+
// -- Last used model (kv) --
|
|
1516
|
+
getLastUsedModel: () => _lastUsedModel,
|
|
1517
|
+
setLastUsedModel: (modelId) => {
|
|
1518
|
+
_lastUsedModel = modelId;
|
|
1519
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_USED_MODEL, modelId);
|
|
1520
|
+
},
|
|
1521
|
+
// -- Disabled providers (kv) --
|
|
1522
|
+
getDisabledProviders: () => _disabledProviders,
|
|
1523
|
+
setDisabledProviders: (urls) => {
|
|
1524
|
+
const normalized = urls.map(normalizeBaseUrl4);
|
|
1525
|
+
_disabledProviders = normalized;
|
|
1526
|
+
void driver.setItem(SDK_STORAGE_KEYS.DISABLED_PROVIDERS, normalized);
|
|
1527
|
+
},
|
|
1528
|
+
// -- Base URLs (kv) --
|
|
1529
|
+
getBaseUrlsList: () => _baseUrlsList,
|
|
1530
|
+
getBaseUrlsLastUpdate: () => _lastBaseUrlsUpdate,
|
|
1531
|
+
setBaseUrlsList: (urls) => {
|
|
1532
|
+
const normalized = urls.map(normalizeBaseUrl4);
|
|
1533
|
+
_baseUrlsList = normalized;
|
|
1534
|
+
void driver.setItem(SDK_STORAGE_KEYS.BASE_URLS_LIST, normalized);
|
|
1535
|
+
},
|
|
1536
|
+
setBaseUrlsLastUpdate: (timestamp) => {
|
|
1537
|
+
_lastBaseUrlsUpdate = timestamp;
|
|
1538
|
+
void driver.setItem(SDK_STORAGE_KEYS.LAST_BASE_URLS_UPDATE, timestamp);
|
|
1539
|
+
},
|
|
1540
|
+
// -- Routstr21 models (kv) --
|
|
1541
|
+
getRoutstr21Models: () => _routstr21Models,
|
|
1542
|
+
setRoutstr21Models: (models) => {
|
|
1543
|
+
_routstr21Models = models;
|
|
1544
|
+
void driver.setItem(SDK_STORAGE_KEYS.ROUTSTR21_MODELS, models);
|
|
1545
|
+
},
|
|
1546
|
+
getRoutstr21ModelsLastUpdate: () => _lastRoutstr21ModelsUpdate,
|
|
1547
|
+
setRoutstr21ModelsLastUpdate: (timestamp) => {
|
|
1548
|
+
_lastRoutstr21ModelsUpdate = timestamp;
|
|
1549
|
+
void driver.setItem(
|
|
1550
|
+
SDK_STORAGE_KEYS.LAST_ROUTSTR21_MODELS_UPDATE,
|
|
1551
|
+
timestamp
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1554
|
+
};
|
|
1555
|
+
};
|
|
1556
|
+
var createProviderRegistryFromDiscoveryAdapter = (adapter, logger) => {
|
|
1557
|
+
const log = (logger ?? consoleLogger).child("ProviderRegistry");
|
|
1558
|
+
return {
|
|
1559
|
+
getModelsForProvider: (baseUrl) => {
|
|
1560
|
+
const normalized = normalizeBaseUrl4(baseUrl);
|
|
1561
|
+
return adapter.getCachedModels()[normalized] || [];
|
|
1562
|
+
},
|
|
1563
|
+
getDisabledProviders: () => adapter.getDisabledProviders(),
|
|
1564
|
+
getProviderMints: (baseUrl) => {
|
|
1565
|
+
const normalized = normalizeBaseUrl4(baseUrl);
|
|
1566
|
+
return adapter.getCachedMints()[normalized] || [];
|
|
1567
|
+
},
|
|
1568
|
+
getProviderInfo: async (baseUrl) => {
|
|
1569
|
+
const normalized = normalizeBaseUrl4(baseUrl);
|
|
1570
|
+
const cached = adapter.getCachedProviderInfo()[normalized];
|
|
1571
|
+
if (cached) return cached;
|
|
1572
|
+
try {
|
|
1573
|
+
const response = await fetch(`${normalized}v1/info`);
|
|
1574
|
+
if (!response.ok) {
|
|
1575
|
+
throw new Error(`Failed ${response.status}`);
|
|
1576
|
+
}
|
|
1577
|
+
const info = await response.json();
|
|
1578
|
+
adapter.setCachedProviderInfo({
|
|
1579
|
+
...adapter.getCachedProviderInfo(),
|
|
1580
|
+
[normalized]: info
|
|
1581
|
+
});
|
|
1582
|
+
return info;
|
|
1583
|
+
} catch (error) {
|
|
1584
|
+
log.warn(`Failed to fetch provider info from ${normalized}:`, error);
|
|
1585
|
+
return null;
|
|
1586
|
+
}
|
|
1587
|
+
},
|
|
1588
|
+
getAllProvidersModels: () => adapter.getCachedModels()
|
|
1589
|
+
};
|
|
1590
|
+
};
|
|
1591
|
+
|
|
1592
|
+
// storage/index.ts
|
|
1593
|
+
var isBrowser3 = () => {
|
|
1594
|
+
try {
|
|
1595
|
+
return typeof window !== "undefined" && typeof window.localStorage !== "undefined";
|
|
1596
|
+
} catch {
|
|
1597
|
+
return false;
|
|
1598
|
+
}
|
|
1599
|
+
};
|
|
1600
|
+
var defaultDriver = null;
|
|
1601
|
+
var getDefaultSdkDriver = () => {
|
|
1602
|
+
if (defaultDriver) return defaultDriver;
|
|
1603
|
+
if (isBrowser3()) {
|
|
1604
|
+
defaultDriver = localStorageDriver;
|
|
1605
|
+
return defaultDriver;
|
|
1606
|
+
}
|
|
1607
|
+
defaultDriver = createMemoryDriver();
|
|
1608
|
+
return defaultDriver;
|
|
1609
|
+
};
|
|
1610
|
+
var defaultStore = null;
|
|
1611
|
+
var defaultUsageTrackingDriver = null;
|
|
1612
|
+
var getDefaultSdkStore = () => {
|
|
1613
|
+
if (!defaultStore) {
|
|
1614
|
+
defaultStore = createSdkStore({ driver: getDefaultSdkDriver() });
|
|
1615
|
+
}
|
|
1616
|
+
return defaultStore.hydrate.then(() => defaultStore.store);
|
|
1617
|
+
};
|
|
1618
|
+
var getDefaultUsageTrackingDriver = () => {
|
|
1619
|
+
if (defaultUsageTrackingDriver) return defaultUsageTrackingDriver;
|
|
1620
|
+
const storageDriver = getDefaultSdkDriver();
|
|
1621
|
+
if (isBrowser3()) {
|
|
1622
|
+
defaultUsageTrackingDriver = createIndexedDBUsageTrackingDriver({
|
|
1623
|
+
legacyStorageDriver: storageDriver
|
|
1624
|
+
});
|
|
1625
|
+
return defaultUsageTrackingDriver;
|
|
1626
|
+
}
|
|
1627
|
+
defaultUsageTrackingDriver = createMemoryUsageTrackingDriver();
|
|
1628
|
+
return defaultUsageTrackingDriver;
|
|
1629
|
+
};
|
|
1630
|
+
var setDefaultUsageTrackingDriver = (driver) => {
|
|
1631
|
+
defaultUsageTrackingDriver = driver;
|
|
1632
|
+
};
|
|
1633
|
+
var defaultDiscoveryAdapter = null;
|
|
1634
|
+
var getDefaultDiscoveryAdapter = async () => {
|
|
1635
|
+
if (defaultDiscoveryAdapter) return defaultDiscoveryAdapter;
|
|
1636
|
+
const driver = getDefaultSdkDriver();
|
|
1637
|
+
defaultDiscoveryAdapter = await createShardedDiscoveryAdapter({ driver });
|
|
1638
|
+
return defaultDiscoveryAdapter;
|
|
1639
|
+
};
|
|
1640
|
+
var getDefaultStorageAdapter = async () => createStorageAdapterFromStore(await getDefaultSdkStore());
|
|
1641
|
+
var getDefaultProviderRegistry = async () => createProviderRegistryFromDiscoveryAdapter(await getDefaultDiscoveryAdapter());
|
|
1642
|
+
|
|
1643
|
+
// storage/drivers/sqlite.ts
|
|
1644
|
+
var isBun = () => {
|
|
1645
|
+
return typeof process.versions.bun !== "undefined";
|
|
1646
|
+
};
|
|
1647
|
+
var cachedDbModule = null;
|
|
1648
|
+
var loadDatabase = async (dbPath) => {
|
|
1649
|
+
if (isBun()) {
|
|
1650
|
+
throw new Error(
|
|
1651
|
+
"SQLite driver not supported in Bun. Use createBunSqliteDriver() instead."
|
|
1652
|
+
);
|
|
1653
|
+
}
|
|
1654
|
+
try {
|
|
1655
|
+
if (!cachedDbModule) {
|
|
1656
|
+
cachedDbModule = (await import('better-sqlite3')).default;
|
|
1657
|
+
}
|
|
1658
|
+
return new cachedDbModule(dbPath);
|
|
1659
|
+
} catch (error) {
|
|
1660
|
+
throw new Error(
|
|
1661
|
+
`better-sqlite3 is required for sqlite storage. Install it to use sqlite storage. (${error})`
|
|
1662
|
+
);
|
|
1663
|
+
}
|
|
1664
|
+
};
|
|
1665
|
+
var createSqliteDriver = (options = {}) => {
|
|
1666
|
+
const dbPath = options.dbPath || "routstr.sqlite";
|
|
1667
|
+
const tableName = options.tableName || "sdk_storage";
|
|
1668
|
+
let db;
|
|
1669
|
+
let selectStmt;
|
|
1670
|
+
let upsertStmt;
|
|
1671
|
+
let deleteStmt;
|
|
1672
|
+
const initDb = async () => {
|
|
1673
|
+
if (!db) {
|
|
1674
|
+
db = await loadDatabase(dbPath);
|
|
1675
|
+
db.exec(
|
|
1676
|
+
`CREATE TABLE IF NOT EXISTS ${tableName} (key TEXT PRIMARY KEY, value TEXT NOT NULL)`
|
|
1677
|
+
);
|
|
1678
|
+
selectStmt = db.prepare(`SELECT value FROM ${tableName} WHERE key = ?`);
|
|
1679
|
+
upsertStmt = db.prepare(
|
|
1680
|
+
`INSERT INTO ${tableName} (key, value) VALUES (?, ?)
|
|
1681
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
|
1682
|
+
);
|
|
1683
|
+
deleteStmt = db.prepare(`DELETE FROM ${tableName} WHERE key = ?`);
|
|
1684
|
+
}
|
|
1685
|
+
};
|
|
1686
|
+
const ensureInit = async () => {
|
|
1687
|
+
if (!db) {
|
|
1688
|
+
await initDb();
|
|
1689
|
+
}
|
|
1690
|
+
};
|
|
1691
|
+
return {
|
|
1692
|
+
async getItem(key, defaultValue) {
|
|
1693
|
+
try {
|
|
1694
|
+
await ensureInit();
|
|
1695
|
+
const row = selectStmt.get(key);
|
|
1696
|
+
if (!row || typeof row.value !== "string") return defaultValue;
|
|
1697
|
+
try {
|
|
1698
|
+
return JSON.parse(row.value);
|
|
1699
|
+
} catch (parseError) {
|
|
1700
|
+
if (typeof defaultValue === "string") {
|
|
1701
|
+
return row.value;
|
|
1702
|
+
}
|
|
1703
|
+
throw parseError;
|
|
1704
|
+
}
|
|
1705
|
+
} catch (error) {
|
|
1706
|
+
console.error(`SQLite getItem failed for key "${key}":`, error);
|
|
1707
|
+
return defaultValue;
|
|
1708
|
+
}
|
|
1709
|
+
},
|
|
1710
|
+
async setItem(key, value) {
|
|
1711
|
+
try {
|
|
1712
|
+
await ensureInit();
|
|
1713
|
+
upsertStmt.run(key, JSON.stringify(value));
|
|
1714
|
+
} catch (error) {
|
|
1715
|
+
console.error(`SQLite setItem failed for key "${key}":`, error);
|
|
1716
|
+
}
|
|
1717
|
+
},
|
|
1718
|
+
async removeItem(key) {
|
|
1719
|
+
try {
|
|
1720
|
+
await ensureInit();
|
|
1721
|
+
deleteStmt.run(key);
|
|
1722
|
+
} catch (error) {
|
|
1723
|
+
console.error(`SQLite removeItem failed for key "${key}":`, error);
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
};
|
|
1727
|
+
};
|
|
1728
|
+
|
|
1729
|
+
// storage/usageTracking/sqlite.ts
|
|
1730
|
+
var MIGRATION_MARKER_KEY3 = "usage_tracking_migration_v1";
|
|
1731
|
+
var ADDED_COLUMNS = [
|
|
1732
|
+
{ name: "provider", type: "TEXT" },
|
|
1733
|
+
{ name: "base_msats", type: "REAL" },
|
|
1734
|
+
{ name: "input_msats", type: "REAL" },
|
|
1735
|
+
{ name: "output_msats", type: "REAL" },
|
|
1736
|
+
{ name: "total_msats", type: "REAL" },
|
|
1737
|
+
{ name: "total_usd", type: "REAL" },
|
|
1738
|
+
{ name: "cache_read_input_tokens", type: "INTEGER" },
|
|
1739
|
+
{ name: "cache_creation_input_tokens", type: "INTEGER" },
|
|
1740
|
+
{ name: "cache_read_msats", type: "REAL" },
|
|
1741
|
+
{ name: "cache_creation_msats", type: "REAL" },
|
|
1742
|
+
{ name: "remaining_balance_msats", type: "REAL" }
|
|
1743
|
+
];
|
|
1744
|
+
var normalizeBaseUrl5 = (baseUrl) => baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
1745
|
+
var isBun2 = () => {
|
|
1746
|
+
return typeof process.versions.bun !== "undefined";
|
|
1747
|
+
};
|
|
1748
|
+
var cachedDbModule2 = null;
|
|
1749
|
+
var loadDatabase2 = async (dbPath) => {
|
|
1750
|
+
if (isBun2()) {
|
|
1751
|
+
throw new Error(
|
|
1752
|
+
"SQLite driver not supported in Bun. Use createMemoryDriver() instead."
|
|
1753
|
+
);
|
|
1754
|
+
}
|
|
1755
|
+
try {
|
|
1756
|
+
if (!cachedDbModule2) {
|
|
1757
|
+
cachedDbModule2 = (await import('better-sqlite3')).default;
|
|
1758
|
+
}
|
|
1759
|
+
return new cachedDbModule2(dbPath);
|
|
1760
|
+
} catch (error) {
|
|
1761
|
+
throw new Error(
|
|
1762
|
+
`better-sqlite3 is required for sqlite usage tracking. Install it to use sqlite storage. (${error})`
|
|
1763
|
+
);
|
|
1764
|
+
}
|
|
1765
|
+
};
|
|
1766
|
+
var buildWhereClause = (options = {}) => {
|
|
1767
|
+
const clauses = [];
|
|
1768
|
+
const params = [];
|
|
1769
|
+
if (typeof options.before === "number") {
|
|
1770
|
+
clauses.push("timestamp < ?");
|
|
1771
|
+
params.push(options.before);
|
|
1772
|
+
}
|
|
1773
|
+
if (typeof options.after === "number") {
|
|
1774
|
+
clauses.push("timestamp > ?");
|
|
1775
|
+
params.push(options.after);
|
|
1776
|
+
}
|
|
1777
|
+
if (options.modelId) {
|
|
1778
|
+
clauses.push("model_id = ?");
|
|
1779
|
+
params.push(options.modelId);
|
|
1780
|
+
}
|
|
1781
|
+
if (options.baseUrl) {
|
|
1782
|
+
clauses.push("base_url = ?");
|
|
1783
|
+
params.push(normalizeBaseUrl5(options.baseUrl));
|
|
1784
|
+
}
|
|
1785
|
+
if (options.sessionId) {
|
|
1786
|
+
clauses.push("session_id = ?");
|
|
1787
|
+
params.push(options.sessionId);
|
|
1788
|
+
}
|
|
1789
|
+
if (options.client) {
|
|
1790
|
+
clauses.push("client = ?");
|
|
1791
|
+
params.push(options.client);
|
|
1792
|
+
}
|
|
1793
|
+
if (options.clients && options.clients.length > 0) {
|
|
1794
|
+
const placeholders = options.clients.map(() => "?").join(", ");
|
|
1795
|
+
clauses.push(`client IN (${placeholders})`);
|
|
1796
|
+
params.push(...options.clients);
|
|
1797
|
+
}
|
|
1798
|
+
if (options.provider) {
|
|
1799
|
+
clauses.push("provider = ?");
|
|
1800
|
+
params.push(options.provider);
|
|
1801
|
+
}
|
|
1802
|
+
return {
|
|
1803
|
+
sql: clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "",
|
|
1804
|
+
params
|
|
1805
|
+
};
|
|
1806
|
+
};
|
|
1807
|
+
var createSqliteUsageTrackingDriver = (options = {}) => {
|
|
1808
|
+
const dbPath = options.dbPath || "routstr.sqlite";
|
|
1809
|
+
const tableName = options.tableName || "usage_tracking";
|
|
1810
|
+
const legacyStorageDriver = options.legacyStorageDriver;
|
|
1811
|
+
let db;
|
|
1812
|
+
let insertStmt;
|
|
1813
|
+
let migrationComplete = false;
|
|
1814
|
+
const initDb = async () => {
|
|
1815
|
+
if (!db) {
|
|
1816
|
+
db = await loadDatabase2(dbPath);
|
|
1817
|
+
db.exec(`
|
|
1818
|
+
CREATE TABLE IF NOT EXISTS ${tableName} (
|
|
1819
|
+
id TEXT PRIMARY KEY,
|
|
1820
|
+
timestamp INTEGER NOT NULL,
|
|
1821
|
+
model_id TEXT NOT NULL,
|
|
1822
|
+
base_url TEXT NOT NULL,
|
|
1823
|
+
request_id TEXT NOT NULL,
|
|
1824
|
+
cost REAL NOT NULL,
|
|
1825
|
+
sats_cost REAL NOT NULL,
|
|
1826
|
+
prompt_tokens INTEGER NOT NULL,
|
|
1827
|
+
completion_tokens INTEGER NOT NULL,
|
|
1828
|
+
total_tokens INTEGER NOT NULL,
|
|
1829
|
+
client TEXT,
|
|
1830
|
+
session_id TEXT,
|
|
1831
|
+
tags TEXT
|
|
1832
|
+
);
|
|
1833
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_timestamp ON ${tableName}(timestamp);
|
|
1834
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_model_id ON ${tableName}(model_id);
|
|
1835
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_base_url ON ${tableName}(base_url);
|
|
1836
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_session_id ON ${tableName}(session_id);
|
|
1837
|
+
CREATE INDEX IF NOT EXISTS idx_${tableName}_client ON ${tableName}(client);
|
|
1838
|
+
`);
|
|
1839
|
+
const existingColumns = new Set(
|
|
1840
|
+
db.prepare(`PRAGMA table_info(${tableName})`).all().map((row) => String(row.name))
|
|
1841
|
+
);
|
|
1842
|
+
for (const column of ADDED_COLUMNS) {
|
|
1843
|
+
if (!existingColumns.has(column.name)) {
|
|
1844
|
+
db.exec(
|
|
1845
|
+
`ALTER TABLE ${tableName} ADD COLUMN ${column.name} ${column.type}`
|
|
1846
|
+
);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
db.exec(
|
|
1850
|
+
`CREATE INDEX IF NOT EXISTS idx_${tableName}_provider ON ${tableName}(provider)`
|
|
1851
|
+
);
|
|
1852
|
+
insertStmt = db.prepare(`
|
|
1853
|
+
INSERT OR REPLACE INTO ${tableName} (
|
|
1854
|
+
id, timestamp, model_id, base_url, request_id,
|
|
1855
|
+
cost, sats_cost, prompt_tokens, completion_tokens, total_tokens,
|
|
1856
|
+
client, session_id, tags,
|
|
1857
|
+
provider, base_msats, input_msats, output_msats, total_msats,
|
|
1858
|
+
total_usd, cache_read_input_tokens, cache_creation_input_tokens,
|
|
1859
|
+
cache_read_msats, cache_creation_msats, remaining_balance_msats
|
|
1860
|
+
) VALUES (
|
|
1861
|
+
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
1862
|
+
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
|
1863
|
+
)
|
|
1864
|
+
`);
|
|
1865
|
+
}
|
|
1866
|
+
};
|
|
1867
|
+
const ensureInit = async () => {
|
|
1868
|
+
if (!db) {
|
|
1869
|
+
await initDb();
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
const appendOne = (entry) => {
|
|
1873
|
+
insertStmt.run(
|
|
1874
|
+
entry.id,
|
|
1875
|
+
entry.timestamp,
|
|
1876
|
+
entry.modelId,
|
|
1877
|
+
normalizeBaseUrl5(entry.baseUrl),
|
|
1878
|
+
entry.requestId,
|
|
1879
|
+
entry.cost,
|
|
1880
|
+
entry.satsCost,
|
|
1881
|
+
entry.promptTokens,
|
|
1882
|
+
entry.completionTokens,
|
|
1883
|
+
entry.totalTokens,
|
|
1884
|
+
entry.client ?? null,
|
|
1885
|
+
entry.sessionId ?? null,
|
|
1886
|
+
JSON.stringify(entry.tags ?? []),
|
|
1887
|
+
entry.provider ?? null,
|
|
1888
|
+
entry.baseMsats ?? null,
|
|
1889
|
+
entry.inputMsats ?? null,
|
|
1890
|
+
entry.outputMsats ?? null,
|
|
1891
|
+
entry.totalMsats ?? null,
|
|
1892
|
+
entry.totalUsd ?? null,
|
|
1893
|
+
entry.cacheReadInputTokens ?? null,
|
|
1894
|
+
entry.cacheCreationInputTokens ?? null,
|
|
1895
|
+
entry.cacheReadMsats ?? null,
|
|
1896
|
+
entry.cacheCreationMsats ?? null,
|
|
1897
|
+
entry.remainingBalanceMsats ?? null
|
|
1898
|
+
);
|
|
1899
|
+
};
|
|
1900
|
+
const ensureMigrated = async () => {
|
|
1901
|
+
if (!legacyStorageDriver || migrationComplete) return;
|
|
1902
|
+
const migrated = await legacyStorageDriver.getItem(
|
|
1903
|
+
MIGRATION_MARKER_KEY3,
|
|
1904
|
+
false
|
|
1905
|
+
);
|
|
1906
|
+
if (migrated) {
|
|
1907
|
+
migrationComplete = true;
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1910
|
+
const legacyEntries = await legacyStorageDriver.getItem(
|
|
1911
|
+
SDK_STORAGE_KEYS.USAGE_TRACKING,
|
|
1912
|
+
[]
|
|
1913
|
+
);
|
|
1914
|
+
for (const entry of legacyEntries) {
|
|
1915
|
+
appendOne(entry);
|
|
1916
|
+
}
|
|
1917
|
+
if (legacyEntries.length > 0) {
|
|
1918
|
+
await legacyStorageDriver.removeItem(SDK_STORAGE_KEYS.USAGE_TRACKING);
|
|
1919
|
+
}
|
|
1920
|
+
await legacyStorageDriver.setItem(MIGRATION_MARKER_KEY3, true);
|
|
1921
|
+
migrationComplete = true;
|
|
1922
|
+
};
|
|
1923
|
+
const mapRow = (row) => ({
|
|
1924
|
+
id: row.id,
|
|
1925
|
+
timestamp: row.timestamp,
|
|
1926
|
+
modelId: row.model_id,
|
|
1927
|
+
baseUrl: row.base_url,
|
|
1928
|
+
requestId: row.request_id,
|
|
1929
|
+
cost: row.cost,
|
|
1930
|
+
satsCost: row.sats_cost,
|
|
1931
|
+
promptTokens: row.prompt_tokens,
|
|
1932
|
+
completionTokens: row.completion_tokens,
|
|
1933
|
+
totalTokens: row.total_tokens,
|
|
1934
|
+
client: row.client ?? void 0,
|
|
1935
|
+
sessionId: row.session_id ?? void 0,
|
|
1936
|
+
tags: typeof row.tags === "string" ? JSON.parse(row.tags) : void 0,
|
|
1937
|
+
provider: row.provider ?? void 0,
|
|
1938
|
+
baseMsats: row.base_msats ?? void 0,
|
|
1939
|
+
inputMsats: row.input_msats ?? void 0,
|
|
1940
|
+
outputMsats: row.output_msats ?? void 0,
|
|
1941
|
+
totalMsats: row.total_msats ?? void 0,
|
|
1942
|
+
totalUsd: row.total_usd ?? void 0,
|
|
1943
|
+
cacheReadInputTokens: row.cache_read_input_tokens ?? void 0,
|
|
1944
|
+
cacheCreationInputTokens: row.cache_creation_input_tokens ?? void 0,
|
|
1945
|
+
cacheReadMsats: row.cache_read_msats ?? void 0,
|
|
1946
|
+
cacheCreationMsats: row.cache_creation_msats ?? void 0,
|
|
1947
|
+
remainingBalanceMsats: row.remaining_balance_msats ?? void 0
|
|
1948
|
+
});
|
|
1949
|
+
return {
|
|
1950
|
+
async migrate() {
|
|
1951
|
+
await ensureInit();
|
|
1952
|
+
await ensureMigrated();
|
|
1953
|
+
},
|
|
1954
|
+
async append(entry) {
|
|
1955
|
+
await ensureInit();
|
|
1956
|
+
await ensureMigrated();
|
|
1957
|
+
appendOne(entry);
|
|
1958
|
+
},
|
|
1959
|
+
async appendMany(entries) {
|
|
1960
|
+
await ensureInit();
|
|
1961
|
+
await ensureMigrated();
|
|
1962
|
+
for (const entry of entries) {
|
|
1963
|
+
appendOne(entry);
|
|
1964
|
+
}
|
|
1965
|
+
},
|
|
1966
|
+
async list(options2 = {}) {
|
|
1967
|
+
await ensureInit();
|
|
1968
|
+
await ensureMigrated();
|
|
1969
|
+
const { sql, params } = buildWhereClause(options2);
|
|
1970
|
+
const limitSql = typeof options2.limit === "number" ? " LIMIT ?" : "";
|
|
1971
|
+
const stmt = db.prepare(
|
|
1972
|
+
`SELECT * FROM ${tableName} ${sql} ORDER BY timestamp DESC${limitSql}`
|
|
1973
|
+
);
|
|
1974
|
+
const rows = stmt.all(
|
|
1975
|
+
...typeof options2.limit === "number" ? [...params, options2.limit] : params
|
|
1976
|
+
);
|
|
1977
|
+
return rows.map(mapRow);
|
|
1978
|
+
},
|
|
1979
|
+
async count(options2 = {}) {
|
|
1980
|
+
await ensureInit();
|
|
1981
|
+
await ensureMigrated();
|
|
1982
|
+
const { sql, params } = buildWhereClause(options2);
|
|
1983
|
+
const stmt = db.prepare(`SELECT COUNT(*) as count FROM ${tableName} ${sql}`);
|
|
1984
|
+
const row = stmt.get(...params);
|
|
1985
|
+
return Number(row?.count ?? 0);
|
|
1986
|
+
},
|
|
1987
|
+
async aggregate(options2 = {}) {
|
|
1988
|
+
await ensureInit();
|
|
1989
|
+
await ensureMigrated();
|
|
1990
|
+
const where = buildWhereClause(options2);
|
|
1991
|
+
const { sql, params } = buildAggregateSql(tableName, where, options2);
|
|
1992
|
+
const rows = db.prepare(sql).all(...params);
|
|
1993
|
+
return rows.map(mapAggregateRow);
|
|
1994
|
+
},
|
|
1995
|
+
async deleteOlderThan(timestamp) {
|
|
1996
|
+
await ensureInit();
|
|
1997
|
+
await ensureMigrated();
|
|
1998
|
+
const stmt = db.prepare(`DELETE FROM ${tableName} WHERE timestamp < ?`);
|
|
1999
|
+
const result = stmt.run(timestamp);
|
|
2000
|
+
return result.changes;
|
|
2001
|
+
},
|
|
2002
|
+
async clear() {
|
|
2003
|
+
await ensureInit();
|
|
2004
|
+
await ensureMigrated();
|
|
2005
|
+
db.prepare(`DELETE FROM ${tableName}`).run();
|
|
2006
|
+
}
|
|
2007
|
+
};
|
|
2008
|
+
};
|
|
2009
|
+
|
|
2010
|
+
export { SDK_STORAGE_KEYS, createDiscoveryAdapterFromStore, createIndexedDBDriver, createIndexedDBUsageTrackingDriver, createMemoryDriver, createMemoryUsageTrackingDriver, createProviderRegistryFromDiscoveryAdapter, createProviderRegistryFromStore, createSdkStore, createShardedDiscoveryAdapter, createSqliteDriver, createSqliteUsageTrackingDriver, createStorageAdapterFromStore, getDefaultDiscoveryAdapter, getDefaultProviderRegistry, getDefaultSdkDriver, getDefaultSdkStore, getDefaultStorageAdapter, getDefaultUsageTrackingDriver, localStorageDriver, setDefaultUsageTrackingDriver };
|
|
2011
|
+
//# sourceMappingURL=node.mjs.map
|
|
2012
|
+
//# sourceMappingURL=node.mjs.map
|