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 | 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";