Skip to content

fix(chat): handle HTML artifacts and browser overlays - #279

Merged
alwaysmavs merged 3 commits into
mainfrom
codex/fix-html-artifacts-browser-modals
Jul 28, 2026
Merged

fix(chat): handle HTML artifacts and browser overlays#279
alwaysmavs merged 3 commits into
mainfrom
codex/fix-html-artifacts-browser-modals

Conversation

@alwaysmavs

Copy link
Copy Markdown
Contributor

Issue

Generated HTML reports were treated as intermediate execution files instead of final artifacts, so users only saw a raw message link. Those local links were also routed through external-link behavior, producing encoded filesystem paths that could neither be opened reliably nor copied through Electron's trusted clipboard path.

The integrated browser introduced two related desktop interaction problems. Empty toolbar space was not draggable, and Electron's native WebContentsView always composited above renderer-owned modal backdrops. Hiding the native view fixed the stacking issue but made the preview appear to disappear while a modal was open.

Root cause

  • .html and .htm were included in the intermediate-code extension classifier.
  • Message links did not distinguish local paths from external URLs.
  • The link modal called the renderer navigator.clipboard API directly and silently swallowed failures.
  • Browser toolbar drag regions were not declared explicitly.
  • A native WebContentsView cannot be covered by renderer DOM, so ordinary z-index changes cannot make modal overlays appear above it.

Fix

  • Classify generated HTML as a final webpage artifact.
  • Parse encoded Unix, Windows, UNC, and file: link targets and open local files through the existing trusted openLocalPath service.
  • Copy decoded local paths through Wanta's native Electron clipboard bridge, retaining browser and DOM fallbacks and reporting copy failures.
  • Make browser toolbar whitespace draggable while keeping navigation controls and the address form interactive.
  • Capture a current browser viewport snapshot below the native view. When a renderer modal opens, hide only the native view so the modal backdrop dims the snapshot; restore the live view and measured bounds after the modal closes.
  • Document the native-view/modal compositing strategy.

Validation

  • pnpm run format
  • pnpm run lint
  • pnpm run ts-check
  • 128 focused tests across artifact classification, local-link handling, clipboard behavior, browser panel behavior, and browser main-process services

@alwaysmavs
alwaysmavs marked this pull request as ready for review July 28, 2026 08:28
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The change adds browser preview capture and modal-aware native view visibility, including preview rendering, ordered show/hide operations, layout observation, and drag-region styling. It adds local filesystem path detection with native clipboard and file-opening actions, localized text, error handling, and tests. HTML files are excluded from intermediate-code processing and standalone HTML reports are verified as web-page artifacts.

Sequence Diagram(s)

sequenceDiagram
  participant RendererModal
  participant BrowserPanel
  participant BrowserService
  participant BrowserManager
  RendererModal->>BrowserPanel: aria-modal changes
  BrowserPanel->>BrowserService: hide or show browser view
  BrowserPanel->>BrowserService: capturePreview(sessionId)
  BrowserService->>BrowserManager: capturePreview(sessionId)
  BrowserManager-->>BrowserPanel: PNG preview data URL or null
  BrowserPanel-->>RendererModal: render preview beneath backdrop
Loading
sequenceDiagram
  participant MessageLinkSafetyModal
  participant NativeClipboard
  participant ChatService
  MessageLinkSafetyModal->>MessageLinkSafetyModal: derive local path
  MessageLinkSafetyModal->>NativeClipboard: writeClipboardText(localPath)
  MessageLinkSafetyModal->>ChatService: invoke openLocalPath
  ChatService-->>MessageLinkSafetyModal: success or error
Loading

Possibly related PRs

  • oomol-lab/wanta#277: Provides the integrated-browser show/hide plumbing used by preview capture and modal overlay handling.
🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description has useful content, but it does not follow the required template and is missing the Summary, Verification checkboxes, and Safety and Compatibility section. Rewrite the description to match the template with Summary, Verification checklist items, and Safety and Compatibility checklist items.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title follows the required format and accurately summarizes the HTML artifact and browser overlay changes.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch codex/fix-html-artifacts-browser-modals

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/ai-elements/message-streamdown.tsx`:
- Around line 235-243: Guard the openLink flow with a pending state so repeated
activations cannot invoke chatService.invoke("openLocalPath", ...) while the
native request is awaiting. Update the related button state at the controls
around the open action to disable it during the request, and reliably clear the
pending state when the operation completes or fails while preserving the
existing onClose behavior.

In `@src/routes/Chat/BrowserPanel.tsx`:
- Around line 39-41: Update the preview capture flow around capturePreview so
every completed request sets preview state to its returned value, including
null, and track request ordering to ignore responses from superseded captures.
Ensure only the latest capture can update setPreviewDataUrl, preventing stale
screenshots from reappearing.
- Around line 68-114: Serialize native-view visibility transitions in the
BrowserPanel effect by tracking the latest desired visibility and invalidating
stale show/hide operations, ensuring a show that resolves after an overlay opens
or unmount begins cannot override the subsequent hide. Update BrowserPanel.tsx
lines 68-114 accordingly. Add a delayed-show regression test in
BrowserPanel.test.ts lines 72-105 that opens the overlay before show resolves
and verifies the final native-view action is hide.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9d4a34b9-0ae0-4e4f-93cd-f0b3253fdfad

📥 Commits

Reviewing files that changed from the base of the PR and between b99f3a3 and 9e4ef8c.

📒 Files selected for processing (13)
  • docs/ai/integrated-browser-implementation.md
  • electron/browser/common.ts
  • electron/browser/node.ts
  • electron/chat/node.test.ts
  • electron/chat/turn-output-files.ts
  • src/components/ai-elements/message-streamdown.test.ts
  • src/components/ai-elements/message-streamdown.tsx
  • src/i18n/app-messages.en.ts
  • src/i18n/app-messages.zh.ts
  • src/lib/message-link-target.test.ts
  • src/lib/message-link-target.ts
  • src/routes/Chat/BrowserPanel.test.ts
  • src/routes/Chat/BrowserPanel.tsx
💤 Files with no reviewable changes (1)
  • electron/chat/turn-output-files.ts

Comment thread src/components/ai-elements/message-streamdown.tsx
Comment thread src/routes/Chat/BrowserPanel.tsx
Comment thread src/routes/Chat/BrowserPanel.tsx Outdated
@alwaysmavs alwaysmavs changed the title Fix HTML artifacts and integrated browser overlays fix(chat): handle HTML artifacts and browser overlays Jul 28, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/routes/Chat/BrowserPanel.test.ts (1)

108-118: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated getBoundingClientRect mock literal.

This exact bounds object is now duplicated three times in the file (pre-existing test at Lines 73-83, here, and again at Lines 159-169). Extracting a shared helper/constant would prevent drift if the mocked bounds ever need to change.

♻️ Suggested refactor
+const MOCK_BOUNDS: DOMRect = {
+  bottom: 500,
+  height: 400,
+  left: 600,
+  right: 1100,
+  top: 100,
+  width: 500,
+  x: 600,
+  y: 100,
+  toJSON: () => undefined,
+}
+
 it("hides after an in-flight show when a modal opens", async () => {
-  vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockReturnValue({
-    bottom: 500,
-    height: 400,
-    left: 600,
-    right: 1100,
-    top: 100,
-    width: 500,
-    x: 600,
-    y: 100,
-    toJSON: () => undefined,
-  })
+  vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockReturnValue(MOCK_BOUNDS)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/routes/Chat/BrowserPanel.test.ts` around lines 108 - 118, Extract the
repeated getBoundingClientRect bounds object into a shared helper or constant in
BrowserPanel.test.ts, then reuse it in all three mockReturnValue calls,
including the test around the current mock. Preserve the existing mocked
dimensions and behavior while eliminating the duplicated literal.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/routes/Chat/BrowserPanel.test.ts`:
- Around line 108-118: Extract the repeated getBoundingClientRect bounds object
into a shared helper or constant in BrowserPanel.test.ts, then reuse it in all
three mockReturnValue calls, including the test around the current mock.
Preserve the existing mocked dimensions and behavior while eliminating the
duplicated literal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 72ac05a8-2356-472d-8eed-644826a7ac4f

📥 Commits

Reviewing files that changed from the base of the PR and between 9e4ef8c and c19fdb3.

📒 Files selected for processing (4)
  • src/components/ai-elements/message-streamdown.test.ts
  • src/components/ai-elements/message-streamdown.tsx
  • src/routes/Chat/BrowserPanel.test.ts
  • src/routes/Chat/BrowserPanel.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/ai-elements/message-streamdown.tsx
  • src/routes/Chat/BrowserPanel.tsx
  • src/components/ai-elements/message-streamdown.test.ts

@alwaysmavs
alwaysmavs merged commit b54f916 into main Jul 28, 2026
2 checks passed
@alwaysmavs
alwaysmavs deleted the codex/fix-html-artifacts-browser-modals branch July 28, 2026 09:01
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