routstrd 0.2.22 → 0.3.1

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/index.js CHANGED
@@ -27,6 +27,7 @@ var __export = (target, all) => {
27
27
  });
28
28
  };
29
29
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
30
+ var __require = import.meta.require;
30
31
 
31
32
  // node_modules/commander/lib/error.js
32
33
  var require_error = __commonJS((exports) => {
@@ -748,11 +749,11 @@ var require_suggestSimilar = __commonJS((exports) => {
748
749
 
749
750
  // node_modules/commander/lib/command.js
750
751
  var require_command = __commonJS((exports) => {
751
- var EventEmitter = import.meta.require("events").EventEmitter;
752
- var childProcess = import.meta.require("child_process");
753
- var path = import.meta.require("path");
754
- var fs = import.meta.require("fs");
755
- var process2 = import.meta.require("process");
752
+ var EventEmitter = __require("events").EventEmitter;
753
+ var childProcess = __require("child_process");
754
+ var path = __require("path");
755
+ var fs = __require("fs");
756
+ var process2 = __require("process");
756
757
  var { Argument, humanReadableArgName } = require_argument();
757
758
  var { CommanderError } = require_error();
758
759
  var { Help, stripColor } = require_help();
@@ -1000,8 +1001,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1000
1001
  this._exitCallback = (err) => {
1001
1002
  if (err.code !== "commander.executeSubCommandAsync") {
1002
1003
  throw err;
1003
- } else {
1004
- }
1004
+ } else {}
1005
1005
  };
1006
1006
  }
1007
1007
  return this;
@@ -2235,8 +2235,7 @@ async function readLockOwner(lockDir) {
2235
2235
  token: typeof parsed.token === "string" ? parsed.token : undefined
2236
2236
  };
2237
2237
  }
2238
- } catch {
2239
- }
2238
+ } catch {}
2240
2239
  return null;
2241
2240
  }
2242
2241
  async function isLockStale(lockDir, staleAfterMs) {
@@ -2298,8 +2297,7 @@ async function withCrossProcessLock(lockDir, fn, options = {}) {
2298
2297
  await release();
2299
2298
  }
2300
2299
  }
2301
- var init_process_lock = () => {
2302
- };
2300
+ var init_process_lock = () => {};
2303
2301
 
2304
2302
  // src/start-daemon.ts
2305
2303
  async function isDaemonHealthy(port) {
@@ -5220,8 +5218,7 @@ function unsafeWrapper(fn) {
5220
5218
  return function(...args) {
5221
5219
  try {
5222
5220
  return fn.apply(null, args);
5223
- } catch (e) {
5224
- }
5221
+ } catch (e) {}
5225
5222
  };
5226
5223
  }
5227
5224
  function bech32Polymod(pre) {
@@ -7171,28 +7168,49 @@ function calcPaddedLen(len) {
7171
7168
  throw new Error("expected positive integer");
7172
7169
  if (len <= 32)
7173
7170
  return 32;
7174
- const nextPower = 1 << Math.floor(Math.log2(len - 1)) + 1;
7171
+ const nextPower = 2 ** (Math.floor(Math.log2(len - 1)) + 1);
7175
7172
  const chunk = nextPower <= 256 ? 32 : nextPower / 8;
7176
7173
  return chunk * (Math.floor((len - 1) / chunk) + 1);
7177
7174
  }
7178
7175
  function writeU16BE(num2) {
7179
- if (!Number.isSafeInteger(num2) || num2 < minPlaintextSize || num2 > maxPlaintextSize)
7176
+ if (!Number.isSafeInteger(num2) || num2 < minPlaintextSize || num2 > 65535)
7180
7177
  throw new Error("invalid plaintext size: must be between 1 and 65535 bytes");
7181
7178
  const arr = new Uint8Array(2);
7182
7179
  new DataView(arr.buffer).setUint16(0, num2, false);
7183
7180
  return arr;
7184
7181
  }
7182
+ function writeU32BE(num2) {
7183
+ if (!Number.isSafeInteger(num2) || num2 < extendedPrefixThreshold || num2 > maxPlaintextSize)
7184
+ throw new Error("invalid plaintext size: must be between 65536 and 4294967295 bytes");
7185
+ const arr = new Uint8Array(4);
7186
+ new DataView(arr.buffer).setUint32(0, num2, false);
7187
+ return arr;
7188
+ }
7185
7189
  function pad(plaintext) {
7186
7190
  const unpadded = utf8Encoder.encode(plaintext);
7187
7191
  const unpaddedLen = unpadded.length;
7188
- const prefix = writeU16BE(unpaddedLen);
7192
+ if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize)
7193
+ throw new Error("invalid plaintext size: must be between 1 and 4294967295 bytes");
7194
+ const prefix = unpaddedLen >= extendedPrefixThreshold ? concatBytes(new Uint8Array([0, 0]), writeU32BE(unpaddedLen)) : writeU16BE(unpaddedLen);
7189
7195
  const suffix = new Uint8Array(calcPaddedLen(unpaddedLen) - unpaddedLen);
7190
7196
  return concatBytes(prefix, unpadded, suffix);
7191
7197
  }
7192
7198
  function unpad(padded) {
7193
- const unpaddedLen = new DataView(padded.buffer).getUint16(0);
7194
- const unpadded = padded.subarray(2, 2 + unpaddedLen);
7195
- if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize || unpadded.length !== unpaddedLen || padded.length !== 2 + calcPaddedLen(unpaddedLen))
7199
+ const dv = new DataView(padded.buffer, padded.byteOffset, padded.byteLength);
7200
+ const firstTwo = dv.getUint16(0);
7201
+ let unpaddedLen;
7202
+ let prefixLen;
7203
+ if (firstTwo === 0) {
7204
+ unpaddedLen = dv.getUint32(2);
7205
+ if (unpaddedLen < extendedPrefixThreshold)
7206
+ throw new Error("invalid padding");
7207
+ prefixLen = 6;
7208
+ } else {
7209
+ unpaddedLen = firstTwo;
7210
+ prefixLen = 2;
7211
+ }
7212
+ const unpadded = padded.subarray(prefixLen, prefixLen + unpaddedLen);
7213
+ if (unpaddedLen < minPlaintextSize || unpaddedLen > maxPlaintextSize || unpadded.length !== unpaddedLen || padded.length !== prefixLen + calcPaddedLen(unpaddedLen))
7196
7214
  throw new Error("invalid padding");
7197
7215
  return utf8Decoder.decode(unpadded);
7198
7216
  }
@@ -7206,7 +7224,7 @@ function decodePayload(payload) {
7206
7224
  if (typeof payload !== "string")
7207
7225
  throw new Error("payload must be a valid string");
7208
7226
  const plen = payload.length;
7209
- if (plen < 132 || plen > 87472)
7227
+ if (plen < 132)
7210
7228
  throw new Error("invalid payload length: " + plen);
7211
7229
  if (payload[0] === "#")
7212
7230
  throw new Error("unknown encryption version");
@@ -7217,7 +7235,7 @@ function decodePayload(payload) {
7217
7235
  throw new Error("invalid base64: " + error.message);
7218
7236
  }
7219
7237
  const dlen = data.length;
7220
- if (dlen < 99 || dlen > 65603)
7238
+ if (dlen < 99)
7221
7239
  throw new Error("invalid data length: " + dlen);
7222
7240
  const vers = data[0];
7223
7241
  if (vers !== 2)
@@ -7403,6 +7421,135 @@ function parse2(uri) {
7403
7421
  decoded: decode(match[1])
7404
7422
  };
7405
7423
  }
