Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions apps/web/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2706,8 +2706,10 @@ export default function ChatView(props: ChatViewProps) {
const splitChatFraction = useBrowserPanelStore((store) => store.splitChatFraction);
const setSplitChatFraction = useBrowserPanelStore((store) => store.setSplitChatFraction);
const browserExpanded = useBrowserPanelStore((store) => store.expanded);
// The preview is a Chromium webview, which only the desktop app can host: a
// web build has no browser to toggle, so it gets no button and no panel.
// General chats have no project and therefore no dev server to look at.
const browserAvailable = !isGeneralChatThread;
const browserAvailable = isElectron && !isGeneralChatThread;
const browserOpen = browserAvailable && browserPanelState.open;

const handleToggleBrowser = useCallback(() => {
Expand Down Expand Up @@ -6982,7 +6984,10 @@ export default function ChatView(props: ChatViewProps) {
{/* The agent's end of the browser is mounted with the thread, not with
the panel: a closed panel is a closed panel, not the absence of a
browser, and a request for the browser opens it. */}
{browserAvailable && routeThreadRef !== null ? (
{!isGeneralChatThread && routeThreadRef !== null ? (
// Mounted on the web build too: the host reads the desktop bridge at
// effect time and refuses to connect without one, so it costs nothing
// there and keeps working if the preload attaches late.
// The project is passed alongside the thread because a local draft
// thread has no shell to look it up from, and browser approvals are
// recorded per project.
Expand Down
15 changes: 12 additions & 3 deletions apps/web/src/components/settings/SettingsPanels.browser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1884,9 +1884,18 @@ describe("GeneralSettingsPanel observability", () => {

await expect.element(page.getByText(/Credential configured · Claude Max/)).toBeInTheDocument();
await page.getByLabelText("Toggle Claude details").click();
await expect.element(page.getByText("Chat configured")).toBeInTheDocument();
await expect.element(page.getByText("Usage verified")).toBeInTheDocument();
await page.getByText("Advanced: headless chat token").click();
await expect.element(page.getByText("Chat configured")).toBeVisible();
await expect.element(page.getByText("Usage verified")).toBeVisible();
const advancedTokenLabel = page.getByText("Advanced: headless chat token");
await expect.element(advancedTokenLabel).toBeVisible();
const advancedTokenToggle = advancedTokenLabel.element().closest("summary");
// The summary can have stable bounds while its parent is still revealing it.
// Wait for that height transition before sending a pointer click.
const detailsPanel = advancedTokenToggle?.closest('[data-slot="collapsible-panel"]');
if (!advancedTokenToggle || !detailsPanel)
throw new Error("Claude details panel did not render");
await Promise.all(detailsPanel.getAnimations().map((animation) => animation.finished));
await page.elementLocator(advancedTokenToggle).click();
await expect.element(page.getByText(/Optional for remote or headless chat/)).toBeVisible();
});

Expand Down
Loading