aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md14
-rw-r--r--extensions/chrome-profile-bridge/browser-extension/manifest.json2
-rw-r--r--extensions/chrome-profile-bridge/index.ts27
-rw-r--r--package.json2
4 files changed, 39 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99af471..5f2fed8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,20 @@
All notable user-facing changes to `pi-chrome`.
+## 0.17.1 — 2026-05-16
+
+### Fix: `/chrome onboard` stuck on "Waiting for the extension to wake up…"
+
+0.17.0 made the daemon (not the Pi process) own the HTTP listener, but the Pi client's
+`bridge.status().connected` still reflected the *local Pi*'s `lastSeenAt`, which never gets
+updated in the daemon model. Result: onboard's connect-wait loop spun forever even when the
+extension was happily polling the daemon.
+
+- New `ChromeProfileBridge.daemonStatus()` async method: fetches the daemon's `/status` and
+ returns its view (the only correct source of truth in 0.17+).
+- `/chrome onboard`, `/chrome doctor`, `/chrome status` now query `daemonStatus()` for the
+ `connected` flag instead of reading stale Pi-side `lastSeenAt`.
+
## 0.17.0 — 2026-05-16
### Standalone daemon (no more owner-vs-client topology)
diff --git a/extensions/chrome-profile-bridge/browser-extension/manifest.json b/extensions/chrome-profile-bridge/browser-extension/manifest.json
index dd7d19a..98f47a5 100644
--- a/extensions/chrome-profile-bridge/browser-extension/manifest.json
+++ b/extensions/chrome-profile-bridge/browser-extension/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Pi Chrome Connector",
- "version": "0.17.0",
+ "version": "0.17.1",
"description": "Lets Pi control tabs in Chrome via a local connector at 127.0.0.1.",
"permissions": [
"tabs",
diff --git a/extensions/chrome-profile-bridge/index.ts b/extensions/chrome-profile-bridge/index.ts
index c20cf9a..db41ce3 100644
--- a/extensions/chrome-profile-bridge/index.ts
+++ b/extensions/chrome-profile-bridge/index.ts
@@ -895,6 +895,22 @@ class ChromeProfileBridge {
console.warn(`pi-chrome: killed PID ${pid}; will spawn the daemon next.`);
}
+ // Probe the daemon's /status and return its view (which is the only source of truth for
+ // `connected` / `lastSeenAt` in 0.17+, since the extension polls the daemon, not Pi).
+ async daemonStatus(timeoutMs = 1_000): Promise<Record<string, unknown> | undefined> {
+ const controller = new AbortController();
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
+ try {
+ const res = await fetch(`${this.url}/status`, { signal: controller.signal });
+ if (!res.ok) return undefined;
+ return (await res.json()) as Record<string, unknown>;
+ } catch {
+ return undefined;
+ } finally {
+ clearTimeout(timer);
+ }
+ }
+
// Signed admin RPC to the daemon. Used for state mutations the daemon owns: arm-pair-window,
// reset, status. Pre-pair (when the daemon has no state file), unauthenticated; once paired,
// the daemon requires the broker-key envelope (same signature as /command).
@@ -1453,7 +1469,7 @@ Usage rules:
// the doctor command for the full 35s waiting for a response that will never come.
if (!bridge.bridgeAuth.paired) {
lines.push("✗ Skipping extension probe — bridge isn't paired yet. Run /chrome onboard.");
- } else if (!status.connected) {
+ } else if (!(await bridge.daemonStatus(1_500))?.connected) {
lines.push(
"✗ Chrome extension hasn't polled the bridge recently.",
" Fix: load the extension via /chrome onboard, keep that Chrome window open, then re-run /chrome doctor.",
@@ -1744,11 +1760,13 @@ Usage rules:
// poll = lastSeenAt updates = `bridge.status().connected` flips true.
ctx.ui.notify("Waiting for the extension to wake up and poll the bridge…", "info");
const connectStart = Date.now();
+ let connected = false;
while (Date.now() - connectStart < 15_000) {
- if (bridge.status().connected) break;
+ const ds = await bridge.daemonStatus(1_500);
+ if (ds && ds.connected === true) { connected = true; break; }
await new Promise((r) => setTimeout(r, 500));
}
- if (!bridge.status().connected) {
+ if (!connected) {
ctx.ui.notify(
[
"✗ The Chrome extension didn't poll the bridge within 15 s.",
@@ -1837,7 +1855,8 @@ Usage rules:
if (!bridge.bridgeAuth.paired) {
return "✗ Chrome bridge not paired (run /chrome onboard)";
}
- if (!bridge.status().connected) {
+ const ds = await bridge.daemonStatus(1_000);
+ if (!ds?.connected) {
return "✗ Chrome extension not polling (load extension via /chrome onboard, keep Chrome open)";
}
try {
diff --git a/package.json b/package.json
index 6b38254..1813de4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "pi-chrome",
- "version": "0.17.0",
+ "version": "0.17.1",
"scripts": {
"version": "node scripts/sync-manifest-version.js",
"prepublishOnly": "node scripts/sync-manifest-version.js"