Skip to content

Latest commit

 

History

History
1677 lines (1587 loc) · 162 KB

features.md

File metadata and controls

1677 lines (1587 loc) · 162 KB

Dao Browser Feature Inventory

This document catalogs the features Dao Browser adds on top of the Chromium baseline configured in dao.json. Dao-owned code lives in src/dao/; Chromium integration patches live in src/patches/.

Migration basis: Chromium 155.0.8059.86 (804d6b05f089b27af8342622a36558c49401a1d4). The integration notes below describe that target; they are not a record of completed build or runtime checks.

Android GeckoView features, including the native Compose browser shell, are documented separately in features-android.md. The Android shell now uses Android Components BrowserStore tabs with regular-session restore and real tab thumbnails, plus persistent history and bookmarks, Android system downloads, persistent engine preferences, installed-extension state, and QR scanning.

Desktop platform scope

Human-readable release notes are maintained in English and Simplified Chinese, with other languages generated by i18n.sh --only changelog. Desktop version bumps archive only desktop Unreleased entries before packaging; release failures restore them along with version metadata. Windows attachments and --skip-bump preserve pending notes. See the changelog guide. The website's /changelog page reads the English document at build time, with platform switching, permanent version links, and a responsive release timeline. There is no language switcher; /changelog/zh-CN redirects to /changelog. The navigation places Changelog before the GitHub icon. Only archived versions are public; /history remains the download archive. Website deployment also runs when changelog documents change.

npm run release:rollback uses an interactive arrow-key menu to select a historical website download snapshot, checks its installers and original signed Windows manifest, and commits website/public/info.json plus windows-update.json locally from a clean main. No Git remote access or synchronization is required; push manually to trigger website deployment. It preserves application versions and Mac appcast; installed browsers are not downgraded. See the development guide.

The development CLI supports native macOS arm64 and an experimental Windows x64 target. Windows uses the existing setup/import/rebuild commands, a local dao.exe, and separate Dao debug/release profiles. Windows browser and child processes use dao.exe; installers, web-app launchers, and automatic updates use the same name. Upgrades from chrome.exe keep the installation and profile locations and retarget existing shortcuts in standard Windows locations. Normal Windows browser windows combine their address row and native Chromium minimize/maximize/close controls, removing the separate title-bar row. Caption buttons stay at the window's top right while either sidebar toggles or split panes resize. Address bars reserve the actual caption bounds, shrink the URL, and hide actions that cannot fit in narrow panes; the Agent uses Chromium's Window Controls Overlay geometry to fit its compact header beside them, with a distinct collapse button and an overflow menu for new chat, history, and settings. Fullscreen hides the caption buttons and restores the regular Agent header. Native caption hit testing preserves Snap Layouts, window close handling, and dragging from sidebar-header and address-row empty space. Popup and app window frames retain their existing layout. Native caption buttons use a transparent layer over the address row or Agent, with glyph contrast following the underlying surface as page colors, tabs, split panes, and Agent visibility change. Caption hover and pressed backgrounds are clipped to the underlying surface's bounds and rounded corners. Caption glyphs are centered within that visible hover area, excluding the frame gutters and inter-button spacing. Caption hit testing uses Chromium's overlay routing so the Agent's native WebView does not interrupt minimize/close hover; Windows 11 maximize keeps Snap Layouts. Sidebar windows also clip the parked native toolbar's composited children to the top container so duplicate navigation controls cannot cover the frame. Windows event interception uses Aura with restoration on overlay close and drag cancellation. Closing site controls or the command bar after switching tabs restores the originally blocked page. Download cards use Windows file type icons when an image thumbnail is unavailable. Windows file icons retain separate 1x/2x images from the highest-resolution Shell icon available, with smaller-icon fallback for file types without a large asset. Recent-file scans run on a COM-initialized background sequence. Agent workspace paths accept UTF-8 input. On Windows, existing path components are resolved through directory junctions before checking workspace containment, including ancestors of files that do not yet exist. Dao Home project scans use portable forward-slash file names and reject Windows directory junctions as well as file symlinks. Chromium tab search uses dao://tab-search.top-chrome/ to match its registered WebUI configuration, including when opened with Ctrl+Shift+A on Windows.

Windows supports the local MCP server, existing-tab grants, Dao Lite background tasks, and manual installation of local-agent skills and the CLI. The Windows port excludes native share pickers, AppKit drag-to-new-window completion detection, ImageIO thumbnails, the external-URL Little Dao launcher, and Sparkle updates. Windows reuses Chromium's mini_installer for unsigned x64 installation, shortcuts, browser registration, upgrades, and uninstall. The distributed NSIS EXE opens a Win32/WebView2 installer with bundled HTML/CSS in a fixed, DPI-scaled 560 x 420 window. Its custom title bar supports dragging, minimizing and closing; the centered Dao mark, halo and ring follow the supplied compact installer design. English and Simplified Chinese, system light/dark themes, keyboard navigation, high contrast and reduced motion are supported; logos retain square proportions. The installation path expands inline for editing: Enter confirms, Escape cancels the edit, and Browse starts from the current path's nearest existing parent. The picker appends a Dao product folder unless that folder is already selected. Progress remains indeterminate while the native backend runs, with rotating product tips. Completion offers an explicit launch button; closing never launches Dao. Installation failures retain retry and a dialog with the error code and log location. The bridge accepts only fixed installer actions, and external navigation is blocked. WebView2 is never downloaded on the user's machine: a missing runtime or startup failure opens the native NSIS wizard instead. /NATIVE selects that wizard explicitly; /S bypasses both interfaces. Once installation starts, closing is blocked until the backend exits, and a WebView failure cannot start another installation. Fresh per-user installations can choose a writable directory on a local fixed drive; binaries go into its Application child while profiles stay under %LOCALAPPDATA%\Dao\User Data. Repair and upgrades retain the registered location. When a per-user installation is detected, both installer interfaces offer Uninstall Dao and hand off to the registered Chromium uninstaller, which owns confirmation and the browsing-data removal choice. Uninstall is unavailable during installation and after completion; launch failures show localized guidance. Moving requires uninstalling while preserving browsing data, then installing again. System folders, profile folders, and existing unowned Application/Temp contents are rejected. Native install and profile paths use Dao, with Dao AppUserModelID/ProgID prefixes and separate COM server identities. Chrome and Chromium installations remain independent. release --platform windows reuses dao.json's desktop version and v<version> tag and attaches only the EXE to the shared GitHub Release after checking its local SHA-256 checksum. GitHub archival also verifies signed Windows metadata, but does not upload .sha256 or .update.json attachments. The default npm run release bumps the desktop version once, builds macOS and Windows sequentially on a Mac, and uploads both installers to R2 before staging the signed Windows feed for website deployment. Artifact uploads rely on Wrangler success; the release command does not download them for verification. Existing objects are checked with HEAD for uncompressed size when provided and skipped on retry; local Windows signatures and checksums remain verified. Website deployment verifies the signed feed against its immutable R2 manifest and available installer before publishing. Deployment does not write to R2 or require Cloudflare Actions secrets. release:mac retains the Mac-only workflow; release:windows retains the existing tag attachment workflow without advancing the Windows feed. Windows does not use Apple signing, notarization, or Sparkle at runtime. macOS hosts can select --platform windows to cross-compile the browser and WebView2 installer host from source and package the NSIS EXE locally. The pipeline reuses Chromium's hermetic Windows SDK and bundled host tools, keeps the cross build in out/dao-win-x64[-debug], and preserves native Mac caches. windows-toolchain setup --accept-license can download Microsoft's public VS 2026/Windows SDK packages and create the required archive entirely on Mac, including ATL, DIA, debugging tools, runtime DLLs, and Chromium environment files. The pinned downloader and package hashes are verified; downloads are cached and incomplete inputs fail before an archive is configured. Existing private SDK archives remain supported through configure/setup/export; native Mac remains the default target. Both hosts publish Windows assets under the same existing desktop version/tag. Windows build/release cancellation stops the owned process tree and waits for cleanup; unrelated build jobs remain independent. Failed tree termination is reported explicitly instead of claiming successful cancellation. rebuild -- -- --release reuses the release cache for installer verification; plain rebuild continues to use the debug cache. See development.md for setup and verification requirements.

Windows updates

browser/updater/dao_windows_updater.* uses Chromium networking to check https://dao.msgbyte.com/windows-update.json after a 30-second startup delay when due, then daily. It runs only for registered per-user x64 installations using the default user-data directory, excluding component builds and Guest/Incognito-only starts. The separate installer origin remains R2. The legacy R2 feed is no longer synchronized; clients using it need a manual upgrade. Website feed responses explicitly disable browser/CDN caching. macOS continues using Sparkle.

The updater verifies an Ed25519 signature over the exact metadata payload, requires a newer Dao version and no Chromium downgrade, and accepts only the fixed R2 installer URL. Metadata is limited to 64 KiB and installers to 1 GiB; redirects and credentials are disabled. Size and SHA-256 are checked before caching in the user-restricted Dao/Updates directory and again before launch. A signed ready update survives browser restarts. Settings About exposes localized checking, downloading, current, ready, unsupported-installation, and error states; the sidebar only shows its existing update control for ready/applying states. The Windows sidebar menu's Check for Updates command starts a manual check and opens Settings About to display progress and results. It remains available during an update and on unsupported installations so users can see the current status.

Applying an update starts an authenticated, current-user-only named-pipe handoff to the existing NSIS installer host without WebView2. The helper waits for an explicit graceful-exit commit and the original browser process to exit. Cancelling an unload/download prompt cancels the handoff, including a later unrelated quit. The helper rechecks registration and other processes, silently installs into the existing directory, and relaunches with session restoration. It never force-kills browsers. Installer errors show localized retry guidance and log locations. The browser launches the update wrapper from its cache directory, and the NSIS wrapper switches to its temporary directory before starting helpers, including when launched by an older Dao version. Waiting updater processes therefore do not lock the installed version directory during same-Chromium-version upgrades. The silent backend writes to the displayed %TEMP%\dao_installer.log path; the handoff log preserves its installation exit code. Existing Windows versions without this updater need one manual upgrade first.

1. Vertical Sidebar

An Arc-inspired vertical sidebar replaces Chromium's top tab strip — the single biggest UI change in Dao Browser. The sidebar is a hybrid: a C++ Views container hosts a Lit/TypeScript WebUI that renders the actual tab list, favorites, and controls.

1.1 Sidebar Core (C++ Views)

  • DaoSidebarView (sidebar/dao_sidebar_view.{h,cc}) — Main container, 240px default, collapsible to 4px with animation
  • Drag-to-resize — Mouse drag, 150–400px range, ignored while collapsed; width preserved across collapse/expand cycles
  • Edge hover auto-expand — Hovering the collapsed sidebar's left-edge strip temporarily expands it; leaving collapses it again. A window-wide mouse monitor keeps the edge active in fullscreen (where the collapsed sidebar has zero width) and collapses even when the cursor leaves before entering the expanded sidebar. Webpage fullscreen never reveals it. Manual collapse state is unchanged
  • DaoSidebarUIHandler — Mojo bridge between sidebar C++ and the WebUI (media state, folder persistence, tab commands)
  • Windows browser menu — A Lucide menu button occupies the top-left of the native sidebar header, opposite the collapse button. It opens a left-aligned native browser menu with Settings first and Check for Updates second, followed by Chromium's existing window, history, downloads, bookmarks, extensions, editing, zoom, print, and developer-tool actions. The button uses the sidebar's theme and hover colors; its bounds remain clickable while empty header space still drags the window. sidebar/dao_app_menu_button.{h,cc} reuses AppMenuModel and AppMenu for localization, policy checks, dynamic submenus, and keyboard navigation. The profile submenu and its extra spacing are omitted. Alt+F uses the same entry point and temporarily reveals a collapsed sidebar, waiting for its animation before opening the menu. Hover-expanded sidebars stay open while the menu is active. Shortcut labels omit Chromium defaults that Dao reserves for sidebar, duplicate-tab, Agent, and copy-URL actions. macOS retains its system menu bar.
  • Incognito indicator — Native shield-check status icon beside the sidebar collapse button in Incognito windows, with a localized privacy tooltip
  • Sidebar context menu — Native right-click menu support with registered shortcut labels for Duplicate Tab, Copy Link, and Close Tab. When the local MCP server is enabled, regular-profile tabs also expose Copy Tab ID for stable MCP targeting. Incognito and Guest windows keep the action hidden. Regular tab menus keep copy, pin, mute, move-to-new-window, and close-tab actions at the top level. Organize Tabs groups move-to-top, stale-tab archiving, and configured AI classification actions; Close Multiple Tabs groups duplicate, other, above, and below closures. Close Tab is the last menu item, below Close Multiple Tabs. Each submenu has only one level, and closing it preserves the target tab until the whole menu closes.
  • Move tab to top — The regular tab context menu moves a tab to the top of the sidebar list, or to the top of its current folder without changing membership. Loose split tabs move together in their existing order. The saved sidebar order survives reloads and session restore.
  • Close duplicate tabs — The sidebar context menu keeps the most recently active tab for each URL. After all close attempts finish, a localized native toast reports how many duplicate tabs actually closed. Pages retain their normal leave-confirmation flow; cancelled closures are excluded from the count.
  • Undo batch tab closing — Close Other Tabs, Close Tabs Above, Close Tabs Below, and Close Duplicate Tabs show a shared Dao toast with an Undo button for 10 seconds, extended while hovered or keyboard-focused. Undo restores only the tabs actually closed by that operation, with their history, session storage, pinned state, and tab-strip positions. Cancelled leave prompts are excluded. Snapshots stay in memory, support private windows and batches larger than recently-closed history, and are released when the toast expires or is replaced. Single-tab closing and Delete Folder retain their existing flows.
  • DaoTabTooltipView (sidebar/dao_tab_tooltip_view.{h,cc}) — Hover contextual info next to the sidebar
  • Tab hover previews — Settings > You and Dao exposes the profile-scoped dao.tab_hover_preview_enabled preference, off by default, with a text-free, theme-aware illustration of the feature. Chromium's ThumbnailTabHelper is owned by TabFeatures (ui/tabs/tab_features.cc.patch) and created even when upstream hover-card images are disabled. Dao looks it up through ThumbnailTabHelper::From(tab) so readiness is tracked from the first navigation, but its switch-away capture in tab_strip_model.cc.patch only runs while the preference is on. Only the tab the user is leaving is snapshotted, as a downscaled in-memory JPEG; background tabs are never force-rendered because Dao reads the stored data instead of subscribing to the thumbnail. Entering a sidebar tab row immediately sends showTabPreview; for tabs that are not on screen, HandleShowTabPreview draws that snapshot above the title in a card pinned just right of the sidebar and level with the row, sliding up to stay inside the window. The card is as wide as the 240 DIP snapshot and wraps the title to two lines before eliding. The card takes no sidebar space, hides on leave, click, or drag, and suppresses the delayed title tooltip; tabs without a snapshot keep the settled title tooltip. Discard recreates the helper for the replacement WebContents while preserving its stored thumbnail; reading a preview does not reload the discarded tab. Navigations clear stale snapshots, and tall cursor-anchored tooltips flip to stay inside the window. Toggling applies without restart; turning it off stops captures and hides previews, while snapshots already in memory are released as their tabs navigate or close.

