Commit Graph
1096 Commits
Author SHA1 Message Date
Brennan Benson 175f10e32b Run local usage services in a supervised backend process (#40792)
* Move local usage services into a supervised backend process

* Own usage recovery and worker retirement lifetimes

* Preserve answered usage data during background refresh

* Run independent usage scans concurrently in the backend

* Limit backend startup paths to the delegated usage service

* Show usage failures through backend recovery

* Include usage failure strings in the English catalog

* Keep usage update details beside refresh failures

* Resolve usage freshness failure from the final producer snapshot

* Retain the forced refresh completion requirement

* Keep managed backend failures out of application crash reports

* Preserve usage recovery boundaries across backend reconnects

* Match the backend RPC cancellation signal in the usage seam proof

* Avoid serializing backend requests before port delivery

* Keep receiving request validation in the boundary schemas

* test: align usage transport coverage with renderer project

* fix: preserve unknown usage state and renderer retirement

* fix(usage): revalidate tracking before scan admission

* fix(usage): retry failed backend startup on demand

* test(usage): isolate stale backend ownership checks
2026-11-11 16:39:52 -08:00
Kelvin Amoaba b72ef23702 fix(native-chat): refuse a startup card choice when the terminal highlight moved, and add the multi-server MCP card (#41216)
* fix(native-chat): refuse a stale startup-dialog card choice and add a card for the multi-server MCP dialog

* fix(native-chat): drop casts from the startup-dialog guard

* fix(native-chat): refuse a startup card choice until the screen model has applied all received output

* fix(native-chat): refuse a clipped MCP server list and guard restored startup cards

* fix(native-chat): allow one startup card choice per screen so a second client's keys can't hit the next dialog
2026-11-12 00:10:05 +00:00
Kelvin Amoaba cab41b4075 fix(browser): tell agents when a page waits on a passkey, and let them cancel it (#41048) 2026-11-11 23:27:38 +00:00
Brennan Benson 576a6c9342 Update browser navigation state without blocking page attachment (#41045)
* Keep browser chrome metadata current without synchronous guest reads

* Provide the guest Escape subscription in browser pane fixtures

* Provide native navigation state in browser guest fixtures

* Preserve browser navigation and loading across asynchronous metadata reads

* Retire browser metadata when its actual guest is removed

* Explain native identity casts in browser disposal fixtures

* Preserve URL titles for untitled client browser pages

* Preserve current browser navigation and untitled page labels

* Keep merged browser failure type within lint limit

* Keep merged browser failure type within lint limit

* Bound published browser titles to the existing wire limit

* Use template literals in browser title regression
2026-11-11 12:38:19 -08:00
Kelvin Amoaba 04537aabc6 fix(ai-vault): Session History Hand Off gives OpenCode sessions their full history (#41236)
OpenCode, OpenCode 2 and Z Code keep every conversation in one shared
database, so Session History could only hand off the row's preview
messages. The session's own host now copies that one conversation into
the per-chat hand-off snapshot the chat Hand Off already uses, and the
dialog points the new agent at it. Older hosts, SSH rows and failed
reads keep the preview.
2026-11-11 20:06:53 +00:00
Kelvin Amoaba 215197f46d fix(editor): live-update tabs reached through a symlinked folder (#41075)
The workspace watch never follows a symlinked folder, so a tab opened
through one (target outside the root) got no change events. Watch each
such tab's folder directly; main checks for the link with an lstat walk
and already rewrites the folder watch's events to the link spelling.
2026-11-11 08:12:54 +00:00
Jinwoo Hong 5e342d7e1a fix(orchestration): a worker report during an Orca restart is not rejected as a changed identity (#41014)
* fix(orchestration): a worker report during an Orca restart is not rejected as a changed identity

* refactor(orchestration): share the startup bounded wait; skip long-poll checks

* chore(orchestration): drop casts in the restart identity wait

* fix(orchestration): only long-poll checks skip the restart identity wait

* fix(orchestration): ordinary mail never waits for the restart identity restore
2026-11-11 00:59:18 -05:00
Neil 45b433671e fix(recipes): show credentials recipe scripts inherit, add opt-in passEnv allowlist (#40757)
* fix(recipes): warn which credentials recipe scripts inherit, add opt-in passEnv allowlist

Recipe lifecycle scripts run locally with Orca's full environment. Keep that
default (provider CLIs and git auth rely on it) but name the credential-like
variables in Settings and let a recipe opt into passEnv so only listed
variables plus a safe base set reach its scripts.

* fix(recipes): fail closed on a malformed passEnv instead of dropping the recipe

Dropping the recipe let a stored snapshot or a same-id plugin recipe run with
the full environment. Keep it with an empty allowlist and a diagnostic, match
base variable names exactly outside Windows, and make the warning copy apply
to any recipe source.

* fix(recipes): import user-agent-platform from its new app-shell location
2026-11-10 17:58:06 -08:00
Brennan BensonandClaude Opus 5.5 8ac9fb6eee Stop re-reading every linked GitHub issue when the window returns (#40534)
* fix(github): stop re-reading every linked issue when the window returns

Each window reveal re-read the linked GitHub issue of every workspace, shown or not,
through the shared 4-slot gh queue, so PR, Checks and Merge waited behind hundreds of
issue reads, and above 500 linked issues the cache thrashed on every reveal.

Surfaces that show an issue now own its freshness: the reveal handler no longer sweeps
the catalog; workspace cards keep their own visible-only issue poll, now also in the
paired web client and for folder workspaces; the space manager's decision hover polls
its one issue while open.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(space): the open space-manager hover asks the main window to refresh its issue

The desktop Space window shows the main window's published issue cache, so a read done
in the Space window was overwritten by the next snapshot. The decision hover now owns
its issue's freshness only while open, follows the live link, and asks the main window
(the cache owner) to re-read it; the web client reads in place.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(space): route the hover's issue refresh by window and follow owner changes

Choose the main-window relay only in the separate Space window (the paired web client's
fallback API made the relay look available), and refresh when the worktree's owning host
changes, not only its link.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(space): key the open hover's issue refresh off the row projection

The hover re-resolved its worktree owner from the store on every Space-window snapshot,
rebuilding the catalog lookup index each time. Use the cache key the row projection
already computes for the issue it shows.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(space): use typed fixtures in the hover freshness test

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-10 16:46:16 -08:00
Brennan Benson fd20d34362 Save the issue title on GitHub issue links made without one (#40853)
* fix(github): title GitHub issue links that were saved without one

A workspace linked to a GitHub issue from the CLI (`--issue N`), a phone, the paired web
client or a typed number kept only the number, so search could match its issue title only
while a client happened to hold that issue. The host that owns the workspace now reads each
newly linked untitled issue once, after the write returns, the way its card would, and saves
the title on the link. It keeps the current review selection and never resurrects a removed link.

* fix(github): bound and publish issue-title fills like other metadata writes

Skip writes that leave links untouched before normalizing, check a queued link is still wanted
before reading it, publish filled titles once per repo per 2 s window, refresh the resolved rows
remote clients read, never wake a stopped WSL distro for a background read, keep a selected
review's PR suppression, and keep a failing write observer from failing a saved write.

* fix(github): keep link-title fills off unrelated writes and out of per-title refreshes

Ignore linkedWorkItem in the unchanged-links check (it is rebuilt on every write and always
titled), publish filled titles at once on a quiet host and at most once per repo per 30 s
during a burst on a timer, and only lift a PR suppression when the selected PR changes, so
restating the current PR (as a title fill does) keeps a hidden branch PR hidden.

* perf(github): publish filled link titles as addressed workspace metadata

Instead of a whole-repo worktreesChanged refresh per burst window, the host publishes one
addressed workspaceMetadata set record {hostId, epoch, seq, id, row} for the workspace whose
link was titled: to its desktop window over IPC and to paired clients as a runtime client event.
Clients patch that one row (Cmd-J reads it) and drop replayed records; older clients ignore the
new event and see the title on their next listing.

* fix(github): agreed workspaceMetadata record shape, per-id seqs and late-listing refill

Records name their kind and domain, clients keep the last applied seq per workspace for each
producer epoch (dropped when the epoch changes), and a listing that read metadata before the
title write cannot drop the title: recorded titles refill rows that still hold the same untitled
link for 60 s, never restoring a removed link. The IPC channel is marked as interim transport.

* fix(github): title-only, host-addressed application of workspaceMetadata records

Clients fill the record's issue titles into the named row's still-untitled links and never take
its links over the row's current ones, so a record that arrives after an unlink cannot restore
the issue. A paired host's records reach the row of their own execution host (an SSH twin is a
different row), and go through the bridge's connection-generation check like other host events.

* test(github): type the metadata-record test helper as AppState

* fix(github): keep recorded titles until expiry, refill only changed repos, retire with the pairing

A record that beats the listing adding its link keeps its titles for the full window; the refill
runs only for repos whose listing changed, indexes that repo's rows once and skips rows already
checked; per-workspace seqs live in the expiring entries; a re-pair or reconnect of the producing
environment retires its titles.

* fix(github): read the listing through the workspace record selector

* fix(github): keep link titles until their producer changes; fall back to a listing on eviction

Recorded issue titles no longer expire on a timer (a slow listing could outlast it): they live until
the producer's epoch, pairing or connection changes, refilling only present untitled links. When
more than the cap are in flight the oldest is evicted and its repo is listed afresh, which carries
the saved title. The refill runs in updater form so it never merges a stale store snapshot.

* fix(github): sequenced listings replace the retained-title refill

Per the re-plan ruling: the store keeps one workspaceMetadata cursor per process; a title record takes
the next seq in the same turn as its write, and each listing records the cursor when it reads metadata.
Clients note each record's seq per producer and repo; a listing at or past it ends the obligation, an
older one keeps titles the rows already show and lists the repo afresh (a new invocation, never joining
the stale one), a record whose row or link isn't listed yet asks for a fresh listing, and a seq gap
lists every repo of that producer. The retained-title table, its watcher, TTL and cap are gone.

* test(github): stamp capture, gap, restart and recovery coverage for workspace metadata listings

Also retire an environment's earlier coverage bookkeeping when it is re-paired or reconnects.

* fix(space): keep issue-title coverage per repo and host until a newer listing lands

Coverage now keeps each projection's newest record seq after its covering listing settles, so an older listing that finishes later still keeps shown titles. Projections are keyed by repo and host, paired producers keep their stream cursor, retired pairings and unlisted projections are dropped, every listing served by this host carries its metadata stamp, and a record with any unlisted titled link asks for a listing.


* fix(space): re-list after any stale listing and drop retired metadata producers

A stale listing now always asks for one fresh listing, so a link it dropped comes back and a failed scan can no longer end the wait. Removed environments drop their producer state, the producer's repo list is built only on a gap or a first-seen projection, and recovery listings skip the lineage refresh.


* perf(space): filter current rows only for listings that keep titles


* fix(space): forget removed repos on a metadata gap; keep titles for another producer run's listing


* fix(palette): search a linked issue by its saved title before its card renders

The issue's search entry took its title only from the issue cache, which fills when the card renders, and it shadowed the saved link's titled entry under the same id. It now falls back to the link's saved title.


* perf(palette): read a row's links once per palette document


* fix(palette): give each saved link its own search unit

Saved-link evidence was meant to carry an `attachment:` id but the override set an unused field, so a link shared the `issue:N` unit id with the legacy issue field and with same-number links from other repos, and only the first (often untitled) survived. The id now applies to the unit and its fields, so every saved link's title is searchable. Replaces the cache-title fallback.


* fix(space): keep the title queue draining past a failed link; encode environment ids in coverage keys


---------
2026-11-10 16:38:44 -08:00
Neil 08bb458da4 Remove the per-repo agent folder trust prompt (#40934)
The first-launch 'Trust <repo> for agents?' modal blocked agent launches
to ask a question that offered no real protection: undecided repos, and
every unattended launch, already pre-trusted. Drop the dialog, the launch
hold and the skipAgentWorkspaceTrust plumbing. Repos default to
pre-trust; the per-repo setting remains as an opt-out.
2026-11-11 00:34:24 +00:00
Jinjing 3e86c5ac73 fix(i18n): translate sparse preset validation failures (#40277)
* fix(i18n): translate sparse preset validation failures

* fix: classify sparse directory validation by type
2026-11-09 15:12:50 -08:00
Kelvin Amoaba 98bc1acf16 feat(dictation): pulse three dots in the pill while spoken words are still on their way (#40443)
* feat(dictation): show pending dots while the engine holds speech it hasn't committed

The VAD pause segmenter already knows when a phrase is open. The recognizer
now posts speech-pending when a phrase opens and clears it once that phrase's
text is posted, and the desktop pill shows three dots after the text while it
is on. Only pause-cut on-device streams send it, so cloud, the paired web
client and phones keep today's pill.

* fix(speech): keep a lone click from turning the pending dots on
2026-11-09 20:14:48 +00:00
Jinjing 8ef4680142 Improve project group ordering across hosts (#39816)
* Improve project group ordering across hosts

* fix(project-groups): restore each group order after a failed drop

A deleted group made the aggregate rollback stop early, leaving other groups at
the ranks from the failed drop. Restore each group independently and log the
swallowed single-update failures again.

* refactor(main): give project group RPC methods their own module

Keeps repo.ts under the 300-line cap as the project group surface grows.
2026-11-09 11:40:51 -08:00
Kelvin Amoaba 58733086c9 feat(speech): spell dictated code terms with a personal and per-repo dictionary (#40450)
* feat(speech): spell dictionary terms in dictation, with repo terms and Whisper prompt

* test(speech): pin host repo terms for phone dictation

* fix(speech): keep symbol terms whole, accept null setup params, resolve SSH repos

* refactor(speech): key transcript words once and type phone terms at the reply schema

* refactor(speech): merge speech-types imports in the speech IPC
2026-11-09 19:22:46 +00:00
Kelvin Amoaba 9a45e8bdfb feat(speech): dictate through any OpenAI-compatible transcription service (#40160)
Add an OpenAI-compatible model whose base URL, model and optional key
are set up in a Voice settings dialog and sealed together in ~/.orca,
so a key is never sent to a host it wasn't saved for. It reaches
OpenAI, Groq, Mistral and local servers, and replaces the unused
userModels setting.
2026-11-09 16:57:24 +00:00
Neil 9a21a515d3 fix(vm-recipes): hide an in-progress VM checkout in every window, the phone and the jump palette (#40373)
* fix(vm-recipes): hide an in-progress VM checkout in every window, the phone and the jump palette

A VM create's checkout was hidden only in the sidebar of the window that
started the create. Windows now publish their pending VM checkouts to the
main process, which shares every window's set with all windows and
filters the paired phone's host workspace list and workspace context.
The jump palette and the sidebar read the shared set, and a grouped VM
project no longer draws an empty-project placeholder while its create
is pending. A window's set is dropped when it closes, crashes or reloads.

* test(project-groups): reset leaked runtime environment revisions between files
2026-11-09 06:51:21 -08:00
Neil 6c951c0a9a feat(vm-recipes): show VM lifecycle states in the sidebar, with Suspend/Resume VM (#40046)
* feat(vm-recipes): show VM lifecycle states in the sidebar, with Suspend/Resume VM

* fix(vm-recipes): Suspend VM suspends an idle parent with active children; dedupe repeat suspends

- With active children, Suspend VM sleeps this workspace too, so its VM
  suspends once their sessions stop.
- A repeat Suspend VM while one is pending is dropped in the coordinator
  instead of trusting a possibly stale suspended record.
- After a direct suspend, re-probe the host so its header reads Suspended.
2026-11-09 05:54:03 -08:00
Pr1pandNeil 4bb808e650 fix(build): bundle browser-extension-preload as a standalone sandboxed script (#39884)
The browser-extension preload was a main-build Rollup input, so it could be
split into shared CJS chunks that a sandboxed preload cannot require. Build it
with the other guest preloads as a self-contained bundle, and share the
one-byte unminified output options between the preload build and sandboxed
bundles so the extension preload stays one-byte in V8.

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:48:28 -08:00
Kelvin Amoaba c323f876b8 feat(dictation): dictate into the focused field of a page in the browser pane (#40191)
* feat(dictation): dictate into the focused field of a page in the browser pane

* test(dictation): cover dictation into a focused browser page

* fix(dictation): type page dictation through the frame that owns the field

* fix(dictation): space page rich-text dictation within its block and offer editors the beforeinput

* test(dictation): simplify the page insertion test mock

* fix(dictation): copy page dictation to the clipboard when an editor blocks the input
2026-11-09 08:52:28 +00:00
Neil 920a83889c refactor: move browser contracts and publication to defining owners (#40209)
* refactor: move atomic publication to its filesystem owner

* refactor: group shared browser definitions by feature

* refactor: bind proxy process and session contracts to defining owners

* refactor: consolidate direct session contract type imports

* refactor: retain atomic publication test timing under moved owner

* fix(benchmark): resolve historical tunnel framing source before loading
2026-11-09 00:45:45 -08:00
Kelvin Amoaba 80deb09aa9 feat(dictation): fixed-size dictation pill with cancel, timer and finish (#40155)
* feat(dictation): fixed-size dictation pill with cancel, timer and finish

* fix(dictation): abort a cloud upload cancelled while finishing; time recorded audio

* refactor(dictation): reuse Esc/IME helpers, keep the pane on the target, isolate meter renders

* fix(dictation): pause the pill timer while hidden; compile under React Compiler
2026-11-09 07:04:54 +00:00
Kelvin Amoaba b41ab35b72 fix(clone): let a clone use its own folder when the repo's name is taken (#40066)
Cloning always went into <parent>/<repo name>, so a same-named repository
from another owner (or any non-empty folder of that name) could not be
cloned into the same parent. Before cloning, Orca now checks the target
on the clone host. If it is taken, the clone forms show a Folder name
field with a free suggestion (<repo>-<owner>, then <repo>-2...) and clone
into that instead. RPC repo.clone and `orca project setup-clone` accept
the folder name too.
2026-11-09 03:14:06 +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
Neil 0b1efd9b90 fix(vm-recipes): record each VM before create runs so a quit or crash can't leak it (#39241)
* fix(vm-recipes): record each VM before create runs so a quit or crash can't leak it

Orca now saves a "provisioning" record for a recipe VM before running its
create command, and updates it when create finishes. If Orca quits or
crashes mid-create, or create fails without returning a result, the VM
stays listed in Settings > Cloud VMs as Failed with its instance id, so the
user can run Cleanup (destroy gets the instance id) or remove it from the
list. On startup, provisioning records with no create running are marked
as interrupted.

Records without a recipe result live in a separate file that older builds
never read, so downgrading keeps working. Records also store the repo path
so Cleanup, Copy command, suspend and resume still work after the repo is
removed or re-added under a new id (#17293).

* fix(vm-recipes): keep no runtime row when create is cancelled or rejected before its script starts

* fix(vm-recipes): harden write-ahead records from review

- Never overwrite a provisioning-records file this build cannot read; refuse new records instead.
- Remove the provisioning-records file when empty instead of rewriting it on every store write.
- Only fall back to the saved repo path while it still defines the same recipe.
- Don't let Cleanup or Attach act on a create that is still running or never returned a result.
- Show Provisioning before Cleanup disabled; stamp running records with the save time.

* fix(vm-recipes): keep new store code off direct sync fs calls and render-path translate

* fix(vm-recipes): detect a missing provisioning-records file without a type assertion
2026-11-08 16:31:49 -08:00
Kelvin Amoaba 6c31d92522 fix(native-chat): keep links when pasting rich text into the composer (#39213)
Rich-text pastes now keep their hyperlinks as Markdown links, and pasting a
URL over selected words links them, as other message editors do.

Fixes #39153
Fixes #39150
2026-11-08 23:38:26 +00:00
Neil 0d1220c31f Organize SSH and managed-server modules by concrete owner (#39937)
* refactor(main): organize SSH transport and managed server owners

* Remove orphan deploy readiness fixture and shrink test baselines

* refactor(wsl): import lock records from their defining owner

* refactor(wsl): use the canonical deferred update contract
2026-11-08 12:20:22 -08:00
Brennan Benson 252b427dfd Display private GitHub attachment images in fetched items (#39250)
* Display private GitHub attachment images in fetched items

* Keep attachment event identity aligned with committed renders

* Complete GitHub image response type contracts

* Return private image sources with accepted issue edits

* Keep issue edits successful without optional display data

* Cover unusable issue edit image responses

* Keep optional GitHub image parsing from failing accepted saves

* Fetch GitHub body images with the existing body read
2026-11-08 11:58:15 -08:00
Kelvin Amoaba 9abd095d08 feat(agents): send paired phones the desktop Agents list's verdict per agent (#39243)
While a phone is paired, the desktop window publishes its own Agents-list
classification for each pane (listed, status, unread, clearable, title,
worker parent) and worktree.ps attaches it to each agent row, so the phone
lists agents exactly as the sidebar does. agentActivity.setRead/clear apply
through the sidebar's own Activity actions and resolve once the new
verdicts are stored.
2026-11-08 19:30:27 +00:00
Neil c10881fa8c refactor(shared): organize execution and automation defining owners (#39776)
* refactor: import journal queue state from defining owners

* refactor(shared): organize execution and automation owners

* fix: retain type imports used by surviving test cases

* refactor: finish work item owners and refresh validation metadata

* test: infer reconnect status fixture type

* test(claude): resolve source files beside same-named directories

* test(runtime): group repository creation mock registrations
2026-11-08 06:46:09 -08:00
ae6675d67c fix(window): cancelling a quit prompt clears the quit latch so later closes aren't treated as quits (#39597)
* fix(window): cancelling a quit prompt now cancels the quit

Renderer-owned quit prompts (running-work "Close Window?", Save dialog,
close-guard and shutdown-checkpoint vetoes) never reach
will-prevent-unload, so main kept isQuitting latched after Cancel. A later
plain close was treated as a quit and renderer crashes were not recovered.

Add a window:close-cancelled IPC (preload ui.cancelWindowClose; no-op in the
web client) that the renderer sends on each cancel path. Main accepts it only
from its own renderer, only while quitting, and only once that renderer has
acknowledged the newest close request, then runs the same abort path as a
beforeunload veto.

Fixes #39596

Co-authored-by: Neil <neil@stably.ai>

* test(window): expose webContents.send on the renderer recovery harness type

---------

Co-authored-by: tomarai85 <tomarai85@users.noreply.github.com>
Co-authored-by: Neil <neil@stably.ai>
2026-11-08 06:17:53 -08:00
Brennan Benson d857e09615 Git Graph: commit actions (checkout, cherry-pick, revert) (#39069)
Adds commit actions to the Git Graph: check out a commit or branch, cherry-pick, revert, and create a branch from a commit. Conflicts hand off to Source Control with continue and abort. Works on local, WSL and remote hosts.
2026-11-08 03:43:30 -08:00
Jinjing 5e496520c5 Allow interleaving projects and groups in the sidebar (#39768)
* Allow interleaving projects and groups in sidebar

* Fix drag refs during render
2026-11-08 00:16:23 -08:00
Neil 83f8e6340d refactor(shared): organize file operations and storage owners (#39746) 2026-11-07 22:58:35 -08:00
fb313c4745 perf(terminal): park and defer restored plain-shell tabs whose sessions no longer exist (#39725)
Restored tabs whose local daemon session is gone no longer mount and
respawn a shell at startup; they park and respawn on open.

- Separate pty:getGoneSessionIds probe, started unawaited at startup so
  it never gates reconnect; the authoritative-capability call is unchanged.
- Binding a PTY id (spawn, cold restore, attach) clears its gone mark so a
  revived pane gets parked exit/byte watchers again; late answers for bound
  ids are ignored.
- Agent tabs (launchAgent or sleeping record) and mixed live/gone splits
  keep the mounted restore path.

Replaces #37410.

Co-authored-by: m4air <m4air@Mac.localdomain>
Co-authored-by: thefrikidude <100475418+thefrikidude@users.noreply.github.com>
2026-11-07 21:11:15 -08:00
Neil 009def47a6 feat(app-icon): import a custom app icon from Appearance settings (#39443)
Adds a Custom… option to the App Icon switcher. The picked PNG/JPEG is
header-checked before decoding (square, 64–2048 px, ≤10 MB), re-encoded as
PNG into userData, and applied to the macOS Dock and every window icon. It
persists across restarts and can be removed, which resets to Classic.

Closes #13316
2026-11-07 18:22:37 -08:00
OrcaWinandOrcaWin deb834db05 test: remove 244 low-value tests (#39507)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-07 06:33:36 -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 ee04233cf2 feat(pairing): show which devices still sign in with their original pairing code (#38949)
* 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.
2026-11-07 02:17:33 -08:00
Jinwoo Hong 228263d566 feat(automations): launch desktop runs from main, not the renderer window (#39247)
Desktop automation runs now launch from the main process through the same launcher orca serve uses. The renderer dispatch path is deleted.
2026-11-07 03:04:56 -05:00
Kelvin Amoaba d3a24e358b perf(dictation): send desktop dictation audio straight to the speech process instead of through main (#39346)
* 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
2026-11-07 07:38:20 +00:00
193dd5726f Git Graph tab: all branches, commit details and file changes (#6746)
* Add Git Graph view showing all branches and commit history

Adds a full-pane Git Graph tab that visualizes the whole repository —
all local branches, remote-tracking branches, tags, merges, and HEAD —
instead of only the current branch's linear history shown in the Source
Control sidebar today.

- Add an opt-in allRefs scope to the shared git-history loader so the
  graph query enumerates --branches --remotes --tags HEAD; the default
  current-branch path is unchanged. The flag is forwarded through the
  local IPC, SSH provider, and runtime RPC boundaries so it works in all
  environments.
- New git-graph tab content type with a full-pane GitGraphPane that
  reuses the existing graph SVG/row components, virtualizes rows, and
  opens a commit's combined diff on click. Wired into the tab strip as a
  chip (activate/close/keyboard-cycle) mirroring the simulator pattern.
- Entry point: an Open Git Graph button in the Source Control commits
  header (Cmd/Ctrl-click opens in a split).

Closes #4521

Co-authored-by: Orca <help@stably.ai>

* Address review: virtual-tab guards, nav-order, truncation copy

- Treat the Git Graph (and mobile emulator) tab chip as a virtual tab:
  add an isVirtual contract to EditorFileTab/EditorFileTabContextMenu so
  rename, copy-path, copy-relative-path, and reveal-in-finder are disabled
  for tabs whose filePath is a display label, not an on-disk path. Prevents
  a rename on the synthetic 'Git Graph' path running a real file operation.
- Forward gitGraphIds through the legacy reconcileTabOrder fallback in
  getActiveTabNavOrder so keyboard tab navigation does not drop git-graph
  tabs when no split-group layout exists yet.
- Make the truncation banner explicit: 'Showing first N commits across all
  branches' (was 'of many'), across all locales.
- Tests: virtual-tab hides path actions; git-graph survives the legacy
  nav-order fallback.

Co-authored-by: Orca <help@stably.ai>

* Forward allRefs over SSH relay and web runtime paths

Two boundaries re-destructured git.history params and dropped the new
allRefs flag, leaving the repo-wide Git Graph inert (linear default-branch
history) for SSH and web-runtime worktrees:

- src/relay/git-handler.ts: the relay host's git.history handler forwarded
  only { limit, baseRef }. Add allRefs so the SSH host enumerates all refs.
  Adds an end-to-end relay test (a feature-branch commit absent from linear
  history appears only when allRefs is forwarded).
- src/renderer/src/web/web-preload-api.ts: the web preload history shim
  destructured only { worktreePath, limit, baseRef }. Forward allRefs.

Also fix a request-id race in useGitGraphHistory: bump requestIdRef before
the null-context early return so an in-flight fetch from a prior worktree
can't resolve and overwrite the 'idle' state after the worktree clears.

Co-authored-by: Orca <help@stably.ai>

* Support filtered and pinned Git history

Resolve branch and tag roots on the host, keep paging tied to the chosen revision set, and echo the applied filter across Git transports.

Co-authored-by: Matheus Breguêz <matbrgz@gmail.com>

* Add the Git Graph tab and commit details

Open the all-branch view from Source Control or the command palette, preserve older clients' layouts, and keep the sidebar HEAD-only.

* Restore files the main merge left at stale versions

The earlier merge of origin/main kept older or missing copies of 61 files
unrelated to the Git Graph (CI script tests, reliability gates, shard
timings and five terminal runtime files). Take main's version of each so
the PR changes only its own files.

* Limit pinned history to explicit graph scopes

Keep All and HEAD snapshots free of redundant ref names, and filter ref searches before nested-tag peeling. Default history requests retain unpinned paging without evicting graph tokens.

Co-authored-by: Matheus Breguêz <matbrgz@gmail.com>

* Preserve canonical placement for older graph clients

Pass graph-free record deltas through without rebuilding layouts, retain existing empty groups, and translate content creation into canonical groups while preserving hidden graph tabs.

* Retain Git Graph browsing state for the tab lifetime

Own history retrieval, selection and scroll in one renderer controller that retires on close or owner/filter changes. Accumulate parent pages before publishing, share action-time workspace navigation, serialize ref searches, and scope refreshes to the workspace.

* Apply Git Graph branch selections on picker close

Keep checkbox changes local until dismissal, then normalize and apply one chosen ref set. Allow picker reads to use a qualified host scope.

* Keep Git Graph navigation bound to its tab owner

Retain the tab's qualified owner and Git connection across workspace focus changes. Newer selections and refreshes supersede pending parent navigation without losing fetched pages.

Report stale workspace switches and let the commit menu handle empty space in the Branch / Tag cell. Cover twin-owner retention, superseded navigation and picker apply-on-close with renderer regressions.

* Translate desktop layout commands against canonical state

Resolve older desktops' visible groups, tab gaps and split paths inside the canonical mutation, including detach and cross-partition moves. Keep initial admission visibility-aware and cache graph presence for binding-only frames.

* Refine Git Graph picker and owner transitions

Discard branch drafts on Escape or owner changes, follow updated tab ownership, and report workspace lookup failures for the current owner. Keep parent navigation queued behind pending history loads.

* Drop the redundant default from the exhaustive layout command switch

* Align Git Graph with changed-code quality rules

Use typed fixtures and an event guard, keep primitive styling on content wrappers, and prune loaded-commit bookkeeping after render.

* Route Git Graph opening through the existing editor action

Use workspace record selectors for stable owner inputs and remove two
loading labels orphaned by the graph changes from all locale catalogs.

* Preserve Git Graph selection and keep row content visible

Refresh and token recovery retain loaded depth and selection in one
accumulating operation. Keep the published view until it settles, and
only fall back to the first commit after history is exhausted.

Prioritize current and open-workspace refs, reserve their markers, clip
wide graphs and retain filenames when long paths need truncation.

* Bound Git Graph refresh and allow graph column resizing

Restore the loaded depth without searching for vanished selections, retain the published result on retrieval errors, and keep newer selections visible. Allow the bounded graph column to expand to every lane through the existing resize mechanism.

* Retain Git Graph history for errors without a message

Detect failed retrieval independently of its message and cover an empty-message rejection in the existing partial-failure regression.

* Retain Git Graph widths and preserve shifted selections

Separate committed and live resize widths, retaining the chosen width for the graph tab lifetime. Allow one bounded extra history page for selections shifted by new commits, and give the resize separator a translated label.

* Preserve nullable Git Graph owner fallback

* Fix Git Graph layout imports after the RPC method move

* Route the Git Graph owner connection through the source-control connection helper

* Keep the Git Graph button idle in hidden Source Control sections

* Re-probe Git Graph support when the owner's runtime status changes

---------

Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Matheus Breguêz <matbrgz@gmail.com>
2026-11-06 19:59:47 -08:00
Brennan Benson f308486115 Show Source Control for folder workspaces (#38831)
* Separate editor tab placement from content ownership

* Show scoped Source Control sections for attached worktrees

* Preserve active diff refresh and validate section catalogs

* Complete folder section test worktree metadata

* Use contextual types for scoped Source Control actions

* Preserve optional scoped action parameters

* Preserve editor ownership through restore, mirroring and workspace removal

* Retire Source Control drafts only after confirmed owner removal

* Limit section work to visible expanded repositories

* Keep editor follow-up actions and bulk closes in their invoking views

* Track the consolidated editor order writer in its owning module

* Use complete typed fixtures for repair contracts

* Preserve live editor placement during layout readback

* Pass projected editor placement directly to serialization

* Read attached worktree lineage from shared graph module

* Retain inferred owner checks and scope placement retirement

* Preserve selection in untouched workspaces during purge

* Exercise editor placements in existing launch and lifecycle fixtures

* Preserve shared buffer prompts and editor strip order

* Pause inactive section context subscriptions

* Keep section recovery and file actions in the folder workspace

* Describe attached Source Control in folder workspace CLI help

* Attribute Git metadata signals once per dispatch

* Watch mounted source control sections outside the warm budget

* Resolve section watches only for served filesystem roots

* Restore restart-stable editor identity across SSH opens

* Apply section terminal routing to explicit Chat choices

* Include cross-store descendants in folder workspace panels

* Keep cross-host recovery on its existing workspace route

* Start cross-host section agents in their workspace without navigation

* Update memoized Source Control labels on language changes

* Remove unused terminal close-to-right implementation

* Suspend inactive Source Control body observers

* Retain base ref query while section observation pauses

* Cover retained base ref search across section visibility

* Resolve note menu ownership from the retained snapshot

* Preserve section agent working directories and background placement

* Keep Source Control sections active while their overlays are open

* Read current settings when Source Control commands execute

* Adapt editor and browser test stores to view subscriptions

* Preserve bound store hooks for ordinary app views

* Trust agent starts outside the placement workspace

* Trust the section worktree through transient launch ownership

* Extract editor follow-up file actions from the panel

* Fail section launches when trust capability lookup fails

Preserve explicit unsupported-host fallback, propagate lookup failures to the existing launch error path, and let the existing transport retry refresh rejected capability probes.

* Follow the moved pane launch test in web configs

* Preserve section file ownership during refresh and close

* Share tab order removal across editor close paths

* Verify companion editor close through the real store

* Close all workspace split copies for legacy mobile file requests

* Keep unmatched mobile close requests within their workspace

* Reuse the agent menu render snapshot

* Keep attached folder roots scoped to their resolved host

* Apply repository trust decisions to the launch trust owner
2026-11-06 18:25:57 -08:00
Neil 89fb7c8abe feat(settings): show which paired devices still sign in with older encryption (#39222)
The host now records, per paired device, whether its most recent
sign-in used the legacy E2EE framing (set on a legacy sign-in, cleared
on a v2 one). The field rides on the existing deferred lastSeen write,
so it adds no extra registry saves, and older builds keep unknown row
fields as they are.

Settings shows a notice under such rows:
- Mobile paired devices: "Uses older encryption. Update the Orca app on
  this device."
- Runtime access links: "Last used with older encryption. Update Orca
  where this link is used." (one link can be shared by several clients)

Local only: nothing is sent anywhere, and no connection is refused.
2026-11-06 17:06:25 -08:00
Neil 090945007b Ask once per repo before pre-trusting agent folders (#38946)
* Ask once per repo before pre-trusting agent folders

* Route the trust prompt's repo lookup by the launch host; use dialog primitives as designed

* Bound the first-launch trust hold and honour the answer for the launch

* Move agent folder trust settings into their own settings group
2026-11-06 17:02:46 -08:00
Neil 93589dc6f8 fix(shell): open linked scripts in the editor and reveal programs instead of launching them (#37930)
* fix(shell): show linked scripts in the editor and reveal programs instead of launching them

Markdown file links that would run code no longer go to the OS default
app. Main inspects the target (following symlinks, checking every name
in the chain plus the executable bit and the file header): readable
scripts open in an Orca editor tab, binaries and bundles are revealed in
the file manager, and everything else opens as before.

* fix(shell): reveal linked archives instead of unpacking them

Zip, tar, gzip, bzip2, xz, zstd, 7z, rar, cab and zip-based packages
(.war, .ear, .apk, .ipa, .xpi, .crx, .vsix, .nupkg) are revealed in the
file manager. Archive headers are also treated as binary content, so an
archive under a script name or an extensionless executable name is
revealed rather than shown as text.
2026-11-06 16:25:12 -08:00
Neil bb5f37c916 feat(pairing): unscanned desktop pairing codes expire (QR 10 min, link 60 min) (#37957)
* feat(pairing): unscanned desktop pairing offers expire (QR 10 min, link 60 min)

Headless serve/orcad mint offers without a TTL, so they never expire.
Paired rows and rows without offerExpiresAt are unaffected.

* feat(pairing): refresh the mobile QR before it expires and show runtime link expiry

The QR re-mints a minute before expiry while visible; an unused runtime
link shows its expiry and, once expired, is replaced by a notice. Web
clients rejected while pairing now suggest asking for a new link.

* feat(mobile): say a refused pairing code expired or was replaced

A first pairing the desktop refuses (direct or Relay) now asks for a new
code instead of showing the raw transport error.

* refactor(pairing): replace type assertions in code-refusal detection and tests

* test(mobile): re-record pairing race golden for refused-code error

* fix(pairing): keep pairing codes valid across sleep and stale registry writers

- QR refresh rechecks the wall clock every 15 s and on window focus, so a
  computer waking from sleep never keeps showing an expired code.
- A registry save from a process with an older copy can no longer reset a
  paired row back to unscanned (which would let its offer expire).
- The QR caption says how long a copied code works.

* test(pairing): annotate the IPC handler stub cast
2026-11-06 16:23:44 -08:00
Kelvin Amoaba 768df33d84 fix(dictation): handle cloud dictation's 10-minute cap, stalled uploads and bad API keys (#39114)
* fix(dictation): bound cloud uploads, stop at the 10-minute cap, check the OpenAI key on save

* refactor(dictation): share the OpenAI error reader
2026-11-07 00:22:24 +00:00
Jinwoo Hong 555bd481bc Let multi-repo folder workspaces parent and nest workspaces, including on other machines (#38904)
Multi-repo folder workspaces can parent workspaces on this machine and on paired servers, and their children nest under them in the sidebar and on the phone. Task parents are inferred at creation instead of on every lineage refresh.
2026-11-06 19:03:51 -05:00
Neil 2137a614d9 feat(browser): show when an SSH host is controlling Orca browser tabs, and let people stop it (#39212) 2026-11-06 15:49:24 -08:00