← Commit history

v2.0.676 (insiders): pup-bridge#124 (one verb surface, image fullPath/safePath, ok and output fields on every reply) plus two recovery fixes for multi-tab windows after an upgrade: a new extension-lane tab opens only in the window pup names (the extension refuses rather than guess; tabs had landed in another thread's window), and reopened tabs are de-duplicated by exact URL (stripping the query had dropped different pages on one path).

John Lauer ·7547aaf944 ·1mo ago ·parent 645be41
5 files changed +36−20
rust/Cargo.lock+12−12
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"  [[package]] name = "adom-pup-bridge"-version = "2.0.674"+version = "2.0.676" dependencies = [  "pup-browser",  "pup-cdp",@@ -655,7 +655,7 @@ dependencies = [  [[package]] name = "pup-browser"-version = "2.0.674"+version = "2.0.676" dependencies = [  "pup-core",  "pup-host",@@ -667,7 +667,7 @@ dependencies = [  [[package]] name = "pup-cdp"-version = "2.0.674"+version = "2.0.676" dependencies = [  "serde_json",  "thiserror",@@ -677,7 +677,7 @@ dependencies = [  [[package]] name = "pup-core"-version = "2.0.674"+version = "2.0.676" dependencies = [  "serde",  "serde_json",@@ -687,7 +687,7 @@ dependencies = [  [[package]] name = "pup-dashboard"-version = "2.0.674"+version = "2.0.676" dependencies = [  "pup-cdp",  "pup-core",@@ -700,7 +700,7 @@ dependencies = [  [[package]] name = "pup-host"-version = "2.0.674"+version = "2.0.676" dependencies = [  "serde",  "serde_json",@@ -709,14 +709,14 @@ dependencies = [  [[package]] name = "pup-host-mac"-version = "2.0.674"+version = "2.0.676" dependencies = [  "pup-host", ]  [[package]] name = "pup-host-win"-version = "2.0.674"+version = "2.0.676" dependencies = [  "pup-core",  "pup-host",@@ -726,7 +726,7 @@ dependencies = [  [[package]] name = "pup-identity"-version = "2.0.674"+version = "2.0.676" dependencies = [  "fontdue",  "image",@@ -736,7 +736,7 @@ dependencies = [  [[package]] name = "pup-session"-version = "2.0.674"+version = "2.0.676" dependencies = [  "pup-core",  "serde",@@ -746,7 +746,7 @@ dependencies = [  [[package]] name = "pup-vault"-version = "2.0.674"+version = "2.0.676" dependencies = [  "pup-core",  "pup-host",@@ -757,7 +757,7 @@ dependencies = [  [[package]] name = "pup-verbs"-version = "2.0.674"+version = "2.0.676" dependencies = [  "base64",  "png 0.17.16",
rust/Cargo.toml+1−1
@@ -4,7 +4,7 @@ members = ["core", "host", "host-win", "host-mac", "cdp", "browser", "session",  # One version for the whole bridge, in lockstep with src/BRIDGE_VERSION (tools/ship.sh bumps both). [workspace.package]-version = "2.0.674"+version = "2.0.676" edition = "2021" license = "MIT" 
rust/verbs/src/recovery.rs+4−1
@@ -173,7 +173,10 @@ pub fn relaunch_from_file(ctx: &Ctx, f: &Value) {     if r["ok"] == json!(true) {         // 2.0.478: dedup the reopened tabs by base URL (and drop the active url) so a file that accumulated a         // duplicate never reopens the same page twice.-        let base = |u: &str| u.split('?').next().unwrap_or("").trim_end_matches('/').to_string();+        // 2.0.675: exact URLs (only a trailing slash ignored). Stripping the query collapsed different pages on one+        // path (two YouTube videos, two search results, example.org/?a2 and ?a3): a recovered window came back with+        // 2 of its 4 tabs on CRR, 2026-09-22.+        let base = |u: &str| u.trim_end_matches('/').to_string();         let mut seen: Vec<String> = vec![base(&url)];         let rest: Vec<String> = f["tabs"].as_array().map(|a| a.iter().filter_map(|t| t["url"].as_str()).map(|u| u.to_string()).filter(|u| {             let b = base(u);
rust/verbs/src/transport.rs+5−1
@@ -136,7 +136,11 @@ pub fn open_tab(lane: &Lane, s: &mut Session, url: &str) -> Result<Tab, Value> {             // 20 s: a slow site (nordicsemi behind Cloudflare) must return BEFORE ab's ~60 s relay gives up, or the             // tab opens in Chrome while the caller sees "Request timed out" and pup never records it. The title             // fills in on the next listing; refresh_all also adopts any tab pup missed.-            let r = run(json!({ "action": "newtab", "url": url, "windowId": s.window_id, "waitMs": 20000 }), 40)?;+            // 2.0.675: name the window twice over (a live tab in it, and its Chrome window id); the worker refuses+            // rather than guess, so a tab can never land in another thread's window again.+            let anchor = s.active().map(ext_id).filter(|v| !v.is_null()).or_else(|| s.tabs.iter().map(ext_id).find(|v| !v.is_null()));+            if anchor.is_none() && s.window_id.is_none() { return Err(err("window_not_found", "pup does not know which Chrome window this session is (no tab, no window id); refusing to open a tab in some other window", Some("pup_my_windows shows the window's state; pup_open_window with this window name opens it fresh."))); }+            let r = run(json!({ "action": "newtab", "url": url, "tabId": anchor, "windowId": s.window_id, "waitMs": 20000 }), 40)?;             let id = r["tabId"].as_i64().ok_or_else(|| err("ext_no_tab", "the extension opened no tab", None))?;             Ok(ext_tab(s, id, r["url"].as_str().unwrap_or(url), r["title"].as_str().unwrap_or("")))         }
src/extension/worker.js+14−5
@@ -402,11 +402,20 @@ async function pupExtPollOnce() {     } else if (cmd.action === 'newtab') {       // a TAB in the SAME window: the channel could only create new WINDOWS, so it could not show many       // pages in one window the way the CDP lane does.-      const ref = await pupExtTab(cmd);-      const t = await chrome.tabs.create({ url: cmd.url || 'about:blank', windowId: (ref && ref.windowId) || undefined, active: false });-      await pupExtWaitComplete(t.id, cmd.waitMs || 30000);-      const t2 = await chrome.tabs.get(t.id);-      out = { id: cmd.id, ok: true, tabId: t.id, windowId: t2.windowId, url: t2.url, title: t2.title };+      // 2.0.675: the new tab goes into the window pup NAMED (its tab, else its windowId), never a guess. The old+      // fallback (pupExtTab: any real page in the browser) put a recovered window's reopened tabs into ANOTHER+      // thread's window after an upgrade (AdomLapper, 2026-09-22: 6 of Cohort-IV's tabs in adom-insiders' window).+      let wid = null;+      if (cmd.tabId) { try { wid = (await chrome.tabs.get(cmd.tabId)).windowId; } catch (e) {} }+      if (!wid && cmd.windowId) { try { wid = (await chrome.windows.get(cmd.windowId)).id; } catch (e) {} }+      if (!wid) {+        out = { id: cmd.id, ok: false, errorCode: 'window_not_found', error: 'the window this tab belongs in is gone (no live tab or window id); not opening it in another window' };+      } else {+        const t = await chrome.tabs.create({ url: cmd.url || 'about:blank', windowId: wid, active: false });+        await pupExtWaitComplete(t.id, cmd.waitMs || 30000);+        const t2 = await chrome.tabs.get(t.id);+        out = { id: cmd.id, ok: true, tabId: t.id, windowId: t2.windowId, url: t2.url, title: t2.title };+      }     } else if (cmd.action === 'activate') {       const t = await pupExtTab(cmd);       await chrome.tabs.update(t.id, { active: true });