import { readFileSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; /** * Providers pi can authenticate on its own from `~/.pi/agent/auth.json`. * * The backend injects a single managed model key (`THT_MODEL_API_KEY[_FILE]`), * which belongs to exactly one provider. Forcing that one key onto a different * provider's credential variable breaks its auth. So when the selected provider * is present in pi's own auth store, the backend skips injection and lets pi * resolve that provider's key itself. An absent/malformed store (e.g. a * containerized deployment that ships no auth.json) yields an empty set, which * keeps the managed-key path authoritative there. */ export function loadPiAuthProviders( opts: { agentDir?: string; read?: (path: string) => string } = {}, ): Set { const agentDir = opts.agentDir ?? join(homedir(), ".pi", "agent"); const read = opts.read ?? ((path: string) => readFileSync(path, "utf8")); try { const raw: unknown = JSON.parse(read(join(agentDir, "auth.json"))); if (!raw || typeof raw !== "object" || Array.isArray(raw)) return new Set(); return new Set( Object.keys(raw as Record) .map((key) => key.trim().toLowerCase()) .filter((key) => key.length > 0), ); } catch { return new Set(); } }