@routstr/sdk 0.3.10 → 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.
Files changed (63) hide show
  1. package/dist/browser.d.mts +2 -2
  2. package/dist/browser.d.ts +2 -2
  3. package/dist/browser.js +201 -66
  4. package/dist/browser.js.map +1 -1
  5. package/dist/browser.mjs +198 -67
  6. package/dist/browser.mjs.map +1 -1
  7. package/dist/bun.d.mts +5 -5
  8. package/dist/bun.d.ts +5 -5
  9. package/dist/bun.js +271 -66
  10. package/dist/bun.js.map +1 -1
  11. package/dist/bun.mjs +268 -67
  12. package/dist/bun.mjs.map +1 -1
  13. package/dist/{bunSqlite-BMTseLIz.d.ts → bunSqlite-BmXWNc25.d.ts} +1 -1
  14. package/dist/{bunSqlite-D6AreVE2.d.mts → bunSqlite-Bro9efsl.d.mts} +1 -1
  15. package/dist/client/index.d.mts +31 -10
  16. package/dist/client/index.d.ts +31 -10
  17. package/dist/client/index.js +185 -36
  18. package/dist/client/index.js.map +1 -1
  19. package/dist/client/index.mjs +182 -37
  20. package/dist/client/index.mjs.map +1 -1
  21. package/dist/discovery/index.d.mts +3 -3
  22. package/dist/discovery/index.d.ts +3 -3
  23. package/dist/discovery/index.js +12 -20
  24. package/dist/discovery/index.js.map +1 -1
  25. package/dist/discovery/index.mjs +12 -20
  26. package/dist/discovery/index.mjs.map +1 -1
  27. package/dist/index.d.mts +8 -6
  28. package/dist/index.d.ts +8 -6
  29. package/dist/index.js +201 -66
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +198 -67
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/node.d.mts +2 -2
  34. package/dist/node.d.ts +2 -2
  35. package/dist/node.js +272 -66
  36. package/dist/node.js.map +1 -1
  37. package/dist/node.mjs +269 -67
  38. package/dist/node.mjs.map +1 -1
  39. package/dist/storage/bun.d.mts +4 -4
  40. package/dist/storage/bun.d.ts +4 -4
  41. package/dist/storage/bun.js +169 -0
  42. package/dist/storage/bun.js.map +1 -1
  43. package/dist/storage/bun.mjs +169 -0
  44. package/dist/storage/bun.mjs.map +1 -1
  45. package/dist/storage/index.d.mts +2 -2
  46. package/dist/storage/index.d.ts +2 -2
  47. package/dist/storage/index.js +99 -0
  48. package/dist/storage/index.js.map +1 -1
  49. package/dist/storage/index.mjs +99 -0
  50. package/dist/storage/index.mjs.map +1 -1
  51. package/dist/storage/node.d.mts +2 -2
  52. package/dist/storage/node.d.ts +2 -2
  53. package/dist/storage/node.js +170 -0
  54. package/dist/storage/node.js.map +1 -1
  55. package/dist/storage/node.mjs +170 -0
  56. package/dist/storage/node.mjs.map +1 -1
  57. package/dist/{store-C8MZlfuz.d.ts → store-CAQLSbEj.d.ts} +38 -1
  58. package/dist/{store-BiuM2V9N.d.mts → store-CuXwe5Rg.d.mts} +38 -1
  59. package/dist/wallet/index.js +38 -24
  60. package/dist/wallet/index.js.map +1 -1
  61. package/dist/wallet/index.mjs +38 -24
  62. package/dist/wallet/index.mjs.map +1 -1
  63. package/package.json +1 -1
@@ -4,9 +4,9 @@ export { D as DiscoveryAdapter } from './interfaces-Cv1k2EUK.mjs';
4
4
  export { MintDiscovery, ModelManager, ModelManagerConfig } from './discovery/index.mjs';
5
5
  export { A as ApiKeyEntry, C as ChildKeyEntry, P as ProviderRegistry, R as RoutstrClientOptions, S as StorageAdapter, a as StreamingCallbacks, W as WalletAdapter, X as XCashuTokenEntry } from './interfaces-Csn8Uq04.mjs';
6
6
  export { BalanceManager, BalanceState, CashuSpender, CreateProviderTokenOptions, ProviderTokenResult, RefundApiKeyOptions, SpendOptions, TopUpOptions } from './wallet/index.mjs';
