pi extension update
This commit is contained in:
@@ -62,6 +62,21 @@ function getModelShortName(modelId: string): string {
|
||||
return modelId.replace(/^claude-/, "");
|
||||
}
|
||||
|
||||
// Format duration in milliseconds to human readable (e.g., "2h 55m")
|
||||
function formatDurationMs(ms: number): string {
|
||||
if (!Number.isFinite(ms) || ms <= 0) return "now";
|
||||
const totalSeconds = Math.floor(ms / 1000);
|
||||
const d = Math.floor(totalSeconds / 86400);
|
||||
const h = Math.floor((totalSeconds % 86400) / 3600);
|
||||
const m = Math.floor((totalSeconds % 3600) / 60);
|
||||
if (d > 0 && h > 0) return `${d}d ${h}h`;
|
||||
if (d > 0) return `${d}d`;
|
||||
if (h > 0 && m > 0) return `${h}h ${m}m`;
|
||||
if (h > 0) return `${h}h`;
|
||||
if (m > 0) return `${m}m`;
|
||||
return "<1m";
|
||||
}
|
||||
|
||||
// Nerd Font codepoints matched to what claude-account-switch.ts emits
|
||||
const ICON_PERSONAL = "\uEF85"; // U+EF85 — home
|
||||
const ICON_WORK = "\uDB80\uDCD6"; // U+F00D6 — briefcase (surrogate pair)
|
||||
@@ -71,6 +86,12 @@ export default function (pi: ExtensionAPI) {
|
||||
let ctx: any = null;
|
||||
let tuiRef: any = null;
|
||||
let footerDataRef: any = null;
|
||||
|
||||
// Track usage data for dynamic S/W bar rendering
|
||||
let usageSession: number | null = null;
|
||||
let usageWeekly: number | null = null;
|
||||
let sessionResetsAt: number | null = null;
|
||||
let weeklyResetsAt: number | null = null;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Footer line builder — called on every render
|
||||
@@ -106,7 +127,33 @@ export default function (pi: ExtensionAPI) {
|
||||
const usageRaw = statuses.get("usage-bars");
|
||||
const contextUsage = ctx?.getContextUsage?.();
|
||||
{
|
||||
let block = usageRaw ?? "";
|
||||
let block: string;
|
||||
|
||||
if (usageSession !== null && usageWeekly !== null) {
|
||||
// Build S/W bars directly from stored event data so we can cleanly
|
||||
// append the dynamic countdown without trying to parse ANSI strings.
|
||||
const session = Math.max(0, Math.min(100, Math.round(usageSession)));
|
||||
const weekly = Math.max(0, Math.min(100, Math.round(usageWeekly)));
|
||||
|
||||
let sPart = theme.fg("muted", "S ") + renderBrailleBar(theme, session) + " " + theme.fg("dim", `${session}%`);
|
||||
let wPart = theme.fg("muted", "W ") + renderBrailleBar(theme, weekly) + " " + theme.fg("dim", `${weekly}%`);
|
||||
|
||||
if (sessionResetsAt !== null) {
|
||||
const msLeft = sessionResetsAt - Date.now();
|
||||
if (msLeft > 0) sPart += " " + theme.fg("dim", formatDurationMs(msLeft));
|
||||
}
|
||||
|
||||
if (weeklyResetsAt !== null) {
|
||||
const msLeft = weeklyResetsAt - Date.now();
|
||||
if (msLeft > 0) wPart += " " + theme.fg("dim", `\u27F3 ${formatDurationMs(msLeft)}`);
|
||||
}
|
||||
|
||||
block = sPart + pipeSep + wPart;
|
||||
} else {
|
||||
// Fallback to raw status for loading / error states
|
||||
block = usageRaw ?? "";
|
||||
}
|
||||
|
||||
if (contextUsage && contextUsage.percent !== null) {
|
||||
const pct = Math.round(contextUsage.percent);
|
||||
const cBar =
|
||||
@@ -188,4 +235,14 @@ export default function (pi: ExtensionAPI) {
|
||||
pi.events.on("claude-account:switched", () => {
|
||||
if (tuiRef) tuiRef.requestRender();
|
||||
});
|
||||
|
||||
// Listen for usage updates — store raw values so we can build bars + dynamic
|
||||
// countdown directly rather than parsing the ANSI status string from usage-bars.
|
||||
pi.events.on("usage:update", (data: any) => {
|
||||
if (data.session !== undefined) usageSession = data.session;
|
||||
if (data.weekly !== undefined) usageWeekly = data.weekly;
|
||||
if (data.sessionResetsAt !== undefined) sessionResetsAt = data.sessionResetsAt;
|
||||
if (data.weeklyResetsAt !== undefined) weeklyResetsAt = data.weeklyResetsAt;
|
||||
if (tuiRef) tuiRef.requestRender();
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user