* fix(ssh): keep old relay channels off the host's own SSH connection
Each old relay still running a shell held one exec session on the target's
connection. At sshd's MaxSessions (default 10) every later exec failed, so the
host stuck at Connecting with 'Could not detect the remote platform: (SSH)
Channel open failure: open failed'.
* test: say why the session-limit repro needs a longer timeout
* test: note why the relay channel fakes are cast
* test: move the many-relays repro into the existing legacy relay bridge suite
React Compiler drops bare `void x;` reads, narrows callback deps to the fields
read, and oxc 0.152 emits `a[q.head++]` as a prefix update. Rewrite those
sites so they behave the same with the compiler on, and identically to today
with it off:
- `void tick` memo invalidators -> `recomputeOn([tick], () => ...)`
- `void el.offsetWidth` transition resets -> `forceLayoutReflow(el)`
- pty termination queue reads, then advances, the head index
- host agent preference subscription takes the whole subscription object
Prunes the compiler-compat hazard baseline from 40 to 2 entries.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
A keychain item for agy does not prove agy can sign in silently: agy acp then
answers every session request with "Authentication required", and Orca never
authenticates the host (oauth-personal opens a browser). The host check now
also lists sessions after initialize (which writes no conversation, unlike
session/new), so a signed-out agy keeps new chats on Orca's runtime. Any
answer except an incompatible binary is rechecked after 5 minutes so a lapsed
or restored sign-in is noticed. agy settings that name a modelProvider select
API-key auth, whose key host launches drop, so they keep chats off the host.
Refs #39006
* feat(pairing): show which devices still sign in with their original pairing code
Settings lists paired phones and access links that signed in with a pairing
code but never exchanged it (apps from before single-use pairing) with
"Uses an older pairing method. Update ...". Display only; rows from older
builds are never flagged.
* fix(pairing): no update hint for links used by plain-http browsers or still pairing
A link that served a session-only browser key is marked, so the hint stays
off after a host restart drops those keys. Codes still inside the pairing
window are not flagged either: an updated client exchanges within moments.
* feat(plugins): let plugins contribute web fonts to the font pickers
Plugins declare font families under contributes.fonts (WOFF/WOFF2 only).
Install checks each file's signature against its extension and caps file
size, family count and plugin total; main never parses a font. Files are
served over the plugin image scheme only while the plugin is enabled,
typed and nosniff. The renderer registers each family under a name that
carries the plugin key, so a plugin font cannot shadow an installed or
built-in font, and it applies only once the user picks it. Disabling or
uninstalling removes the faces; uninstalling also resets font settings
that named them.
Refs #38607
* fix(plugins): harden plugin fonts and re-measure editors when they load
- Refuse WOFF/WOFF2-wrapped font collections by checking the flavor bytes.
- Check dev folders' font files at discovery, not only at install.
- Re-check family, weight and style from the plugin list in the renderer.
- Track loaded families (case-insensitively) from document font loads, so
the code editor re-measures and terminals, previews, the SSH terminal and
the dashboard popout re-apply only when their own font changes.
- Register plugin fonts in the dashboard popout window.
- Give dev-folder font URLs their change count so edits reload.
- Keep monospace fallbacks unless the chosen family is exactly that font.
* fix(terminal): keep every fallback only for plugin font families
System font choices keep their existing fallback list unchanged.
* fix(plugins): leave the dashboard popout's plugin list alone; add the font row string
Registering fonts there started the plugin auto-update watcher in a window with no toaster, which could consume update notices. Adds the new contribution-row string to the English catalog and the fonts list to the RPC test manifest.
* Use Cmd+K for search on new Mac profiles
Preserve existing search and terminal clear shortcuts during migration
on desktop and web.
* Preserve legacy Mac shortcuts during web profile migration
* Preserve keybinding resets across profiles and platforms
* Preserve legacy shortcuts and markdown link bindings
* Separate profile shortcut defaults from shared overrides
* Check shortcut conflicts when restoring defaults
* Fix tab shortcuts targeting floating workspace panels
* perf: stop host-status pings rebuilding the title catalog and rereading server config
Host-status updates walked every saved tab for title-refresh support before checking whether any host's support changed, and remote RPC/tunnel/worker checks reread, rehardened and reparsed the saved-server registry files on every call. Gate the title walk on an actual per-host capability flip, and reuse the merged registry read while a stat signature of its three files is unchanged.
* perf: invalidate registry read cache on in-process writes
Coarse-timestamp filesystems can reuse an inode within one tick, so a same-size rewrite could slip past the stat signature; writers in this process now bump a generation that is part of the signature.
* perf: key the registry read cache on file bytes, not stat metadata
A stat signature can miss a same-size rewrite on coarse-timestamp filesystems or a reused inode. Comparing the files' exact bytes (plus mode/ctime and the directory mode, which the uncached read re-hardens) means a hit can never serve data that differs from disk, from any writer.
* perf: only reuse a registry read once hardening holds and the path is unchanged
Reuse now requires the files' permissions to already be restricted (POSIX), so a transient chmod failure is retried on the next read as before; Windows hits keep the ACL verify-and-retry. Snapshots also record each path entry's identity, so a symlink re-pointed and restored mid-read cannot pin the value read through the other target.
* perf: build the cached registry value from the exact bytes it is keyed on
The value was computed by a second, independent read, so a directory or symlink swapped and restored around it could pin data the key's bytes never held. Each reader is split into read + parse-text, and on a miss the cache hardens, snapshots once, and parses that snapshot. Reuse also now requires the exact 0600/0700 modes the readers set, so an incomplete owner mode is repaired as before.
* perf: require the full hardened mode, including special bits, before reusing a registry read
* perf: keep Windows on the plain registry reader
Measured on a Windows host: a cache hit still has to re-verify ACLs, so it cost as much as the read it skipped (0.37 ms vs 0.33 ms). Windows now always uses the original reader, keeping its behavior byte-for-byte unchanged.
* perf(daemon): cache Linux CLK_TCK instead of forking getconf per start-time read
CLK_TCK is fixed for the kernel's lifetime, so the daemon identity check
no longer runs a synchronous getconf process on every read.
* fix(daemon): retry invalid Linux clock tick reads
---------
Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* feat(mobile): transcribe dictation on device with SpeechTranscriber on iOS 26
* fix(mobile): fall back to the dictation model, reserve locales and stop a finishing session on cancel
* fix(mobile): resolve on-device speech locales deterministically and report the simulator unsupported
* refactor(mobile): simplify the on-device speech engine and skip conversion when formats match
* feat(pairing): Add server and orca environment add exchange the link for their own token
After verifying the host, Add server (and repair) swap the access link's
token for one generated on this computer when the host advertises
pairing.ticket-exchange.v1, and save that instead. orca environment add does
the same with a short best-effort probe. Any failure saves the link as today;
the host keeps accepting it until the new token is used.
* test(pairing): Add server and CLI leave links unchanged for a released host
* fix(pairing): Add server and orca environment add sign in once after exchanging, and the CLI rejects a refused code
After exchanging a link, sign in once with the new token so the host
retires the link right away instead of at the first later use; a host
downgraded in between would not know the new token.
orca environment add no longer saves a pairing code the host refuses
(for example one another device already used); it asks for a new code.
* feat(mobile): define the on-device speech contract for the native audio module and page bridge
* feat(mobile): dictate on the phone first and replay to the computer when the phone fails
* refactor(mobile): type the on-device speech module without a cast
* fix(mobile): point dictation's finish ref at the committed callback
* test(mobile): wait on the takeover request instead of a fixed sleep
* fix(mobile): release each dictation request's own share of a replayed backlog
* fix(mobile): let the computer's text replace the phone's after a fallback
* fix(crash-reporting): don't report a speech process exit as an Orca crash
* fix(crash-reporting): keep every speech process exit out of crash reports, including OOM
* feat(mobile): recognize dictation on-device on Android with ML Kit
* feat(mobile): fall back to Android's on-device recognizer on phones without AICore
* fix(mobile): keep on-device speech events and finishes tied to the current session
* fix(mobile): let an ended on-device session release the recognizer before the next starts
* refactor(mobile): trim the Android on-device speech engines
* refactor(pairing): move device sighting bookkeeping out of the device registry
* refactor(editor): define plugin Monaco themes outside the hook so it compiles
* fix(diff): keep one tint on wholly new and deleted files
A new file diffs against an empty original, so every line carried both the line tint and the character tint, plus a red row for the empty original line. Drop the stacked character tint and the empty side's lone tint for whole-file additions and deletions in the file diff and combined diff.
* fix(diff): hide the empty side's lone marker and cover the accessible diff viewer
* feat(native-chat): dim the message rail until hover, focus or scroll
The rail drew at full strength the whole time. It now rests at 40% opacity and lights on pointer hover, keyboard focus (focus-visible) or reader scroll input, fading back after about a second idle. Scroll input writes a data attribute on the rail node, so no React render runs per scroll. Reduced motion switches without a fade.
* fix(native-chat): keep the rail lit through drags and its preview, and snap under reduced motion
Chat strong inherited bolder (700), heavier than the chat's own
semibold (600) headings. Use 600 so emphasis stays distinct without
dominating long answers.
Refs #39060
A terminal.send guard with onError: deny that returned an invalid result (e.g. a
deny reason over 500 chars) was logged and skipped, letting the action through.
Treat a malformed result from a fail-closed participant as a failure. (STA-13532)
* fix(antigravity): keep Gemini Enterprise chats off the host's agy
A saved Chat account type other than a personal Google account (or a
malformed or still-saving one) now keeps new Antigravity chats on Orca's
managed runtime, whose sign-in honors it. Before, Enterprise users who had
not yet signed in to Orca's Chat were silently pinned to the host agy's
personal account. The check reads the execution host's own saved settings,
and the health snapshot refreshes when the setting changes.
Refs #39006, #38737
* test(antigravity): drop the settings cast
* feat(pairing): a browser's saved device key retires the pairing link it came from
When a browser signs in for the first time with a saved device key forked
from a ticket row, the row's link token is replaced by a value nobody holds
(the row stays as the fork's anchor; orchestration fingerprint pinned).
Session-only keys re-register from the link on every page load, so they never
retire it. Links from older builds are untouched.
* fix(pairing): a browser key retires a link only during pairing and only if nobody claimed it
A saved browser key now retires its link only when it was registered within
the pairing window of the link's first sign-in, and only when no other
client already proposed its own token for it (that first claim wins, so the
desktop that proposed first is never locked out).
* test(pairing): the web key migration wire test expects a fresh link to be single use
* fix(web): say a refused pairing link may already have been used
A browser opening a single-use link after another device used it is
refused as unauthorized; the message now names that case and asks for a
new pairing link from Orca.
Adds oxc-transform-react as a devDependency and a ratchet that runs React
Compiler in analysis mode over the shipped renderer sources. Files can't gain
bailouts (new files must compile fully), and new code the compiler would run
differently is banned: hooks it memoizes into a cached block, bare `void x;`
reads, member postfix updates used as values, and "use no memo" opt-outs.
Both baselines are generated by --update / --prune.
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
Explicit SGR backgrounds equal to the translucent default background, and
style-only cells (dim, italic, extended underline) in WebGL, painted an
opaque fill over the theme wallpaper. Treat them as the default background
in both the WebGL and DOM renderers; the buffer keeps the original color.
Closes#37671
- Keep a bounded history of approved setup hashes per repo; creates send it and the host
runs setup when the created branch matches any approved content.
- Approving a created branch's different setup now saves it to that history.
- Automation runs record skipped setup content; the run page and list offer
"Review and approve setup", and saving re-confirms setup after a skipped run.
- Device registry: if saving a device's first sign-in fails, keep the sign-in in
memory and retry the save every minute until it lands. Before, a restart after
the pairing code's expiry treated the device as an unused, expired code and
refused and removed it.
- Remote runtime client: when a host remembered as E2EE v2 refuses v2 and the
legacy status check gets a sealed "unauthorized" reply, report that refusal
instead of "update Orca on that host" with close code 4001, which managed
orcad read as a different server on its port.
The New workspace and New issue discs on the host and Tasks screens were
a pale #e5e5e5 fill that glared on the dark page. Dark mode now uses the
same accent fill as the Home + button; light mode keeps its dark fill.
Refs #37401
* feat(mobile): exchange the scanned pairing code for a token kept on the phone
When the desktop advertises pairing.ticket-exchange.v1, the phone sends a
token it generated as the last call on the winning pairing socket and saves
that token instead of the scanned one. For Relay pairings the journal is
rewritten first so recovery republishes the same token. Any failure keeps
the scanned code, which the desktop still accepts.
* fix(mobile): say a refused pairing code may already have been used
Single-use pairing codes are refused once another device signs in with
them, so the scan error now mentions that case alongside expiry and
replacement, and still asks for a new code from the desktop.
* feat(pairing): let clients exchange a pairing code for their own token
New offers are marked as tickets. A client signed in with the pairing token
can call pairing.exchangeTicket with a token it generated; the host stores it
durably and keeps accepting the pairing token until the client first signs in
with the new one. That sign-in retires the pairing token and cuts sockets
still using it. Advertised as pairing.ticket-exchange.v1; clients that never
call it keep working exactly as before.
* fix(pairing): never retire a code other clients may already rely on
Exchange is offered only within 10 minutes of a ticket's first sign-in;
after that the code may be in use by several older clients and stays a
plain token. The first client to propose keeps its claim: a different
proposal is refused (that client keeps the code) instead of displacing it,
so two clients pairing at once can't lock out the first. Adds cross-version
tests against the pinned release: downgrade keeps exchanged and unexchanged
phones working, rows from an older host are never single-use, and the older
host doesn't advertise the exchange.
* feat(antigravity): run Chat on the host's agy acp when compatible
New Antigravity chats prefer a compatible host-local `agy acp` (initialize
must answer as "Antigravity ACP Server" >= 1.5.2, protocol 1, loadSession and
session/resume) and fall back to Orca's managed runtime otherwise. The chat's
account home pins its backend, so resume and auth failures never switch it.
Managed chats and their <userData>/antigravity-chat sign-in are unchanged.
Refs #38833, STA-14062
* test(acp): launch an attached host rig with its spec
* fix(antigravity): keep Orca's Chat sign-in, back off a hung agy, and never downgrade permissions
The host's agy takes a new chat only when nobody is signed in to Orca's own
Chat and agy has its own credential. A failed check waits 5 minutes before
retrying (5 s timeout). Full-access chats stay on Orca's runtime, and a host
chat refuses a permission mode agy lacks instead of asking.
* fix(antigravity): check agy's sign-in without a keychain prompt, ignore inherited API keys, allow own mode
agy falls back to an inherited GEMINI_API_KEY, which its models reject, so
host chats drop it. The macOS presence check reads only the keychain item's
attributes. Chats in agents' own permission mode may use the host's agy.
* fix(native-chat): show Orca's install card only for chats on the managed runtime
The status summary marks chats pinned to a host program (hostProgram), so a
chat on the host's agy is no longer blocked when Orca's runtime is missing.
* fix(mobile): show host agy sign-in copy for Antigravity chats
The desktop host now reports antigravitySystemNotSignedIn when a chat on the
host's agy is signed out; give the phone the same copy so its failure table
stays complete.
* feat(dictation): send desktop dictation audio straight to the speech process
* test(speech): pin that a desktop audio port reaches only its own stream
* test(speech): give the speech IPC test's ipcMain mock the on listener the port handoff registers
* refactor(speech): track an open audio port by its map entry and require the port capability
Each chunk RPC holds one of the page bridge's 60 desktop request slots until
the host answers, through a reconnect too, so the page drained the microphone
only every 500 ms. Cap chunk sends at four per dictation and merge audio
captured meanwhile into the next request, then drain every 150 ms.
* feat(dictation): pre-warm the speech model and make the unload timeout a setting
The first dictation after launch, or after the idle recognizer unloaded,
waited for the speech host to spawn and load the model. The host now loads
the selected on-device model when voice is on: after the first window (or
at orca serve start), when the voice settings change, and when an Orca
window regains focus after an unload. A dictation started meanwhile binds
to the loading recognizer instead of loading a second one.
Voice settings gain Unload Speech Model: Never, Immediately, 5, 15 (the new
default, was 60) or 60 minutes. Immediately also turns pre-warm off, voice
off frees an idle recognizer, and a model that failed to load is retried
only on a settings change or after a dictation loads it.
* fix(dictation): don't mark a model failed when its warm-up was torn down on purpose, and stop a warm-up that voice-off superseded
* fix(agent-launch): paste Copilot launch drafts when its composer row draws, not after the loading spinner settles
* chore(plugins): regenerate declarative runtime for the Copilot composer signal