import { existsSync, readFileSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; import { isRecord } from "./utils.js"; function isMissingAuthFileError(error: unknown): boolean { if (typeof error === "object" && error !== null && "code" in error) { const code = (error as { code?: unknown }).code; if (code === "ENOENT") return true; } const msg = error instanceof Error ? error.message : String(error); return msg.includes("ENOENT") || msg.includes("not found"); } export interface AuthKeyOptions { env?: Record; authPaths?: readonly string[]; homeDir?: () => string; readFile?: (path: string) => string; fileExists?: (path: string) => boolean; } export function defaultAuthPaths(home: string): string[] { return [ join(home, ".cline", "data", "settings", "providers.json"), join(home, ".pi", "agent", "auth.json"), ]; } export function walkAuthPaths( options: AuthKeyOptions, extract: (parsed: Record) => T | undefined, ): T | undefined { const home = options.homeDir?.() ?? homedir(); const authPaths = options.authPaths ?? defaultAuthPaths(home); const readFile = options.readFile ?? ((p: string) => readFileSync(p, "utf-8")); const fileExists = options.fileExists ?? ((p: string) => existsSync(p)); for (const authPath of authPaths) { let parsed: unknown; try { if (!fileExists(authPath)) continue; parsed = JSON.parse(readFile(authPath)); } catch (e) { if (!isMissingAuthFileError(e)) { const msg = e instanceof Error ? e.message : String(e); console.warn(`[cline] Warning: failed to read auth file ${authPath}: ${msg}`); } continue; } if (!isRecord(parsed)) continue; const result = extract(parsed); if (result !== undefined) return result; } return undefined; } export function walkClineProviderSettings( parsed: Record, extract: (settings: Record) => T | undefined, ): T | undefined { if (!isRecord(parsed)) return undefined; const providers = isRecord(parsed.providers) ? parsed.providers : undefined; if (!providers) return undefined; for (const key of ["cline-pass", "cline"]) { const provider = isRecord(providers[key]) ? providers[key] : undefined; if (!provider) continue; const settings = isRecord(provider.settings) ? provider.settings : undefined; if (!settings) continue; const result = extract(settings); if (result !== undefined) return result; } return undefined; }