import { existsSync, readFileSync } from "node:fs"; import { resolve, join, dirname } from "node:path"; import { homedir } from "node:os"; import type { InboxConfig } from "./types.ts"; export const DEFAULTS: InboxConfig = { inbox: "default", dataDir: join(homedir(), ".pi", "inbox"), pollIntervalMs: 2000, maxReplayMessages: 20, }; function expandHome(path: string): string { if (path === "~") { return homedir(); } if (path.startsWith("~/")) { return join(homedir(), path.slice(2)); } return path; } function loadProjectConfig(cwd: string): Partial | null { let dir = resolve(cwd); const root = resolve("/"); while (dir !== root) { try { const projectConfigPath = join(dir, ".pi", "inbox.json"); if (existsSync(projectConfigPath)) { const raw = readFileSync(projectConfigPath, "utf-8"); return JSON.parse(raw) as Partial; } } catch { // invalid or unreadable } const parent = dirname(dir); if (parent === dir) break; dir = parent; } return null; } function loadGlobalConfig(): Partial | null { try { const globalConfigPath = join(homedir(), ".pi", "agent", "inbox.json"); if (existsSync(globalConfigPath)) { const raw = readFileSync(globalConfigPath, "utf-8"); return JSON.parse(raw) as Partial; } } catch { // not found or invalid } return null; } export function getDataDir(config: InboxConfig): string { return resolve(expandHome(config.dataDir)); } export function loadConfig(cwd: string, cliOverrides?: Partial): InboxConfig { const project = loadProjectConfig(cwd) ?? {}; const global = loadGlobalConfig() ?? {}; // Priority: CLI > project > global > defaults return { inbox: cliOverrides?.inbox ?? project.inbox ?? global.inbox ?? DEFAULTS.inbox, dataDir: cliOverrides?.dataDir ?? project.dataDir ?? global.dataDir ?? DEFAULTS.dataDir, pollIntervalMs: cliOverrides?.pollIntervalMs ?? project.pollIntervalMs ?? global.pollIntervalMs ?? DEFAULTS.pollIntervalMs, maxReplayMessages: cliOverrides?.maxReplayMessages ?? project.maxReplayMessages ?? global.maxReplayMessages ?? DEFAULTS.maxReplayMessages, }; }