routstrd 0.2.0 → 0.2.2

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
@@ -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
- settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = "gpt-5.4";
29006
- settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = "claude-opus-4.7";
29007
- settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = "minimax-m2.7";
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));
@@ -36370,8 +36387,8 @@ var AuditLogger = class _AuditLogger {
36370
36387
  if (typeof window === "undefined") {
36371
36388
  try {
36372
36389
  const fs2 = await import("fs");
36373
- const path2 = await import("path");
36374
- const logPath = path2.join(process.cwd(), "audit.log");
36390
+ const path = await import("path");
36391
+ const logPath = path.join(process.cwd(), "audit.log");
36375
36392
  fs2.appendFileSync(logPath, logLine);
36376
36393
  } catch (error) {
36377
36394
  console.error("[AuditLogger] Failed to write to file:", error);
@@ -36914,6 +36931,9 @@ function parsePositiveIntOrExit(value, fieldName) {
36914
36931
  }
36915
36932
  return parsed;
36916
36933
  }
36934
+ function isPositiveIntegerString(value) {
36935
+ return /^[1-9]\d*$/.test(value.trim());
36936
+ }
36917
36937
  async function printLightningInvoice(invoice) {
36918
36938
  const paymentUri = `lightning:${invoice}`;
36919
36939
  const qr = await $toString(paymentUri, {
@@ -36924,21 +36944,21 @@ async function printLightningInvoice(invoice) {
36924
36944
  Invoice:
36925
36945
  ${invoice}`);
36926
36946
  }
36947
+ async function installCocodOrExit() {
36948
+ logger.log("cocod not found. Installing globally with bun...");
36949
+ const installProc = Bun.spawn(["bun", "install", "--global", "@routstr/cocod"], {
36950
+ stdout: "inherit",
36951
+ stderr: "inherit"
36952
+ });
36953
+ const installCode = await installProc.exited;
36954
+ if (installCode !== 0 || !await isCocodInstalled()) {
36955
+ logger.error("Failed to install cocod. Please run 'bun install --global @routstr/cocod' manually.");
36956
+ throw new Error("cocod installation failed");
36957
+ }
36958
+ logger.log("cocod installed successfully.");
36959
+ }
36927
36960
  async function initDaemon() {
36928
36961
  logger.log("Initializing routstrd...");
36929
- if (!await checkCocodInstalled()) {
36930
- logger.log("cocod not found. Installing globally with bun...");
36931
- const installProc = Bun.spawn(["bun", "install", "--global", "cocod"], {
36932
- stdout: "inherit",
36933
- stderr: "inherit"
36934
- });
36935
- const installCode = await installProc.exited;
36936
- if (installCode !== 0 || !await checkCocodInstalled()) {
36937
- logger.error("Failed to install cocod. Please run 'bun install --global cocod' manually.");
36938
- return;
36939
- }
36940
- logger.log("cocod installed successfully.");
36941
- }
36942
36962
  if (!existsSync9(CONFIG_DIR)) {
36943
36963
  mkdirSync5(CONFIG_DIR, { recursive: true });
36944
36964
  logger.log(`Created config directory: ${CONFIG_DIR}`);
@@ -36952,24 +36972,14 @@ async function initDaemon() {
36952
36972
  logger.log(`Created config file: ${CONFIG_FILE}`);
36953
36973
  }
36954
36974
  const config = await loadConfig();
36955
- const cocodExecutable = resolveCocodExecutable(config.cocodPath);
36956
36975
  if (!await isCocodInstalled(config.cocodPath)) {
36957
36976
  if (config.cocodPath) {
36958
36977
  logger.error(`Configured cocod executable was not found: ${config.cocodPath}`);
36959
36978
  return;
36960
36979
  }
36961
- logger.log("cocod not found. Installing globally with bun...");
36962
- const installProc = Bun.spawn(["bun", "install", "--global", "cocod"], {
36963
- stdout: "inherit",
36964
- stderr: "inherit"
36965
- });
36966
- const installCode = await installProc.exited;
36967
- if (installCode !== 0 || !await isCocodInstalled(config.cocodPath)) {
36968
- logger.error("Failed to install cocod. Please run 'bun install --global cocod' manually.");
36969
- return;
36970
- }
36971
- logger.log("cocod installed successfully.");
36980
+ await installCocodOrExit();
36972
36981
  }
36982
+ const cocodExecutable = resolveCocodExecutable(config.cocodPath);
36973
36983
  console.log(`Database will be stored at: ${DB_PATH}`);
36974
36984
  console.log(`
36975
36985
  Initializing cocod...`);
@@ -37017,22 +37027,12 @@ ${initStderr}`.toLowerCase();
37017
37027
  logger.log(`
37018
37028
  Initialization complete!`);
37019
37029
  logger.log(`
37020
- use 'routstrd wallet receive cashu <token>' or 'routstrd wallet receive bolt11 2100' to top up your local wallet!`);
37030
+ use 'routstrd receive <cashu-token>' or 'routstrd receive 2100' to top up your local wallet using Lightning!`);
37031
+ logger.log(`
37032
+ full wallet commands still work too, e.g. 'routstrd wallet receive cashu <token>' and 'routstrd wallet receive bolt11 2100'.`);
37021
37033
  logger.log(`
37022
37034
  To ensure routstrd persists across system restarts, run: 'routstrd service install'`);
37023
37035
  }
37024
- async function checkCocodInstalled() {
37025
- try {
37026
- const proc = Bun.spawn({
37027
- cmd: ["which", "cocod"],
37028
- stdout: "pipe"
37029
- });
37030
- const code = await proc.exited;
37031
- return code === 0;
37032
- } catch {
37033
- return false;
37034
- }
37035
- }
37036
37036
  program.name("routstrd").description("Routstr daemon - Manage routstr processes").version(cliVersion, "--version", "output the version number");
37037
37037
  program.command("onboard").description("Initialize routstrd (creates config directory and initializes cocod)").action(async () => {
37038
37038
  await initDaemon();
@@ -37330,6 +37330,55 @@ program.command("top").description("Open interactive TUI for usage monitoring (a
37330
37330
  const { runUsageTui: runUsageTui2 } = await Promise.resolve().then(() => (init_usage(), exports_usage));
37331
37331
  await runUsageTui2();
37332
37332
  });
37333
+ program.command("send <target>").description("Shortcut: numbers send Cashu, non-numbers pay a Lightning invoice").option("--mint-url <url>", "Mint URL to use").action(async (target, options) => {
37334
+ if (isPositiveIntegerString(target)) {
37335
+ await handleDaemonCommand("/wallet/send/cashu", {
37336
+ method: "POST",
37337
+ body: {
37338
+ amount: parsePositiveIntOrExit(target, "amount"),
37339
+ mintUrl: options.mintUrl
37340
+ }
37341
+ });
37342
+ return;
37343
+ }
37344
+ await handleDaemonCommand("/wallet/send/bolt11", {
37345
+ method: "POST",
37346
+ body: {
37347
+ invoice: target,
37348
+ mintUrl: options.mintUrl
37349
+ }
37350
+ });
37351
+ });
37352
+ program.command("receive <value>").description("Shortcut: numbers create a Lightning invoice, non-numbers receive a Cashu token").option("--mint-url <url>", "Mint URL to use for bolt11 receive").action(async (value, options) => {
37353
+ if (isPositiveIntegerString(value)) {
37354
+ try {
37355
+ await ensureDaemonRunning();
37356
+ const result = await callDaemon("/wallet/receive/bolt11", {
37357
+ method: "POST",
37358
+ body: {
37359
+ amount: parsePositiveIntOrExit(value, "amount"),
37360
+ mintUrl: options.mintUrl
37361
+ }
37362
+ });
37363
+ const output4 = result.output;
37364
+ if (typeof output4?.invoice === "string" && output4.invoice) {
37365
+ await printLightningInvoice(output4.invoice);
37366
+ return;
37367
+ }
37368
+ if (result.output !== undefined) {
37369
+ console.log(JSON.stringify(result.output, null, 2));
37370
+ }
37371
+ } catch (error) {
37372
+ console.error(error.message);
37373
+ process.exit(1);
37374
+ }
37375
+ return;
37376
+ }
37377
+ await handleDaemonCommand("/wallet/receive/cashu", {
37378
+ method: "POST",
37379
+ body: { token: value }
37380
+ });
37381
+ });
37333
37382
  var walletCmd = program.command("wallet").description("Wallet operations");
37334
37383
  walletCmd.command("status").description("Check wallet status").action(async () => {
37335
37384
  await handleDaemonCommand("/wallet/status");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "routstrd",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "module": "src/index.ts",
5
5
  "type": "module",
6
6
  "private": false,
@@ -13,7 +13,6 @@
13
13
  "lint": "tsc --noEmit",
14
14
  "test": "bun test",
15
15
  "build": "mkdir -p dist/daemon && bun build src/index.ts --target=bun --outfile=dist/index.js && bun build src/daemon/index.ts --target=bun --outfile=dist/daemon/index.js",
16
- "build:dev": "sed -i '' 's/\"@routstr\\/sdk\": \"\\^0.2.11\"/\"@routstr\\/sdk\": \"file:..\\/routstr-chat\\/sdk\"/' package.json && bun install && bun run build && sed -i '' 's/\"@routstr\\/sdk\": \"file:..\\/routstr-chat\\/sdk\"/\"@routstr\\/sdk\": \"^0.2.11\"/' package.json && bun install",
17
16
  "prepublishOnly": "bun run build"
18
17
  },
19
18
  "devDependencies": {
@@ -25,7 +24,7 @@
25
24
  },
26
25
  "dependencies": {
27
26
  "@cashu/cashu-ts": "^3.1.1",
28
- "@routstr/sdk": "^0.2.12",
27
+ "@routstr/sdk": "^0.3.0",
29
28
  "applesauce-core": "^5.1.0",
30
29
  "applesauce-relay": "^5.1.0",
31
30
  "commander": "^14.0.2",
package/src/cli.ts CHANGED
@@ -59,6 +59,10 @@ function parsePositiveIntOrExit(value: string, fieldName: string): number {
59
59
  return parsed;
60
60
  }
61
61
 
62
+ function isPositiveIntegerString(value: string): boolean {
63
+ return /^[1-9]\d*$/.test(value.trim());
64
+ }
65
+
62
66
  async function printLightningInvoice(invoice: string): Promise<void> {
63
67
  const paymentUri = `lightning:${invoice}`;
64
68
  const qr = await QRCode.toString(paymentUri, {
@@ -69,27 +73,27 @@ async function printLightningInvoice(invoice: string): Promise<void> {
69
73
  console.log(`${qr}\nInvoice:\n${invoice}`);
70
74
  }
71
75
 
72
- async function initDaemon(): Promise<void> {
73
- logger.log("Initializing routstrd...");
76
+ async function installCocodOrExit(): Promise<void> {
77
+ logger.log("cocod not found. Installing globally with bun...");
74
78
 
75
- if (!(await checkCocodInstalled())) {
76
- logger.log("cocod not found. Installing globally with bun...");
79
+ const installProc = Bun.spawn(["bun", "install", "--global", "@routstr/cocod"], {
80
+ stdout: "inherit",
81
+ stderr: "inherit",
82
+ });
77
83
 
78
- const installProc = Bun.spawn(["bun", "install", "--global", "cocod"], {
79
- stdout: "inherit",
80
- stderr: "inherit",
81
- });
84
+ const installCode = await installProc.exited;
85
+ if (installCode !== 0 || !(await isCocodInstalled())) {
86
+ logger.error(
87
+ "Failed to install cocod. Please run 'bun install --global @routstr/cocod' manually.",
88
+ );
89
+ throw new Error("cocod installation failed");
90
+ }
82
91
 
83
- const installCode = await installProc.exited;
84
- if (installCode !== 0 || !(await checkCocodInstalled())) {
85
- logger.error(
86
- "Failed to install cocod. Please run 'bun install --global cocod' manually.",
87
- );
88
- return;
89
- }
92
+ logger.log("cocod installed successfully.");
93
+ }
90
94
 
91
- logger.log("cocod installed successfully.");
92
- }
95
+ async function initDaemon(): Promise<void> {
96
+ logger.log("Initializing routstrd...");
93
97
 
94
98
  // Create config directory
95
99
  if (!existsSync(CONFIG_DIR)) {
@@ -108,7 +112,6 @@ async function initDaemon(): Promise<void> {
108
112
  }
109
113
 
110
114
  const config = await loadConfig();
111
- const cocodExecutable = resolveCocodExecutable(config.cocodPath);
112
115
 
113
116
  if (!(await isCocodInstalled(config.cocodPath))) {
114
117
  if (config.cocodPath) {
@@ -118,24 +121,11 @@ async function initDaemon(): Promise<void> {
118
121
  return;
119
122
  }
120
123
 
121
- logger.log("cocod not found. Installing globally with bun...");
122
-
123
- const installProc = Bun.spawn(["bun", "install", "--global", "cocod"], {
124
- stdout: "inherit",
125
- stderr: "inherit",
126
- });
127
-
128
- const installCode = await installProc.exited;
129
- if (installCode !== 0 || !(await isCocodInstalled(config.cocodPath))) {
130
- logger.error(
131
- "Failed to install cocod. Please run 'bun install --global cocod' manually.",
132
- );
133
- return;
134
- }
135
-
136
- logger.log("cocod installed successfully.");
124
+ await installCocodOrExit();
137
125
  }
138
126
 
127
+ const cocodExecutable = resolveCocodExecutable(config.cocodPath);
128
+
139
129
  console.log(`Database will be stored at: ${DB_PATH}`);
140
130
  console.log("\nInitializing cocod...");
141
131
 
@@ -202,26 +192,16 @@ async function initDaemon(): Promise<void> {
202
192
 
203
193
  logger.log("\nInitialization complete!");
204
194
  logger.log(
205
- "\n use 'routstrd wallet receive cashu <token>' or 'routstrd wallet receive bolt11 2100' to top up your local wallet!",
195
+ "\n use 'routstrd receive <cashu-token>' or 'routstrd receive 2100' to top up your local wallet using Lightning!",
196
+ );
197
+ logger.log(
198
+ "\n full wallet commands still work too, e.g. 'routstrd wallet receive cashu <token>' and 'routstrd wallet receive bolt11 2100'.",
206
199
  );
207
200
  logger.log(
208
201
  "\nTo ensure routstrd persists across system restarts, run: 'routstrd service install'",
209
202
  );
210
203
  }
211
204
 
212
- async function checkCocodInstalled(): Promise<boolean> {
213
- try {
214
- const proc = Bun.spawn({
215
- cmd: ["which", "cocod"],
216
- stdout: "pipe",
217
- });
218
- const code = await proc.exited;
219
- return code === 0;
220
- } catch {
221
- return false;
222
- }
223
- }
224
-
225
205
  program
226
206
  .name("routstrd")
227
207
  .description("Routstr daemon - Manage routstr processes")
@@ -733,6 +713,77 @@ program
733
713
  await runUsageTui();
734
714
  });
735
715
 
716
+ program
717
+ .command("send <target>")
718
+ .description(
719
+ "Shortcut: numbers send Cashu, non-numbers pay a Lightning invoice",
720
+ )
721
+ .option("--mint-url <url>", "Mint URL to use")
722
+ .action(async (target: string, options: { mintUrl?: string }) => {
723
+ if (isPositiveIntegerString(target)) {
724
+ await handleDaemonCommand("/wallet/send/cashu", {
725
+ method: "POST",
726
+ body: {
727
+ amount: parsePositiveIntOrExit(target, "amount"),
728
+ mintUrl: options.mintUrl,
729
+ },
730
+ });
731
+ return;
732
+ }
733
+
734
+ await handleDaemonCommand("/wallet/send/bolt11", {
735
+ method: "POST",
736
+ body: {
737
+ invoice: target,
738
+ mintUrl: options.mintUrl,
739
+ },
740
+ });
741
+ });
742
+
743
+ program
744
+ .command("receive <value>")
745
+ .description(
746
+ "Shortcut: numbers create a Lightning invoice, non-numbers receive a Cashu token",
747
+ )
748
+ .option("--mint-url <url>", "Mint URL to use for bolt11 receive")
749
+ .action(async (value: string, options: { mintUrl?: string }) => {
750
+ if (isPositiveIntegerString(value)) {
751
+ try {
752
+ await ensureDaemonRunning();
753
+
754
+ const result = await callDaemon("/wallet/receive/bolt11", {
755
+ method: "POST",
756
+ body: {
757
+ amount: parsePositiveIntOrExit(value, "amount"),
758
+ mintUrl: options.mintUrl,
759
+ },
760
+ });
761
+
762
+ const output = result.output as
763
+ | { invoice?: string; amount?: number; mintUrl?: string }
764
+ | undefined;
765
+
766
+ if (typeof output?.invoice === "string" && output.invoice) {
767
+ await printLightningInvoice(output.invoice);
768
+ return;
769
+ }
770
+
771
+ if (result.output !== undefined) {
772
+ console.log(JSON.stringify(result.output, null, 2));
773
+ }
774
+ } catch (error) {
775
+ console.error((error as Error).message);
776
+ process.exit(1);
777
+ }
778
+ return;
779
+ }
780
+
781
+ await handleDaemonCommand("/wallet/receive/cashu", {
782
+ method: "POST",
783
+ body: { token: value },
784
+ });
785
+ });
786
+
736
787
  const walletCmd = program.command("wallet").description("Wallet operations");
737
788
 
738
789
  walletCmd
@@ -1,7 +1,8 @@
1
1
  import { randomBytes } from "crypto";
2
2
  import { type IncomingMessage, type ServerResponse } from "http";
3
+ import { Readable } from "stream";
3
4
  import {
4
- routeRequestsToNodeResponse,
5
+ routeRequests,
5
6
  InsufficientBalanceError,
6
7
  ProviderManager,
7
8
  } from "@routstr/sdk";
@@ -968,7 +969,8 @@ export function createDaemonRequestHandler(deps: {
968
969
  try {
969
970
  await deps.ensureProvidersBootstrapped();
970
971
  logger.log("Routing request with path: ", url.pathname);
971
- await routeRequestsToNodeResponse({
972
+
973
+ const response = await routeRequests({
972
974
  modelId,
973
975
  requestBody,
974
976
  path: url.pathname,
@@ -984,8 +986,58 @@ export function createDaemonRequestHandler(deps: {
984
986
  usageTrackingDriver: deps.usageTrackingDriver,
985
987
  sdkStore: deps.store,
986
988
  providerManager: deps.providerManager,
987
- res,
988
989
  });
990
+
991
+ // Bridge the Web `Response` to the Node `ServerResponse` with no
992
+ // transforms: status + headers + pipe(body → res).
993
+ res.statusCode = response.status;
994
+ response.headers.forEach((value, key) => {
995
+ res.setHeader(key, value);
996
+ });
997
+
998
+ const finalize = (response as any).finalize as
999
+ | (() => Promise<number>)
1000
+ | undefined;
1001
+
1002
+ if (!response.body) {
1003
+ res.end();
1004
+ if (finalize) {
1005
+ try {
1006
+ await finalize();
1007
+ } catch (err) {
1008
+ logger.error(`[daemon] finalize error: ${toErrorMessage(err)}`);
1009
+ }
1010
+ }
1011
+ return;
1012
+ }
1013
+
1014
+ const nodeReadable = Readable.fromWeb(response.body as any);
1015
+ await new Promise<void>((resolve, reject) => {
1016
+ let settled = false;
1017
+ const finish = () => {
1018
+ if (settled) return;
1019
+ settled = true;
1020
+ resolve();
1021
+ };
1022
+ const fail = (err: unknown) => {
1023
+ if (settled) return;
1024
+ settled = true;
1025
+ reject(err);
1026
+ };
1027
+ res.once("finish", finish);
1028
+ res.once("close", finish);
1029
+ res.once("error", fail);
1030
+ nodeReadable.once("error", fail);
1031
+ nodeReadable.pipe(res);
1032
+ });
1033
+
1034
+ if (finalize) {
1035
+ try {
1036
+ await finalize();
1037
+ } catch (err) {
1038
+ logger.error(`[daemon] finalize error: ${toErrorMessage(err)}`);
1039
+ }
1040
+ }
989
1041
  return;
990
1042
  } catch (error) {
991
1043
  const message = error instanceof Error ? error.message : String(error);
@@ -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
- // Default models as requested
66
- settings.env["ANTHROPIC_DEFAULT_SONNET_MODEL"] = "gpt-5.4";
67
- settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = "claude-opus-4.7";
68
- settings.env["ANTHROPIC_DEFAULT_HAIKU_MODEL"] = "minimax-m2.7";
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 });