← Commit history

Scrub personal emails from extension/bridge/host source + rebuild store zip

John Lauer ·527e9fbaed · ·parent 59e1f97
3 files changed +6−6
bridge/server.js+4−4
@@ -54,7 +54,7 @@ const pending = new Map(); // id -> { resolve, timer } let lastVerb = null, lastActivityAt = 0;  // ---- multi-profile connections ---------------------------------------------// One bridge can hold a host connection PER BROWSER PROFILE ([email protected], [email protected], …) so the+// One bridge can hold a host connection PER BROWSER PROFILE ([email protected], [email protected], …) so the // AI can drive any of the user's signed-in browsers. By default we'll drive all of them (the user can // switch the active one or blocklist any they don't want touched). Each host sends a `hello {profile}` // handshake on connect; we key the connection by profile email (or a stable fallback id).@@ -64,7 +64,7 @@ let provSeq = 0;           // provisional keys for hosts that haven't sent their // Connections are keyed by BROWSER + PROFILE so the same account signed into Chrome AND Edge (or any // browser/profile combo) are DISTINCT, independently-addressable connections that coexist — letting // multiple AI threads each drive a different browser/profile in parallel without colliding. e.g.-// "chrome:[email protected]", "edge:[email protected]", "chrome:[email protected]".+// "chrome:[email protected]", "edge:[email protected]", "chrome:[email protected]". function profileKey(p) {   const b = (p && p.browser) || 'chrome';   const id = (p && (p.email || p.id)) || 'unknown';@@ -88,7 +88,7 @@ function targetConn(args) {   const wantBrowser = args && args.browser; // optional: disambiguate the SAME email across browsers   if (want) {     if (isBlocked(String(want))) return { blocked: true, key: String(want) };-    // `want` may be a full key ("edge:[email protected]") or just an email — match either, and if a browser+    // `want` may be a full key ("edge:[email protected]") or just an email — match either, and if a browser     // is also given require it (so parallel threads can pin "this email in THIS browser").     for (const [k, c] of conns) {       if (!(c.sock && !c.sock.destroyed)) continue;@@ -380,7 +380,7 @@ function dispatch(verb, args) {     // --- multi-profile management (bridge-local) ---     if (verb === 'nbrowser_profiles') {       const list = [...conns.entries()].map(([k, c]) => ({ profile: k, label: profileLabel(c.profile), email: c.profile.email || '', browser: c.profile.browser || 'chrome', active: k === activeProfile, blocked: isBlocked(k), live: !!(c.sock && !c.sock.destroyed) }));-      return resolve({ success: true, output: JSON.stringify({ ok: true, profiles: list, active: activeProfile, blocklist: [...blocklist], _hint: 'Each entry is one BROWSER×PROFILE the AI can drive — `profile` is the addressable key like "edge:[email protected]" (browser:email). Target any of them in PARALLEL by passing profile:"<key>" (or profile:"<email>"+browser:"edge") on any verb — different AI threads can each drive a different one at once. ▶active is only the default when no target is passed. Switch the default with nbrowser_use_profile; exclude one with nbrowser_profile_block.' }) });+      return resolve({ success: true, output: JSON.stringify({ ok: true, profiles: list, active: activeProfile, blocklist: [...blocklist], _hint: 'Each entry is one BROWSER×PROFILE the AI can drive — `profile` is the addressable key like "edge:[email protected]" (browser:email). Target any of them in PARALLEL by passing profile:"<key>" (or profile:"<email>"+browser:"edge") on any verb — different AI threads can each drive a different one at once. ▶active is only the default when no target is passed. Switch the default with nbrowser_use_profile; exclude one with nbrowser_profile_block.' }) });     }     if (verb === 'nbrowser_use_profile') {       const want = String((args && (args.profile || args.email)) || '');
extension/src/sw.js+1−1
@@ -68,7 +68,7 @@ function connect() { }  // Tell the host+bridge which browser PROFILE this is, so one bridge can hold a connection per profile-// ([email protected], [email protected], …) and the AI can target/switch between them. Email comes from+// ([email protected], [email protected], …) and the AI can target/switch between them. Email comes from // chrome.identity; if the profile isn't signed into Google, fall back to a stable random id. let helloSent = false; async function sendHello() {
host/native-host.js+1−1
@@ -30,7 +30,7 @@ const HOSTFILE = path.join(BRIDGE_DIR, 'host.json'); // ---- PER-PROFILE SINGLETON guard ------------------------------------------- // Native-messaging hosts must NOT accumulate. The 2026-06-19 machine-wide port exhaustion was caused // by N hosts each retrying connect()/sec. The rule is now ONE host PER BROWSER PROFILE (not one per-// machine) so several profiles ([email protected], [email protected], …) can each drive concurrently — but a+// machine) so several profiles ([email protected], [email protected], …) can each drive concurrently — but a // single profile still can't spawn a pile of hosts. The profile id arrives in the extension's `hello` // handshake (see pumpStdin); until then no lock is held, and a fallback timer takes a 'default' lock if // no hello ever comes (old extension), preserving the original single-host loop-safety.