routstrd 0.2.13 → 0.2.14

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/bun.lock CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
- "lockfileVersion": 0,
2
+ "lockfileVersion": 1,
3
+ "configVersion": 0,
3
4
  "workspaces": {
4
5
  "": {
5
6
  "dependencies": {
@@ -8,6 +9,7 @@
8
9
  "applesauce-core": "^5.1.0",
9
10
  "applesauce-relay": "^5.1.0",
10
11
  "commander": "^14.0.2",
12
+ "nostr-tools": "^2.12.0",
11
13
  "qrcode": "^1.5.4",
12
14
  "rxjs": "^7.8.1",
13
15
  "zustand": "^5.0.5",
@@ -35401,12 +35401,6 @@ async function sha256Hex(data) {
35401
35401
  function base64EncodeUtf8(value) {
35402
35402
  return btoa(String.fromCharCode(...new TextEncoder().encode(value)));
35403
35403
  }
35404
- function npubFromPubkey(pubkey) {
35405
- return nip19_exports.npubEncode(pubkey.toLowerCase());
35406
- }
35407
- function npubFromSecretKey(secretKey) {
35408
- return npubFromPubkey(getPublicKey2(secretKey));
35409
- }
35410
35404
  async function createNIP98Authorization(secretKey, url2, method, body) {
35411
35405
  const tags3 = [
35412
35406
  ["u", url2],
@@ -35745,24 +35739,6 @@ async function runIntegrationsForClients(clientIds, config) {
35745
35739
  }
35746
35740
 
35747
35741
  // src/utils/clients.ts
35748
- function getNpubSuffix(config) {
35749
- if (!config.daemonUrl || !config.nsec)
35750
- return null;
35751
- try {
35752
- const secretKey = parseSecretKey(config.nsec);
35753
- const npub = npubFromSecretKey(secretKey);
35754
- return npub.slice(-7);
35755
- } catch {
35756
- return null;
35757
- }
35758
- }
35759
- function removeSuffixFromId(id, suffix) {
35760
- const suffixStr = `-${suffix}`;
35761
- if (id.endsWith(suffixStr)) {
35762
- return id.slice(0, -suffixStr.length);
35763
- }
35764
- return id;
35765
- }
35766
35742
  function getClientsFromStore(store) {
35767
35743
  const state = store.getState();
35768
35744
  const clientIds = state.clientIds || [];
@@ -35771,23 +35747,23 @@ function getClientsFromStore(store) {
35771
35747
  name: c.name,
35772
35748
  apiKey: c.apiKey,
35773
35749
  createdAt: c.createdAt,
35774
- lastUsed: c.lastUsed
35750
+ lastUsed: c.lastUsed,
35751
+ ownerNpub: c.ownerNpub
35775
35752
  }));
35776
35753
  }
35777
35754
  async function getClientsList() {
35778
- const config = await loadConfig();
35779
35755
  const result = await callDaemon("/clients");
35780
35756
  const clients = result.output?.clients;
35781
35757
  if (!clients) {
35782
35758
  return [];
35783
35759
  }
35784
- const suffix = config.daemonUrl ? getNpubSuffix(config) : null;
35785
- return clients.filter((c) => !suffix || c.id.endsWith(`-${suffix}`)).map((c) => ({
35786
- clientId: suffix ? removeSuffixFromId(c.id, suffix) : c.id,
35760
+ return clients.map((c) => ({
35761
+ clientId: c.id,
35787
35762
  name: c.name,
35788
35763
  apiKey: c.apiKey,
35789
35764
  createdAt: c.createdAt,
35790
- lastUsed: c.lastUsed
35765
+ lastUsed: c.lastUsed,
35766
+ ownerNpub: c.ownerNpub
35791
35767
  }));
35792
35768
  }
35793
35769
 
@@ -36277,7 +36253,8 @@ function createDaemonRequestHandler(deps) {
36277
36253
  name: c.name,
36278
36254
  apiKey: c.apiKey,
36279
36255
  createdAt: c.createdAt,
36280
- lastUsed: c.lastUsed
36256
+ lastUsed: c.lastUsed,
36257
+ ownerNpub: c.ownerNpub
36281
36258
  }));
36282
36259
  res.writeHead(200, { "Content-Type": "application/json" });
36283
36260
  res.end(JSON.stringify({
@@ -36298,6 +36275,7 @@ function createDaemonRequestHandler(deps) {
36298
36275
  const body = bodyText ? JSON.parse(bodyText) : {};
36299
36276
  const name = body.name;
36300
36277
  const explicitId = body.id;
36278
+ const ownerNpub = body.ownerNpub;
36301
36279
  if (!name || typeof name !== "string" || name.trim() === "") {
36302
36280
  res.writeHead(400, { "Content-Type": "application/json" });
36303
36281
  res.end(JSON.stringify({
@@ -36335,7 +36313,8 @@ function createDaemonRequestHandler(deps) {
36335
36313
  clientId,
36336
36314
  name: name.trim(),
36337
36315
  apiKey,
36338
- createdAt: Date.now()
36316
+ createdAt: Date.now(),
36317
+ ...ownerNpub && typeof ownerNpub === "string" ? { ownerNpub } : {}
36339
36318
  };
36340
36319
  deps.store.getState().setClientIds((prev) => [
36341
36320
  ...prev || [],
@@ -36350,7 +36329,8 @@ function createDaemonRequestHandler(deps) {
36350
36329
  id: clientId,
36351
36330
  name: name.trim(),
36352
36331
  apiKey,
36353
- createdAt: newClient.createdAt
36332
+ createdAt: newClient.createdAt,
36333
+ ownerNpub: newClient.ownerNpub
36354
36334
  }
36355
36335
  }
36356
36336
  }));
package/dist/index.js CHANGED
@@ -9570,12 +9570,6 @@ function getUserNpub(config) {
9570
9570
  return null;
9571
9571
  }
9572
9572
  }
9573
- function getNpubSuffix(config) {
9574
- const npub = getUserNpub(config);
9575
- if (!npub)
9576
- return null;
9577
- return npub.slice(-7);
9578
- }
9579
9573
  async function startDaemonProcess() {
9580
9574
  const config = await loadConfig();
9581
9575
  await startDaemon({
@@ -13897,13 +13891,7 @@ async function fetchUsage(limit2 = 1e4) {
13897
13891
  if (result.error)
13898
13892
  return null;
13899
13893
  const entries = result.output;
13900
- const entriesArray = Array.isArray(entries) ? entries : [];
13901
- const suffix = getNpubSuffix(await loadConfig());
13902
- const suffixStr = suffix ? `-${suffix}` : null;
13903
- const visibleEntries = suffixStr ? entriesArray.filter((entry) => entry.client?.endsWith(suffixStr)).map((entry) => ({
13904
- ...entry,
13905
- client: entry.client?.slice(0, -suffixStr.length)
13906
- })) : entriesArray;
13894
+ const visibleEntries = Array.isArray(entries) ? entries : [];
13907
13895
  const totals = visibleEntries.reduce((acc, entry) => ({
13908
13896
  promptTokens: acc.promptTokens + entry.promptTokens,
13909
13897
  completionTokens: acc.completionTokens + entry.completionTokens,
@@ -14914,7 +14902,6 @@ init_daemon_client();
14914
14902
 
14915
14903
  // src/utils/clients.ts
14916
14904
  init_daemon_client();
14917
- init_nip98();
14918
14905
  init_logger();
14919
14906
 
14920
14907
  // src/integrations/registry.ts
@@ -15203,41 +15190,19 @@ async function runIntegrationsForClients(clientIds, config) {
15203
15190
  }
15204
15191
 
15205
15192
  // src/utils/clients.ts
15206
- function getNpubSuffix2(config) {
15207
- if (!config.daemonUrl || !config.nsec)
15208
- return null;
15209
- try {
15210
- const secretKey = parseSecretKey(config.nsec);
15211
- const npub = npubFromSecretKey(secretKey);
15212
- return npub.slice(-7);
15213
- } catch {
15214
- return null;
15215
- }
15216
- }
15217
- function addSuffixToId(id, suffix) {
15218
- return `${id}-${suffix}`;
15219
- }
15220
- function removeSuffixFromId(id, suffix) {
15221
- const suffixStr = `-${suffix}`;
15222
- if (id.endsWith(suffixStr)) {
15223
- return id.slice(0, -suffixStr.length);
15224
- }
15225
- return id;
15226
- }
15227
15193
  async function getClientsList() {
15228
- const config = await loadConfig();
15229
15194
  const result = await callDaemon("/clients");
15230
15195
  const clients = result.output?.clients;
15231
15196
  if (!clients) {
15232
15197
  return [];
15233
15198
  }
15234
- const suffix = config.daemonUrl ? getNpubSuffix2(config) : null;
15235
- return clients.filter((c) => !suffix || c.id.endsWith(`-${suffix}`)).map((c) => ({
15236
- clientId: suffix ? removeSuffixFromId(c.id, suffix) : c.id,
15199
+ return clients.map((c) => ({
15200
+ clientId: c.id,
15237
15201
  name: c.name,
15238
15202
  apiKey: c.apiKey,
15239
15203
  createdAt: c.createdAt,
15240
- lastUsed: c.lastUsed
15204
+ lastUsed: c.lastUsed,
15205
+ ownerNpub: c.ownerNpub
15241
15206
  }));
15242
15207
  }
15243
15208
  async function addDaemonClient(name) {
@@ -15250,16 +15215,14 @@ async function addDaemonClient(name) {
15250
15215
  name: existing.name,
15251
15216
  apiKey: existing.apiKey,
15252
15217
  createdAt: existing.createdAt,
15253
- lastUsed: existing.lastUsed
15218
+ lastUsed: existing.lastUsed,
15219
+ ownerNpub: existing.ownerNpub
15254
15220
  };
15255
15221
  return { client, created: false };
15256
15222
  }
15257
- const config = await loadConfig();
15258
- const suffix = getNpubSuffix2(config);
15259
- const clientId = suffix ? addSuffixToId(derivedId, suffix) : derivedId;
15260
15223
  const result = await callDaemon("/clients/add", {
15261
15224
  method: "POST",
15262
- body: { name, id: clientId }
15225
+ body: { name, id: derivedId }
15263
15226
  });
15264
15227
  const output4 = result.output;
15265
15228
  if (!output4?.client?.apiKey) {
@@ -15295,12 +15258,9 @@ async function listClientsAction() {
15295
15258
  }
15296
15259
  async function deleteClientAction(id) {
15297
15260
  await ensureDaemonRunning();
15298
- const config = await loadConfig();
15299
- const suffix = getNpubSuffix2(config);
15300
- const resolvedId = suffix ? addSuffixToId(id, suffix) : id;
15301
15261
  const result = await callDaemon("/clients/delete", {
15302
15262
  method: "POST",
15303
- body: { id: resolvedId }
15263
+ body: { id }
15304
15264
  });
15305
15265
  if (result.error) {
15306
15266
  console.log(result.error);
@@ -15314,7 +15274,6 @@ async function deleteClientAction(id) {
15314
15274
  async function addClientAction(options) {
15315
15275
  await ensureDaemonRunning();
15316
15276
  const config = await loadConfig();
15317
- const suffix = getNpubSuffix2(config);
15318
15277
  const integrationKeys = [];
15319
15278
  if (options.opencode)
15320
15279
  integrationKeys.push("opencode");
@@ -15340,7 +15299,7 @@ async function addClientAction(options) {
15340
15299
  await integrationFn(config, client.apiKey, integrationConfig);
15341
15300
  console.log(`
15342
15301
  ${integrationConfig.name}:`);
15343
- console.log(` Client ID: ${suffix ? removeSuffixFromId(client.id, suffix) : client.id}`);
15302
+ console.log(` Client ID: ${client.id}`);
15344
15303
  console.log(` API Key: ${client.apiKey}`);
15345
15304
  } catch (error) {
15346
15305
  logger.error(`Failed to set up ${integrationConfig.name} integration:`, error);
@@ -15360,7 +15319,7 @@ async function addClientAction(options) {
15360
15319
  if (!created) {
15361
15320
  console.log(`Client '${options.name}' already exists.`);
15362
15321
  console.log(`
15363
- ID: ${suffix ? removeSuffixFromId(client.id, suffix) : client.id}`);
15322
+ ID: ${client.id}`);
15364
15323
  console.log(` Name: ${client.name}`);
15365
15324
  console.log(` API Key: ${client.apiKey}`);
15366
15325
  return;
@@ -15369,7 +15328,7 @@ async function addClientAction(options) {
15369
15328
  console.log(message);
15370
15329
  }
15371
15330
  console.log(`
15372
- ID: ${suffix ? removeSuffixFromId(client.id, suffix) : client.id}`);
15331
+ ID: ${client.id}`);
15373
15332
  console.log(` Name: ${client.name}`);
15374
15333
  console.log(` API Key: ${client.apiKey}`);
15375
15334
  console.log(`
@@ -15558,7 +15517,7 @@ async function isCocodInstalled(cocodPath) {
15558
15517
  // package.json
15559
15518
  var package_default = {
15560
15519
  name: "routstrd",
15561
- version: "0.2.13",
15520
+ version: "0.2.14",
15562
15521
  module: "src/index.ts",
15563
15522
  type: "module",
15564
15523
  private: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "routstrd",
3
- "version": "0.2.13",
3
+ "version": "0.2.14",
4
4
  "module": "src/index.ts",
5
5
  "type": "module",
6
6
  "private": false,
package/src/cli.ts CHANGED
@@ -7,7 +7,6 @@ import {
7
7
  isDaemonRunning,
8
8
  loadConfig,
9
9
  getDaemonBaseUrl,
10
- getNpubSuffix,
11
10
  getUserNpub,
12
11
  } from "./utils/daemon-client";
13
12
  import {
@@ -1,5 +1,5 @@
1
1
  import type { UsageTrackingEntry } from "../../daemon/types.ts";
2
- import { callDaemon, getNpubSuffix, isDaemonRunning, loadConfig } from "../../utils/daemon-client.ts";
2
+ import { callDaemon, isDaemonRunning } from "../../utils/daemon-client.ts";
3
3
  import type { ClientStats, DayStats, ModelStats, ProviderStats, UsageStats } from "./types.ts";
4
4
 
5
5
  export interface BalanceKey {
@@ -82,21 +82,10 @@ export async function fetchUsage(limit = 10000): Promise<UsageStats | null> {
82
82
  const result = await callDaemon(`/usage?limit=${limit}`);
83
83
  if (result.error) return null;
84
84
 
85
- // The daemon returns { output: [...] } where output is the entries array directly.
86
- // In remote daemon mode, client IDs are suffixed with the last 7 chars of our npub.
87
- // Fetch the full daemon result, but only display/aggregate entries for our clients.
85
+ // The auth proxy filters usage to the authenticated npub's clients and
86
+ // returns client IDs without the owner suffix.
88
87
  const entries = result.output as UsageTrackingEntry[] | undefined;
89
- const entriesArray = Array.isArray(entries) ? entries : [];
90
- const suffix = getNpubSuffix(await loadConfig());
91
- const suffixStr = suffix ? `-${suffix}` : null;
92
- const visibleEntries = suffixStr
93
- ? entriesArray
94
- .filter((entry) => entry.client?.endsWith(suffixStr))
95
- .map((entry) => ({
96
- ...entry,
97
- client: entry.client?.slice(0, -suffixStr.length),
98
- }))
99
- : entriesArray;
88
+ const visibleEntries = Array.isArray(entries) ? entries : [];
100
89
 
101
90
  // Calculate totals from visible entries
102
91
  const totals = visibleEntries.reduce(
@@ -4,49 +4,16 @@ import {
4
4
  getDaemonBaseUrl,
5
5
  ensureDaemonRunning,
6
6
  } from "./daemon-client";
7
- import {
8
- parseSecretKey,
9
- npubFromSecretKey,
10
- } from "./nip98";
11
- import { type RoutstrdConfig } from "./config";
12
7
  import { logger } from "./logger";
13
8
  import { CLIENT_INTEGRATIONS, CLIENT_CONFIGS } from "../integrations/registry";
14
9
 
15
- export function getNpubSuffix(config: RoutstrdConfig): string | null {
16
- if (!config.daemonUrl || !config.nsec) return null;
17
- try {
18
- const secretKey = parseSecretKey(config.nsec);
19
- const npub = npubFromSecretKey(secretKey);
20
- return npub.slice(-7);
21
- } catch {
22
- return null;
23
- }
24
- }
25
-
26
- /**
27
- * Add suffix to a client ID.
28
- */
29
- export function addSuffixToId(id: string, suffix: string): string {
30
- return `${id}-${suffix}`;
31
- }
32
-
33
- /**
34
- * Remove suffix from a client ID if present.
35
- */
36
- export function removeSuffixFromId(id: string, suffix: string): string {
37
- const suffixStr = `-${suffix}`;
38
- if (id.endsWith(suffixStr)) {
39
- return id.slice(0, -suffixStr.length);
40
- }
41
- return id;
42
- }
43
-
44
10
  export interface ClientEntry {
45
11
  clientId: string;
46
12
  name: string;
47
13
  apiKey: string;
48
14
  createdAt: number;
49
15
  lastUsed?: number | null;
16
+ ownerNpub?: string;
50
17
  }
51
18
 
52
19
  export interface DaemonClient {
@@ -55,6 +22,7 @@ export interface DaemonClient {
55
22
  apiKey: string;
56
23
  createdAt: number;
57
24
  lastUsed?: number | null;
25
+ ownerNpub?: string;
58
26
  }
59
27
 
60
28
  /**
@@ -71,12 +39,14 @@ export function getClientsFromStore(store: { getState(): any }): ClientEntry[] {
71
39
  apiKey: string;
72
40
  createdAt: number;
73
41
  lastUsed?: number | null;
42
+ ownerNpub?: string;
74
43
  }) => ({
75
44
  clientId: c.clientId,
76
45
  name: c.name,
77
46
  apiKey: c.apiKey,
78
47
  createdAt: c.createdAt,
79
48
  lastUsed: c.lastUsed,
49
+ ownerNpub: c.ownerNpub,
80
50
  }),
81
51
  );
82
52
  }
@@ -86,7 +56,6 @@ export function getClientsFromStore(store: { getState(): any }): ClientEntry[] {
86
56
  * Use this when running remotely (CLI in remote mode).
87
57
  */
88
58
  export async function getClientsList(): Promise<ClientEntry[]> {
89
- const config = await loadConfig();
90
59
  const result = await callDaemon("/clients");
91
60
  const clients = (
92
61
  result.output as
@@ -97,6 +66,7 @@ export async function getClientsList(): Promise<ClientEntry[]> {
97
66
  apiKey: string;
98
67
  createdAt: number;
99
68
  lastUsed?: number | null;
69
+ ownerNpub?: string;
100
70
  }>;
101
71
  }
102
72
  | undefined
@@ -106,17 +76,14 @@ export async function getClientsList(): Promise<ClientEntry[]> {
106
76
  return [];
107
77
  }
108
78
 
109
- const suffix = config.daemonUrl ? getNpubSuffix(config) : null;
110
-
111
- return clients
112
- .filter((c) => !suffix || c.id.endsWith(`-${suffix}`))
113
- .map((c) => ({
114
- clientId: suffix ? removeSuffixFromId(c.id, suffix) : c.id,
115
- name: c.name,
116
- apiKey: c.apiKey,
117
- createdAt: c.createdAt,
118
- lastUsed: c.lastUsed,
119
- }));
79
+ return clients.map((c) => ({
80
+ clientId: c.id,
81
+ name: c.name,
82
+ apiKey: c.apiKey,
83
+ createdAt: c.createdAt,
84
+ lastUsed: c.lastUsed,
85
+ ownerNpub: c.ownerNpub,
86
+ }));
120
87
  }
121
88
 
122
89
  export async function addDaemonClient(
@@ -135,18 +102,14 @@ export async function addDaemonClient(
135
102
  apiKey: existing.apiKey,
136
103
  createdAt: existing.createdAt,
137
104
  lastUsed: existing.lastUsed,
105
+ ownerNpub: existing.ownerNpub,
138
106
  };
139
107
  return { client, created: false };
140
108
  }
141
109
 
142
- const config = await loadConfig();
143
- const suffix = getNpubSuffix(config);
144
- const clientId = suffix ? addSuffixToId(derivedId, suffix) : derivedId;
145
-
146
-
147
110
  const result = await callDaemon("/clients/add", {
148
111
  method: "POST",
149
- body: { name, id: clientId },
112
+ body: { name, id: derivedId },
150
113
  });
151
114
 
152
115
 
@@ -196,13 +159,9 @@ export async function listClientsAction(): Promise<void> {
196
159
  export async function deleteClientAction(id: string): Promise<void> {
197
160
  await ensureDaemonRunning();
198
161
 
199
- const config = await loadConfig();
200
- const suffix = getNpubSuffix(config);
201
- const resolvedId = suffix ? addSuffixToId(id, suffix) : id;
202
-
203
162
  const result = await callDaemon("/clients/delete", {
204
163
  method: "POST",
205
- body: { id: resolvedId },
164
+ body: { id },
206
165
  });
207
166
 
208
167
  if (result.error) {
@@ -233,7 +192,6 @@ export interface AddClientOptions {
233
192
  export async function addClientAction(options: AddClientOptions): Promise<void> {
234
193
  await ensureDaemonRunning();
235
194
  const config = await loadConfig();
236
- const suffix = getNpubSuffix(config);
237
195
 
238
196
  const integrationKeys: string[] = [];
239
197
  if (options.opencode) integrationKeys.push("opencode");
@@ -259,7 +217,7 @@ export async function addClientAction(options: AddClientOptions): Promise<void>
259
217
  await integrationFn(config, client.apiKey, integrationConfig);
260
218
 
261
219
  console.log(`\n ${integrationConfig.name}:`);
262
- console.log(` Client ID: ${suffix ? removeSuffixFromId(client.id, suffix) : client.id}`);
220
+ console.log(` Client ID: ${client.id}`);
263
221
  console.log(` API Key: ${client.apiKey}`);
264
222
  } catch (error) {
265
223
  logger.error(
@@ -286,7 +244,7 @@ export async function addClientAction(options: AddClientOptions): Promise<void>
286
244
 
287
245
  if (!created) {
288
246
  console.log(`Client '${options.name}' already exists.`);
289
- console.log(`\n ID: ${suffix ? removeSuffixFromId(client.id, suffix) : client.id}`);
247
+ console.log(`\n ID: ${client.id}`);
290
248
  console.log(` Name: ${client.name}`);
291
249
  console.log(` API Key: ${client.apiKey}`);
292
250
  return;
@@ -295,7 +253,7 @@ export async function addClientAction(options: AddClientOptions): Promise<void>
295
253
  if (message) {
296
254
  console.log(message);
297
255
  }
298
- console.log(`\n ID: ${suffix ? removeSuffixFromId(client.id, suffix) : client.id}`);
256
+ console.log(`\n ID: ${client.id}`);
299
257
  console.log(` Name: ${client.name}`);
300
258
  console.log(` API Key: ${client.apiKey}`);
301
259
  console.log(`\n Access Routstr at: ${getDaemonBaseUrl(config)}/v1`);