From 892203bdb393debd2962f12a8c58151fd330b697 Mon Sep 17 00:00:00 2001 From: newideas99 Date: Mon, 26 Jan 2026 23:25:43 -0500 Subject: [PATCH] feat(quotio): read config from Quotio's config.yaml file Auto-detect base URL and API key from Quotio's config file: - macOS: ~/Library/Application Support/Quotio/config.yaml - Linux: ~/.config/quotio/config.yaml - Fallback: ~/.quotio/config.yaml Priority: env vars > config file > defaults This enables zero-config setup when Quotio is installed. --- src/commands/auth-choice.apply.quotio.ts | 49 ++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/src/commands/auth-choice.apply.quotio.ts b/src/commands/auth-choice.apply.quotio.ts index 601da3506..157d9d3a0 100644 --- a/src/commands/auth-choice.apply.quotio.ts +++ b/src/commands/auth-choice.apply.quotio.ts @@ -1,3 +1,7 @@ +import { readFileSync } from "node:fs"; +import { homedir } from "node:os"; +import { join } from "node:path"; +import { parse as parseYaml } from "yaml"; import { upsertAuthProfile } from "../agents/auth-profiles.js"; import { resolveClawdbotAgentDir } from "../agents/agent-paths.js"; import type { ClawdbotConfig } from "../config/config.js"; @@ -9,6 +13,12 @@ const QUOTIO_DEFAULT_BASE_URL = "http://127.0.0.1:18317/v1"; const QUOTIO_DEFAULT_API_KEY = "quotio-local"; const QUOTIO_PROBE_TIMEOUT_MS = 3000; +type QuotioConfigFile = { + host?: string; + port?: number; + "api-keys"?: string[]; +}; + type QuotioModel = { id: string; object?: string; @@ -35,6 +45,38 @@ function getEnvQuotioConfig(): { baseUrl?: string; apiKey?: string } { }; } +function getQuotioConfigPaths(): string[] { + const home = homedir(); + return [ + join(home, "Library", "Application Support", "Quotio", "config.yaml"), + join(home, ".config", "quotio", "config.yaml"), + join(home, ".quotio", "config.yaml"), + ]; +} + +function readQuotioConfigFile(): { baseUrl?: string; apiKey?: string } { + for (const configPath of getQuotioConfigPaths()) { + try { + const content = readFileSync(configPath, "utf-8"); + const config = parseYaml(content) as QuotioConfigFile; + + if (!config) continue; + + const host = config.host || "127.0.0.1"; + const port = config.port || 18317; + const apiKeys = config["api-keys"]; + + return { + baseUrl: `http://${host}:${port}/v1`, + apiKey: apiKeys?.[0], + }; + } catch { + continue; + } + } + return {}; +} + async function probeQuotioEndpoint( baseUrl: string, apiKey: string, @@ -69,9 +111,10 @@ async function probeQuotioEndpoint( async function autoDetectQuotio(): Promise { const env = getEnvQuotioConfig(); + const fileConfig = readQuotioConfigFile(); - const baseUrl = env.baseUrl || QUOTIO_DEFAULT_BASE_URL; - const apiKey = env.apiKey || QUOTIO_DEFAULT_API_KEY; + const baseUrl = env.baseUrl || fileConfig.baseUrl || QUOTIO_DEFAULT_BASE_URL; + const apiKey = env.apiKey || fileConfig.apiKey || QUOTIO_DEFAULT_API_KEY; const result = await probeQuotioEndpoint(baseUrl, apiKey); if (result.ok) { @@ -83,7 +126,7 @@ async function autoDetectQuotio(): Promise { }; } - if (env.baseUrl || env.apiKey) { + if (baseUrl !== QUOTIO_DEFAULT_BASE_URL || apiKey !== QUOTIO_DEFAULT_API_KEY) { const defaultResult = await probeQuotioEndpoint( QUOTIO_DEFAULT_BASE_URL, QUOTIO_DEFAULT_API_KEY,