pi-chrome 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # pi-chrome
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/pi-chrome.svg)](https://www.npmjs.com/package/pi-chrome)
4
+
3
5
  Control the Chrome profile you already use from Pi.
4
6
 
5
7
  `pi-chrome` gives Pi agents browser tools for your **real Chrome windows, tabs, and authenticated sessions**. It uses a companion Chrome extension instead of the Chrome DevTools Protocol (CDP), so it does not launch a throwaway debug browser profile and does not require re-signing into the apps you already have open.
@@ -25,6 +27,10 @@ For local development from a checkout:
25
27
  pi install ./pi-chrome
26
28
  ```
27
29
 
30
+ ### Why an unpacked Chrome extension?
31
+
32
+ `pi-chrome` cannot ship through the Chrome Web Store: a Web Store extension is not allowed to talk to a local bridge controlled by another tool. Instead it ships as a small, MIT-licensed unpacked extension in `extensions/chrome-profile-bridge/browser-extension/` — read the source before loading. `/chrome-doctor` reports the loaded extension version and warns when it drifts from the installed `pi-chrome`.
33
+
28
34
  ## First-time setup
29
35
 
30
36
  In Pi, run:
@@ -93,6 +99,32 @@ Local web app repro with screenshot:
93
99
  Use chrome_tab list to find my localhost app, inspect it with chrome_snapshot, navigate through the bug repro flow, and save a screenshot when you reach the broken state.
94
100
  ```
95
101
 
102
+ ## Recipes
103
+
104
+ Copy-paste these into Pi after setup. Each one uses tabs you already have open and accounts you are already signed into.
105
+
106
+ - **PR triage:** "Use chrome_tab list to find my GitHub notifications tab, snapshot it, and summarize PRs needing my review."
107
+ - **Linear standup:** "Open my Linear current cycle in the active tab, snapshot it, and write me a 5-bullet standup."
108
+ - **Bug repro with evidence:** "Open the staging app I'm already signed into, reproduce <bug>, and save a screenshot of each step under ./repro/."
109
+ - **Form auto-fill (no submit):** "Open <vendor> portal, fill the new-vendor form from this JSON, but stop before submit."
110
+ - **Admin cross-check:** "Across my Stripe / Postmark / our admin tabs, find any user where state disagrees."
111
+ - **Local dev visual diff:** "Snapshot localhost:3000 and the staging URL of the same page; tell me what's visually different."
112
+ - **Auth-only data pull:** "Open my analytics dashboard tab and chrome_evaluate to extract today's KPIs from the page state."
113
+
114
+ Screenshots save under `.pi/chrome-screenshots/` by default, which composes nicely with PR demo workflows.
115
+
116
+ ## Diagnostics
117
+
118
+ - `/chrome-status` — quick health check; reports the connected Chrome extension ID and version.
119
+ - `/chrome-doctor` — deeper diagnosis with one-line fixes for common setup failures (extension not loaded, bridge owner stale after `pi update`, version mismatch between pi-chrome and the loaded Chrome extension).
120
+
121
+ If the Chrome extension you have loaded is older than `pi-chrome` on disk, `/chrome-doctor` will tell you to reload it from `chrome://extensions`.
122
+
123
+ ## Compose with
124
+
125
+ - **pi-qq** — ask side questions about what the agent saw in Chrome without polluting the main transcript: `/qq summarize what the active GitHub tab shows`.
126
+ - **PR demo skills** (such as `ios-pr-agent` / `ios-demo-record` workflows) — `chrome_screenshot` writes to `.pi/chrome-screenshots/` so you can attach images to PR descriptions or demo bundles.
127
+
96
128
  ## Tools
97
129
 
98
130
  The package registers these Pi tools:
@@ -110,7 +142,8 @@ The package registers these Pi tools:
110
142
 
111
143
  These tools are especially useful for authenticated web app debugging, repro flows, admin workflows, visual checks, and inspecting local development pages without rebuilding login state.
112
144
 
113
- ## How it works
145
+ <details>
146
+ <summary><strong>How it works (technical details)</strong></summary>
114
147
 
115
148
  Pi starts a local bridge on `127.0.0.1:17318`. The companion Chrome extension, installed in your normal Chrome profile, polls that local bridge for commands and executes them using Chrome extension APIs.
116
149
 
@@ -118,6 +151,8 @@ If another Pi session is already running the bridge, additional Pi sessions auto
118
151
 
119
152
  This is intentionally different from CDP-based tools: the browser extension lives inside the profile you already use, so Pi can interact with existing tabs and authenticated page state.
120
153
 
154
+ </details>
155
+
121
156
  ## Security model
122
157
 
123
158
  The companion Chrome extension runs in the Chrome profile where you install it and has broad tab/scripting permissions. Only install it from a package source you trust.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "Pi Existing Chrome Profile Bridge",
4
- "version": "0.1.0",
4
+ "version": "0.4.0",
5
5
  "description": "Lets Pi control tabs in this existing Chrome profile via a local bridge at 127.0.0.1.",
6
6
  "permissions": ["tabs", "scripting", "storage", "activeTab", "alarms"],
7
7
  "host_permissions": ["<all_urls>", "http://127.0.0.1:17318/*"],
@@ -80,7 +80,12 @@ function sleep(ms) {
80
80
  async function dispatch(action, params) {
81
81
  switch (action) {
82
82
  case "tab.version":
83
- return { extensionId: chrome.runtime.id, bridgeUrl: BRIDGE_URL, userAgent: navigator.userAgent };
83
+ return {
84
+ extensionId: chrome.runtime.id,
85
+ extensionVersion: chrome.runtime.getManifest().version,
86
+ bridgeUrl: BRIDGE_URL,
87
+ userAgent: navigator.userAgent,
88
+ };
84
89
  case "tab.list":
85
90
  return (await chrome.tabs.query({})).map(formatTab);
86
91
  case "tab.new": {
@@ -46,6 +46,7 @@ type BridgeResult = {
46
46
  error?: string;
47
47
  };
48
48
 
49
+ const PI_CHROME_VERSION = "0.4.0";
49
50
  const DEFAULT_HOST = process.env.PI_CHROME_BRIDGE_HOST ?? "127.0.0.1";
50
51
  const DEFAULT_PORT = Number(process.env.PI_CHROME_BRIDGE_PORT ?? "17318");
51
52
  const DEFAULT_TIMEOUT_MS = 30_000;
@@ -351,19 +352,50 @@ If chrome_* tools time out, ask the user to run /chrome-onboard, then load the b
351
352
  handler: async (_args, ctx) => {
352
353
  ctx.ui.notify("Performing Chrome bridge health check", "info");
353
354
  try {
354
- const version = (await bridge.send("tab.version", {}, 35_000)) as { extensionId?: string };
355
- ctx.ui.notify(
356
- version.extensionId
357
- ? `Chrome profile bridge connected (ID: ${version.extensionId})`
358
- : "Chrome profile bridge connected",
359
- "info",
360
- );
355
+ const version = (await bridge.send("tab.version", {}, 35_000)) as { extensionId?: string; extensionVersion?: string };
356
+ const suffix = [version.extensionId ? `ID: ${version.extensionId}` : null, version.extensionVersion ? `ext v${version.extensionVersion}` : null]
357
+ .filter(Boolean)
358
+ .join(", ");
359
+ ctx.ui.notify(suffix ? `Chrome profile bridge connected (${suffix})` : "Chrome profile bridge connected", "info");
361
360
  } catch (error) {
362
361
  ctx.ui.notify(`Chrome bridge health check failed: ${(error as Error).message}`, "warning");
363
362
  }
364
363
  },
365
364
  });
366
365
 
366
+ pi.registerCommand("chrome-doctor", {
367
+ description:
368
+ "Diagnose Chrome bridge setup. Checks the local bridge, the companion Chrome extension, and reports a one-line fix for common failures.",
369
+ handler: async (_args, ctx) => {
370
+ const lines: string[] = [`pi-chrome v${PI_CHROME_VERSION}`];
371
+ const status = bridge.status();
372
+ lines.push(`• Local bridge: mode=${status.mode}, url=${status.url}`);
373
+ try {
374
+ const version = (await bridge.send("tab.version", {}, 8_000)) as {
375
+ extensionId?: string;
376
+ extensionVersion?: string;
377
+ };
378
+ if (version.extensionId)
379
+ lines.push(`✓ Companion Chrome extension responding (ID: ${version.extensionId}, ext v${version.extensionVersion ?? "unknown"})`);
380
+ else lines.push("✓ Companion Chrome extension responding (no extension ID reported)");
381
+ if (version.extensionVersion && version.extensionVersion !== PI_CHROME_VERSION) {
382
+ lines.push(
383
+ `⚠ Extension version (${version.extensionVersion}) differs from pi-chrome (${PI_CHROME_VERSION}). Reload "Pi Existing Chrome Profile Bridge" in chrome://extensions to pick up the latest service worker.`,
384
+ );
385
+ }
386
+ } catch (error) {
387
+ const message = (error as Error).message;
388
+ lines.push(`✗ Companion Chrome extension not responding: ${message}`);
389
+ if (message.includes("older pi-chrome without multi-session")) {
390
+ lines.push(" Fix: restart the Pi session that owns the bridge (it was started on an older pi-chrome).");
391
+ } else {
392
+ lines.push(" Fix: run /chrome-onboard, then load the bundled browser-extension folder in chrome://extensions and keep that Chrome window open.");
393
+ }
394
+ }
395
+ ctx.ui.notify(lines.join("\n"), "info");
396
+ },
397
+ });
398
+
367
399
  pi.registerCommand("chrome-foreground", {
368
400
  description:
369
401
  "Toggle whether chrome_* tools bring Chrome to the foreground. Foreground ON: you can watch the agent work in your browser, useful for demos, pair-driving, and debugging — tradeoff: Chrome pops up and steals focus, interrupting whatever app you were using. Foreground OFF (default): chrome_* tools act silently in the background, so your editor/terminal keeps focus and your workflow is not interrupted. Pass `on` / `off` to set explicitly, or no argument to toggle.",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-chrome",
3
- "version": "0.3.2",
4
- "description": "Control your existing authenticated Chrome profile from Pi with tabs, snapshots, clicks, typing, JS evaluation, waits, and screenshots \u2014 background by default.",
3
+ "version": "0.4.1",
4
+ "description": "Drive your existing logged-in Chrome from Pi \u2014 no re-login, no throwaway profile, background by default.",
5
5
  "keywords": [
6
6
  "pi-package",
7
7
  "pi-extension",