7
- export { AlertLevel, DebugLevel, FetchAIResponseDeps, ModelProviderPrice, ProviderManager, RouteRequestParams, RoutstrClient, RoutstrClientConfig, RoutstrClientMode, StreamCallbacks, StreamProcessor, createSSEParserTransform, fetchAIResponse, inspectSSEWebStream } from './client/index.mjs';
7
+ export { AlertLevel, DebugLevel, FetchAIResponseDeps, ModelProviderPrice, ProviderManager, RequestResponseLogRequestInput, RequestResponseLogSink, RouteRequestParams, RoutstrClient, RoutstrClientConfig, RoutstrClientMode, StreamCallbacks, StreamProcessor, UsageTrackingData, createSSEParserTransform, extractResponseId, extractUsageFromResponseBody, extractUsageFromSSEJson, fetchAIResponse, inspectSSEWebStream, toUsageStats } from './client/index.mjs';
8
8
  export { SDK_STORAGE_KEYS, ShardedDiscoveryAdapterOptions, createIndexedDBDriver, createIndexedDBUsageTrackingDriver, createMemoryDriver, createMemoryUsageTrackingDriver, createProviderRegistryFromDiscoveryAdapter, createShardedDiscoveryAdapter, getDefaultDiscoveryAdapter, getDefaultProviderRegistry, getDefaultSdkDriver, getDefaultSdkStore, getDefaultStorageAdapter, getDefaultUsageTrackingDriver, localStorageDriver, setDefaultUsageTrackingDriver } from './storage/index.mjs';
9
- export { L as ListUsageTrackingOptions, S as SdkStore, a as StorageDriver, U as UsageTrackingDriver, b as UsageTrackingEntry, c as createDiscoveryAdapterFromStore, d as createProviderRegistryFromStore, e as createSdkStore, f as createStorageAdapterFromStore } from './store-BiuM2V9N.mjs';
9
+ export { A as AggregateUsageOptions, L as ListUsageTrackingOptions, S as SdkStore, a as StorageDriver, U as UsageAggregateRow, b as UsageGroupBy, c as UsageTrackingDriver, d as UsageTrackingEntry, e as createDiscoveryAdapterFromStore, f as createProviderRegistryFromStore, g as createSdkStore, h as createStorageAdapterFromStore } from './store-CuXwe5Rg.mjs';
10
10
  import 'applesauce-core';
11
11
  import 'stream';
12
12
  import 'zustand/vanilla';
package/dist/browser.d.ts CHANGED
@@ -4,9 +4,9 @@ export { D as DiscoveryAdapter } from './interfaces-iL7CWeG5.js';
4
4
  export { MintDiscovery, ModelManager, ModelManagerConfig } from './discovery/index.js';
5
5
  export { A as ApiKeyEntry, C as ChildKeyEntry, P as ProviderRegistry, R as RoutstrClientOptions, S as StorageAdapter, a as StreamingCallbacks, W as WalletAdapter, X as XCashuTokenEntry } from './interfaces-C-DYd9Jy.js';
6
6
  export { BalanceManager, BalanceState, CashuSpender, CreateProviderTokenOptions, ProviderTokenResult, RefundApiKeyOptions, SpendOptions, TopUpOptions } from './wallet/index.js';
7
- export { AlertLevel, DebugLevel, FetchAIResponseDeps, ModelProviderPrice, ProviderManager, RouteRequestParams, RoutstrClient, RoutstrClientConfig, RoutstrClientMode, StreamCallbacks, StreamProcessor, createSSEParserTransform, fetchAIResponse, inspectSSEWebStream } from './client/index.js';
7
+ export { AlertLevel, DebugLevel, FetchAIResponseDeps, ModelProviderPrice, ProviderManager, RequestResponseLogRequestInput, RequestResponseLogSink, RouteRequestParams, RoutstrClient, RoutstrClientConfig, RoutstrClientMode, StreamCallbacks, StreamProcessor, UsageTrackingData, createSSEParserTransform, extractResponseId, extractUsageFromResponseBody, extractUsageFromSSEJson, fetchAIResponse, inspectSSEWebStream, toUsageStats } from './client/index.js';
8
8
  export { SDK_STORAGE_KEYS, ShardedDiscoveryAdapterOptions, createIndexedDBDriver, createIndexedDBUsageTrackingDriver, createMemoryDriver, createMemoryUsageTrackingDriver, createProviderRegistryFromDiscoveryAdapter, createShardedDiscoveryAdapter, getDefaultDiscoveryAdapter, getDefaultProviderRegistry, getDefaultSdkDriver, getDefaultSdkStore, getDefaultStorageAdapter, getDefaultUsageTrackingDriver, localStorageDriver, setDefaultUsageTrackingDriver } from './storage/index.js';
