routstrd 0.2.2 → 0.2.4
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/SKILL.md +27 -2
- package/dist/daemon/index.js +9 -4
- package/dist/index.js +47 -1
- package/package.json +2 -2
- package/src/cli.ts +67 -4
package/SKILL.md
CHANGED
|
@@ -113,11 +113,36 @@ List all registered clients with their ID, name, API key, and creation date.
|
|
|
113
113
|
|
|
114
114
|
#### `routstrd clients add`
|
|
115
115
|
|
|
116
|
-
Add a new client.
|
|
116
|
+
Add a new client or set up a client integration.
|
|
117
117
|
|
|
118
118
|
| Option | Description |
|
|
119
119
|
|--------|-------------|
|
|
120
|
-
| `-n, --name <name>` |
|
|
120
|
+
| `-n, --name <name>` | Client name (required when not using integration flags) |
|
|
121
|
+
| `--opencode` | Set up OpenCode integration |
|
|
122
|
+
| `--openclaw` | Set up OpenClaw integration |
|
|
123
|
+
| `--pi-agent` | Set up Pi Agent integration |
|
|
124
|
+
| `--claude-code` | Set up Claude Code integration |
|
|
125
|
+
|
|
126
|
+
Set up a specific client integration (creates API key and writes config to the client's config file):
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
routstrd clients add --opencode
|
|
130
|
+
routstrd clients add --claude-code
|
|
131
|
+
routstrd clients add --pi-agent
|
|
132
|
+
routstrd clients add --openclaw
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
You can also set up multiple integrations at once:
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
routstrd clients add --opencode --pi-agent --claude-code
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Add a generic client manually:
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
routstrd clients add -n "My App"
|
|
145
|
+
```
|
|
121
146
|
|
|
122
147
|
Returns the client ID and API key for use with the OpenAI-compatible API.
|
|
123
148
|
|
package/dist/daemon/index.js
CHANGED
|
@@ -30266,6 +30266,8 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
|
|
|
30266
30266
|
const msg = error.message.toLowerCase();
|
|
30267
30267
|
if (msg.includes("fetch failed"))
|
|
30268
30268
|
return true;
|
|
30269
|
+
if (msg.includes("429"))
|
|
30270
|
+
return true;
|
|
30269
30271
|
if (msg.includes("502"))
|
|
30270
30272
|
return true;
|
|
30271
30273
|
if (msg.includes("503"))
|
|
@@ -30474,6 +30476,8 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
|
|
|
30474
30476
|
const msg = error.message.toLowerCase();
|
|
30475
30477
|
if (msg.includes("fetch failed"))
|
|
30476
30478
|
return true;
|
|
30479
|
+
if (msg.includes("429"))
|
|
30480
|
+
return true;
|
|
30477
30481
|
if (msg.includes("502"))
|
|
30478
30482
|
return true;
|
|
30479
30483
|
if (msg.includes("503"))
|
|
@@ -33881,9 +33885,10 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
|
|
|
33881
33885
|
try {
|
|
33882
33886
|
const currentBalanceInfo = await this.balanceManager.getTokenBalance(params.token, baseUrl);
|
|
33883
33887
|
const currentBalance = currentBalanceInfo.unit === "msat" ? currentBalanceInfo.amount / 1000 : currentBalanceInfo.amount;
|
|
33884
|
-
const
|
|
33888
|
+
const reservedBalance = currentBalanceInfo.unit === "msat" ? (currentBalanceInfo.reserved ?? 0) / 1000 : currentBalanceInfo.reserved ?? 0;
|
|
33889
|
+
const shortfall = Math.max(0, params.requiredSats - currentBalance + reservedBalance);
|
|
33885
33890
|
topupAmount = shortfall > 0.21 * params.requiredSats ? shortfall : 0.21 * params.requiredSats;
|
|
33886
|
-
this._log("DEBUG", `The shortfall is: ${shortfall}. requiredSats: ${params.requiredSats}. Current Balance: ${currentBalance} `);
|
|
33891
|
+
this._log("DEBUG", `The shortfall is: ${shortfall}. requiredSats: ${params.requiredSats}. Current Balance: ${currentBalance}. Reserved Balance: ${reservedBalance}. Available Balance: ${currentBalance - reservedBalance}`);
|
|
33887
33892
|
} catch (e) {
|
|
33888
33893
|
this._log("WARN", "Could not get current token balance for topup calculation:", e);
|
|
33889
33894
|
}
|
|
@@ -33974,8 +33979,8 @@ var import_rxjs24, InsufficientBalanceError, ProviderError, MintUnreachableError
|
|
|
33974
33979
|
tryNextProvider = true;
|
|
33975
33980
|
}
|
|
33976
33981
|
}
|
|
33977
|
-
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
|
|
33978
|
-
this._log("DEBUG", `[RoutstrClient] _handleErrorResponse: Status ${status} (auth/server error), attempting refund for ${baseUrl}, mode=${this.mode}`);
|
|
33982
|
+
if ((status === 401 || status === 403 || status === 413 || status === 400 || status === 429 || status === 500 || status === 502 || status === 503 || status === 504 || status === 521) && !tryNextProvider) {
|
|
33983
|
+
this._log("DEBUG", `[RoutstrClient] _handleErrorResponse: Status ${status} (${status === 429 ? "rate limited" : "auth/server error"}), attempting refund for ${baseUrl}, mode=${this.mode}`);
|
|
33979
33984
|
if (this.mode === "apikeys") {
|
|
33980
33985
|
this._log("DEBUG", `[RoutstrClient] _handleErrorResponse: Attempting API key refund for ${baseUrl}, key preview=${token}`);
|
|
33981
33986
|
const latestBalanceInfo = await this.balanceManager.getTokenBalance(token, baseUrl);
|
package/dist/index.js
CHANGED
|
@@ -29058,6 +29058,12 @@ var CLIENT_CONFIGS = {
|
|
|
29058
29058
|
configPath: join2(process.env.HOME || "", ".claude/settings.json")
|
|
29059
29059
|
}
|
|
29060
29060
|
};
|
|
29061
|
+
var CLIENT_INTEGRATIONS = {
|
|
29062
|
+
opencode: installOpencodeIntegration,
|
|
29063
|
+
"pi-agent": installPiIntegration,
|
|
29064
|
+
openclaw: installOpenClawIntegration,
|
|
29065
|
+
"claude-code": installClaudeCodeIntegration
|
|
29066
|
+
};
|
|
29061
29067
|
|
|
29062
29068
|
// src/integrations/opencode.ts
|
|
29063
29069
|
var OPENCODE_SMALL_MODEL = "routstr/minimax-m2.5";
|
|
@@ -37300,9 +37306,49 @@ clientsCmd.command("list").description("List all clients").action(async () => {
|
|
|
37300
37306
|
console.log("");
|
|
37301
37307
|
}
|
|
37302
37308
|
});
|
|
37303
|
-
clientsCmd.command("add").description("Add a new client").
|
|
37309
|
+
clientsCmd.command("add").description("Add a new client or set up client integrations").option("-n, --name <name>", "Client name").option("--opencode", "Set up OpenCode integration").option("--openclaw", "Set up OpenClaw integration").option("--pi-agent", "Set up Pi Agent integration").option("--claude-code", "Set up Claude Code integration").action(async (options) => {
|
|
37304
37310
|
await ensureDaemonRunning();
|
|
37305
37311
|
const config = await loadConfig();
|
|
37312
|
+
const integrationKeys = [];
|
|
37313
|
+
if (options.opencode)
|
|
37314
|
+
integrationKeys.push("opencode");
|
|
37315
|
+
if (options.openclaw)
|
|
37316
|
+
integrationKeys.push("openclaw");
|
|
37317
|
+
if (options.piAgent)
|
|
37318
|
+
integrationKeys.push("pi-agent");
|
|
37319
|
+
if (options.claudeCode)
|
|
37320
|
+
integrationKeys.push("claude-code");
|
|
37321
|
+
if (integrationKeys.length > 0) {
|
|
37322
|
+
const sqliteDriver = await createBunSqliteDriver(DB_PATH);
|
|
37323
|
+
const { store } = await createSdkStore({ driver: sqliteDriver });
|
|
37324
|
+
for (const key of integrationKeys) {
|
|
37325
|
+
const integrationFn = CLIENT_INTEGRATIONS[key];
|
|
37326
|
+
const integrationConfig = CLIENT_CONFIGS[key];
|
|
37327
|
+
if (!integrationFn || !integrationConfig)
|
|
37328
|
+
continue;
|
|
37329
|
+
try {
|
|
37330
|
+
await integrationFn(config, store, integrationConfig);
|
|
37331
|
+
} catch (error) {
|
|
37332
|
+
logger.error(`Failed to set up ${integrationConfig.name} integration:`, error);
|
|
37333
|
+
continue;
|
|
37334
|
+
}
|
|
37335
|
+
const state = store.getState();
|
|
37336
|
+
const client2 = (state.clientIds || []).find((c) => c.clientId === key);
|
|
37337
|
+
if (client2) {
|
|
37338
|
+
console.log(`
|
|
37339
|
+
${integrationConfig.name}:`);
|
|
37340
|
+
console.log(` Client ID: ${client2.clientId}`);
|
|
37341
|
+
console.log(` API Key: ${client2.apiKey}`);
|
|
37342
|
+
}
|
|
37343
|
+
}
|
|
37344
|
+
console.log(`
|
|
37345
|
+
Access Routstr at: http://localhost:${config.port || 8008}`);
|
|
37346
|
+
return;
|
|
37347
|
+
}
|
|
37348
|
+
if (!options.name) {
|
|
37349
|
+
console.error("error: required option '-n, --name <name>' not specified");
|
|
37350
|
+
process.exit(1);
|
|
37351
|
+
}
|
|
37306
37352
|
const result = await callDaemon("/clients/add", {
|
|
37307
37353
|
method: "POST",
|
|
37308
37354
|
body: { name: options.name }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "routstrd",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"module": "src/index.ts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@cashu/cashu-ts": "^3.1.1",
|
|
27
|
-
"@routstr/sdk": "^0.3.
|
|
27
|
+
"@routstr/sdk": "^0.3.1",
|
|
28
28
|
"applesauce-core": "^5.1.0",
|
|
29
29
|
"applesauce-relay": "^5.1.0",
|
|
30
30
|
"commander": "^14.0.2",
|
package/src/cli.ts
CHANGED
|
@@ -18,7 +18,11 @@ import {
|
|
|
18
18
|
type RoutstrdConfig,
|
|
19
19
|
} from "./utils/config";
|
|
20
20
|
import { logger } from "./utils/logger";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
setupIntegration,
|
|
23
|
+
CLIENT_CONFIGS,
|
|
24
|
+
CLIENT_INTEGRATIONS,
|
|
25
|
+
} from "./integrations";
|
|
22
26
|
import { createSdkStore } from "@routstr/sdk";
|
|
23
27
|
import { createBunSqliteDriver } from "@routstr/sdk/storage";
|
|
24
28
|
import * as QRCode from "qrcode";
|
|
@@ -657,12 +661,71 @@ clientsCmd
|
|
|
657
661
|
|
|
658
662
|
clientsCmd
|
|
659
663
|
.command("add")
|
|
660
|
-
.description("Add a new client")
|
|
661
|
-
.
|
|
662
|
-
.
|
|
664
|
+
.description("Add a new client or set up client integrations")
|
|
665
|
+
.option("-n, --name <name>", "Client name")
|
|
666
|
+
.option("--opencode", "Set up OpenCode integration")
|
|
667
|
+
.option("--openclaw", "Set up OpenClaw integration")
|
|
668
|
+
.option("--pi-agent", "Set up Pi Agent integration")
|
|
669
|
+
.option("--claude-code", "Set up Claude Code integration")
|
|
670
|
+
.action(async (options: {
|
|
671
|
+
name?: string;
|
|
672
|
+
opencode?: boolean;
|
|
673
|
+
openclaw?: boolean;
|
|
674
|
+
piAgent?: boolean;
|
|
675
|
+
claudeCode?: boolean;
|
|
676
|
+
}) => {
|
|
663
677
|
await ensureDaemonRunning();
|
|
664
678
|
const config = await loadConfig();
|
|
665
679
|
|
|
680
|
+
const integrationKeys: string[] = [];
|
|
681
|
+
if (options.opencode) integrationKeys.push("opencode");
|
|
682
|
+
if (options.openclaw) integrationKeys.push("openclaw");
|
|
683
|
+
if (options.piAgent) integrationKeys.push("pi-agent");
|
|
684
|
+
if (options.claudeCode) integrationKeys.push("claude-code");
|
|
685
|
+
|
|
686
|
+
if (integrationKeys.length > 0) {
|
|
687
|
+
const sqliteDriver = await createBunSqliteDriver(DB_PATH);
|
|
688
|
+
const { store } = await createSdkStore({ driver: sqliteDriver });
|
|
689
|
+
|
|
690
|
+
for (const key of integrationKeys) {
|
|
691
|
+
const integrationFn = CLIENT_INTEGRATIONS[key];
|
|
692
|
+
const integrationConfig = CLIENT_CONFIGS[key];
|
|
693
|
+
if (!integrationFn || !integrationConfig) continue;
|
|
694
|
+
|
|
695
|
+
try {
|
|
696
|
+
await integrationFn(config, store, integrationConfig);
|
|
697
|
+
} catch (error) {
|
|
698
|
+
logger.error(
|
|
699
|
+
`Failed to set up ${integrationConfig.name} integration:`,
|
|
700
|
+
error,
|
|
701
|
+
);
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
const state = store.getState();
|
|
706
|
+
const client = (state.clientIds || []).find(
|
|
707
|
+
(c: { clientId: string }) => c.clientId === key,
|
|
708
|
+
);
|
|
709
|
+
if (client) {
|
|
710
|
+
console.log(`\n ${integrationConfig.name}:`);
|
|
711
|
+
console.log(` Client ID: ${client.clientId}`);
|
|
712
|
+
console.log(` API Key: ${client.apiKey}`);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
console.log(
|
|
717
|
+
`\n Access Routstr at: http://localhost:${config.port || 8008}`,
|
|
718
|
+
);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
if (!options.name) {
|
|
723
|
+
console.error(
|
|
724
|
+
"error: required option '-n, --name <name>' not specified",
|
|
725
|
+
);
|
|
726
|
+
process.exit(1);
|
|
727
|
+
}
|
|
728
|
+
|
|
666
729
|
const result = await callDaemon("/clients/add", {
|
|
667
730
|
method: "POST",
|
|
668
731
|
body: { name: options.name },
|