Skip to content

fix(owned-browser): tag eval-with-url navigations with their owner#3934

Merged
louis030195 merged 2 commits into
mainfrom
claude/loving-herschel-ddb7c2
Jun 9, 2026
Merged

fix(owned-browser): tag eval-with-url navigations with their owner#3934
louis030195 merged 2 commits into
mainfrom
claude/loving-herschel-ddb7c2

Conversation

@louis030195

Copy link
Copy Markdown
Collaborator

before / after: a background pipe no longer pops its page into your chat

Problem

When you're in a chat, the browser sidebar sometimes pops open because a background pipe is driving the owned browser. It should only show for the chat that actually drove it.

Root cause

The owned browser is a single webview shared by every chat and every background pipe. Each navigation is tagged with an owner, and the sidebar ignores navigations owned by a chat other than the one on screen. That gate already worked for POST /navigate — it reads the x-screenpipe-session header the agent's curl shim injects (pipe:<name> for a pipe).

The gap: POST /eval with a url (navigate-and-scrape in one call — a common pipe path) never read that header. TauriOwnedHandle::eval hardcoded prepare_navigation(.., None), so the owned-browser:navigate event was emitted with owner = None, which the frontend treats as "the sidebar's own restore/reload" and always reveals.

Fix

Thread the owner through the eval path, mirroring the existing navigate_with_owner chain:

  • browser_run_eval reads x-screenpipe-session and calls eval_with_owner
  • new Browser::eval_with_owner / OwnedWebviewHandle::eval_with_owner (both default to plain eval), overridden by OwnedBrowser and TauriOwnedHandle
  • TauriOwnedHandle::eval_inner threads owner into prepare_navigation

Defensive frontend tightening in isForeignNavigation: a tagged navigation with no bound chat (conversationId null — e.g. a brand-new unsaved chat) is now treated as foreign too, so a pipe can't pop into an empty chat.

Tests

  • connect unit: eval_with_owner forwards the owner to the handle; plain eval stays un-owned
  • engine integration: real axum router, POST /eval with x-screenpipe-session reaches the browser with the owner — this is the repro discriminator (pre-fix it routed through eval and the owner was None)
  • frontend vitest: isForeignNavigation gates a tagged nav when no chat is bound
  • e2e (zz-owned-browser-background-nav): drives the real /eval-with-url path with a foreign owner header and asserts the browser stays hidden

Local run: connect + engine cargo tests, frontend vitest, and bindings:check all green. The wdio GUI e2e runs in CI (not launched locally — there is a live screenpipe on :3030 it would conflict with).

Louis Beaumont and others added 2 commits June 9, 2026 09:02
The owned browser is one webview shared by every chat and every background
pipe. Navigations are owner-tagged so the sidebar ignores ones owned by a chat
other than the one on screen — but only the /navigate endpoint read the
x-screenpipe-session owner header. The navigate-and-scrape /eval path (a pipe
opening a page and reading it in one call) dropped the owner, so its
owned-browser:navigate event was emitted with owner=None, which the frontend
treats as "the sidebar's own action" and always reveals. Result: a background
pipe popped its page into whatever chat you were looking at.

Thread the owner through the eval path, mirroring navigate_with_owner:
- browser_run_eval reads x-screenpipe-session and calls eval_with_owner
- new Browser::eval_with_owner / OwnedWebviewHandle::eval_with_owner (both
  default to the existing eval), overridden by OwnedBrowser + TauriOwnedHandle
- TauriOwnedHandle::eval_inner threads owner into prepare_navigation

Also tighten the frontend gate: a tagged navigation with no bound chat
(conversationId null, e.g. a fresh unsaved chat) is now treated as foreign, so
a background pipe can't pop into an empty chat either.

Tests:
- screenpipe-connect: eval_with_owner forwards owner to the handle; plain eval
  stays un-owned
- screenpipe-engine: POST /eval with x-screenpipe-session reaches the browser
  with the owner (real axum router; would fail pre-fix, which routed through eval)
- frontend vitest: isForeignNavigation gates a tagged nav when no chat is bound
- e2e: zz-owned-browser-background-nav drives the real /eval-with-url path with a
  foreign owner header and asserts the browser stays hidden

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@louis030195 louis030195 merged commit ce75674 into main Jun 9, 2026
26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant