diff --git a/CHANGELOG.md b/CHANGELOG.md index 70d904a..a4081f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## Unreleased +- Changed `browser_handoff` into an asynchronous start operation. It now returns `completed` immediately after the durable handoff and global browser blackout are active, allowing the initiating agent to continue independent non-browser work while the user completes the step; browser observation and mutation remain blocked until the handoff clears. +- Added a disabled-by-default popup setting named YOLO mode. When enabled, recognizable consequential controls execute in the original `browser_act` call instead of entering Commit review; enabling it discards pending staged actions while task ownership, origin policy, revision checks, handoff blackout, credential isolation, and all other Standard boundaries remain enforced. - Replaced the Chrome Bridge v1 runtime with the AgentTab 2.0 release candidate: a Rust production host over OS-native local IPC, nine task-scoped Standard methods, explicit resumable capabilities, a developer-only tenth method, TypeScript and Python SDKs, MCP and OMP adapters, a transactional installer, and a minimal extension. Consequential controls now use a two-party Commit flow: `browser_act` stages an exact effect, the popup approves the durable review record without executing it, and the requesting task must consume its private one-use token through `browser_commit`. - Added explicit `browser_finish` lifecycle finalization across Core RPC, the extension, TypeScript and Python SDKs, CLI, MCP, OMP, and Pi. Automatic cleanup tracks tab provenance, closes task-created tabs, retains adopted tabs, ungroups retained tabs, and releases ownership; popup policy can require confirmation or retain all tabs, while active handoff, Commit review, and in-flight work defer cleanup without destroying resumability. - Fixed OMP adapter compatibility with providers that reject top-level union tool schemas. `browser_open` and `browser_snapshot` now expose provider-compatible object schemas while retaining strict runtime validation for their mode-specific parameters. diff --git a/README.md b/README.md index 2b3a1dd..41cc5dc 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ The command has no path, token, or shell-specific argument and is suitable for P 1. An agent calls `browser_open` with `mode: "create"`. AgentTab creates a background tab for that task and returns its task, tab, window, page-revision, and automation-route identifiers. `placement: "new_window"` may create the task's first tab in a separate unfocused normal window. 2. On a normal web origin, the agent calls `browser_snapshot`, works from revisioned accessibility references, then calls `browser_act` with the expected page revision. It cannot act on unrelated tabs. 3. If managed policy enables 1Password and an ordinary sign-in page has at most three origin-matching Login items, the agent can request a short-lived opaque token and ask the host to fill named field refs. Credential values travel only from `op` to the host and extension, never through Core RPC or the adapter. Every other human-only input uses `browser_handoff`, which focuses that tab, pauses automation, and blocks browser observation until the declared completion condition or **I'm done**. -4. If AgentTab recognizes a send, publish, purchase, delete, upload, authorization, or permission-grant control, `browser_act` can return `commit_required`. The extension shows the staged effect in its popup. A human must approve it there before the agent can call `browser_commit` with the one-use staged token. +4. If AgentTab recognizes a send, publish, purchase, delete, upload, authorization, or permission-grant control, `browser_act` can return `commit_required`. The extension shows the staged effect in its popup. A human must approve it there before the agent can call `browser_commit` with the one-use staged token. The disabled-by-default YOLO mode setting skips this Commit review and executes recognized consequential controls in the original `browser_act` call. 5. The task can list only its own tabs with `browser_tabs`. A separate client gets a separate task unless it proves its durable resume capability. 6. When browser work is complete, the agent calls `browser_finish`. Automatic cleanup closes tabs created by the task, preserves tabs adopted from the user's existing browser state, ungroups retained tabs, and releases task ownership. The popup setting can instead require confirmation or retain every tab. @@ -37,7 +37,7 @@ Commit is a two-party, best-effort semantic barrier, not proof that a page has n - **Task ownership is an execution and coordination boundary, not profile isolation.** AgentTab can use the signed-in session in the browser profile, but Standard mode does not expose raw cookies, storage, passwords, arbitrary JavaScript, raw CDP, coordinate actions, network interception, or a generic browser-global mutation API. Its one window-level operation creates an unfocused normal window for the first tab of an otherwise empty task. - **Your Turn is the only routine focus transition.** Routine task work stays in task-owned tabs. During handoff, all agent observation and capture are denied so human credentials are not captured. -- **Commit requires human approval and agent intent.** A staged action is bound to its task, tab, page revision, element fingerprint, effect, and short expiry. Popup approval records consent but does not execute it. The agent must then call `browser_commit`; a changed page, expired stage, used token, or unapproved stage cannot execute. +- **Commit requires human approval and agent intent unless YOLO mode is enabled.** By default, a staged action is bound to its task, tab, page revision, element fingerprint, effect, and short expiry. Popup approval records consent but does not execute it. The agent must then call `browser_commit`; a changed page, expired stage, used token, or unapproved stage cannot execute. YOLO mode is an explicit local opt-out from Commit review, not from ownership, origin policy, revisions, handoff blackout, or credential boundaries. - **Local by default.** Policy, task state, audit records, and IPC stay on the machine. AgentTab has no telemetry. See [Telemetry](docs/telemetry.md) and [Security](docs/security.md). ## Tool surface diff --git a/docs/mcp.md b/docs/mcp.md index d9f8f15..d006e82 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -96,7 +96,7 @@ The Core response has `protocol: "agenttab.rpc"`, `version: 1`, matching `reques Mutation methods carry a UUIDv7 idempotency key in Core RPC. MCP, OMP, and Pi bind one key to each harness invocation ID so a retry of that invocation retains its reconciliation identity. Reusing a completed key for identical work returns the durable response; reusing it with different input is a conflict. A mutation found only as started after recovery returns `unknown` and is not replayed. -The stdio MCP reader dispatches requests concurrently, while its writer serializes complete JSON-RPC lines. A long `browser_wait` or `browser_handoff` therefore does not block `ping`, discovery, or an independent tool call at the adapter layer. +`browser_handoff` returns as soon as the durable handoff and global browser blackout are active. The stdio MCP reader also dispatches requests concurrently while its writer serializes complete JSON-RPC lines, so handoff completion never holds the initiating agent call or blocks `ping`, discovery, or independent non-browser work. Raw TypeScript and Python SDK clients raise `AgentTabTransportError` for an ambiguous timeout, connection close, or transport failure. The error carries the method and, for mutations, the exact generated or caller-supplied idempotency key. A caller may reconnect and explicitly retry the same method and parameters with that key; the SDK never replays the request automatically. MCP and OMP adapters likewise return the failed invocation, discard a cached client only when its transport is closed, and reconnect on the next invocation. @@ -104,9 +104,9 @@ Raw TypeScript and Python SDK clients raise `AgentTabTransportError` for an ambi When managed policy enables 1Password, call `browser_credentials` on an ordinary sign-in page before requesting manual password entry. `prepare` derives the current origin from host-owned tab state. `fill` accepts only accessibility refs and returns filled-field booleans; credential material never crosses Core RPC. Submit separately through `browser_act`, inspect the result, and use `next` only after the site rejects the current candidate. -Call `browser_handoff` when credential preparation returns `needs_user`, the bounded candidates fail, or the site requires a passkey, security key, CAPTCHA, payment secret, account recovery, or unsupported verification. AgentTab activates a global blackout, focuses the declared tab, opens its user-facing handoff state, and denies browser observation and capture for every task while the handoff is active. Automation resumes only after the declared navigation, URL, selector, or manual completion condition is satisfied and the handoff is cleared. +Call `browser_handoff` when credential preparation returns `needs_user`, the bounded candidates fail, or the site requires a passkey, security key, CAPTCHA, payment secret, account recovery, or unsupported verification. AgentTab activates a global browser blackout, focuses the declared tab, opens its user-facing handoff state, and returns a completed start result immediately. Browser automation resumes only after the declared navigation, URL, selector, or manual completion condition is satisfied and the handoff is cleared. -The agent must not attempt snapshots, page reads, or mutations during a handoff. It should report the handoff prompt to the user and wait for the terminal tool result or an explicit user completion. +The agent must not attempt snapshots, page reads, or browser mutations during a handoff. It should report the prompt to the user, continue independent non-browser work, and resume browser work after explicit user completion or a later status check confirms the handoff cleared. ### Staged Commit @@ -128,7 +128,9 @@ The agent must not attempt snapshots, page reads, or mutations during a handoff. The token is bound to the task, tab, effect, page revision, and element fingerprint. It expires after at most five minutes and is one-use. The extension popup must first record a human approval for that exact stage. Approval does not execute the action and does not expose the native token. The agent must then call `browser_commit`, which takes only the staged token, revalidates the target, and executes only an approved stage. A changed page, ownership change, expiry, unapproved stage, or repeated token makes the commit fail. -A `browser_act` batch is sequential and non-atomic. The extension stops before the first recognizable staged action and does not execute later actions implicitly. The current host response preserves the staged token and binding metadata, but does not publicly return the extension's completed-prefix list or staged index. Clients must not infer how many preceding actions ran from a `commit_required` response; inspect the page before deciding the next action. This is a source limitation, not a guarantee of an atomic batch. +YOLO mode is a disabled-by-default local popup setting. When enabled, recognized consequential controls execute inside the original `browser_act` call and return its ordinary completed result instead of `commit_required`. Enabling the setting discards pending staged actions. It bypasses only Commit review: task ownership, origin policy, expected page revisions, restricted-origin routing, handoff blackout, credential isolation, and action validation still apply. + +With YOLO mode off, a `browser_act` batch is sequential and non-atomic. The extension stops before the first recognizable staged action and does not execute later actions implicitly. The current host response preserves the staged token and binding metadata, but does not publicly return the extension's completed-prefix list or staged index. Clients must not infer how many preceding actions ran from a `commit_required` response; inspect the page before deciding the next action. This is a source limitation, not a guarantee of an atomic batch. With YOLO mode on, the recognized action executes inline and the batch continues until completion or the next failure. Commit reduces recognizable risk only. It requires both the popup's human approval and the agent's later `browser_commit`, but it cannot prove that a page's labels, event handlers, or side effects are benign. diff --git a/docs/security.md b/docs/security.md index f4db295..5ddfffe 100644 --- a/docs/security.md +++ b/docs/security.md @@ -66,6 +66,8 @@ Before a Standard mutation, the extension prepares the target, classifies recogn Commit is a best-effort semantic barrier, not proof that an action is harmless. It requires two distinct events, human approval in the popup and the agent's later Commit request. A page can hide an external effect behind an innocent label, alter meaning through script, or use an effect AgentTab does not recognize. Harmless-looking controls may execute without review. Batches are sequential and non-atomic: work stops before a staged action and never runs later actions implicitly. +YOLO mode is an explicit, disabled-by-default opt-out from Commit review. When enabled, recognized consequential controls execute during the original `browser_act` call, and pending staged actions are discarded when the setting changes on. The mode does not bypass task ownership, origin policy, expected revisions, restricted-origin routing, handoff blackout, credential isolation, or action validation. + ## Your Turn blackout During a `browser_handoff`, AgentTab pauses browser work and applies a global blackout across tasks. Page observations and captures are denied while the human enters information. The extension persists the active handoff before focusing the tab; the host restores the blackout from durable state after restart. Completion requires the declared condition or explicit completion, capture scrubbing, and host acknowledgement before automation resumes. diff --git a/packages/extension/src/background.ts b/packages/extension/src/background.ts index 9e7d65e..5e0136a 100644 --- a/packages/extension/src/background.ts +++ b/packages/extension/src/background.ts @@ -6,7 +6,6 @@ import { commitRequired, completed, failed, - needsUser, type NativeDispatchCommand, type NativeOriginPolicy, type NativeResponse, @@ -409,7 +408,7 @@ async function dispatch(command: NativeDispatchCommand): Promise if (!scheduler.isAccepting() || (await readState()).paused) { throw scheduler.notStarted("AgentTab is paused"); } - return needsUser( + return completed( command.request_id, await handoff.begin( command.task_id, @@ -697,6 +696,7 @@ async function handlePopupMessage(message: Record): Promise): Promise { + state.skipCommitReview = enabled; + if (enabled) state.stagedCommits = {}; + }); + return { enabled }; + } if ( message.kind === "set_cleanup_policy" && (message.policy === "automatic" || message.policy === "ask" || message.policy === "keep") diff --git a/packages/extension/src/browser.ts b/packages/extension/src/browser.ts index cf55a26..4162fa4 100644 --- a/packages/extension/src/browser.ts +++ b/packages/extension/src/browser.ts @@ -456,7 +456,7 @@ export class StandardBrowserRuntime { } await this.revisions.assertExpected(tabId, pageRevision); const stagedConsequence = await this.consequence(tabId, pageRevision, action); - if (stagedConsequence) { + if (stagedConsequence && !(await readState()).skipCommitReview) { const staged: StagedCommit = { native_token: randomToken(), task_id: taskId, diff --git a/packages/extension/src/handoff.ts b/packages/extension/src/handoff.ts index f886041..5832621 100644 --- a/packages/extension/src/handoff.ts +++ b/packages/extension/src/handoff.ts @@ -151,6 +151,7 @@ export class HandoffController { started_at_ms: startedAt, }); return { + handoff_started: true, task_id: taskId, tab_id: numericTabId, prompt: params.prompt, diff --git a/packages/extension/src/popup.html b/packages/extension/src/popup.html index 0ca960f..7b5e1e0 100644 --- a/packages/extension/src/popup.html +++ b/packages/extension/src/popup.html @@ -98,6 +98,13 @@

Task groups

+