import { VERSION, type ExtensionAPI, } from "@earendil-works/pi-coding-agent"; import { satisfies, valid } from "semver"; import { AutoCompactController } from "./src/auto-compact-controller.ts"; import { loadAutoCompactConfig, type ConfigLoadResult } from "./src/config.ts"; export const REQUIRED_PI_RANGE = ">=0.84.1"; interface AutoCompactExtensionOptions { readonly piVersion?: string; readonly loadConfig?: () => ConfigLoadResult; } export function supportsPiVersion(version: string): boolean { return valid(version) !== null && satisfies(version, REQUIRED_PI_RANGE); } export function createWjPiAutoCompactExtension( options: AutoCompactExtensionOptions = {}, ): (pi: ExtensionAPI) => void { const piVersion = options.piVersion ?? VERSION; return (pi: ExtensionAPI): void => { if (!supportsPiVersion(piVersion)) { let warningShown = false; pi.on("session_start", (_event, ctx) => { if (warningShown || !ctx.hasUI) return; warningShown = true; ctx.ui.notify( `wj-pi-auto-compact is disabled: requires Pi ${REQUIRED_PI_RANGE}; current version: ${piVersion}`, "warning", ); }); return; } const controller = new AutoCompactController( pi, (options.loadConfig ?? loadAutoCompactConfig)(), ); pi.on("session_start", (_event, ctx) => controller.startSession(ctx)); pi.on("turn_end", (event, ctx) => controller.onTurnEnd(event, ctx)); pi.on("turn_start", (event, ctx) => controller.onTurnStart(event, ctx)); pi.on("agent_end", (event, ctx) => controller.onAgentEnd(event, ctx)); pi.on("message_start", (event) => controller.onMessageStart(event)); pi.on("session_before_compact", (event, ctx) => controller.onSessionBeforeCompact(event, ctx)); pi.on("session_compact", (event, ctx) => controller.onSessionCompact(event, ctx)); pi.on("agent_settled", (_event, ctx) => controller.onAgentSettled(ctx)); pi.on("session_shutdown", () => controller.shutdown()); }; } export default createWjPiAutoCompactExtension();