9
- export { L as ListUsageTrackingOptions, S as SdkStore, a as StorageDriver, U as UsageTrackingDriver, b as UsageTrackingEntry, c as createDiscoveryAdapterFromStore, d as createProviderRegistryFromStore, e as createSdkStore, f as createStorageAdapterFromStore } from './store-C8MZlfuz.js';
9
+ export { A as AggregateUsageOptions, L as ListUsageTrackingOptions, S as SdkStore, a as StorageDriver, U as UsageAggregateRow, b as UsageGroupBy, c as UsageTrackingDriver, d as UsageTrackingEntry, e as createDiscoveryAdapterFromStore, f as createProviderRegistryFromStore, g as createSdkStore, h as createStorageAdapterFromStore } from './store-CAQLSbEj.js';
10
10
  import 'applesauce-core';
11
11
  import 'stream';
12
12
  import 'zustand/vanilla';
package/dist/browser.js CHANGED
@@ -139,6 +139,11 @@ var MintDiscoveryError = class extends Error {
139
139
  }
140
140
  baseUrl;
141
141
  };
142
+ var DEFAULT_NOSTR_RELAYS = [
143
+ "wss://relay.damus.io",
144
+ "wss://nos.lol",
145
+ "wss://relay.routstr.com"
146
+ ];
142
147
  var ModelManager = class _ModelManager {
143
148
  constructor(adapter, config = {}) {
144
149
  this.adapter = adapter;
@@ -332,11 +337,11 @@ var ModelManager = class _ModelManager {
332
337
  return this.bootstrapFromHttp(torMode, forceRefresh);
333
338
  }
334
339
  /**
335
- * Resolve Nostr relay URLs for a given use case.
336
- * Returns user-configured relays if set, otherwise the provided defaults.
340
+ * Resolve Nostr relay URLs.
341
+ * Returns user-configured relays if set, otherwise the shared defaults.
337
342
  */
338
- getNostrRelays(defaults) {
339
- return this.nostrRelays && this.nostrRelays.length > 0 ? this.nostrRelays : defaults;
343
+ getNostrRelays() {
344
+ return this.nostrRelays && this.nostrRelays.length > 0 ? this.nostrRelays : DEFAULT_NOSTR_RELAYS;
340
345
  }
341
346
  /**
342
347
  * Bootstrap providers from Nostr network (kind 38421)
@@ -345,11 +350,7 @@ var ModelManager = class _ModelManager {
345
350
  * @returns Array of provider base URLs
346
351
  */
347
352
  async bootstrapFromNostr(kind, torMode, forceRefresh = false) {
348
- const relays = this.getNostrRelays([
349
- "wss://relay.primal.net",
350
- "wss://nos.lol",
351
- "wss://relay.damus.io"
352
- ]);
353
+ const relays = this.getNostrRelays();
353
354
  const cached = await this.getCachedNostrEvents(
354
355
  { kinds: [kind] },
355
356
  this.cacheTTL,
@@ -532,12 +533,7 @@ var ModelManager = class _ModelManager {
532
533
  );
533
534
  let sessionEvents = cached;
534
535
  if (cached.length === 0) {
535
- const lgtmRelays = this.getNostrRelays([
536
- "wss://relay.primal.net",
537
- "wss://nos.lol",
538
- "wss://relay.damus.io",
539
- "wss://relay.routstr.com"
540
- ]);
536
+ const lgtmRelays = this.getNostrRelays();
541
537
  const pool = new applesauceRelay.RelayPool();
542
538
  const timeoutMs = 5e3;
543
539
  await new Promise((resolve) => {
@@ -783,11 +779,7 @@ var ModelManager = class _ModelManager {
783
779
  return cachedModels;
784
780
  }
785
781
  }
786
- const relays = this.getNostrRelays([
787
- "wss://relay.damus.io",
788
- "wss://nos.lol",
789
- "wss://relay.routstr.com"
790
- ]);
782
+ const relays = this.getNostrRelays();
791
783
  const cached = await this.getCachedNostrEvents(
792
784
  { kinds: [38423], "#d": ["routstr-21-models"], authors: [this.routstrPubkey] },
793
785
  this.cacheTTL,
@@ -1999,8 +1991,8 @@ var BalanceManager = class _BalanceManager {
1999
1991
  const refundableProviderBalance = Object.entries(
2000
1992
  balanceState.providerBalances
2001
1993
  ).filter(([providerBaseUrl]) => providerBaseUrl !== baseUrl).reduce((sum, [, value]) => sum + value, 0);
2002
- if (totalMintBalance + targetProviderBalance < adjustedAmount && totalMintBalance + targetProviderBalance + refundableProviderBalance >= adjustedAmount && retryCount < 2) {
2003
- await this._refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount);
1994
+ if (totalMintBalance + targetProviderBalance < adjustedAmount && totalMintBalance + targetProviderBalance + refundableProviderBalance >= adjustedAmount && retryCount < 3) {
1995
+ await this._refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount, adjustedAmount);
2004
1996
  return this.createProviderToken({
2005
1997
  ...options,
2006
1998
  retryCount: retryCount + 1
@@ -2139,33 +2131,47 @@ var BalanceManager = class _BalanceManager {
2139
2131
  }
2140
2132
  return candidates;
2141
2133
  }
2142
- async _refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount) {
2134
+ async _refundOtherProvidersForTopUp(baseUrl, mintUrl, retryCount, requiredAmount) {
2143
2135
  const apiKeyDistribution = this.storageAdapter.getApiKeyDistribution();
2144
2136
  const forceRefund = retryCount >= 2;
2145
- const apiKeysToRefund = apiKeyDistribution.filter(
2146
- (apiKey) => apiKey.baseUrl !== baseUrl && apiKey.amount > 0
2147
- );
2148
- const apiKeyRefundResults = await Promise.allSettled(
2149
- apiKeysToRefund.map(async (apiKeyEntry) => {
2150
- const fullApiKeyEntry = this.storageAdapter.getApiKey(
2151
- apiKeyEntry.baseUrl
2152
- );
2153
- if (!fullApiKeyEntry) {
2154
- return { baseUrl: apiKeyEntry.baseUrl, success: false };
2155
- }
2156
- const result = await this.refundApiKey({
2137
+ const candidates = apiKeyDistribution.filter((apiKey) => apiKey.baseUrl !== baseUrl && apiKey.amount > 0).map((apiKey) => {
2138
+ const full = this.storageAdapter.getApiKey(apiKey.baseUrl);
2139
+ return {
2140
+ baseUrl: apiKey.baseUrl,
2141
+ amount: apiKey.amount,
2142
+ lastUsed: full?.lastUsed ?? 0,
2143
+ key: full?.key
2144
+ };
2145
+ }).filter((c) => c.key != null).sort((a, b) => a.lastUsed - b.lastUsed);
2146
+ if (candidates.length === 0) return;
2147
+ if (forceRefund) {
2148
+ for (const candidate of candidates) {
2149
+ await this.refundApiKey({
2157
2150
  mintUrl,
2158
- baseUrl: apiKeyEntry.baseUrl,
2159
- apiKey: fullApiKeyEntry.key,
2160
- forceRefund
2151
+ baseUrl: candidate.baseUrl,
2152
+ apiKey: candidate.key,
2153
+ forceRefund: true
2161
2154
  });
2162
- return { baseUrl: apiKeyEntry.baseUrl, success: result.success };
2163
- })
2164
- );
2165
- for (const result of apiKeyRefundResults) {
2166
- if (result.status === "fulfilled" && result.value.success) {
2167
- this.storageAdapter.updateApiKeyBalance(result.value.baseUrl, 0);
2155
+ const newState = await this.getBalanceState();
2156
+ const newAvailable = (newState.mintBalances[mintUrl] || 0) + (newState.providerBalances[baseUrl] || 0);
2157
+ if (newAvailable >= requiredAmount) {
2158
+ this.logger.log(
2159
+ `_refundOtherProvidersForTopUp: freed enough balance (${newAvailable} >= ${requiredAmount}), stopping early`
2160
+ );
2161
+ return;
2162
+ }
2168
2163
  }
2164
+ } else {
2165
+ await Promise.allSettled(
2166
+ candidates.map(
2167
+ (candidate) => this.refundApiKey({
2168
+ mintUrl,
2169
+ baseUrl: candidate.baseUrl,
2170
+ apiKey: candidate.key,
2171
+ forceRefund: false
2172
+ })
2173
+ )
2174
+ );
2169
2175
  }
2170
2176
  }
2171
2177
  /**
@@ -3162,6 +3168,91 @@ var SDK_STORAGE_KEYS = {
3162
3168
  PROVIDERS_ON_COOLDOWN: "providers_on_cooldown"
3163
3169
  };
3164
3170
 
3171
+ // storage/usageTracking/aggregate.ts
3172
+ var pad2 = (n) => String(n).padStart(2, "0");
3173
+ var jsGroupKey = (entry, groupBy, tzOffsetMinutes) => {
3174
+ switch (groupBy) {
3175
+ case "modelId":
3176
+ return entry.modelId ?? null;
3177
+ case "baseUrl":
3178
+ return entry.baseUrl ?? null;
3179
+ case "client":
3180
+ return entry.client ?? null;
3181
+ case "sessionId":
3182
+ return entry.sessionId ?? null;
3183
+ case "provider":
3184
+ return entry.provider ?? null;
3185
+ case "day": {
3186
+ const d = new Date(entry.timestamp - tzOffsetMinutes * 6e4);
3187
+ return `${d.getUTCFullYear()}-${pad2(d.getUTCMonth() + 1)}-${pad2(d.getUTCDate())}`;
3188
+ }
3189
+ case "hour": {
3190
+ const d = new Date(entry.timestamp - tzOffsetMinutes * 6e4);
3191
+ return pad2(d.getUTCHours());
3192
+ }
3193
+ }
3194
+ };
3195
+ var reduceAggregate = (entries, options = {}) => {
3196
+ const emptyRow = (group) => ({
3197
+ group,
3198
+ requests: 0,
3199
+ promptTokens: 0,
3200
+ completionTokens: 0,
3201
+ totalTokens: 0,
3202
+ cost: 0,
3203
+ satsCost: 0,
3204
+ baseMsats: 0,
3205
+ inputMsats: 0,
3206
+ outputMsats: 0,
3207
+ totalMsats: 0,
3208
+ totalUsd: 0,
3209
+ cacheReadInputTokens: 0,
3210
+ cacheCreationInputTokens: 0,
3211
+ cacheReadMsats: 0,
3212
+ cacheCreationMsats: 0
3213
+ });
3214
+ const accumulate = (row, entry) => {
3215
+ row.requests += 1;
3216
+ row.promptTokens += entry.promptTokens;
3217
+ row.completionTokens += entry.completionTokens;
3218
+ row.totalTokens += entry.totalTokens;
3219
+ row.cost += entry.cost;
3220
+ row.satsCost += entry.satsCost;
3221
+ row.baseMsats += entry.baseMsats ?? 0;
3222
+ row.inputMsats += entry.inputMsats ?? 0;
3223
+ row.outputMsats += entry.outputMsats ?? 0;
3224
+ row.totalMsats += entry.totalMsats ?? 0;
3225
+ row.totalUsd += entry.totalUsd ?? 0;
3226
+ row.cacheReadInputTokens += entry.cacheReadInputTokens ?? 0;
3227
+ row.cacheCreationInputTokens += entry.cacheCreationInputTokens ?? 0;
3228
+ row.cacheReadMsats += entry.cacheReadMsats ?? 0;
3229
+ row.cacheCreationMsats += entry.cacheCreationMsats ?? 0;
3230
+ };
3231
+ if (!options.groupBy) {
3232
+ const total = emptyRow(null);
3233
+ for (const entry of entries) accumulate(total, entry);
3234
+ return [total];
3235
+ }
3236
+ const tz = options.tzOffsetMinutes ?? 0;
3237
+ const groups = /* @__PURE__ */ new Map();
3238
+ for (const entry of entries) {
3239
+ const key = jsGroupKey(entry, options.groupBy, tz);
3240
+ let row = groups.get(key);
3241
+ if (!row) {
3242
+ row = emptyRow(key);
3243
+ groups.set(key, row);
3244
+ }
3245
+ accumulate(row, entry);
3246
+ }
3247
+ const rows = [...groups.values()];
3248
+ if (options.groupBy === "day" || options.groupBy === "hour") {
3249
+ rows.sort((a, b) => (a.group ?? "").localeCompare(b.group ?? ""));
3250
+ } else {
3251
+ rows.sort((a, b) => b.satsCost - a.satsCost);
3252
+ }
3253
+ return rows;
3254
+ };
3255
+
3165
3256
  // storage/usageTracking/indexedDB.ts
3166
3257
  var DEFAULT_DB_NAME = "routstr-sdk";
3167
3258
  var DEFAULT_STORE_NAME = "usage_tracking";
@@ -3224,6 +3315,9 @@ var matchesFilters = (entry, options = {}) => {
3224
3315
  if (options.client && entry.client !== options.client) {
3225
3316
  return false;
3226
3317
  }
3318
+ if (options.clients && options.clients.length > 0 && (entry.client == null || !options.clients.includes(entry.client))) {
3319
+ return false;
3320
+ }
3227
3321
  if (options.provider && entry.provider !== options.provider) {
3228
3322
  return false;
3229
3323
  }
@@ -3322,6 +3416,10 @@ var createIndexedDBUsageTrackingDriver = (options = {}) => {
3322
3416
  const results = await this.list(options2);
3323
3417
  return results.length;
3324
3418
  },
3419
+ async aggregate(options2 = {}) {
3420
+ const entries = await this.list(options2);
3421
+ return reduceAggregate(entries, options2);
3422
+ },
3325
3423
  async deleteOlderThan(timestamp) {
3326
3424
  await ensureMigrated();
3327
3425
  const db = await getDb();
@@ -3379,6 +3477,9 @@ var matchesFilters2 = (entry, options = {}) => {
3379
3477
  if (options.client && entry.client !== options.client) {
3380
3478
  return false;
3381
3479
  }
3480
+ if (options.clients && options.clients.length > 0 && (entry.client == null || !options.clients.includes(entry.client))) {
3481
+ return false;
3482
+ }
3382
3483
  if (options.provider && entry.provider !== options.provider) {
3383
3484
  return false;
3384
3485
  }
@@ -3411,6 +3512,10 @@ var createMemoryUsageTrackingDriver = (seed = []) => {
3411
3512
  async count(options = {}) {
3412
3513
  return (await this.list(options)).length;
3413
3514
  },
3515
+ async aggregate(options = {}) {
3516
+ const entries = [...store.values()].filter((entry) => matchesFilters2(entry, options));
3517
+ return reduceAggregate(entries, options);
3518
+ },
3414
3519
  async deleteOlderThan(timestamp) {
3415
3520
  let deleted = 0;
3416
3521
  for (const [id, entry] of store.entries()) {
@@ -4562,13 +4667,14 @@ function hasUsageChanged(previous, next) {
4562
4667
  function isInspectionComplete(responseIdCaptured, usage) {
4563
4668
  return responseIdCaptured && !!usage && usage.totalTokens > 0 && typeof usage.totalMsats === "number" && !!usage.provider;
4564
4669
  }
4565
- async function inspectSSEWebStream(stream, onUsage, onResponseId) {
4670
+ async function inspectSSEWebStream(stream, onUsage, onResponseId, options) {
4566
4671
  const reader = stream.getReader();
4567
4672
  const decoder = new TextDecoder("utf-8");
4568
4673
  let buffer = "";
4569
4674
  let capturedUsage = null;
4570
4675
  let capturedResponseId;
4571
4676
  let responseIdCaptured = false;
4677
+ let rawChunkSequence = 0;
4572
4678
  const inspectDataPayload = (jsonText) => {
4573
4679
  const trimmed = jsonText.trim();
4574
4680
  if (!trimmed || trimmed === "[DONE]") {
@@ -4639,7 +4745,9 @@ async function inspectSSEWebStream(stream, onUsage, onResponseId) {
4639
4745
  const { value, done } = await reader.read();
4640
4746
  if (done) break;
4641
4747
  if (value && value.byteLength > 0) {
4642
- buffer += decoder.decode(value, { stream: true });
4748
+ const text = decoder.decode(value, { stream: true });
4749
+ void options?.onRawChunk?.(value, rawChunkSequence++, text);
4750
+ buffer += text;
4643
4751
  drainBufferedEvents();
4644
4752
  }
4645
4753
  }
@@ -4784,6 +4892,7 @@ var RoutstrClient = class {
4784
4892
  this.mode = mode;
4785
4893
  this.usageTrackingDriver = options.usageTrackingDriver;
4786
4894
  this.sdkStore = options.sdkStore;
4895
+ this.requestResponseLogSink = options.requestResponseLogSink;
4787
4896
  this.providerManager = options.providerManager ?? new ProviderManager(providerRegistry, this.sdkStore, this.logger);
4788
4897
  }
4789
4898
  walletAdapter;
@@ -4798,6 +4907,7 @@ var RoutstrClient = class {
4798
4907
  usageTrackingDriver;
4799
4908
  sdkStore;
4800
4909
  logger;
4910
+ requestResponseLogSink;
4801
4911
  /**
4802
4912
  * Get the current client mode
4803
4913
  */
@@ -4988,6 +5098,7 @@ var RoutstrClient = class {
4988
5098
  let usagePromise = Promise.resolve({});
4989
5099
  if (contentType.includes("text/event-stream") && response.body) {
4990
5100
  const [clientStream, inspectStream] = response.body.tee();
5101
+ const requestResponseLogId = response.requestResponseLogId;
4991
5102
  processedResponse = new Response(clientStream, {
4992
5103
  status: response.status,
4993
5104
  statusText: response.statusText,
@@ -4995,6 +5106,7 @@ var RoutstrClient = class {
4995
5106
  });
4996
5107
  processedResponse.baseUrl = response.baseUrl;
4997
5108
  processedResponse.token = response.token;
5109
+ processedResponse.requestResponseLogId = requestResponseLogId;
4998
5110
  usagePromise = inspectSSEWebStream(
4999
5111
  inspectStream,
5000
5112
  (usage) => {
@@ -5004,8 +5116,23 @@ var RoutstrClient = class {
5004
5116
  (responseId) => {
5005
5117
  capturedResponseId = responseId;
5006
5118
  processedResponse.requestId = responseId;
5119
+ },
5120
+ {
5121
+ onRawChunk: (_chunk, sequence, text) => {
5122
+ void this.requestResponseLogSink?.logResponseChunk?.(
5123
+ requestResponseLogId,
5124
+ sequence,
5125
+ text
5126
+ );
5127
+ }
5007
5128
  }
5008
- );
5129
+ ).then(async (result) => {
5130
+ await this.requestResponseLogSink?.logResponseEnd?.(requestResponseLogId);
5131
+ return result;
5132
+ }).catch(async (error) => {
5133
+ await this.requestResponseLogSink?.logResponseError?.(requestResponseLogId, error);
5134
+ throw error;
5135
+ });
5009
5136
  processedResponse.usagePromise = usagePromise;
5010
5137
  }
5011
5138
  return {
@@ -5039,16 +5166,30 @@ var RoutstrClient = class {
5039
5166
  const { path, method, body, baseUrl, token, headers } = params;
5040
5167
  try {
5041
5168
  const url = `${baseUrl.replace(/\/$/, "")}${path}`;
5169
+ const requestBodyText = body === void 0 || method === "GET" ? void 0 : JSON.stringify(body);
5170
+ const requestLogId = await this.requestResponseLogSink?.logRequest?.({
5171
+ method,
5172
+ url,
5173
+ path,
5174
+ baseUrl,
5175
+ headers,
5176
+ body,
5177
+ rawBody: requestBodyText
5178
+ });
5042
5179
  if (this.mode === "xcashu") this._log("DEBUG", "HEADERS,", headers);
5043
5180
  const response = await fetch(url, {
5044
5181
  method,
5045
5182
  headers,
5046
- body: body === void 0 || method === "GET" ? void 0 : JSON.stringify(body)
5183
+ body: requestBodyText
5047
5184
  });
5048
5185
  if (this.mode === "xcashu") this._log("DEBUG", "response,", response);
5049
5186
  response.baseUrl = baseUrl;
5050
5187
  response.token = token;
5188
+ response.requestResponseLogId = requestLogId;
5189
+ await this.requestResponseLogSink?.logResponseStart?.(requestLogId, response);
5190
+ const contentType = response.headers.get("content-type") || "";
5051
5191
  if (!response.ok) {
5192
+ void this.requestResponseLogSink?.logResponseBody?.(requestLogId, response.clone());
5052
5193
  const requestId = response.headers.get("x-routstr-request-id") || void 0;
5053
5194
  let bodyText;
5054
5195
  try {
@@ -5066,6 +5207,9 @@ var RoutstrClient = class {
5066
5207
  params.retryCount ?? 0
5067
5208
  );
5068
5209
  }
5210
+ if (!contentType.includes("text/event-stream")) {
5211
+ void this.requestResponseLogSink?.logResponseBody?.(requestLogId, response.clone());
5212
+ }
5069
5213
  return response;
5070
5214
  } catch (error) {
5071
5215
  if (isNetworkErrorMessage(error?.message || "")) {
@@ -5955,15 +6099,8 @@ async function fetchAIResponse(options, callbacks, deps) {
5955
6099
  const apiMessages = await convertMessages(messageHistory);
5956
6100
  callbacks.onPaymentProcessing?.(true);
5957
6101
  callbacks.onTokenCreated?.(deps.getPendingCashuTokenAmount?.() ?? 0);
5958
- const providerInfo = await deps.providerRegistry.getProviderInfo(baseUrl);
5959
- const providerVersion = providerInfo?.version ?? "";
5960
- let modelIdForRequest = selectedModel.id;
5961
- if (/^0\.1\./.test(providerVersion)) {
5962
- const newModel = await deps.client.getProviderManager().getModelForProvider(baseUrl, selectedModel.id);
5963
- modelIdForRequest = newModel?.id ?? selectedModel.id;
5964
- }
5965
6102
  const body = {
5966
- model: modelIdForRequest,
6103
+ model: selectedModel.id,
5967
6104
  messages: apiMessages,
5968
6105
  stream: true
5969
6106
  };
@@ -6098,7 +6235,8 @@ async function resolveRouteRequestContext(options) {
6098
6235
  usageTrackingDriver,
6099
6236
  sdkStore,
6100
6237
  providerManager: providedProviderManager,
6101
- logger
6238
+ logger,
6239
+ requestResponseLogSink
6102
6240
  } = options;
6103
6241
  let modelManager;
6104
6242
  let providers;
@@ -6147,15 +6285,8 @@ async function resolveRouteRequestContext(options) {
6147
6285
  baseUrl = cheapest.baseUrl;
6148
6286
  selectedModel = cheapest.model;
6149
6287
  }
6150
- const balances = await walletAdapter.getBalances();
6151
- const totalBalance = Object.values(balances).reduce((sum, v) => sum + v, 0);
6152
- if (totalBalance <= 0) {
6153
- throw new Error(
6154
- "Wallet balance is empty. Add a mint and fund it before making requests."
6155
- );
6156
- }
6157
6288
  const providerMints = providerRegistry.getProviderMints(baseUrl);
6158
- const mintUrl = walletAdapter.getActiveMintUrl() || providerMints[0] || Object.keys(balances)[0];
6289
+ const mintUrl = walletAdapter.getActiveMintUrl() || providerMints[0] || Object.keys(await walletAdapter.getBalances())[0];
6159
6290
  if (!mintUrl) {
6160
6291
  throw new Error("No mint configured in wallet");
6161
6292
  }
@@ -6165,7 +6296,7 @@ async function resolveRouteRequestContext(options) {
6165
6296
  providerRegistry,
6166
6297
  "min",
6167
6298
  mode,
6168
- { usageTrackingDriver, sdkStore, providerManager, logger }
6299
+ { usageTrackingDriver, sdkStore, providerManager, logger, requestResponseLogSink }
6169
6300
  );
6170
6301
  const maxTokens = extractMaxTokens(requestBody);
6171
6302
  const stream = extractStream(requestBody);
@@ -6257,6 +6388,9 @@ exports.createSSEParserTransform = createSSEParserTransform;
6257
6388
  exports.createSdkStore = createSdkStore;
6258
6389
  exports.createShardedDiscoveryAdapter = createShardedDiscoveryAdapter;
6259
6390
  exports.createStorageAdapterFromStore = createStorageAdapterFromStore;
6391
+ exports.extractResponseId = extractResponseId;
6392
+ exports.extractUsageFromResponseBody = extractUsageFromResponseBody;
6393
+ exports.extractUsageFromSSEJson = extractUsageFromSSEJson;
6260
6394
  exports.fetchAIResponse = fetchAIResponse;
6261
6395
  exports.filterBaseUrlsForTor = filterBaseUrlsForTor;
6262
6396
  exports.getDefaultDiscoveryAdapter = getDefaultDiscoveryAdapter;
@@ -6274,5 +6408,6 @@ exports.noopLogger = noopLogger;
6274
6408
  exports.normalizeProviderUrl = normalizeProviderUrl;
6275
6409
  exports.routeRequests = routeRequests;
6276
6410
  exports.setDefaultUsageTrackingDriver = setDefaultUsageTrackingDriver;
6411
+ exports.toUsageStats = toUsageStats;
6277
6412
  //# sourceMappingURL=browser.js.map
6278
6413
  //# sourceMappingURL=browser.js.map