import { dirname, join } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { getUiTweaksPatchState } from "./patch-state.ts"; const THEME_FG_PATCH_KEY = Symbol.for("zigai.pi-ui-tweaks.neutral-border-color-patched"); type ThemePrototype = { [THEME_FG_PATCH_KEY]?: true; fg(this: ThemeInstance, color: string, text: string): string; }; type ThemeInstance = { fg(color: string, text: string): string; }; function getUnknownProperty(value: unknown, key: PropertyKey): unknown { if ((typeof value !== "object" || value === null) && typeof value !== "function") { return undefined; } return Reflect.get(value, key) as unknown; } function warnNeutralBorderPatchUnavailable(error?: unknown): void { let suffix = ""; if (error instanceof Error && error.message.length > 0) { suffix = `: ${error.message}`; } console.warn( `[pi-ui-tweaks] neutral border color patch unavailable; Pi internals may have changed${suffix}`, ); } function isThemePrototype(value: unknown): value is ThemePrototype { if (typeof value !== "object" || value === null) { return false; } return typeof Reflect.get(value, "fg") === "function"; } async function resolvePiDistDir(): Promise { const codingAgentEntry = fileURLToPath(import.meta.resolve("@earendil-works/pi-coding-agent")); return dirname(codingAgentEntry); } /** * Sets whether theme border colors should render as normal text color. */ export function setNeutralBorderColor(enabled: boolean): void { getUiTweaksPatchState().neutralBorderColor = enabled; } /** * Installs an idempotent patch that maps Pi border theme tokens away from blue. */ export async function installNeutralBorderColorPatch(): Promise { try { const distDir = await resolvePiDistDir(); const themePath = pathToFileURL(join(distDir, "modes/interactive/theme/theme.js")).href; const themeModule: unknown = (await import(themePath)) as unknown; const theme = getUnknownProperty(themeModule, "Theme"); const prototype = getUnknownProperty(theme, "prototype"); if (!isThemePrototype(prototype)) { warnNeutralBorderPatchUnavailable(); return; } if (prototype[THEME_FG_PATCH_KEY] === true) { return; } const originalFgValue: unknown = Reflect.get(prototype, "fg"); if (typeof originalFgValue !== "function") { warnNeutralBorderPatchUnavailable(); return; } // SAFETY: The immediately preceding runtime guard proves the private Theme.fg seam is callable. const originalFg = originalFgValue as ThemePrototype["fg"]; prototype.fg = function neutralBorderFg( this: ThemeInstance, color: string, text: string, ): string { if ( getUiTweaksPatchState().neutralBorderColor && (color === "border" || color === "borderMuted") ) { return originalFg.call(this, "text", text); } return originalFg.call(this, color, text); }; prototype[THEME_FG_PATCH_KEY] = true; } catch (error: unknown) { warnNeutralBorderPatchUnavailable(error); } }