cmux next chat: site icons for thread details sources (labs sourceIcons)
stacked on #21315 (base next-chat-ui), retarget to feat-cmux-next once that lands. split out of #21315 so that pr stays the render engine and lawrence's #21760 fixes.
thread details' sources show each site's icon instead of the generic row icon. behind agentPane.labs.sourceIcons (debug settings, pages section), on by default. switched off, nothing is fetched.
Summary
- each source row in thread details shows its site's icon; a
site:search shows the searched site's. - the web links in the agent's own reply show their site's icon the same way. only reply prose fetches: github review comments, quotes, bare urls in other text and every other surface never fetch (they still show an icon cmux already holds). at most 32 chat sites, within 64 per pane.
- an icon cmux already holds (an open tab of that site) wins; otherwise the pane asks the app (
link.favicon, passive) once per site. - the app fetches it through the browser's favicon loader: http(s) only, ephemeral, no cookies sent or stored, 1 MiB body cap, decoded to 64 px.
- when the site has no
/favicon.ico(or it does not decode), the app reads up to 256 KiB of the site's home page and tries the two best<link rel="icon">icons, as a browser does (nbc news, leafdraft-style sites). a small scanner reads only<link>and<base>tags; the icons can sit on another host and go through the same guarded fetch. medium still shows the generic icon: its/favicon.icois served corrupt and it blocks non-browser page requests. - a link asks only once it has finished streaming in (no half-typed hostnames). one 12 s limit per site for the whole chain. the app keeps results in memory (icon 6 h, "no icon" 10 min, 256 sites); a timeout, 5xx or full queue is temporary, not cached, and gets one retry. svg icons are refused (raster only).
heads up (trust): this is the one new network request the app makes for the chat: the site learns this mac's ip and that its link was shown, without a click. the agent (or a page that prompt-injects it) picks the links, so a unique subdomain per reader could track; the per-pane cap bounds that. the agent may have read the site from its provider's servers, not this mac, so it can be a new contact. it is in the trust note for #13742 with the off switch.
| Preview (site icons beside links in an agent reply) |
|---|
| Preview (thread details sources) |
|---|
Testing
- swift (local,
swift test --filter AgentPaneSourceIconinPackages/macOS/CmuxNext): 69 tests in 7 suites pass (icon queue, admission, html scanner, fallback chain, recovery/cache/deadline, format/svg refusal, png). the cmux-next workflow does not run on this stacked pr (basenext-chat-ui), so ci has not run them; they run once the pr is retargeted tofeat-cmux-next. - web (bun, one file each):
source-icons34,labs-precedence5,url-chip-hover2,render-stream26,sources-files-once2,reply-image-outside3,link-preview-card-styles1, all pass. lint/types: only the 3 upstreamsrc/motionwarnings. - the full app builds locally and runs (cmux DEV chat): nbc news and leafdraft-style sites now show icons from their home page; medium stays generic.
- reviewed by three read-only codex passes (performance/caching, privacy/security, the leafdraft trace); their pre-merge findings are fixed in this pr. two older gaps in the shared remote fetch (some special-purpose ipv6 ranges pass the public-address check; chunk framing bytes are not counted toward the byte cap) are left for a separate pr.
- ci: the red checks are upstream (markdown page bundle budget 7890 bytes over on the base too, so the web test step does not run; repo workflow guards; full-recipe static checks).
Changelog
Added: thread details sources and links in the agent's replies show each site's icon (labs, on by default).
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Thread details sources, site: searches, and eligible agent-reply links now show site icons instead of generic icons.
agentPane.labs.sourceIconsis on by default; disabling it prevents fetches.- Existing tab icons take precedence; otherwise settled sources and agent reply prose fetch once per site, while quotes and third-party text do not.
- Fetches use a shared bounded queue, check public addresses and redirects, send no cookies, and cache results; sites can see the Mac's IP when an icon is requested.
- If
/favicon.icofails, the app checks the home page's best icon links.