1.2 Sidebar WebUI (dao://sidebar)

  • dao_sidebar_app.ts + sidebar.{html,css,ts} — Lit application root
  • sidebar_bridge.ts — Mojo client wrapper
  • dao_sidebar_section.ts — Reusable collapsible section container
  • dao_tab_list.ts / dao_tab_item.ts — Vertical tab list, dual-line layout for the active tab (title + URL)
  • Tab close-button focus — Close buttons stay out of sequential Tab navigation, and mouse clicks do not leave them focused for accidental Space/Enter activation. Close-tab shortcuts and context-menu actions remain available.
  • Active-tab auto-scroll — Expands a collapsed folder when one of its tabs becomes active, then smoothly keeps the active tab inside the tab-list viewport. Switching to a pinned tab, including after closing the active tab, scrolls the ordinary tab list back to the top and replaces any pending scroll.
  • dao_favorites_view.ts — Pinned site icon row
  • dao_pinned_tabs_grid.ts + DaoPinnedTabModel — Persistent Pin grid with stable logical backing identities across navigation, discard/WebContents replacement, session restore, and Chromium session-command compaction. Open backing tabs are resolved across every browser window in the same profile, so activating a Pin focuses the existing tab instead of opening a second copy. Pin mutations are propagated to every same-profile sidebar handler before persistence, preventing a stale window from rewriting newer state. Live synchronization preserves open and dormant states without repeating session reconciliation, avoiding refresh loops across ordinary windows and Dao Lite tasks. Dragging a Pin into another window's ordinary tab list moves its backing tab into that window. URL remains display/reopen metadata and is used for legacy migration only when exactly one candidate exists. Confirmed dormant items reopen once; identity conflicts fail closed without increasing the tab count. Pin state is serialized through a shared sequenced writer and atomically replaces the previous profile file.
  • dao_folder_item.ts / dao_folder_model.ts — Folder grouping with profile-wide persistence and per-window rendering. Ordinary tab identities are recorded in the session log as soon as the sidebar exposes them. Stable session tab IDs preserve membership across window transfers and restart; partial restore and other windows never prune unmatched references. Explicit edits are merged against the latest profile snapshot, written in sequence with atomic file replacement, and propagated to all same-profile windows. Initial loads and refreshes do not rewrite the file. Drag ordering maps visible rows back to stored positions, including when other windows have hidden tabs or folders. Concurrent moves and unfoldering preserve one global membership per tab; stale edits cannot resurrect closed tabs. Legacy window snapshots are merged on read without losing their folders. URL matching for legacy references without a stable ID is restricted to session-restored tabs, so newly opened tabs never inherit an old folder or position merely by visiting the same URL. Off-the-record windows keep folders in profile-owned memory and never access the regular profile's folder file. Every folder context menu exposes Unfolder, which removes the folder and releases its child tabs in place, and Delete Folder, which uses a Dao native system confirmation dialog before closing the folder's currently matched child tabs. The folder is deleted only after those tabs actually close; cancelling either confirmation or a page's beforeunload prompt preserves the folder and remaining tabs.
  • AI tab classification — Once an Agent model is configured, the sidebar background and ordinary-tab context menus expose Classify Tabs with AI. The tab menu also offers Classify Tabs Below with AI, using sidebar visual order captured when the menu opens and excluding the clicked tab. An empty or closed selection never falls back to classifying all tabs. Both actions group only loose HTTP(S) tabs in the current window; pinned tabs, split panes, existing folder members, and Agent/MCP-controlled tabs are preserved. Off-the-record and Guest windows do not expose classification. Each request sends the chosen tabs' titles and URLs plus the profile's existing folder names and IDs to the configured model, without page content, chat history, or browser tools. Existing categories are preferred; new folders are created only when needed, in the interface language. Categories are the existing folders, with no separate category database or pre-created empty folders. You and Dao > Tab categories lists all of them as chips: clicking a name renames it in place, the chip's × deletes it, and a trailing Add category chip opens an in-place editor. Enter saves and Escape cancels (Enter during IME composition is ignored). Deleting a category there releases its tabs in place across windows without closing pages; the sidebar's separate Delete Folder action retains its close-confirmation flow. Names must be nonblank, unique without regard to case, and at most 100 Unicode codepoints. Changes persist through the existing profile folder file and notify both Settings and all same-profile sidebars. Classification uses the resident Agent's model adapter without opening a chat, permits one request per profile, and aborts after 60 seconds. Invalid, incomplete, or duplicate assignments fail without changing folders. Closed, transferred, navigated, pinned, or newly grouped tabs are excluded when results are applied; manual edits or reordered snapshots can discard the result with retry feedback. Closing a tab, including one outside the chosen range, does not discard the classification of surviving tabs, even when the newly active tab automatically expands its folder. The final atomic write compares normalized snapshots so unchanged legacy data remains writable, and rejects newer folder data rather than overwriting it. Classification does not activate or navigate tabs. A persistent loading indicator at the bottom of the sidebar stays visible until classification and saving finish; completion, empty scope, and failure use Dao native toasts. Requests exceeding 1,000 tabs, 500 existing folders, or 512 KiB fail without partial classification.
  • Configurable stale-tab expiration — The "You and Dao" Settings page stores a profile-scoped integer from 1–720 hours (24 hours by default), chosen from 1 day / 3 days / 5 days / 1 week / 2 weeks presets or a Custom hours field that also shows any saved non-preset value; the sidebar's "Move Stale Tabs to stale" action reads that value when run, validates it defensively, and archives only qualifying ordinary tabs. Closing an ordinary active tab skips archived tabs when another ordinary tab remains. If only stale tabs remain, or the closed tab was already in stale, Chromium's normal choice is kept and the folder expands to it.
  • dao_new_tab_button.ts — New-tab button
  • dao_download_button.ts — Download flyout trigger
  • dao_media_control.ts — Background-tab media playback controls driven by controllable MediaSessions. Playback must continue for one second before the card appears; brief notification sounds do not qualify. The current source stays selected through pause, mute, silence, and other tabs playing. Ended or inactive sessions hide after 500ms, while closed or foreground tabs disappear immediately. Media controls follow tab identity across reordering. When tab muting removes the controllable session, the card retains playback state while play/pause is disabled until control becomes available again; ending or destroying the player and navigating to a new page clear the card.

1.3 Tab System Foundations

  • New-tab placement — Ordinary new tabs default to the top of the unpinned list. Webpage links opened in a new foreground or background tab are the exception: each opens immediately below the current source tab. Links from a sidebar folder appear below that folder without changing membership. Navigation into another window, extension-created tabs, and bookmark-manager tabs also default to the top, below pinned tabs, when no position is specified. Explicit extension positions and opener relationships remain intact. Browser UI actions still default to the top even when scored as link navigations. Link tabs retain their opener; native group membership follows explicit group requests or Chromium's group contiguity constraints. Explicit insertion positions and groups, session restoration, duplication, drag placement, and Split View retain their intended positions.
  • DaoTabIdentity (dao_tab_identity.h) — Stable cross-window tab IDs decoupled from TabStripModel indices, migrated across WebContents replacement and persisted in session extra data
  • DaoTabCommands (dao_tab_commands.h) — Tab action vocabulary (duplicate, pin, copy URL, close, etc.)
  • DaoCrossWindowDrag (dao_cross_window_drag.{h,cc}) — Shared parsing and tab resolution for dao-tab-drag:<session_id>:<tab_index>:<tab_id> payloads; legacy index-only identities remain readable. Stable IDs prevent moving a different tab when the source window reorders during a drag. Existing-window and Split View drops use the same transfer helper.
  • Move tab to a new window — The ordinary tab context menu uses Chromium's native move command and localized label. Dragging a tab onto the desktop creates a window before transferring its contents; dragging the only tab moves the existing window. Desktop drop detection and window placement use primary-display global coordinates, including on displays of different sizes. Native drag completion controls tear-off, while successful drops and Escape cancellation only clean up drag state. Cross-window folder drops are rejected; ordinary tab-list drops never remove a destination window's folder membership by interpreting a foreign tab index.
  • Detach guards — Prevents accidental reordering while dragging
  • Patches: tab_strip_model.cc.patch, tab_helpers.cc.patch

1.4 Address Bar and Active-Tab URL

  • DaoAddressBarView (dao_address_bar_view.{h,cc}) — Embedded URL pill (14px radius), referenced by sidebar / command bar / control center; adapts text color to background luminance
    • Long URLs shrink to leave room for status icons and action buttons, including when high-performance mode is enabled after navigation
    • Shows a separately clickable red Lucide ShieldOff before the URL pill when Chromium reports a warning or dangerous connection state; clicking it opens native Page Info
    • The stop/reload button and page-load glow follow Chromium's loading UI state. Late iframe loads and same-document navigation stay quiet, including when switching tabs; normal page navigation still shows loading feedback.
  • Active-tab URL display is rendered inline in the dual-line tab item
  • Native Side Panel compatibility — Chromium Side Panel content and its 40px header remain client-hit-testable where they overlap Dao's macOS titlebar, so header controls such as Pin and Close continue to receive clicks

1.5 Command Bar (Spotlight-style)

  • DaoCommandBarView (dao_command_bar_view.{h,cc}) — Translucent scrim + frosted floating panel + layered shadows
    • Cmd+L → Show() pre-fills current URL (SetFocusToLocationBar(is_user_initiated=true))
    • Cmd+T → ShowForNewTab() opens the Command Bar without creating a tab; navigation creates the destination tab only after submission
    • Escape in macOS fullscreen — A short press dismisses the command bar and restores page focus without a delayed fullscreen exit. Window-scoped native release observation cancels both held-Escape timers even when focus moves between native UI and a webpage; deactivation clears the old window's pending hold. Genuine long presses and page/keyboard/pointer-lock escape behavior retain Chromium's existing handling.
    • Remove recommendations — Hover a deletable recommendation and click its X, or press Shift+Delete on the selected row. Chromium's SupportsDeletion() controls availability and AutocompleteController::DeleteMatch() delegates deletion, including duplicate matches, to the original providers. History-backed suggestions may delete their history entries; bookmarks stay intact. Non-deletable rows leave Shift+Delete to normal text editing.
    • Ask AI — Submits prompt directly to the Agent
    • Experimental suggestion ordering — An independent, default-off toggle in You and Dao keeps the typed Search/Open action first, followed by matching open tabs, commands, Ask AI, and the remaining Chromium results. Enabling it preserves typed text during automatic updates and arrow-key browsing; Right Arrow moves the caret, while Tab explicitly accepts a selected suggestion. Enter submits the original query or address unless the user explicitly selected a suggestion. An open tab at the typed address never replaces the default Open action. Keyword-based site searches remain selectable even when their edit text matches the original input. Disabling the experiment restores existing ordering and completion behavior. Enhanced command bar suggestions separately enables more Chromium providers, current-page context, and action labels; either setting works independently. Explicit > command mode retains its command-only behavior.
    • Open-tab search — Normal input matches open-tab titles and URLs, including UUIDs, without requiring @tabs. Both suggestion modes show a localized Switch Tab label; accepting the row activates the existing tab instead of opening a duplicate. Matching stays within the same profile and private-browsing context. Open-tab results retain the matched tab's identity, distinguishing full URLs including fragments and same-URL tabs with different titles. Moving a target to another window preserves the destination; closing it or navigating it elsewhere makes the stale action a no-op. Previously accepted tab suggestions that reappear from shortcut history behave as URL suggestions: clicking or pressing Enter opens the address when the original tab is no longer available.
    • System commands — Normal input supplements Chromium results with at most two whole-title or alias prefix matches; with experimental ordering off, an exact safe UI command is promoted to the front. The Enable > command mode toggle in You and Dao settings is off by default and independent of enhanced suggestions. When enabled, > switches to provider-free command mode and lists or filters all eight commands: Open Settings, Reopen Closed Tab, Copy Current Link, Open Downloads, Open History, Manage Extensions, Open Agent Settings, and Open Task Manager. Localized aliases augment the English matching vocabulary. When disabled, > remains ordinary input; normal command suggestions remain available.
    • Command rows use localized titles, native Lucide icons, a Command intent, availability checks, and disabled reasons. Arrow keys skip disabled rows; Tab and Right Arrow fill the title without executing it; Enter and clicks recheck availability before dispatch. Copy Current Link remains bound to the tab that was active when the bar opened, and Task Manager reuses its existing native window.
    • Asynchronous results preserve explicitly selected rows. Restore uses the current tab, window, or group title for display and completion; Agent Settings follows the browser's existing Settings availability checks.
    • URL-vs-query detection heuristics + inline completion when no selection preview is active and experimental ordering is off; the native textfield contains the typed prefix plus a selected completion suffix, derived from the default URL when its provider omits the suffix, so Select All, copy, and replacement edits include the completed text, while long suffixes keep the typed prefix and caret boundary visible
    • Every non-blank query keeps one exact-input Search action alongside the full Chromium autocomplete result. The dropdown remains five rows tall and scrolls by pointer or keyboard when more results are available; empty and whitespace-only input shows no suggestions
    • Enter before suggestions arrive submits the typed query through the default search provider; Ask AI requires an actual selected suggestion
    • With experimental ordering off, the first result is highlighted automatically without writing that row's fill_into_edit value into the native textfield; prefix-matching URL inline completion remains a distinct selected suffix, and only explicit arrow-key browsing previews a row while the original query remains separate and autocomplete is not restarted. Updates to the selected URL's display text refresh its preview while preserving the selection. Inline completion waits for stable results; without a visible suffix or an explicit selection, Enter opens or searches the visible input instead of accepting a different automatically highlighted destination.
    • With experimental ordering off, Backspace rejects a non-identical preview without deleting the query; that exact rejected suggestion stays suppressed while the user continues typing, and later provider results remain highlight-only until the user browses or accepts them; Right Arrow or Tab accepts the highlighted or previewed row without navigating, Enter submits visible inline completion or the explicitly selected result, and Esc dismisses
  • DaoSuggestionItemView (dao_suggestion_item_view.{h,cc}) — Suggestion row for autocomplete matches, Ask AI, and accessible enabled or disabled commands
  • DaoNewTabButton also routes through ShowForNewTab() without creating a tab until the user navigates

1.6 Downloads (sidebar-anchored)

  • Parallel downloading — Settings > You and Dao exposes the profile-scoped dao.parallel_downloading_enabled preference, explicitly off by default. Changes apply immediately to new downloads without restarting Dao. Each item captures the choice before its job and file writer start; active downloads and same-session resumptions retain that choice. Restored downloads with persisted parallel slices retain parallel mode so partial files can resume safely. Chromium's native eligibility checks, request splitting, retry, and assembly remain in charge; unsupported downloads stay serial. Dao's preference is the desktop source of truth, independent of chrome://flags and its restart state. Upstream tracking: this reuses Chromium's experimental ParallelDownloading implementation (flag enable-parallel-downloading), not a Dao download engine. On each Chromium upgrade, track whether that experiment ships, changes default, gains runtime configuration, or is removed; review its Finch parameters, protocol eligibility, job selection, resume/slice handling, and file obfuscation checks. Adapt or retire these integration patches when upstream provides an equivalent runtime setting. Source entry points are components/download/internal/common/{parallel_download_utils,download_job_factory, download_item_impl,download_file_impl}.cc and chrome/browser/download/chrome_download_manager_delegate.cc.
  • Download-start feedback — A blue download icon pops out at the pointer position captured when a new download is created, follows a 560ms upward quadratic throw into the sidebar button, and shrinks/fades on arrival. The button briefly pulses and highlights. Feedback is independent of progress, including files that complete immediately, and only runs in the active source window. Bursts before the sidebar replies coalesce into the latest flight. Reduced motion uses a highlight without flight or scaling; a collapsed sidebar uses the shared localized Dao toast. Restored and transient downloads do not trigger the animation.
  • DaoDownloadFlyoutView (sidebar/dao_download_flyout_view.{h,cc}) — Anchored flyout panel
  • File icons (sidebar/dao_file_icon_util_mac.{h,mm}, sidebar/dao_file_icon_util_win.cc) — Native macOS and Windows file type icons; Windows supplies a high-resolution 2x image for the 40 DIP download cards and retains a 1x image for native dragging.
  • Active-download hover details — After a settled 400ms hover, an active download row reuses the native sidebar tooltip to show the full filename, transferred/total size, percentage, current speed, and reliable remaining time. Long filenames wrap in detailed mode, and the popup flips above its anchor when needed to remain inside the browser window. Unknown totals, percentages, speeds, and estimates are omitted rather than replaced with misleading values; leaving or removing the row hides the popup immediately.
  • Latest completed download — The sidebar download button becomes a persistent filename label when an observed in-progress download completes. Clicking the label opens that file, while its close button only dismisses the label. Dragging the label starts a native file copy drag to the desktop, folders, or applications that accept files, then dismisses the label and download list without opening the file. Holding the left mouse button keeps the label alive when leaving its hover area, so outward drags can start even at the label edge; releasing without a drag or losing focus dismisses it. The drag uses the download's actual target path, including custom save locations. Hovering opens the existing download list; the label stays visible while moving between both surfaces and is dismissed after leaving their shared hover area. It never expires on a timer, and later completions replace the displayed item without adding a separate history queue.

1.7 Content Area Styling

  • DaoCornerOverlayView (dao_corner_overlay_view.{h,cc}) — 10px rounded corners + 6-step soft shadow overlay on web contents
  • Adaptive theming — Content area switches light/dark text and separators based on page luminance
  • DaoColors (dao_colors.{h,cc}) — Shared blue accent (70,120,190) plus the light/dark hierarchy tokens; consumed by chrome_color_mixer.cc.patch
  • DaoLucideIcons (dao_lucide_icons.{h,cc}) — Unified Lucide icon set

1.8 Toast and Feedback

  • Chromium toast integration (toast_controller.cc.patch, toast_view.cc.patch) — All Chromium native toast content, including Copy Link, uses the shared DaoToastView surface at the top-right of the active page, including in Split View. Chromium retains localized messages, loading indicators, action buttons (including opening the reading list), menus, close callbacks, queueing, keyboard access through pane focus shortcuts, accessibility, and tab/navigation scope; the shared surface also supports interactive content without starting a second dismiss timer
  • DaoToastView (dao_toast_view.{h,cc}) — Shared lightweight fade-in/fade-out toast for native browser feedback, including Copy URL, Copy Image from webpages and the reading side panel, QR decode failures, Control Center actions, and pinned-tab close confirmation. The pinned-tab message stays inside the Dao content area, is exposed as an accessibility alert, and preserves the existing per-tab repeat-to-close behavior. The Control Center Dark action remains clickable while system appearance is light and explains the system-dark requirement through this toast; callers retain action-specific localized text

2. AI Agent System

The AI Agent is Dao's flagship feature. Unlike browsers that bolt on a chat sidebar, Dao integrates the agent into the page lifecycle itself — it can read DOM, click elements, navigate, and remember context across sessions. Every layer (C++ Views, WebUI, Mojo bridge, LLM runtime, vendor pipeline) is purpose-built for agentic browsing.

The stack includes: LLM tool calling, long-term memory (SQLite + FTS5), proactive suggestions, a skill system, and page-aware tools (page capture, readable extraction, element interaction, accessibility tree, resource inspection).

2.1 Agent Core Services (src/dao/browser/agent/)

  • DaoAgentMemoryService (+ DaoAgentMemoryServiceFactory) — Profile-keyed long-term memory service, SQLite backend, background sequenced execution
  • DaoAgentMemoryStore — SQLite FTS5 full-text search store. Five direct store round-trip tests remain disabled because test-time RazeAndPoison conflicts with direct Init(); focused service and read-path coverage remain active.
  • DaoAgentMemoryTypes (dao_agent_memory_types.{h,cc}) — Episodic / semantic memory record types
  • DaoAgentProactiveEngine — Navigation-triggered proactive suggestion engine
    • Scenario matching (URL pattern + page hints)
    • Episodic memory matching
    • Learning pipeline triggers
  • DaoAgentScenarioRegistry — Scenario registry (seed + personal)
  • DaoAgentSkillService (+ DaoAgentSkillServiceFactory)
  • DaoAgentSkillTypes (dao_agent_skill_types.{h,cc})

2.2 Agent Tab Integration (C++ Views)

  • DaoAgentSidebarView (dao_agent_sidebar_view.{h,cc}) — WebUI-driven container, preloaded for fast toggle
  • DaoAgentCursorView (dao_agent_cursor_view.{h,cc}) — Native white-core blue orb with a soft halo, a 200ms fading motion trail, one breath on arrival, and core-press plus double shock-wave clicks. AnimateAgentCursorInViewport is the shared Agent/MCP/task-window path: it converts page CSS pixels to view DIPs with the tab's page zoom (pinch zoom is ignored) before moving the cursor. When click_by_ref supplies the target element's rect, ComputeAgentCursorFrame pads it, gives tiny targets a 28px minimum, clips it to the target's own viewport (so Split View panes never bleed into each other), and skips page-sized containers that cover at least 80% of the viewport; the rounded blue focus brackets appear as the move starts, tighten on arrival, squeeze on click, stay through the 1.12s click effect, and fade over 520ms afterward (about 1.64s from click feedback to disappearance). agent_click keeps its in-page highlight instead, and move_cursor draws no frame. The cursor fades in, stays where it last acted, and dims after 5s idle. While the tab is agent-locked, it remains at that position until the next action and hides when the lock ends; failed or cancelled tools clear movement, focus brackets, and click effects without hiding or repositioning the cursor, and complete pending movement callbacks. Unlocked cursors fade out after 12s. A framed target waits for its click before idling. Opacity runs on compositor layer animations, so idle dimming and fading never repaint the overlay, and a new action eases back to full opacity. A hidden cursor reappears just up-left of its next target instead of at the content center. BrowserView forwards active-tab changes and updates; the cursor only reacts when the active tab changes or its agent lock starts or ends, so page loads and title changes never move, reveal, or hide it. Reduced motion jumps without trail, breath, or bracket travel. Visuals render only when the pinned target is the active tab of a visible, non-minimized, active window. Background moves are successful visual no-ops, while background clicks skip animation and keep dispatching through the pinned DevTools target. Short foreground moves use direct easing; long moves follow a bounded curved path. Overlapping requests skip animation without dropping a pending callback; new moves cancel old ripples, and delayed click feedback cannot interrupt a move. Recentering the cursor, including when switching to a locked tab, cancels pending movement and completes its callback.
  • DaoAgentLockBannerView (dao_agent_lock_banner_view.{h,cc}) — Animated banner shown while AI controls a tab
  • DaoAgentLockTabHelper (agent/dao_agent_lock_tab_helper.{h,cc}) — Per-tab lock state observer
  • Action cursor feedback (automation/dao_page_tools.{h,cc}) — Shared MCP/Agent form filling focuses the validated input, textarea, or contenteditable host, moves the native cursor to it, then revalidates the target before editing. Filling shows no click ripple or click-only focus brackets. Direct text input and key chords show the cursor over the focused element, including open shadow-root inputs and nested same-origin or cross-origin frames, without waiting for animation before dispatching input. Successful results wait for feedback to finish so sequential actions cannot skip cursor destinations; a navigation after an action completes does not invalidate that completed result. Selector clicks and highlights show the target position; page scrolling shows the viewport center, and scrolling to an element reveals it immediately before positioning the cursor over its visible area. Element feedback intersects the target with ancestor scroll/paint clips and each frame viewport; Clipping follows positioned and slotted inputs through their layout ancestors; focused-frame coordinates include frame borders, padding, and scaling. Feedback failures do not block legacy actions; failed or cancelled actions cancel their cursor effects. Background targets keep executing without activating their tab or window or hiding another tab's cursor. Read-only queries and arbitrary scripts do not invent a target position.
  • Window-scoped tab automation (automation/dao_tab_tools.{h,cc}) — Shared Agent/MCP list, switch, open, and close operations stay inside the authorized browser window. Agent turns start on the current page, then keep their stable target when the user changes tabs, windows, or applications; Agent switch_tab retargets without activation and open_tab creates a background target. MCP switch_tab activates a granted page, while open_tab creates a granted background target. Sessions follow the same stable tab across WebContents replacement, tab IDs are reconciled to remain unique within a window, and ambiguous selectors fail closed. New targets are limited to HTTP, HTTPS, or about:blank; close results wait for unload approval; Agent retargets after removal, while MCP never adopts a replacement page.
  • Scoped semantic page automation (automation/dao_page_tools.{h,cc}) — Agent and MCP clients can query a bounded set of elements by selector/ref scope, role, accessible name, text, visibility, enabled/writable state, and first/last/index selection. Queries recognize contenteditable hosts as textboxes unless explicitly assigned another role, match text fields by their current content, and return non-sensitive plain-text values capped at 2,000 characters with a truncation marker. Ref scopes require the document and snapshot tokens that produced the ref, preventing a reused ref label from resolving inside a newer snapshot. Query and full-tree results carry document and snapshot tokens; click_by_ref validates the target before moving the native cursor, then revalidates those tokens plus optional URL, visibility, enabled, text, role, and ancestor preconditions in the same page script that dispatches the click. Successful clicks with completed foreground cursor moves show the Dao ripple; background clicks remain pinned without activating the window. Navigation, a newer snapshot, or a changed target during animation fails closed.
  • Synchronous page scripts (automation/dao_page_tools.cc, browser_tool_catalog.json) — Agent and MCP execute_script evaluates code as supplied, with IIFE examples for reusable local declarations and return values. Top-level let/const bindings persist across calls, top-level await is unsupported, and returned promises are not awaited. Script exceptions retain their original JavaScript details and existing non-retryable INTERNAL_ERROR classification, including runtime SyntaxError exceptions from JSON parsing or page code.
  • Batched Agent browser actions (resources/agent/pi_tool_adapter.ts, agent_bridge.ts) — Browser tools emitted in the same model response execute sequentially through the existing runtime. A failed or invalid earlier tool call skips later browser actions in that response, including legacy error results without a code. The default prompt batches only known arguments and observes again at decision boundaries; callers must reacquire refs after any successful query or tree snapshot.
  • Guarded form input and semantic waits (automation/dao_page_tools.{h,cc}) — Shared Agent/MCP fill_by_ref replaces or clears a visible, enabled, writable text input, textarea, or contenteditable host after validating document/snapshot/ref tokens, optional click preconditions, and focus. A synthetic, cancelable beforeinput hook runs in the same page task as the Chromium editor operation; cancellation preserves the value, and focus, target identity, editability, and preconditions are checked again after handlers run. The editor restores the full selection before replacing or clearing and emits trusted input events for controlled fields. Rich-text replacements use plain text, with logical block/BR line breaks, CRLF normalized to LF, and nonbreaking spaces normalized to spaces. Value reads collapse source indentation and ordinary HTML whitespace while preserving spaces and newlines in preformatted content; replacements preserve requested consecutive spaces even when the field normally collapses whitespace. No-op detection and immediate verification also check that embedded content such as images and horizontal rules has been removed, including content restored by input handlers. Queries, value preconditions, and immediate fill verification share that representation; inherited editable descendants are not separate fill targets. Agent guidance prefers a query followed by one fill without separate focus/select/readback scripts; success describes the local value, not submission or task completion. press_key_chord dispatches trusted Chromium key events using US-layout key names. Keydown and keyup are queued together so cancelling or timing out while a page handles keydown does not leave the key held. Shortcut letters are case-insensitive without adding Shift; explicit Shift and standalone uppercase letters retain their meaning. Supported macOS editor commands include Cmd+A, Cmd+ArrowLeft/Right for line boundaries, Cmd+ArrowUp/Down for document boundaries, Shift selection variants, Cmd+Backspace, and Cmd+Z/Shift+Z, alongside page defaults such as Enter and Tab. wait_for_element reuses semantic query filters with bounded 100 ms polling, a 30-second maximum, and cancellation/navigation cleanup; pending waits preserve refs, success creates a fresh snapshot, and exact zero matches requires an existing scope. Agent bridge deadlines accommodate the full native element/network wait budgets.
  • Session-scoped DevTools automation (automation/dao_devtools_tools.{h,cc}) — Agent and MCP clients share native network, console, and page-resource tools. Network tracking returns a monotonic cursor, and wait_for_network_response waits for a later completed response by wildcard URL, method, status, or a bounded simple dotted JSON path while projecting only requested values. Missing select paths are omitted without rejecting the response, explicit JSON nulls are preserved, and json_path/any_of remain matching conditions. Domain requests persist independently from confirmed state; events arriving while an enable attempt is pending are staged for that exact generation and host, then committed by a matching success or dropped after all matching attempts fail, cancellation, or a binding change. Clear actions remove both committed and currently staged events without cancelling the matching enable attempt, so only later events can commit. Within one binding, confirmation is monotonic after any successful enable and resets only when the binding changes. Network and console capture retain recent entries under UTF-8-safe field, entry-count, and aggregate-byte budgets with explicit dropped/truncated metadata. One iterative, deduplicating resource traversal synthesizes each frame's Document and reports item, URL-byte, depth, source, scan, and match limits separately. Resource reads require the current exact (frame, URL) tree entry when a frame is supplied and reject known decoded sizes over 1 MiB before fetching content; independent per-command response ceilings cover missing metadata. Resource search reports attempted, successfully searched, failed, and content-limited sources plus explicit incompleteness, including bounded Document DOM ingress.

2.3 Local MCP Server

  • Process-global native service (mcp/dao_mcp_service.{h,cc}) — A default-off Local State preference controls one authenticated local endpoint with at most 32 admitted clients, bounded requests, serialized native approval prompts, idle-client eviction, and exclusive per-page automation leases. Authentication and catalog discovery do not prompt or start approval timers. First calls without tab_id approve creation in the exact selected normal window, including when its active page is internal; no existing page is granted. New tabs open in the background, are granted only to their creator, and become that connection's default target. Listing and all page/tab operations expose or control granted pages only, and MCP tab indices count granted pages only. Optional page-tool tab_id routes to a granted page; losing the default target clears routing without a fallback.
  • Explicit MCP page grants and revocation — An initial tab_id retains narrow access to that exact page, including a background page across windows, without creation permission. The MCP-only request_tab_access tool requires a reason and requests another page in the approved window: an ID pins approval to that page, while omission opens a native picker without disclosing candidates to the client. Ambiguous IDs and identities changed during approval fail closed, as do stale, cancelled, denied, or lost targets. Native management lists connections, creation scope, and granted pages; revoke cancels one page's work and releases its lease while leaving the page open, and Stop ends the explicit connection. Zero-page connections preserve creation permission; with page auto-approval off, revoked pages always require fresh approval. Window/profile loss, disconnect, and disabling MCP release every grant.
  • Settings master switch, connection, quick setup, and usage (mcp/dao_mcp_settings_handler.{h,cc}, resources/settings/dao_page/) — You and Dao groups the process-global MCP Local State switch, live connection status, profile-scoped usage, and enabled-only setup into one native-style card. Opening the section initializes live MCP status and the skill/command list on direct navigation and in the settings overview. It renders Disabled, Ready, Approval requested, and Connected states; lists this profile's connections, creation permissions, and granted pages with explicit connection-stop and per-page revoke actions; and lists total and per-tool calls with a reset action. Usage counts each call that reaches the real executor, whether it succeeds or fails; validation, denial, unknown-tool, and pre-execution target failures are excluded. Quick setup defaults to Codex CLI and also offers a user-scoped Claude Code CLI command plus Generic MCP JSON. The preview and clipboard always contain the same native-generated content: CLI commands remain single-line, while Generic MCP is Chromium-native three-space pretty JSON. Malformed Generic MCP JSON fails closed by clearing the preview and leaving the clipboard unchanged; the former standalone configuration button is removed. Native shell quoting (POSIX on macOS, PowerShell on Windows) protects the running installation's actual helper path and its explicit current user-data-directory argument, so Debug and custom-profile installs connect to the correct runtime endpoint.
  • Hardened local transport (local_ipc/dao_local_ipc_transport.{h,cc}, dao_local_ipc_connection.{h,cc}, dao_local_ipc_runtime_files.{h,mm}, dao_local_ipc_runtime_files_win.cc, dao_local_ipc_win_util.{h,cc}; compatibility headers in mcp/) — The server owns all listener and connection I/O on Chromium's browser IO thread, uses a non-abstract Unix domain socket with owner-only permissions and peer UID checks on macOS, or a loopback-only ephemeral TCP port with current-user process checks and private runtime ACLs on Windows, authenticates every connection with a fresh 256-bit nonce, caps open sockets at four times the 32-client admission limit so hello-time eviction and rejection can drain while aggregate ingress credits stay sized for 32 admitted clients, and removes runtime artifacts on disable or shutdown. Atomic runtime.json metadata publishes the endpoint and nonce only inside that private directory. Windows directory handles allow write sharing for atomic metadata publication while denying delete sharing to keep the directory pinned; metadata file handles retain read-only sharing. The Windows helper verifies the connected server process against the metadata before sending its nonce; reparse points, hard links, and permissive runtime ACLs are rejected. Per-connection and aggregate IO-thread credits bound requests posted but not yet consumed by the UI thread, terminal responses synchronously close only that connection's logical request gate, aggregate write budgets fail closed under backpressure, and graceful close has bounded request and write-drain deadlines.
  • Versioned NDJSON protocol (mcp/dao_mcp_protocol.{h,cc}) — Protocol version 1 supports hello, tools/list, tools/call, and tools/cancel, with an 8 MiB line ceiling, 64-request/8 MiB pending-ingress budget, and structured errors. Catalog discovery is available before approval, while execution waits for approval and the external automation lease. Every MCP tool advertises a reason argument required on the first call of each connection; missing, blank, invalid UTF-8, or reasons over 1024 UTF-8 bytes fail before opening a prompt. Later calls may omit it except for request_tab_access, get_site_skills, and save_skill, which always require a reason; permission metadata is removed before page-tool execution.
  • Central external-target eligibility and MCP lifecycle policy (automation/dao_browser_target_policy.{h,cc}, mcp/dao_mcp_session_lifecycle_monitor.{h,cc}) — Every MCP target stays pinned to its exact tab in the approved normal Browser and regular Profile, with no eligible-tab or active-tab fallback. HTTP, HTTPS, literal about:blank, and web-hosted PDFs are allowed; popup, Incognito, Guest, internal, extension, DevTools, Agent WebUI, file, data, and custom-scheme targets are rejected. Target destruction or forbidden navigation cancels and removes only that tab's work, lock, overlay, and CDP state; zero-page connections remain available; losing the Browser or the Profile closes only the affected logical connection and releases its leases.
  • Exact-window approval and control UX (dao_mcp_approval_dialog.{h,cc}, dao_mcp_control_banner_view.{h,cc}, dao_address_bar_view.{h,cc}, ui/webui/dao_sidebar_ui.{h,cc}, resources/sidebar/dao_tab_item.ts) — Execution leases display localized, fail-closed Dao system dialogs one at a time in the exact normal Browser selected for approval, with a scope-specific title, the sanitized self-reported requester, the requested tab title and site (or a visible tab picker), a sanitized reason labeled as client-provided, and one explanation of signed-in access, JavaScript, and authorization scope. An initially collapsed details section holds the client version, browser-recorded request date/time with time zone, window, full URL, and Profile; the Profile stays visible outside details when multiple profiles exist. Queued prompts preserve their original reason and timestamp, and long reasons scroll within a bounded area. Dialog content stays within the fixed dialog width (a nominal 720 DIP content area for an explicit target tab, otherwise 480 DIP, with Chromium's standard width snapping) even with long tab titles or URLs, with full-text hover tooltips for single-line text. Explicit-target prompts place the requester, reason, permission explanation, and collapsible details on the left, with a 320 DIP-wide local page preview on the right and the page title and site below it. The tab picker keeps its vertical layout and updates its preview with the selected page. Page previews reuse cached thumbnails when available; otherwise, they temporarily request rendering and take a bounded surface snapshot, even when tab hover previews are disabled. On-demand capture preserves tab selection and page visibility, retries unavailable surfaces, and releases its rendering request on success, cancellation, navigation, tab closure, or a three-second timeout. Missing previews show a localized fallback; selection changes, filtering, navigation, and tab closure clear obsolete images, and preview pixels never reach the requesting client. The tab picker filters titles and URLs as the user types, ignoring case, and shows a message when nothing matches. Filtering out the selected tab clears the selection and disables Allow until another tab is selected. Before showing a prompt, Dao activates that native Browser window so approval requests arriving while Dao is behind another application come to the foreground; unanswered prompts time out after 60 seconds. Allow is intentionally not the default action. A robot button immediately before the URL pill appears only while the active page is controlled, and its popup closes when that page is no longer controlled; an approved connection alone does not show the button; every controlled tab also shows a quiet robot in its sidebar close-button slot, replaced by the normal close button on pointer hover or keyboard focus. The address-bar popup lists that window's connections, creation scope, and granted pages, with a revoke action for each page and Stop for each explicit connection. Tool calls update each connection's latest accepted tool and granted page titles and URLs in place without dismissing the popup, including calls from other windows; grant changes close the popup so it cannot show stale grants. Stop cancels the selected connection's external work, releases its leases, and closes it without inserting a control row above page content.
  • Per-tab peer contention — The browser-automation lease is exclusive per tab, so different Codex or Dao Agent sessions can operate different tabs concurrently. A second browser-tool session targeting an already controlled tab waits or fails with the stable retryable busy error before CDP execution; chat and non-browser tools remain available.
  • Native stdio MCP helper (mcp/helper/) — The standalone dao-mcp executable speaks newline-delimited JSON-RPC and negotiates MCP 2025-11-25 or 2025-06-18 over stdin/stdout, discovers the authenticated browser endpoint from the active user-data directory, and bridges MCP string or numeric request IDs to bounded browser IPC IDs. Its initialization response opts out of Codex's shared tool-catalog cache and directs MCP clients to prefer Dao tools for Dao Browser work, create background research tabs with open_tab, request existing pages with request_tab_access, use create_space for multi-step work that should not take over the user's tabs, preserve that target across follow-ups, and treat ambiguous open/click/select requests as page-local query_elements plus guarded click_by_ref interactions. switch_tab is reserved for explicit browser-tab navigation, while exported tool descriptions retain only the general Dao MCP preference. It maps the 44-tool catalog to MCP annotations, normalized object/scalar/list results to text plus object structuredContent, screenshot media to one image content block with its real MIME type and metadata-only structuredContent (without duplicate base64), and tool failures to isError: true. Cancellation is forwarded to the browser and late responses are discarded. Windows stdout uses bounded nonblocking write chunks so catalogs and tool results larger than Node clients' pipe buffers make progress, preserving queued bytes and message order when the reader pauses. Stdout remains protocol-only; unavailable-browser diagnostics are deterministic stderr output.
  • 44-tool external scope — The shared native catalog contains 45 browser tools: 42 for the Dao Agent, including seven Agent Space tools, plus the MCP-only get_site_skills, save_skill, and request_tab_access; MCP exposes 44 and excludes the Agent-specific resolve_element_context. General Agent memory, workspace, web-provider tools, and other skill management remain outside the local MCP server. Skill access is limited to reading host-specific instructions and saving user skills with separate consent.
  • Desktop helper packaging (mcp/BUILD.gn, cli/BUILD.gn, dao_version.gni, chrome/BUILD_mcp_helper.gn.patch) — The helpers are built independently from the browser service, receive the same Dao product-version build argument as the app, and are copied with executable permissions to Dao.app/Contents/Helpers/dao-mcp and Dao.app/Contents/Helpers/dao-browser on macOS. Windows builds and installs dao-mcp.exe and dao-browser.exe alongside chrome.dll in the version directory, keeping the CLI and browser runtime together during updates.
  • Independent execution peer — MCP owns one isolated automation session, DevTools client, executor, cursor integration, and cancellation state per controlled tab. It reuses the shared native tab/page/DevTools implementations and lease coordinator without depending on the Agent WebUI lifecycle.

2.3a Agent Spaces (background task windows)

  • Hidden task windows (agent_space/dao_agent_space{,_service}.{h,cc}) — create_space opens a normal Browser window in the user's regular profile that is never shown, omitted from session restore, and registered as an Agent Space. With logins: false it opens a clean space instead, in a temporary off-the-record profile without the user's cookies or sign-ins that goes away with its window. Every tab in a running space holds a visible-capture keep-alive (IncrementCapturerCount, not hidden), and on macOS the never-shown window keeps its compositor unsuspended (native_widget_mac_ns_window_host.{h,mm}.patch, dao_native_util_mac.{h,mm}), so pages render, run timers, play media, and report visible exactly as on screen, and stays locked against user input while the agent controls it. At most four spaces run per profile, each with up to eight tabs; popups past the limit close and are reported in the next result's closed_popups. Running spaces with no activity for 30 minutes stop automatically. Spaces belong to a client type: the Dao Agent sees only its spaces, and MCP/CLI clients share theirs so short-lived CLI connections can resume work. Finished and stopped spaces (up to eight) are kept in the dao.agent_space.history profile pref, so the sidebar still shows their results after a restart until dismissed.
  • Window-finder isolation (agent_space/dao_hidden_browser.h, browser_collection.cc.patch, profile_browser_collection.cc.patch, browser_window_interface_iterator_non_android.cc.patch, browser_navigator.cc.patch) — While a task window is off screen, last-active lookups and FindTabbedBrowser skip it, so external links, new-window commands, notifications, and MCP window approval never land in it. Guarded clicks in a space carry a user gesture (DaoPageTools::UiDelegate::GrantsUserActivation), so pages can open popups and new tabs from them as they would for the user; popups, new windows, Document PiP, and split views from its pages get a tab in the same hidden window instead, and the navigator never shows a hidden task window. The "AI is working" lock banner animates only while its window is visible.
  • Dialogs and browser prompts off screen (tab_modal_dialog_manager{.cc,_delegate.h}.patch, javascript_tab_modal_dialog_manager_delegate_desktop.{h,cc}.patch, agent_space/dao_hidden_dialog.h, browser_web_contents_delegate.cc.patch, chooser_bubble_ui.cc.patch) — JavaScript dialogs go to the agent: alerts are accepted so the page continues and are reported in the next tool result's dialogs; confirm and prompt stay pending instead of being cancelled, cancel the call stuck behind them, and make other tools fail with PAGE_DIALOG_OPEN until handle_dialog answers them. If the user opens the window first, Chromium's pending-dialog path shows the dialog to them. beforeunload prompts in a hidden window proceed. Browser UI only the user can answer hands the space to the user: file pickers and USB, Bluetooth, serial, or HID device choosers are cancelled and reported, and tab-modal browser dialogs such as site sign-in, security key, and certificate prompts stay open for the user (WebContentsModalDialogManager::Observer).
  • Downloads (download_target_determiner.cc.patch) — Downloads started in a hidden task window are saved without a prompt into Downloads/<AI Tasks>/<task name>/ (folder name localized). Each space tracks its downloads with file name, path, and state (in_progress, complete, interrupted, cancelled, or needs_review for files the browser flagged), shows them in the timeline, and reports them from list_spaces and finish_space.
  • Space-routed tools — Every page, tab, and DevTools tool accepts an optional space_id (plus label, a 3-6 word caption) that runs it against the space's own automation session, DevTools client, and executor; omitting it keeps today's behavior on the user's current tab. Space tools are create_space, list_spaces, set_space_status, request_user_help, finish_space, handle_dialog, run_browser_script, and the MCP-only get_site_skills, which returns Dao's host-specific skills (builtin/ and user/hosts/<host>/) for a URL. Direct MCP get_site_skills calls use the independent read consent below instead of space routing; dao.siteSkills(url) inside an approved Lite script keeps using the script's consent. Non-tab tools also accept a space tab_id to retarget first, and list_tabs in a space reports opened_by (agent or user). Tabs the user opened while in control refuse agent tools until the agent claims one with switch_tab.
  • Control and handoff — A space is running (agent controls) or user_in_control. Taking over, a page permission prompt (location, camera, notifications and other requests are invisible off screen), the browser prompts above, or request_user_help moves control to the user, cancels in-flight agent calls, releases the keep-alive, and unlocks tabs; agent tools then fail with SPACE_USER_IN_CONTROL and fixed guidance to stop without retrying. The user hears about it from a localized toast and a system notification that opens the task window when clicked; both clear when control returns or the space ends. request_user_help waits up to 14 minutes for the user to hand control back and returns what changed (opened, navigated, and closed tabs). finish_space closes the window; kept tabs move into an "AI results" folder at the top of the user's sidebar (dao_folder_storage.{h,cc} AddTabsToFolderFile; pages of clean spaces reopen by URL) and a localized toast reports the result. Closing or hiding a live task window preserves its pages and in-flight work; if the user has control, it also hands control back to the agent and resolves any pending help request with the user's page changes. The user can reopen it without restarting the task. Closing or hiding a fullscreen task window exits fullscreen before hiding it, so macOS does not leave an empty fullscreen Space; reopening during the exit cancels the pending hide and keeps the current control owner. Stop, closing all browser windows, closing all windows of its profile (including profile deletion), and browser shutdown end the space with SPACE_CLOSED; cancelling a bulk-close confirmation leaves tasks running; stop and finish detach tabs before closing so beforeunload prompts cannot strand a hidden window.
  • Sidebar watching (ui/webui/dao_agent_spaces_handler.{h,cc}, resources/sidebar/dao_agent_spaces.ts, agent_space/dao_agent_space_frame_capturer.{h,cc}) — User windows list AI tasks below pinned sites and above the New Tab button under a header that counts running tasks. A collapse arrow sits before the header title. Clicking the header or pressing Enter/Space while it is focused collapses or expands the list; the title and live task count stay visible, task updates keep the section collapsed, and collapsing closes any inline panel and stops pending or active previews without stopping tasks. The section starts expanded when the sidebar is created. Each row has a state icon (spinning while running, an amber hand when the task needs the user, an accent hand after a manual takeover, a check when finished) and the agent's status, latest step or pending page dialog; rows that need the user show a Resolve button that opens the task window, finished and stopped rows show the agent's summary (up to two lines) with Remove from list, and running rows reveal Open window and Stop on hover. Hovering streams a live 4 fps preview with the agent's pointer into the native sidebar tooltip; opening a task turns the row into a card that names the requesting client and start time, streams a 12 fps JPEG view with an animated pointer, leads with a Now line (status, dialog, or handoff reason), lists the three latest steps (label or step type and the targeted element's role and name from earlier query results; time and site on hover) with Show all steps for up to eight, and ends with Take over / Hand back plus Open window and Stop icon buttons. Frames are captured only while someone watches. Leaving the sidebar, removing or finishing a task, and disconnecting its UI cancel pending and active hover capture. Live hover sessions cannot overwrite or dismiss a newer tab or download tooltip; frames with unchanged title and size repaint the tooltip without triggering browser layout. In a task window the sidebar shows a control bar with the task, its state, Take over or Hand back, Hide window, and Stop.
  • Code-first scripts (agent_space/dao_agent_script_run.{h,cc}) — run_browser_script evaluates model-written async JavaScript in a hidden, offline about:blank page without WebUI bindings (CDP Network.emulateNetworkConditions), so scripts cannot use the user's cookies directly. A CDP Runtime.addBinding bridge turns dao.call(), dao.createSpace(), dao.siteSkills(), and Space helpers (find, waitFor, click, fill, type, press, open, eval, status, help, dialog, finish) into ordinary space-routed tool calls, so scripts can only act in spaces. dao.saveFile() returns up to 3 MiB of text or base64 bytes that the dao-browser CLI writes locally; the browser never writes to script-chosen paths. Results include the return value and captured console output; syntax errors report the user's line and column; runs are bounded by a 10-minute maximum and 500 tool calls. If the user takes over or stops a space mid-run, the script's output is dropped and only the stop guidance is returned.
  • Built-in Agent integration (resources/agent/{agent_bridge,browser_tool_catalog,tool_catalog}.ts, dao_agent_ui.cc) — The Agent advertises optional space_id/label on browser tools, routes space calls through executeSpaceTool without requiring the active-tab turn lease, cancels its in-flight space calls when a turn ends, and its system prompt explains when to use a space, clean spaces, labeling, dialogs, help requests, and the hard-stop rule. Its first create_space asks the user in a Dao system dialog (DaoMcpApprovalDialog::ShowAgentSpaceConsent); "Don't ask again" sets the AI settings toggle "Let Dao Agent start background tasks without asking" (dao_agent_space_allowed), which the user can turn off again.
  • Completed task review — Finished and stopped sidebar rows expand to show the full summary and the final page list, in tab order. Selecting a page activates its surviving result tab or reopens its saved address in the user window; reopened pages may have changed and are not content snapshots. Finishing a task while its card is open replaces the live view with results and stops capture. Regular-space page titles, addresses, and active-tab metadata persist with the task history; clean-space page lists remain available only for the current browser session. Older records without saved pages show an explicit empty state. Dismissing a record leaves opened result tabs alone.
  • Saved site instructions consent (mcp/dao_mcp_service.cc, dao_mcp_approval_dialog.{h,cc}) — Each direct get_site_skills call requires a reason and a separate read-only dialog naming the requested host and profile. Consent covers one read of enabled notes matching that host or a parent domain, excludes global skills, grants no window, tab, or Dao Lite access, and is never remembered. Reads remain bound to the profile selected before consent. Cancellation, timeout, denial, and disconnection prevent delivery; late approval callbacks cannot authorize a reused request ID. The catalog recommends this optional read only when it helps the task.
  • External skill saving consent (mcp/dao_mcp_service.cc, agent/dao_agent_skill_service.{h,cc}, dao_mcp_approval_dialog.{h,cc}) — Direct MCP save_skill creates or replaces a website or global user skill after a separate approval for each save. The dialog shows the complete proposed Markdown, destination, host/global scope, and pinned profile. A reason is required; page, read, and Dao Lite grants never authorize saving. IDs and lowercase hosts are path-validated, content is valid UTF-8 with required name/description frontmatter and instructions within 64 KiB, site-scoped frontmatter cannot broaden the host, and saves reject symlink destinations and replace files atomically. Agent Space and nested script calls are rejected. Denial or cancellation before approval prevents writes; after dispatch, timeout or disconnection may not stop a save, so callers must verify before retrying.
  • Dao Lite background consent (mcp/dao_mcp_service.cc, dao_mcp_approval_dialog.{h,cc}) — MCP calls that are space tools or name a space_id use a separate Dao Lite approval scope, except direct get_site_skills reads and save_skill writes. "Allow for 1 hour" lasts one fixed hour from approval for the same reported client name and profile, across reconnects; activity does not renew it. The next operation after expiry asks again, including on an existing connection; nested script operations also reject expired consent. Concurrent pending connections reuse the approved grant. "Always allow" retains the existing Local State client-name preference. Disabling MCP clears both grants; stopping a connection also revokes its background grant. Reported names are labels, not authenticated application identities. No user window or tab is leased, and ordinary page authorization remains separate.
  • Independent YOLO permissions (mcp/dao_mcp_service.*, dao_pref_names.*, resources/settings/dao_page/dao_local_agent_page.{html,ts}.patch) — Local agent collaboration groups two persistent, process-wide switches under YOLO mode, both defaulting off without enabling the MCP server. Dao Lite auto-approval covers background spaces only; browser-page auto-approval covers requested window creation scope and eligible existing pages only. Either can be enabled without authorizing the other. A page request without an ID selects only the approved window's current eligible tab; an internal or otherwise forbidden active tab never falls back to another page. Target validation, exact-window scope, exclusive leases, Stop, and Revoke remain enforced; new requests may automatically reacquire revoked pages while page auto-approval is on. Enabling either switch resolves its pending approval dialogs after revalidating the original targets; stale dialog callbacks cannot authorize later requests. Turning either switch off restores its existing consent rules for new access requests, including subsequent Dao Lite calls and running script subcalls, without creating remembered or one-hour grants from automatic approval. Existing manual Dao Lite consent remains valid. Existing page grants remain until revoked or disconnected. Saved-instruction reads and writes retain their separate consent.
  • Local agent collaboration settings (resources/settings/dao_page/dao_local_agent_page.{html,ts}.patch) — A dedicated section beside Dao Agent groups local integrations on macOS and Windows. The MCP card places enabled-only Quick setup directly below the server switch, followed by the YOLO mode group with independent Dao Lite and browser-page switches, explicitly labeled MCP server status, connections, and usage. Connection status and Quick setup refresh immediately when the server switch changes, without reloading Settings. A separate Skills and command card keeps manual installation available when MCP is off and includes a collapsed How to use guide with Codex and Claude Code invocation examples, including targeting an existing page by copied tab ID, and background tasks. The section has its own navigation entry and participates in settings search.
  • dao-browser CLI and three entry skills (cli/, mcp/dao_local_agent_integration.{h,cc}) — The packaged dao-browser (dao-browser.exe on Windows) provides skill (existing-page guide) and skill --lite (background-task guide; both embedded at build time and wrapped in version markers, with the version read recorded in <user data>/dao_browser_guide_version), run (one script per call, stdin or file, --space, --timeout; writes dao.saveFile() files), call, status, and mcp (the stdio MCP server). Those existing-page and background commands reuse the authenticated MCP endpoint, start Dao in the background when it is not running, and exit 2 with fixed guidance on a hard stop. After a successful run or call it prints [dao-browser:notice] lines to stderr when the guide for this Dao version has not been read yet or a downloaded update waits for a restart (update_ready in the hello reply). Local agent collaboration > Skills and command offers independent Install, Update, and Uninstall actions for the shared Codex/other-agent skill set in ~/.agents/skills, the Claude Code skill set in ~/.claude/skills, and the ~/.local/bin/dao-browser command link (dao-browser.cmd on Windows). Windows entry skills include a quoted PowerShell fallback to the installed executable, so they also work without changing PATH. The MCP switch controls existing-page and Dao Lite access; Home editing uses its independent endpoint. Opening or returning to the local-agent section (including sidebar navigation and scrolling) or settings overview automatically compares installed skill contents and the CLI target with the running app; stale copies show Update available. Status also refreshes after install, update, and uninstall actions; there is no separate Check for updates button. Explicit shared-skill updates migrate Dao-managed ~/.codex/skills/dao-browser copies into .agents, and shared uninstall removes both managed copies. Custom files and symlinks to user skills are preserved, and conflicts or filesystem failures are reported. Status reads and mutations run on the same sequence. An explicit user choice of dao-browser, dao-lite, or dao-home takes priority, including when an older installed guide suggests another mode. Without an explicit choice, use dao-home for Home project editing, dao-browser for existing Dao tabs or windows, and dao-lite for searches, research, and background web automation. The Dao Lite entry skills, Claude Code command, and background guide prefer one Agent Space per user goal, with multiple tabs for related sites and subtasks and the same active space_id reused across CLI calls and phases. Separate spaces are for independent goals, required sign-in isolation, or an explicit user request; complexity alone does not justify splitting a task. Space resumption preserves user-takeover and stopped-task hard stops. dao-browser uses a persistent MCP connection and separate page approval. Its guide, MCP initialization instructions, and page-access tool descriptions require a supplied target tab ID to be passed verbatim, treating a single otherwise-unexplained UUID in an existing-page request as that ID even on a separate line. Multiple ambiguous UUIDs need clarification. A missing supplied ID returns TAB_NOT_FOUND, prompting one retry on the same connection with the same reason and no tab ID. That retry follows normal page approval or configured page auto-approval; denial, revocation, and forbidden targets do not trigger it. Both can use sign-ins. Updating installs all three skills, detects incomplete installations, and preserves custom files; uninstall removes managed copies of all three. agent-plugins/claude-code/ packages all three entry skills and commands for Claude Code; agent-plugins/agents/ shares one portable Agent Plugins manifest and three-skill set across Codex, Cursor, and other compatible agents.

2.4 Agent WebUI (dao://agent and dao://skills)

Application shell (src/dao/browser/ui/webui/resources/agent/)

  • agent.{html,css,ts} + dao_agent_app.ts — Chat app entry; its settings button uses a fixed native navigation command to open the unified dao://settings/agent secondary page and closes the sidebar only after the navigation succeeds
  • skills.html + skills.ts — Skill manager standalone entry
  • agent_bridge.ts — Mojo bridge
  • agent_settings_{sync,native_bridge}.ts — One-time migration from the dao://agent local-storage origin and live synchronization with the Profile-scoped settings source of truth

Chat surface

  • dao_chat_view.ts — Main conversation view (session resume, skill picker, dynamic chips, composer height tracking, cost stats / usage)
  • Response links — HTTP(S) links in the Agent sidebar open a foreground tab in the sidebar's owning browser window, preserving the conversation and the current page; Markdown and tool-result links support new-tab targets
  • Agent browser-turn lifecycle — New sends, retries, regeneration, and edited-message resends each acquire their own native turn before execution and release it on completion or failure. Editing an active response waits for both model cancellation and native cleanup before starting the next turn. Agent and MCP share the native browser tools and per-tab lease coordinator; their sessions, authorization, and turn lifecycles remain independent.
  • Historical message editing — After stopping a response, use the user message's More actions > Edit menu to change its text and remove individual page, selection, element, PDF, image, or file attachments. Cancel keeps the original message intact. Save and resend persists the edited message, excludes removed context from the model request, and replaces all later messages while preserving earlier conversation history. Attachment-only messages remain valid while at least one attachment is kept.
  • Latest Agent error retry — A terminal provider error exposes a retry action that reuses the original user submission, replaces only its failed assistant/tool branch, and preserves every earlier timeline entry; cancelled and historical errors cannot truncate the conversation
  • dao_chat_history_panel.ts — History panel
  • dao_compact.ts — Conversation compaction for context management
  • dao_page_capture.ts — Convert current page to markdown and insert into the message
  • dao_share_image.ts — Share-card image generation
  • dao_tool_renderer.ts — Tool-call result rendering
    • Every tool call keeps its stable tool name visible; provider-specific search/fetch context is shown as secondary summary text, while parameters and output stay collapsed by default and can be expanded per call

Skills + tools

  • dao_skill_manager_view.ts — Skill management surface
  • skill_registry.ts — Skill catalog and lookup
  • tool_catalog.ts — Tool catalog schema

Unified Agent settings (dao://settings/agent, overview entry #agent)

  • The optional bundled Jev plugin has an experimental, default-off connection checkbox after the main provider settings and a separate default-off global tool permission. Its full HTTP(S) API URL, masked Bearer token and optional model ID persist in Profile settings independently of the main model. The model ID is trimmed for requests; empty or whitespace-only values use jev-latest. Opening or editing settings sends no inference request. Invalid or incomplete configuration is unavailable. MCP discovery lists run_browser_task only when the connection and tool permission are enabled with valid configuration; clients must refresh the tool list after settings changes.
  • With both switches enabled, run_browser_task delegates a bounded subtask through a shared native executor available to Dao Agent and external MCP. Agent calls retain the existing turn and sequential scheduler; MCP calls retain connection approval and the exact authorized tab lease, and work with the Agent panel closed. Both enforce browser permissions. Jev uses the choice protocol, selects fill targets and known inputs separately to keep every choice below the service's 255-option limit, accepts only offered actions and known non-sensitive inputs, and verifies all completion predicates locally. Compact viewport snapshots and guarded refs support click, fill, scroll and wait (at most 20 steps / 60 seconds). Native input buttons and ARIA buttons retain their visible names in both observations and action guards. Main-document navigation waits within the task deadline, discards obsolete decisions, and rechecks completion on the new page before choosing another action. This initial snapshot excludes sensitive form controls (links and buttons that merely mention passwords stay clickable), all editable contenteditable forms (empty, true, and plaintext-only, case-insensitively), their nested controls, iframe and shadow-root contents; unsupported tasks return to the caller, and a non-HTTP(S) target stops with unsupported_target.
  • Permission/configuration changes, stopping, cancelling an MCP call, revoking its connection or losing its target cancel pending plugin requests and prevent late responses from acting. Agent-owned tasks also stop when their WebUI unloads. Unloading also invalidates native tool callbacks before cancellation so pending ordinary tools cannot respond into a disabled WebUI; a reloaded Agent can start a new turn. Native checks reject old configuration revisions; credentialed redirects are disabled. Errors retain partial action evidence and timing/count metrics, with bounded stale-ref recovery and no-progress detection. MCP failures retain this structured outcome with isError: true. Ordinary browser tools do not invoke Jev automatically. Actual service compatibility and performance require a configured endpoint and representative end-to-end trials; no speedup is assumed.
  • DaoAgentSettingsHandler stores durable Agent choices in Profile prefs and is shared by the Agent and Settings WebUIs
  • Agent remains a compact top-level Dao-exclusive Settings entry beside You and Dao. You and Dao owns browser capabilities only; the complete Agent configuration, Memory, Workspace, Usage, Skills, and Dream controls appear exactly once on the Agent secondary page
  • The Agent module is packaged in Chromium's shared Settings lazy bundle and reached from the compact overview entry. The detail page uses five vertical Settings sections: Model and connection, Behavior and context, Capabilities, Learning and analysis, and Data and management. It adds no section rail or tabs
  • Model/provider credentials, session/display behavior, persona, page and conversation context, web search, memory/proactive suggestions, and Dream analysis are managed in the Agent Settings section
  • The provider selector groups API formats (OpenAI-compatible, Anthropic-compatible) apart from named service providers. Only API formats show the Base URL field; its placeholder shows whether to include /v1 (OpenAI-style URLs do, Anthropic's does not, and a trailing /v1 on an Anthropic-compatible URL is dropped). Named providers always use pi-ai's catalog endpoint, and model ids outside the catalog (new releases, gateway aliases) reuse the provider's native API via pi_model.ts
  • Test connection sends a one-line prompt with the current form values through the preloaded chrome://agent page (llm_connection_test.ts), so it exercises the same pi-ai path as chat. DaoAgentSettingsHandler relays the request between the two pages; the card shows the latency on success, or the provider's raw error, a timeout, or that the agent panel is not ready yet
  • The persona card can restore the runtime default, while the Dream card can generate a report immediately when Memory and Dream analysis are enabled and keeps the existing Dream report history link available
  • Tool group shortcuts and the expandable individual-permission list preserve the existing per-tool enable/disable controls. Rapid changes update one optimistic disabled-tool set and serialize complete-array writes before resynchronizing from the Profile snapshot
  • Existing origin-scoped Agent settings migrate once, filling only values that have not already been configured in Settings; runtime/session state remains local to the Agent. Partial legacy usage records receive canonical defaults, while malformed values are rejected and initialized Profile data wins
  • Session resume retains its established three-hour default and accepts zero hours. Configuration has independent loading, error, and retry feedback, so a configuration failure does not hide or disable management summaries
  • The Agent section owns complete Memory, Workspace, and Usage management. These modules render as independent compact cards inside Data and management so their headings and actions remain visually separated. Memory and workspace data come from their Profile-keyed services; usage counters are stored in the Profile dao.agent_usage_stats pref, which is the source of truth shared with already-open Agent WebUIs
  • DaoAgentSettingsHandler exposes only the management facade needed by the Agent section: memory summary/clear, workspace summary/reveal, and usage read/reset/record. It does not register workspace mutation messages
  • dao://memory, dao://skills, and dao://dream remain secondary management pages linked from the Agent section rather than duplicate top-level settings

Settings shell (dao://settings)

  • Chromium's Google AI settings are hidden from the menu, overview, search, and /ai routes, including after Gemini availability changes. Dao Agent settings, model providers, and skill management remain independent and available.
  • All visible top-level Chromium and Dao settings render as one continuous overview in the Dao Open Design shell. Its 184px table of contents, integrated search, 680px content column, 30px section rhythm, and light/dark tokens share one page background without a repeated Dao brand header or footer. Nested page index views are kept in normal document flow so their cards contribute real height instead of overlapping later sections. Search filters the table of contents to matching sections, clears hidden selection on zero results, and restores the captured pre-search scroll position without top-level routing
  • Table-of-contents activation scrolls to a section and updates the URL hash; scrolling updates the selected item. Direct legacy top-level paths continue to resolve and normalize to overview hashes
  • Complex management flows remain independent secondary pages. Returning from one restores the overview and its section/scroll context. Entering a secondary page from the overview starts at the top, including repeated visits to Agent configuration, without inheriting the overview's scroll offset
  • Chromium settings components continue to own their routes, preferences, visibility gates, search integration, and external destinations; the shell changes presentation without replacing the settings inventory
  • Upstream About, People, On Startup, and Reset dialog templates use .html.ts Lit patches. Overview styling follows the migrated settings_shared_lit.css, settings_page/settings_section.css, and A11y/Appearance/People *_page_index.css patches; Dao-owned page templates and the remaining Polymer shell keep their existing paths

LLM / runtime plumbing

  • llm_config.ts — Model + provider configuration
  • pi_app_storage.ts — Persistent storage abstraction
  • pi_llm_stream.ts — Streaming LLM client
  • pi_model.ts — Resolves provider/model/base URL into a pi-ai model
  • llm_connection_test.ts — Runs the Settings "Test connection" request
  • pi_tool_adapter.ts — Tool adapter
  • chromium_types.d.ts — Type bindings for chromium WebUI APIs
  • readability_bundle.ts / turndown_bundle.ts — Reader-mode + HTML→Markdown bundles

LLM tool set (see agent-console-api.md for the full schema)

  • Page access: get_page_content / get_page_info / get_readable_content
  • Page interaction: click_element, fill, scroll, etc.
  • Accessibility tree generation and interaction
  • Resource inspection (reverse-engineering helpers)
  • Web access: web_search uses provider built-in search when available, optional Jina Search with a user-supplied API key as the local fallback, and DuckDuckGo HTML as a best-effort final tier with explicit anomaly verification-page reporting; fetch_url uses Jina Reader before browser fetch.

2.5 Vendor Pipeline (Generated, never hand-edit)

  • npm run vendor — Compiles pi-mono / pi-web-ui and related deps from vendor.config.ts + vendor/entries/*
  • Artifacts: agent/vendor/pi_runtime_bundle.ts and agent/vendor/pi_web_ui.css
  • manifest.json sha256 drift check guards against direct edits

2.6 Dream Analysis (nightly behavior learning)

  • Shared foreground activity service — an eager service runs once for each regular Profile, independently of Dream and Agent Memory; it is not created for off-the-record Profiles. At most one page is timed: the selected HTTP(S) tab in the active, visible, non-minimized browser window, or the selected pane when that tab is in Split View. Tab, navigation, window, suspend/resume, and timezone events settle elapsed time with a monotonic clock. A 60-second checkpoint bounds loss before an abrupt exit, normal shutdown writes a final checkpoint, suspended time is excluded, and a timezone change starts new local-calendar attribution without rewriting prior aggregates. Local midnight and 06:00, 12:00, 18:00, and 22:00 are exact boundaries, including 23- and 25-hour DST days.
  • Privacy-minimized activity store — each regular Profile keeps its own DaoForegroundActivity.db, containing only aggregate elapsed milliseconds by local date, time bucket, and canonical host. It stores no full URL, path, query, fragment, page title, page content, or interaction log; snapshots checkpoint before reading, and retention is the current local date plus the preceding 370 dates.
  • DaoDreamService (+ Factory) — profile-keyed scheduler: nightly (22:00–06:00 local, system idle ≥1h), daytime catch-up for yesterday, and manual trigger from Agent settings. Off by default (dao.dream_enabled), double-gated behind agent memory.
  • DreamMaterialCollector — aggregates one day of signals: history (domain+title+time-bucket granularity, top 50; full URLs never leave the browser), search keywords (extracted in C++), agent conversation excerpts, proactive-feedback stats. Visit-count buckets remain available to the model, while measured foreground seconds are also aggregated by morning, afternoon, evening, and night for the report rhythm visualization. History continues to provide visits, titles, searches, coarse visit buckets, and visit duration. For each exact 06:00-to-06:00 Dream window, foreground time is selected per local date without overlap: dates before native tracking use legacy History; the tracking-start date and current date are native partial; completed retained dates are native full, including measured zero when no row exists; and pruned or failed native queries are unavailable rather than falling back. Daily and weekly reports never add History foreground time to native foreground time for the same date, though a weekly report may mix sources across different dates. Ongoing windows retain partial coverage up to the query time, including when their end falls on a future local date.
  • dao_dream_runner.ts — resident agent WebUI executes the LLM summarization (user's configured provider) and returns structured one-minute recap data (summary, time-of-day rhythm, and up to three themes), habits, and a full morning-report markdown. The recap is persisted inside the report's existing material-stats JSON, so older databases need no migration.
  • Results: memory suggestions remain report-local candidates until the user confirms one at confidence 0.95; rejection never deletes or rewrites an existing preference. The report is archived in the dream_reports table, with a morning report card in the Agent panel, per-candidate confirm/reject, and an optional debug view of the exact LLM input (dao.dream_debug).
  • Agent morning report card — yesterday's unviewed report shows its one-sentence recap directly above the chat, with a localized read-report button below and a close button halfway outside the top-right corner. Legacy reports reuse the report page's markdown-summary fallback. Reading opens the standalone report and immediately dismisses the card locally; closing also persists the dismissal without marking the report viewed or removing it from history.
  • dao://dream one-minute recap — responsive two-column report with a 53-week real-report activity heatmap, compact daily-and-weekly history rail, localized date-and-active-duration tooltips for report-bearing heatmap cells on pointer hover and keyboard focus, summary card, measured foreground-focus rhythm, topic cards, aggregate counts, memory-candidate actions, and a folded full report. Existing rerun, image sharing, source-domain exclusion, and debug controls remain available. Legacy markdown-only reports derive a summary and topic cards locally instead of rendering an incomplete page. Newly generated reports persist foreground_source, foreground_coverage, and coverage_seconds; the UI labels partial coverage and does not present unavailable coverage as measured zero, while older reports without these keys retain their legacy rendering unchanged.

2.7 Dao Home Personal Web Runtime (dao://home)

  • URL-only personal website — dao://home/ and its internal paths load one Profile-owned project. The browser adds no new-tab, startup, sidebar, or Settings launch entry. A regular Profile is required; Incognito/Guest are disabled.
  • External Home editing (cli/dao_home_*, home/dao_home_external_service.*, local_ipc/) — The installed dao-home skill uses dao-browser home to pull, diff, preview, publish, inspect sources and diagnostics, capture the preview, list versions, and roll back. A native approval binds a fixed one-hour editing session to one regular Profile. Home uses its own authenticated local endpoint and works with MCP disabled; it does not start the built-in Agent or make a browser-side model call. Local files live only in fresh, owner-private system temporary workspaces, with an explicit workspace path required for later commands. Binary assets keep their bytes; complete snapshots include additions and removals and retain the existing 500-file/20-MiB limits. Unsafe paths, links, unexpected development artifacts, local changes after preview, and stale published bases fail without replacing the user's edited files. Cleanup refuses unpublished changes unless explicitly discarded. Cleanup is local unless --close-session explicitly ends the shared session, so retiring an old checkout does not stop a replacement checkout. Failed project cleanup preserves recovery metadata and the exclusive workspace lock until the command exits, allowing a retry. Resume reuses a live session and its preview, resolves pending publication when possible, requests new consent only after expiry or browser restart, and refuses a session explicitly stopped by the user. Settings > Local agent collaboration > Skills and command includes Home installation steps and Codex/Claude Code examples in How to use.
  • Dedicated real-Profile preview — External preview opens a separate visible Dao window in the approved Profile and runs the actual Home app and native source collectors using that Profile's signed-in state. Source approval remains separate from editing consent, and cookie values never leave the browser. Ordinary Home tabs keep the published project and their own runtime state. Focusing another application, switching tabs in an ordinary window, or closing the original consent window does not cancel the dedicated preview. Native owner visibility distinguishes an occluded window from a hidden one; same-document hash/history changes preserve the preview receipt. In-flight source collection also survives occlusion; failed source navigation releases its detached page after Chromium finishes notifying navigation observers. Closing, hiding, navigating, or switching away from the preview's own document invalidates its receipt. Successful previews remain visible until publication, replacement, or cancellation; late runtime errors revoke publication readiness. Trusted Home UI identifies the external editing session and exposes Stop. The ordinary Home controls and empty state also expose the editor and Stop before its first preview, without changing the published page's runtime. Session expiry or Stop cancels its work and closes only an intact owned preview window, leaving ordinary windows and pages the user added alone.
  • Exact external publication and recovery — Publication requires the same immutable, successfully previewed draft, byte digest, base revision, and live document authorization. Source grants and the version commit together, while the final summary can change independently of project bytes (up to 500 UTF-8 bytes). Unchanged, still-authorized sources may report failure as a warning when the page handles it; new or changed source code, schemas, permissions, limits, and renewed grants must pass source tests. Render and source outcomes remain separate. Publication and rollback record their operation ID and exact request with the version, allowing a lost response to be resolved after renewed consent without duplicating a version. A changed request cannot reuse that ID, and exported/imported projects never carry these browser-local operation records. A successful publication advances only the temporary base copy, preserving edits made while it ran; rollback creates a new version without restoring revoked source grants. An unresolved operation stays pending even when no provenance is found; agents can pull a fresh temporary checkout and compare/reapply local edits without retrying the unknown operation. Unreferenced temporary snapshots are pruned. Screenshot failures report a separate result without losing a valid preview.
  • Existing Agent integration — The two empty-state actions open the existing right-side Agent. Home-specific atomic tools are injected only for a turn pinned to the exact active Home tab and published revision, and native code revalidates the pinned document and its one-way Home authorization before and after asynchronous work. That document authorization is the authoritative lifecycle signal: focusing the Agent sidebar or a different browser window does not retarget the turn, and macOS occlusion does not invalidate a still-selected Home document. Selecting another tab in the initiating window, truly hiding the Home document, or navigating it still invalidates the authorization. Each active Home turn also receives a bounded construction contract covering the required manifest, directly runnable browser files, V4A patch grammar, strict CSP and opaque-origin runtime constraints, and the atomic apply-preview-publish sequence. It directs generated interaction code into project script files, memory-only state through dao.session, and external navigation through the trusted confirmation API instead of inline script, Web Storage, or raw network APIs. Native tool failures include their stable error code in the model-visible message so the Agent can correct a rejected patch instead of guessing another project format. Re-entrant manual or command-bar submits are ignored while a send is establishing or running its native turn, so a duplicate UI event cannot replace the turn and invalidate its Home lease. Publication, trusted import, and rollback calls carry a one-way document/turn lease into the blocking project store; tab, navigation, visibility, or turn loss invalidates the lease, and a stale turn cannot acquire a replacement after the Home returns to the foreground. Publication rechecks the lease while holding the final commit guard. A cancelled rollback also discards its browser-owned temporary draft before returning. The Agent tool settings expose the complete Home group, including asset import, so the group or individual Home tools can be disabled with the shared tool policy. home_preview loads the exact immutable draft in a temporary untrusted sandbox; both regular and permission-expanding Agent publication paths require that draft's in-memory success receipt. Existing-project edits must list and read every target file first. Focused changes use exact V4A hunks, while whole-file rewrites use the atomic home_replace_files tool, which puts all related full-file replacements in one atomic draft instead of deleting and re-adding paths. Both routes create an unpublished validated draft and retain the same preview and publication gates. The Agent composer's DOM-context and element-screenshot pickers also work on the active Home document. A narrowly scoped legacy UI session may capture that exact dao://home target. While picking, the trusted host temporarily covers the generated-app iframe so pointer events never reach project code, then asks the fixed runtime to hit-test the pointer coordinates without dispatching a click. The cover is removed immediately after selection or cancellation and is never installed during ordinary Home use. Selection prefers a stable data-dao-node-id and records it for home_get_selected_element; existing projects without node IDs receive a bounded unique CSS locator instead. Selection suppresses the element's normal action and translates its bounds back into top-level screenshot coordinates. Other internal pages remain ineligible for browser automation.
  • Built-in design direction — Every Home creation and editing turn receives a compact browser-owned design-director contract, so users do not install or select a design skill. The Agent chooses one coherent visual point of view, uses explicit hierarchy, spacing, type, color, radius, and responsive rules, rejects common generic AI-page defaults, and silently reviews the draft for hierarchy, craft, function, originality, responsiveness, and runtime safety before preview. The approach is adapted from the MIT-licensed OpenDesign director protocol and is bundled locally; generation does not depend on a live third-party design service.
  • Local project ownership — DaoHomeProjectService stores validated text files, immutable published revisions, drafts, summaries, grants, rollback, and grant-free JSON export/import under the Profile. A secondary trusted menu exposes summary-first version history, a read-only source tree, and an explicit older-version-to-current source diff. Export includes runtime dependency guidance but excludes approvals, credentials, Agent data, and collected source content. A destructive trusted-menu reset requires explicit confirmation, then atomically returns Home to its initial empty state and deletes every project revision, temporary draft, connector grant, and local diagnostic; a failed or stale reset leaves the published project unchanged. Export/import round-trips the bounded immutable revision history and its source files. After explicit confirmation, the imported draft must pass the same isolated preview as an Agent draft before it can create a new local head, and the imported project always remains disconnected. Import rejects a package whose declared current files differ from its exported head, whose exported revision is not the final head, or whose parent/restore graph is disconnected. It discards all temporary draft/history files on any failed, cancelled, or abandoned operation.
  • Privacy-minimized history bootstrap — Only an explicit user action reads the last 30 days of local history. A native reducer converts eligible HTTP(S) visits into at most 12 ranked origin-root launch targets and at most three feed-capable source candidates discovered from distinct routes in a repeated route family. Candidate slots are reserved independently from the twelve most-frequent launch origins, so high-frequency utility sites cannot crowd every content source out of the brief. Origin identity includes scheme and port, and route-family working state is strictly bounded. No domain catalog or site-specific collection recipe participates in discovery. Generic semantic route signals keep account, authentication, mail, payment, settings, search, and discovery surfaces out of automatic feed collection. The Agent receives only stable action IDs, label/category hints, canonical root URLs, source eligibility, and locale—no browsing titles, visit counts, time buckets, paths, or full visited URLs. Feed candidates include a browser-owned bounded result schema and generic collection, intent, and content-kind starting hints. The Agent dynamically proposes the exact same-site feed URL and its site_feed, following, subscription, or activity semantics while authoring the collector. The trusted browser rejects missing, duplicate, unsupported, credential-bearing, or cross-site proposals and binds the accepted URL and semantics to the visible permission and test transaction. This lets the generated collector adapt to the site's actual feed conventions, including a meaningful same-site subdomain, without turning site identities, collection paths, or DOM selectors into browser code. The Agent dynamically authors each collector from the candidate website and the fixed page RPC instead of selecting a browser-hardcoded site recipe. Personalized feed intents must stay inside semantic feed-card or activity containers; the trusted manifest validator requires every collection query to use an inline quoted selector for structured repeated-card roots, so its scope can be audited without evaluating generated code. It rejects both generic and content-path-constrained whole-page link fallbacks, so a successful collector cannot silently degrade into recommendations or site navigation. Personalized collectors query card roots and extract structured fields through ordered descendant-selector fallbacks, making them less dependent on a single internal title-link class. When card classes have drifted, a collector may try a bounded union of alternate semantic card roots but must return an empty result rather than leave the personalized container. The brief is never persisted by Home. The exact Home tab must still be active when the asynchronous history query completes, and leaving that Home document clears any unconsumed material. A random one-shot token binds the material to the exact external history prompt and Agent turn for that document; a normal or replacement prompt, another window, or another turn cannot consume it. Replacing or failing to dispatch the prompt and timing out or failing Agent chat initialization, and aborting or ending the claimed turn clear the material. Losing the Home owner while Agent bootstrap still awaits the project snapshot also releases the browser-control lease, and the native begin operation is explicitly cancelled if its WebUI callback times out, so MCP and later Agent turns are not left busy.
  • Feed-first history Home — The history turn builds a comprehensive information portal, never a launchpad or browsing report. Quick navigation remains compact and preserves every launch target, while successful sources produce a prominent continuous feed and source/category controls. The Agent chooses a top-aligned, inline, single-column, split, or lateral composition from the actual content and viewport instead of inheriting a mandatory sidebar or fixed column width. Source-free fallbacks keep the required feed state compact rather than turning most of the page into an empty panel. It asks the trusted Home UI for one grouped decision covering up to three proposed live sources, tests selected sources sequentially, and publishes one final revision. Rejected, authentication-required, runtime- failed, and schema-failed sources degrade to launch-only actions; an empty selection or all-failed run still publishes a useful launchpad. If no source candidate exists, the browser binds every supplied candidate up to the three-source limit to its AI-authored conventional collector module in the provisional draft, replaces model-authored connector declarations with canonical read-only permissions, and writes the bounded result schema before permission is shown. The detached executor uses the regular Profile so these collectors reuse an existing signed-in session without receiving credentials. A missing, empty, or structurally unsafe authored collector is omitted on a per-source basis before the grouped permission request; valid collectors in the same batch still proceed to permission and testing instead of one broken candidate invalidating the whole bootstrap. A brief with no candidates transitions directly to disconnected final construction without presenting an empty permission dialog. Provisional drafts are never previewed or published. The grouped decision is exempt from the ordinary Agent bridge timeout, completed decisions are idempotent, and a timed-out pending decision can be atomically resolved to an empty selection on the same provisional draft instead of stranding the transaction in an already_exists state. Successful tests expose only bounded native-generated sample_shape type and empty/non-empty metadata to the Agent; raw values, dynamic keys, media handles, and error payloads remain ephemeral and cannot enter drafts, revisions, or exports. Browser-owned preview validation requires every canonical action and successful source slot exactly once, rejects report persistence and direct HTTP(S) anchors/forms/submit overrides, and permits publication only from the exact live turn, base revision, and tested connector fingerprints. Before final preview, the browser overwrites experience.json with canonical metadata derived from the four highest-ranked launch actions and the final successfully tested connector IDs. Additional valid launch actions remain allowed and every launch target from the brief must be present, while the highest-ranked controls remain visible and focusable. The launch index cannot be the entire page: preview requires a visible, non-empty data-dao-feed region with explicit loading, populated, empty, and unavailable states. Successful sources populate that region with fresh cards; a source-free fallback remains honest about having no collected items. Each successful source is represented exactly once by matching data-dao-source-slot and data-dao-connector semantics, including when its current collection is empty; failed and deselected sources cannot claim a slot. The generation contract states these required attributes explicitly so preview validation does not depend on an undocumented convention. Final UI drafts remain connector-free: immediately before preview, the trusted browser copies only successfully tested modules and schemas from the provisional draft and binds their exact canonical declarations and limits. This preserves approved fingerprints without asking the model to reconstruct security-sensitive manifest fields. This removes model-authored experience metadata as a failure point and prevents ordinary single-source permission requests from bypassing the grouped bootstrap flow.
  • Untrusted generated application — User HTML/CSS/JavaScript runs at chrome-untrusted://dao-home-app without WebUI bindings or arbitrary network access. The fixed runtime exposes only session state, source collection, bounded HTTP(S) navigation, media-resolution requests, and stable node selection. The fixed runtime automatically connects canonical data-dao-action / data-dao-action-url controls to trusted navigation, so a validated launch action opens directly without an extra confirmation. Collected cards marked with data-dao-feed-link, data-dao-feed-url, and data-dao-feed-source use the same direct user-click path. Arbitrary dao.navigation.open calls still require browser-owned confirmation. A synchronous trusted prelude owns canonical action clicks before project scripts run, so generated capture handlers cannot replace or suppress the confirmation path. The host inserts that prelude after a real leading doctype and before all project markup, without mistaking HTML comments for document structure. The generated canvas fills the browser-owned content card without adding another inset or border, and the prelude clears only the browser's default html and body margins before project styles run so generated layouts start edge-to-edge but can still add intentional spacing. Unpublished preview resources are available only while the trusted Home host owns an active Agent preview request or a retained external preview in its dedicated window. Generated code cannot submit its own preview verdict: the trusted parent reports only the iframe load, while the browser process binds the exact preview frame and rejects console errors, failed loads, or cross-document replacement before issuing the draft receipt. A trusted Home dialog displays and confirms non-action generated-app navigation before it occurs.
  • Generated connector isolation — Connector modules run in a second no-bindings chrome-untrusted://dao-home-connector sandbox and receive only a fixed, audited page RPC. Native code owns a detached, never-focused regular Profile WebContents, origin/path/capability checks, sensitive-control rejection, login-state detection, JSON-schema/result limits, timeout, and active-Home cancellation. Page-visible media becomes an opaque session handle; generated code can resolve only a bounded local blob and never sees the original media URL. Finishing a collection snapshots referenced media into a bounded immutable in-memory payload and immediately destroys the detached source page, so cached handles cannot drift after page navigation or DOM changes. Unique media URLs are encoded sequentially; a canvas is rejected before allocation when its raw pixels exceed the remaining 5 MiB session budget, and repeated handles share one retained blob. Completed executors retain only those snapshots for a bounded session window. The trusted host keeps at most the same 16 successful collection results, evicts them in executor-completion order, and reruns an evicted request so returned media handles always have a retained native owner.
  • Trusted source permission — Agent code can create an opaque permission request but cannot grant access. Home shows normalized website, path, read-only capability, lifecycle scope, and collection budgets. For budget expansion, the trusted dialog shows each increased dimension as the exact previous and requested values. Confirmation grants only the exact draft connector and budget fingerprint; the Agent must successfully test every expanded connector before Home atomically publishes the previewed draft and its grants. Budget increases require renewed approval, while decreases migrate an existing exact grant without widening access. Rollback never restores a revoked grant, and import clears all grants.
  • No automatic maintenance — Opening Home renders published code without an LLM call. Source collection is visible-card initiated, duplicate requests are coalesced for the active session, and successful results (including an empty result) are reused for ten minutes before the next foreground collection can refresh them. Generated feed apps keep the same per-connector ten-minute memory cache and never create a refresh timer or background crawl. The connector sandbox is also present on an empty active Home so the first approved connector draft can be tested before its initial publication. Source payloads and generated-app session state remain memory-only and are cleared when Home loses active ownership; both untrusted frames and native executors are torn down and recreated only after Home becomes active again. Agent draft sampling uses a separate executor: ending or replacing the Agent turn cancels its draft work without interrupting an in-flight published Home card, while Home navigation, hiding, closure, or revision replacement cancels both classes. Connector and generated-runtime failures record bounded non-content diagnostics; only the explicit Ask Dao to fix action starts a repair turn. A Home-scoped Agent sample request is routed through the same trusted host, detached executor, schema validation, and lifecycle cancellation as a visible source card.

3. Picture-in-Picture Enhancements

Built on Chromium's native PiP, adds a Document-PiP interception layer plus several visual + behavior tweaks.

3.1 Dao-owned (src/dao/browser/pip/)

  • DaoPipInterceptor — Intercepts PiP requests on configured sites and redirects to Document PiP with a specific DOM element; selecting the opener tab closes the active Document PiP and restores the moved element for both manual and automatic entry, while capture-driven visibility changes leave the PiP open
  • DaoPipSiteRules — Site rules loaded from pip_site_rules.json

3.2 Auto-PiP triggers

  • DaoAutoPipVisibilityHelper (browser/dao_auto_pip_visibility_helper.{h,cc}) — Watches window-visibility changes (minimize, hide) and triggers auto-PiP for the active tab's playing video; complements Chromium's AutoPictureInPictureTabHelper (which handles tab switching). Both paths obey Chromium's native automatic Picture-in-Picture content setting, exposed as a switch on You and Dao
  • Patches: auto_picture_in_picture_tab_helper.cc.patch, picture_in_picture_window_manager.cc.patch

3.3 PiP window chrome

  • Patches: views/frame/picture_in_picture_browser_frame_view.{h,cc}.patch and views/picture_in_picture/pip_top_bar_animation_controller.{h,cc}.patch — The frame starts the controller inactive and fades the entire overlay through its opacity delegate. Initial hiding, first-activation suppression, hover fading, drag movement, and corner resizing remain in the frame
  • Document PiP top-bar positioning — The floating title bar follows main-window bounds changes as well as layout updates, so Windows moves without resizing keep the title bar attached to the video, including title-bar drags.
  • Document PiP top-bar display recovery — Showing the main window or revealing the controls resynchronizes the floating title bar, flushes its pending layout, and requests a fresh frame without resizing the video. Hidden main windows keep the title-bar window hidden; repeated hover requests retry a hidden overlay.
  • PiP event-monitor lifetime — The frame and floating top bar use separate forwarding observers (browser/pip/dao_pip_window_event_monitor.h) so Windows detaches each listener from the correct native window during PiP or opener teardown, including when returning to the video tab closes PiP.
  • Patches: back_to_tab_button.cc.patch, minimize_button.cc.patch, video_overlay_window_views.cc.patch — Overlay button restyling
  • Patches: video_picture_in_picture_window_controller_impl.cc.patch — Capturer guard preventing tab throttling
  • User-interaction event forwarding via chrome_render_widget_host_view_mac_delegate.mm.patch
  • Full-work-area manual resize — Document PiP and video PiP windows can be enlarged to the display's complete usable work area; initial sizing and site-request limits remain unchanged

4. Split View

  • DaoSplitView (split/dao_split_view.{h,cc}) — Split container whose rounded backing matches the dividers through inner pane corner cutouts, preserves the outer frame shadow, and remains transparent in single-pane mode
  • Content host ownership — DaoSplitView is a child of MultiContentsView. Active split panes own their WebContents while Chromium hosts remain nonempty 3×1 placeholders for status-bubble anchoring. Split fills the combined content card, replacing the global address bar with pane address bars; leaving split restores the primary content host and single-pane viewport. Inactive split does not intercept mouse input except during a sidebar tab drag
  • DaoSplitNode / DaoSplitPaneView — Split tree nodes and panes
  • DaoSplitDividerView — Draggable divider with an opaque fill matching the shadowed content-frame edge in light/dark and incognito windows, including appearance changes; blue hover/drag feedback stays visible, and the content backing uses the Dao-themed surface
  • Native tab-drag cleanup — Successful and cancelled macOS tab drags reset drag-only Split View hit testing in every browser window, so WebContents mouse interaction cannot remain blocked when WebUI dragend is skipped
  • Status: wired up but not enabled by default

5. Control Center

macOS-style floating control center panel bundling extensions and utilities.

  • Per-tab High Performance Mode — The Control Center main panel has a lightning tile for the current tab that lights up while enabled. A localized lightning indicator appears immediately to the left of the address bar's MCP control indicator while enabled. Clicking it opens a native popup matching the MCP control popup, with an explanation of background protection, a resource-usage note, and a button to turn the mode off. The popup closes when switching tabs, closing the tab, or disabling the mode; dismissing the popup alone leaves the mode enabled. The mode follows the tab through reloads, navigation, and window moves, and ends when the tab closes; it is not restored across browser restarts. Chromium treats the current page as visible for scheduling and painting, rejects browser discard and freeze requests, maintains foreground renderer priority, and exempts its frame sinks and descendants from Energy Saver and other frame throttling. Turning it off restores normal policies without changing other tabs' settings. Fenced frames and MPArch guest pages inherit renderer priority; inner and guest WebContents inherit the owning tab's mode through attachment, navigation, and detachment. Shared frame sinks remain protected while any ancestor is exempt. Capture alone retains Chromium's undrawn-frame protection. Native indicators subscribe directly to mode changes without delayed tab UI invalidation. Shared renderer processes may also benefit from the priority boost. Normal garbage collection, OS memory management, system sleep, hardware limits, crashes, and websites' own focus-based behavior remain unchanged.
  • DaoControlCenterButton — 24px trigger button with a 6px-radius hover highlight that follows the address bar's page background, matching neighboring action buttons even when the page and system themes differ
  • DaoControlCenterPopup — Floating popup with transparent overlay click-to-close. Keyboard input in the page keeps the popup open, except Escape, which closes it. The main panel is a 16px-radius frosted card with a hairline border holding rounded tiles in a macOS Control Center layout; the QR and More sub-panels replace the tiles inside the same card
  • DaoControlCenterExtensionsSection — Extensions tile: a localized Extensions header keeps Add and Manage visible at its trailing edge, and extension icons wrap onto extra rows of eight instead of pushing items out of view. Mini Dao's site center reuses the same titled, wrapping extension tile
  • DaoControlCenterUtilitySection — Utility tiles: wide Dark Mode and High Performance Mode tiles show a localized On / Off status line, fill their icon badges with the Dao accent while active, and expose toggle state to accessibility. High Performance Mode replaces the Security tile and stays in sync with the active tab. Compact QR Code, Mini Dao, and More tiles sit below
  • DaoControlCenterQrView — Generates the current page's QR code with its favicon. Click the QR image to copy it without closing the panel. A small copy icon appears over the image only on hover or keyboard focus, then changes to a checkmark with localized confirmation after copying. The clipboard image excludes this overlay. Only the URL remains below the image; there is no separate copy-button row. Failed generation clears the image and disables copying.
  • DaoControlCenterMoreMenu — Full Page Screenshot, Share on macOS, and site data cleanup actions. High Performance Mode is available only on the main panel. A divider separates cache and cookie cleanup from the other actions; cleanup stays scoped to the active page's current site with completion toast feedback.
  • Full-page screenshots — More saves the current loaded document as a PNG, including content beyond the viewport, through Chromium's download manager. Capture uses the shared DaoDevToolsClient and Chromium's full-document capture without scroll stitching, preserving the page's viewport and scroll position afterward. The panel closes before capture, duplicate requests are disabled while pending, and navigation or tab closure cancels the capture. Localized Dao toasts report capture progress and failure, including blocked screenshots; the DisableScreenshots policy remains effective. Capture has a 30-second timeout and a 128 MiB protocol-response limit, in addition to Chromium's image-size limits. Unloaded infinite-scroll content and content hidden inside independently scrolling elements are not expanded.
  • DaoPinnedExtensionsContainer — Pinned extension icon container
  • Extension action badges — Pinned and Control Center extension icons render the active tab's badge text and extension-defined badge colors using Chromium's native badge compositor, with independently compacted text and a 10px-tall background sized for Dao's smaller icon surfaces
  • DaoNativeShareMac (dao_native_share_mac.{h,mm}) — Native macOS share sheet
  • DaoNativeUtilMac (dao_native_util_mac.{h,mm}) — Misc native helpers (incl. cross-window-drag drop side)

6. Welcome Page

  • DaoWelcomeUI (webui/dao_welcome_ui.{h,cc}) — dao://welcome WebUI controller
  • WebUI: welcome.{html,css,ts} + dao_welcome_app.ts + welcome_bridge.ts (Lit)
  • Menu item + command handling — User can reopen anytime
  • First-run preference tracking — Auto-opens only on first launch (managed via dao_pref_names)
  • Localized tutorial — The document title, welcome heading and subtitle, all seven shortcut descriptions, demonstration labels and copy feedback, and GitHub link use Dao's GRIT/WebUI strings. Simplified Chinese is provided; untranslated locales fall back to English.
  • Browser migration entry — A compact localized link in the page's top trailing corner opens dao://import/ in the current tab, where users choose a source browser and data categories before starting migration. It sits outside the centered tutorial layout and supports visible keyboard focus.

6.1 Browser Data Migration

  • Standalone migration surface — dao://import is a dedicated Lit WebUI, with a localized Import browser data document title for its browser tab, exposed as an explicit Import browser data row on the You and Dao Settings page and from the existing system Import Bookmarks and Settings… command instead of Chromium's modal importer. Its source grid uses the native browser catalog: Chrome, Arc, Edge, and Firefox on Windows, plus Safari on macOS. Detected profiles remain individually selectable, while supported browser kinds without a detected profile appear as disabled cards. The flow lets the user choose supported data categories, reconnects to an active profile-scoped job after reload, and reports per-category progress and retryable partial failures. Stopped jobs retain completed-batch counts and are presented as cancelled, not completed. Partial completion identifies the categories that need retrying in a dedicated summary and visually marks their result cards without hiding any items that were imported before the failure. The active migration rail uses the detected source browser's product logo and Dao's packaged product logo instead of generic letter placeholders.
  • Asynchronous candidate counts — Selecting a Chromium-family profile starts independent background counts for each supported category without blocking navigation or migration. Bookmark, history, password, and extension counts read source metadata directly; password counting never decrypts a credential or triggers Keychain authorization. Tab sessions are counted only from a temporary snapshot because Chromium's session reader can rotate files. These preflight values describe scanned candidates and may differ from final imported totals if the source changes or Dao skips conflicts. Legacy Safari and Firefox importers report the count as unavailable until migration.
  • Supported sources — Chrome, Arc, and Edge profiles use Dao's snapshot adapters. A shared native catalog supplies localized names, platform roots, and adapter selection. Windows roots use Local AppData, including Arc's packaged LocalCache profile; macOS roots use Application Support. Default root discovery and profile scanning run off the UI thread. Safari and Firefox use Chromium's platform importers and their reported category capabilities.
  • Safe source reads — Chromium-family stores are copied to a temporary profile snapshot with bounded metadata-stability retries. SQLite sidecars and session directories are included. The background reader owns its snapshot until reading finishes, independently of callback argument evaluation order. Session file reads use a single-thread worker and read the latest saved session without rotating it away; session objects are restored on the UI thread to preserve Chromium's global session-ID ownership. Tab import keeps standard tab/window, navigation, pin, and closure commands while ignoring unrelated metadata, including Edge-specific commands that would otherwise stop Chromium's restore parser and incorrectly report zero tabs. Windows session files locked by a running source browser require fully quitting that browser; the completion page explains this and offers a retry. Temporary snapshots are deleted with the category operation. Cleanup stays off the UI thread and blocks browser shutdown until copied history, password, and session data has been removed.
  • Merge-only destination writes — Bookmarks are placed under a localized imported root, destination password conflicts are preserved, already-open tab URLs and installed extensions are skipped, and history writes use the profile History service. History and password counts advance only after the destination services confirm the persisted records. No category replaces existing Dao data.
  • Accurate failure summary — If every selected category fails without importing data, the completion page reports failure instead of partial success. Failed or cancelled jobs use an attention indicator.
  • Passwords and extensions — Chromium-family password import is offered only on macOS, where its source capability enables the Keychain authorization notice. Windows does not offer it until a source password decryptor exists; Firefox retains the capabilities of Chromium's platform importer without a Keychain notice. A denial fails only passwords. Extension scans and snapshots include optional Secure Preferences; protected entries override ordinary Preferences entries by extension ID. Compatible web-store extensions are reinstalled in sequence; extension storage and sign-in state are not copied.
  • Imported tabs — Source session tabs retain order, become background discarded tabs, and are collected in a collapsed sidebar folder. Tabs are created in cancellable batches; a failed folder write rolls back tabs from that import instead of leaving orphaned browser tabs. Successful folder persistence invalidates every live same-profile sidebar cache. Migration reads and commits folder data through the shared background storage queue, and reports completion only after the asynchronous write succeeds.
  • Privacy boundary — Migration records, snapshots, and progress stay local; only official extension reinstallation may use the network. Cookies are not imported because Chromium does not expose a safe cross-profile cookie import API and copied encrypted cookie stores are not portable.
  • Core owners: browser/import/dao_migration_service.*, dao_profile_snapshot.*, source adapters and target writers; webui/dao_import_ui.* and webui/resources/import/ own the WebUI.

7. Little Dao Window

Lightweight window form factor for popups / mini-tools.

  • DaoLittleDaoController / DaoLittleDaoView (little_dao/) — Top bar (48px) with hostname display + "Open in Dao" button
  • Mini Dao site controls — A frosted card uses the main Control Center's shared action tiles and wrapping extensions tile, with Page Info, native share on macOS, QR Code, and More arranged in two columns. The extensions tile scrolls when the window is too short to show every row, keeping the site action tiles fully visible; resizing a narrower window also clamps the card to its right edge. The site header and QR sub-panel remain page-scoped, and Mini Dao extraction is omitted
  • Address click feedback — Clicking the address opens the command bar and fades out the pressed highlight, so the address does not stay dark after the command bar closes
  • Download progress card — Downloads started in the Mini Dao window appear in a compact frosted card at the bottom left, with a soft rounded shadow to separate it from the page. The card shows progress, speed, cancellation, and overflow for additional downloads
  • Browser::Create timing control — Static-flag pattern (IsCreatingLittleDao()) to pass state into BrowserView during construction
  • External-link trust — The macOS external-link path preserves Chromium's launch-trust classification through StartupTabs. Untrusted launches retain an opaque navigation initiator; ordinary launches keep the default behavior.
  • Permanently windowed — Mini Dao disables browser fullscreen commands and macOS native maximize/fullscreen eligibility, including when an external link creates it while the main Dao window is fullscreen
  • macOS traffic-light repositioning

8. Webstore Branding

  • DaoWebstoreBrandingTabHelper (browser/dao_webstore_branding_tab_helper.{h,cc}) — WebContentsObserver that injects a script on Chrome Web Store pages to rewrite "Add to Chrome" / "Remove from Chrome" → "Add to Dao" / "Remove from Dao"

9. Preferences and Centralized Pref Names

  • DaoPrefNames (browser/dao_pref_names.{h,cc}) — Single source of truth for Dao-owned pref keys (welcome shown, sidebar width, folder file path, etc.)
  • Patches: prefs/browser_prefs.cc.patch, prefs/session_startup_pref.cc.patch

10. Web JavaScript Dialogs

  • Dao-styled alert(), confirm(), and prompt() — Keeps Chromium's tab-modal JavaScript dialog lifecycle, origin title, accessibility behavior, and callbacks while centering the dialog within the active web contents and applying Dao's rounded surface, primary/secondary actions, Enter/Esc keycaps, and themed prompt input
  • Patches: chrome/browser/ui/views/javascript_tab_modal_dialog_view_views.{cc,h}.patch, components/constrained_window/constrained_window_views.cc.patch, ui/views/window/dialog_delegate.h.patch

11. Branding and Visuals

  • Dao brand assets — Logos / SVGs; product name globally rebranded ("Chromium" → "Dao")
  • Platform-specific application icons — macOS uses branding/mac/app.icns; Windows maintains its own branding/win/app.png master with tighter outer spacing, preserving the Dao mark and white rounded tile at a visual size comparable to neighboring taskbar icons. scripts/generate-windows-icon.ps1 packages that master into a 16–256px ICO, including intermediate Windows DPI sizes. Import copies branding/win/dao.ico into Chromium's shared EXE/DLL icon resource for Explorer, the taskbar, and Alt+Tab. Existing profile shortcut icons regenerate on startup through an icon-version bump.
  • chrome:// → dao:// — Internal URL schemes rewritten via content/common/url_schemes.cc.patch
  • chrome_color_mixer.cc.patch — Threads dao_colors tokens into the global color pipeline
  • Custom scrollbar — third_party/blink/renderer/core/css/css_default_style_sheets.cc.patch + html.css.patch for globally restyled scrollbars
  • Chromium string rebranding — *_strings.grd[p] patch files plus import-time rewrites for generated / terms resources

12. Shortcuts and Menus

  • Dao shortcuts on Windows — Ctrl+S and Ctrl+Backslash toggle the sidebar, Ctrl+D duplicates the active tab, Ctrl+E toggles Agent, and Ctrl+Shift+C copies the active page URL with Dao toast feedback. Little Dao uses Ctrl+O to move its tab into the main browser. macOS keeps the corresponding Command keys. Duplicate, Agent, and Copy URL take precedence over Chromium's conflicting shortcuts while a page, sidebar, or Agent renderer has focus. Ctrl+S lets the webpage handle the first press; if intercepted, a localized toast offers a second press to toggle the sidebar. Button hints, tab-menu shortcut labels, and the welcome tutorial use platform-appropriate keys. Other Chromium shortcuts keep their native platform mappings.
  • Google Lens Overlay disabled — components/lens/lens_features.cc.patch permanently disables the overlay capability, removing its toolbar, address-bar, app-menu, and context-menu entry points while preserving ordinary search-provider image search
  • macOS global shortcuts — chrome/browser/global_keyboard_shortcuts_mac.mm.patch
  • macOS main menu — cocoa/main_menu_builder.mm.patch + cocoa/accelerators_cocoa.mm.patch
  • App controller — app_controller_mac.mm.patch (validate + execute commands when no browser window exists)
  • IDC_* command IDs — chrome/app/chrome_command_ids.h.patch reserves 34090–34095 for the six Dao commands. QR decoding uses local context-menu UMA bucket 170 with sentinel 171; both tables require collision checks
  • Command handling — browser_command_controller.cc.patch + browser_commands.cc.patch
  • Adding a new IDC_* requires keeping its declaration, shortcut/menu wiring, and command-controller handling synchronized.

13. Chromium Core Integration Patches

The live patch inventory is the tracked tree under src/patches/. The groups below describe its major integration surfaces without duplicating a volatile file count.

13.1 URLs and Schemes

  • content/common/url_schemes.cc.patch — Register dao://
  • chrome/common/url_constants.h.patch, chrome/common/webui_url_constants.h.patch, content/public/common/url_constants.h.patch — Constant tables
  • content/browser/webui/{url_data_manager_backend,web_ui_data_source_impl,web_ui_url_loader_factory}.cc.patch + content/public/browser/url_data_source.cc.patch — Data source / loader factory hooks
  • Canonical WebUI load-time data — dao://resources/js/load_time_data.js owns the shared data instance. The legacy chrome:// module re-exports that instance so Chromium components read the same strings and flags initialized by Dao pages. Built-in component extensions such as the PDF viewer retain their existing resource access through the canonical Dao scheme; ordinary extensions and untrusted WebUI resources retain their separate permissions.
  • chrome/browser/ui/webui/{chrome_web_ui_configs,chrome_web_ui_controller_factory}.cc.patch — Register Dao WebUI controllers
  • components/url_formatter/url_fixer.cc.patch — URL fixer adaptations
  • chrome/browser/browser_about_handler.cc.patch — dao:// about-page routing
  • third_party/blink/public/common/chrome_debug_urls.h.patch — Debug URL alias

13.2 BrowserView Integration

  • views/frame/browser_view.{h,cc}.patch — Inject DaoSidebarView and DaoCornerOverlayView; toolbar stays alive but is parked at y=-height so Chromium omnibox and command plumbing remain available
  • chrome/common/webui_url_constants.h.patch — Omnibox popup, AI popup, and Omnibox Everywhere URLs use dao:// to match their WebUI registrations, including the popup initialized when a browser window opens
  • views/frame/browser_view_layout (implicit via patches) — Layout adjustments
  • views/frame/{browser_native_widget_mac,browser_frame_mac,immersive_mode_controller_mac}.mm.patch — macOS frame integrations
  • Opaque macOS main windows — Use Chromium's default opaque native window behind the solid sidebar and content backgrounds. Command-bar and control-center blur stays within the browser's composited layers and does not require desktop transparency.
  • window_feature_controller/window_feature_controller.cc.patch — Keep macOS sidebar windows on Dao's fullscreen layout; non-tabbed app windows retain Chromium's immersive layout
  • views/frame/contents_web_view.{h,cc}.patch + views/frame/multi_contents_view.cc.patch — Content area layout and Dao split host ownership
  • views/frame/layout/browser_view_{popup,tabbed}_layout_impl.cc.patch — Per-mode layout impls
  • views/bubble_anchor_util_views.cc.patch — Bubble anchoring near the sidebar
  • color/{chrome_color_id.h,chrome_color_mixer.cc,BUILD.gn}.patch — Native textfields use Dao text color IDs while preserving system-based light/dark colors in the command bar and JavaScript prompts

13.3 Tab Strip and Tab Helpers

  • chrome/browser/ui/tabs/tab_strip_model.cc.patch — Tab model hooks (incl. cross-window drag)
  • chrome/browser/ui/tab_helpers.cc.patch — Attach Dao tab helpers (DaoAgentLockTabHelper, DaoWebstoreBrandingTabHelper, DaoAutoPipVisibilityHelper)
  • chrome/browser/ui/tabs/tab_features.cc.patch — Own the thumbnail helper independently of the upstream hover-card feature
  • content/browser/web_contents/web_contents_view_mac.mm.patch — Native drag-drop integration
  • content/browser/renderer_host/render_frame_host_impl.cc.patch — Frame-host hook

13.4 Startup Flow

  • ui/startup/startup_browser_creator.cc.patch + startup_browser_creator_impl.cc.patch — Startup behavior
  • Always restore regular sessions — Regular profiles restore their saved tabs after clean exits and forced quits, including secondary profiles and windows opened after the process has already started. Stored startup settings cannot disable recovery or append configured startup pages. Settings shows the localized continue-session description instead of conflicting startup choices; the Windows launch-on-login toggle remains available. Incognito and Guest never restore regular tabs or configured startup pages. Pending crash recovery takes precedence over the existing-process new-window path, and the sidebar waits for recovery before reconciling pinned tabs even when an old startup setting requested a blank page. The recovery uses Chromium's session service and resumes normal session saving afterward. Only data already saved to disk can be recovered; pending writes and damaged session files are not covered by this behavior. startup_browser_creator_impl_session_restore.cc.patch owns the deferred-launch fix; scripts/checks/session-restore.mjs exercises repeated force-quits and a subsequent clean restart with disposable profiles that retain legacy blank-page and specified-page startup settings.
  • ui/startup/infobar_utils.cc.patch — Infobar suppression
  • signin/account_consistency_mode_manager.cc.patch — Account consistency mode
  • profiles/chrome_browser_main_extra_parts_profiles.cc.patch — Profile init hook

13.5 Extensions

  • Legacy Manifest V2 support — ManifestV2Handler consults Dao's retained extensions.manifest_v2 preference for installation, enablement, and disable/re-enable transitions. The Dao default is 2 (allow); the restore-deprecation flag selects 0 (upstream restrictions). An explicit managed value takes precedence: 1 blocks MV2, 2 allows it, and 3 allows forced or recommended installations only; unmanaged values cannot override the Dao default. Normal extension-management restrictions remain effective. This retained preference does not restore delivery of the retired ExtensionManifestV2Availability enterprise policy. Browser fixtures disable Chromium's test-only MV2 exemption
  • extensions/browser/manifest_v2_handler.{h,cc}.patch + extensions/browser/extension_prefs.cc.patch — Handler integration, pref registration, and managed-pref change observation
  • views/extensions/extension_popup.cc.patch — Popup layout
  • extensions/browser/api/web_request/extension_web_request_event_router.cc.patch — Duplicate cleanup handles M154 per-context dispatch by matching the registration filter and extra-info options, preserving distinct listeners under one parent event name, process/request ownership checks, pending-request cleanup, and completion signaling
  • extensions/common/api/_api_features.json.patch + chrome/common/extensions/api/_api_features.json.patch — Feature allowlists

13.6 WebUI Pages (HTML / Lit / CSS customization)

  • app_home, bookmarks, certificate_manager, downloads, extensions, history, password_manager, print_preview, settings/people_page, settings/settings, signin/profile_picker — HTML and Lit template patches
  • settings/reset_page/reset_profile_dialog.{html.ts,ts}.patch — Reset profile dialog customization
  • chrome/browser/ui/webui/settings/settings_ui.cc.patch

13.7 macOS Platform

  • History-swipe lifetime — Keep the history swiper alive until touch-end cleanup finishes, including when Back closes the current tab and returns to its opener (chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm.patch).
  • skia/ext/skia_utils_mac.mm.patch
  • third_party/blink/renderer/platform/mac/graphics_context_canvas.mm.patch
  • ui/display/mac/screen_utils_mac.mm.patch
  • ui/gfx/image/image_unittest_util_apple.mm.patch
  • services/shape_detection/text_detection_impl_mac_unittest.mm.patch
  • components/os_crypt/common/keychain_password_mac.mm.patch
  • chrome/common/chrome_paths_mac.mm.patch
  • chrome/app/app-Info.plist.patch
  • build/toolchain/apple/filter_libtool.py.patch

13.8 Blink and Rendering

  • third_party/blink/renderer/core/css/css_default_style_sheets.cc.patch — Default stylesheets
  • third_party/blink/renderer/core/html/resources/html.css.patch — Default HTML CSS
  • third_party/blink/renderer/platform/graphics/paint/paint_controller.cc.patch — Paint hook
  • components/global_media_controls/public/views/media_progress_view.cc.patch — Media progress UI
  • media/base/media_switches.cc.patch — Media switches

13.9 Build / WebUI Toolchain

  • chrome/BUILD_mcp_helper.gn.patch, chrome/browser/BUILD.gn.patch, chrome/browser/ui/BUILD.gn.patch, chrome/test/BUILD.gn.patch, chrome/chrome_paks.gni.patch, chrome/app/theme/chromium/BRANDING.patch — Build graph
  • third_party/lit/v3_0/BUILD.gn.patch — Lit framework integration
  • ui/webui/resources/tools/build_webui.gni.patch + ui/webui/webui_util.cc.patch — WebUI build helpers
  • tools/gritsettings/resource_ids.spec.patch — Resource ID allocation
  • tools/metrics/histograms/metadata/sql/histograms.xml.patch — SQL histograms
  • chrome/browser/download/bubble/download_bubble_prefs.cc.patch
  • chrome/browser/accessibility/soda_installer_impl.cc.patch
  • components/performance_manager/user_tuning/prefs.cc.patch

13.10 String Localization and Rebranding

  • Default browser settings in Simplified Chinese — Dao-branded status, setup guidance, taskbar-pinning guidance, and error messages use matching GRIT translation IDs in chrome/app/resources/chromium_strings_zh-CN.xtb.patch.
  • ash/ash_strings.grd + ash/login/resources/ash_login_strings.grd — Import-time scheme rewriting preserves Dao links as ChromeOS messages move into Ash and login resources
  • chrome/app/*_strings.grd[p] and chromium_strings.grd / google_chrome_strings.grd — Branded strings
  • components/*_strings.grdp — Component strings (autofill, crash, error, history clusters, management, omnibox, policy, privacy sandbox, security interstitials, site settings, version, etc.)
  • Settings localized-string provider patches — Dao settings page strings
  • components/resources/terms/terms_*.html rebranding is handled by import-time rewrites, not patch files

14. Testing

  • browser_tests (dao_browser_browsertest.cc) — Integration test framework
  • Migration regression checks — DaoSplitViewBrowserTest.SplitPreservesContentCardAndRestoresPrimaryContent checks split host bounds, ownership, visibility, and input restoration. DaoSidebarThumbnailBrowserTest.HelperSurvivesDiscardWithoutUpstreamHoverImages checks tab-owned helper recreation when hover-card images are disabled
  • interactive_ui_tests — PictureInPictureBrowserFrameViewTest.DaoOverlayOpacityTracksTopBarAnimation in picture_in_picture_browser_frame_view_interactive_uitest.cc.patch checks initial, intermediate, and final overlay opacity without moving the client bounds; it is separate from the disabled legacy overlay tests
  • Coverage: sidebar presence / default width / collapse-expand, drag resize, address bar, command bar show/hide & idempotency, tab CRUD, SplitView, CornerOverlay, folder persistence, URL detection heuristics, extension icon and badge updates, PiP site rules / interception / top bar overlay
  • Known disabled: 5 DaoAgentMemoryStore round-trip tests due to FTS5 RazeAndPoison under direct Init(), plus 4 PiP overlay tests awaiting replacement after upstream API drift

15. Build and Packaging

  • scripts/cli.ts — Unified CLI (download / import / export / build / rebuild / test / start) — the single entrypoint; never run autoninja / ninja / siso directly
  • appdmg integration — DMG packaging
  • configs/common.gn + configs/macos.gn — Shared + macOS GN args (component build, no NaCl, proprietary codecs, no Google API keys)
  • Custom checkout variables — Build configuration flexibility
  • Vendor pipeline — Agent WebUI dependency bundling (npm run vendor)

Current Status

  • Version source: dao.json is authoritative for both the Dao display version and Chromium baseline
  • Target platform: macOS arm64
  • Source inventory: src/dao/ contains Dao-owned sources and src/patches/ contains the live Chromium integration patch set