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