tune sub bar behavior
This commit is contained in:
@@ -46,7 +46,8 @@ interface PiAuthShape {
|
||||
}
|
||||
|
||||
const CACHE_TTL_MS = 5 * 60 * 1000;
|
||||
const REFRESH_MS = 2 * 60 * 1000;
|
||||
const ANTHROPIC_CACHE_TTL_MS = 30 * 60 * 1000;
|
||||
const REFRESH_MS = 5 * 60 * 1000;
|
||||
const PROVIDER_ORDER: ProviderName[] = ["anthropic", "codex", "gemini", "opencode-go"];
|
||||
const SHORTCUT_TOGGLE = "ctrl+alt+b";
|
||||
const showToggleState = async (ctx: ExtensionContext, next: boolean, refresh: () => Promise<void>) => {
|
||||
@@ -200,7 +201,12 @@ function buildColumnWidths(totalWidth: number, columns: number): number[] {
|
||||
return widths;
|
||||
}
|
||||
|
||||
function formatUsageTwoLines(theme: Theme, usage: UsageSnapshot, width: number): { top: string; bottom?: string } {
|
||||
function formatUsageTwoLines(
|
||||
theme: Theme,
|
||||
usage: UsageSnapshot,
|
||||
width: number,
|
||||
statusNote?: string,
|
||||
): { top: string; bottom?: string } {
|
||||
const provider = theme.bold(theme.fg("accent", usage.displayName));
|
||||
if (usage.error && usage.windows.length === 0) {
|
||||
const age = getErrorAge(usage.lastSuccessAt);
|
||||
@@ -244,7 +250,11 @@ function formatUsageTwoLines(theme: Theme, usage: UsageSnapshot, width: number):
|
||||
return barForPercent(theme, pct, colWidth);
|
||||
});
|
||||
|
||||
const top = prefix + topCols.join(gap);
|
||||
let top = prefix + topCols.join(gap);
|
||||
if (statusNote) {
|
||||
const note = theme.fg("warning", ` ⚠ ${statusNote}`);
|
||||
top = truncateToWidth(top + note, width);
|
||||
}
|
||||
const bottomPrefix = " ".repeat(prefixWidth);
|
||||
const bottom = bottomPrefix + bottomCols.join(gap);
|
||||
|
||||
@@ -459,6 +469,7 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
let activeProvider: ProviderName | "auto" = "auto";
|
||||
let widgetEnabled = true;
|
||||
let refreshTimer: NodeJS.Timeout | undefined;
|
||||
let anthropicRetryAfter = 0;
|
||||
const cache: Partial<Record<ProviderName, ProviderCache>> = {};
|
||||
|
||||
function getSelectedProvider(ctx?: ExtensionContext): ProviderName | undefined {
|
||||
@@ -487,10 +498,24 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
const safeWidth = Math.max(1, width);
|
||||
const topDivider = theme.fg("dim", "─".repeat(safeWidth));
|
||||
if (!snapshot) {
|
||||
const loading = truncateToWidth(theme.fg("dim", `sub bar loading ${provider} usage...`), safeWidth);
|
||||
const cooldown = provider === "anthropic" && anthropicRetryAfter > Date.now()
|
||||
? formatDuration(Math.max(1, Math.floor((anthropicRetryAfter - Date.now()) / 1000)))
|
||||
: undefined;
|
||||
const text = cooldown
|
||||
? `anthropic usage limited, retry in ${cooldown}`
|
||||
: `sub bar loading ${provider} usage...`;
|
||||
const loading = truncateToWidth(theme.fg("dim", text), safeWidth);
|
||||
return [topDivider, padToWidth(loading, safeWidth)];
|
||||
}
|
||||
const lines = formatUsageTwoLines(theme, snapshot, safeWidth);
|
||||
const cooldown = provider === "anthropic" && anthropicRetryAfter > Date.now()
|
||||
? formatDuration(Math.max(1, Math.floor((anthropicRetryAfter - Date.now()) / 1000)))
|
||||
: undefined;
|
||||
const statusNote = snapshot.error
|
||||
? snapshot.error
|
||||
: cooldown
|
||||
? `usage endpoint limited, retry in ${cooldown}`
|
||||
: undefined;
|
||||
const lines = formatUsageTwoLines(theme, snapshot, safeWidth, statusNote);
|
||||
const output = [topDivider, lines.top];
|
||||
if (lines.bottom) output.push(lines.bottom);
|
||||
return output;
|
||||
@@ -507,14 +532,22 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
ctx.ui.setWidget("sub-bar-local", undefined);
|
||||
return;
|
||||
}
|
||||
if (provider === "anthropic" && anthropicRetryAfter > Date.now()) {
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
const cached = cache[provider]?.usage;
|
||||
if (!force && cached && Date.now() - cached.fetchedAt < CACHE_TTL_MS) {
|
||||
const ttl = provider === "anthropic" ? ANTHROPIC_CACHE_TTL_MS : CACHE_TTL_MS;
|
||||
if (!force && cached && Date.now() - cached.fetchedAt < ttl) {
|
||||
render(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const fresh = await fetchUsage(provider);
|
||||
if (provider === "anthropic") {
|
||||
anthropicRetryAfter = 0;
|
||||
}
|
||||
cache[provider] = {
|
||||
usage: {
|
||||
...fresh,
|
||||
@@ -526,18 +559,37 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "fetch failed";
|
||||
const fallback = cache[provider]?.usage;
|
||||
cache[provider] = {
|
||||
usage: {
|
||||
provider,
|
||||
displayName: fallback?.displayName ?? provider,
|
||||
windows: fallback?.windows ?? [],
|
||||
error: message,
|
||||
fetchedAt: Date.now(),
|
||||
const isAnthropic429 = provider === "anthropic" && message.includes("429");
|
||||
|
||||
if (isAnthropic429) {
|
||||
anthropicRetryAfter = Date.now() + 30 * 60 * 1000;
|
||||
}
|
||||
|
||||
if (isAnthropic429 && fallback) {
|
||||
cache[provider] = {
|
||||
usage: {
|
||||
...fallback,
|
||||
fetchedAt: Date.now(),
|
||||
fromCache: true,
|
||||
},
|
||||
lastSuccessAt: cache[provider]?.lastSuccessAt,
|
||||
fromCache: Boolean(fallback),
|
||||
},
|
||||
lastSuccessAt: cache[provider]?.lastSuccessAt,
|
||||
};
|
||||
};
|
||||
} else if (isAnthropic429) {
|
||||
delete cache[provider];
|
||||
} else {
|
||||
cache[provider] = {
|
||||
usage: {
|
||||
provider,
|
||||
displayName: fallback?.displayName ?? provider,
|
||||
windows: fallback?.windows ?? [],
|
||||
error: message,
|
||||
fetchedAt: Date.now(),
|
||||
lastSuccessAt: cache[provider]?.lastSuccessAt,
|
||||
fromCache: Boolean(fallback),
|
||||
},
|
||||
lastSuccessAt: cache[provider]?.lastSuccessAt,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
render(ctx);
|
||||
@@ -608,7 +660,11 @@ export default function createSubBarLocal(pi: ExtensionAPI) {
|
||||
if (!ctx.hasUI) return;
|
||||
render(ctx);
|
||||
if (activeProvider === "auto") {
|
||||
await refreshCurrent(ctx, true);
|
||||
if (getSelectedProvider(ctx) === "anthropic") {
|
||||
render(ctx);
|
||||
} else {
|
||||
await refreshCurrent(ctx, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user