/** * Configuration loading for the extension. * * Reads global/project JSON config files plus environment overrides and exposes * a normalized, fully-populated runtime config object. */ import { existsSync, readFileSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; export type JsonRecord = Record; export type ExtensionConfig = { enabled?: boolean; notify?: boolean; }; export function isRecord(value: unknown): value is JsonRecord { return typeof value === "object" && value !== null && !Array.isArray(value); } function readJsonFile(path: string): JsonRecord | undefined { if (!existsSync(path)) return undefined; try { const parsed = JSON.parse(readFileSync(path, "utf8")); return isRecord(parsed) ? parsed : undefined; } catch { return undefined; } } function toBoolean(value: unknown): boolean | undefined { if (typeof value === "boolean") return value; if (typeof value === "number") return value !== 0; if (typeof value !== "string") return undefined; const normalized = value.trim().toLowerCase(); if (["1", "true", "yes", "on"].includes(normalized)) return true; if (["0", "false", "no", "off"].includes(normalized)) return false; return undefined; } export function loadConfig(cwd: string): Required { const globalPath = join(homedir(), ".pi", "agent", "openai-server-compaction.json"); const projectPath = join(cwd, ".pi", "openai-server-compaction.json"); const globalCfg = readJsonFile(globalPath) ?? {}; const projectCfg = readJsonFile(projectPath) ?? {}; const merged = { ...globalCfg, ...projectCfg }; return { enabled: toBoolean(process.env.PI_OPENAI_SERVER_COMPACTION_ENABLED) ?? toBoolean(merged.enabled) ?? true, notify: toBoolean(process.env.PI_OPENAI_SERVER_COMPACTION_NOTIFY) ?? toBoolean(merged.notify) ?? false, }; }