From 3d390fe541761b87efe4f6ff57b2d261f4dacf66 Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Sun, 26 Apr 2026 20:58:12 +0530 Subject: [PATCH] refactor: split cli-shared into utils/daemon-client and cli.ts - Moved daemon communication helpers (loadConfig, callDaemon, isDaemonRunning, startDaemonProcess, ensureDaemonRunning, handleDaemonCommand) from cli-shared.ts to src/utils/daemon-client.ts - Moved the refund command from cli-shared.ts into cli.ts with the rest of the CLI commands - cli.ts now imports program directly from commander and daemon helpers from utils/daemon-client - TUI imports are updated to use utils/daemon-client - Removed src/cli-shared.ts --- src/cli.ts | 79 ++++++++++++++++- src/tui/usage/app.ts | 2 +- src/tui/usage/data.ts | 2 +- src/{cli-shared.ts => utils/daemon-client.ts} | 86 +------------------ 4 files changed, 82 insertions(+), 87 deletions(-) rename src/{cli-shared.ts => utils/daemon-client.ts} (53%) diff --git a/src/cli.ts b/src/cli.ts index 2b61841..3ee9945 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,12 +1,12 @@ +import { program } from "commander"; import { startDaemon } from "./start-daemon"; import { - program, handleDaemonCommand, callDaemon, ensureDaemonRunning, isDaemonRunning, loadConfig, -} from "./cli-shared"; +} from "./utils/daemon-client"; import { existsSync, mkdirSync } from "fs"; import { execSync } from "child_process"; import { @@ -211,6 +211,81 @@ program .description("Routstr daemon - Manage routstr processes") .version(cliVersion, "--version", "output the version number"); +program + .command("refund") + .description("Refund pending tokens and API keys to a specified mint") + .option("-m, --mint-url ", "Mint URL to refund to (defaults to first mint in wallet)") + .option("-y, --yes", "Skip confirmation prompt", false) + .action(async (options: { mintUrl?: string; yes: boolean }) => { + const config = await loadConfig(); + + let mintUrl = options.mintUrl; + if (!mintUrl) { + const balanceResponse = await fetch(`http://localhost:${config.port}/balance`); + const balanceResult = (await balanceResponse.json()) as { + output?: { balances?: Record }; + error?: string; + }; + if (balanceResult.error) { + console.log(balanceResult.error); + process.exit(1); + } + const balances = balanceResult.output?.balances; + if (!balances || Object.keys(balances).length === 0) { + console.log("No mint URLs found in wallet balance"); + process.exit(1); + } + mintUrl = Object.keys(balances)[0]; + console.log(`Using mint URL: ${mintUrl}`); + } + + try { + const response = await fetch(`http://localhost:${config.port}/refund`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ mintUrl }), + }); + + if (!response.ok) { + const errorData = (await response.json()) as { error?: string }; + throw new Error(errorData.error || `HTTP ${response.status}`); + } + + const result = (await response.json()) as { + output?: { + message: string; + pendingTokens: number; + apiKeys: number; + results: Array<{ baseUrl: string; success: boolean }>; + }; + error?: string; + }; + + if (result.error) { + console.log(result.error); + process.exit(1); + } + + if (result.output) { + console.log(result.output.message); + console.log(`\nPending tokens: ${result.output.pendingTokens}`); + console.log(`API keys: ${result.output.apiKeys}`); + console.log("\nResults:"); + for (const r of result.output.results) { + console.log(` - ${r.baseUrl}: ${r.success ? "success" : "failed"}`); + } + } + } catch (error) { + const message = (error as Error).message; + if (message?.includes("fetch failed") || message?.includes("Connection refused")) { + console.error("Daemon is not running"); + process.exit(1); + } + console.error(message); + process.exit(1); + } + }); + // Onboard - initialize the daemon program .command("onboard") diff --git a/src/tui/usage/app.ts b/src/tui/usage/app.ts index c29218f..853ce92 100644 --- a/src/tui/usage/app.ts +++ b/src/tui/usage/app.ts @@ -28,7 +28,7 @@ import { import { COLORS } from "./constants.ts"; import { renderHeader, renderSearchBar, renderSeparator, renderTabContent, renderTabs } from "./render.ts"; import type { TabId, UsageStats } from "./types.ts"; -import { isDaemonRunning } from "../../cli-shared.ts"; +import { isDaemonRunning } from "../../utils/daemon-client.ts"; export async function runUsageTui(): Promise { const running = await isDaemonRunning(); diff --git a/src/tui/usage/data.ts b/src/tui/usage/data.ts index 84cb674..d5e2523 100644 --- a/src/tui/usage/data.ts +++ b/src/tui/usage/data.ts @@ -1,5 +1,5 @@ import type { UsageTrackingEntry } from "../../daemon/types.ts"; -import { callDaemon, isDaemonRunning } from "../../cli-shared.ts"; +import { callDaemon, isDaemonRunning } from "../../utils/daemon-client.ts"; import type { ClientStats, DayStats, ModelStats, ProviderStats, UsageStats } from "./types.ts"; export interface BalanceKey { diff --git a/src/cli-shared.ts b/src/utils/daemon-client.ts similarity index 53% rename from src/cli-shared.ts rename to src/utils/daemon-client.ts index 23dec10..838abb2 100644 --- a/src/cli-shared.ts +++ b/src/utils/daemon-client.ts @@ -1,11 +1,10 @@ -import { program } from "commander"; import { existsSync } from "fs"; import { CONFIG_FILE, DEFAULT_CONFIG, LOGS_DIR, type RoutstrdConfig, -} from "./utils/config"; +} from "./config"; export interface CommandResponse { output?: unknown; @@ -24,7 +23,7 @@ export async function loadConfig(): Promise { return DEFAULT_CONFIG; } -async function callDaemon( +export async function callDaemon( path: string, options: { method?: "GET" | "POST"; body?: object } = {}, ): Promise { @@ -61,9 +60,7 @@ export async function startDaemonProcess(): Promise { await Bun.$`mkdir -p ${LOGS_DIR}`; } - const proc = Bun.spawn([ - "bun", "run", `${import.meta.dir}/daemon/index.ts` - ], { + const proc = Bun.spawn(["bun", "run", `${import.meta.dir}/../daemon/index.ts`], { stdout: "inherit", stderr: "inherit", stdin: "ignore", @@ -128,80 +125,3 @@ export async function handleDaemonCommand( process.exit(1); } } - -export { program, callDaemon }; - -program - .command("refund") - .description("Refund pending tokens and API keys to a specified mint") - .option("-m, --mint-url ", "Mint URL to refund to (defaults to first mint in wallet)") - .option("-y, --yes", "Skip confirmation prompt", false) - .action(async (options: { mintUrl?: string; yes: boolean }) => { - const config = await loadConfig(); - - let mintUrl = options.mintUrl; - if (!mintUrl) { - const balanceResponse = await fetch(`http://localhost:${config.port}/balance`); - const balanceResult = (await balanceResponse.json()) as { - output?: { balances?: Record }; - error?: string; - }; - if (balanceResult.error) { - console.log(balanceResult.error); - process.exit(1); - } - const balances = balanceResult.output?.balances; - if (!balances || Object.keys(balances).length === 0) { - console.log("No mint URLs found in wallet balance"); - process.exit(1); - } - mintUrl = Object.keys(balances)[0]; - console.log(`Using mint URL: ${mintUrl}`); - } - - try { - const response = await fetch(`http://localhost:${config.port}/refund`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ mintUrl }), - }); - - if (!response.ok) { - const errorData = (await response.json()) as { error?: string }; - throw new Error(errorData.error || `HTTP ${response.status}`); - } - - const result = (await response.json()) as { - output?: { - message: string; - pendingTokens: number; - apiKeys: number; - results: Array<{ baseUrl: string; success: boolean }>; - }; - error?: string; - }; - - if (result.error) { - console.log(result.error); - process.exit(1); - } - - if (result.output) { - console.log(result.output.message); - console.log(`\nPending tokens: ${result.output.pendingTokens}`); - console.log(`API keys: ${result.output.apiKeys}`); - console.log("\nResults:"); - for (const r of result.output.results) { - console.log(` - ${r.baseUrl}: ${r.success ? "success" : "failed"}`); - } - } - } catch (error) { - const message = (error as Error).message; - if (message?.includes("fetch failed") || message?.includes("Connection refused")) { - console.error("Daemon is not running"); - process.exit(1); - } - console.error(message); - process.exit(1); - } - });