Add SF-TUI extension main entry point.

Integrates footer rendering, working vibes, prompt history stash,
and git status tracking into unified TUI enhancement extension.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
ace-pm 2026-04-15 16:18:15 +02:00
parent f878e9b4a1
commit 09691fe2e8

View file

@ -0,0 +1,84 @@
/**
* SF-TUI Unified TUI enhancements for Singularity Forge
*
* Features:
* - Rich footer: git branch, model, session cost, context usage
* - Working vibes: context-aware loading messages
* - Prompt history stash: Ctrl+Alt+H overlay with quick-pick
*/
import type { ExtensionAPI, ExtensionContext } from "@sf-run/pi-coding-agent";
import { Key } from "@sf-run/pi-tui";
import { isAutoActive } from "../sf/auto.js";
import { openStashOverlay, readStash, pushStash, writeStash } from "./stash.js";
import { renderFooter } from "./footer.js";
import { setVibeForPrompt, setVibeForTool, clearVibe } from "./vibes.js";
import { invalidateGitStatus } from "./git.js";
export { setVibeForPrompt, setVibeForTool, clearVibe } from "./vibes.js";
function installFooter(ctx: ExtensionContext): void {
if (!ctx.hasUI) return;
ctx.ui.setFooter((tui, theme, footerData) => {
return {
render: (width: number) => {
if (isAutoActive()) return [];
return renderFooter(theme, footerData, ctx, width);
},
invalidate: () => {},
dispose: () => {},
};
});
}
export default function sfTui(pi: ExtensionAPI): void {
const stash = readStash();
let wasAutoActive = false;
pi.on("session_start", async (_event, ctx) => {
if (!ctx.hasUI) return;
installFooter(ctx);
pi.registerShortcut(Key.ctrlAlt("h"), {
description: "Open prompt history stash",
handler: openStashOverlay,
});
pi.registerShortcut(Key.ctrlShift("h"), {
description: "Open prompt history stash (fallback)",
handler: openStashOverlay,
});
wasAutoActive = isAutoActive();
});
pi.on("before_agent_start", async (event) => {
const prompt = event.prompt?.trim();
if (prompt) {
pushStash(stash, prompt);
writeStash(stash);
}
});
pi.on("tool_call", async (event, ctx) => {
setVibeForTool(ctx, event.toolName, event.input);
});
pi.on("tool_result", async (_event, ctx) => {
invalidateGitStatus();
const autoNow = isAutoActive();
if (!autoNow && wasAutoActive) {
installFooter(ctx);
}
wasAutoActive = autoNow;
});
pi.on("agent_end", async (_event, ctx) => {
clearVibe(ctx);
const autoNow = isAutoActive();
if (!autoNow) {
installFooter(ctx);
}
wasAutoActive = autoNow;
});
}