Repository navigation
fix(extension): reduce idle overlay and Accessibility overhead - #408
Open
NianJiuZst wants to merge 5 commits into
Open
NianJiuZst wants to merge 5 commits into
NianJiuZst wants to merge 5 commits into
Conversation
The control overlay animated an inset box-shadow on a full-viewport element forever. box-shadow is not compositor-animatable, so the whole viewport was repainted on every frame for as long as the agent held control, even while it was idle. The animation also ignored prefers-reduced-motion. Paint the resting glow and the brighter glow as two static shadows and fade only the brighter layer's opacity, for two pulses. Under reduced motion only the resting glow is shown. Refs Tencent#391. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LZRCYsFEKFsAZe6i8WAc9o
Every capture sent Accessibility.enable to each target but never disabled it, so the renderer kept its accessibility tree live and reported changes for the rest of the debugger attachment. Once a target's AX trees are read, or the capture fails or is cancelled first, disable the domain again on each target that enabled it. The cleanup shares the capture's worker bound, settles before the capture does, only uses the attachment that enabled AX, and is never queued behind a read still pending past its deadline: such a target is skipped, and the read gate now refuses Accessibility.disable behind a pending read. Refs Tencent#391. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LZRCYsFEKFsAZe6i8WAc9o
Refs Tencent#391. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LZRCYsFEKFsAZe6i8WAc9o
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #391.
An agent session can keep doing browser work between commands: the control overlay continuously animates a viewport-sized inset shadow, and observation enables Chrome's Accessibility domain without disabling it afterward. This PR makes the control glow settle after two opacity pulses and releases Accessibility on the targets whose capture reads have finished.
Problem and resulting behavior
box-shadowanimation runs for the entire time the overlay is visible.prefers-reduced-motion: reducedisables the pulse and leaves the static control glow.Accessibility.enable, but completed captures leave the domain enabled.Accessibility.disableafter the AX read phase, before document-identity and geometry work.Implementation
Control overlay
ControlOverlay.tsxkeeps the resting inset shadow on the existing overlay and adds a brighter child layer. Thebsk-breathekeyframes now contain only opacity changes, with a finite iteration count of two. The child has a resting opacity of zero, and a reduced-motion media query disables its animation. The control indicator, interruption button, and input-blocking behavior remain available.Accessibility lifetime
capture-coordinator.tsrecords each successfully enabled target together with its debugger attachment ID. Release uses the capture's existing worker helper, with at most four cleanup requests in flight, and is awaited before the capture completes.finallyaround the AX read phase.sendGuardedwith the original attachment ID in production, so an old capture cannot reconnect or send cleanup to a replacement attachment.command-deadline.tsguardsAccessibility.disableagainst earlier pending reads and gives cleanup itself a 1-second deadline. A timed-out disable retains its target gate until Chrome replies or the debugger detaches; late replies cannot clear a replacement attachment.Observation refs retain their backend DOM node IDs and document/attachment identity; the implementation does not depend on Accessibility node IDs surviving between captures. The changelog records both user-visible changes.
Regression coverage
Eight new cases extend three existing test files:
ControlOverlay.test.tsx(2): static shadows, opacity-only keyframes, exactly two pulses, no infinite animation, and the reduced-motion override.capture-coordinator.test.ts(5): release for root and child targets after their AX reads; release before identity/geometry work; dispatch on the original attachment; no cleanup on a replacement attachment; skipping a timed-out child while releasing the root; and cleanup during cancellation. Some cases assert multiple related behaviors.command-deadline.test.ts(1): a pending child-session AX read blocks its own cleanup without blocking root-target cleanup.Validation — 2026-10-20
Merged upstream main
e8777ab71bb851196895515b53eea2481462dd57; current revisiond305f8de8867bc42081d23c765502ab2291ce44b.Accessibility.disablepending. The production read gate returned its timeout after 1,002 ms, rejected another read while pending, and recovered after the original command settled following execution termination.Limits and performance evidence
Thanks to @code-yeongyu for the report, measurements, and original prototype.