| 1 | // Package cdp drives an external Chrome over the DevTools Protocol and |
| 2 | // presents it as a browser.Executor, so CLI, Serve, and headless sessions get |
| 3 | // the same browser_* tools the desktop shell serves from its own |
| 4 | // WebContentsViews. Nothing here is provider-visible: the tool schemas and |
| 5 | // their descriptions stay in internal/browser, and attaching this executor |
| 6 | // leaves the system-prompt prefix byte-identical. |
| 7 | // |
| 8 | // The contract's refusals are owned here because a raw Chrome has no ledger of |
| 9 | // its own. Every write reserves its model-minted operationId once and forever; |
| 10 | // a snapshot mints an opaque documentToken that the next navigation, page |
| 11 | // replacement, or user take-over retires, and a write carrying a retired token |
| 12 | // is refused as browser.ErrStaleReference rather than replayed against a page |
| 13 | // the model has not seen. |
| 14 | // |
| 15 | // Take-over detection is an approximation of the shell's guest preload. Refs |
| 16 | // and the listeners that watch for human input live in a per-document isolated |
| 17 | // world, so page scripts can neither read nor forge them, but CDP-dispatched |
| 18 | // input is indistinguishable from a hand at the keyboard once it reaches the |
| 19 | // DOM. The executor therefore marks a short window around each dispatch and |
| 20 | // counts trusted events outside it as the user's. A human click landing inside |
| 21 | // that window is missed; the failure mode is a stale snapshot, never a silent |
| 22 | // replay, because writes still carry single-use operationIds. |
| 23 | // |
| 24 | // Only tabs this executor opened are visible: an attached Chrome may hold the |
| 25 | // user's own logged-in tabs, and the agent never enumerates or drives them. |
| 26 | package cdp |
| 27 |