mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 09:04:26 +00:00
When the agent is running, we prefix an animated braille spinner to the title to show busy state. Its cleared when the agent is done
58 lines
1.6 KiB
TypeScript
58 lines
1.6 KiB
TypeScript
/**
|
|
* Titlebar Spinner Extension
|
|
*
|
|
* Shows a braille spinner animation in the terminal title while the agent is working.
|
|
* Uses `ctx.ui.setTitle()` to update the terminal title via the extension API.
|
|
*
|
|
* Usage:
|
|
* pi --extension examples/extensions/titlebar-spinner.ts
|
|
*/
|
|
|
|
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
import path from "node:path";
|
|
|
|
const BRAILLE_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
|
|
function getBaseTitle(pi: ExtensionAPI): string {
|
|
const cwd = path.basename(process.cwd());
|
|
const session = pi.getSessionName();
|
|
return session ? `π - ${session} - ${cwd}` : `π - ${cwd}`;
|
|
}
|
|
|
|
export default function (pi: ExtensionAPI) {
|
|
let timer: ReturnType<typeof setInterval> | null = null;
|
|
let frameIndex = 0;
|
|
|
|
function stopAnimation(ctx: ExtensionContext) {
|
|
if (timer) {
|
|
clearInterval(timer);
|
|
timer = null;
|
|
}
|
|
frameIndex = 0;
|
|
ctx.ui.setTitle(getBaseTitle(pi));
|
|
}
|
|
|
|
function startAnimation(ctx: ExtensionContext) {
|
|
stopAnimation(ctx);
|
|
timer = setInterval(() => {
|
|
const frame = BRAILLE_FRAMES[frameIndex % BRAILLE_FRAMES.length];
|
|
const cwd = path.basename(process.cwd());
|
|
const session = pi.getSessionName();
|
|
const title = session ? `${frame} π - ${session} - ${cwd}` : `${frame} π - ${cwd}`;
|
|
ctx.ui.setTitle(title);
|
|
frameIndex++;
|
|
}, 80);
|
|
}
|
|
|
|
pi.on("agent_start", async (_event, ctx) => {
|
|
startAnimation(ctx);
|
|
});
|
|
|
|
pi.on("agent_end", async (_event, ctx) => {
|
|
stopAnimation(ctx);
|
|
});
|
|
|
|
pi.on("session_shutdown", async (_event, ctx) => {
|
|
stopAnimation(ctx);
|
|
});
|
|
}
|