orcad-browser-provider and the pinned runtime materializer each kept a private
errorMessage; the WSL holder record and the secret-key record kept private
error-code checks, and the secret-key record its own kill(0) liveness check.
They now call errorMessage, hasErrorCode and isProcessAlive.
* feat(ssh): let a nodejs.org mirror serve the pinned Node on both machines
* fix(ssh): share one deadline across every host download URL
* fix(ssh): give each host download URL its share of the deadline and cap its size
* refactor(ssh): one tool per host, labelled sources and a portable wget watchdog
* fix(ssh): quote this computer's short download reason in the combined error
* fix(ssh): fetch only validated mirror URLs on the host
* fix(ssh): drop an empty query or fragment from the mirror URL
* fix(ssh): keep a cancel or a local error as it is after the mirror fails
* fix(ssh): let the host download the pinned Node when this computer can't
* fix(ssh): keep both host download tools inside one time budget
* fix(ssh): use timeout for wget only where it runs as expected
* feat(runtime): remove an agent's downloaded runtime only once nothing on the host can still run it
managedRuntime.remove {agent} (host-admin, capability managed-runtime.remove.v1)
deletes the agent's releases inside the launch gate. Before anything is deleted the
gate aborts starts under way (chat starts and conversation copies), stops the
agent's loaded chats on this host, and proves every retained child gone: failed
chat starts and sign-in children whose close was never proven. Every close settles
before the gate releases; if any owner stays unproven, Remove fails and keeps the
files. Stopping chats by agent is now one generic host helper that sign-in shares.
Install refuses while a removal runs, Remove refuses while an install runs, and a
removal cannot be cancelled.
* fix(runtime): status says whether a copy is there to remove, damaged copies included
canRemove is set whenever Orca's copy is present, whole or damaged, so Settings offers Remove for a
damaged copy too. The failed-start retain is dropped: the launch gate already holds every child it
admitted until it exits.
* feat(acp): open Antigravity in the Chat UI over its ACP server
With the experimental chat setting on, Antigravity chats run Google's
Antigravity ACP server, which Orca installs only when the person clicks
Install: a pinned 1.3.0 release whose archive and both executables are
verified by hash and size (macOS arm64/x64, Linux x64/arm64). A start
never downloads it.
Each host keeps one private sign-in folder for these chats under Orca's
data folder, made owner-only before every start; the server keeps its
sign-in there as a file. A chat signs in with the server's Google method
through the existing auth-required retry; with no saved sign-in the
server's sign-in prompt ends the chat signed out. The Agent Permissions
setting maps to the server's own mode, and a question the server asks
shows as a question that takes one of its choices, never auto-answered.
A chat reopens its session with session/resume.
* fix(acp): separate Antigravity chat command and require pinned host
* test(acp): assert Antigravity launch arguments across hosts
* feat(acp): Antigravity chats offer Ask, Accept edits and Full access per chat
Each mode maps to the server's own (default, auto_edit, yolo). No Approve for me:
the server has no automatic reviewer. Accept edits gets its own description,
since auto_edit approves file edit tools only.
* feat(acp): Antigravity installs from Settings and Accounts, and says its download size
The Antigravity chat server installs only when the person clicks Install. Besides
the chat's own Install card, Settings > Chat gains a Providers section and the
Antigravity accounts section gains the same install row for its host (never a WSL
distro), both following the host's install status. A host now reports its pinned
release's download size, so an idle row reads "111.5 MB download." instead of
"Not installed.".
* test(acp): the launch parity install puts the Antigravity harness beside its server
* fix(acp): Antigravity chats also drop the gcloud project variables
* fix(acp): Antigravity command rows, a refused /logout, the risky Allow Always warning, and an install that proves the server runs
- A command's line and output now show in Orca's command row: the dialect maps the server's
command_line/combinedOutput/exitCode to the shared shape and drops its duplicate output copy.
- The server's own /logout is hidden from the command list, and a message that is only /logout is
refused before it is sent: it would sign out every Antigravity chat on this host outside Orca's
sign-in gate. Dialects can now name withheld commands; the refusal has its own plain sentence.
- The server's prompt-injection warning on "Allow Always (risky)" is shown on the approval card.
- Install starts the unpacked server once under a throwaway home, asks initialize only, and keeps
the copy only if it answers as the pinned release and its process is proven stopped.
- The server runs with PYTHONUNBUFFERED=1; its environment lives beside its runtime.
- The permission mode option is found by its category, so the spec no longer names it.
* fix(antigravity): the install check accepts only the protocol version Orca's connection speaks
* fix(acp): keep the structured session create support within its line limit
Main's file already sat at the limit, so the account-home services pass inline instead of
through a variable.
* test(acp): Antigravity's launch snapshots follow main's per-chat permission launches
Main now starts ACP chats without full access and applies the chat's own mode after
start, as the Grok and OpenCode snapshots already record.
* fix(mobile): edit queued messages in place
* fix(mobile): use the platform input font size for queued edits
* fix(mobile): handle missing host support while probing queued edits
* Keep phone queued edits owned through save settlement
* Keep phone queued edits local to mounted chat
* fix(mobile): retire queued editor when its card disappears
* fix(mobile): retain queued edits while reconnecting
* test(mobile): await reconnect timer inside act callback
* fix(mobile): publish queued edit transport after commit
* test(mobile): await queued Edit inside act callbacks
* fix(mobile): hand a stale queued Save to the composer and reopen on the newer text
* fix(mobile): close an unchanged queued Save locally and keep stale typing in its own chat
* fix(mobile): explain disconnected queued edit refusal
* fix(mobile): combine queued session contract imports
* feat(acp): hosts install a managed runtime over RPC, and mark agents whose program Orca provides
managedRuntime.status / managedRuntime.install / managedRuntime.cancel, negotiated by
managed-runtime.install.v1, act on the host that receives them, the one that runs the agent's
chats, with no workspace needed. A status read naming the revision it shows is a long-poll on its
own call-queue lane, so every client sees another's start, progress and outcome.
agentSession.agents marks an agent whose program Orca provides on that host.
* fix(runtime): install status says a copy outside Orca's runs only when a start would really run it
* fix(runtime): install status is pushed to subscribers instead of long-polled, and Cancel answers with the outcome
managedRuntime.subscribe {agent} sends a full snapshot on subscribe, then one
snapshot per install state change, and closes with the transport. It replaces
the managedRuntime.status long-poll and its slot registrations.
* feat(acp): a managed runtime installs only when asked, with progress and cancel
One installation per runtime owns every change to its releases: it reclaims old ones once, first,
then installs one at a time. An install checks free space, downloads with byte progress, extracts,
hashes each member (abortable), writes the receipt, then publishes by rename, the commit point: a
cancel after it reports success. Reinstall rehashes the pinned release without downloading. A
status read waits, bounded, for a newer revision and rereads the installed release from disk.
* fix(runtime): Install repairs a damaged copy, says when unzip is missing before downloading, and reads a failed download plainly
- Install over a damaged pinned copy downloads and verifies a fresh one, then swaps the damaged
folder into staging, so there is no dead end; status reports the damaged fact.
- A host that cannot unpack the archive (no unzip) reports it in status and refuses Install
without downloading.
- A network failure while downloading reads "Couldn't download …"; the raw error goes to the log.
- Reclamation skips the whole pass when a release folder could not be read.
* fix(runtime): a status read that can't read the installed files fails instead of saying not installed, and extraction uses the extractor the preflight found
* fix(runtime): a host that can't report free disk space still installs, and says so in the log
* fix(runtime): a download that can't be fixed by retrying says so instead of blaming the network
* fix(runtime): Install unpacks the release itself, checks it starts before publishing, and Cancel answers with the outcome
- The managed install unzips in-process (fflate, bundled into main), so a host without unzip can install; the unzip preflight and the missingProgram status field are gone. The Node runtime download keeps its own extractor.
- A runtime may provide validate(): Install starts the downloaded copy once before publishing it, and an existing copy before reusing it; a failure reads "<agent> couldn't start on this host".
- No 'cancelling' phase: Cancel resolves once the work has unwound and returns cancelled, or succeeded when it had already committed.
- Byte progress every 250 ms; status rereads disk and PATH only on a first read or a phase change.
- The declared download size is checked only for an uncompressed body.
- An existing copy whose files hash correctly but whose receipt is missing gets its receipt rewritten instead of reading as damaged forever.
* refactor(runtime): move the steps that put one release on disk out of the installer
The installer class now holds only its lifecycle: the shared operation state, the one-at-a-time
queue, install, cancel, status, reclaim and progress publishing. Reusing a whole copy, the free
space check, the download, unpacking, checking each file, the start check, the receipt, the
publishing rename and the failure sentences move unchanged into managed-runtime-release-install.ts,
which gets the pin, folder, label, signal and two callbacks (progress, and the commit point right
after the rename) instead of the class. No behavior change; this keeps the installer well under
the file-length limit once Remove lands in it.
* chore(deps): lock fflate for the in-process runtime unzip
* fix(runtime): a failed download blames the release only for a proven mismatch, so a refused proxy reads as a network problem
* fix(runtime): runtime downloads skip the HTTP cache, so Remove frees the space and nothing is stored twice
The deploy's pinned-runtime download (SSH, WSL host, Windows host) passes no fetcher, so it goes
through getMainHttpClient(), which the desktop backs with Chromium's default session: system, PAC
and Orca proxy settings and proxy login apply. Guard that a plain global fetch never replaces it.
Co-authored-by: Claude <noreply@anthropic.com>
* feat(acp): ACP agents can run with a private per-process temp folder
* feat(acp): a reclamation primitive removes all but the kept managed runtime release
The installer calls it while it owns the runtime's installs and launches; it answers the entries it
could not remove so that caller can report them. Nothing calls it from adapter construction.
* feat(acp): ACP agents can declare a managed runtime that a start runs but never installs
A start resolves PATH and the agent's install folders first, then the newest whole release under
Orca's data folder (its completion receipt and member sizes checked); with none it refuses with
runtimeNotInstalled instead of downloading.
* fix(runtime): tell an unreadable runtime release from a broken one, and point a not-installed chat at the chat itself
A transient read error (EIO, EMFILE) no longer counts a working release as incomplete; only
definite absence or a mismatch does. The not-installed refusal no longer sends a remote chat's
user to this computer's Settings.
* fix(acp): a start runs Orca's installed release before a copy on PATH, and a copy elsewhere only beside every file it needs
* build(linux): carry the pinned Node inside the AppImage so orca serve's slot works offline
Linux packaging places the pinned glibc Node at resources/node-runtime/bin/node before the
glibc-floor gate, proves it serves one PTY with the packaged daemon entry, and deb/rpm exclude
it through fpm. orca serve's orcad slot copies that Node (hash-checked) instead of downloading.
* test(serve): type the bundled Node fixture
---------
Co-authored-by: m4air <m4air@Mac.localdomain>