import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent"; import { fmt } from "./format"; import { fileRows, skillRows, toolRows } from "./lists"; import { buildReport } from "./report"; import type { ListRow } from "./types"; import { showListUi, showPanel } from "./ui"; /** * The `/context` command handler — routes subcommands and picks the output * sink per mode (tui / json / print / notify). Factory form so `index.ts` * stays a thin registration stub. */ export const contextCommand = (pi: ExtensionAPI) => async (args: string | undefined, ctx: ExtensionCommandContext): Promise => { const sub = (args ?? "").trim().split(/\s+/)[0]?.toLowerCase() ?? ""; /* --- list subcommands (skills / tools / files) --- */ if (sub === "skills" || sub === "tools" || sub === "files") { const rows: ListRow[] = sub === "skills" ? skillRows(ctx) : sub === "tools" ? toolRows(pi) : fileRows(ctx); const title = sub === "skills" ? "Skills" : sub === "tools" ? "Tools" : "Context files"; if (ctx.mode === "tui") { await showListUi(ctx, title, rows); return; } // Non-TUI fallback: plain text rows. const text = rows .sort((a, b) => b.tokens - a.tokens) .map((r) => `${r.name}\t${r.desc}\t${fmt(r.tokens)}`) .join("\n"); const payload = `${title}:\n${text || "(none)"}`; if (ctx.hasUI) ctx.ui.notify(payload, "info"); else if (ctx.mode === "json") process.stderr.write(payload + "\n"); else console.log(payload); return; } if (sub === "help" || sub === "h") { const help = "Context usage commands:\n" + " /context overview + section breakdown\n" + " /context skills list loaded skills by estimated size\n" + " /context tools list registered tools by estimated size\n" + " /context files list loaded context files (AGENTS.md etc.)"; if (ctx.mode === "tui") await showPanel(ctx, help); else console.log(help); return; } /* --- default: overview + breakdown --- */ if (ctx.mode === "tui") { await showPanel(ctx, buildReport(pi, ctx)); return; } const report = buildReport(pi, ctx); if (ctx.hasUI) { ctx.ui.notify(report, "info"); } else if (ctx.mode === "json") { // JSON mode streams events to stdout — keep the report off the protocol. process.stderr.write(report + "\n"); } else { // Print mode: emit the report as plain text. console.log(report); } };