all repos — sz-chrome-remote-extension @ dce772f330db12a73e85297918882c0c4f28f030

pi-chrome, patched to drive a signed-in browser on another host through a broker, with an MCP server

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
commit

dce772f330db12a73e85297918882c0c4f28f030

parent

35bebbbb35d4f461ca6d3302294b45d5602eca13

1 files changed, 37 insertions(+), 1 deletions(-)

jump to
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];