fix(browser): reveal panel for agent captures

Fixes #3175
This commit is contained in:
Bohdan Triapitsyn
2026-08-28 14:06:43 +03:00
parent 262397f896
commit 3f3d942aab
2 changed files with 47 additions and 5 deletions
@@ -452,13 +452,12 @@ export const ContextPanel: React.FC = () => {
// Lets an agent's browser.open create the tab it needs when none is open yet.
// Registered from the panel because opening a tab is panel state, not
// something the browser view itself can do before it exists. Background on
// purpose: an agent working a page must not pop the panel open (or steal
// the active surface) under the user — the tab mounts invisibly, and the
// rail is where the user opens it when curious.
// something the browser view itself can do before it exists. Reveal the
// panel so Electron gives the webview a composited surface; capturePage()
// cannot capture the zero-width webview inside a closed panel.
React.useEffect(() => {
if (!effectiveDirectory) return;
return registerBrowserOpener((url) => openContextBrowser(effectiveDirectory, url, { reveal: false }));
return registerBrowserOpener((url) => openContextBrowser(effectiveDirectory, url));
}, [effectiveDirectory, openContextBrowser]);
const reorderContextPanelTabs = useUIStore((state) => state.reorderContextPanelTabs);
const setSelectedFilePath = useFilesViewTabsStore((state) => state.setSelectedPath);
@@ -0,0 +1,43 @@
/**
* Regression coverage for https://github.com/openchamber/openchamber/issues/3175
*
* A full ContextPanel mount is not available in bun test because its import
* graph includes a Vite worker URL. This test follows the source-level guard
* pattern used by the neighboring ContextPanel regression tests and exercises
* the real store behavior that the registered opener delegates to.
*/
import { beforeEach, describe, expect, test } from 'bun:test';
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { useUIStore } from '@/stores/useUIStore';
const __dirname = dirname(fileURLToPath(import.meta.url));
const contextPanelSource = readFileSync(join(__dirname, '..', 'ContextPanel.tsx'), 'utf-8');
const DIRECTORY = '/path/to/repository';
beforeEach(() => {
useUIStore.setState({ contextPanelByDirectory: {}, contextRailOrder: [] });
});
describe('issue #3175 browser capture while the context panel is closed', () => {
test('registers the agent browser opener without suppressing panel reveal', () => {
expect(contextPanelSource).toContain(
'registerBrowserOpener((url) => openContextBrowser(effectiveDirectory, url))',
);
expect(contextPanelSource).not.toContain(
'openContextBrowser(effectiveDirectory, url, { reveal: false })',
);
});
test('opening the agent browser gives its webview a visible panel surface', () => {
useUIStore.getState().openContextBrowser(DIRECTORY, 'https://example.com');
const panel = useUIStore.getState().contextPanelByDirectory[DIRECTORY];
expect(panel.isOpen).toBe(true);
expect(panel.tabs).toHaveLength(1);
expect(panel.tabs[0]?.mode).toBe('browser');
expect(panel.tabs[0]?.targetPath).toBe('https://example.com');
});
});