7424
+ function parseKind(kind) {
7425
+ if (!kind)
7426
+ return;
7427
+ return /^\d+$/.test(kind) ? parseInt(kind, 10) : kind;
7428
+ }
7429
+ function parseAddressPointer(value, relayUrl) {
7430
+ const idx = value.indexOf(":");
7431
+ const idx2 = value.indexOf(":", idx + 1);
7432
+ if (idx === -1 || idx2 === -1)
7433
+ return;
7434
+ const kind = parseInt(value.slice(0, idx), 10);
7435
+ if (Number.isNaN(kind))
7436
+ return;
7437
+ return {
7438
+ kind,
7439
+ pubkey: value.slice(idx + 1, idx2),
7440
+ identifier: value.slice(idx2 + 1),
7441
+ relays: relayUrl ? [relayUrl] : []
7442
+ };
7443
+ }
7444
+ function parsePointer(tag) {
7445
+ switch (tag[0]) {
7446
+ case "E":
7447
+ case "e":
7448
+ if (!tag[1])
7449
+ return;
7450
+ return {
7451
+ id: tag[1],
7452
+ relays: tag[2] ? [tag[2]] : [],
7453
+ author: tag[3]
7454
+ };
7455
+ case "A":
7456
+ case "a":
7457
+ if (!tag[1])
7458
+ return;
7459
+ return parseAddressPointer(tag[1], tag[2]);
7460
+ case "I":
7461
+ case "i":
7462
+ if (!tag[1])
7463
+ return;
7464
+ return {
7465
+ value: tag[1],
7466
+ hint: tag[2]
7467
+ };
7468
+ }
7469
+ }
7470
+ function parseQuote(tag) {
7471
+ if (!tag[1])
7472
+ return;
7473
+ if (tag[1].includes(":")) {
7474
+ return parseAddressPointer(tag[1], tag[2]);
7475
+ }
7476
+ return {
7477
+ id: tag[1],
7478
+ relays: tag[2] ? [tag[2]] : [],
7479
+ author: tag[3]
7480
+ };
7481
+ }
7482
+ function choosePointer(candidates) {
7483
+ return candidates.findLast((candidate) => candidate.tagName === "A" || candidate.tagName === "a")?.pointer || candidates.findLast((candidate) => candidate.tagName === "I" || candidate.tagName === "i")?.pointer || candidates.findLast((candidate) => candidate.tagName === "E" || candidate.tagName === "e")?.pointer;
7484
+ }
7485
+ function inheritRelayHints(pointer, profiles) {
7486
+ if (!pointer || !("id" in pointer) || !pointer.author)
7487
+ return;
7488
+ const author = profiles.find((profile) => profile.pubkey === pointer.author);
7489
+ if (!author || !author.relays)
7490
+ return;
7491
+ if (!pointer.relays) {
7492
+ pointer.relays = [];
7493
+ }
7494
+ author.relays.forEach((url) => {
7495
+ if (pointer.relays.indexOf(url) === -1)
7496
+ pointer.relays.push(url);
7497
+ });
7498
+ author.relays = pointer.relays;
7499
+ }
7500
+ function parse3(event) {
7501
+ const result = {
7502
+ root: undefined,
7503
+ rootKind: undefined,
7504
+ reply: undefined,
7505
+ replyKind: undefined,
7506
+ mentions: [],
7507
+ quotes: [],
7508
+ profiles: []
7509
+ };
7510
+ const rootCandidates = [];
7511
+ const replyCandidates = [];
7512
+ for (const tag of event.tags) {
7513
+ if ((tag[0] === "E" || tag[0] === "A" || tag[0] === "I") && tag[1]) {
7514
+ const pointer = parsePointer(tag);
7515
+ if (pointer)
7516
+ rootCandidates.push({ tagName: tag[0], pointer });
7517
+ continue;
7518
+ }
7519
+ if ((tag[0] === "e" || tag[0] === "a" || tag[0] === "i") && tag[1]) {
7520
+ const pointer = parsePointer(tag);
7521
+ if (pointer)
7522
+ replyCandidates.push({ tagName: tag[0], pointer });
7523
+ continue;
7524
+ }
7525
+ if (tag[0] === "K") {
7526
+ result.rootKind = parseKind(tag[1]);
7527
+ continue;
7528
+ }
7529
+ if (tag[0] === "k") {
7530
+ result.replyKind = parseKind(tag[1]);
7531
+ continue;
7532
+ }
7533
+ if (tag[0] === "q") {
7534
+ const pointer = parseQuote(tag);
7535
+ if (pointer)
7536
+ result.quotes.push(pointer);
7537
+ continue;
7538
+ }
7539
+ if ((tag[0] === "P" || tag[0] === "p") && tag[1]) {
7540
+ result.profiles.push({
7541
+ pubkey: tag[1],
7542
+ relays: tag[2] ? [tag[2]] : []
7543
+ });
7544
+ }
7545
+ }
7546
+ result.root = choosePointer(rootCandidates);
7547
+ result.reply = choosePointer(replyCandidates);
7548
+ inheritRelayHints(result.root, result.profiles);
7549
+ inheritRelayHints(result.reply, result.profiles);
7550
+ result.quotes.forEach((pointer) => inheritRelayHints(pointer, result.profiles));
7551
+ return result;
7552
+ }
7406
7553
  function finishReactionEvent(t, reacted, privateKey) {
7407
7554
  const inheritedTags = reacted.tags.filter((tag) => tag.length >= 2 && (tag[0] === "e" || tag[0] === "p"));
7408
7555
  return finalizeEvent({
@@ -7437,7 +7584,7 @@ function getReactedEventPointer(event) {
7437
7584
  author: lastPTag[1]
7438
7585
  };
7439
7586
  }
7440
- function* parse3(content) {
7587
+ function* parse4(content) {
7441
7588
  let emojis = [];
7442
7589
  if (typeof content !== "string") {
7443
7590
  for (let i2 = 0;i2 < content.tags.length; i2++) {
@@ -7591,8 +7738,7 @@ function* matchAll(content) {
7591
7738
  start: match.index,
7592
7739
  end: match.index + shortcode.length
7593
7740
  };
7594
- } catch (_e) {
7595
- }
7741
+ } catch (_e) {}
7596
7742
  }
7597
7743
  }
7598
7744
  function replaceAll(content, replacer) {
@@ -7617,12 +7763,12 @@ async function validateGithub(pubkey, username, proof) {
7617
7763
  function parseConnectionString(connectionString) {
7618
7764
  const { host, pathname, searchParams } = new URL(connectionString);
7619
7765
  const pubkey = pathname || host;
7620
- const relay = searchParams.get("relay");
7766
+ const relays = searchParams.getAll("relay");
7621
7767
  const secret = searchParams.get("secret");
7622
- if (!pubkey || !relay || !secret) {
7768
+ if (!pubkey || relays.length === 0 || !secret) {
7623
7769
  throw new Error("invalid connection string");
7624
7770
  }
7625
- return { pubkey, relay, secret };
7771
+ return { pubkey, relay: relays[0], relays, secret };
7626
7772
  }
7627
7773
  async function makeNwcRequestEvent(pubkey, secretKey, invoice) {
7628
7774
  const content = {
@@ -7672,8 +7818,7 @@ async function getZapEndpoint(metadata) {
7672
7818
  if (body.allowsNostr && body.nostrPubkey) {
7673
7819
  return body.callback;
7674
7820
  }
7675
- } catch (err) {
7676
- }
7821
+ } catch (err) {}
7677
7822
  return null;
7678
7823
  }
7679
7824
  function makeZapRequest(params) {
@@ -8034,8 +8179,7 @@ var __defProp2, __export2 = (target, all) => {
8034
8179
  this.reconnectTimeoutHandle = setTimeout(async () => {
8035
8180
  try {
8036
8181
  await this.connect();
8037
- } catch (err) {
8038
- }
8182
+ } catch (err) {}
8039
8183
  }, backoff);
8040
8184
  }
8041
8185
  handleHardClose(reason) {
@@ -8339,7 +8483,11 @@ var __defProp2, __export2 = (target, all) => {
8339
8483
  case "AUTH": {
8340
8484
  this.challenge = data[1];
8341
8485
  if (this.onauth) {
8342
- this.auth(this.onauth);
8486
+ this.auth(this.onauth).catch((err) => {
8487
+ if (!(err instanceof SendingOnClosedConnection)) {
8488
+ throw err;
8489
+ }
8490
+ });
8343
8491
  }
8344
8492
  return;
8345
8493
  }
@@ -8407,8 +8555,7 @@ var __defProp2, __export2 = (target, all) => {
8407
8555
  try {
8408
8556
  this.relay.send('["CLOSE",' + JSON.stringify(this.id) + "]");
8409
8557
  } catch (err) {
8410
- if (err instanceof SendingOnClosedConnection) {
8411
- } else {
8558
+ if (err instanceof SendingOnClosedConnection) {} else {
8412
8559
  throw err;
8413
8560
  }
8414
8561
  }
@@ -8420,7 +8567,7 @@ var __defProp2, __export2 = (target, all) => {
8420
8567
  this.relay.idleSince = Date.now();
8421
8568
  this.onclose?.(reason);
8422
8569
  }
8423
- }, _WebSocket, _WebSocket2, nip19_exports, NostrTypeGuard, Bech32MaxSize = 5000, BECH32_REGEX, nip04_exports, nip05_exports, NIP05_REGEX, isNip05 = (value) => NIP05_REGEX.test(value || ""), _fetch, nip10_exports, nip11_exports, _fetch2, nip13_exports, nip17_exports, nip59_exports, nip44_exports, minPlaintextSize = 1, maxPlaintextSize = 65535, v2, TWO_DAYS, now = () => Math.round(Date.now() / 1000), randomNow = () => Math.round(now() - Math.random() * TWO_DAYS), nip44ConversationKey = (privateKey, publicKey) => getConversationKey(privateKey, publicKey), nip44Encrypt = (data, privateKey, publicKey) => encrypt22(JSON.stringify(data), nip44ConversationKey(privateKey, publicKey)), nip44Decrypt = (data, privateKey) => JSON.parse(decrypt22(data.content, nip44ConversationKey(privateKey, data.pubkey))), unwrapEvent2, unwrapManyEvents2, nip18_exports, nip21_exports, NOSTR_URI_REGEX, nip25_exports, nip27_exports, noCharacter, noURLCharacter, MAX_HASHTAG_LENGTH = 42, nip28_exports, channelCreateEvent = (t, privateKey) => {
8570
+ }, _WebSocket, _WebSocket2, nip19_exports, NostrTypeGuard, Bech32MaxSize = 5000, BECH32_REGEX, nip04_exports, nip05_exports, NIP05_REGEX, isNip05 = (value) => NIP05_REGEX.test(value || ""), _fetch, nip10_exports, nip11_exports, _fetch2, nip13_exports, nip17_exports, nip59_exports, nip44_exports, minPlaintextSize = 1, maxPlaintextSize = 4294967295, extendedPrefixThreshold = 65536, v2, TWO_DAYS, now = () => Math.round(Date.now() / 1000), randomNow = () => Math.round(now() - Math.random() * TWO_DAYS), nip44ConversationKey = (privateKey, publicKey) => getConversationKey(privateKey, publicKey), nip44Encrypt = (data, privateKey, publicKey) => encrypt22(JSON.stringify(data), nip44ConversationKey(privateKey, publicKey)), nip44Decrypt = (data, privateKey) => JSON.parse(decrypt22(data.content, nip44ConversationKey(privateKey, data.pubkey))), unwrapEvent2, unwrapManyEvents2, nip18_exports, nip21_exports, NOSTR_URI_REGEX, nip22_exports, nip25_exports, nip27_exports, noCharacter, noURLCharacter, MAX_HASHTAG_LENGTH = 42, nip28_exports, channelCreateEvent = (t, privateKey) => {
8424
8571
  let content;
8425
8572
  if (typeof t.content === "object") {
8426
8573
  content = JSON.stringify(t.content);
@@ -9087,12 +9234,10 @@ var init_esm = __esm(() => {
9087
9234
  };
9088
9235
  try {
9089
9236
  _WebSocket = WebSocket;
9090
- } catch {
9091
- }
9237
+ } catch {}
9092
9238
  try {
9093
9239
  _WebSocket2 = WebSocket;
9094
- } catch {
9095
- }
9240
+ } catch {}
9096
9241
  nip19_exports = {};
9097
9242
  __export2(nip19_exports, {
9098
9243
  BECH32_REGEX: () => BECH32_REGEX,
@@ -9135,8 +9280,7 @@ var init_esm = __esm(() => {
9135
9280
  NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w_-]+(\.[\w_-]+)+)$/;
9136
9281
  try {
9137
9282
  _fetch = fetch;
9138
- } catch (_) {
9139
- }
9283
+ } catch (_) {}
9140
9284
  nip10_exports = {};
9141
9285
  __export2(nip10_exports, {
9142
9286
  parse: () => parse
@@ -9148,8 +9292,7 @@ var init_esm = __esm(() => {
9148
9292
  });
9149
9293
  try {
9150
9294
  _fetch2 = fetch;
9151
- } catch {
9152
- }
9295
+ } catch {}
9153
9296
  nip13_exports = {};
9154
9297
  __export2(nip13_exports, {
9155
9298
  getPow: () => getPow,
@@ -9182,7 +9325,9 @@ var init_esm = __esm(() => {
9182
9325
  v2 = {
9183
9326
  utils: {
9184
9327
  getConversationKey,
9185
- calcPaddedLen
9328
+ calcPaddedLen,
9329
+ pad,
9330
+ unpad
9186
9331
  },
9187
9332
  encrypt: encrypt22,
9188
9333
  decrypt: decrypt22
@@ -9203,6 +9348,10 @@ var init_esm = __esm(() => {
9203
9348
  test: () => test
9204
9349
  });
9205
9350
  NOSTR_URI_REGEX = new RegExp(`nostr:(${BECH32_REGEX.source})`);
9351
+ nip22_exports = {};
9352
+ __export2(nip22_exports, {
9353
+ parse: () => parse3
9354
+ });
9206
9355
  nip25_exports = {};
9207
9356
  __export2(nip25_exports, {
9208
9357
  finishReactionEvent: () => finishReactionEvent,
@@ -9210,7 +9359,7 @@ var init_esm = __esm(() => {
9210
9359
  });
9211
9360
  nip27_exports = {};
9212
9361
  __export2(nip27_exports, {
9213
- parse: () => parse3
9362
+ parse: () => parse4
9214
9363
  });
9215
9364
  noCharacter = /\W/m;
9216
9365
  noURLCharacter = /[^\w\/] |[^\w\/]$|$|,| /m;
@@ -9237,8 +9386,7 @@ var init_esm = __esm(() => {
9237
9386
  });
9238
9387
  try {
9239
9388
  _fetch3 = fetch;
9240
- } catch {
9241
- }
9389
+ } catch {}
9242
9390
  nip47_exports = {};
9243
9391
  __export2(nip47_exports, {
9244
9392
  makeNwcRequestEvent: () => makeNwcRequestEvent,
@@ -9259,8 +9407,7 @@ var init_esm = __esm(() => {
9259
9407
  });
9260
9408
  try {
9261
9409
  _fetch4 = fetch;
9262
- } catch {
9263
- }
9410
+ } catch {}
9264
9411
  nip77_exports = {};
9265
9412
  __export2(nip77_exports, {
9266
9413
  Negentropy: () => Negentropy,
@@ -9383,15 +9530,19 @@ async function loadConfig() {
9383
9530
  function getDaemonBaseUrl(config) {
9384
9531
  return config.daemonUrl?.replace(/\/$/, "") || `http://localhost:${config.port}`;
9385
9532
  }
9386
- async function callDaemon(path, options = {}) {
9533
+ function getAuthBaseUrl(config) {
9534
+ if (config.authUrl) {
9535
+ return config.authUrl.replace(/\/$/, "");
9536
+ }
9537
+ return getDaemonBaseUrl(config);
9538
+ }
9539
+ async function _callUrl(baseUrl, path, options, config) {
9387
9540
  const { method = "GET", body } = options;
9388
- const config = await loadConfig();
9389
- const baseUrl = getDaemonBaseUrl(config);
9390
9541
  const url = `${baseUrl}${path}`;
9391
9542
  const bodyString = body ? JSON.stringify(body) : undefined;
9392
9543
  const bodyBytes = bodyString ? new TextEncoder().encode(bodyString) : undefined;
9393
9544
  let authorization;
9394
- if (config.daemonUrl && config.nsec) {
9545
+ if ((config.daemonUrl || config.authUrl) && config.nsec) {
9395
9546
  const secretKey = parseSecretKey(config.nsec);
9396
9547
  authorization = await createNIP98Authorization(secretKey, url, method, bodyBytes);
9397
9548
  }
@@ -9409,6 +9560,16 @@ async function callDaemon(path, options = {}) {
9409
9560
  }
9410
9561
  return response.json();
9411
9562
  }
9563
+ async function callDaemon(path, options = {}) {
9564
+ const config = await loadConfig();
9565
+ const baseUrl = getDaemonBaseUrl(config);
9566
+ return _callUrl(baseUrl, path, options, config);
9567
+ }
9568
+ async function callAuth(path, options = {}) {
9569
+ const config = await loadConfig();
9570
+ const baseUrl = getAuthBaseUrl(config);
9571
+ return _callUrl(baseUrl, path, options, config);
9572
+ }
9412
9573
  async function isDaemonRunning() {
9413
9574
  try {
9414
9575
  const config = await loadConfig();
@@ -11269,8 +11430,8 @@ var require_qrcode = __commonJS((exports) => {
11269
11430
 
11270
11431
  // node_modules/pngjs/lib/chunkstream.js
11271
11432
  var require_chunkstream = __commonJS((exports, module) => {
11272
- var util = import.meta.require("util");
11273
- var Stream = import.meta.require("stream");
11433
+ var util = __require("util");
11434
+ var Stream = __require("stream");
11274
11435
  var ChunkStream = module.exports = function() {
11275
11436
  Stream.call(this);
11276
11437
  this._buffers = [];
@@ -11626,7 +11787,7 @@ var require_filter_parse = __commonJS((exports, module) => {
11626
11787
 
11627
11788
  // node_modules/pngjs/lib/filter-parse-async.js
11628
11789
  var require_filter_parse_async = __commonJS((exports, module) => {
11629
- var util = import.meta.require("util");
11790
+ var util = __require("util");
11630
11791
  var ChunkStream = require_chunkstream();
11631
11792
  var Filter = require_filter_parse();
11632
11793
  var FilterAsync = module.exports = function(bitmapInfo) {
@@ -11740,8 +11901,7 @@ var require_parser = __commonJS((exports, module) => {
11740
11901
  this.inflateData = dependencies.inflateData;
11741
11902
  this.finished = dependencies.finished;
11742
11903
  this.simpleTransparency = dependencies.simpleTransparency;
11743
- this.headersFinished = dependencies.headersFinished || function() {
11744
- };
11904
+ this.headersFinished = dependencies.headersFinished || function() {};
11745
11905
  };
11746
11906
  Parser.prototype.start = function() {
11747
11907
  this.read(constants.PNG_SIGNATURE.length, this._parseSignature.bind(this));
@@ -11933,8 +12093,7 @@ var require_parser = __commonJS((exports, module) => {
11933
12093
  var require_bitmapper = __commonJS((exports) => {
11934
12094
  var interlaceUtils = require_interlace();
11935
12095
  var pixelBppMapper = [
11936
- function() {
11937
- },
12096
+ function() {},
11938
12097
  function(pxData, data, pxPos, rawPos) {
11939
12098
  if (rawPos === data.length) {
11940
12099
  throw new Error("Ran out of data");
@@ -11975,8 +12134,7 @@ var require_bitmapper = __commonJS((exports) => {
11975
12134
  }
11976
12135
  ];
11977
12136
  var pixelBppCustomMapper = [
11978
- function() {
11979
- },
12137
+ function() {},
11980
12138
  function(pxData, pixelData, pxPos, maxBit) {
11981
12139
  let pixel = pixelData[0];
11982
12140
  pxData[pxPos] = pixel;
@@ -12220,8 +12378,8 @@ var require_format_normaliser = __commonJS((exports, module) => {
12220
12378
 
12221
12379
  // node_modules/pngjs/lib/parser-async.js
12222
12380
  var require_parser_async = __commonJS((exports, module) => {
12223
- var util = import.meta.require("util");
12224
- var zlib = import.meta.require("zlib");
12381
+ var util = __require("util");
12382
+ var zlib = __require("zlib");
12225
12383
  var ChunkStream = require_chunkstream();
12226
12384
  var FilterAsync = require_filter_parse_async();
12227
12385
  var Parser = require_parser();
@@ -12255,8 +12413,7 @@ var require_parser_async = __commonJS((exports, module) => {
12255
12413
  }
12256
12414
  if (this._filter) {
12257
12415
  this._filter.destroy();
12258
- this._filter.on("error", function() {
12259
- });
12416
+ this._filter.on("error", function() {});
12260
12417
  }
12261
12418
  this.errord = true;
12262
12419
  };
@@ -12615,7 +12772,7 @@ var require_packer = __commonJS((exports, module) => {
12615
12772
  var CrcStream = require_crc();
12616
12773
  var bitPacker = require_bitpacker();
12617
12774
  var filter = require_filter_pack();
12618
- var zlib = import.meta.require("zlib");
12775
+ var zlib = __require("zlib");
12619
12776
  var Packer = module.exports = function(options) {
12620
12777
  this._options = options;
12621
12778
  options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
@@ -12699,8 +12856,8 @@ var require_packer = __commonJS((exports, module) => {
12699
12856
 
12700
12857
  // node_modules/pngjs/lib/packer-async.js
12701
12858
  var require_packer_async = __commonJS((exports, module) => {
12702
- var util = import.meta.require("util");
12703
- var Stream = import.meta.require("stream");
12859
+ var util = __require("util");
12860
+ var Stream = __require("stream");
12704
12861
  var constants = require_constants();
12705
12862
  var Packer = require_packer();
12706
12863
  var PackerAsync = module.exports = function(opt) {
@@ -12732,10 +12889,10 @@ var require_packer_async = __commonJS((exports, module) => {
12732
12889
 
12733
12890
  // node_modules/pngjs/lib/sync-inflate.js
12734
12891
  var require_sync_inflate = __commonJS((exports, module) => {
12735
- var assert = import.meta.require("assert").ok;
12736
- var zlib = import.meta.require("zlib");
12737
- var util = import.meta.require("util");
12738
- var kMaxLength = import.meta.require("buffer").kMaxLength;
12892
+ var assert = __require("assert").ok;
12893
+ var zlib = __require("zlib");
12894
+ var util = __require("util");
12895
+ var kMaxLength = __require("buffer").kMaxLength;
12739
12896
  function Inflate(opts) {
12740
12897
  if (!(this instanceof Inflate)) {
12741
12898
  return new Inflate(opts);
@@ -12895,8 +13052,7 @@ var require_filter_parse_sync = __commonJS((exports) => {
12895
13052
  write: function(bufferPart) {
12896
13053
  outBuffers.push(bufferPart);
12897
13054
  },
12898
- complete: function() {
12899
- }
13055
+ complete: function() {}
12900
13056
  });
12901
13057
  filter.start();
12902
13058
  reader.process();
@@ -12907,7 +13063,7 @@ var require_filter_parse_sync = __commonJS((exports) => {
12907
13063
  // node_modules/pngjs/lib/parser-sync.js
12908
13064
  var require_parser_sync = __commonJS((exports, module) => {
12909
13065
  var hasSyncZlib = true;
12910
- var zlib = import.meta.require("zlib");
13066
+ var zlib = __require("zlib");
12911
13067
  var inflateSync = require_sync_inflate();
12912
13068
  if (!zlib.deflateSync) {
12913
13069
  hasSyncZlib = false;
@@ -12993,7 +13149,7 @@ var require_parser_sync = __commonJS((exports, module) => {
12993
13149
  // node_modules/pngjs/lib/packer-sync.js
12994
13150
  var require_packer_sync = __commonJS((exports, module) => {
12995
13151
  var hasSyncZlib = true;
12996
- var zlib = import.meta.require("zlib");
13152
+ var zlib = __require("zlib");
12997
13153
  if (!zlib.deflateSync) {
12998
13154
  hasSyncZlib = false;
12999
13155
  }
@@ -13025,10 +13181,10 @@ var require_packer_sync = __commonJS((exports, module) => {
13025
13181
 
13026
13182
  // node_modules/pngjs/lib/png-sync.js
13027
13183
  var require_png_sync = __commonJS((exports) => {
13028
- var parse4 = require_parser_sync();
13184
+ var parse5 = require_parser_sync();
13029
13185
  var pack = require_packer_sync();
13030
13186
  exports.read = function(buffer, options) {
13031
- return parse4(buffer, options || {});
13187
+ return parse5(buffer, options || {});
13032
13188
  };
13033
13189
  exports.write = function(png, options) {
13034
13190
  return pack(png, options);
@@ -13037,8 +13193,8 @@ var require_png_sync = __commonJS((exports) => {
13037
13193
 
13038
13194
  // node_modules/pngjs/lib/png.js
13039
13195
  var require_png = __commonJS((exports) => {
13040
- var util = import.meta.require("util");
13041
- var Stream = import.meta.require("stream");
13196
+ var util = __require("util");
13197
+ var Stream = __require("stream");
13042
13198
  var Parser = require_parser_async();
13043
13199
  var Packer = require_packer_async();
13044
13200
  var PNGSync = require_png_sync();
@@ -13242,7 +13398,7 @@ var require_utils2 = __commonJS((exports) => {
13242
13398
 
13243
13399
  // node_modules/qrcode/lib/renderer/png.js
13244
13400
  var require_png2 = __commonJS((exports) => {
13245
- var fs = import.meta.require("fs");
13401
+ var fs = __require("fs");
13246
13402
  var PNG = require_png().PNG;
13247
13403
  var Utils = require_utils2();
13248
13404
  exports.render = function render(qrData, options) {
@@ -13366,7 +13522,7 @@ var require_utf8 = __commonJS((exports) => {
13366
13522
  cb = options;
13367
13523
  options = undefined;
13368
13524
  }
13369
- const fs = import.meta.require("fs");
13525
+ const fs = __require("fs");
13370
13526
  const utf8 = exports.render(qrData, options);
13371
13527
  fs.writeFile(path, utf8, cb);
13372
13528
  };
@@ -13540,7 +13696,7 @@ var require_svg = __commonJS((exports) => {
13540
13696
  cb = options;
13541
13697
  options = undefined;
13542
13698
  }
13543
- const fs = import.meta.require("fs");
13699
+ const fs = __require("fs");
13544
13700
  const svgTag = exports.render(qrData, options);
13545
13701
  const xmlStr = '<?xml version="1.0" encoding="utf-8"?>' + '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + svgTag;
13546
13702
  fs.writeFile(path, xmlStr, cb);
@@ -14157,8 +14313,7 @@ function renderBox(lines, width, title) {
14157
14313
  function startBarSection(sectionKey, maxLabelLen) {
14158
14314
  _sectionMaxLabelLen.set(sectionKey, maxLabelLen);
14159
14315
  }
14160
- function endBarSection(_sectionKey) {
14161
- }
14316
+ function endBarSection(_sectionKey) {}
14162
14317
  function renderBarChart(label, value, maxValue, width, color, percentageValue, sectionKey) {
14163
14318
  const safeMaxValue = Math.max(maxValue, 1);
14164
14319
  const pct = percentageValue !== undefined ? percentageValue.toFixed(1) : (value / safeMaxValue * 100).toFixed(1);
@@ -14925,7 +15080,6 @@ init_logger();
14925
15080
  import { join as join3 } from "path";
14926
15081
 
14927
15082
  // src/integrations/opencode.ts
14928
- init_logger();
14929
15083
  init_daemon_client();
14930
15084
  import { existsSync as existsSync3, mkdirSync } from "fs";
14931
15085
  import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
@@ -14933,9 +15087,9 @@ import { dirname as dirname2 } from "path";
14933
15087
  var OPENCODE_SMALL_MODEL = "routstr/minimax-m2.5";
14934
15088
  async function installOpencodeIntegration(config, apiKey, integrationConfig) {
14935
15089
  const { name, configPath } = integrationConfig;
14936
- logger.log(`
15090
+ console.log(`
14937
15091
  Installing routstr models in opencode.json...`);
14938
- logger.log(`Using API key for ${name}`);
15092
+ console.log(`Using API key for ${name}`);
14939
15093
  const baseUrl = getDaemonBaseUrl(config);
14940
15094
  let opencodeConfig;
14941
15095
  try {
@@ -14956,7 +15110,7 @@ Installing routstr models in opencode.json...`);
14956
15110
  const data = await callDaemon("/models");
14957
15111
  const models = data.output?.models || [];
14958
15112
  if (models.length === 0) {
14959
- logger.log("No models found from routstr daemon.");
15113
+ console.log("No models found from routstr daemon.");
14960
15114
  return;
14961
15115
  }
14962
15116
  const modelsObj = {};
@@ -14975,23 +15129,22 @@ Installing routstr models in opencode.json...`);
14975
15129
  };
14976
15130
  opencodeConfig.small_model = OPENCODE_SMALL_MODEL;
14977
15131
  await writeFile2(configPath, JSON.stringify(opencodeConfig, null, 2));
14978
- logger.log(`Added "routstr" provider with ${models.length} models to opencode.json`);
15132
+ console.log(`Added "routstr" provider with ${models.length} models to opencode.json`);
14979
15133
  } catch (error) {
14980
- logger.error("Failed to install models in opencode.json:", error);
15134
+ console.error("Failed to install models in opencode.json:", error);
14981
15135
  }
14982
15136
  }
14983
15137
 
14984
15138
  // src/integrations/pi.ts
14985
- init_logger();
14986
15139
  init_daemon_client();
14987
15140
  import { existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
14988
15141
  import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
14989
15142
  import { dirname as dirname3 } from "path";
14990
15143
  async function installPiIntegration(config, apiKey, integrationConfig) {
14991
15144
  const { name, configPath } = integrationConfig;
14992
- logger.log(`
15145
+ console.log(`
14993
15146
  Installing routstr models in pi models.json...`);
14994
- logger.log(`Using API key for ${name}`);
15147
+ console.log(`Using API key for ${name}`);
14995
15148
  const baseUrl = `${getDaemonBaseUrl(config)}/v1`;
14996
15149
  let piConfig = {};
14997
15150
  try {
@@ -15010,12 +15163,16 @@ Installing routstr models in pi models.json...`);
15010
15163
  const data = await callDaemon("/models");
15011
15164
  const models = data.output?.models || [];
15012
15165
  if (models.length === 0) {
15013
- logger.log("No models found from routstr daemon.");
15166
+ console.log("No models found from routstr daemon.");
15014
15167
  return;
15015
15168
  }
15016
- const providerModels = models.map((model) => ({
15017
- id: model.id
15018
- }));
15169
+ const providerModels = models.map((model) => {
15170
+ const entry = { id: model.id };
15171
+ if (model.context_length !== undefined && model.context_length > 0) {
15172
+ entry.contextWindow = model.context_length;
15173
+ }
15174
+ return entry;
15175
+ });
15019
15176
  piConfig.providers["routstr"] = {
15020
15177
  baseUrl,
15021
15178
  api: "openai-completions",
@@ -15023,14 +15180,13 @@ Installing routstr models in pi models.json...`);
15023
15180
  models: providerModels
15024
15181
  };
15025
15182
  await writeFile3(configPath, JSON.stringify(piConfig, null, 2));
15026
- logger.log(`Added "routstr" provider with ${models.length} models to pi models.json`);
15183
+ console.log(`Added "routstr" provider with ${models.length} models to pi models.json`);
15027
15184
  } catch (error) {
15028
- logger.error("Failed to install models in pi models.json:", error);
15185
+ console.error("Failed to install models in pi models.json:", error);
15029
15186
  }
15030
15187
  }
15031
15188
 
15032
15189
  // src/integrations/openclaw.ts
15033
- init_logger();
15034
15190
  init_daemon_client();
15035
15191
  import { existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
15036
15192
  import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
@@ -15040,9 +15196,9 @@ var OPENCLAW_DEFAULT_PRIMARY_MODEL = "routstr/minimax-m2.5";
15040
15196
  var OPENCLAW_DEFAULT_FALLBACK_MODEL = "routstr/kimi-k2.5";
15041
15197
  async function installOpenClawIntegration(config, apiKey, integrationConfig) {
15042
15198
  const { name, configPath } = integrationConfig;
15043
- logger.log(`
15199
+ console.log(`
15044
15200
  Installing routstr models in openclaw.json...`);
15045
- logger.log(`Using API key for ${name}`);
15201
+ console.log(`Using API key for ${name}`);
15046
15202
  const baseUrl = getDaemonBaseUrl(config);
15047
15203
  let openclawConfig = {};
15048
15204
  try {
@@ -15070,7 +15226,7 @@ Installing routstr models in openclaw.json...`);
15070
15226
  const data = await callDaemon("/models");
15071
15227
  const models = data.output?.models || [];
15072
15228
  if (models.length === 0) {
15073
- logger.log("No models found from routstr daemon.");
15229
+ console.log("No models found from routstr daemon.");
15074
15230
  return;
15075
15231
  }
15076
15232
  const providerModels = models.map((model) => ({
@@ -15099,23 +15255,22 @@ Installing routstr models in openclaw.json...`);
15099
15255
  };
15100
15256
  }
15101
15257
  await writeFile4(configPath, JSON.stringify(openclawConfig, null, 2));
15102
- logger.log(`Added "${OPENCLAW_PROVIDER_ID}" provider with ${models.length} models to openclaw.json`);
15258
+ console.log(`Added "${OPENCLAW_PROVIDER_ID}" provider with ${models.length} models to openclaw.json`);
15103
15259
  } catch (error) {
15104
- logger.error("Failed to install models in openclaw.json:", error);
15260
+ console.error("Failed to install models in openclaw.json:", error);
15105
15261
  }
15106
15262
  }
15107
15263
 
15108
15264
  // src/integrations/claudecode.ts
15109
- init_logger();
15110
15265
  init_daemon_client();
15111
15266
  import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
15112
15267
  import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
15113
15268
  import { dirname as dirname5 } from "path";
15114
15269
  async function installClaudeCodeIntegration(config, apiKey, integrationConfig) {
15115
15270
  const { name, configPath } = integrationConfig;
15116
- logger.log(`
15271
+ console.log(`
15117
15272
  Installing routstr configuration in ${configPath}...`);
15118
- logger.log(`Using API key for ${name}`);
15273
+ console.log(`Using API key for ${name}`);
15119
15274
  const baseUrl = getDaemonBaseUrl(config);
15120
15275
  let settings = {};
15121
15276
  try {
@@ -15124,7 +15279,7 @@ Installing routstr configuration in ${configPath}...`);
15124
15279
  settings = JSON.parse(content);
15125
15280
  }
15126
15281
  } catch (error) {
15127
- logger.error(`Error reading ${configPath}, creating new one.`);
15282
+ console.error(`Error reading ${configPath}, creating new one.`);
15128
15283
  }
15129
15284
  if (!settings.env) {
15130
15285
  settings.env = {};
@@ -15141,39 +15296,38 @@ Installing routstr configuration in ${configPath}...`);
15141
15296
  settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = opus.id;
15142
15297
  settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = sonnet.id;
15143
15298
  settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = haiku.id;
15144
- logger.log(`Set Claude models: Opus=${opus.id}, Sonnet=${sonnet.id}, Haiku=${haiku.id}`);
15299
+ console.log(`Set Claude models: Opus=${opus.id}, Sonnet=${sonnet.id}, Haiku=${haiku.id}`);
15145
15300
  } else if (models.length > 0) {
15146
15301
  const model = models[0];
15147
- logger.log(`Only ${models.length} models available, falling back to defaults.`);
15302
+ console.log(`Only ${models.length} models available, falling back to defaults.`);
15148
15303
  settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = model.id;
15149
15304
  settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = model.id;
15150
15305
  settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = model.id;
15151
15306
  } else {
15152
- logger.log("No models available from routstr daemon.");
15307
+ console.log("No models available from routstr daemon.");
15153
15308
  }
15154
15309
  } catch (error) {
15155
- logger.error("Failed to fetch models for Claude Code integration:", error);
15310
+ console.error("Failed to fetch models for Claude Code integration:", error);
15156
15311
  }
15157
15312
  try {
15158
15313
  mkdirSync4(dirname5(configPath), { recursive: true });
15159
15314
  await writeFile5(configPath, JSON.stringify(settings, null, 2));
15160
- logger.log(`Successfully updated ${configPath} with routstr settings.`);
15315
+ console.log(`Successfully updated ${configPath} with routstr settings.`);
15161
15316
  } catch (error) {
15162
- logger.error(`Failed to write to ${configPath}:`, error);
15317
+ console.error(`Failed to write to ${configPath}:`, error);
15163
15318
  }
15164
15319
  }
15165
15320
 
15166
15321
  // src/integrations/hermes.ts
15167
- init_logger();
15168
15322
  init_daemon_client();
15169
15323
  import { existsSync as existsSync7, mkdirSync as mkdirSync5 } from "fs";
15170
15324
  import { readFile as readFile6, writeFile as writeFile6 } from "fs/promises";
15171
15325
  import { dirname as dirname6 } from "path";
15172
15326
  async function installHermesIntegration(config, apiKey, integrationConfig) {
15173
15327
  const { name, configPath } = integrationConfig;
15174
- logger.log(`
15328
+ console.log(`
15175
15329
  Installing routstr configuration in ${configPath}...`);
15176
- logger.log(`Using API key for ${name}`);
15330
+ console.log(`Using API key for ${name}`);
15177
15331
  const baseUrl = getDaemonBaseUrl(config);
15178
15332
  const baseUrlV1 = `${baseUrl}/v1`;
15179
15333
  let defaultModel = "minimax-m2.7";
@@ -15182,16 +15336,16 @@ Installing routstr configuration in ${configPath}...`);
15182
15336
  const models = data.output?.models || [];
15183
15337
  if (models.length >= 3) {
15184
15338
  defaultModel = models[2].id;
15185
- logger.log(`Set default model to 3rd available model: ${defaultModel}`);
15339
+ console.log(`Set default model to 3rd available model: ${defaultModel}`);
15186
15340
  } else if (models.length > 0) {
15187
15341
  defaultModel = models[0].id;
15188
- logger.log(`Only ${models.length} models available, using ${defaultModel} as default.`);
15342
+ console.log(`Only ${models.length} models available, using ${defaultModel} as default.`);
15189
15343
  } else {
15190
- logger.log("No models available from routstr daemon, using fallback default.");
15344
+ console.log("No models available from routstr daemon, using fallback default.");
15191
15345
  }
15192
15346
  } catch (error) {
15193
- logger.error("Failed to fetch models for Hermes integration:", error);
15194
- logger.log("Using fallback default model.");
15347
+ console.error("Failed to fetch models for Hermes integration:", error);
15348
+ console.log("Using fallback default model.");
15195
15349
  }
15196
15350
  let content = "";
15197
15351
  try {
@@ -15199,7 +15353,7 @@ Installing routstr configuration in ${configPath}...`);
15199
15353
  content = await readFile6(configPath, "utf-8");
15200
15354
  }
15201
15355
  } catch (error) {
15202
- logger.error(`Error reading ${configPath}, creating new one.`);
15356
+ console.error(`Error reading ${configPath}, creating new one.`);
15203
15357
  }
15204
15358
  content = content.replace(/^model:\n(?: .*\n)*/gm, "");
15205
15359
  content = content.replace(/^custom_providers:\n(?:- .*\n(?: .*\n)*)*/gm, "");
@@ -15229,9 +15383,9 @@ Installing routstr configuration in ${configPath}...`);
15229
15383
  try {
15230
15384
  mkdirSync5(dirname6(configPath), { recursive: true });
15231
15385
  await writeFile6(configPath, newContent);
15232
- logger.log(`Successfully updated ${configPath} with routstr settings.`);
15386
+ console.log(`Successfully updated ${configPath} with routstr settings.`);
15233
15387
  } catch (error) {
15234
- logger.error(`Failed to write to ${configPath}:`, error);
15388
+ console.error(`Failed to write to ${configPath}:`, error);
15235
15389
  }
15236
15390
  }
15237
15391
 
@@ -15286,7 +15440,7 @@ async function runIntegrationsForClients(clientIds, config) {
15286
15440
 
15287
15441
  // src/utils/clients.ts
15288
15442
  async function getClientsList() {
15289
- const result = await callDaemon("/clients");
15443
+ const result = await callAuth("/clients");
15290
15444
  const clients = result.output?.clients;
15291
15445
  if (!clients) {
15292
15446
  return [];
@@ -15315,7 +15469,7 @@ async function addDaemonClient(name) {
15315
15469
  };
15316
15470
  return { client, created: false };
15317
15471
  }
15318
- const result = await callDaemon("/clients/add", {
15472
+ const result = await callAuth("/clients/add", {
15319
15473
  method: "POST",
15320
15474
  body: { name, id: derivedId }
15321
15475
  });
@@ -15353,7 +15507,7 @@ async function listClientsAction() {
15353
15507
  }
15354
15508
  async function deleteClientAction(id) {
15355
15509
  await ensureDaemonRunning();
15356
- const result = await callDaemon("/clients/delete", {
15510
+ const result = await callAuth("/clients/delete", {
15357
15511
  method: "POST",
15358
15512
  body: { id }
15359
15513
  });
@@ -15477,14 +15631,14 @@ function parseChoice(input) {
15477
15631
  return 1;
15478
15632
  }
15479
15633
  async function setupIntegration(config) {
15480
- logger.log(`
15634
+ console.log(`
15481
15635
  Choose an integration to set up:`);
15482
- logger.log("1. OpenCode (default)");
15483
- logger.log("2. OpenClaw");
15484
- logger.log("3. Pi");
15485
- logger.log("4. Claude Code");
15486
- logger.log("5. Hermes");
15487
- logger.log("6. Skip for now");
15636
+ console.log("1. OpenCode (default)");
15637
+ console.log("2. OpenClaw");
15638
+ console.log("3. Pi");
15639
+ console.log("4. Claude Code");
15640
+ console.log("5. Hermes");
15641
+ console.log("6. Skip for now");
15488
15642
  const answer = await ask("Select integration [1]: ");
15489
15643
  const choice = parseChoice(answer);
15490
15644
  const integrationByChoice = {
@@ -15496,15 +15650,15 @@ Choose an integration to set up:`);
15496
15650
  };
15497
15651
  const key = integrationByChoice[choice];
15498
15652
  if (!key) {
15499
- logger.log("Skipping integration setup.");
15653
+ console.log("Skipping integration setup.");
15500
15654
  return;
15501
15655
  }
15502
15656
  const integrationConfig = CLIENT_CONFIGS[key];
15503
15657
  const { client, created } = await addDaemonClient(integrationConfig.name);
15504
15658
  if (created) {
15505
- logger.log(`Created new API key for ${integrationConfig.name}`);
15659
+ console.log(`Created new API key for ${integrationConfig.name}`);
15506
15660
  } else {
15507
- logger.log(`Using existing API key for ${integrationConfig.name}`);
15661
+ console.log(`Using existing API key for ${integrationConfig.name}`);
15508
15662
  }
15509
15663
  if (key === "opencode") {
15510
15664
  await installOpencodeIntegration(config, client.apiKey, integrationConfig);
@@ -15629,7 +15783,7 @@ async function isCocodInstalled(cocodPath) {
15629
15783
  // package.json
15630
15784
  var package_default = {
15631
15785
  name: "routstrd",
15632
- version: "0.2.22",
15786
+ version: "0.3.1",
15633
15787
  module: "src/index.ts",
15634
15788
  type: "module",
15635
15789
  private: false,
@@ -15653,9 +15807,10 @@ var package_default = {
15653
15807
  },
15654
15808
  dependencies: {
15655
15809
  "@cashu/cashu-ts": "^4.3.0",
15656
- "@routstr/sdk": "^0.3.8",
15810
+ "@routstr/sdk": "^0.3.9",
15657
15811
  "applesauce-core": "^5.1.0",
15658
15812
  "applesauce-relay": "^5.1.0",
15813
+ "applesauce-wallet-connect": "^6.0.0",
15659
15814
  commander: "^14.0.2",
15660
15815
  "nostr-tools": "^2.12.0",
15661
15816
  qrcode: "^1.5.4",
@@ -15687,17 +15842,17 @@ Invoice:
15687
15842
  ${invoice}`);
15688
15843
  }
15689
15844
  async function installCocodOrExit() {
15690
- logger.log("cocod not found. Installing globally with bun...");
15845
+ console.log("cocod not found. Installing globally with bun...");
15691
15846
  const installProc = Bun.spawn(["bun", "install", "--global", "@routstr/cocod"], {
15692
15847
  stdout: "inherit",
15693
15848
  stderr: "inherit"
15694
15849
  });
15695
15850
  const installCode = await installProc.exited;
15696
15851
  if (installCode !== 0 || !await isCocodInstalled()) {
15697
- logger.error("Failed to install cocod. Please run 'bun install --global @routstr/cocod' manually.");
15852
+ console.error("Failed to install cocod. Please run 'bun install --global @routstr/cocod' manually.");
15698
15853
  throw new Error("cocod installation failed");
15699
15854
  }
15700
- logger.log("cocod installed successfully.");
15855
+ console.log("cocod installed successfully.");
15701
15856
  }
15702
15857
  async function requireLocalDaemon() {
15703
15858
  const config = await loadConfig();
@@ -15707,10 +15862,10 @@ async function requireLocalDaemon() {
15707
15862
  }
15708
15863
  }
15709
15864
  async function initDaemon() {
15710
- logger.log("Initializing routstrd...");
15865
+ console.log("Initializing routstrd...");
15711
15866
  if (!existsSync9(CONFIG_DIR)) {
15712
15867
  mkdirSync6(CONFIG_DIR, { recursive: true });
15713
- logger.log(`Created config directory: ${CONFIG_DIR}`);
15868
+ console.log(`Created config directory: ${CONFIG_DIR}`);
15714
15869
  }
15715
15870
  if (!existsSync9(CONFIG_FILE)) {
15716
15871
  const config2 = {
@@ -15718,7 +15873,7 @@ async function initDaemon() {
15718
15873
  cocodPath: null
15719
15874
  };
15720
15875
  await Bun.write(CONFIG_FILE, JSON.stringify(config2, null, 2));
15721
- logger.log(`Created config file: ${CONFIG_FILE}`);
15876
+ console.log(`Created config file: ${CONFIG_FILE}`);
15722
15877
  }
15723
15878
  const config = await loadConfig();
15724
15879
  if (!await isCocodInstalled(config.cocodPath)) {
@@ -15761,27 +15916,27 @@ Initializing cocod...`);
15761
15916
  ${initStderr}`.toLowerCase();
15762
15917
  const alreadyInitialized = combinedOutput.includes("already initialized");
15763
15918
  if (initCode !== 0 && !alreadyInitialized) {
15764
- logger.error("Failed to initialize cocod. Please run 'cocod init' manually.");
15919
+ console.error("Failed to initialize cocod. Please run 'cocod init' manually.");
15765
15920
  return;
15766
15921
  }
15767
15922
  if (alreadyInitialized) {
15768
- logger.log("cocod is already initialized.");
15923
+ console.log("cocod is already initialized.");
15769
15924
  } else {
15770
- logger.log("cocod initialized successfully.");
15925
+ console.log("cocod initialized successfully.");
15771
15926
  }
15772
15927
  await startDaemon({ port: String(config.port || 8008) });
15773
15928
  await setupIntegration(config);
15774
- logger.log(`
15929
+ console.log(`
15775
15930
  Initialization complete!`);
15776
- logger.log(`
15931
+ console.log(`
15777
15932
  use 'routstrd receive <cashu-token>' or 'routstrd receive 2100' to top up your local wallet using Lightning!`);
15778
- logger.log(`
15933
+ console.log(`
15779
15934
  full wallet commands still work too, e.g. 'routstrd wallet receive cashu <token>' and 'routstrd wallet receive bolt11 2100'.`);
15780
- logger.log(`
15935
+ console.log(`
15781
15936
  To ensure routstrd persists across system restarts, run: 'routstrd service install'`);
15782
15937
  }
15783
15938
  program.name("routstrd").description("Routstr daemon - Manage routstr processes").version(package_default.version, "--version", "output the version number");
15784
- program.command("refund").description("Refund pending tokens and API keys to a specified mint").option("-m, --mint-url <mintUrl>", "Mint URL to refund to (defaults to first mint in wallet)").option("-y, --yes", "Skip confirmation prompt", false).action(async (options) => {
15939
+ program.command("refund").description("Refund pending tokens and API keys to a specified mint").option("-m, --mint-url <mintUrl>", "Mint URL to refund to (defaults to first mint in wallet)").option("-y, --yes", "Skip confirmation prompt", false).option("--xcashu", "Refund xcashu tokens only (uses refundXcashuTokens)", false).action(async (options) => {
15785
15940
  await ensureDaemonRunning();
15786
15941
  let mintUrl = options.mintUrl;
15787
15942
  if (!mintUrl) {
@@ -15799,6 +15954,27 @@ program.command("refund").description("Refund pending tokens and API keys to a s
15799
15954
  console.log(`Using mint URL: ${mintUrl}`);
15800
15955
  }
15801
15956
  try {
15957
+ if (options.xcashu) {
15958
+ const result2 = await callDaemon("/refund/xcashu", {
15959
+ method: "POST",
15960
+ body: { mintUrl }
15961
+ });
15962
+ if (result2.error) {
15963
+ console.log(result2.error);
15964
+ process.exit(1);
15965
+ }
15966
+ const output2 = result2.output;
15967
+ if (output2) {
15968
+ console.log(output2.message);
15969
+ console.log(`
15970
+ Results:`);
15971
+ for (const r of output2.results) {
15972
+ const status = r.success ? "success" : `failed: ${r.error || "unknown"}`;
15973
+ console.log(` - ${r.baseUrl}: ${status}`);
15974
+ }
15975
+ }
15976
+ return;
15977
+ }
15802
15978
  const result = await callDaemon("/refund", {
15803
15979
  method: "POST",
15804
15980
  body: { mintUrl }
@@ -15829,18 +16005,29 @@ Results:`);
15829
16005
  process.exit(1);
15830
16006
  }
15831
16007
  });
15832
- program.command("remote <url>").description("Configure a remote daemon URL").action(async (url) => {
16008
+ program.command("remote <url>").description("Configure a remote daemon URL").option("--auth-url <authUrl>", "URL of the auth proxy for management commands (npubs, clients, usage)").action(async (url, options) => {
15833
16009
  try {
15834
16010
  new URL(url);
15835
16011
  } catch {
15836
16012
  console.error(`Invalid URL: ${url}`);
15837
16013
  process.exit(1);
15838
16014
  }
16015
+ if (options.authUrl) {
16016
+ try {
16017
+ new URL(options.authUrl);
16018
+ } catch {
16019
+ console.error(`Invalid auth URL: ${options.authUrl}`);
16020
+ process.exit(1);
16021
+ }
16022
+ }
15839
16023
  if (!existsSync9(CONFIG_DIR)) {
15840
16024
  mkdirSync6(CONFIG_DIR, { recursive: true });
15841
16025
  }
15842
16026
  const config = await loadConfig();
15843
16027
  const updates = { daemonUrl: url };
16028
+ if (options.authUrl) {
16029
+ updates.authUrl = options.authUrl;
16030
+ }
15844
16031
  let generatedNpub;
15845
16032
  if (!config.nsec) {
15846
16033
  const secretKey = generateSecretKey();
@@ -15855,6 +16042,9 @@ program.command("remote <url>").description("Configure a remote daemon URL").act
15855
16042
  };
15856
16043
  await Bun.write(CONFIG_FILE, JSON.stringify(updatedConfig, null, 2));
15857
16044
  console.log(`Remote daemon URL set to: ${url}`);
16045
+ if (options.authUrl) {
16046
+ console.log(`Auth proxy URL set to: ${options.authUrl}`);
16047
+ }
15858
16048
  if (generatedNpub) {
15859
16049
  console.log(`
15860
16050
  A new Nostr identity has been generated for remote authentication.`);
@@ -16032,7 +16222,7 @@ program.command("usage").description("Show recent usage logs and total sats cost
16032
16222
  await ensureDaemonRunning();
16033
16223
  const requested = Number.parseInt(options.limit, 10);
16034
16224
  const limit = Number.isFinite(requested) && requested > 0 ? Math.min(requested, 1000) : 10;
16035
- const result = await callDaemon(`/usage?limit=${limit}`);
16225
+ const result = await callAuth(`/usage?limit=${limit}`);
16036
16226
  if (result.error) {
16037
16227
  console.log(result.error);
16038
16228
  process.exit(1);
@@ -16139,7 +16329,7 @@ npubsCmd.command("list").description("List configured npubs with their roles").a
16139
16329
  await ensureDaemonRunning();
16140
16330
  const config = await loadConfig();
16141
16331
  const userNpub = getUserNpub(config);
16142
- const result = await callDaemon("/npubs");
16332
+ const result = await callAuth("/npubs");
16143
16333
  if (result.error) {
16144
16334
  console.log(result.error);
16145
16335
  process.exit(1);
@@ -16172,7 +16362,7 @@ npubsCmd.command("register").description("Register yourself as the first admin (
16172
16362
  console.error("No Nostr identity configured. Run 'routstrd remote <url>' to set one up.");
16173
16363
  process.exit(1);
16174
16364
  }
16175
- const result = await callDaemon("/npubs");
16365
+ const result = await callAuth("/npubs");
16176
16366
  if (result.error) {
16177
16367
  console.log(result.error);
16178
16368
  process.exit(1);
@@ -16189,7 +16379,7 @@ npubsCmd.command("register").description("Register yourself as the first admin (
16189
16379
  console.error("Failed to normalize user npub.");
16190
16380
  process.exit(1);
16191
16381
  }
16192
- const addResult = await callDaemon("/npubs", {
16382
+ const addResult = await callAuth("/npubs", {
16193
16383
  method: "POST",
16194
16384
  body: { npub: npubFromPubkey(normalized) }
16195
16385
  });
@@ -16216,7 +16406,7 @@ npubsCmd.command("add <npub>").description("Add a npub (hex pubkey or npub1...).
16216
16406
  process.exit(1);
16217
16407
  }
16218
16408
  const body = { npub: npubFromPubkey(normalized), role: options.role };
16219
- const result = await callDaemon("/npubs", {
16409
+ const result = await callAuth("/npubs", {
16220
16410
  method: "POST",
16221
16411
  body
16222
16412
  });
@@ -16240,7 +16430,7 @@ npubsCmd.command("update <npub>").description("Update the role of an existing np
16240
16430
  console.error("Invalid role. Expected 'admin' or 'user'.");
16241
16431
  process.exit(1);
16242
16432
  }
16243
- const result = await callDaemon("/npubs", {
16433
+ const result = await callAuth("/npubs", {
16244
16434
  method: "PATCH",
16245
16435
  body: { npub: npubFromPubkey(normalized), role: options.role }
16246
16436
  });
@@ -16262,7 +16452,7 @@ npubsCmd.command("delete <npub>").description("Delete an npub (hex pubkey or npu
16262
16452
  console.error("Invalid npub value. Use npub1... or 64-char hex pubkey.");
16263
16453
  process.exit(1);
16264
16454
  }
16265
- const result = await callDaemon(`/npubs/${encodeURIComponent(npubFromPubkey(normalized))}`, {
16455
+ const result = await callAuth(`/npubs/${encodeURIComponent(npubFromPubkey(normalized))}`, {
16266
16456
  method: "DELETE"
16267
16457
  });
16268
16458
  if (result.error) {
@@ -16407,6 +16597,65 @@ walletMintsCmd.command("info <url>").description("Get wallet mint info").action(
16407
16597
  body: { url }
16408
16598
  });
16409
16599
  });
16600
+ var nwcCmd = program.command("nwc").description("Manage NWC (Nostr Wallet Connect) integration");
16601
+ nwcCmd.command("connect").description("Connect to a Lightning wallet via NWC").argument("[connection-string]", "NWC connection string (nostr+walletconnect://...)").action(async (connectionString) => {
16602
+ if (!connectionString) {
16603
+ const rl = __require("readline").createInterface({
16604
+ input: process.stdin,
16605
+ output: process.stdout
16606
+ });
16607
+ connectionString = await new Promise((resolve) => {
16608
+ rl.question("Paste your NWC connection string: ", (answer) => {
16609
+ rl.close();
16610
+ resolve(answer.trim());
16611
+ });
16612
+ });
16613
+ }
16614
+ if (!/^nostr\+walletconnect:\/\/[0-9a-fA-F]{64}\?relay=/.test(connectionString)) {
16615
+ console.error("Invalid NWC connection string: expected nostr+walletconnect://<64-char-hex>?relay=...");
16616
+ process.exit(1);
16617
+ }
16618
+ await handleDaemonCommand("/nwc/connect", {
16619
+ method: "POST",
16620
+ body: { connectionString }
16621
+ });
16622
+ });
16623
+ nwcCmd.command("disconnect").description("Disconnect from NWC wallet").action(async () => {
16624
+ await handleDaemonCommand("/nwc/disconnect", {
16625
+ method: "POST"
16626
+ });
16627
+ });
16628
+ nwcCmd.command("status").description("Show NWC connection status and wallet info").action(async () => {
16629
+ await handleDaemonCommand("/nwc/status");
16630
+ });
16631
+ nwcCmd.command("fund <amount>").description("Manually fund the Cashu wallet from the connected NWC wallet").action(async (amount) => {
16632
+ const parsedAmount = parsePositiveIntOrExit(amount, "amount");
16633
+ await handleDaemonCommand("/nwc/fund", {
16634
+ method: "POST",
16635
+ body: { amount: parsedAmount }
16636
+ });
16637
+ });
16638
+ var autoRefillCmd = nwcCmd.command("auto-refill").description("Manage automatic wallet refill from NWC");
16639
+ autoRefillCmd.command("on").description("Enable auto-refill").option("--threshold <sats>", "Refill when Cashu balance drops below this many sats", "500").option("--amount <sats>", "Refill this many sats at a time", "1000").option("--cooldown <seconds>", "Minimum time between refills in seconds", "300").action(async (options) => {
16640
+ const threshold = parsePositiveIntOrExit(options.threshold, "threshold");
16641
+ const amount = parsePositiveIntOrExit(options.amount, "amount");
16642
+ const cooldownSec = parsePositiveIntOrExit(options.cooldown, "cooldown");
16643
+ await handleDaemonCommand("/nwc/auto-refill", {
16644
+ method: "POST",
16645
+ body: {
16646
+ enabled: true,
16647
+ threshold,
16648
+ amount,
16649
+ cooldownMs: cooldownSec * 1000
16650
+ }
16651
+ });
16652
+ });
16653
+ autoRefillCmd.command("off").description("Disable auto-refill").action(async () => {
16654
+ await handleDaemonCommand("/nwc/auto-refill", {
16655
+ method: "POST",
16656
+ body: { enabled: false }
16657
+ });
16658
+ });
16410
16659
  program.command("stop").description("Stop the background daemon").action(async () => {
16411
16660
  await handleDaemonCommand("/stop", { method: "POST" });
16412
16661
  });
@@ -16428,7 +16677,7 @@ serviceCmd.command("install").description("Install and start routstrd using PM2
16428
16677
  try {
16429
16678
  daemonPath = Bun.resolveSync("./daemon/index.js", import.meta.url);
16430
16679
  } catch (e) {
16431
- const path = import.meta.require("path");
16680
+ const path = __require("path");
16432
16681
  daemonPath = path.join(path.dirname(import.meta.url).replace("file://", ""), "daemon", "index.js");
16433
16682
  }
16434
16683
  if (!existsSync9(daemonPath)) {
@@ -16465,8 +16714,7 @@ serviceCmd.command("uninstall").description("Stop and remove routstrd from PM2")
16465
16714
  serviceCmd.command("logs").description("View PM2 logs for routstrd").action(() => {
16466
16715
  try {
16467
16716
  execSync("pm2 logs routstrd", { stdio: "inherit" });
16468
- } catch (e) {
16469
- }
16717
+ } catch (e) {}
16470
16718
  });
16471
16719
  program.command("restart").description("Restart the background daemon").option("--port <port>", "Port to listen on").option("-p, --provider <provider>", "Default provider to use").action(async (options) => {
16472
16720
  await requireLocalDaemon();
@@ -16507,7 +16755,7 @@ program.command("mode").description("Set the client mode (lazyrefund/apikeys or
16507
16755
  Current mode: ${currentMode}`);
16508
16756
  const modes = ["apikeys", "xcashu"];
16509
16757
  const selectedIndex = await new Promise((resolve) => {
16510
- const rl = import.meta.require("readline").createInterface({
16758
+ const rl = __require("readline").createInterface({
16511
16759
  input: process.stdin,
16512
16760
  output: process.stdout
16513
16761
  });