Commit Graph
1241 Commits
Author SHA1 Message Date
buf0-bot[bot] fd07f97d64 Update README downloads badge (#41149)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-11 12:26:07 +00:00
Jinwoo Hong 818055fcbb feat(orchestration): answer workers' permission prompts from the coordinator (#40756)
* feat(orchestration): deny a worker's permission prompt, and say when mail is held

A chat worker that stops at a permission prompt now escalates with the prompt
itself as structured data (approval id, state, worker, summary, allowed
actions). The coordinator can deny it with a reason through
`orchestration deny`; the worker carries on and gets the reason as mail.
Only a person can allow a prompt: the answer method decides "person" from
the transport, never from params. The stop report keys one escalation per
approval and sends one closing line when it is answered, and no longer tells
the coordinator that `orchestration send` answers a prompt.

`orchestration send` now warns when the delivery gate would hold the mail
right now (an open prompt, a blocked status, typed text), and says delivery
state is unknown for a worker on a paired server.

* fix(orchestration): only the desktop app counts as a person for worker approvals

A paired device can carry a remote CLI, so it is treated as an agent: it can deny with a reason but never allow.

* fix(orchestration): approval answers and held receipts follow the real gates

- A same-option answer counts as Orca's only when Orca recorded it; a retry returns the same
  receipt with no second reason mail.
- An unreadable chat is not a closed prompt: the answer refuses, and the closer keeps watching.
- A closing line tells a reason only when it went to the worker as mail.
- The terminal held receipt prints the delivery gate's own refusal; the chat one prints what the
  pointer's admission and queue gate would do (not attached, refused, or behind an open prompt).

* fix(orchestration): read the held receipt only after the mail is stored

An await before the insert let a worker settle meanwhile, so the mail could land on a settled
Dispatch after its follow-up scan. The closer also removes only the approval map it read.

* fix(orchestration): tell the coordinator not to block on a worker's permission prompt

The approval escalation now says the worker is waiting for permission, tells a chat
coordinator the user has been shown Allow/Deny (a terminal coordinator: a person must
answer it in Orca or the worker), asks it to carry on with other work and not message
the worker until the answer arrives, and offers deny only as the way out when the
prompt is holding up the task. The guide and CLI docs say the same.

* fix(orchestration): a paired coordinator without an Orca session id mails a deny reason from its Run

* feat(orchestration): answer a Claude terminal worker's permission prompt

A worker pane's PermissionRequest hook now waits for Orca's answer, so the coordinator can deny
it with a reason (the worker continues) and a person can allow it. One record per waiting hook,
keyed by Claude's prompt and tool call; it is answerable only while the hook waits and the dialog
is on screen, and anything else gets `{}` as before.

* test: annotate the fake screen instead of casting

* test: wait on the hang-up instead of sleeping

* fix(orchestration): claim a terminal answer only from what Claude shows

An answer is written only while a caught-up screen still shows the dialog
in the same process run, and claimed only once Claude shows it applied: the
hook's deny line for a deny, no other close for an allow. A Yes, a No or the
2:00 auto-block that wins the race is refused and named from the screen.

A hook that hangs up is not an answer: with the dialog still up the
coordinator is told a person must answer it in the worker's terminal.

A PermissionRequest entry the user made async stays async: it prints {}
first and never waits for a decision.

* fix(orchestration): name a terminal prompt's close from its tool_result

The screen could show an older prompt's close, so who answered is now read
from the tool_result Claude's transcript records for that tool call: Orca's
own deny text credits Orca, the user's No and the 2:00 safety-check block
name themselves, and a run names an allow. Hook events cannot say this: a
deny or a No fires no PostToolUse. The screen only says whether the dialog
is still up before a write, and a PostToolUse seen mid-answer is kept.

* fix(orchestration): read a prompt's tool_result without blocking main

The transcript read is async, reads only its tail, and skips any path that
is not a regular file, so a FIFO or device cannot stall the main process.
A closed prompt still awaiting its result gets one last read when the lead's
turn stops, so a result written late still names the close.

* feat(native-chat): answer workers' approvals from the coordinator chat

A worker's open permission prompt appears as a card at the end of its coordinator's chat, drawn
from the escalation payload as soon as it is stored. The person allows or denies it there; the
card's buttons answer the worker's own prompt over the desktop app's IPC, so only a person can
allow. Once answered, the card turns into a receipt saying who answered.

* fix(orchestration): read a terminal prompt's countdown when it is first escalated

* refactor(orchestration): give a terminal prompt's hold state its own module

* fix(native-chat): let a worker's approval card answer, and drop it once it lapses

The window's runtime calls never carried the orchestration contract
version, so the card's Allow and Deny were refused as an obsolete client.
The renderer ships with its main process, so desktop IPC states the current
contract. An open card whose agent's own countdown has passed, with no
closing message (the app restarted while it was open), is no longer shown.

* test: say why the desktop fence test's runtime stub is enough

* fix(orchestration): a chat worker's approval asks to allow its tool, like a terminal worker's

* fix(native-chat): pause the approval countdown while the window is hidden

* chore(i18n): protect the approval card's worker line copy

* fix(orchestration): close a terminal prompt's card as soon as Orca can't answer it

When the dialog leaves without an answer through Orca, the closing line is
published at once, so the coordinator's card becomes a receipt; a tool
result that arrives later adds a second line naming how it closed, without
waking the coordinator. On startup, open terminal prompts left by an earlier
run are closed the same way, since their holds lived in memory. A Claude
terminal card's reason is the warning Claude prints under the command.

* fix(orchestration): keep the dialog-warning patterns ASCII for the orcad bundle

* fix(native-chat): say when a deny reason reached the worker as a separate message

A coordinator's deny reason for a chat worker whose prompt takes no message is sent
as mail. The receipt showed it the same as a reason that went with the denial, so it
now labels it 'Reason, sent as a message'.

* chore(native-chat): follow main's moved window-activity and agent-session modules

* fix(orchestration): only Orca's own reports draw approval cards, and every card closes

- Cards and the startup sweep read approvals only from rows whose id is the stop report's own
  stable id for that approval, through one shared parser; a worker's send cannot draw a card.
- A chat worker's card closes as soon as its own chat answers it (a journal watch replaces the
  turn-edge check), when an answer finds the prompt already gone, and after a restart.
