feat(browser): port upstream browser improvements - #291
Conversation
Port bounded browser capture, profile-aware sessions, cookie import, popup auth, browser defaults, and unified link routing while preserving fork-specific preview behavior.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
There are confirmed UI/test correctness issues (e.g., cookie-import target label and browser add-surface submenu test) that should be fixed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Ports a set of upstream preview-browser improvements into this fork, spanning contracts, web UI, server preview session state, and desktop Electron runtime/IPC to support profiles, link-target preference, cookie import, popup handling, and more robust automation/snapshot behavior.
Changes:
- Add browser defaults + profile support across settings, preview open/session snapshots, right-panel entry points, and desktop partition derivation/clearing.
- Introduce consent-based cookie import (Chromium/Firefox/Safari) via new desktop services + IPC contracts and settings UI.
- Improve preview automation host budgeting and desktop capture/keyboard/popup behaviors for reliability and security posture.
File summaries
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds keyring dependency lock entries |
| packages/shared/src/nodeSqliteClient.ts | Shared node:sqlite Effect SQL client |
| packages/shared/package.json | Export nodeSqliteClient entry point |
| packages/contracts/src/settings.ts | Client settings: defaults, profiles, link target |
| packages/contracts/src/previewAutomation.ts | Schema annotations + list-tabs input tweak |
| packages/contracts/src/preview.ts | Viewport/defaults, profileId in snapshots/open |
| packages/contracts/src/ipc.ts | Desktop preview IPC contracts for profiles/import |
| packages/contracts/src/index.ts | Re-export browserProfile/browserImport contracts |
| packages/contracts/src/browserProfile.ts | Browser profile schema + resolution helpers |
| packages/contracts/src/browserProfile.test.ts | Tests for profile resolution/validation |
| packages/contracts/src/browserImport.ts | Cookie import contract + user-facing copy |
| apps/web/src/localApi.test.ts | Update persisted settings test fixtures |
| apps/web/src/components/ui/menu.tsx | MenuSubTrigger icon/layout behavior |
| apps/web/src/components/ThreadTerminalDrawer.tsx | Pass modifier event into link opener |
| apps/web/src/components/settings/SettingsPanels.tsx | UI for browser defaults, profiles, cookie import |
| apps/web/src/components/RightPanelTabs.tsx | Add-surface Browser submenu by profile |
| apps/web/src/components/RightPanelTabs.browser.tsx | Update browser add-surface test wiring |
| apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx | Use unified link-opening logic |
| apps/web/src/components/preview/PreviewView.tsx | Pass env/profile into preview menu |
| apps/web/src/components/preview/PreviewMoreMenu.tsx | Clear cookies/cache scoped by env/profile |
| apps/web/src/components/preview/PreviewAutomationHosts.tsx | Host deadline budgeting for overlay readiness |
| apps/web/src/components/preview/previewAutomationHostBudget.ts | New host wait-budget utilities |
| apps/web/src/components/preview/previewAutomationHostBudget.test.ts | Tests for wait-budget behavior |
| apps/web/src/components/preview/openTerminalLinkInPreview.ts | Route terminal link opens via preference |
| apps/web/src/components/preview/openPreviewSession.ts | Apply default viewport/profile on open |
| apps/web/src/components/preview/openPreviewSession.test.ts | Expect defaults passed to preview.open |
| apps/web/src/components/preview/addBrowserSurface.ts | Allow opening browser surface in profile |
| apps/web/src/components/ChatView.tsx | Plumb profile-aware browser surface creation |
| apps/web/src/components/ChatMarkdown.tsx | Use unified link-opening hook |
| apps/web/src/browser/useOpenLink.ts | New unified open-in-app vs external hook |
| apps/web/src/browser/previewWebviewConfigState.ts | Cache preview config by env+profile key |
| apps/web/src/browser/previewWebviewConfigState.test.ts | Update tests for new signature/keying |
| apps/web/src/browser/HostedBrowserWebview.tsx | Load preview config + tab defaults by profile |
| apps/web/src/browser/ElectronBrowserHost.tsx | Pass profileId into HostedBrowserWebview |
| apps/web/src/browser/desktopTabLifetime.ts | Create tab with default zoom/colorScheme |
| apps/web/src/browser/browserLinkTarget.ts | Link target resolution utilities |
| apps/web/src/browser/browserDefaults.ts | Resolve viewport/zoom/appearance/profile defaults |
| apps/web/src/browser/browserDefaults.test.ts | Tests for default-profile resolution |
| apps/server/src/preview/Manager.ts | Persist viewport/profileId in server snapshots |
| apps/server/src/preview/Manager.test.ts | Test profile retention across events |
| apps/desktop/src/preview/Runtime.ts | Provide BrowserImport layers to runtime |
| apps/desktop/src/preview/Manager.ts | Capture retry, popup handling, refresh shortcut |
| apps/desktop/src/preview/Manager.test.ts | Update mocks + capture timeout test |
| apps/desktop/src/preview/BrowserSession.ts | Profile namespaces + partition scoping/clears |
| apps/desktop/src/preview/BrowserSession.test.ts | Tests for digest encoding + partition disjointness |
| apps/desktop/src/preview/BrowserImport/SafariCookies.ts | Safari binarycookies parser + TCC detection |
| apps/desktop/src/preview/BrowserImport/LinuxBrowserSecret.ts | Locate bundled Linux secret helper |
| apps/desktop/src/preview/BrowserImport/FirefoxCookies.ts | Firefox cookies sqlite reader/import mapping |
| apps/desktop/src/preview/BrowserImport/CookieDatabase.ts | Shared snapshot + cookie shaping helpers |
| apps/desktop/src/preview/BrowserImport/ChromiumKeys.ts | Key acquisition across platforms |
| apps/desktop/src/preview/BrowserImport/ChromiumCookies.ts | Chromium cookie decryption + read pipeline |
| apps/desktop/src/preview/BrowserImport/BrowserImport.ts | Import orchestration + session writes |
| apps/desktop/src/preview/BrowserImport/BrowserImport.test.ts | Primitive tests for decrypt/parsers/scope |
| apps/desktop/src/preload.ts | Expose new preview IPC methods to renderer |
| apps/desktop/src/ipc/methods/preview.ts | IPC methods: profile scoping, clears, import |
| apps/desktop/src/ipc/methods/preview.test.ts | Tests for partition scope derivation |
| apps/desktop/src/ipc/DesktopIpcHandlers.ts | Register new import IPC handlers |
| apps/desktop/src/ipc/channels.ts | Add channels for listing/importing cookies |
| apps/desktop/src/clientPersistence.test.ts | Update client settings fixture for new fields |
| apps/desktop/package.json | Add @napi-rs/keyring dependency |
Review details
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
- Files reviewed: 60/61 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Preserve the opener for unsupported popup URLs rather than weakening Electron blank-window isolation. Ship the Linux libsecret helper and restore tab-owned zoom shortcuts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Review follow-up pushed in
Validation: format, lint and typecheck passed (pre-existing contract warnings). New import-target/deletion Chromium regression, link/PR ownership tests, guest zoom test and packaging test passed. Full Real-client pass used isolated state and exercised creating/selecting/deleting a synthetic profile, confirming the import target label and fallback. Native cookie import was simulated in the Chromium component regression; no real cookies or credentials were accessed. The screenshot below shows that synthetic regression, not a real account import. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Summary
Ports the seven requested browser improvements into the fork as focused vertical slices, preserving the fork's existing preview/runtime architecture and fixes.
de1b798c6)b5fb3fba0)134d51096, fix(web): offer browser profiles from the empty-panel launcher pingdotgg/t3code#9279 /064392ffc)0e2905eb7)39449e53e, feat(desktop): resolve Chromium cookie keys on Linux pingdotgg/t3code#7261 /498ab9c39, fix(desktop): address the browser import review left over from the stack pingdotgg/t3code#9516 /3653cb22f, feat(desktop): import cookies from Safari pingdotgg/t3code#7262 /ed2bdbb27)949feb61e)18062da94)Original implementation validation
pnpm fmt:checkpassedpnpm lintpassed with existing unused-import warnings inpackages/contracts/src/ipc.tspnpm typecheckpassed with existing Effect diagnostic suggestionspnpm testcompleted with 220 test files passing and 2 unrelated existing orchestration integration failures inintegration/orchestrationEngine.integration.test.ts(checkpoint Git refs unavailable)Limitations
scripts/dev-runner.tsfilter argument shape, so the real-client stack was started with equivalent explicit environment variables while retaining isolated state.Review follow-up
Review fixes were pushed in
e1ac18156: import target/consent, terminal routing and defaults, explicitly associated PR browser routing, guest zoom, and Linux native helper delivery. See the review follow-up comment for regression results and a synthetic import-target screenshot.Remaining boundary: blank-first OAuth popups remain unsupported because Electron cannot override inherited about:blank preferences. Rejected URLs no longer replace the opener. PRs without an active explicitly associated thread continue opening links externally.