fix(mobile): links tapped in the conversation leave the app instead of opening in-app
Problem
A web link tapped in the conversation leaves the app. packages/mobile/lib/chat/ChatMarkdown.tsx:126 hands every link to Linking.openURL, so the user lands in Safari or Chrome and has to come back to AO by hand. Reported by @illegalcall in Discord #dev-chat ("On mobile: links don't open in AO browser").
On desktop the same tap opens the page inside the session's AO Browser inspector (frontend/src/renderer/hooks/useSessionBrowserLink.ts, components/AppLink.tsx); only a modifier-click or the context menu goes to the system browser.
Two consequences beyond the context switch:
- A github.com link in the conversation skips the app's own rule for github.com.
lib/openGitHub.tsopens a repo or PR in the GitHub app when it has a screen for it (that is where the user's session lives; a private PR in a browser is a login wall or a 404) and falls back to the browser otherwise. PR cards and worker rows use it;ChatMarkdowndoes not, so the same URL is routed by two different rules depending on where it sits. - A
localhostlink the agent prints is opened as the phone's own localhost. The preview screen already maps the agent machine's loopback onto the AO host (lib/api.ts,mobileReachablePreviewURL); chat links do not go through it.
What this is not
- Not a job for
app/preview/[id].tsx. That WebView shows the workspace's detectedindex.htmlor the session's advertisedpreviewUrl, with AO's auth header. A tapped link is a third-party page that may need a login, cookies, a share sheet or an address bar — a rawWKWebViewhas none of that, and ATS refuses plainhttpto anything but local hosts inside it. - Not the elicitation "Open link" button (
ChatTimeline.tsx): the desktop sends that to the system browser too, and the flow behind it belongs to the desktop machine. - Not the "Review is not available" half of the same report. That is a missing feature (no caller of
/sessions/{id}/reviews*exists inpackages/mobile), not a bug, and needs a product decision first.
Proposed direction
Open links in the platform's in-app browser — SFSafariViewController on iOS, a Chrome Custom Tab on Android — through expo-web-browser, which is what chat apps do with a tapped link: the user stays in the app and gets a real browser with a Done button.
ChatMarkdownreports the tap; the conversation screen decides how it opens (it knows the AO host).- Map the loopback with
mobileReachablePreviewURLfirst, then go throughopenGitHub, so github.com keeps its app handoff and a tapped link and a PR card follow one rule.openGitHub's browser fallback becomes the in-app browser; non-web schemes (the iOS bug report'sx-safari-https://) still go to the system. - New native module, so the runtime version changes: ships in a store build, not over the air.
Alternatives considered
- Route into
preview/[id]with the tapped URL. Works, but is a hand-rolled browser — see above. NSAllowsArbitraryLoadsInWebContentto make the WebView route viable for plain-http links. Widens ATS for the whole app to solve the wrong problem.- Leave it. Safari is not broken; it is the wrong place, and it drops the github.com rule and the loopback mapping the app already has.
Before submitting
- I searched existing issues / discussions for something similar
- I am willing to help implement this if maintainers agree on scope
Source: Untrivial-ai/agent-orchestrator