Skip to content

feat(preview): report failed navigations to the MCP tools - #350

Merged
Tryanks merged 1 commit into
mainfrom
preview-load-error
Sep 7, 2026
Merged

feat(preview): report failed navigations to the MCP tools#350
Tryanks merged 1 commit into
mainfrom
preview-load-error

Conversation

@Tryanks

@Tryanks Tryanks commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Why

When the preview browser cannot load a page (typically a dev server with a self-signed certificate), WebKit and WebView2 keep the previous document on screen. preview_status is computed by JavaScript inside that page, so it keeps reporting the old URL and the agent cannot distinguish "untrusted certificate" from "slow server". preview_wait_for just burns its timeout.

What

  • New crates/ui/src/preview_panel/load_error.rs: keeps the last failed navigation per native webview as { url, code, message }, cleared when a navigation starts.
    • macOS: lb-wry's WryNavigationDelegate implements neither didStartProvisionalNavigation nor didFail(Provisional)Navigation. After the webview is built we add those three methods to its class once via class_addMethod (skipping any selector a future wry defines itself), then re-assign the delegate because WKWebView caches the delegate's method set at assignment time. code is "<NSError.domain> <code>", message is localizedDescription, url comes from NSURLErrorFailingURLErrorKey.
    • Windows: add_NavigationStarting / add_NavigationCompleted on the ICoreWebView2; code is the WebErrorStatus SDK name such as CertificateIsInvalid. Adds webview2-com (pinned to the version lb-wry resolves) and windows-core as optional Windows-target deps.
  • preview_status merges load_error into its JSON when present. preview_wait_for fails immediately with navigation to <url> failed: <message> (<code>) when a failure is recorded. tcode-initiated navigations clear the record synchronously so a wait issued right after a navigate cannot trip on the old one.
  • Records are dropped when the webview is dropped or pruned so a later allocation at the same address cannot inherit one.
  • One clause added to the preview_status tool description; open/navigate reply notes mention load_error.

No TLS bypass and no settings. This is reporting only; trusting a dev certificate is still done at the OS level (mkcert or the keychain).

Verification

  • macOS, end to end: openssl s_server -www -accept 8443 with a fresh self-signed cert, navigated a real webview through the --preview-smoke harness. Recorded:
    LoadError { url: "https://localhost:8443/", code: "NSURLErrorDomain -1202",
      message: "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “localhost” …" }
    
    and None after the next successful navigation. The temporary probe was removed; the full pre-existing smoke suite passes with the change.
  • cargo clippy --workspace --all-targets clean, cargo test -p tcode-ui preview (7, incl. 2 new), cargo test -p preview-mcp (4).
  • Windows path is untested. It cannot be compiled on this host; signatures were checked against webview2-com 0.38.2 in the registry and modelled on lb-wry's own usage. Needs a cargo check on Windows before trusting it. One known soft spot: the record is keyed by the ICoreWebView2 raw pointer from WebViewExtWindows::webview() and from the event sender; these should be the same interface pointer for the same object but that is not a COM guarantee.

Touches the same preview_status description line as #348; expect a one-hunk trivial conflict whichever merges second.

A navigation that fails (untrusted certificate, dead port) leaves the
previous document on screen, so the JavaScript status probe cannot see
it and the agent is left guessing. Observe the platform's own navigation
callbacks instead: on macOS add didStart/didFail methods to wry's
navigation delegate class at runtime, on Windows hook WebView2's
NavigationStarting/NavigationCompleted. Keep the last failure per native
webview; preview_status reports it as load_error {url, code, message}
and preview_wait_for fails with it instead of waiting out its timeout.

Reporting only. No TLS bypass, no settings.
@Tryanks
Tryanks merged commit 44e2321 into main Sep 7, 2026
5 checks passed
@Tryanks
Tryanks deleted the preview-load-error branch September 7, 2026 03:25
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