From 6461b0f84ab79a40d3f3b69ca57ca50a8b875a0a Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:07:06 +0530 Subject: [PATCH] fix(integrations): use remote daemon URL and callDaemon for client setups - Export getDaemonBaseUrl from daemon-client for shared URL resolution - Replace all hardcoded http://localhost: in client integrations (opencode, claudecode, openclaw, pi) with getDaemonBaseUrl(config) - Replace raw fetch(http://localhost:/models) with callDaemon("/models") so model fetching works with remote daemons and gets NIP-98 signed - Fix clients add command output to print the actual daemon base URL instead of hardcoded localhost --- src/cli.ts | 5 +++-- src/integrations/claudecode.ts | 10 +++++----- src/integrations/openclaw.ts | 10 +++++----- src/integrations/opencode.ts | 10 +++++----- src/integrations/pi.ts | 9 ++++----- src/utils/daemon-client.ts | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 5780245..7b0f7b9 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -6,6 +6,7 @@ import { ensureDaemonRunning, isDaemonRunning, loadConfig, + getDaemonBaseUrl, } from "./utils/daemon-client"; import { existsSync, mkdirSync } from "fs"; import { execSync } from "child_process"; @@ -820,7 +821,7 @@ clientsCmd } console.log( - `\n Access Routstr at: http://localhost:${config.port || 8008}/v1`, + `\n Access Routstr at: ${getDaemonBaseUrl(config)}/v1`, ); return; } @@ -860,7 +861,7 @@ clientsCmd console.log(` Name: ${output.client.name}`); console.log(` API Key: ${output.client.apiKey}`); console.log( - `\n Access Routstr at: http://localhost:${config.port || 8008}/v1`, + `\n Access Routstr at: ${getDaemonBaseUrl(config)}/v1`, ); } }); diff --git a/src/integrations/claudecode.ts b/src/integrations/claudecode.ts index 0a4e5c5..22bfb64 100644 --- a/src/integrations/claudecode.ts +++ b/src/integrations/claudecode.ts @@ -6,6 +6,7 @@ import { logger } from "../utils/logger"; import type { SdkStore } from "@routstr/sdk"; import type { IntegrationConfig, RoutstrModel } from "./registry"; import { generateApiKey } from "./registry"; +import { callDaemon, getDaemonBaseUrl } from "../utils/daemon-client"; export async function installClaudeCodeIntegration( config: RoutstrdConfig, @@ -16,7 +17,7 @@ export async function installClaudeCodeIntegration( logger.log(`\nInstalling routstr configuration in ${configPath}...`); - const port = config.port || 8008; + const baseUrl = getDaemonBaseUrl(config); // Get or create clientId entry const state = store.getState(); @@ -60,12 +61,11 @@ export async function installClaudeCodeIntegration( } settings.env["ANTHROPIC_AUTH_TOKEN"] = apiKey; - settings.env["ANTHROPIC_BASE_URL"] = `http://localhost:${port}`; + settings.env["ANTHROPIC_BASE_URL"] = baseUrl; try { - const response = await fetch(`http://localhost:${port}/models`); - const data = await response.json() as { output?: { models: RoutstrModel[] } }; - const models = data.output?.models || []; + const data = await callDaemon("/models"); + const models = (data.output as { models: RoutstrModel[] } | undefined)?.models || []; if (models.length >= 3) { settings.env["ANTHROPIC_DEFAULT_OPUS_MODEL"] = models[0].id; diff --git a/src/integrations/openclaw.ts b/src/integrations/openclaw.ts index b16a204..c8de2bb 100644 --- a/src/integrations/openclaw.ts +++ b/src/integrations/openclaw.ts @@ -6,6 +6,7 @@ import { logger } from "../utils/logger"; import type { SdkStore } from "@routstr/sdk"; import type { IntegrationConfig, RoutstrModel } from "./registry"; import { generateApiKey } from "./registry"; +import { callDaemon, getDaemonBaseUrl } from "../utils/daemon-client"; const OPENCLAW_PROVIDER_ID = "routstr"; const OPENCLAW_DEFAULT_PRIMARY_MODEL = "routstr/minimax-m2.5"; @@ -59,7 +60,7 @@ export async function installOpenClawIntegration( logger.log("\nInstalling routstr models in openclaw.json..."); - const port = config.port || 8008; + const baseUrl = getDaemonBaseUrl(config); // Get or create clientId entry for OpenClaw const state = store.getState(); @@ -113,9 +114,8 @@ export async function installOpenClawIntegration( try { mkdirSync(dirname(configPath), { recursive: true }); - const response = await fetch(`http://localhost:${port}/models`); - const data = await response.json() as { output?: { models: RoutstrModel[] } }; - const models = data.output?.models || []; + const data = await callDaemon("/models"); + const models = (data.output as { models: RoutstrModel[] } | undefined)?.models || []; if (models.length === 0) { logger.log("No models found from routstr daemon."); @@ -129,7 +129,7 @@ export async function installOpenClawIntegration( })); openclawConfig.models.providers[OPENCLAW_PROVIDER_ID] = { - baseUrl: `http://localhost:${port}/v1`, + baseUrl: `${baseUrl}/v1`, apiKey, api: "openai-completions", models: providerModels, diff --git a/src/integrations/opencode.ts b/src/integrations/opencode.ts index 325becf..b725017 100644 --- a/src/integrations/opencode.ts +++ b/src/integrations/opencode.ts @@ -6,6 +6,7 @@ import { logger } from "../utils/logger"; import type { SdkStore } from "@routstr/sdk"; import type { IntegrationConfig, RoutstrModel } from "./registry"; import { generateApiKey } from "./registry"; +import { callDaemon, getDaemonBaseUrl } from "../utils/daemon-client"; const OPENCODE_SMALL_MODEL = "routstr/minimax-m2.5"; @@ -18,7 +19,7 @@ export async function installOpencodeIntegration( logger.log("\nInstalling routstr models in opencode.json..."); - const port = config.port || 8008; + const baseUrl = getDaemonBaseUrl(config); // Get or create clientId entry for OpenCode const state = store.getState(); @@ -77,9 +78,8 @@ export async function installOpencodeIntegration( try { mkdirSync(dirname(configPath), { recursive: true }); - const response = await fetch(`http://localhost:${port}/models`); - const data = await response.json() as { output?: { models: RoutstrModel[] } }; - const models = data.output?.models || []; + const data = await callDaemon("/models"); + const models = (data.output as { models: RoutstrModel[] } | undefined)?.models || []; if (models.length === 0) { logger.log("No models found from routstr daemon."); @@ -95,7 +95,7 @@ export async function installOpencodeIntegration( npm: "@ai-sdk/openai-compatible", name: "routstr", options: { - baseURL: `http://localhost:${port}/`, + baseURL: `${baseUrl}/`, apiKey, includeUsage: true, }, diff --git a/src/integrations/pi.ts b/src/integrations/pi.ts index 2823010..7e99b68 100644 --- a/src/integrations/pi.ts +++ b/src/integrations/pi.ts @@ -6,6 +6,7 @@ import { logger } from "../utils/logger"; import type { SdkStore } from "@routstr/sdk"; import type { IntegrationConfig, RoutstrModel } from "./registry"; import { generateApiKey } from "./registry"; +import { callDaemon, getDaemonBaseUrl } from "../utils/daemon-client"; type PiModelEntry = { id: string; @@ -31,8 +32,7 @@ export async function installPiIntegration( logger.log("\nInstalling routstr models in pi models.json..."); - const port = config.port || 8008; - const baseUrl = `http://localhost:${port}/v1`; + const baseUrl = `${getDaemonBaseUrl(config)}/v1`; // Get or create clientId entry for Pi Agent const state = store.getState(); @@ -78,9 +78,8 @@ export async function installPiIntegration( // Ensure directory exists mkdirSync(dirname(configPath), { recursive: true }); - const response = await fetch(`http://localhost:${port}/models`); - const data = await response.json() as { output?: { models: RoutstrModel[] } }; - const models = data.output?.models || []; + const data = await callDaemon("/models"); + const models = (data.output as { models: RoutstrModel[] } | undefined)?.models || []; if (models.length === 0) { logger.log("No models found from routstr daemon."); diff --git a/src/utils/daemon-client.ts b/src/utils/daemon-client.ts index 7c0ae7e..aeb9826 100644 --- a/src/utils/daemon-client.ts +++ b/src/utils/daemon-client.ts @@ -28,7 +28,7 @@ export async function loadConfig(): Promise { return DEFAULT_CONFIG; } -function getDaemonBaseUrl(config: RoutstrdConfig): string { +export function getDaemonBaseUrl(config: RoutstrdConfig): string { return config.daemonUrl?.replace(/\/$/, "") || `http://localhost:${config.port}`; }