/** * Timestamps extension for Pi. * * - Shows elapsed session time in footer (updates every second) * - Shows how long the last turn took (from your message to agent completion) */ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent"; // Track session time and turn durations let sessionStart = Date.now(); let timerHandle: ReturnType | null = null; let turnStartTime: number | null = null; let lastTurnDuration: number | null = null; function formatElapsed(ms: number): string { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); if (hours > 0) { return `${hours}h ${minutes % 60}m`; } else if (minutes > 0) { return `${minutes}m ${seconds % 60}s`; } else { return `${seconds}s`; } } function formatDuration(ms: number): string { if (ms < 1000) return `${ms}ms`; if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`; return `${(ms / 60000).toFixed(1)}m`; } export default function (pi: ExtensionAPI) { const updateStatus = (ctx: { ui: { setStatus: (id: string, text: string | undefined) => void; theme: { fg: (color: string, text: string) => string } } }) => { const elapsed = Date.now() - sessionStart; let status = ctx.ui.theme.fg("dim", `⏱ ${formatElapsed(elapsed)}`); // Show last turn duration if available if (lastTurnDuration !== null) { status += ctx.ui.theme.fg("muted", ` | took ${formatDuration(lastTurnDuration)}`); } ctx.ui.setStatus("timestamps", status); }; // Start timer on session start pi.on("session_start", async (_event, ctx) => { sessionStart = Date.now(); turnStartTime = null; lastTurnDuration = null; // Clear any existing timer if (timerHandle) clearInterval(timerHandle); // Update status every second timerHandle = setInterval(() => updateStatus(ctx), 1000); updateStatus(ctx); }); // Track turn timing pi.on("turn_start", async () => { turnStartTime = Date.now(); }); pi.on("turn_end", async (_event, ctx) => { if (turnStartTime !== null) { lastTurnDuration = Date.now() - turnStartTime; turnStartTime = null; updateStatus(ctx); } }); // Clean up on shutdown pi.on("session_shutdown", async () => { if (timerHandle) { clearInterval(timerHandle); timerHandle = null; } }); }