routstrd 0.2.1 → 0.2.3
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 -6
- package/dist/daemon/index.js +20 -3
- package/dist/index.js +82 -41
- package/package.json +1 -1
- package/src/cli.ts +87 -51
- package/src/integrations/claudecode.ts +23 -6
package/SKILL.md
CHANGED
|
@@ -49,10 +49,6 @@ Restart the daemon (stops if running, then starts).
|
|
|
49
49
|
|
|
50
50
|
Check daemon and wallet status. Returns JSON with current state.
|
|
51
51
|
|
|
52
|
-
### `routstrd ping`
|
|
53
|
-
|
|
54
|
-
Test connection to the daemon.
|
|
55
|
-
|
|
56
52
|
### `routstrd balance`
|
|
57
53
|
|
|
58
54
|
Get wallet and API key balances. Shows per-mint wallet balances, per-key API balances, and a grand total (all in sats).
|
|
@@ -117,11 +113,36 @@ List all registered clients with their ID, name, API key, and creation date.
|
|
|
117
113
|
|
|
118
114
|
#### `routstrd clients add`
|
|
119
115
|
|
|
120
|
-
Add a new client.
|
|
116
|
+
Add a new client or set up a client integration.
|
|
121
117
|
|
|
122
118
|
| Option | Description |
|
|
123
119
|
|--------|-------------|
|
|
124
|
-
| `-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
|
+
```
|
|
125
146
|
|
|
126
147
|
Returns the client ID and API key for use with the OpenAI-compatible API.
|
|
127
148
|
|
package/dist/daemon/index.js
CHANGED
|
@@ -41534,9 +41534,26 @@ Installing routstr configuration in ${configPath}...`);
|
|
|
41534
41534
|
}
|
|
41535
41535
|
settings.env["ANTHROPIC_AUTH_TOKEN"] = apiKey;
|
|
41536
41536
|
settings.env["ANTHROPIC_BASE_URL"] = `http://localhost:${port}`;
|
|
41537
|
-
|
|
41538
|
-
|
|
41539
|
-
|
|
41537
|
+
try {
|
|
41538
|
+
const response = await fetch(`http://localhost:${port}/models`);
|
|
41539
|
+
const data = await response.json();
|
|
41540
|
+
const models = data.output?.models || [];
|
|
41541
|
+
if (models.length >= 3) {
|
|
41542
|
+
settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = models[0].id;
|
|
41543
|
+
settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = models[1].id;
|
|
41544
|
+
settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = models[2].id;
|
|
41545
|
+
logger3.log(`Set Claude models: Opus=${models[0].id}, Sonnet=${models[1].id}, Haiku=${models[2].id}`);
|
|
41546
|
+
} else if (models.length > 0) {
|
|
41547
|
+
logger3.log(`Only ${models.length} models available, falling back to defaults.`);
|
|
41548
|
+
settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = models[0].id;
|
|
41549
|
+
settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = models[0].id;
|
|
41550
|
+
settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = models[0].id;
|
|
41551
|
+
} else {
|
|
41552
|
+
logger3.log("No models available from routstr daemon.");
|
|
41553
|
+
}
|
|
41554
|
+
} catch (error) {
|
|
41555
|
+
logger3.error("Failed to fetch models for Claude Code integration:", error);
|
|
41556
|
+
}
|
|
41540
41557
|
try {
|
|
41541
41558
|
mkdirSync3(dirname3(configPath), { recursive: true });
|
|
41542
41559
|
await writeFile3(configPath, JSON.stringify(settings, null, 2));
|
package/dist/index.js
CHANGED
|
@@ -29002,9 +29002,26 @@ Installing routstr configuration in ${configPath}...`);
|
|
|
29002
29002
|
}
|
|
29003
29003
|
settings.env["ANTHROPIC_AUTH_TOKEN"] = apiKey;
|
|
29004
29004
|
settings.env["ANTHROPIC_BASE_URL"] = `http://localhost:${port}`;
|
|
29005
|
-
|
|
29006
|
-
|
|
29007
|
-
|
|
29005
|
+
try {
|
|
29006
|
+
const response = await fetch(`http://localhost:${port}/models`);
|
|
29007
|
+
const data = await response.json();
|
|
29008
|
+
const models = data.output?.models || [];
|
|
29009
|
+
if (models.length >= 3) {
|
|
29010
|
+
settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = models[0].id;
|
|
29011
|
+
settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = models[1].id;
|
|
29012
|
+
settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = models[2].id;
|
|
29013
|
+
logger.log(`Set Claude models: Opus=${models[0].id}, Sonnet=${models[1].id}, Haiku=${models[2].id}`);
|
|
29014
|
+
} else if (models.length > 0) {
|
|
29015
|
+
logger.log(`Only ${models.length} models available, falling back to defaults.`);
|
|
29016
|
+
settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = models[0].id;
|
|
29017
|
+
settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = models[0].id;
|
|
29018
|
+
settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = models[0].id;
|
|
29019
|
+
} else {
|
|
29020
|
+
logger.log("No models available from routstr daemon.");
|
|
29021
|
+
}
|
|
29022
|
+
} catch (error) {
|
|
29023
|
+
logger.error("Failed to fetch models for Claude Code integration:", error);
|
|
29024
|
+
}
|
|
29008
29025
|
try {
|
|
29009
29026
|
mkdirSync3(dirname3(configPath), { recursive: true });
|
|
29010
29027
|
await writeFile3(configPath, JSON.stringify(settings, null, 2));
|
|
@@ -29041,6 +29058,12 @@ var CLIENT_CONFIGS = {
|
|
|
29041
29058
|
configPath: join2(process.env.HOME || "", ".claude/settings.json")
|
|
29042
29059
|
}
|
|
29043
29060
|
};
|
|
29061
|
+
var CLIENT_INTEGRATIONS = {
|
|
29062
|
+
opencode: installOpencodeIntegration,
|
|
29063
|
+
"pi-agent": installPiIntegration,
|
|
29064
|
+
openclaw: installOpenClawIntegration,
|
|
29065
|
+
"claude-code": installClaudeCodeIntegration
|
|
29066
|
+
};
|
|
29044
29067
|
|
|
29045
29068
|
// src/integrations/opencode.ts
|
|
29046
29069
|
var OPENCODE_SMALL_MODEL = "routstr/minimax-m2.5";
|
|
@@ -36927,21 +36950,21 @@ async function printLightningInvoice(invoice) {
|
|
|
36927
36950
|
Invoice:
|
|
36928
36951
|
${invoice}`);
|
|
36929
36952
|
}
|
|
36953
|
+
async function installCocodOrExit() {
|
|
36954
|
+
logger.log("cocod not found. Installing globally with bun...");
|
|
36955
|
+
const installProc = Bun.spawn(["bun", "install", "--global", "@routstr/cocod"], {
|
|
36956
|
+
stdout: "inherit",
|
|
36957
|
+
stderr: "inherit"
|
|
36958
|
+
});
|
|
36959
|
+
const installCode = await installProc.exited;
|
|
36960
|
+
if (installCode !== 0 || !await isCocodInstalled()) {
|
|
36961
|
+
logger.error("Failed to install cocod. Please run 'bun install --global @routstr/cocod' manually.");
|
|
36962
|
+
throw new Error("cocod installation failed");
|
|
36963
|
+
}
|
|
36964
|
+
logger.log("cocod installed successfully.");
|
|
36965
|
+
}
|
|
36930
36966
|
async function initDaemon() {
|
|
36931
36967
|
logger.log("Initializing routstrd...");
|
|
36932
|
-
if (!await checkCocodInstalled()) {
|
|
36933
|
-
logger.log("cocod not found. Installing globally with bun...");
|
|
36934
|
-
const installProc = Bun.spawn(["bun", "install", "--global", "cocod"], {
|
|
36935
|
-
stdout: "inherit",
|
|
36936
|
-
stderr: "inherit"
|
|
36937
|
-
});
|
|
36938
|
-
const installCode = await installProc.exited;
|
|
36939
|
-
if (installCode !== 0 || !await checkCocodInstalled()) {
|
|
36940
|
-
logger.error("Failed to install cocod. Please run 'bun install --global cocod' manually.");
|
|
36941
|
-
return;
|
|
36942
|
-
}
|
|
36943
|
-
logger.log("cocod installed successfully.");
|
|
36944
|
-
}
|
|
36945
36968
|
if (!existsSync9(CONFIG_DIR)) {
|
|
36946
36969
|
mkdirSync5(CONFIG_DIR, { recursive: true });
|
|
36947
36970
|
logger.log(`Created config directory: ${CONFIG_DIR}`);
|
|
@@ -36955,24 +36978,14 @@ async function initDaemon() {
|
|
|
36955
36978
|
logger.log(`Created config file: ${CONFIG_FILE}`);
|
|
36956
36979
|
}
|
|
36957
36980
|
const config = await loadConfig();
|
|
36958
|
-
const cocodExecutable = resolveCocodExecutable(config.cocodPath);
|
|
36959
36981
|
if (!await isCocodInstalled(config.cocodPath)) {
|
|
36960
36982
|
if (config.cocodPath) {
|
|
36961
36983
|
logger.error(`Configured cocod executable was not found: ${config.cocodPath}`);
|
|
36962
36984
|
return;
|
|
36963
36985
|
}
|
|
36964
|
-
|
|
36965
|
-
const installProc = Bun.spawn(["bun", "install", "--global", "cocod"], {
|
|
36966
|
-
stdout: "inherit",
|
|
36967
|
-
stderr: "inherit"
|
|
36968
|
-
});
|
|
36969
|
-
const installCode = await installProc.exited;
|
|
36970
|
-
if (installCode !== 0 || !await isCocodInstalled(config.cocodPath)) {
|
|
36971
|
-
logger.error("Failed to install cocod. Please run 'bun install --global cocod' manually.");
|
|
36972
|
-
return;
|
|
36973
|
-
}
|
|
36974
|
-
logger.log("cocod installed successfully.");
|
|
36986
|
+
await installCocodOrExit();
|
|
36975
36987
|
}
|
|
36988
|
+
const cocodExecutable = resolveCocodExecutable(config.cocodPath);
|
|
36976
36989
|
console.log(`Database will be stored at: ${DB_PATH}`);
|
|
36977
36990
|
console.log(`
|
|
36978
36991
|
Initializing cocod...`);
|
|
@@ -37026,18 +37039,6 @@ Initialization complete!`);
|
|
|
37026
37039
|
logger.log(`
|
|
37027
37040
|
To ensure routstrd persists across system restarts, run: 'routstrd service install'`);
|
|
37028
37041
|
}
|
|
37029
|
-
async function checkCocodInstalled() {
|
|
37030
|
-
try {
|
|
37031
|
-
const proc = Bun.spawn({
|
|
37032
|
-
cmd: ["which", "cocod"],
|
|
37033
|
-
stdout: "pipe"
|
|
37034
|
-
});
|
|
37035
|
-
const code = await proc.exited;
|
|
37036
|
-
return code === 0;
|
|
37037
|
-
} catch {
|
|
37038
|
-
return false;
|
|
37039
|
-
}
|
|
37040
|
-
}
|
|
37041
37042
|
program.name("routstrd").description("Routstr daemon - Manage routstr processes").version(cliVersion, "--version", "output the version number");
|
|
37042
37043
|
program.command("onboard").description("Initialize routstrd (creates config directory and initializes cocod)").action(async () => {
|
|
37043
37044
|
await initDaemon();
|
|
@@ -37305,9 +37306,49 @@ clientsCmd.command("list").description("List all clients").action(async () => {
|
|
|
37305
37306
|
console.log("");
|
|
37306
37307
|
}
|
|
37307
37308
|
});
|
|
37308
|
-
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) => {
|
|
37309
37310
|
await ensureDaemonRunning();
|
|
37310
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
|
+
}
|
|
37311
37352
|
const result = await callDaemon("/clients/add", {
|
|
37312
37353
|
method: "POST",
|
|
37313
37354
|
body: { name: options.name }
|
package/package.json
CHANGED
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";
|
|
@@ -73,27 +77,27 @@ async function printLightningInvoice(invoice: string): Promise<void> {
|
|
|
73
77
|
console.log(`${qr}\nInvoice:\n${invoice}`);
|
|
74
78
|
}
|
|
75
79
|
|
|
76
|
-
async function
|
|
77
|
-
logger.log("
|
|
80
|
+
async function installCocodOrExit(): Promise<void> {
|
|
81
|
+
logger.log("cocod not found. Installing globally with bun...");
|
|
78
82
|
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
const installProc = Bun.spawn(["bun", "install", "--global", "@routstr/cocod"], {
|
|
84
|
+
stdout: "inherit",
|
|
85
|
+
stderr: "inherit",
|
|
86
|
+
});
|
|
81
87
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
const installCode = await installProc.exited;
|
|
89
|
+
if (installCode !== 0 || !(await isCocodInstalled())) {
|
|
90
|
+
logger.error(
|
|
91
|
+
"Failed to install cocod. Please run 'bun install --global @routstr/cocod' manually.",
|
|
92
|
+
);
|
|
93
|
+
throw new Error("cocod installation failed");
|
|
94
|
+
}
|
|
86
95
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
logger.error(
|
|
90
|
-
"Failed to install cocod. Please run 'bun install --global cocod' manually.",
|
|
91
|
-
);
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
96
|
+
logger.log("cocod installed successfully.");
|
|
97
|
+
}
|
|
94
98
|
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
async function initDaemon(): Promise<void> {
|
|
100
|
+
logger.log("Initializing routstrd...");
|
|
97
101
|
|
|
98
102
|
// Create config directory
|
|
99
103
|
if (!existsSync(CONFIG_DIR)) {
|
|
@@ -112,7 +116,6 @@ async function initDaemon(): Promise<void> {
|
|
|
112
116
|
}
|
|
113
117
|
|
|
114
118
|
const config = await loadConfig();
|
|
115
|
-
const cocodExecutable = resolveCocodExecutable(config.cocodPath);
|
|
116
119
|
|
|
117
120
|
if (!(await isCocodInstalled(config.cocodPath))) {
|
|
118
121
|
if (config.cocodPath) {
|
|
@@ -122,24 +125,11 @@ async function initDaemon(): Promise<void> {
|
|
|
122
125
|
return;
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const installProc = Bun.spawn(["bun", "install", "--global", "cocod"], {
|
|
128
|
-
stdout: "inherit",
|
|
129
|
-
stderr: "inherit",
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
const installCode = await installProc.exited;
|
|
133
|
-
if (installCode !== 0 || !(await isCocodInstalled(config.cocodPath))) {
|
|
134
|
-
logger.error(
|
|
135
|
-
"Failed to install cocod. Please run 'bun install --global cocod' manually.",
|
|
136
|
-
);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
logger.log("cocod installed successfully.");
|
|
128
|
+
await installCocodOrExit();
|
|
141
129
|
}
|
|
142
130
|
|
|
131
|
+
const cocodExecutable = resolveCocodExecutable(config.cocodPath);
|
|
132
|
+
|
|
143
133
|
console.log(`Database will be stored at: ${DB_PATH}`);
|
|
144
134
|
console.log("\nInitializing cocod...");
|
|
145
135
|
|
|
@@ -216,19 +206,6 @@ async function initDaemon(): Promise<void> {
|
|
|
216
206
|
);
|
|
217
207
|
}
|
|
218
208
|
|
|
219
|
-
async function checkCocodInstalled(): Promise<boolean> {
|
|
220
|
-
try {
|
|
221
|
-
const proc = Bun.spawn({
|
|
222
|
-
cmd: ["which", "cocod"],
|
|
223
|
-
stdout: "pipe",
|
|
224
|
-
});
|
|
225
|
-
const code = await proc.exited;
|
|
226
|
-
return code === 0;
|
|
227
|
-
} catch {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
209
|
program
|
|
233
210
|
.name("routstrd")
|
|
234
211
|
.description("Routstr daemon - Manage routstr processes")
|
|
@@ -684,12 +661,71 @@ clientsCmd
|
|
|
684
661
|
|
|
685
662
|
clientsCmd
|
|
686
663
|
.command("add")
|
|
687
|
-
.description("Add a new client")
|
|
688
|
-
.
|
|
689
|
-
.
|
|
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
|
+
}) => {
|
|
690
677
|
await ensureDaemonRunning();
|
|
691
678
|
const config = await loadConfig();
|
|
692
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
|
+
|
|
693
729
|
const result = await callDaemon("/clients/add", {
|
|
694
730
|
method: "POST",
|
|
695
731
|
body: { name: options.name },
|
|
@@ -4,7 +4,7 @@ import { dirname } from "path";
|
|
|
4
4
|
import type { RoutstrdConfig } from "../utils/config";
|
|
5
5
|
import { logger } from "../utils/logger";
|
|
6
6
|
import type { SdkStore } from "@routstr/sdk";
|
|
7
|
-
import type { IntegrationConfig } from "./registry";
|
|
7
|
+
import type { IntegrationConfig, RoutstrModel } from "./registry";
|
|
8
8
|
import { generateApiKey } from "./registry";
|
|
9
9
|
|
|
10
10
|
export async function installClaudeCodeIntegration(
|
|
@@ -61,11 +61,28 @@ export async function installClaudeCodeIntegration(
|
|
|
61
61
|
|
|
62
62
|
settings.env["ANTHROPIC_AUTH_TOKEN"] = apiKey;
|
|
63
63
|
settings.env["ANTHROPIC_BASE_URL"] = `http://localhost:${port}`;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const response = await fetch(`http://localhost:${port}/models`);
|
|
67
|
+
const data = await response.json() as { output?: { models: RoutstrModel[] } };
|
|
68
|
+
const models = data.output?.models || [];
|
|
69
|
+
|
|
70
|
+
if (models.length >= 3) {
|
|
71
|
+
settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = models[0].id;
|
|
72
|
+
settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = models[1].id;
|
|
73
|
+
settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = models[2].id;
|
|
74
|
+
logger.log(`Set Claude models: Opus=${models[0].id}, Sonnet=${models[1].id}, Haiku=${models[2].id}`);
|
|
75
|
+
} else if (models.length > 0) {
|
|
76
|
+
logger.log(`Only ${models.length} models available, falling back to defaults.`);
|
|
77
|
+
settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = models[0].id;
|
|
78
|
+
settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = models[0].id;
|
|
79
|
+
settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = models[0].id;
|
|
80
|
+
} else {
|
|
81
|
+
logger.log("No models available from routstr daemon.");
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
logger.error("Failed to fetch models for Claude Code integration:", error);
|
|
85
|
+
}
|
|
69
86
|
|
|
70
87
|
try {
|
|
71
88
|
mkdirSync(dirname(configPath), { recursive: true });
|