feat: show remaining auth time in Chrome Bridge status bar (#5)
* 0.15.36: richer chrome_snapshot + chrome_find/chrome_inspect (ported from foxfirecodes fork)
- chrome_snapshot returns a concise observation (layout, hints, actions, forms,
page map, query matches, diff) with mode/query/maxTextChars params
- new chrome_find (query -> ranked uids) and chrome_inspect (deep element context,
with page.inspect fallback)
- includeSnapshot on click/type/fill/key now embeds the formatted snapshot
- snapshot/inspect logic shipped as eval-free packaged snapshot_injected.js,
sharing window.__PI_CHROME_STATE__ (el- uid scheme) with existing input helpers
* feat: show remaining auth time in Chrome Bridge status bar
Before: ● Chrome Bridge
After: ● Chrome Bridge (14m)
● Chrome Bridge (indefinite)
Changes:
- authCountdownLabel() computes remaining minutes from chromeAuthorizedUntil
- updateChromeStatus appends the label to the status line
- startCountdownTicker() runs setInterval every 60s to refresh the display
while a timed authorization is active; no-ops for indefinite auth
- clearCountdownInterval() called in lockChromeControl and session_shutdown
so no interval leaks on revoke or reload
- scheduleAuthExpiry calls startCountdownTicker so the ticker starts
whenever authorization is granted or restored after /reload
---------
Co-authored-by: Tianren Dong <tianrendong.dtr@gmail.com>
TJ Dong 122852285+tj-dong@users.noreply.github.com
Mon, 08 Jun 2026 20:39:14 -0700
1 files changed,
37 insertions(+),
1 deletions(-)
M
extensions/chrome-profile-bridge/index.ts
→
extensions/chrome-profile-bridge/index.ts
@@ -702,6 +702,7 @@ else globalState[PI_CHROME_AUTH_KEY] = { until: chromeAuthorizedUntil };
}; let chromeToolsRegistered = false; let authExpiryTimer: NodeJS.Timeout | undefined; + let countdownInterval: NodeJS.Timeout | undefined; // Remembered so bridge sends can tag tabs with this session's group even when ctx isn't handy. let sessionCtx: ExtensionContext | undefined;@@ -709,6 +710,12 @@ const clearAuthExpiryTimer = (): void => {
if (!authExpiryTimer) return; clearTimeout(authExpiryTimer); authExpiryTimer = undefined; + }; + + const clearCountdownInterval = (): void => { + if (!countdownInterval) return; + clearInterval(countdownInterval); + countdownInterval = undefined; }; const activeToolNamesWithoutChrome = (): string[] => pi.getActiveTools().filter((name) => !CHROME_TOOL_NAME_SET.has(name));@@ -724,6 +731,7 @@ };
const lockChromeControl = (): void => { clearAuthExpiryTimer(); + clearCountdownInterval(); chromeAuthorizedUntil = undefined; persistAuth(); deactivateChromeTools();@@ -759,16 +767,42 @@ const id = sm.getSessionId?.();
return `Pi Session: ${name || id || "unknown"}`; }; + const authCountdownLabel = (): string => { + if (chromeAuthorizedUntil === "indefinite") return " (indefinite)"; + if (typeof chromeAuthorizedUntil === "number") { + const remainingMs = chromeAuthorizedUntil - Date.now(); + if (remainingMs > 0) { + const mins = Math.ceil(remainingMs / 60_000); + return mins >= 1 ? ` (${mins}m)` : " (<1m)"; + } + } + return ""; + }; + const updateChromeStatus = (ctx: ExtensionContext): void => { if (chromeControlAuthorized()) { - ctx.ui.setStatus("chrome", ctx.ui.theme.fg("success", "●") + " Chrome Bridge"); + ctx.ui.setStatus("chrome", ctx.ui.theme.fg("success", "●") + " Chrome Bridge" + authCountdownLabel()); } else { ctx.ui.setStatus("chrome", undefined); } }; + // Ticks every 60 s while a timed authorization is active to keep the countdown current. + const startCountdownTicker = (ctx: ExtensionContext): void => { + clearCountdownInterval(); + if (chromeAuthorizedUntil === "indefinite" || typeof chromeAuthorizedUntil !== "number") return; + countdownInterval = setInterval(() => { + if (!chromeControlAuthorized()) { + clearCountdownInterval(); + return; + } + updateChromeStatus(ctx); + }, 60_000); + }; + const scheduleAuthExpiry = (ctx: ExtensionContext, until: number | "indefinite"): void => { clearAuthExpiryTimer(); + startCountdownTicker(ctx); if (until === "indefinite") return; authExpiryTimer = setTimeout(() => { if (chromeAuthorizedUntil !== until) return;@@ -816,12 +850,14 @@ // Reestablish in-memory state after a /reload restored chromeAuthorizedUntil from globalThis.
if (chromeControlAuthorized()) { activateChromeTools(); if (typeof chromeAuthorizedUntil === "number") scheduleAuthExpiry(ctx, chromeAuthorizedUntil); + else if (chromeAuthorizedUntil === "indefinite") startCountdownTicker(ctx); } updateChromeStatus(ctx); }); pi.on("session_shutdown", () => { clearAuthExpiryTimer(); + clearCountdownInterval(); bridge.stop(); if (globalState[PI_CHROME_GLOBAL_KEY]?.token === instanceToken) { delete globalState[PI_CHROME_GLOBAL_KEY];