repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/strata/index.ts
Rawimport type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import type { Strata } from "./implementation.js";
import { closeDebug, dbg, span } from "./src/debug.ts";
import { findExecutable } from "./src/pi-ext-executable.ts";
export default function strata(pi: ExtensionAPI) {
let runtime: Strata | undefined;
let generation = 0;
const openings = new Set<Promise<unknown>>();
// Shared so repeated invocations evaluate ./implementation.js once.
// Pi's jiti loader (module cache disabled) can otherwise hand one caller a
// partially initialized module whose imports are still undefined.
let implementationModule:
| Promise<typeof import("./implementation.js")>
| undefined;
const loadImplementation = (): Promise<
typeof import("./implementation.js")
> => {
implementationModule ??= import("./implementation.js");
return implementationModule;
};
pi.on("session_start", (_event, ctx) => {
dbg?.("session.start");
const version = ++generation;
void hasGit().then((available) => {
if (!available && generation === version)
ctx.ui.notify("Strata requires Git on PATH.", "warning");
});
});
pi.on("session_shutdown", async () => {
dbg?.("session.shutdown");
generation++;
const stopped = runtime?.dispose();
runtime = undefined;
await Promise.allSettled([...openings, stopped]);
closeDebug();
});
pi.registerCommand("strata", {
description: "Review Git changes as semantic layers in a local browser",
getArgumentCompletions(prefix) {
return ["--staged", "--base", "--pr", "cancel"]
.filter((value) => value.startsWith(prefix))
.map((value) => ({ value, label: value }));
},
async handler(args, ctx) {
const finish = span?.("review.open");
if (args.trim() === "cancel") {
generation++;
await runtime?.close();
finish?.("finish", { outcome: "cancelled" });
return;
}
try {
const version = generation;
const { Strata } = await loadImplementation();
if (generation !== version) {
finish?.("finish", { outcome: "superseded" });
return;
}
runtime ??= new Strata(pi);
const opening = runtime.open(args, ctx);
openings.add(opening);
let outcome: Awaited<typeof opening>;
try {
outcome = await opening;
} finally {
openings.delete(opening);
}
finish?.("finish", { outcome });
} catch (error) {
finish?.("error");
throw error;
}
},
});
}
async function hasGit(): Promise<boolean> {
return Boolean(
findExecutable(process.platform === "win32" ? ["git.exe"] : ["git"]),
);
}