Skip to content

feat(webview): open localhost links through a proxied web tab from another device - #401

Open
shenlvkang-collab wants to merge 1 commit into
Ark0N:masterfrom
shenlvkang-collab:pr/loopback-links-webtab
Open

feat(webview): open localhost links through a proxied web tab from another device#401
shenlvkang-collab wants to merge 1 commit into
Ark0N:masterfrom
shenlvkang-collab:pr/loopback-links-webtab

Conversation

@shenlvkang-collab

Copy link
Copy Markdown
Contributor

Summary

An agent prints http://localhost:5173/ (a dev server, a preview it just served) and the user taps it on a phone. That address only exists on the Codeman box, so the link was a guaranteed connection error from any other device — while the web-tab proxy (docs/web-tabs.md) fetches from the server, where it works.

  • A loopback link (localhost, *.localhost, 127/8, 0.0.0.0, ::1) activated in the terminal, or clicked in the Response Viewer, now opens as a proxied web tab whenever the Codeman page itself is not on that box.
  • A saved proxied dashboard on the same origin is reused, with the link's own path, query and fragment opened inside it (openWebview(id, { path }) appends it to the minted /webview/<cap>/ prefix; a mounted frame is navigated, not torn down, so its state survives). Otherwise one is saved under its host:port, sandboxed like any other web tab, so it is in the Run dropdown next time.
  • Only loopback is routed this way. A LAN or tailnet address may well be reachable from the device (a VPN, the same Wi-Fi), and a direct open is the cheaper, richer path, so those keep opening in a new browser tab. On the box itself (a browser on localhost) every link opens directly.
  • One hook, openLinkThroughWebTabIfLoopback(url), returns false when it declines, and both callers fall through to their existing behaviour (window.open in the link provider, the anchor's _blank default in the viewer).

No server change: the proxy, the egress policy (loopback is explicitly allowed) and the capability model are as shipped.

Docs: docs/web-tabs.md (new section). Changeset: minor.

Test plan

  • test/webview-loopback-links.test.ts (new, jsdom): loopback spellings vs LAN/tailnet/invalid; page-on-box exemption; reuse of a saved proxied dashboard with a deep path; navigating a mounted frame in place; saving an unknown origin as host:port; direct-mode dashboards not reused; reachable links left to the caller; both callers consult the hook before their own path.
  • test/webview-menu-rows.test.ts, test/response-viewer-file-links.test.ts, test/response-viewer-external-links.test.ts, test/link-provider-regex.test.ts, test/frontend-public-tooling.test.ts unchanged and green.
  • prettier on all touched files.

🤖 Generated with Claude Code

https://claude.ai/code/session_01McLWqCWBuQYGuPMScb4Aou

…other device

An agent prints `http://localhost:5173/` (a dev server, a preview it just
served) and the user taps it on a phone. That address only exists on the
Codeman box, so the link was a guaranteed connection error from any other
device — while the web-tab proxy fetches from the server, where it works.

A loopback link (`localhost`, `*.localhost`, 127/8, 0.0.0.0, ::1) activated
in the terminal or clicked in the Response Viewer now opens as a proxied
web tab whenever the Codeman page itself is not on that box. A saved
proxied dashboard on the same origin is reused, with the link's own path,
query and fragment opened inside it (a mounted frame is navigated, not torn
down, so its state survives); otherwise one is saved under its host:port,
sandboxed like any other web tab, so it is in the Run dropdown next time.

Only loopback is routed this way. A LAN or tailnet address may well be
reachable from the device (a VPN, the same Wi-Fi) and a direct open is the
cheaper, richer path, so those keep opening in a new browser tab; on the
box itself every link opens directly. The terminal link provider and the
viewer's click handler consult one hook and fall through to their existing
behaviour when it declines.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01McLWqCWBuQYGuPMScb4Aou
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