- A terminal coordinator is told nobody was shown the prompt and to tell the user; the
  terminal-only close asks the same and goes out as an escalation.
- A chat coordinator's line names only the answers its card offers; a prompt with none is a
  plain prompt with no card.
- A person's Deny on a chat worker mails no extra reason.
- A record a quit or budget end closed stays closed.
- One closed-approval builder; `waitingOn` becomes `awaitsReply`.

* fix(orchestration): a failing read cannot hang an answer, fail a stored send, or fail the database open

* refactor(orchestration): add the held-send line in send-delivery-hold, keeping send-methods under the size cap

* test(orchestration): read the worker's mail with a schema, not a cast

* fix(orchestration): an open approval stays visible and closes even behind many closed ones or a missing database
2026-11-11 04:36:35 -05:00
Kelvin Amoaba 3477cb17d4 fix(agents): point DeepSeek Harness install link at the dsh-TUI it launches (#41069)
The catalog's Install link opened DeepSeek's site, which installs only
dsh. Orca launches the community @deepseek-harness-tui/dsh-tui, so users
either stayed undetected or guessed the dead unscoped dsh-tui package.
2026-11-11 07:59:05 +00:00
Kelvin Amoaba c96271dc5b fix(mobile): say Update mobile on desktop chats an old phone app can't show (#41063)
An old mobile app lists a desktop-created structured chat it cannot render
with the title 'Update to view', which doesn't say whether the phone or the
desktop needs the update. Name the phone app, and document the symptom and
recovery steps in the mobile troubleshooting docs.
2026-11-11 07:25:05 +00:00
buf0-bot[bot] 12a6326d1c Update README downloads badge (#41050)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-11 06:29:15 +00:00
Jinjing 5f3b2fa4bf feat(artifacts): allow artifact publishing by default for new profiles (#40948)
New profiles default artifactSharingEnabled to true. Existing users are
unchanged: stored settings win over defaults on load, and a stored profile
saved before the key existed loads as false instead of inheriting the new
default. The gate still requires an explicit true, sign-in is still
required, and web clients still mirror the host (their local fallback no
longer inherits the desktop default). showArtifactsButton is unchanged.
2026-11-10 17:28:29 -08:00
buf0-bot[bot] 06f97dee35 Update README downloads badge (#40940)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-11 00:39:37 +00:00
Kelvin AmoabaandYangNuoCheng c2e6ebbf0b feat(cli): read, message and wait on agent chats with orca chat list/read/send/wait (#40836)
* feat(cli): read and message agent chats with orca chat list/read/send

Carried over from #33115 (squashed onto current main; conflicts with chat rename resolved).

* feat(cli): wait for a chat to settle, read text from stdin, refuse paired hosts

chat send --wait and chat wait poll the history's working flag until the
chat is idle or waits on a question, keeping a queued message pending until
it runs. chat read is one history fetch and returns a cursor. Unattached
and paired-host refusals say what they mean.

* fix(cli): settle a held queued message, skip subagent rows, resolve chat list --worktree

* fix(cli): show chat errors, keep waiting through queue handoffs, return the whole settled turn

* fix(cli): settle any queued message the host will not send, show grouped questions and only answerable prompts

* test(cli): drive chat tests through a real client and fake timers

* fix(cli): describe chat --session, --wait and --state in command help

* fix(cli): report chat wait in chat list's states, reject unknown --state, flag truncated reads

* docs(cli): say chat wait settles on the chat's own turn; no truncated flag on held

* fix(cli): chat rename help asks for a session id, not a handle

---------

Co-authored-by: YangNuoCheng <42427439+YangNuoCheng@users.noreply.github.com>
2026-11-10 22:37:31 +00:00
buf0-bot[bot] aef89c7fca Update README downloads badge (#40817)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-10 18:21:44 +00:00
buf0-bot[bot] 2c6f84cac0 Update README downloads badge (#40763)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-10 12:25:22 +00:00
Neil 9ef5e48f09 Plugins: add editor.readTypography and editor.typography.changed (#40736)
* feat(plugins): add editor.readTypography and editor.typography.changed

Plugins that render code next to Orca's editor had to open the private
profile database and reimplement Orca's font rules to match it. Host API 1.6
adds editor.readTypography (no capability; worker, panel and editor frames):
the font family and CSS stack, size with editor zoom, weight, line height in
px, ligatures, word wrap and minimap that the file editor resolves now.
editor.typography.changed carries the same values after a settings write or
an editor zoom changes them; it is the first event that needs no capability.

The pure resolution (editor typography, editor zoom, monospace font stack)
moves to src/shared so main and the renderer use one implementation.

* fix(plugins): keep editor typography resolution from throwing in main

A hand-edited profile with a non-string font family made the shared resolver
throw, which the main-process watcher would surface at startup and on every
settings write. Font values are now type-checked, the watcher catches and
logs, and it reads live settings so a write without listeners cannot leave the
event payload stale. Over-long font families are cut to the schema bound
instead of failing every read. Regenerates the testing runtime.
2026-11-10 03:38:47 -08:00
Jinjing 1cfcd4b465 Update WeChat community QR code (#40618) 2026-11-09 19:52:40 -08:00
Brennan Benson 0d5d870800 test: isolate every vitest file on Windows to stop native heap-corruption crashes (#40200)
Shared workers (#40067) keep native addons such as the Windows process tree
and ConPTY loaded across files. Windows workers then exit with 0xC0000374
(STATUS_HEAP_CORRUPTION) in the node-server persistence lane. Production code
loads these addons lazily, so the per-file scan cannot detect them.
2026-11-09 18:11:01 -08:00
buf0-bot[bot] 959923e493 Update README downloads badge (#40561)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-10 00:38:17 +00:00
Jinwoo Hong d351b14c34 README: update star history chart (#40549) 2026-11-09 19:14:05 -05:00
Brennan Benson 55db56d989 Make Settings easier to scan and organize General (#40249)
* Simplify Settings chrome and organize General into focused views

* Preserve search and skill actions across Settings views

* Correct Settings validation leftovers

* Keep skill conflict details visible in compact Settings rows

* Refresh Settings search and protected copy catalogs

* Use Settings design tokens and button variants

* Keep Settings test setup and translation catalogs current

* Keep Settings search metadata independent of display labels

* Build repository search groups only for the selected pane

* Keep pending skill installs and server menu labels accurate

* Use the supported role locator in the skill regression

* Keep absent skill installation actions on their supported path

* Restore the Settings sidebar to its existing appearance

* Restore shared navigation title keys in pane headings

* Preserve the Settings shell entry animation

* Drop unused Voice labels after the main sync

* Preserve main Voice translations and the moved skill module import
2026-11-09 16:12:36 -08:00
Jinjing 2fca8c3e6f docs: slim CONTRIBUTING.md to the essentials (#40272)
* docs: slim CONTRIBUTING.md to the essentials for getting a PR merged

Move dev-environment reference into docs/development.md and the maintainer
release process into docs/releasing.md.

* docs: match CONTRIBUTING visual-proof guidance to the PR template

* docs: cut dev-environment internals and drop the stale release doc

Trim docs/development.md to the setup steps people actually hit, drop
docs/releasing.md in favor of the self-documenting Cut Release workflow,
and move the RC Homebrew cask into the README.

* Document Node compatibility and dev profile cleanup
2026-11-09 15:07:39 -08:00
Kelvin Amoaba f9a10a75f1 feat(native-chat): bring back the New divider behind a setting (#40490)
Restores the line above messages that arrived while you were away, the scroll to it on return and the screen-reader announcement, all removed in #38044. A new Chat > Behavior switch, "Mark new messages when returning to a chat" (on by default), turns it off; off tracks nothing.
2026-11-09 22:16:18 +00:00
buf0-bot[bot] e1b6fbe7bf Update README downloads badge (#40440)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-09 18:00:37 +00:00
buf0-bot[bot] 577a1f1fd1 Update README downloads badge (#40336)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-09 12:26:40 +00:00
Neil fc156aad4b feat(release): publish a server-only Linux tarball for orca serve (#40280)
* feat(release): publish a server-only Linux tarball for orca serve

Each release now also uploads orca-server-linux-x64.tar.gz and
orca-server-linux-arm64.tar.gz (orcad slot from the qualified template, the
pinned Node, and an orca-ide launcher) plus orca-server-sha256sums.txt, so a
Linux host can run orca serve without the desktop package.

The tarballs are packed and smoke-tested (serve --recipe-json, then pair a
second profile) on both architectures, including bare ubuntu:24.04 and
debian:12-slim containers. Upload runs only after the release is published
and nothing depends on it, so it cannot hold the desktop release.

* fix(release): keep the server tarball's launcher env out of its terminals; skip refs that predate it

- The launcher runs the CLI with ELECTRON_RUN_AS_NODE=1, as the packaged app does, and the CLI strips it
  before starting orcad; ORCA_APP_EXECUTABLE and ORCA_SERVE_RUNTIME are cleared.
- Ship Node's LICENSE beside the runtime.
- Skip packing on release refs that predate the scripts, and upload only when both tarballs passed.
- Run the PR smoke when the CLI's serve-runtime selection changes; document service install.
2026-11-09 02:36:00 -08:00
OrcaWinandOrcaWin a163b9fc5b test: remove low-value copy, inventory, and runner assertions (#40282)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 10:25:23 +00:00
Neil f358eb6a7d Plugins: add workspace.rename and project names in workspace.list (#40197)
* feat(plugins): add workspace.rename and project names in workspace.list

Plugins that name workspaces had to read Orca's private runtime token and call
worktree.set over the runtime socket, bypassing capability consent. workspace.rename
(workspace:write, worker only, host API 1.5) does the same update as a sidebar
rename. workspace.list rows gain the project name so plugins can prefix names
without reading the runtime's repo list.

* fix(plugins): harden workspace.rename against twin folders and hidden characters

Folder renames require a unique folder id, so twins on two hosts are not both renamed,
and fail when no folder has the id. Names refuse C1, bidi and zero-width characters,
which could make a label read as another workspace's name.

* fix(plugins): workspace.rename matches a sidebar rename for folders and reports kept names

A folder rename also cancels a pending first-agent-message rename, so the automatic
title cannot replace the plugin's name. A rename Orca does not apply (during a WSL
move) is a conflict instead of a silent success. workspace.list's project is optional,
so mocks written for host API 1.4 still validate. More invisible characters are refused.
2026-11-09 00:48:33 -08:00
Kelvin Amoaba 6c07eac31c fix(speech): move OpenAI dictation to gpt-transcribe before the gpt-4o models shut down (#40159)
OpenAI shuts gpt-4o-transcribe and gpt-4o-mini-transcribe down on
2027-02-26. Offer GPT Transcribe instead, retire both old entries so a
saved choice loads as the new model, and send the language hint as
languages[], which gpt-transcribe takes in place of language.
2026-11-09 06:37:29 +00:00
Jinjing 7c1483278b Reduce excessive tooltips and clarify action details (#39960)
* wip

* rm execessive tooltip

* Clarify deletion options and improve resource popover layout

- Show the scope of persistent deletion choices directly in the menu
- Keep resource details accessible in short windows
- Style disabled dropdown actions consistently

* Clarify detached commits and deletion guidance

* Preserve translated tooltip guidance
2026-11-08 21:53:12 -08:00
Kelvin Amoaba 80a9ed69f0 fix(native-chat): move open Codex chats to the account you switch to (#40148)
A Codex chat launched codex app-server on the account home saved when the
chat was created, and nothing compared it with the selection, so after a
switch every message kept going to the old account. A chat that had hit
its usage limit kept failing with "Codex hit its usage limit" even though
the new account had quota.

Codex chats now follow the selection the way Claude chats do: the launch
prepares the selected account's home, the started process reports that
home, and the host replaces an idle chat whose account no longer matches
before its next message. Codex resumes a thread only from a rollout in its
own CODEX_HOME, so the launch links the thread's rollout into the new home
first. The chat's usage card reads the account its next turn runs on.
2026-11-09 05:15:37 +00:00
Jinjing 74106a0dbc Add protected telemetry milestones (#40043)
* Add protected telemetry milestones

* Fix milestone provenance and acceptance

* Fix telemetry test lint suppression

* Relay remote accepted chat prompts to desktop telemetry

* Honor paired desktop consent when chat host runs telemetry

* Fix mobile typecheck for notification retry timer
2026-11-08 16:58:21 -08:00
buf0-bot[bot] d5aa74110d Update README downloads badge (#40045)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-09 00:42:33 +00:00
Neil e1381cfa3e Rotate the server pairing identity when ORCA_INSTANCE_ID changes (#39217)
* Rotate the server pairing identity when ORCA_INSTANCE_ID changes

* Back up replaced identity files, keep the recorded id on reset, keep staged files once the rotating marker is published

* Add identity-reset files to the sync fs baseline and document the backup folder

* Report a reset honestly after finishing an interrupted rotation; keep first backups and the newest one
2026-11-08 16:35:43 -08:00
Jinjing 9b9363f4fb update log efficiency (#40011)
* docs: define protected telemetry dashboard migration

* docs: clarify activation workspace availability rule
2026-11-08 15:05:32 -08:00
buf0-bot[bot] 1af2a4b804 Update README downloads badge (#39922)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-08 18:20:37 +00:00
Jinjing 9a1c3a362d more accurate chat ui invocation count (#39784)
* rm doc

* wip

* wip

* wip

* wip

* wip

* Handle opening message receipt collisions
2026-11-08 00:40:56 -08:00
buf0-bot[bot] 83a3d33681 Update README downloads badge (#39760)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-08 06:26:44 +00:00
Jinjing 18eadb8628 Reorganize the worktree context menu (#39739)
Group related actions into submenus and clarify the scope of sleep and
delete actions for workspaces with descendants.
2026-11-07 22:05:03 -08:00
Jinjing ef55da8770 docs: add WeChat community group QR codes (#39411) 2026-11-08 00:10:19 +00:00
buf0-bot[bot] 97f0dd7a04 Update README downloads badge (#39561)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-07 18:20:34 +00:00
Neil c0e8e4e6eb docs(plugins): theme background video ships in 1.4.254 (#39478)
#39450 merged after the 1.4.253 cut, so the videoPath since-version and the
theme reference name 1.4.254.
2026-11-07 03:49:08 -08:00
Neil b0dd73e7aa feat(plugins): play a looping video behind app themes (#39450)
App themes may set background.videoPath: a muted, looping MP4 or WebM (H.264
recommended, VP9 or AV1; one video track, no audio; <= 60 s, 8 MB, 2.3 MP)
played over the required static background.path. Main checks it from container
headers without decoding and serves it on the orca-plugin-image slot
theme-<i>-video; images stay static-only. The renderer reveals it on its first
frame, keeps the still on any failure or a decoded size past the limits, plays
it only while main reports the window focused, shown and not minimized and no
dialog is open, and omits it under prefers-reduced-motion.

Animated WebP was measured and declined: software-decoded every frame, it cost
11-23 points of CPU vs 3-10 for the same loop as video.

Implements #38363 proposed by @dohaidang.
2026-11-07 03:32:14 -08:00
Neil 35975c0580 feat(themes): theme tokens for chat text styling and a readable chat selection (#39432)
* feat(themes): public plugin theme tokens for chat text and selection

Themes can now set chat bold text, muted text, inline code, code blocks and
the chat selection. Omitted tokens paint exactly what chat painted before,
except the selection, which now keeps selected text 4.5:1 by default.

* docs(themes): note the bubble and code-block checks for chat text tokens

* fix(themes): never lower the chat selection under its visible floor
2026-11-07 03:02:23 -08:00
Neil 51f3c956ed feat(plugins): let plugins ship web fonts for the terminal, editor and interface (#39416)
* 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.
2026-11-07 02:08:35 -08:00
buf0-bot[bot] 3d8a285132 Update README downloads badge (#39291)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-07 04:51:25 +00:00
Neil 3c866a31db feat(serve): refuse public source addresses on orca serve unless allowed (#39207)
* feat(serve): refuse public source addresses on orca serve unless allowed

`orca serve` listens on every interface. It now accepts connections from
loopback, private LAN (10/8, 172.16/12, 192.168/16, 169.254/16, fc00::/7,
fe80::/10) and Tailscale (100.64/10, fd7a:115c:a1e0::/48) sources, and drops
public-source TCP connections before HTTP parsing or the WebSocket upgrade.

Public sources stay accepted when:
- --allow-public is passed (orca serve, orcad, serve service install);
- a paired device has authenticated from a public address (persisted flag);
- --pairing-address is a hostname or a public IP literal;
- any device paired before this server first ran the check is still paired.

The startup log states which rule applies; the first refused public address
each hour is logged with the flag name. Desktop listeners and Orca Relay are
unaffected.

* feat(serve): accept on-link public addresses and add --refuse-public

A public source inside a prefix of one of this host's own interfaces (os.networkInterfaces, re-read at most every 5 s) is a same-network peer, such as a LAN client using global IPv6, and is now admitted. Prefixes wider than /16 (IPv4) or /48 (IPv6) are ignored.

--refuse-public (orca serve, orcad, serve service install) refuses public addresses regardless of grandfathered pairings, a remembered public connection or the pairing address; it cannot be combined with --allow-public.
2026-11-06 17:02:15 -08:00
047e113783 feat(cli): pair clients with a running Orca via orca pair (#36469)
* feat(cli): pair clients with a running Orca via `orca pair`

A headless Orca could only print a pairing offer at startup, so pairing a
phone with `orca serve service install` meant stopping the service. `orca
pair` asks the running runtime for an offer over the owner's local socket
through a new `pairing.createOffer` method (pairing-admin, never granted to
paired clients or phones). It reuses the desktop's offer logic, now shared
by the Settings IPC handlers: mobile offers stay LAN-only unless --relay,
and the first network pairing widens a loopback bind as the desktop does.

Also honor an explicit ORCA_SERVE_RUNTIME=orcad on packaged macOS. Electron
serve needs a desktop login and aborts in an SSH session with nobody logged
in; orcad is plain Node and serves there, at the cost of no in-app updater.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(cli): move the serve-restore and pair handler groups out of the manifest

handler-group-manifest.ts was already at the 300-line limit on main, so
adding the pair group failed lint. Group the two serve/pairing entries in
their own file, as jira, linear and reference already are.

* test(mobile): pin the desktop pairing IPC handlers' replies and runtime calls

Characterizes mobile:getPairingQR and mobile:getRuntimePairingUrl across
every branch (explicit and default address, LAN-only with no address,
Relay without an address, relay failures, this-computer reach, widening
and its failure, unavailable offers). The same file passes unchanged on
main and on this branch, so moving the offer logic into
pairing-offer-requests.ts did not change the desktop path.

* test(mobile): type the QR stub instead of casting it

---------

Co-authored-by: Office exitnote <h@Offices-MBP.lan>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Neil <neil@stably.ai>
2026-11-06 17:01:32 -08:00
Kelvin Amoaba a3a0e68380 fix(packaging): require macOS 13.4, the minimum the on-device speech engine runs on (#39135)
* fix(packaging): require macOS 13.4, which the bundled speech engine needs

* fix(updater): keep the macOS requirement title clear of the close button

* fix(packaging): check out the Darwin floor table for adhoc builds and raise the cask floor

* refactor(updater): reuse the parsed Darwin floor for the macOS requirement

* fix(updater): use a margin to keep the macOS requirement title clear of the close button

* fix(updater): say the macOS requirement comes from Electron and the speech engine
2026-11-07 00:18:50 +00:00
0b5a293fa2 feat(serve): add bind address option (#35095)
* feat(serve): add bind address option

* fix(serve): validate service bind address

* fix(serve): validate bind flag values

* fix(serve): reject scoped bind addresses

* docs(serve): document bind option paths

* docs(serve): note that --mobile-pairing needs an all-interfaces bind

* fix(serve): move bind address parsing to shared so the packaged CLI can load it

The packaged CLI ships out/cli and out/shared but not out/main/orcad, so
cli/runtime/serve-bind-flag.js failed the packaged runtime-import check
(and would fail to load) when it imported main/orcad/orcad-bind-address.
Move the module, unchanged, to src/shared and point orcad, Electron serve
and the CLI at it.

* test(serve): pin down the default listener and the --bind startup paths

- Extract the Electron serve listener pin into resolveServePinnedBindHost
  and test that serve without --bind stays unpinned (all interfaces, as
  before), an explicit --bind pins it from either argv form, and the orcad
  browser sidecar stays on loopback.
- Golden the orcad and Electron serve argv without --bind against the
  pre---bind output.
- Test that the CLI passes bind only when given and refuses --bind with
  --mobile-pairing before launching.
- Guard that serve-bind-flag and the shared serve validation load only CLI
  and shared modules, which is what the packaged CLI ships.

---------

Co-authored-by: lw <13579959+bertramlongwuyan@user.noreply.gitee.com>
Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: xuanchangfeng <210147232+xuanchangfeng@users.noreply.github.com>
2026-11-06 15:47:42 -08:00
Neil de80cd74c0 fix(agents): list agents found through a custom command path (#39178) 2026-11-06 14:52:08 -08:00
Neil be3b87f3ac cli: add orca plugin install, update, uninstall and catalog list/add/rm (#36647)
* cli: add orca plugin install, update, uninstall and catalog list/add/rm

* plugins: escape the invisible-character regex so the orcad bundle stays ASCII

* plugins: split approval re-run helpers and plugin RPC binding to stay under max-lines
2026-11-06 14:20:27 -08:00
Neil f0bfce8fce fix(automations): accept Antigravity model and effort extra arguments (#39161)
Antigravity automations refused --extra-agent-args, so unattended agy jobs
could only use the model and effort from agy's global settings.json. Allow
--model and --effort through the existing allowlist; permission, mode, and
other flags stay refused.

Part of #35234 (STA-12678).
2026-11-06 12:55:54 -08:00
Neil a20e577dc9 feat(antigravity): manage accounts in the selected WSL distro (#39007)
Antigravity Accounts rejected a WSL account location outright. agy inside
WSL keeps its login in its file store (~/.gemini/antigravity-cli/
antigravity-oauth-token; it detects WSL the same way
isAntigravityFileStorageHost does), so save/select/remove now work there:

- A WSL credential backend reads and writes that file through runWslProcess
  in the selected distro (default resolved via resolveWslDefaultDistro). It
  checks the distro is running before every guest command and never starts a
  stopped one. Writes are a compare-and-swap inside the guest (sha256 of the
  expected file), go through a private temp file and rename, and pass the
  credential on stdin rather than the command line.
- runWslProcess accepts stdin input for argv-delivered commands.
- Each distro gets its own encrypted vault, so accounts never cross distros
  or the Windows host.
- Accounts "Refresh usage" is enabled for WSL now that usage reads the
  selected runtime (#38985), and rejects a reading tagged with another
  runtime's provenance.

Fixes #25847
Linear: STA-9624
2026-11-06 12:54:20 -08:00
buf0-bot[bot] 76e4769cf7 Update README downloads badge (#39125)
Co-authored-by: buf0-bot[bot] <252831055+buf0-bot[bot]@users.noreply.github.com>
2026-11-06 18:23:29 +00:00