diff options
| author | Igor Soarez <igor@soarez.org> | 2026-11-08 17:11:15 +0000 |
|---|---|---|
| committer | Igor Soarez <igor@soarez.org> | 2026-11-08 17:11:15 +0000 |
| commit | b8b63ea4d1bad9c4bbac6b05b03cce5f2cfa3f94 (patch) | |
| tree | 255a0979c1d590ea759e27980ca3d9d655b690f5 /extensions/chrome-profile-bridge/browser-extension | |
| parent | b5f7a9eb2cf46867085b46514d6c9faf0d552fad (diff) | |
tabs: back to one window per session; keep new tabs out of the user's window
A window shows only one tab, so sessions sharing one hid each other's tabs: no
real input and blank screenshots for every session but the one whose tab was
active (castle-pirc-web, 2026-11-08). Time-sharing the active tab would flip tabs
under the user while they sign in for an agent, so revert 66fbd30: a session
gets its own unfocused window. Kept: chrome_tab new for a session with no window
opens one for it instead of landing in the user's focused window. The primer
and chrome_tab description now say why to reuse a tab.
Diffstat (limited to 'extensions/chrome-profile-bridge/browser-extension')
| -rw-r--r-- | extensions/chrome-profile-bridge/browser-extension/service_worker.js | 45 |
1 files changed, 14 insertions, 31 deletions
diff --git a/extensions/chrome-profile-bridge/browser-extension/service_worker.js b/extensions/chrome-profile-bridge/browser-extension/service_worker.js index 0ceabda..d47b385 100644 --- a/extensions/chrome-profile-bridge/browser-extension/service_worker.js +++ b/extensions/chrome-profile-bridge/browser-extension/service_worker.js @@ -226,26 +226,12 @@ function isPiChromeOwnedTarget(tabId, sessionKey) { return false; } -// The window agents share. Every session has its own tab group and a group cannot span windows, -// but sessions do not need their own windows: new tabs go to the window that already holds any -// "Pi Session:" group, so agents stay together instead of opening one window each. Returns -// undefined when no such window exists (the first session then creates one). -async function sharedPiWindowId() { - if (!chrome.tabGroups || typeof chrome.windows?.get !== "function") return undefined; - const groups = await chrome.tabGroups.query({}).catch(() => []); - for (const group of groups) { - if (!/^pi session:/i.test((group.title || "").trim()) || typeof group.windowId !== "number") continue; - const win = await chrome.windows.get(group.windowId).catch(() => null); - if (win && (win.type === undefined || win.type === "normal")) return win.id ?? group.windowId; - } - return undefined; -} - // Create a fresh automation target for `sessionKey`. If this session already has a tab group, // create the tab inside that group's window so one Pi session keeps one Chrome tab group (Chrome -// groups cannot span windows). If it has none, use the shared Pi window; only when there is no -// Pi window yet, create one; fall back to a tab. When the tab is created in a pre-existing window, -// leave windowId unset so cleanup only closes our tab, never that whole window. +// groups cannot span windows). If it has none, give the session its own window: a window shows +// only one tab, so sessions sharing a window would hide each other's tabs, and a hidden tab gets no +// real input and blank screenshots (measured 2026-11-08). Fall back to a tab. When the tab is +// created in a pre-existing window, leave windowId unset so cleanup only closes our tab. async function createAutomationTarget(sessionKey, groupTitle) { const existingGroup = groupTitle ? await findGroupRecordByTitle(groupTitle) : null; if (existingGroup && typeof existingGroup.windowId === "number") { @@ -254,14 +240,6 @@ async function createAutomationTarget(sessionKey, groupTitle) { await persistAutomationTargets(); return tab; } - const sharedWindowId = await sharedPiWindowId(); - if (sharedWindowId !== undefined) { - // Someone else's window: leave windowId unset so cleanup only ever closes our tab. - const tab = await chrome.tabs.create({ url: "about:blank", active: false, windowId: sharedWindowId }); - automationTargets.set(sessionKey, { windowId: undefined, tabId: typeof tab.id === "number" ? tab.id : undefined }); - await persistAutomationTargets(); - return tab; - } if (chrome.windows && typeof chrome.windows.create === "function") { try { const win = await chrome.windows.create({ url: "about:blank", focused: false }); @@ -1911,15 +1889,20 @@ async function dispatch(action, params) { const existingGroup = await findGroupRecordByTitle(groupTitle); const createParams = { url: params.url || "about:blank", active: foregroundRequested(params) }; if (existingGroup && typeof existingGroup.windowId === "number") createParams.windowId = existingGroup.windowId; - else { - // No group of this session yet: use the shared Pi window, never the user's focused one. - const sharedWindowId = await sharedPiWindowId(); - if (sharedWindowId !== undefined) createParams.windowId = sharedWindowId; + // No group of this session yet: use the window of its automation tab if it has one, else open + // the tab in a window of its own. Never the user's focused window, where Chrome would put it. + let ownWindow = false; + if (createParams.windowId === undefined) { + const home = await resolveOwnedAutomationTarget(sessionKeyOf(params)).catch(() => null); + if (home && typeof home.windowId === "number") createParams.windowId = home.windowId; + else ownWindow = typeof chrome.windows?.create === "function"; } // Register the creation as in flight until the tab is tracked, so early capture (which only // runs in tracked tabs) waits for it instead of skipping the new tab's first page load. const creation = (async () => { - const created = await chrome.tabs.create(createParams); + const created = ownWindow + ? (await chrome.windows.create({ url: createParams.url, focused: false })).tabs[0] + : await chrome.tabs.create(createParams); await trackSessionTab(sessionKeyOf(params), created.id, true); return created; })(); |
