Files
platform/src/apps/officer-web/Screens/Dashboard/Browser/BrowserScreen.tsx
T
pastilhasandClaude Opus 4.6 4d30672adb browser relay: multi-session override, stale session recovery, better error feedback
- relay accepts new extension connections by closing old one (last wins, code 4000)
- extension recognizes code 4000 and stops auto-reconnect (shows "replaced" badge)
- fix ping interval race where old WS close handler killed new connection's pings
- retry CDP commands on "Session with given id not found" by re-attaching debugger
- describeError() maps known errors to user-friendly badge tooltips
- persisted relay tokens restored on server start
- user-scoped token salts, token regeneration/deletion endpoints
- extension download endpoint, integrations UI for browser relay setup
- browser relay env vars passed to pi-bridge sandboxes
- browser screen layout with chat panel and prompt prefix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 15:22:15 +00:00

42 lines
1.6 KiB
TypeScript

import { useMemo, useCallback } from 'react';
import type { LayoutNode, PanelComponents } from 'officerdev';
import { WorkspaceView } from 'officerdev';
import { useWorkspacesState } from 'state/useWorkspacesState';
import { useIsMobile } from 'hooks/useIsMobile';
import { useGlobal } from 'hooks/useGlobal';
import { defaultLayout } from './defaultLayout';
import { TabList } from './TabList';
import { TabPreview } from './TabPreview';
const PROMPT_PREFIX = `You are a browser assistant. The user has connected Chrome tabs via the Officer Browser Relay. You have a 'browser' tool — use it to list tabs, take screenshots, navigate, evaluate JavaScript, and get page info. When asked about a page, take a screenshot first.`;
export const BrowserScreen = () => {
const isMobile = useIsMobile();
const [selectedId, setSelectedId] = useGlobal<string | null>('BROWSER_SELECTED_TAB', null);
const workspace = useWorkspacesState<LayoutNode>('screens/browser', defaultLayout);
const components: PanelComponents = useMemo(
() => ({
'browser-tabs': TabList,
'browser-preview': TabPreview,
}),
[],
);
const mobilePanelId = isMobile && selectedId ? 'browser-preview' : undefined;
const onMobileBack = useCallback(() => setSelectedId(null), [setSelectedId]);
return (
<div className="h-full w-full pt-2">
<WorkspaceView
workspace={workspace}
locked
components={components}
promptPrefix={PROMPT_PREFIX}
mobilePanelId={mobilePanelId}
onMobilePanelChange={mobilePanelId ? () => onMobileBack() : undefined}
/>
</div>
);
};