Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/intellij/index.ts

Raw
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import type { AutocompleteItem } from "@earendil-works/pi-tui";
import type { IntellijRuntime } from "./implementation.ts";
import { closeDebug, dbg, span } from "./src/debug.ts";

const SUBCOMMANDS = [
	"connect",
	"disconnect",
	"reconnect",
	"status",
	"tools",
] as const;

export default function intellijExtension(pi: ExtensionAPI): void {
	let runtime: Promise<IntellijRuntime> | undefined;
	const getRuntime = () =>
		(runtime ??= import("./implementation.ts").then(
			({ createIntellijRuntime }) => createIntellijRuntime(pi),
		));

	pi.registerCommand("intellij", {
		description: "Connect Pi to IntelliJ's integrated MCP server on demand",
		getArgumentCompletions(prefix): AutocompleteItem[] | null {
			const normalized = prefix.trimStart().toLowerCase();
			if (normalized.includes(" ")) return null;
			const matches = SUBCOMMANDS.filter((command) =>
				command.startsWith(normalized),
			).map((command) => ({ value: command, label: command }));
			return matches.length > 0 ? matches : null;
		},
		async handler(args, ctx) {
			const [command = "", ...rest] = args.trim().split(/\s+/);
			if (!SUBCOMMANDS.some((candidate) => candidate === command)) {
				ctx.ui.notify(
					"Usage: /intellij connect [url] | disconnect | reconnect | status | tools",
					"error",
				);
				return;
			}
			const end = span?.("command.run", {
				selector: command as (typeof SUBCOMMANDS)[number],
			});
			try {
				await (await getRuntime()).run(
					command as (typeof SUBCOMMANDS)[number],
					rest.join(" "),
					ctx,
				);
				end?.();
			} catch (error) {
				end?.("error", { type: "command" });
				throw error;
			}
		},
	});

	pi.on("session_start", (_event, ctx) => {
		dbg?.("session.start", { mode: ctx.mode });
	});

	pi.on("session_shutdown", async () => {
		dbg?.("session.shutdown");
		const end = span?.("runtime.shutdown");
		try {
			if (runtime) await (await runtime).shutdown();
			end?.("finish", { status: runtime ? "stopped" : "idle" });
		} catch (error) {
			end?.("error", { type: "shutdown" });
			throw error;
		} finally {
			closeDebug();
		}
	});
}

export type { IntellijRuntime } from "./implementation.ts";