import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; import { detectAppearance } from "./detectors.js"; import { loadSettings } from "./settings.js"; import type { ExtensionState } from "./types.js"; const POLL_INTERVAL_MS = 5000; export default function (pi: ExtensionAPI) { let intervalId: ReturnType | null = null; let isChecking = false; const state: ExtensionState = {}; function applyTheme(ctx: ExtensionContext, themeName: string): boolean { const theme = ctx.ui.getTheme(themeName); return theme ? ctx.ui.setTheme(theme).success : false; } async function evaluateAndApply(ctx: ExtensionContext): Promise { if (!ctx.hasUI || isChecking) return; isChecking = true; try { const settings = loadSettings(ctx.cwd); const detection = await detectAppearance(settings.darkOrLight?.default); const targetTheme = settings.darkOrLight?.[detection.mode] || detection.mode; if ( state.lastDetected?.mode === detection.mode && state.lastDetected?.source === detection.source && state.lastAppliedTheme === targetTheme ) { return; } let appliedTheme: string | undefined; if (applyTheme(ctx, targetTheme)) { appliedTheme = targetTheme; } else if (targetTheme !== detection.mode && applyTheme(ctx, detection.mode)) { appliedTheme = detection.mode; } state.lastDetected = detection; state.lastAppliedTheme = appliedTheme; } finally { isChecking = false; } } pi.on("session_start", async (_event, ctx) => { if (!ctx.hasUI) return; await evaluateAndApply(ctx); intervalId = setInterval(async () => { try { await evaluateAndApply(ctx); } catch { // Ignore polling errors to keep the extension non-intrusive. } }, POLL_INTERVAL_MS); }); pi.on("session_shutdown", () => { if (intervalId) { clearInterval(intervalId); intervalId = null; } }); }