65 lines
2.1 KiB
TypeScript
65 lines
2.1 KiB
TypeScript
/**
|
|
* Custom Footer Extension - demonstrates ctx.ui.setFooter()
|
|
*
|
|
* footerData exposes data not otherwise accessible:
|
|
* - getGitBranch(): current git branch
|
|
* - getExtensionStatuses(): texts from ctx.ui.setStatus()
|
|
*
|
|
* Token stats come from ctx.sessionManager/ctx.model (already accessible).
|
|
*/
|
|
|
|
import type { AssistantMessage } from "@mariozechner/pi-ai";
|
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
let enabled = false;
|
|
|
|
pi.registerCommand("footer", {
|
|
description: "Toggle custom footer",
|
|
handler: async (_args, ctx) => {
|
|
enabled = !enabled;
|
|
|
|
if (enabled) {
|
|
ctx.ui.setFooter((tui, theme, footerData) => {
|
|
const unsub = footerData.onBranchChange(() => tui.requestRender());
|
|
|
|
return {
|
|
dispose: unsub,
|
|
invalidate() {},
|
|
render(width: number): string[] {
|
|
// Compute tokens from ctx (already accessible to extensions)
|
|
let input = 0,
|
|
output = 0,
|
|
cost = 0;
|
|
for (const e of ctx.sessionManager.getBranch()) {
|
|
if (e.type === "message" && e.message.role === "assistant") {
|
|
const m = e.message as AssistantMessage;
|
|
input += m.usage.input;
|
|
output += m.usage.output;
|
|
cost += m.usage.cost.total;
|
|
}
|
|
}
|
|
|
|
// Get git branch (not otherwise accessible)
|
|
const branch = footerData.getGitBranch();
|
|
const fmt = (n: number) => (n < 1000 ? `${n}` : `${(n / 1000).toFixed(1)}k`);
|
|
|
|
const left = theme.fg("dim", `↑${fmt(input)} ↓${fmt(output)} $${cost.toFixed(3)}`);
|
|
const branchStr = branch ? ` (${branch})` : "";
|
|
const right = theme.fg("dim", `${ctx.model?.id || "no-model"}${branchStr}`);
|
|
|
|
const pad = " ".repeat(Math.max(1, width - visibleWidth(left) - visibleWidth(right)));
|
|
return [truncateToWidth(left + pad + right, width)];
|
|
},
|
|
};
|
|
});
|
|
ctx.ui.notify("Custom footer enabled", "info");
|
|
} else {
|
|
ctx.ui.setFooter(undefined);
|
|
ctx.ui.notify("Default footer restored", "info");
|
|
}
|
|
},
|
|
});
|
|
}
|