Commit Graph
10 Commits
Author SHA1 Message Date
OrcaWinandOrcaWin 9c7654600a perf(browser): throttle idle guests between active operations (#34776)
* perf(browser): throttle idle guests between active operations

* perf(browser): lease only the guest for non-capture agent commands

Keep the renderer paint hold, host unthrottle, and host re-hide readback on
capture paths only, and never let the one-way paint-hint send fail the capture.

* style: format bridge paint-hold test

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-10-28 02:15:30 -07:00
Kelvin Amoaba eb499478da feat(browser): show agent browsing live, with a jump to the page from chat (#33075) 2026-10-25 22:15:00 +00:00
OrcaWin 2847bbe9e8 [comment audit] Consolidate completed code comment cleanup
Combine the completed comment cleanup from 319 stacked PRs into one change against `main`, so the full CI suite validates the combined result once. This replaces the previous audit stack; no additional audit work is included.

The change shortens redundant comments across 2,753 source and shell-snapshot files (25,235 net lines removed). Conflicts preserve current-main executable code. Runtime behavior, test assertions, directives, licenses, generated notices, SAFETY rationales, and compatibility markers are preserved. The audit tracker remains local, outside the repository.

Validation:
- Equivalent source/emitted AST and executable tokens across all 2,750 source files, with separate checks for embedded shell, SQL, JavaScript, CSS, and generated fixtures.
- Identical executable lines in the three shell snapshots; protected comments unchanged.
- Changed-code quality gate passed with no new findings.
- 358 tests passed, 2 skipped across 23 focused test files.
- `git diff --check` passed.
2026-10-23 13:15:45 -07:00
Neil d4b65b9302 fix(browser): a press an SSH host left held across commands is let go of when the host is revoked (#30847) 2026-10-19 18:03:14 -07:00
Neil 90236c3bde refactor(browser): one page gate and one owner for a host command's hold (#30652)
The revocation gate, the input cancel list and the hold's lifecycle each lived in two places.
Sinks now call one gate, held input is recorded at the CDP send (and the one native key path),
and runWithRemoteCliPageAdmission owns retire-on-revoke, release and error conversion.
2026-10-19 03:11:54 -07:00
Neil 94c858cda6 fix(ssh): a cancelled or revoked host's browser command stops on the desktop (#30630)
* fix(ssh): a cancelled or revoked host's browser command stops on the desktop

orcad now tells a cancel-capable desktop when the CLI gave up on a forwarded browser command, and a running host command on the desktop checks revocation before every side-effecting step (each helper CDP message and each direct input dispatch).

* fix(browser): keep local commands out of a host's scope, gate each helper on its proxy

* fix(browser): hold a host-driven page at its input sinks instead of per call site

* test(browser): checked mock types in the host revocation suites

* fix(browser): refuse only a host's own traffic, never the desktop's page commands

* fix(browser): a host's proxy never keeps its scope, and a revoked click still lets go of the button

* fix(browser): a revoked command may release only what it pressed, on every input path

* fix(browser): refuse every revoked step, and let the desktop release what a revoked command left held

* fix(browser): retire a revoked command's helper daemon before letting go of the page; release held input with a lease, synced pointer state and the focus guard

* fix(browser): deferred proxy input keeps its hold, releases count once they land, and a revoked helper is retired at once with its routes kept

* test(browser): keep the mock page cast on its SAFETY line
2026-10-19 01:54:54 -07:00
Neil db22421ae7 fix(ssh): agents on a managed SSH host can drive the desktop Orca browser again, behind the per-host switch (#29384)
* fix(ssh): an opted-in desktop serves its browser to a managed SSH host's orca CLI again

* fix(ssh): scope bridged pages through the renderer, render them as desktop pages, and route the e2e

* fix(ssh): bridge refuses file URLs and clipboard reads, revokes on disconnect, closes desktop tabs

* fix(ssh): judge bridged paste chords as the page sees them; accept long workspace ids

* fix(ssh): bridged clipboard denial follows popups; revoked commands never leave the browser queue

* fix(ssh): refuse option-like host values bound for agent-browser argv; report undeliverable results

* fix(ssh): bound bridged error results and fall back when the host refuses one

* fix(ssh): bridge only routed host tabs, and bound bridged page scripts by a deadline and revocation

* fix(ssh): cap waiting bridged commands below the desktop socket's result capacity

* fix(ssh): bridge revokes on routing changes, checks each page's route at run time, and cancels host-driven downloads

* fix(ssh): name the bridge registry's owner type

* fix(ssh): bridge refuses pages showing a local document, and never starts a command past orcad's deadline

* fix(ssh): bridged commands may leave Chromium error pages, and stop starting before orcad's deadline

* fix(ssh): ask for a fresh opt-in to host CLI control saved before it drove the desktop browser

* test(ssh): type the bridge registry deadline test
2026-10-15 23:40:57 -07:00
Jinwoo Hong f2ac9f29b2 fix(browser): let pixel capture hold its own page drawn, without the desktop window (#22534)
* fix(browser): let pixel capture hold its own page drawn, without the desktop window

Screenshots were the last browser commands that still borrowed the desktop
window: they took the per-page automation-visibility lease, which waits for
two desktop-window animation frames (capped at 2 s) and never arrives when the
window is minimized or throttled. Only pixel capture actually needs a page
drawn — input, scripts, layout, the accessibility tree and PDF all work on a
hidden page.

Capture now takes a main-owned paint hold: a synchronous, per-page ref-count
that tells the renderer one way (no reply awaited) to keep the page drawn and
keeps the desktop renderer unthrottled while held. Both Orca's full-page
capture and the agent-browser helper's screenshots take it in
cdp-screenshot.ts and retry on a bounded schedule until the page answers with
a frame; a CDP error fails fast.

Deleted: the queue's needsPaint lease, the executeJavaScript acquire path and
its two racing 2 s timeouts and late-token cleanup, the renderer's rAF wait and
window bridge, the capture commands' own leases, the fixed 300/500 ms settle
waits, and the global one-screenshot-at-a-time lock.

Rebased onto main after #22528 landed; content identical to the reviewed
branch head 7b390ed6a8.

* fix(browser): probe for a frame instead of repeating the full capture

Retrying a capture resent the caller's full request, so on an already
drawn tall page (a full-page capture takes ~0.5 s) the 250 ms retry
started a second full beyond-viewport capture while the first was still
running. Measured on Electron 43: any later request makes a held page
produce a frame, and that frame answers every pending capture with a
full, correct image. So the capture is sent once and 1x1 probes follow
until it answers; their results are ignored.

Also report a detached debugger as detached rather than destroyed, and
give the layout-metrics timeout its own "did not respond" message, since
that request doesn't need a drawn page.
2026-09-23 21:17:46 -04:00
Jinwoo Hong 7f203ad5aa fix(browser): only pixel-capturing commands wait for the page to be drawn (#22528)
* WIP

* WIP2

* fix(browser): only pixel-capturing commands wait for the page to be drawn

Every targeted browser command used to take an automation-visibility lease,
which waits for two desktop-window animation frames (capped at 2 s). When the
desktop window is minimized or throttled, that wait always hits the cap, so
each phone tap or agent command stalled for up to 2 s (STA-8024).

Input, page JavaScript, layout and accessibility snapshots all work on a
hidden page; only pixel capture needs it drawn. The lease is now opt-in via
`needsPaint` on the two commands that can capture pixels through this path
(`exec` passthrough and `pdf`); `ensureVisible` is removed. Screenshots keep
managing their own lease.

(Commits 24821ae and 07b4a09 carry this change under WIP messages.)

* refactor(browser): drop the session-recreate option only no-lease commands used

Only exec and pdf take the automation-visibility lease now, and both create an
agent-browser session, so the lease's re-registration path always recreates
the session. Remove the `recreate` option from restartSessionForTarget and the
options passthrough that fed it. Also fix the keypress test comment that still
counted the lease's extra page lookup, and note that screenshots lease inside
the screenshot lock.

* fix(browser): resolve a command's page when it runs, not when it is queued

Enqueue resolved the page's guest webContents and created its session up
front. Before this PR every command re-resolved after its lease, which hid
that; now a command queued behind exec/pdf, whose lease can re-register the
page with a new guest webContents, would run against the old one.

Enqueue now only picks the page (and so the queue). The webContents lookup
and session setup move into the queued job and run when the command starts,
after the lease for exec/pdf.

The lease path's refresh collapses into that step. Resolving after the lease
already sees a re-registration that happens during the lease, so the only
thing left from the refresh is the case where the page's existing session is
bound to an older guest: that session is restarted on the new one (keeping
intercept routes) and the active-tab pointers move with it. That check now
covers every session-backed command, not only leased ones.

Admission is still checked at enqueue and again when the job starts.

* refactor(browser): drop the session-restart reconcile no page can reach

Every renderer re-registration of a page with a different guest goes through
browser:registerGuest, which calls onProcessSwap in the same tick. That
destroys the page's session and rejects its queued commands, so by the time a
queued command runs, no session can still be bound to an older guest. The
reconcile in the queue and restartSessionForTarget, its only caller, are
removed along with the two tests that called it directly.

A queued command now resolves the page's current guest, ensures its session,
and runs. The re-registration tests now report the swap through
onProcessSwap, as production does: commands queued behind the swapping lease
are rejected with browser_tab_closed, the leased pdf runs on the new guest,
and intercept routes survive the swap.
2026-09-23 17:32:04 -04:00
Neil 5b4e7edb50 refactor(main): split backend services and startup
(cherry picked from commit a33573328b)
2026-09-01 02:07:33 -07:00