mirror of
https://github.com/stablyai/orca.git
synced 2026-11-03 18:47:40 +00:00
785daec1e14b4fd11c57f731bb5199742befd879
17
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e268135719 |
feat(native-chat): chat agents are offered wherever their chat program runs, not only where their CLI is installed (#28709)
* feat(acp): ACP agents can declare a managed runtime installed on first chat start An ACP launch spec may name a pinned runtime Orca installs under its locked data folder. The stock lookup searches it last (Command, PATH, install directories, managed folder); a start whose lookup missed installs it under the acquisition's signal, then resolves the launch again. A Command setting, restart-recovery reads and catalog probes never install. The pinned-runtime materializer can now publish a verified multi-member folder: extract once into staging, check each member's sha256, rename into place, with a per-asset download size limit. Node's runtime path is unchanged. * Fix ACP managed runtime lookup precedence * feat(acp): ACP agents can run with a private per-process temp folder * feat(acp): old managed runtime versions are removed at host start Once per host start, the ACP registration removes every version beside an agent's current managed runtime folder, and staging left by an earlier process. One host owns the data root and ACP servers are never reattached across host runs, so nothing runs from them. This process's own staging is kept (a publish may be in flight). Best effort: a failure is logged and never holds up a launch. * feat(acp): a sign-in prompt on an ACP agent's stderr ends the start or turn signed out An agent that waits for a browser sign-in prints a link on stderr and blocks for minutes. A launch spec can now name that line (signInPrompt); the connection then closes with a typed sign-in failure through the existing process owner, so a start reads notSignedIn and a running turn fails signed out instead of settling unknown. The matched line, which carries the sign-in URL, never enters the retained stderr tail, errors or diagnostics. * Prevent sign-in URLs leaking from long stderr lines * feat(acp): an agent can enforce the permission mode itself through a session config option An optional launch-spec field names the session config option and its ask/full values. Every new or reopened session gets the value for the chat's full-access posture before it is exposed, and a refusal fails the start. With the field present Orca no longer answers permission requests for the person. No agent sets it yet. * fix(acp): reject unconfirmed permission mode during acquisition * feat(acp): an agent enforcing the permission mode itself runs the chat's own mode The launch spec maps each chat permission mode to its session option value; a start sets the value for the mode the host launches with (ask when it names none), replacing the global Agent Permissions full-access read. A mid-chat change takes effect through the host's existing restart of a child launched with another mode before the next send. * Keep ACP session acquisition within the line limit * 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 on the first chat start: a pinned 1.3.0 release whose archive and both executables are verified by hash (macOS arm64/x64, Linux x64/arm64). 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(native-chat): offer host-provided chats without their CLI detected A host now marks each agentSession.agents row whose chat program Orca provides there (an ACP managed runtime with a pinned build on this host). With Chat UI on, the tab-bar picker, the empty-workspace default chat and the new-agent shortcut offer those agents beside the detected ones when the launch opens as a chat. Terminal launches still follow detection, and an older host that sends no mark keeps today's detection-only offer. * Fix CLI-free chat fallback and picker updates * Fix admission refusal reason test expectation * feat(native-chat): the host health snapshot says whether each chat's program is on the machine Antigravity's chat runs Orca's own download of Google's ACP program, not the agy CLI, so clients could not tell from CLI detection whether it can open as a chat. Each snapshot row now carries an optional chatProgram (available, installable, missing, unknown), found through the agent's own launch resolver without spawning anything, and re-derived after a managed runtime install or removal. Health state and reason are unchanged, so older clients decode the frame as before. * feat(native-chat): one renderer reading of whether an agent can open as a chat on its host Pickers asked CLI detection whether an agent can open as a chat, which is wrong for Antigravity, whose chat runs a program Orca downloads. This module answers from the host's published chat program fact, and for hosts that publish none, from the host's managed-runtime mark and install capability or else CLI detection. Facts not yet learned read as unlearned, not as no. * fix(native-chat): a declined chat opens its agent's terminal only where the CLI is installed Once a chat can be offered without its CLI, a host refusal used to fall back to a terminal that runs a CLI that is not there. The one admission boundary now reports the host's refusal instead when the workspace host's detected agents lack the CLI, for new-tab, work-item and workspace creation launches alike. A caller's own fallback, like the empty workspace's shell, still opens. * feat(native-chat): the + menu and Settings offer a chat wherever its program runs With Chat UI on and no agy CLI, Antigravity had no chat row in the + menu (or a disabled 'Not installed' one when switched on), because both read CLI detection. The menu now reads the host's chat-program answer: a chat row where the program runs or installs from the chat, no '(CLI)' row or terminal button without the CLI. A failed CLI check no longer keeps the menu from learning that answer. Settings shows an unchosen provider on when its CLI or the program Orca runs for it (downloaded or found outside Orca) is installed, and holds the switch until that is known. A saved default that opens as a chat no longer says it is not detected. * feat(native-chat): a default agent that opens as a chat starts without its CLI An empty workspace and the new-agent shortcut skipped a default agent whose CLI is not detected, even when it opens as a chat on that host (Antigravity without agy). Both now honor that default, waiting briefly for the host's chat facts when they are not known yet, while the automatic pick with no default still chooses only detected agents. Blank and the shell fallback are unchanged. * feat(native-chat): new workspaces, work items, continuations and the dashboard offer chat-only agents The new-workspace composer, work-item launches, session continuation and the dashboard launcher listed only agents whose CLI is detected, so an agent that opens as a chat without its CLI could not be picked, and an explicit pick of it was dropped. They now also offer agents that open as a chat on the workspace's host, keep such an explicit choice, and the dashboard republishes when the host's chat facts arrive. Automatic picks still choose only detected agents. * feat(native-chat): Source Control and Fix Checks accept a chosen agent that opens as a chat The Source Control action dialog, its saved auto-start, the checks panel, recovery launches and Fix Checks (before and after its workspace exists) rejected a saved or default agent whose CLI is not detected, even where it opens as a chat. They now accept it there and list it, through the shared source-control pick, while the automatic pick still chooses only detected agents. * fix(native-chat): an empty workspace does not wait on chat facts for a Claude or Codex default Claude and Codex have no program Orca downloads, so without their CLI only the host's own answer could offer them as a chat; holding the workspace empty for the host's agent list could not change that. * test(native-chat): pin the chat-program fact, cold explicit defaults and the CLI-less decline Covers the host's program lookup and its re-read after an install, older and unknown snapshot values falling back to the managed mark and install capability of the same host, an explicit default opening as a chat with CLI detection failed while automatic and blank picks stay on detected agents, kept composer and saved Source Control choices, and a declined chat reporting the refusal instead of opening a terminal for a missing CLI on both launch paths. * refactor(source-control): the action dialog's agent list lives in its own hook The dialog hook was over the file-length limit after it learned which agents open as a chat without their CLI; detection and that offer now live together in use-source-control-launchable-agents. * fix: typed test mocks and record the dialog's pre-existing reset effect The Source Control dialog's open-cycle reset effect was already on main; the changed-code gate reported it because the effect now also learns which agents open as a chat. * fix(native-chat): a declined chat refuses its terminal only when the CLI is known to be missing When a host declines a chat, Orca falls back to that agent's terminal. A chat can now be offered without its CLI, so the fallback must not open a terminal that cannot start. But a failed or still-pending CLI check is not proof the CLI is missing: treating it that way blocked a working terminal fallback (for example an OpenCode version that runs in a terminal but not as a chat). Each detection producer (local, paired server, SSH) now records the outcome of its latest attempt for the exact target, next to the IDs it already keeps. The decline check refuses the terminal only when the same host's latest attempt succeeded and did not list the CLI; pending, failed or unresolved outcomes keep the existing fallback, and a caller's own shell fallback is untouched. * fix(native-chat): every launch surface learns whether a chat opens before it decides A chat whose program runs on the host without its CLI (for example Antigravity) could be missing, greyed out or swapped for another agent depending on which surface launched it: the composer dropped an explicit pick while the host was still answering, Fix Checks and the Checks panel refused a saved chat agent, an inactive paired host was never asked about its chats, the Providers switch flashed off, and session continuation auto-picked an agent that was only offered. One lease per host, runtime and pairing now acquires the host's agent list and health stream for whoever needs it: the + menu, composers, Settings, the dashboard and its pop-out, Source Control and Checks, Fix Checks, work items, shortcuts and continuation. Actions wait for those facts within one bounded deadline (ordinary CLI detection keeps its own wait), cancel when the workspace's host is genuinely replaced, and re-read settings before launching. A saved, default or explicit choice may open as a chat without its CLI; automatic picks still come only from detected agents. Pending or unknown facts never erase a choice or flash a switch off. The dashboard's holds are reconciled by the publishers that read them, and a hold that notifies while it is being created no longer leaks a second stream holder. * fix: the new-workspace composer memoizes its launch workspace from its own fields * fix: a declined chat reads the launch host's own agent inventory; test fixtures match their types * fix: work-item launches detect before waiting on chat facts; the composer and Source Control list agents from one owner The composer card no longer holds its own chat-facts lease beside its modal's, Source Control reads agent inventory only while its dialog is open, and a work-item launch keeps the new workspace's own detection when the store has not loaded that workspace yet. * fix(native-chat): keep acquisition tied to the current host resource * fix(native-chat): verify the current acquisition before returning choices * fix(i18n): retain legacy terminal-list English entries in the runtime catalog * fix(native-chat): the dashboard republishes launch options when the active workspace's host changes Both dashboard publishers now watch the active workspace and its selected host, which own its launch options. Two QuickLaunchButton tests assert the current "couldn't list terminal agents" wording. Restores base forms and drops a duplicate workspace helper to stay inside the change budget. * test: the dashboard publisher test reads its watched state from the function it tests * fix(native-chat): dashboards watch one checked route-input view; saved Source Control discovery settles every outcome Both dashboard publishers observe and derive launch options from one exhaustive, compiler-checked view of the store slices the launch-route readers take, so a route input can no longer be missed by one list. A saved Source Control action's discovery now ends as success, cancelled or failed; only success can auto-start, and a cancelled or failed attempt reveals the editable dialog instead of launching on a replacement runtime. Restores base forms and shares one worktree workspace helper to stay inside the change budget. * style: format the runtime metadata resolver * fix: merge duplicate imports the code-quality gate rejects * test: the dashboard watch fixture seeds every route-input field * test: the dashboard watch fixture is fully typed without a cast * fix: an unknown agent scan stays unknown for Fix Checks and recovery, and a saved Checks agent keeps its message * fix: the action-first chat path asks the same missing-CLI check before opening a declined terminal; compact to the size cap * refactor: compact the chat-program changes to the size cap after merging main * Pickers list an agent that can't open here as disabled with its reason instead of hiding it The Create workspace and continuation pickers only searched the agents the caller could launch, so an enabled agent with no chat on this host (for example Antigravity when the host can't run it) lost its disabled row, while the + menu showed it. * Continuation test accepts more than one disabled subfolder row now that disabled rows are listed * Re-run CI: the code scan was cancelled across the repository * test: cover chat selection without terminal CLI * test: compact host chat program fixtures |
||
|
|
554862d671 |
refactor(orcad): use the shared error and liveness helpers instead of local copies (#31654)
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. |
||
|
|
a439dfa451 |
fix(runtime): detect Linux libraries reliably across SSH and WSL (#31077)
* fix(ssh): detect glibc on Synology hosts without ldd * fix(runtime): share robust Linux library detection across SSH and WSL * docs: remove Synology reproduction notes |
||
|
|
66d37178da |
feat(ssh): let a nodejs.org mirror serve the pinned Node on this computer and the host (#30981)
* 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 |
||
|
|
b6eee3e981 |
fix(ssh): download the pinned Node on the host when this computer can't reach it (#30945)
* 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 |
||
|
|
c0202b460c |
test(node-runtime): skip retry pauses in the refused-download test instead of faking timers (#30967)
Under CI's bun runner the fake-timer loop ran out of turns before the retries finished, and the test hung to its 30 s timeout. |
||
|
|
f1135dd4ca | fix(ssh): say when this computer can't download Node for a managed server, and where an offline copy goes (#30911) | ||
|
|
6fd2172b3f |
feat(runtime): remove an agent's downloaded runtime only once nothing on the host can still run it (#29139)
* 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.
|
||
|
|
2117d777be |
feat(acp): Antigravity in the Chat UI over its ACP server (#28595)
* 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. |
||
|
|
58f1f7de1e |
fix(mobile): edit queued messages in place (#28646)
* 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 |
||
|
|
634ca45fbb |
feat(acp): hosts install a managed runtime over RPC, and mark agents whose program Orca provides (#29024)
* 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.
|
||
|
|
99788a91fa |
feat(acp): a managed runtime installs only when asked, with progress and cancel (#29023)
* 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 |
||
|
|
dbe85f6da3 |
test(orcad): pin that the Node runtime download uses the main HTTP client (#29828)
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> |
||
|
|
48d080e971 |
feat(acp): a reclamation primitive removes all but the kept managed runtime release (#28507)
* 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. |
||
|
|
76735edf31 |
feat(acp): chat agents can declare a managed runtime that a start runs but never installs (#28460)
* 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 |
||
|
|
49a1129aa6 |
build(linux): carry the pinned Node inside the AppImage so serve's slot works offline (#28204)
* 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> |
||
|
|
4ad0129984 |
refactor(orcad): orcad artifacts live under orcad/ and node-runtime/ (#27963)
Co-authored-by: m4air <m4air@Mac.localdomain> |