routstrd 0.1.8 → 0.1.9

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.
@@ -28662,7 +28662,7 @@ var require_file_uri_to_path = __commonJS((exports, module) => {
28662
28662
 
28663
28663
  // ../routstr-chat/node_modules/bindings/bindings.js
28664
28664
  var require_bindings = __commonJS((exports, module) => {
28665
- var __filename = "/Users/r/projects/routstr_main/routstr-chat/node_modules/bindings/bindings.js";
28665
+ var __filename = "/Users/r/projects/routstr_main/screaming-bug/routstr-chat/node_modules/bindings/bindings.js";
28666
28666
  var fs2 = __require("fs");
28667
28667
  var path = __require("path");
28668
28668
  var fileURLToPath = require_file_uri_to_path();
@@ -29413,6 +29413,9 @@ __export(exports_dist, {
29413
29413
  BalanceManager: () => BalanceManager
29414
29414
  });
29415
29415
  import { Transform, Readable } from "stream";
29416
+ import * as fs2 from "fs";
29417
+ import * as path from "path";
29418
+ import * as os2 from "os";
29416
29419
  function isNetworkErrorMessage(message) {
29417
29420
  return message.includes("NetworkError when attempting to fetch resource") || message.includes("Failed to fetch") || message.includes("Load failed") || message.includes("ERR_TLS_CERT_ALTNAME_INVALID") || message.includes("ERR_TLS_CERT_NOT_YET_VALID") || message.includes("ERR_TLS_CERT_EXPIRED") || message.includes("UNABLE_TO_VERIFY_LEAF_SIGNATURE") || message.includes("SELF_SIGNED_CERT_IN_CHAIN");
29418
29421
  }
@@ -29683,11 +29686,28 @@ async function createBunSqliteDriver(dbPath) {
29683
29686
  }
29684
29687
  function createSSEParserTransform(onUsage, onResponseId) {
29685
29688
  let buffer = "";
29686
- let usageCaptured = false;
29689
+ let capturedUsage = null;
29687
29690
  let responseIdCaptured = false;
29691
+ const mergeUsage = (previous, next) => {
29692
+ if (!previous)
29693
+ return next;
29694
+ return {
29695
+ promptTokens: next.promptTokens > 0 ? next.promptTokens : previous.promptTokens,
29696
+ completionTokens: next.completionTokens > 0 ? next.completionTokens : previous.completionTokens,
29697
+ totalTokens: next.totalTokens > 0 ? next.totalTokens : previous.totalTokens,
29698
+ cost: next.cost > 0 ? next.cost : previous.cost,
29699
+ satsCost: next.satsCost > 0 ? next.satsCost : previous.satsCost
29700
+ };
29701
+ };
29702
+ const hasUsageChanged = (previous, next) => {
29703
+ if (!previous)
29704
+ return true;
29705
+ return previous.promptTokens !== next.promptTokens || previous.completionTokens !== next.completionTokens || previous.totalTokens !== next.totalTokens || previous.cost !== next.cost || previous.satsCost !== next.satsCost;
29706
+ };
29688
29707
  const inspectDataPayload = (jsonText) => {
29689
- if (usageCaptured && responseIdCaptured)
29708
+ if (responseIdCaptured && capturedUsage?.satsCost && capturedUsage.totalTokens) {
29690
29709
  return;
29710
+ }
29691
29711
  const trimmed = jsonText.trim();
29692
29712
  if (!trimmed || trimmed === "[DONE]")
29693
29713
  return;
@@ -29702,18 +29722,20 @@ function createSSEParserTransform(onUsage, onResponseId) {
29702
29722
  responseIdCaptured = true;
29703
29723
  }
29704
29724
  }
29705
- if (!usageCaptured) {
29706
- const usage = extractUsageFromSSEJson(data);
29707
- if (usage) {
29708
- onUsage(usage);
29709
- usageCaptured = true;
29725
+ const usage = extractUsageFromSSEJson(data);
29726
+ if (usage) {
29727
+ const mergedUsage = mergeUsage(capturedUsage, usage);
29728
+ if (hasUsageChanged(capturedUsage, mergedUsage)) {
29729
+ capturedUsage = mergedUsage;
29730
+ onUsage(mergedUsage);
29710
29731
  }
29711
29732
  }
29712
29733
  } catch {}
29713
29734
  };
29714
29735
  const inspectEventBlock = (eventBlock) => {
29715
- if (usageCaptured && responseIdCaptured)
29736
+ if (responseIdCaptured && capturedUsage?.satsCost && capturedUsage.totalTokens) {
29716
29737
  return;
29738
+ }
29717
29739
  const lines = eventBlock.split(/\r?\n/);
29718
29740
  const dataParts = [];
29719
29741
  for (const line of lines) {
@@ -29770,7 +29792,7 @@ async function resolveRouteRequestContext(options) {
29770
29792
  const {
29771
29793
  modelId,
29772
29794
  requestBody,
29773
- path = "/v1/chat/completions",
29795
+ path: path2 = "/v1/chat/completions",
29774
29796
  headers = {},
29775
29797
  forcedProvider,
29776
29798
  walletAdapter,
@@ -29858,17 +29880,17 @@ async function resolveRouteRequestContext(options) {
29858
29880
  client: client2,
29859
29881
  baseUrl,
29860
29882
  mintUrl,
29861
- path,
29883
+ path: path2,
29862
29884
  headers,
29863
29885
  modelId,
29864
29886
  proxiedBody
29865
29887
  };
29866
29888
  }
29867
29889
  async function routeRequests(options) {
29868
- const { client: client2, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
29890
+ const { client: client2, baseUrl, mintUrl, path: path2, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
29869
29891
  try {
29870
29892
  const response = await client2.routeRequest({
29871
- path,
29893
+ path: path2,
29872
29894
  method: "POST",
29873
29895
  body: proxiedBody,
29874
29896
  headers,
@@ -29889,10 +29911,10 @@ async function routeRequests(options) {
29889
29911
  }
29890
29912
  async function routeRequestsToNodeResponse(options) {
29891
29913
  const { res } = options;
29892
- const { client: client2, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
29914
+ const { client: client2, baseUrl, mintUrl, path: path2, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options);
29893
29915
  try {
29894
29916
  await client2.routeRequestToNodeResponse({
29895
- path,
29917
+ path: path2,
29896
29918
  method: "POST",
29897
29919
  body: proxiedBody,
29898
29920
  headers,
@@ -30406,10 +30428,10 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
30406
30428
  `;
30407
30429
  if (typeof window === "undefined") {
30408
30430
  try {
30409
- const fs2 = await import("fs");
30410
- const path = await import("path");
30411
- const logPath = path.join(process.cwd(), "audit.log");
30412
- fs2.appendFileSync(logPath, logLine);
30431
+ const fs22 = await import("fs");
30432
+ const path2 = await import("path");
30433
+ const logPath = path2.join(process.cwd(), "audit.log");
30434
+ fs22.appendFileSync(logPath, logLine);
30413
30435
  } catch (error) {
30414
30436
  console.error("[AuditLogger] Failed to write to file:", error);
30415
30437
  }
@@ -31673,6 +31695,10 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
31673
31695
  const isExpired = age >= _ProviderManager.COOLDOWN_DURATION_MS;
31674
31696
  if (isExpired) {
31675
31697
  console.log(`[cleanupExpiredCooldowns:${this.instanceId}] Removing expired cooldown for ${url2} (age: ${age}ms, cooldown: ${_ProviderManager.COOLDOWN_DURATION_MS}ms)`);
31698
+ this.failedProviders.delete(url2);
31699
+ if (this.store) {
31700
+ this.store.getState().removeFailedProvider(url2);
31701
+ }
31676
31702
  }
31677
31703
  return !isExpired;
31678
31704
  });
@@ -31773,59 +31799,36 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
31773
31799
  const torMode = isTorContext();
31774
31800
  const disabledProviders = new Set(this.providerRegistry.getDisabledProviders());
31775
31801
  console.log(`[findNextBestProvider:${this.instanceId}] Starting search for model: ${modelId}`);
31776
- console.log(`[findNextBestProvider:${this.instanceId}] currentBaseUrl: ${currentBaseUrl}`);
31777
- console.log(`[findNextBestProvider:${this.instanceId}] torMode: ${torMode}`);
31778
31802
  console.log(`[findNextBestProvider:${this.instanceId}] disabledProviders: ${[...disabledProviders]}`);
31779
- console.log(`[findNextBestProvider:${this.instanceId}] failedProviders: ${[...this.failedProviders]}`);
31780
31803
  console.log(`[findNextBestProvider:${this.instanceId}] providersOnCooldown: ${this.providersOnCoolDown.map(([url2]) => url2)}`);
31781
31804
  const allProviders = this.providerRegistry.getAllProvidersModels();
31782
31805
  console.log(`[findNextBestProvider:${this.instanceId}] Total providers in registry: ${Object.keys(allProviders).length}`);
31783
31806
  const candidates = [];
31784
- let skippedCurrent = 0, skippedFailed = 0, skippedDisabled = 0, skippedCooldown = 0, skippedOnion = 0, skippedNoModel = 0;
31785
31807
  for (const [baseUrl, models] of Object.entries(allProviders)) {
31786
31808
  if (baseUrl === currentBaseUrl) {
31787
31809
  console.log(`[findNextBestProvider:${this.instanceId}] SKIP (current): ${baseUrl}`);
31788
- skippedCurrent++;
31789
- continue;
31790
- }
31791
- if (this.failedProviders.has(baseUrl)) {
31792
- console.log(`[findNextBestProvider:${this.instanceId}] SKIP (failed): ${baseUrl}`);
31793
- skippedFailed++;
31794
31810
  continue;
31795
31811
  }
31796
31812
  if (disabledProviders.has(baseUrl)) {
31797
- console.log(`[findNextBestProvider:${this.instanceId}] SKIP (disabled): ${baseUrl}`);
31798
- skippedDisabled++;
31799
31813
  continue;
31800
31814
  }
31801
31815
  if (this.isOnCooldown(baseUrl)) {
31802
- console.log(`[findNextBestProvider:${this.instanceId}] SKIP (cooldown): ${baseUrl}`);
31803
- skippedCooldown++;
31804
31816
  continue;
31805
31817
  }
31806
31818
  if (!torMode && (isOnionUrl(baseUrl) || isInsecureHttpUrl(baseUrl))) {
31807
- console.log(`[findNextBestProvider:${this.instanceId}] SKIP (onion/http): ${baseUrl}`);
31808
- skippedOnion++;
31809
31819
  continue;
31810
31820
  }
31811
31821
  const model2 = models.find((m2) => m2.id === modelId);
31812
31822
  if (!model2) {
31813
- console.log(`[findNextBestProvider:${this.instanceId}] SKIP (no model ${modelId}): ${baseUrl} has models: ${models.map((m2) => m2.id).join(", ")}`);
31814
- skippedNoModel++;
31815
31823
  continue;
31816
31824
  }
31817
31825
  const cost = model2.sats_pricing?.completion ?? 0;
31818
- console.log(`[findNextBestProvider:${this.instanceId}] CANDIDATE: ${baseUrl} cost: ${cost}`);
31819
31826
  candidates.push({ baseUrl, model: model2, cost });
31820
31827
  }
31821
- console.log(`[findNextBestProvider:${this.instanceId}] Skipped: current=${skippedCurrent}, failed=${skippedFailed}, disabled=${skippedDisabled}, cooldown=${skippedCooldown}, onion=${skippedOnion}, noModel=${skippedNoModel}`);
31822
- console.log(`[findNextBestProvider:${this.instanceId}] Total candidates: ${candidates.length}`);
31823
31828
  candidates.sort((a, b) => a.cost - b.cost);
31824
31829
  if (candidates.length > 0) {
31825
- console.log(`[findNextBestProvider:${this.instanceId}] Selected provider: ${candidates[0].baseUrl} with cost: ${candidates[0].cost}`);
31826
31830
  return candidates[0].baseUrl;
31827
31831
  } else {
31828
- console.log(`[findNextBestProvider:${this.instanceId}] No candidate providers found`);
31829
31832
  return null;
31830
31833
  }
31831
31834
  } catch (error) {
@@ -33503,7 +33506,7 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
33503
33506
  }
33504
33507
  async _prepareRoutedRequest(params) {
33505
33508
  const {
33506
- path,
33509
+ path: requestPath,
33507
33510
  method,
33508
33511
  body,
33509
33512
  headers = {},
@@ -33538,7 +33541,7 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
33538
33541
  const baseHeaders = this._buildBaseHeaders();
33539
33542
  const requestHeaders = this._withAuthHeader(baseHeaders, token);
33540
33543
  const response = await this._makeRequest({
33541
- path,
33544
+ path: requestPath,
33542
33545
  method,
33543
33546
  body: method === "GET" ? undefined : requestBody,
33544
33547
  baseUrl,
@@ -33557,7 +33560,21 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
33557
33560
  let capturedUsage;
33558
33561
  let capturedResponseId;
33559
33562
  if (contentType.includes("text/event-stream") && response.body) {
33563
+ const logDir = path.join(os2.homedir(), ".routstrd", "stream-response");
33564
+ if (!fs2.existsSync(logDir)) {
33565
+ fs2.mkdirSync(logDir, { recursive: true });
33566
+ }
33567
+ const logFile = path.join(logDir, `${Date.now()}.jsonl`);
33568
+ const logStream = fs2.createWriteStream(logFile);
33560
33569
  const nodeReadable = Readable.fromWeb(response.body);
33570
+ const loggingTransform = new Transform({
33571
+ transform(chunk, encoding, callback) {
33572
+ const raw = chunk.toString();
33573
+ logStream.write(JSON.stringify({ raw, timestamp: Date.now() }) + `
33574
+ `);
33575
+ callback(null, chunk);
33576
+ }
33577
+ });
33561
33578
  const sseParser = createSSEParserTransform((usage) => {
33562
33579
  capturedUsage = usage;
33563
33580
  processedResponse.usage = usage;
@@ -33565,7 +33582,7 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
33565
33582
  capturedResponseId = responseId;
33566
33583
  processedResponse.requestId = responseId;
33567
33584
  });
33568
- const transformed = nodeReadable.pipe(sseParser, { end: true });
33585
+ const transformed = nodeReadable.pipe(loggingTransform).pipe(sseParser, { end: true });
33569
33586
  const webStream = Readable.toWeb(transformed);
33570
33587
  processedResponse = new Response(webStream, {
33571
33588
  status: response.status,
@@ -33622,7 +33639,6 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
33622
33639
  callbacks.onTokenCreated?.(this._getPendingCashuTokenAmount());
33623
33640
  const baseHeaders = this._buildBaseHeaders(headers);
33624
33641
  const requestHeaders = this._withAuthHeader(baseHeaders, token);
33625
- this.providerManager.resetFailedProviders();
33626
33642
  const providerInfo = await this.providerRegistry.getProviderInfo(baseUrl);
33627
33643
  const providerVersion = providerInfo?.version ?? "";
33628
33644
  let modelIdForRequest = selectedModel.id;
@@ -33710,9 +33726,9 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
33710
33726
  }
33711
33727
  }
33712
33728
  async _makeRequest(params) {
33713
- const { path, method, body, baseUrl, token, headers } = params;
33729
+ const { path: path2, method, body, baseUrl, token, headers } = params;
33714
33730
  try {
33715
- const url2 = `${baseUrl.replace(/\/$/, "")}${path}`;
33731
+ const url2 = `${baseUrl.replace(/\/$/, "")}${path2}`;
33716
33732
  if (this.mode === "xcashu")
33717
33733
  this._log("DEBUG", "HEADERS,", headers);
33718
33734
  const response = await fetch(url2, {
@@ -33744,7 +33760,7 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
33744
33760
  }
33745
33761
  async _handleErrorResponse(params, token, status, requestId, xCashuRefundToken, responseBody, retryCount = 0) {
33746
33762
  const MAX_RETRIES_PER_PROVIDER = 2;
33747
- const { path, method, body, selectedModel, baseUrl, mintUrl } = params;
33763
+ const { path: path2, method, body, selectedModel, baseUrl, mintUrl } = params;
33748
33764
  let tryNextProvider = false;
33749
33765
  const errorMessage = responseBody;
33750
33766
  this._log("DEBUG", `[RoutstrClient] _handleErrorResponse: status=${status}, baseUrl=${baseUrl}, mode=${this.mode}, token preview=${token}, requestId=${requestId}, errorMessage=${errorMessage}`);
@@ -33910,7 +33926,7 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
33910
33926
  });
33911
33927
  return this._makeRequest({
33912
33928
  ...params,
33913
- path,
33929
+ path: path2,
33914
33930
  method,
33915
33931
  body,
33916
33932
  baseUrl: nextProvider,
@@ -34384,7 +34400,7 @@ var init_dist3 = __esm(() => {
34384
34400
  // src/daemon/index.ts
34385
34401
  init_dist3();
34386
34402
  import { createServer } from "http";
34387
- import { existsSync as existsSync6 } from "fs";
34403
+ import { existsSync as existsSync8 } from "fs";
34388
34404
 
34389
34405
  // src/utils/config.ts
34390
34406
  var HOME = process.env.HOME || process.env.USERPROFILE || "";
@@ -34403,19 +34419,19 @@ var DEFAULT_CONFIG = {
34403
34419
 
34404
34420
  // src/utils/logger.ts
34405
34421
  import { appendFile, mkdir } from "fs/promises";
34406
- import { existsSync } from "fs";
34407
- import { join as join3 } from "path";
34422
+ import { existsSync as existsSync2 } from "fs";
34423
+ import { join as join4 } from "path";
34408
34424
  var HOME2 = process.env.HOME || process.env.USERPROFILE || "";
34409
34425
  var LOG_DIR = process.env.ROUTSTRD_DIR || `${HOME2}/.routstrd`;
34410
- var LOGS_DIR2 = join3(LOG_DIR, "logs");
34426
+ var LOGS_DIR2 = join4(LOG_DIR, "logs");
34411
34427
  function getLogFileForDate(date = new Date) {
34412
34428
  const year = date.getFullYear();
34413
34429
  const month = String(date.getMonth() + 1).padStart(2, "0");
34414
34430
  const day = String(date.getDate()).padStart(2, "0");
34415
- return join3(LOGS_DIR2, `${year}-${month}-${day}.log`);
34431
+ return join4(LOGS_DIR2, `${year}-${month}-${day}.log`);
34416
34432
  }
34417
34433
  async function ensureLogDir() {
34418
- if (!existsSync(LOGS_DIR2)) {
34434
+ if (!existsSync2(LOGS_DIR2)) {
34419
34435
  await mkdir(LOGS_DIR2, { recursive: true });
34420
34436
  }
34421
34437
  }
@@ -34475,7 +34491,7 @@ function parseArgs(argv) {
34475
34491
 
34476
34492
  // src/daemon/config-store.ts
34477
34493
  import { mkdir as mkdir2 } from "fs/promises";
34478
- import { existsSync as existsSync2 } from "fs";
34494
+ import { existsSync as existsSync3 } from "fs";
34479
34495
  var REQUESTS_DIR = `${CONFIG_DIR}/requests`;
34480
34496
  async function ensureDirs() {
34481
34497
  try {
@@ -34485,7 +34501,7 @@ async function ensureDirs() {
34485
34501
  }
34486
34502
  async function loadDaemonConfig() {
34487
34503
  try {
34488
- if (existsSync2(CONFIG_FILE)) {
34504
+ if (existsSync3(CONFIG_FILE)) {
34489
34505
  const content2 = await Bun.file(CONFIG_FILE).text();
34490
34506
  return { ...DEFAULT_CONFIG, ...JSON.parse(content2) };
34491
34507
  }
@@ -34797,7 +34813,7 @@ function alphabet3(letters) {
34797
34813
  }
34798
34814
  };
34799
34815
  }
34800
- function join4(separator = "") {
34816
+ function join5(separator = "") {
34801
34817
  astr2("join", separator);
34802
34818
  return {
34803
34819
  encode: (from7) => {
@@ -35000,12 +35016,12 @@ function checksum2(len, fn) {
35000
35016
  }
35001
35017
  };
35002
35018
  }
35003
- var base163 = chain3(radix23(4), alphabet3("0123456789ABCDEF"), join4(""));
35004
- var base323 = chain3(radix23(5), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), padding3(5), join4(""));
35005
- var base32nopad2 = chain3(radix23(5), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), join4(""));
35006
- var base32hex3 = chain3(radix23(5), alphabet3("0123456789ABCDEFGHIJKLMNOPQRSTUV"), padding3(5), join4(""));
35007
- var base32hexnopad2 = chain3(radix23(5), alphabet3("0123456789ABCDEFGHIJKLMNOPQRSTUV"), join4(""));
35008
- var base32crockford3 = chain3(radix23(5), alphabet3("0123456789ABCDEFGHJKMNPQRSTVWXYZ"), join4(""), normalize3((s) => s.toUpperCase().replace(/O/g, "0").replace(/[IL]/g, "1")));
35019
+ var base163 = chain3(radix23(4), alphabet3("0123456789ABCDEF"), join5(""));
35020
+ var base323 = chain3(radix23(5), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), padding3(5), join5(""));
35021
+ var base32nopad2 = chain3(radix23(5), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"), join5(""));
35022
+ var base32hex3 = chain3(radix23(5), alphabet3("0123456789ABCDEFGHIJKLMNOPQRSTUV"), padding3(5), join5(""));
35023
+ var base32hexnopad2 = chain3(radix23(5), alphabet3("0123456789ABCDEFGHIJKLMNOPQRSTUV"), join5(""));
35024
+ var base32crockford3 = chain3(radix23(5), alphabet3("0123456789ABCDEFGHJKMNPQRSTVWXYZ"), join5(""), normalize3((s) => s.toUpperCase().replace(/O/g, "0").replace(/[IL]/g, "1")));
35009
35025
  var hasBase64Builtin2 = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toBase64 === "function" && typeof Uint8Array.fromBase64 === "function")();
35010
35026
  var decodeBase64Builtin2 = (s, isUrl) => {
35011
35027
  astr2("base64", s);
@@ -35023,8 +35039,8 @@ var base643 = hasBase64Builtin2 ? {
35023
35039
  decode(s) {
35024
35040
  return decodeBase64Builtin2(s, false);
35025
35041
  }
35026
- } : chain3(radix23(6), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), padding3(6), join4(""));
35027
- var base64nopad2 = chain3(radix23(6), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), join4(""));
35042
+ } : chain3(radix23(6), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), padding3(6), join5(""));
35043
+ var base64nopad2 = chain3(radix23(6), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), join5(""));
35028
35044
  var base64url3 = hasBase64Builtin2 ? {
35029
35045
  encode(b) {
35030
35046
  abytes4(b);
@@ -35033,14 +35049,14 @@ var base64url3 = hasBase64Builtin2 ? {
35033
35049
  decode(s) {
35034
35050
  return decodeBase64Builtin2(s, true);
35035
35051
  }
35036
- } : chain3(radix23(6), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"), padding3(6), join4(""));
35037
- var base64urlnopad2 = chain3(radix23(6), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"), join4(""));
35038
- var genBase583 = (abc) => chain3(radix5(58), alphabet3(abc), join4(""));
35052
+ } : chain3(radix23(6), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"), padding3(6), join5(""));
35053
+ var base64urlnopad2 = chain3(radix23(6), alphabet3("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"), join5(""));
35054
+ var genBase583 = (abc) => chain3(radix5(58), alphabet3(abc), join5(""));
35039
35055
  var base583 = genBase583("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
35040
35056
  var base58flickr3 = genBase583("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ");
35041
35057
  var base58xrp3 = genBase583("rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz");
35042
35058
  var createBase58check2 = (sha2565) => chain3(checksum2(4, (data) => sha2565(sha2565(data))), base583);
35043
- var BECH_ALPHABET3 = chain3(alphabet3("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), join4(""));
35059
+ var BECH_ALPHABET3 = chain3(alphabet3("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), join5(""));
35044
35060
  var POLYMOD_GENERATORS3 = [996825010, 642813549, 513874426, 1027748829, 705979059];
35045
35061
  function bech32Polymod3(pre) {
35046
35062
  const b = pre >> 25;
@@ -35144,7 +35160,7 @@ var hexBuiltin2 = {
35144
35160
  return Uint8Array.fromHex(s);
35145
35161
  }
35146
35162
  };
35147
- var hex3 = hasHexBuiltin3 ? hexBuiltin2 : chain3(radix23(4), alphabet3("0123456789abcdef"), join4(""), normalize3((s) => {
35163
+ var hex3 = hasHexBuiltin3 ? hexBuiltin2 : chain3(radix23(4), alphabet3("0123456789abcdef"), join5(""), normalize3((s) => {
35148
35164
  if (typeof s !== "string" || s.length % 2 !== 0)
35149
35165
  throw new TypeError(`hex.decode: expected string, got ${typeof s} with length ${s.length}`);
35150
35166
  return s.toLowerCase();
@@ -38000,14 +38016,14 @@ class HDKey2 {
38000
38016
  }
38001
38017
  this.pubHash = hash1602(this._publicKey);
38002
38018
  }
38003
- derive(path) {
38004
- if (!/^[mM]'?/.test(path)) {
38019
+ derive(path2) {
38020
+ if (!/^[mM]'?/.test(path2)) {
38005
38021
  throw new Error('Path must start with "m" or "M"');
38006
38022
  }
38007
- if (/^[mM]'?$/.test(path)) {
38023
+ if (/^[mM]'?$/.test(path2)) {
38008
38024
  return this;
38009
38025
  }
38010
- const parts = path.replace(/^[mM]'?\//, "").split("/");
38026
+ const parts = path2.replace(/^[mM]'?\//, "").split("/");
38011
38027
  let child = this;
38012
38028
  for (const c of parts) {
38013
38029
  const m2 = /^(\d+)('?)$/.exec(c);
@@ -38366,7 +38382,7 @@ function bt(s, t) {
38366
38382
  case 2:
38367
38383
  return is(s, t, r);
38368
38384
  case 3:
38369
- return os2(s, t, r);
38385
+ return os3(s, t, r);
38370
38386
  case 4:
38371
38387
  return as2(s, t, r);
38372
38388
  case 5:
@@ -38417,7 +38433,7 @@ function is(s, t, e) {
38417
38433
  throw new Error("Byte string length exceeds data length");
38418
38434
  return { value: new Uint8Array(s.buffer, s.byteOffset + r, n), offset: r + n };
38419
38435
  }
38420
- function os2(s, t, e) {
38436
+ function os3(s, t, e) {
38421
38437
  const { value: n, offset: r } = ot2(s, t, e);
38422
38438
  if (r + n > s.byteLength)
38423
38439
  throw new Error("String length exceeds data length");
@@ -40187,25 +40203,25 @@ function createCocodClient(options = {}) {
40187
40203
  return proc;
40188
40204
  });
40189
40205
  let startPromise = null;
40190
- async function fetchJson(path, init = {}) {
40206
+ async function fetchJson(path2, init = {}) {
40191
40207
  const method = init.method || "GET";
40192
40208
  const requestInit = {
40193
40209
  ...init,
40194
40210
  unix: socketPath
40195
40211
  };
40196
- const response = await fetchImpl(`http://localhost${path}`, requestInit);
40212
+ const response = await fetchImpl(`http://localhost${path2}`, requestInit);
40197
40213
  const rawText = await response.text();
40198
40214
  if (!rawText.trim()) {
40199
- throw new CocodHttpError(response.ok ? 502 : response.status, `Empty response from cocod for ${method} ${path}`);
40215
+ throw new CocodHttpError(response.ok ? 502 : response.status, `Empty response from cocod for ${method} ${path2}`);
40200
40216
  }
40201
40217
  let data;
40202
40218
  try {
40203
40219
  data = JSON.parse(rawText);
40204
40220
  } catch {
40205
- throw new CocodHttpError(response.ok ? 502 : response.status, `Invalid JSON response from cocod for ${method} ${path}`);
40221
+ throw new CocodHttpError(response.ok ? 502 : response.status, `Invalid JSON response from cocod for ${method} ${path2}`);
40206
40222
  }
40207
40223
  if (!data || typeof data !== "object") {
40208
- throw new CocodHttpError(response.ok ? 502 : response.status, `Unexpected response shape from cocod for ${method} ${path}`);
40224
+ throw new CocodHttpError(response.ok ? 502 : response.status, `Unexpected response shape from cocod for ${method} ${path2}`);
40209
40225
  }
40210
40226
  const errorMessage = toErrorText(data.error);
40211
40227
  if (errorMessage) {
@@ -40256,13 +40272,13 @@ function createCocodClient(options = {}) {
40256
40272
  }
40257
40273
  await startPromise;
40258
40274
  }
40259
- async function callDaemon(path, init = {}) {
40275
+ async function callDaemon(path2, init = {}) {
40260
40276
  await ensureDaemonRunning();
40261
- const response = await fetchJson(path, init);
40277
+ const response = await fetchJson(path2, init);
40262
40278
  return response.output;
40263
40279
  }
40264
- function post(path, body) {
40265
- return callDaemon(path, {
40280
+ function post(path2, body) {
40281
+ return callDaemon(path2, {
40266
40282
  method: "POST",
40267
40283
  headers: { "Content-Type": "application/json" },
40268
40284
  body: JSON.stringify(body)
@@ -40380,7 +40396,7 @@ async function createWalletAdapter(options = {}) {
40380
40396
  return { success: true, amount, unit, message };
40381
40397
  } catch (error) {
40382
40398
  const errorMessage = error instanceof Error ? error.message : String(error);
40383
- logger3.error("Error in walletAdapter receiveToken:", error);
40399
+ logger3.error("Error in walletAdapter receiveToken:", errorMessage);
40384
40400
  return { success: false, amount: 0, unit: "sat", message: errorMessage };
40385
40401
  }
40386
40402
  }
@@ -41059,173 +41075,6 @@ function createDaemonRequestHandler(deps) {
41059
41075
  }
41060
41076
  return;
41061
41077
  }
41062
- if (req.method === "POST" && url2.pathname === "/providers/disable") {
41063
- try {
41064
- const bodyText = await readBody(req);
41065
- const body = bodyText ? JSON.parse(bodyText) : {};
41066
- const indices = body.indices;
41067
- if (!Array.isArray(indices)) {
41068
- res.writeHead(400, { "Content-Type": "application/json" });
41069
- res.end(JSON.stringify({
41070
- error: "Missing or invalid 'indices' field (expected number[])."
41071
- }));
41072
- return;
41073
- }
41074
- const state = deps.store.getState();
41075
- const baseUrlsList = state.baseUrlsList || [];
41076
- const disabledProviders = [
41077
- ...state.disabledProviders || []
41078
- ];
41079
- const toDisable = [];
41080
- for (const idx of indices) {
41081
- if (typeof idx === "number" && idx >= 0 && idx < baseUrlsList.length) {
41082
- const baseUrl = baseUrlsList[idx];
41083
- if (!disabledProviders.includes(baseUrl)) {
41084
- disabledProviders.push(baseUrl);
41085
- toDisable.push(baseUrl);
41086
- }
41087
- }
41088
- }
41089
- deps.store.getState().setDisabledProviders(disabledProviders);
41090
- res.writeHead(200, { "Content-Type": "application/json" });
41091
- res.end(JSON.stringify({
41092
- output: {
41093
- message: `Disabled ${toDisable.length} provider(s)`,
41094
- disabled: toDisable
41095
- }
41096
- }));
41097
- } catch (error) {
41098
- res.writeHead(500, { "Content-Type": "application/json" });
41099
- res.end(JSON.stringify({ error: String(error) }));
41100
- }
41101
- return;
41102
- }
41103
- if (req.method === "POST" && url2.pathname === "/providers/enable") {
41104
- try {
41105
- const bodyText = await readBody(req);
41106
- const body = bodyText ? JSON.parse(bodyText) : {};
41107
- const indices = body.indices;
41108
- if (!Array.isArray(indices)) {
41109
- res.writeHead(400, { "Content-Type": "application/json" });
41110
- res.end(JSON.stringify({
41111
- error: "Missing or invalid 'indices' field (expected number[])."
41112
- }));
41113
- return;
41114
- }
41115
- const state = deps.store.getState();
41116
- const baseUrlsList = state.baseUrlsList || [];
41117
- const disabledProviders = [
41118
- ...state.disabledProviders || []
41119
- ];
41120
- const toEnable = [];
41121
- for (const idx of indices) {
41122
- if (typeof idx === "number" && idx >= 0 && idx < baseUrlsList.length) {
41123
- const baseUrl = baseUrlsList[idx];
41124
- const pos = disabledProviders.indexOf(baseUrl);
41125
- if (pos !== -1) {
41126
- disabledProviders.splice(pos, 1);
41127
- toEnable.push(baseUrl);
41128
- }
41129
- }
41130
- }
41131
- deps.store.getState().setDisabledProviders(disabledProviders);
41132
- res.writeHead(200, { "Content-Type": "application/json" });
41133
- res.end(JSON.stringify({
41134
- output: {
41135
- message: `Enabled ${toEnable.length} provider(s)`,
41136
- enabled: toEnable
41137
- }
41138
- }));
41139
- } catch (error) {
41140
- res.writeHead(500, { "Content-Type": "application/json" });
41141
- res.end(JSON.stringify({ error: String(error) }));
41142
- }
41143
- return;
41144
- }
41145
- if (req.method === "GET" && url2.pathname === "/clients") {
41146
- try {
41147
- const state = deps.store.getState();
41148
- const clientIds = state.clientIds || [];
41149
- const clients = clientIds.map((c) => ({
41150
- id: c.clientId,
41151
- name: c.name,
41152
- apiKey: c.apiKey,
41153
- createdAt: c.createdAt,
41154
- lastUsed: c.lastUsed
41155
- }));
41156
- res.writeHead(200, { "Content-Type": "application/json" });
41157
- res.end(JSON.stringify({
41158
- output: {
41159
- clients,
41160
- totalCount: clients.length
41161
- }
41162
- }));
41163
- } catch (error) {
41164
- res.writeHead(500, { "Content-Type": "application/json" });
41165
- res.end(JSON.stringify({ error: String(error) }));
41166
- }
41167
- return;
41168
- }
41169
- if (req.method === "POST" && url2.pathname === "/clients/add") {
41170
- try {
41171
- const bodyText = await readBody(req);
41172
- const body = bodyText ? JSON.parse(bodyText) : {};
41173
- const name = body.name;
41174
- if (!name || typeof name !== "string" || name.trim() === "") {
41175
- res.writeHead(400, { "Content-Type": "application/json" });
41176
- res.end(JSON.stringify({
41177
- error: "Missing required 'name' field (must be a non-empty string)."
41178
- }));
41179
- return;
41180
- }
41181
- const clientId = name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
41182
- if (!clientId) {
41183
- res.writeHead(400, { "Content-Type": "application/json" });
41184
- res.end(JSON.stringify({
41185
- error: "Invalid client name. Must contain alphanumeric characters."
41186
- }));
41187
- return;
41188
- }
41189
- const state = deps.store.getState();
41190
- const existingClients = state.clientIds || [];
41191
- const existingClient = existingClients.find((c) => c.clientId === clientId);
41192
- if (existingClient) {
41193
- res.writeHead(409, { "Content-Type": "application/json" });
41194
- res.end(JSON.stringify({
41195
- error: `Client with id '${clientId}' already exists.`
41196
- }));
41197
- return;
41198
- }
41199
- const apiKey = generateApiKey();
41200
- const newClient = {
41201
- clientId,
41202
- name: name.trim(),
41203
- apiKey,
41204
- createdAt: Date.now()
41205
- };
41206
- deps.store.getState().setClientIds((prev) => [
41207
- ...prev || [],
41208
- newClient
41209
- ]);
41210
- logger3.log(`Added client '${name}' with id '${clientId}'`);
41211
- res.writeHead(200, { "Content-Type": "application/json" });
41212
- res.end(JSON.stringify({
41213
- output: {
41214
- message: `Client '${name}' added successfully`,
41215
- client: {
41216
- id: clientId,
41217
- name: name.trim(),
41218
- apiKey,
41219
- createdAt: newClient.createdAt
41220
- }
41221
- }
41222
- }));
41223
- } catch (error) {
41224
- res.writeHead(500, { "Content-Type": "application/json" });
41225
- res.end(JSON.stringify({ error: String(error) }));
41226
- }
41227
- return;
41228
- }
41229
41078
  if (req.method === "GET" && url2.pathname === "/usage") {
41230
41079
  try {
41231
41080
  const output4 = await deps.usageTrackingDriver.list({
@@ -41347,16 +41196,16 @@ function createDaemonRequestHandler(deps) {
41347
41196
  }
41348
41197
 
41349
41198
  // src/integrations/opencode.ts
41350
- import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
41351
- import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
41352
- import { dirname as dirname3 } from "path";
41199
+ import { existsSync as existsSync7, mkdirSync as mkdirSync5 } from "fs";
41200
+ import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
41201
+ import { dirname as dirname4 } from "path";
41353
41202
 
41354
41203
  // src/integrations/registry.ts
41355
41204
  import { randomBytes as randomBytes6 } from "crypto";
41356
- import { join as join5 } from "path";
41205
+ import { join as join6 } from "path";
41357
41206
 
41358
41207
  // src/integrations/pi.ts
41359
- import { existsSync as existsSync3, mkdirSync } from "fs";
41208
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
41360
41209
  import { readFile, writeFile } from "fs/promises";
41361
41210
  import { dirname } from "path";
41362
41211
  async function installPiIntegration(config, store, integrationConfig) {
@@ -41386,7 +41235,7 @@ Installing routstr models in pi models.json...`);
41386
41235
  }
41387
41236
  let piConfig = {};
41388
41237
  try {
41389
- if (existsSync3(configPath)) {
41238
+ if (existsSync4(configPath)) {
41390
41239
  const content2 = await readFile(configPath, "utf-8");
41391
41240
  piConfig = JSON.parse(content2);
41392
41241
  }
@@ -41397,7 +41246,7 @@ Installing routstr models in pi models.json...`);
41397
41246
  piConfig.providers = {};
41398
41247
  }
41399
41248
  try {
41400
- mkdirSync(dirname(configPath), { recursive: true });
41249
+ mkdirSync2(dirname(configPath), { recursive: true });
41401
41250
  const response = await fetch(`http://localhost:${port}/models`);
41402
41251
  const data = await response.json();
41403
41252
  const models = data.output?.models || [];
@@ -41422,7 +41271,7 @@ Installing routstr models in pi models.json...`);
41422
41271
  }
41423
41272
 
41424
41273
  // src/integrations/openclaw.ts
41425
- import { existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
41274
+ import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
41426
41275
  import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
41427
41276
  import { dirname as dirname2 } from "path";
41428
41277
  var OPENCLAW_PROVIDER_ID = "routstr";
@@ -41454,7 +41303,7 @@ Installing routstr models in openclaw.json...`);
41454
41303
  }
41455
41304
  let openclawConfig = {};
41456
41305
  try {
41457
- if (existsSync4(configPath)) {
41306
+ if (existsSync5(configPath)) {
41458
41307
  const content2 = await readFile2(configPath, "utf-8");
41459
41308
  openclawConfig = JSON.parse(content2);
41460
41309
  }
@@ -41474,7 +41323,7 @@ Installing routstr models in openclaw.json...`);
41474
41323
  openclawConfig.agents.defaults = {};
41475
41324
  }
41476
41325
  try {
41477
- mkdirSync2(dirname2(configPath), { recursive: true });
41326
+ mkdirSync3(dirname2(configPath), { recursive: true });
41478
41327
  const response = await fetch(`http://localhost:${port}/models`);
41479
41328
  const data = await response.json();
41480
41329
  const models = data.output?.models || [];
@@ -41514,6 +41363,60 @@ Installing routstr models in openclaw.json...`);
41514
41363
  }
41515
41364
  }
41516
41365
 
41366
+ // src/integrations/claudecode.ts
41367
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
41368
+ import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
41369
+ import { dirname as dirname3 } from "path";
41370
+ async function installClaudeCodeIntegration(config, store, integrationConfig) {
41371
+ const { clientId, name, configPath } = integrationConfig;
41372
+ logger3.log(`
41373
+ Installing routstr configuration in ${configPath}...`);
41374
+ const port = config.port || 8008;
41375
+ const state = store.getState();
41376
+ const existingClient = (state.clientIds || []).find((c) => c.clientId === clientId);
41377
+ let apiKey;
41378
+ if (existingClient) {
41379
+ apiKey = existingClient.apiKey;
41380
+ logger3.log(`Using existing API key for ${name}`);
41381
+ } else {
41382
+ apiKey = generateApiKey2();
41383
+ store.getState().setClientIds((prev) => [
41384
+ ...prev || [],
41385
+ {
41386
+ clientId,
41387
+ name,
41388
+ apiKey,
41389
+ createdAt: Date.now()
41390
+ }
41391
+ ]);
41392
+ logger3.log(`Created new API key for ${name}`);
41393
+ }
41394
+ let settings = {};
41395
+ try {
41396
+ if (existsSync6(configPath)) {
41397
+ const content2 = await readFile3(configPath, "utf-8");
41398
+ settings = JSON.parse(content2);
41399
+ }
41400
+ } catch (error) {
41401
+ logger3.error(`Error reading ${configPath}, creating new one.`);
41402
+ }
41403
+ if (!settings.env) {
41404
+ settings.env = {};
41405
+ }
41406
+ settings.env["ANTHROPIC_AUTH_TOKEN"] = apiKey;
41407
+ settings.env["ANTHROPIC_BASE_URL"] = `http://localhost:${port}`;
41408
+ settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = "gpt-5.4";
41409
+ settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = "claude-opus-4.7";
41410
+ settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = "minimax-m2.7";
41411
+ try {
41412
+ mkdirSync4(dirname3(configPath), { recursive: true });
41413
+ await writeFile3(configPath, JSON.stringify(settings, null, 2));
41414
+ logger3.log(`Successfully updated ${configPath} with routstr settings.`);
41415
+ } catch (error) {
41416
+ logger3.error(`Failed to write to ${configPath}:`, error);
41417
+ }
41418
+ }
41419
+
41517
41420
  // src/integrations/registry.ts
41518
41421
  function generateApiKey2() {
41519
41422
  const bytes4 = randomBytes6(24);
@@ -41523,23 +41426,29 @@ var CLIENT_CONFIGS = {
41523
41426
  opencode: {
41524
41427
  clientId: "opencode",
41525
41428
  name: "OpenCode",
41526
- configPath: join5(process.env.HOME || "", ".config/opencode/opencode.json")
41429
+ configPath: join6(process.env.HOME || "", ".config/opencode/opencode.json")
41527
41430
  },
41528
41431
  "pi-agent": {
41529
41432
  clientId: "pi-agent",
41530
41433
  name: "Pi Agent",
41531
- configPath: join5(process.env.HOME || "", ".pi/agent/models.json")
41434
+ configPath: join6(process.env.HOME || "", ".pi/agent/models.json")
41532
41435
  },
41533
41436
  openclaw: {
41534
41437
  clientId: "openclaw",
41535
41438
  name: "OpenClaw",
41536
- configPath: join5(process.env.HOME || "", ".openclaw/openclaw.json")
41439
+ configPath: join6(process.env.HOME || "", ".openclaw/openclaw.json")
41440
+ },
41441
+ "claude-code": {
41442
+ clientId: "claude-code",
41443
+ name: "Claude Code",
41444
+ configPath: join6(process.env.HOME || "", ".claude/settings.json")
41537
41445
  }
41538
41446
  };
41539
41447
  var CLIENT_INTEGRATIONS = {
41540
41448
  opencode: installOpencodeIntegration,
41541
41449
  "pi-agent": installPiIntegration,
41542
- openclaw: installOpenClawIntegration
41450
+ openclaw: installOpenClawIntegration,
41451
+ "claude-code": installClaudeCodeIntegration
41543
41452
  };
41544
41453
  async function runIntegrationsForClients(clientIds, config, store) {
41545
41454
  for (const client2 of clientIds) {
@@ -41583,8 +41492,8 @@ Installing routstr models in opencode.json...`);
41583
41492
  }
41584
41493
  let opencodeConfig;
41585
41494
  try {
41586
- if (existsSync5(configPath)) {
41587
- const content2 = await readFile3(configPath, "utf-8");
41495
+ if (existsSync7(configPath)) {
41496
+ const content2 = await readFile4(configPath, "utf-8");
41588
41497
  opencodeConfig = JSON.parse(content2);
41589
41498
  } else {
41590
41499
  opencodeConfig = { provider: {} };
@@ -41596,7 +41505,7 @@ Installing routstr models in opencode.json...`);
41596
41505
  opencodeConfig.provider = {};
41597
41506
  }
41598
41507
  try {
41599
- mkdirSync3(dirname3(configPath), { recursive: true });
41508
+ mkdirSync5(dirname4(configPath), { recursive: true });
41600
41509
  const response = await fetch(`http://localhost:${port}/models`);
41601
41510
  const data = await response.json();
41602
41511
  const models = data.output?.models || [];
@@ -41619,7 +41528,7 @@ Installing routstr models in opencode.json...`);
41619
41528
  models: modelsObj
41620
41529
  };
41621
41530
  opencodeConfig.small_model = OPENCODE_SMALL_MODEL;
41622
- await writeFile3(configPath, JSON.stringify(opencodeConfig, null, 2));
41531
+ await writeFile4(configPath, JSON.stringify(opencodeConfig, null, 2));
41623
41532
  logger3.log(`Added "routstr" provider with ${models.length} models to opencode.json`);
41624
41533
  } catch (error) {
41625
41534
  logger3.error("Failed to install models in opencode.json:", error);
@@ -41674,7 +41583,7 @@ async function main() {
41674
41583
  }));
41675
41584
  Bun.write(PID_FILE, String(process.pid));
41676
41585
  try {
41677
- if (existsSync6(SOCKET_PATH)) {
41586
+ if (existsSync8(SOCKET_PATH)) {
41678
41587
  Bun.spawn(["rm", SOCKET_PATH]);
41679
41588
  }
41680
41589
  } catch {}