Commit Graph
6133 Commits
Author SHA1 Message Date
Brennan BensonandOrca 0fe20ddff9 Fix Monaco Peek References preview collapse (#7662)
Co-authored-by: Orca <help@stably.ai>
2026-07-07 12:55:41 -07:00
Brennan BensonandOrca fed545d330 Stop wiping the shared WebGL glyph atlas on plain window refocus (#7604)
Co-authored-by: Orca <help@stably.ai>
2026-07-07 12:43:53 -07:00
Jinjing 599f9f2138 Update WeChat community info in localized READMEs
- Remove the WeChat community section from the Portuguese translation.
- Add the main and backup WeChat QR codes to the Chinese translation.
2026-07-07 12:33:52 -07:00
Jinjing 0f7658d77c Make center split divider more visible (#7701)
* fix: address review findings

* Improve split divider contrast and refactor tab split context menus

- Increase contrast of `--tab-group-split-divider` colors in light and
  dark modes to achieve at least 3:1 contrast against `--card`.
- Refactor `TerminalTabSplitMenuSection` to use the shared
  `TabWorkspaceLayoutMenuSection` for moving tabs between splits.
- Clarify terminal-specific split action labels in the context menu.
- Remove redundant icon margins in `EditorFileTabContextMenu`.
2026-07-07 12:12:00 -07:00
github-actions[bot] 2dad1f04f3 Update README downloads badge 2026-07-07 18:57:48 +00:00
github-actions[bot] cf7fb4f7bb Update README downloads badge 2026-07-07 07:28:26 +00:00
Neil af59239c1a test(e2e): relax hidden PTY timer drift gate 2026-07-06 23:01:51 -07:00
github-actions[bot] eed0058168 release: v1.4.127-rc.0 v1.4.127-rc.0 2026-07-07 05:04:32 +00:00
JinjingandOrca 544bca5202 fix: terminal IME candidate selection and text commit on Linux (#7634)
* fix terminal IME candidate selection and text commit on Linux

Sogou Pinyin and fcitx on Linux failed in Orca's terminal because bare
229 keydowns were swallowed, and empty composition updates prematurely
deactivated tracking. This led to dropped Chinese text or leaked Space/digit
candidate-selection keys reaching the PTY.

- Allow bare 229 keydowns to bypass suppression on Linux so xterm can diff
  and commit text.
- Prevent empty compositionupdate events from prematurely deactivating
  the composition tracker.
- Suppress and preventDefault candidate-selection keys (Space and digits)
  during active composition and a brief post-composition window.
- Add comprehensive unit tests and an Electron CDP-driven E2E repro.

* fix: register IME gate command as direct spec-file invocation

The reliability-gate checker rejects --grep title selectors and requires
every evidenceRun command to match a gate command. Drop the --grep from
the e2e gate command and its evidence run, and remove the stale 3-file
evidence run superseded by the full 7-file run.

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

* Guard overlapping and post-composition Linux IME candidate keys

- Track pending candidate key releases in a Map instead of a single
  slot to support overlapping selector key events without stranding.
- Apply the candidate selection guard to post-composition key releases
  that arrive after compositionend, preventing digits/Space from
  leaking into the PTY.
- Restrict the Linux/Sogou candidate selection guard to Linux to
  prevent interference on macOS and Windows.
- Exclude Shift+Space from candidate selection key checks.

* Guard held-key IME candidate repeats and scope policy to desktop Linux

- Keep auto-repeat keydowns for a candidate key suppressed past the
  250ms guard window until its corresponding keyup event is received.
- Clear stale pending releases on fresh non-repeat keydowns to avoid
  guarding the wrong key events.
- Exclude Android and ChromeOS user agents from desktop Linux-specific
  IME candidate key suppression behaviors.
- Ensure the composition tracker is activated unconditionally on
  compositionupdate events.

* Clean up IME reference and extract shared test event fixture

- Remove the obsolete Linux Sogou Pinyin IME reference document.
- Extract the fully-defaulted XtermBypassEvent helper into a shared
  fixture file to keep the policy test suites in sync.
- Add a test verifying that Shift+Space (fcitx full-/half-width toggle)
  is not suppressed as an IME candidate key.

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-06 22:03:39 -07:00
Brennan BensonandOrca 46a67cb2eb perf(source-control): cache PR conflict-summary derivation and throttle base fetch (#7606)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 22:02:59 -07:00
Jinwoo HongandOrca e33f31689b Make Codex session-history source home configurable (host + WSL) (#7629)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 21:47:02 -07:00
Brennan BensonandOrca 82eeac6194 Keep GitHub PR status working when the rate-limit budget can't be read (GHES with rate limiting disabled) (#7632)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 21:45:10 -07:00
Jinjing aa0993f546 Improve remote connection terminal error msg and session restore recovery (#7661)
* Robustify SSH terminal reconnect and session restore recovery

- Release the replay guard after a fallback timeout to prevent permanent
  keyboard input lockouts when an unmounted terminal never parses.
- Verify backing process liveness on PTY attach and reap stale entries
  so dead shells cleanly trigger a fresh pane spawn.
- Normalize connection IDs during restore to prevent spurious mismatch
  errors, and treat true mismatches as expired sessions instead of crashing.

* Route disconnected SSH terminal panes through deferred connection gate

Avoid spawning SSH terminal processes against disconnected targets,
which otherwise throws "No PTY provider" and leaves panes stranded.

- Intercept spawning via a new connect gate that triggers the deferred
  connection flow when the SSH target is disconnected.
- Fall back to composite worktree IDs during cold-start hydration to
  ensure deferred SSH session IDs are properly stashed.
- Retry spawning and remounting terminal panes upon SSH reconnect if
  they are stranded or failed to spawn.
2026-07-06 21:41:23 -07:00
Pablo AlbrechtandClaude Opus 4.8 1a4232fe96 fix(tabs): keep the worktree's remembered active tab on switch-back (#7385)
When returning to a worktree in the sidebar, the active tab reset to the
first tab instead of the one the user left on. Three fallback sites derived
the active tab from the first tab rather than the per-worktree remembered
selection (activeTabIdByWorktree):

- reconcileWorktreeTabModel: promoting legacy runtime terminals into a
  freshly-ensured group seeded activeTabId from restoredLegacyTabs[0].
- Terminal.tsx active-terminal repair: reset to tabs[0]; a repair firing on
  a transient worktree-switch render permanently clobbered the selection to
  Terminal 1.
- hydrateLegacyFormat: used the global session.activeTabId, so every
  worktree except the last-focused one lost its terminal on restart.

All three now honor activeTabIdByWorktree before falling back to the first
tab. Adds fails-old/passes-new regression tests.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 21:40:40 -07:00
Neil 6a4e6ce28a perf(ssh): bound the system-ssh port-forward stderr tail (#7647)
The stderr handler in system-ssh-port-forward-provider.ts stays attached
for the forward process's entire lifetime and appends every chunk to an
unbounded string, only ever read to build the exit-error detail. A
chatty/warning-spamming remote sshd over a long-lived `ssh -N -L`
forward could grow it without bound.

Fix: keep only the most-recent 64 KB tail, mirroring
MAX_RELAY_STARTUP_BUFFER_BYTES in ssh-relay-deploy-helpers.ts. The tail
is what the error message surfaces anyway.

Test (red->green): emitting >64 KB of stderr then exiting keeps the
recent tail marker and drops the oldest, detail bounded below the
produced size; without the cap the whole string is retained.
2026-07-06 21:28:15 -07:00
Neil 54c4959830 perf(mobile): cap the scheduled-notification map + tap-dedup set (#7646)
scheduledNotificationsByHostAndNotificationId (mobile-notifications.ts)
retained one entry per scheduled desktop notification. The key embeds
notificationId, which carries a per-completion timestamp
(buildAgentNotificationId), so every agent-task-complete inserts a new,
never-reused key. Entries are removed only when the desktop sends a
matching dismiss — which a remote mobile user (not sitting at the
desktop) frequently never receives — so the module-level map grew for
the app's whole lifetime. Small per entry, but genuinely unbounded.

Fix: bound the map to the 256 most-recent SETTLED entries (never evict
one mid-schedule). A settled entry only retains a small identifier used
for later programmatic dismissal, which is unnecessary for long-past
completions, so eviction has no user-visible effect.

Also FIFO-cap RootLayout's handledNotificationIdsRef tap-dedup Set
(RootLayout never unmounts, so it otherwise grew one id per tapped
notification forever).

Test (red->green): with the cap at 1, scheduling a second notification
evicts the first, so a later dismiss for the evicted id is a no-op while
the retained one still dismisses; without the cap the old entry survives.
2026-07-06 21:28:09 -07:00
Neil d0403d808e perf(renderer): FIFO-cap recentlyClosedAgentStatusTabIds (#7645)
recentlyClosedAgentStatusTabIds (agent-status store) suppresses late
hook/status events for a just-closed terminal tab. It was only ever
added to — one `true` entry per agent-tab close, keyed by the ephemeral
tabId, never deleted or capped — so it grew for the renderer's whole
session. It's the renderer twin of the main-process
closedAgentStatusTabIds set that #7561 already FIFO-capped.

Fix: bound it to the 1024 most-recent closed tabs via delete-then-set
LRU with oldest-key eviction (Record key order is insertion order),
mirroring #7561. A status event for a tab closed >1024 tabs ago cannot
still arrive, so suppression behavior is unchanged.

Test (red->green): closing 1029 tabs leaves exactly 1024 markers with
the oldest evicted and the most-recent retained; without the cap all
1029 persist.
2026-07-06 21:28:03 -07:00
Neil 8936225889 perf(native-chat): LRU-bound the pending-send and command-marker scope caches (#7643)
Two module-level caches in native-chat-pending.ts capped their per-key
arrays (8 entries) but never bounded the KEY count:

- commandMarkerCache — keyed by paneKey\0agent\0sessionId; sessionId
  changes on every /clear and paneKey embeds an ephemeral leafId, so a
  distinct key was stranded per (pane, session) for the renderer's whole
  life. Only test-only clear() ever removed keys.
- pendingSendCache — self-cleans on the normal empty-drain path, but a
  pane closed with an unconfirmed send (agent crash / early close) left
  its non-empty entry keyed forever.

Route both writes through the existing setBoundedScopeCacheEntry LRU
helper (cap 128) that #7566 already applied to the draft/attachment
caches in the same folder — same pattern, same file family, was just
missed here. Values are tiny so this is a slow leak, but real and
unbounded.

Tests (red->green): appending 133 distinct scopes evicts the oldest and
keeps the most-recent 128; without the cap all 133 survive.
2026-07-06 21:27:57 -07:00
Jinjing 7842a48090 Pin PR comments list header when scrolling checks panel (#7657)
Keep the filter and add-comment actions reachable while reading long
threads in the sidebar. Also add a test to verify the sticky classes
are applied.
2026-07-06 21:22:08 -07:00
NeilandOrca f057c9d664 perf(pty): cap the unsent main→renderer PTY backlog (Win/Linux GB-scale leak) (#7630)
* perf(pty): cap the unsent main→renderer PTY backlog (Win/Linux GB leak)

The per-pty `pendingData` string in ipc/pty.ts (main's unsent
main→renderer output queue) had no size cap. The 512 KB/pty + 8 MB
in-flight caps bound only SENT-but-unacked bytes; `onData` appends to
`pendingData` unconditionally and `flushPendingData` merely `continue`s
(no drain) while ack-gated. On Windows/Linux the main renderer is
background-throttled — `setBackgroundThrottling(false)` is set only for
`process.platform === 'darwin'` — and Chromium freezes hidden pages
after ~5 min, so a backgrounded Orca with an active/verbose agent stops
ACKing: in-flight pins at 8 MB, the flush gates, and `pendingData` grows
at raw PTY throughput → MB→GB in the main process. macOS is unaffected.

Fix: cap the backlog to the most-recent PENDING_DATA_MAX_CHARS (2 MB,
matching the daemon pendingOutput and renderer scheduler caps),
advancing startSeq by the dropped-char count (the same arithmetic
flushPendingData uses when slicing), and set a `droppedBacklog` flag on
the next payload. The renderer's dataCallback sees the flag and calls
the existing markHiddenOutputRestoreNeeded(), so on hidden→visible it
rebuilds the dropped span from the main headless snapshot — no output is
lost within scrollback depth. Background agents keep writing full-speed
into the runtime buffer; only the redundant delivery copy is trimmed.
The flag threads through the same layers as the existing `background`
field: main payload → preload types → dispatcher PtyDataMeta → renderer.

Tests (red→green): a daemon pty emits 5 MB while the renderer never
ACKs. Without the cap the flag is never set (fail); with it the first
emitted chunk carries droppedBacklog exactly once and delivery stays
bounded. Ordinary small output never sets the flag.

Note: leak + fix are Win/Linux-only (macOS is throttling-exempt), so not
reproducible at runtime on macOS; evidence is the code trace + tests.

* test(pty): clarify that the sent-total assertion is a sanity bound, not the cap proof

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-06 20:58:53 -07:00
b23fcf3b2b Handle Windows SSH directory browsing fallback (#7123)
* Allow Windows SSH directory browsing to recover

The remote project picker runs before the relay filesystem ACLs exist, so it uses a raw SSH exec channel with POSIX shell commands. Windows OpenSSH targets whose default shell is cmd.exe reject Orca's POSIX exec wrapper, which prevented browsing any remote directories. Keep the existing POSIX path as the first attempt, then fall back to a narrowly scoped PowerShell listing that emits the same line-based format.

Constraint: Add Remote Project needs raw SSH browsing before relay roots are registered
Constraint: Windows OpenSSH may use cmd.exe as the remote command shell
Rejected: Replace the POSIX command for all hosts | riskier for existing Linux/macOS SSH targets
Confidence: medium
Scope-risk: narrow
Directive: Keep POSIX browsing as the primary path; Windows fallback exists only for shell-wrapper rejection errors
Tested: npx --yes pnpm@10.24.0 exec vitest run --config config/vitest.config.ts src/main/ipc/ssh-browse.test.ts
Tested: npx --yes pnpm@10.24.0 exec oxlint src/main/ipc/ssh-browse.ts src/main/ipc/ssh-browse.test.ts
Tested: npx --yes pnpm@10.24.0 exec oxfmt --check src/main/ipc/ssh-browse.ts src/main/ipc/ssh-browse.test.ts
Tested: npx --yes pnpm@10.24.0 run typecheck:node
Not-tested: Live Windows OpenSSH host with cmd.exe default shell

* fix(ssh-browse): strip CRLF in Windows PowerShell browse output

Windows OpenSSH exec emits CRLF, but the browse parser split on \n only
and never stripped the trailing \r. Every directory line then failed the
endsWith('/') check and was misclassified as a file with a stray CR in
its name (and resolvedPath kept a trailing \r) — breaking the exact
Windows path this PR adds. Split on /\r?\n/ to match the existing
ssh-relay-versioned-install convention; POSIX (LF-only) output and
filenames with legitimate leading/trailing spaces are unaffected.

The added fallback test used \n-only fixtures that no real Windows host
produces, masking the bug; switch it to realistic CRLF output so it now
guards the regression.

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

* fix(ssh-browse): locale-independent Windows fallback + UTF-8 output

- Trigger the PowerShell fallback on cmd.exe's locale-independent 9009 exit
  code, not just English/Spanish stderr text, so non-English Windows hosts
  actually recover.
- Pin [Console]::OutputEncoding to UTF-8 in the PowerShell script so non-ASCII
  names (e.g. C:\Users\José, CJK, Cyrillic) aren't mojibake'd when decoded.
- Rethrow the original POSIX error when the PowerShell retry also fails, so a
  false-positive predicate match doesn't mask the real failure.
- Tests: decode the -EncodedCommand payload to guard injection-safe escaping
  and the UTF-8 pin; add a 9009-locale fallback case and a negative-predicate
  (permission denied must not retry) case.
- Drop an incorrect sentence from the CRLF-split comment.

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

* fix(ssh-browse): surface PowerShell error on proven-Windows fallback

When the fallback was triggered by cmd.exe's 9009 exit, the host is provably
Windows and PowerShell genuinely ran, so its error ('Cannot find path' /
'Access is denied') is the real cause — surface it instead of the misleading
cmd.exe "exec is not recognized" prose. Only the string-heuristic path (a
possible POSIX false positive) still rethrows the original error.

Also: note the system-ssh transport's 8-bit exit-code truncation caveat in the
9009 comment, and add tests for both double-failure paths (9009 -> surface
PowerShell error; heuristic -> surface original).

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

* test(ssh-browse): guard the ~ -> $HOME PowerShell fallback branch

The tilde expansion in powerShellPathExpression (~ is the default browse path)
was unguarded — collapsing it to a literal would pass the whole suite. Add a
fallback test asserting the decoded script contains $dir = $HOME.

Also tighten the 9009 comment: the locale-independent trigger only holds for a
cmd.exe DefaultShell on the ssh2 transport; a powershell.exe DefaultShell exits
1 (not 9009) and, like the system-ssh transport, relies on the stderr heuristics.

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

* fix(ssh-browse): emit forward-slash resolvedPath from Windows fallback

Get-Location.ProviderPath returns a native backslash path (C:\Users\alice),
but the renderer's parentPath/joinPath only split on '/': backslash paths make
the browser's 'Up' button a no-op and produce mixed separators when descending.
Normalize the emitted resolvedPath to forward slashes (matching the POSIX
branch) while keeping the native $resolved for Get-ChildItem -LiteralPath.

Update the fallback-test fixtures to the real forward-slash output and assert
the -replace normalization is present in the generated script.

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

* fix(ssh-browse): root Windows drive paths in the PowerShell fallback

The forward-slash resolvedPath means the renderer rebuilds Windows paths with
POSIX helpers, so it hands back drive paths Set-Location mishandles: the
breadcrumb prepends a spurious leading '/' (/C:/Users -> current drive's root),
and 'Up' from a first-level dir yields a bare drive letter ('C:' is
drive-relative, not C:\). Normalize both to a rooted drive path in
powerShellPathExpression so navigation lands where the user clicked. POSIX,
UNC, and relative paths are left untouched.

Add parametrized tests for /C:/Users and C: -> rooted $dir literals.

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

* test(ssh-browse): cover combined /C: drive-path normalization

Guards the strip-then-root ordering in normalizeWindowsDrivePath so a future
refactor can't regress the combined leading-slash + bare-drive case.

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

* fix(ssh-browse): trigger Windows fallback on non-zero exit, not exit 9009

Verified on real Windows OpenSSH + cmd.exe that a rejected POSIX exec
wrapper arrives over SSH as process exit code 1, not 9009 (cmd.exe's 9009
ERRORLEVEL never crosses its process boundary; sshd forwards the process
exit code). Confirmed on both the ssh2 and system-ssh transports.

The old trigger keyed off exit 9009 (dead code) with an English/Spanish
stderr string fallback, so non-English cmd.exe hosts (German/French/
Japanese/etc.) never fell back and directory browsing failed.

Fix: retry via PowerShell whenever the POSIX attempt fails with a
RemoteBrowseError (command ran, exited non-zero) - locale-independent and
covers every cmd.exe locale. Transport errors/timeouts aren't
RemoteBrowseErrors, so dropped connections aren't mis-retried. Pick the
error to surface via the POSIX "command not found" exit 127 (no
powershell.exe means the host isn't Windows, so surface the original POSIX
error). Removes the fragile 9009/stderr-string heuristics.

Tests: correct injected exit codes to the real value (1), add a
Japanese-locale regression test, and lock the retry/no-mask contract.

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Jinwoo Hong <73622457+Jinwoo-H@users.noreply.github.com>
2026-07-06 20:46:48 -07:00
gatsby74andJinjing 98d850aeba fix(settings): keep full installed font list (#7581)
* fix(settings): keep full installed font list

* fix(settings): bound font picker rendering

* Fix redundant font queries and handle partial state in worktree purge

- Latch the loaded state even when the returned font list is empty, preventing font-less systems from reissuing font listing calls on every picker interaction.
- Add null-tolerance for `ptyIdsByTabId` when building worktree purge state to support callers that pass partial AppState.

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-06 20:21:58 -07:00
Jinwoo HongandOrca a6cbd3102a fix(terminal): repaint revealed panes stuck behind xterm's paused-render gate (#7614)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 20:17:35 -07:00
Neil 86f404ef53 perf(native-chat): byte-cap the transcript read-cache to bound RSS (GB-scale leak) (#7625) 2026-07-06 19:08:42 -07:00
Jinjing 4cbf699360 fix: quote queued OMP resumes for Windows shells (#7628) 2026-07-06 18:41:32 -07:00
PP 0b4196fc17 fix(ssh): stop deleted ~/.ssh/config hosts from reappearing on sync (#7302)
Deleting a config-sourced SSH target had no lasting effect: the Manage-SSH pane
re-imports ~/.ssh/config on open, and the import was a pure upsert with no record
of deletions, so the just-deleted host was re-inserted verbatim from the config
that still exists on disk.

Persist a `deletedSshConfigAliases` tombstone set:

- Deleting a config-managed target (source 'ssh-config', or an adopted legacy
  import) records its alias; manual targets are never tombstoned.
- The passive on-open sync skips tombstoned aliases, so a deleted host stays
  deleted.
- Re-adding or editing a target reclaims its alias, and the explicit Import
  action (`reAdopt`) clears all tombstones to deliberately re-adopt config.

This also fixes the edit-then-reappear case: editing a config host to `manual`
already reserved its current alias, and reclaim covers alias changes.
2026-07-06 18:35:42 -07:00
51c3849a00 fix(github): route PR merges through repo owner (#7590)
* fix(github): route PR merges through repo owner

- Use repo-owner runtime settings before source-context overrides in PR actions
- Keep headless/runtime repos on runtime RPC instead of local gh:mergePR
- Add source-boundary coverage for merge routing and Windows-safe newline matching

* fix(github): preserve repo-owner merge routing

- Apply task-source runtime overrides only when they resolve to a runtime host
- Keep runtime-owned repos from being downgraded to local gh:mergePR
- Guard the routing contract with source-boundary coverage
- Important because non-runtime source contexts could recreate the issue #6957 access-denied path

* test(github): add behavioral regression test for repo-owner merge routing

Mirrors PRActionsPanel's merge-routing decision through the real
repo-runtime-owner/task-source helpers so a revert to source-only
routing (issue #6957) fails here. Covers the runtime-owned repo with a
local GitHub source view and the local-repo-while-runtime-focused case.

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

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-07-06 18:34:02 -07:00
Jinwoo-HandOrca d84041c52a test: lock composer agent-detection host precedence for runtime repos (#7082)
Regression guard for the runtime-agent-list fix: asserts the composer's
detectedAgentList selector and detection effect resolve SSH -> runtime ->
local in that order, so a runtime-owned repo shows the paired runtime's
agents instead of the local machine's.

Co-authored-by: Orca <help@stably.ai>
2026-07-06 18:13:55 -07:00
Eren Çakar 1886ea27f7 fix: use runtime agent IDs in workspace composer (#7082) 2026-07-06 18:13:55 -07:00
f61500280b feat(ai-vault): add OMP sessions to the AI Vault session browser (#7618)
* feat(ai-vault): add OMP sessions to the AI Vault session browser

Adds OMP ("Oh My Pi") to the AI Vault/Agents catalog so historical
.omp/agent/sessions/**/*.jsonl transcripts are discovered, parsed, and
resumable from the right-sidebar session browser — locally and over SSH.

- Discovery mirrors Pi (OMP_CODING_AGENT_DIR env, WSL home roots, per-agent
  limit) in both the local scanner and the remote/SSH scanner.
- Parses OMP's message-graph JSONL via the shared graph parser (new
  MessageGraphAgent type), capturing the model from model_change.model (OMP's
  key, not Pi's modelId) or the assistant message, and tokens from usage.
- Routes OMP through the incremental parse cache so ~5s rescans resume from
  the last byte instead of re-reading whole transcripts.
- Resumes by absolute transcript path (`omp --resume <path>`) so it resolves
  regardless of which session-dir root (custom OMP_CODING_AGENT_DIR / WSL
  store) the file was discovered under; threaded through both the scanner and
  the renderer's local resume/copy rebuild.
- Renderer reuses the existing OmpIcon/catalog/grouping; adds overflow-x-hidden
  so long worktree chips never widen the sidebar.

Generalizes normalizePiSessionsDir -> normalizeAgentSessionsDir. Verified
end-to-end against 10 real ~/.omp transcripts and rendered in the app.

Co-authored-by: gatsby74 <166927047+gatsby74@users.noreply.github.com>

* fix: make AI Vault parse-cache agent switch explicit

---------

Co-authored-by: gatsby74 <166927047+gatsby74@users.noreply.github.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-07-06 18:03:36 -07:00
Neil e30f9d36f2 perf(renderer): purge seven per-tab/per-pty terminal maps on bulk worktree removal (#7613) 2026-07-06 17:57:31 -07:00
Brennan BensonandOrca 9a3bf1293c Mobile file tree follow-ups: reconnect no-blank + old-desktop files.list fallback (#7599)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 17:13:21 -07:00
NeilandOrca f311307560 Add max-lines ratchet CI gate to block new line-limit bypasses (#7608)
oxlint already fails any file over max-lines that is not suppressed, so the
only way to grow past the budget is to add an eslint/oxlint-disable max-lines
comment or a per-file max-lines bump in mobile/.oxlintrc.json. This adds a CI
gate that freezes the current set of suppressions (config/max-lines-baseline.txt,
355 grandfathered entries) and fails the build when a NEW one appears — with a
loud, actionable message pointing at 'split the file'. Existing oversized files
are untouched; the baseline may only shrink (pnpm check:max-lines-ratchet --prune).

Wired into the root lint script and as a dedicated pr.yml step. Unit-tested
(15 cases) and verified against all three failure paths + clean-tree pass.

Co-authored-by: Orca <help@stably.ai>
2026-07-06 17:12:27 -07:00
Jinwoo HongandOrca 9bed9bbd34 perf(ssh): bound relay bulk-stream backlog so PTY echo is not head-of-line blocked (#7601)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 17:10:04 -07:00
Jinjing 7c7ffd64ad docs: update Android APK release link (#7609) 2026-07-06 17:06:17 -07:00
NeilandOrca 6ebe352f36 perf(renderer): project TabBar's agent-status subscription to stable agent types (#7559)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 17:03:44 -07:00
Brennan BensonandNeil f5d1a9d549 fix(agent-status): cap retainedAgentsByPaneKey to stop renderer heap OOM (#7528)
retainedAgentsByPaneKey snapshots a completed agent (a full AgentStatusEntry
— up to ~24KB of prompt/message text — plus a TerminalTab) per ephemeral
paneKey. paneKeys never recur, and the map is pruned only on worktree removal
or manual dismissal, so a long-lived worktree in a busy multi-agent /
orchestration session grows it without bound. This is the dominant
large-payload driver of the renderer JS-heap OOM seen in the Windows crash
bundles (heap climbing to the 3586 MB V8 old-space limit under continuous
multi-agent work).

Cap the map with insertion-order (== retention-order) FIFO eviction, mirroring
capRecordByInsertionOrder in github.ts: the newest completions survive; the
oldest simply stop showing in the recently-completed overlay. retainAgents is
the only path that grows the map, so capping there fully bounds it.

Adds a leak regression test that drives the production retainAgents path with
distinct ephemeral paneKeys and asserts the map stays bounded — fails before
this change (grows to N), passes after (capped at MAX_RETAINED_AGENTS).

Co-authored-by: Neil <neil@stably.ai>
2026-07-06 16:57:54 -07:00
NeilandOrca 459b8ecbee perf(renderer): gate CodexRestartChip's store subscriptions on restart-notice existence (#7560)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 16:48:45 -07:00
NeilandOrca d39812f98d perf(renderer): LRU-bound the native-chat composer scope caches (#7566)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 16:46:04 -07:00
NeilandOrca e82eb82716 perf(renderer): purge sparse-preset maps when a repo is removed (#7564)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 16:45:29 -07:00
NeilandOrca 39dbab41d8 perf(renderer): purge three orphaned tab/worktree module maps on removal (#7562)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 16:44:58 -07:00
NeilandOrca aa3936c1e0 perf(main): bound agent-hook closed-tab suppression set (#7561)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 16:44:18 -07:00
NeilandOrca c4c934cf7c perf(main): bound authorized-external-path set with LRU eviction (#7556)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 16:43:43 -07:00
NeilandOrca ec52db6d20 perf(main): drop localhost label routes when a worktree is removed (#7557)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 16:43:05 -07:00
Brennan BensonandOrca 7237c8e592 Route title-status consumers through one pane-agent-evidence seam (title evidence plan, PR 2) (#7600)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 16:39:20 -07:00
github-actions[bot] ee2e3a30a5 release: v1.4.126 v1.4.126 2026-07-06 22:59:57 +00:00
Brennan BensonandOrca 99ae2dc90f Show full workspace file tree on mobile (#7289)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 15:41:51 -07:00
Brennan Benson a393facef8 Keep the Peek References scrollbar visible (#7584) 2026-07-06 15:28:09 -07:00
Jinwoo HongandOrca bc84f4b04b Speed up startup with deferred remote catalogs (#7087)
Co-authored-by: Orca <help@stably.ai>
2026-07-06 15:15:15 -07:00
github-actions[bot] 014fd3cf26 release: v1.4.126-rc.0 v1.4.126-rc.0 2026-07-06 22:14:09 +00:00