mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
eb545aaa59be6ca812eaaa0a55421d78f0acaa3e
29
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c3526cc19d |
feat(codex): surface a stalled config sync instead of failing silently (#10449)
* feat(codex): surface a stalled config sync instead of failing silently Why: the mirror keeps serving the last synced settings when ~/.codex/config.toml is missing, blank, or unreadable. That is the right call for data safety, but it is invisible — a downed WSL distro or an unhydrated cloud-synced home leaves "Orca ignores my config edits" with no log line and no UI to diagnose. Status is derived on demand from the same predicates the mirror uses, so the two cannot disagree. The stall is logged once per episode rather than on every launch and quota poll, and the Codex account section names the file and what to do. * fix(codex): latch an unreadable source and stop over-claiming recovery An unreadable source throws out of the mirror, so reporting only on the success path left that stall latch-less: it logged the raw failure on every launch and quota poll while its reason never reached the surfaced status. Report from the catch path too. The clear message also claimed the source was "readable again", which is false when the stall ended because the runtime config was removed rather than because the source came back. Restoring console.warn now happens in afterEach — an inline mockRestore is skipped by a failing assertion, and the leaked spy made every later case in the block fail spuriously. * fix(codex): latch the stall promotion hits first, and scope it to the host Review round 1 findings: - The unreadable-source latch still never fired in the steady state. Once a baseline exists, promotion reads the source before the mirror does, so it throws first and `!promotionPlan` returned before any reporting — logging a reasonless failure every launch and quota poll, which is exactly what the previous commit claimed to fix. Report from that branch too. The test only passed because its fixture had no baseline; it now seeds one first and fails without the fix. - The banner named the host's ~/.codex while a WSL or per-account runtime was selected, whose real source is a different file entirely. Gate it to the host scope, matching how the sign-in warning is already gated. - Three new translate keys were missing from the locale catalogs, failing the localization gate in `pnpm lint`. - The registrar mock was never asserted, so deleting the registration left the suite green. - `codexConfigSyncStatus` hung off the `agentHooks` namespace despite having nothing to do with agent hooks; moved to its own `codexConfigSync.status` while it is still a four-file change. * fix(codex): report sync health for the home the selection actually mirrors Review round 2: - The status resolved the shared runtime home, but the system default now runs Codex directly against ~/.codex and managed accounts get their own home. So a stalled per-account mirror showed no banner at all, while a stale shared home could warn about a config the active lane never reads. Resolve the mirrored home from the current selection, and report synced when the lane has no mirror to fall behind. - The round-1 report on the promotion failure path could clear the latch on a pass where no mirror ran, claiming a recovery that never happened and silencing every later pass. Only ever latch a stall there; leave clearing to the path that actually mirrored. * fix(codex): refetch sync status when the active Codex account changes Review round 3: - Resolving the status per selection made the fetch account-dependent, but the effect was not keyed on the active account. Switching accounts left the banner describing the previous one — and switching INTO a stalled account showed nothing at all, which is the silence this change exists to remove. - Pin the home resolution itself: it had no direct test, and its shared-home path was a hand-copied literal that could drift from the real helper and silence the banner with every other test still green. - Narrow the handler's dependency to the one method it calls, which also drops an `as unknown as` cast from its test. - Skip the chmod-based test on Windows, where a read-only directory does not block writes so the scenario cannot be constructed; matches the convention already used in config-settings-promotion.test.ts. * chore(codex): restore the handler docstring and isolate the resolver suite Round 4 returned clean; these are its two non-blocking nits. Narrowing the handler param left its JSDoc stranded above the new type, so the function had no hover doc. The resolver suite also read the developer's real CODEX_HOME and shell rc, so anyone exporting one would see it fail locally. |
||
|
|
6a72c8f120 |
fix(codex): preserve runtime config when system source is missing (#9127)
* fix(codex): preserve runtime config without system source * fix(codex): retain baseline when mirror is skipped * refactor(codex): extract deprecated hook-flag normalization Why: codex-config-mirror.ts sat at the 300-line cap, so the missing-source guard could not land without a max-lines disable. * fix(codex): bootstrap a baseline when the mirror is skipped Why: a runtime home seeded outside the mirror (WSL, per-account) never got a baseline while the source was missing, so promotion stayed inert and silently reverted the in-Codex change once the source returned. * fix(codex): stop a synthesized source config from wiping runtime settings Two routes still reached the #9073 data loss after the missing-source guard: - Promotion runs before the guard and, with no ~/.codex/config.toml, created one holding only the promoted keys. The next mirror treated that skeleton as authoritative and deleted every other runtime setting. It needs no missing file: `codex mcp add` inside an Orca-launched Codex plus /model was enough to drop the MCP server for good. Promotion now seeds a brand-new system config from the runtime's ordinary settings, so the mirror round-trips them. - A 0-byte source (half-written, or an unhydrated cloud-synced home) still read as an authoritative empty config and advanced the baseline, making the loss unrecoverable. A blank source is now treated like a missing one. Moves the TOML section model out of codex-config-mirror.ts so promotion can share it without a cycle. --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> |
||
|
|
aab112933e |
Revert "fix(memory): bound OOM-prone accumulators (#10179)" (#10255)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
ef985ed800 |
fix(codex): re-land TUI settings promotion with anchored baseline (#10213)
* Reapply "Preserve Codex [tui] settings across managed CODEX_HOME remirrors (#9475)" (#10085)
This reverts commit
|
||
|
|
8f40ddf328 | fix(memory): bound OOM-prone accumulators (#10179) | ||
|
|
09756dfaff |
Revert "Preserve Codex [tui] settings across managed CODEX_HOME remirrors (#9475)" (#10085)
This reverts commit
|
||
|
|
c8381f3ea7 |
Preserve Codex [tui] settings across managed CODEX_HOME remirrors (#9475)
* fix(codex): promote [tui] settings so they survive the managed-home remirror
Codex TUI preferences (/statusline, theme, terminal title) are written into
the [tui] table of the managed runtime config.toml, but the write-back
promotion allowlist only covered four top-level scalars — so the next mirror
pass rewrote the runtime config from ~/.codex and silently discarded them.
Extend promotion to the [tui] keys the Codex TUI persists (status_line,
status_line_use_colors, terminal_title, theme), keyed as structured tui.*
paths so the same three-way merge (runtime vs baseline vs ~/.codex) applies:
in-Codex changes promote into ~/.codex before the mirror, and outside edits
to ~/.codex still win over stale runtime values.
The byte-preserving upsert moves to codex-config-settings-upsert.ts (max-lines)
and learns [tui] placement: replace an existing bare or dotted key in place,
insert into the first [tui] body, insert dotted beside existing dotted tui.*
keys, or create one [tui] table at EOF — never defining tui twice, including
when the system config holds an inline tui = {...} table.
* Add codex-config-settings-upsert to the CLI tsconfig file list
* fix(codex): keep tui upserts out of array tables
* fix(codex): handle quoted tui config paths during promotion
* fix(codex): harden tui promotion writes
|
||
|
|
407d7afc11 |
feat(telemetry): classify codex trust-grant fallbacks and attribute grant lane (#10001)
* feat(telemetry): classify codex trust-grant fallbacks and attribute grant lane * fix(telemetry): tighten codex trust-grant classification |
||
|
|
c24ebcade5 |
fix(rate-limits): unstick Claude "Limited" usage — respect Retry-After and feed live usage from session statuslines (#9617)
* fix(rate-limits): unstick Claude "Limited" usage and feed live usage from session statuslines The OAuth usage endpoint's 429 Retry-After (~50 min) was ignored, so the 30s-15min automated retry lanes kept landing inside the throttle window and the status bar stayed on a bare "Limited" indefinitely while Claude itself worked fine. - Respect Retry-After on 429: carry it through usageMetadata.retryAtMs and gate automated refetches (activation lane, poll cycles) until it expires; user-directed refreshes still bypass. - Keep the last-known usage snapshot visible through rate-limited windows (24h) instead of dropping it after the generic 30-minute stale threshold. - Add a managed Claude statusLine command that forwards each session's rate_limits (Claude Code >=2.1.80) to a new /statusline/claude loopback route, feeding live usage windows with zero usage-endpoint calls; OAuth polling pauses while the live feed is fresh. User-owned statusLine settings are never overwritten. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(rate-limits): keep last-known window when a statusline post carries only one Statusline payloads may report five_hour and seven_day independently; a partial post must not wipe the other bar to null. Also document the seconds-vs-ms epoch heuristic. Addresses CodeRabbit review on #9617. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(rate-limits): unstick Claude usage with live statusline feed The OAuth polling endpoint is rate-limited; Claude's status often shows "Limited" until the next poll cycle, even when quota remains. Live posts from the statusline command update usage within 100ms, eliminating false "Limited" displays during active sessions. Manages install lifecycle via marker to respect user deletions. Handles Windows payload buffering and guards before curl spawn. Protects against live-post/OAuth-fetch races and cross-attribution during account switches. Gracefully tolerates schema drift in statusline parsing. * test(rate-limits): assert stale outgoing post doesn't affect incoming Capture usedPercent before ingesting and assert it remains unchanged, rather than checking for a specific value. This is more precise and less brittle when testing session switch isolation. --------- Co-authored-by: Dzmitry Bachko <dbachko@users.noreply.github.com> Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> |
||
|
|
e58de71f5e |
feat(codex): real-home routing + self-contained multi-account homes (#9501)
* feat(codex): backfill managed-home sessions into the real Codex home once per host Orca-launched Codex sessions currently land only in the Orca-managed runtime home, so the user's own `codex resume` picker and app history never see them (#4444, #8612). Backfill the managed sessions tree into the real ~/.codex/sessions/YYYY/MM/DD layout once per host: - hardlink first (one physical rollout log), copy as the cross-volume fallback; existing target files are always skipped, nothing in either home is deleted or moved - idempotent; per-file failures leave the completion marker unset so the next startup retries cheaply - JSONL audit log of every link/copy/failure under <userData>/codex-session-backfill/ - honors the custom Codex session source home override, mirroring the existing system->managed bridge WSL managed homes are distro-local and need an in-distro variant; that is a follow-up. * feat(codex): flag-gated system-default real-home routing scaffolding Staged internal flag (default OFF, no settings UI): route the SYSTEM-DEFAULT Codex account at the user's real ~/.codex instead of Orca's managed runtime home. Flag OFF is byte-identical to today; managed (multi-account) selections are unchanged in either state. Routing (flag ON + host system default = no managed account): - CodexRuntimeHomeService.prepareForCodexLaunch / prepareForRateLimitFetch return null so the PTY/env layer injects no managed CODEX_HOME and the rate-limit fetcher + auth-presence gate fall back to ~/.codex (the background poller stops spawning Codex against the managed home — the #5370 auth war). - buildPtyHostEnv strips only a nested-Orca-inherited Orca-owned override (CODEX_HOME matching the private ORCA_CODEX_HOME marker), preserving a user-set CODEX_HOME. Shell-ready re-exports already no-op without the marker. - The headless commit-message Codex path strips the same inherited override. Hook install for the real-home lane (append-last into ~/.codex/hooks.json, trust via the app-server client) lands with the trust plumbing; the managed hook install is skipped for this lane meanwhile. Credit @jellychoco (#8606) for the native-home routing direction. Depends on the codex trust-rpc-grant plumbing for the real-home hook installer. * fix(codex): strip the daemon-inherited Orca CODEX_HOME override for real-home routing The daemon spawns PTYs from its own inherited environment and honors only spawnOptions.envToDelete, so mutating the sparse env object was not enough to strip an Orca-owned CODEX_HOME the daemon already carries. Add the strip to envToDelete for both daemon host-spawn paths, preserving a user-set CODEX_HOME. Verified live via CDP against a sandboxed dev instance (flag ON): an Orca-spawned pane reports empty CODEX_HOME/ORCA_CODEX_HOME, so Codex resolves its own ~/.codex. Adds daemon-path unit coverage (strip Orca-owned, preserve user-owned, no-op when flag OFF). * fix(codex): harden one-time session backfill * test(codex): cover staged cross-volume install * feat(codex): app-server trust-grant client, capability cache, and grant ledger Short-lived codex app-server JSON-RPC client (hooks/list + config/batchWrite, the same pair the Codex TUI 'Trust all' flow calls), run in a bundled ELECTRON_RUN_AS_NODE entry so synchronous launch prep can block on it with a hard deadline and guaranteed child reap. Capability cache modeled on GitCapabilityCache, scoped per execution host (native vs each WSL distro), with a narrow unknown-method/missing-subcommand unsupported predicate. The grant ledger records verified grants so steady-state launches skip the RPC. * fix(codex): grant managed hook trust via codex app-server RPCs in install/refresh Host and WSL installs now grant trust for Orca's managed status hooks through codex's own hooks/list -> config/batchWrite -> re-list verify, scoped to exactly the managed entries; the previous computeTrustedHash lane is the unchanged fallback for incapable/erroring CLIs. getStatus and the removal paths recognize ledger-recorded codex hashes so drift between codex's real algorithm and the replica no longer misreports or strands trust. SSH remote install is untouched by design. * test(codex): cover app-server trust grant client, cache, ledger, and lanes * test(codex): cover commit-message real-home override strip/preserve Adds the two cases for the headless commit-message Codex env under real-home routing: a nested-Orca-inherited Orca-owned CODEX_HOME is stripped, and a user-owned CODEX_HOME is preserved. * test(codex): WSL grant-lane coverage — in-distro invocation and fallback parity * feat(codex): real-home hook installer trusted via the codex app-server grant client With the real-home flag ON and the system-default selection, install Orca's status hook into the user's real ~/.codex before any pane spawns: - entry APPENDED LAST per managed event: codex hook trust keys are positional (source:event:group:handler), so appending keeps every user entry's position and trust record intact; user entries and unknown top-level hooks.json fields are preserved verbatim - trust is granted exclusively through the codex app-server client (hooks/list + config/batchWrite, verified by re-list); Orca never writes [hooks.state] into the user's real config.toml itself - if the grant lane is unavailable (old binary, unsupported RPC, verify failure), the appended entry is rolled back byte-exactly and the host keeps the managed-home lane end to end (PTY env, rate limits, commit messages) via a lane gate on the runtime-home service - one-time pristine backup of the user's hooks.json under Orca's userData; a rolling .bak sits next to the file (existing atomic writer) - hook opt-out sweeps Orca entries from the real home and drops Orca-owned trust records; flag-off downgrade re-arms the existing legacy system-home sweep, which removes the entry and its trust keys cleanly - the legacy system-home sweep is suppressed only while the real-home lane owns ~/.codex/hooks.json, so managed installs cannot delete the entry * fix(codex): resolve the trust-grant entry without requiring electron The grant bridge is reachable from plain-Node CLI entries, where the plain-node entry guard rejects any chunk containing require("electron"). Resolve the bundled session entry from __dirname (root chunk and chunks/ layouts) with an app.asar -> app.asar.unpacked rewrite for packaged runs, instead of electron's app path APIs. * fix(codex): keep session backfill off main thread Use asynchronous, sequential filesystem operations for the one-time rollout backfill, and avoid repeated target-directory probes. Treat inaccessible managed session roots as retryable failures instead of writing a false completion marker. * fix(codex): harden app-server trust grant fallback * fix(codex): install cross-volume session backfill copies atomically On a real Codex home whose filesystem supports no hardlinks (exFAT/FAT, some network mounts), the staged cross-volume copy was installed with a non-atomic copyFile(..., COPYFILE_EXCL) straight into the final rollout-*.jsonl name. An install interrupted mid-copy (app quit, crash, ENOSPC during the deferred run) could strand a truncated rollout that the next run then skips as already-present, defeating the staging design's own guarantee that a failed copy never leaves a partial session behind. Install the fully-staged copy with an atomic rename instead, guarded by an existence re-check so it keeps the never-overwrite contract (and the rename source is the same immutable managed rollout, so any clobber would be byte-identical). Cover the no-hardlink-support target and an interrupted install that must leave no partial in the user's sessions tree. * fix(codex): resolve grant entry from __dirname so plain-node CLI entries stay electron-free The build guard rejects any electron require reachable from plain-node entries; the bridge now maps app.asar to app.asar.unpacked by string replacement instead of consulting electron app paths. CLI typecheck project lists the new trust-grant module graph. * fix(codex): harden trust grant reconciliation * fix(codex): restore trust config permissions on rollback * fix(codex): harden real-home routing cleanup and retries * fix(codex): preserve unicode trust RPC responses * fix(codex): preserve remote env and complete real-home cleanup * fix(codex): preserve real-home lane invariants * test(terminal): isolate replacement idle reset assertion * fix(codex): preserve real-home dotfile links * fix(codex): preserve verified trust grants across launch prep * fix(codex): preserve dangling config symlinks on rollback * fix(codex): don't revoke a just-granted WSL home on a false 'missing' probe The async wsl.exe canonical-path settlement could report the runtime home 'missing' immediately after a verified RPC grant (a false negative — codex had just written and re-listed trust there), which drove the reconciliation 'remove' branch to delete all six granted [hooks.state] tables, leaving a bare [hooks.state] the launching pane read as 'hooks need review'. A 'missing' settlement now revokes only when no successful install ran this generation; a genuinely moved home still resolves to a different path and reinstalls. * test(codex): model codex config/batchWrite faithfully on Windows The grant-lane stub simulated codex by calling Orca's upsertHookTrustEntries, which writes both separator variants for a Windows key (a fallback-lane compat shim real codex never does) — fabricating duplicate tables and whitespace the RPC path never produces, so the byte-stable and no-duplicate assertions failed on win32. Replace it with a single-variant, blank-line-separated writer that matches the real 0.144.x binary's output. * feat(codex): collapse duplicate session listings across Codex roots Backfilled/bridged rollouts are hardlinked into both the real ~/.codex and Orca's managed runtime home, so AI Vault listed each session once per root (#7521). Dedup candidates by rollout file name pre-parse and parsed sessions by session id post-parse, keeping the canonical root: host real home first (unprefixed resume), then the managed runtime home, then other homes. Applies to local, WSL, and SSH-remote scans. * feat(codex): background sqlite index heal for backfilled sessions Codex's own state-DB metadata backfill is one-shot, so rollouts hardlinked in by Orca's session backfill never become visible to Codex's DB-driven surfaces. Extract the app-server stdio JSONL transport into codex-app-server-session (shared with the trust-grant client) and add a bounded, resumable background pass that drives Codex's lazy indexing via thread/read per backfilled session: recent-first, batched onto one short-lived server per batch with small concurrency, ledger + marker so steady-state startups are a no-op, stop-aware on quit, and capability-aware on CLIs without the app-server surface. * fix(codex): preserve session identity during dedup heal * fix(codex): preserve user trust during real-home cleanup * fix(codex): harden real-home heal boundaries * fix(codex): fail closed on unsafe backfill install * fix: harden real-home hook cleanup * fix(ai-vault): preserve execution boundaries and reap children * fix(codex): narrow app-server unsupported detection * fix(codex): bound user hook trust rebase retries per host The rebase lane ran a codex app-server session on every launch prep while a host was stuck (CLI without app-server support, or keys hooks/list cannot match). Gate the transaction on the shared capability cache and add the same 5-minute transient cooldown the grant lane uses, so sweep and legacy-cleanup retries cost plain fs reads instead of a codex session per pane spawn. * fix(codex): enforce real-home resume and heal boundaries * fix(codex): establish real-home lane before cleanup * fix(codex): stop index heal before delayed spawn * fix(codex): protect symlinked rolling backups * fix(ai-vault): preserve resume env deletion through drag * fix(codex): strip inherited Codex homes on mobile real-home resume The mobile resume surface types a bare real-home codex resume into a freshly created pane, but never asked for CODEX_HOME/ORCA_CODEX_HOME deletion at pane spawn, so an agentDefaultEnv-pinned or daemon-inherited Codex home rerouted the resume away from the user's real ~/.codex while the same session resumed correctly on desktop. Share the deletion helper from the AI Vault resume builders and forward it through the mobile launch and session.tabs.createTerminal call. * fix(codex): gate session migration on real-home lane * fix(codex): stop session backfill after opt-out * fix(codex): keep session heal failures retryable * fix(codex): keep session migration state recoverable * fix(codex): retry republished missing session heals * fix(codex): preserve hook symlink trust path * fix(codex): disambiguate POSIX trust paths * fix(codex): align hook trust source paths * fix(codex): harden trust grant lifecycle * fix(codex): restore envToDelete on client invocation type after base reconcile * test(codex): type child.stdout as PassThrough for oversized-output write * Assemble RC: reconcile app-server transport API across PRs Unify on the object RPC surface from the index-heal transport (#8921) while preserving the default-home env strip (#8828) and the narrowed missing-app-server capability signal (#8847): adapt the user-hook-trust-rebase consumer + tests, port envToDelete stripping into the shared session, and route stderr classification through the canonical capability-signal module. * RC: enable system-default real-home routing by default (flag ON) Flip codexSystemDefaultRealHomeEnabled to default ON for this RC's staged rollout (a user can still opt out by setting it false, which stays byte-identical to managed-home behavior). This is the only intended behavior difference between the RC branch and the individual PRs. Updates the two tests that assumed the prior OFF default. * fix(codex): snapshot hooks.json bytes+parse in one read to close real-home clobber race The install/sweep/legacy-cleanup paths parsed hooks.json, then did a separate later read to capture the previous bytes for the pre-write generation guard. A concurrent save (second Orca instance or the user editing the file) could land between the parse and that second read and be silently overwritten. readHooksJsonWithRaw returns the raw bytes and parse from a single read so the guard compares against exactly what it parsed. Adds a regression test that mutates hooks.json mid-RPC and asserts the sweep aborts without clobbering. * fix(codex): sanitize managed account config trust * fix(codex): guard OAuth add for custom providers * fix(codex): persist outgoing managed tokens before real-home lane takeover (PR-C) prepareForCodexLaunch returns null early for the real-home / system-default lane before syncForCurrentSelection runs. If a managed account is still recorded as synced when the selection has dropped to the system default (nulled without a sync pass, or auto-deselect on missing managed auth), a Codex-refreshed token stranded in the shared runtime home is never persisted to its canonical per-account home -> token loss. Read the outgoing managed account's refreshed token back before the real home takes over. The real-home lane implies host === null, so running the managed->system-default transition restores only Orca's runtime mirror from ~/.codex and never writes the real ~/.codex. It is a no-op once the selection has already been reconciled, so the normal select path does not double-write. * fix(codex): preserve refreshes across all default transitions * feat(codex): show system-default/real-home account identity in switcher (PR-B) The account switcher modeled the system-default Codex account as activeAccountId:null with no identity fields, so the null row rendered blank ("System default" / generic subtitle) even though its effective login is whatever ~/.codex/auth.json currently is. Add a CodexSystemDefaultIdentity descriptor {hasAuth, authKind, email, providerAccountId, workspaceLabel} to CodexRateLimitAccountsState, resolved live and READ-ONLY from ~/.codex by the accounts service and returned from listAccounts()/getSnapshot(). The settings switcher now renders the null (system-default) row as that real identity: the OAuth email when signed in, "Custom provider — no usage tracked." for env-key/custom-provider logins (auth.json with OPENAI_API_KEY, or an OPENAI_API_KEY env with no auth.json), and the generic fallback when signed out. Identity is host-scoped (per-distro WSL keeps the generic label). Orca never writes ~/.codex; managed-account switches only touch Orca-owned homes, so the system-default identity stays a stable, displayed source of truth. Usage already routes to the real home via getSystemCodexHomePath, so the switcher now attributes it to a real face. Tests (sandboxed temp homes only): OAuth email/provider resolution, api-key auth.json and env-key (no auth.json) as custom-provider, signed-out, and select/deselect of a managed account never mutating ~/.codex/auth.json. * fix(codex): parse multiline provider pins in OAuth guard * fix(codex): harden managed trust sanitization * fix(codex): harden system-default identity rendering * feat(codex): give each managed account a self-contained CODEX_HOME; retire shared mirror (PR-E) With the real-home flag ON, a host managed account now launches directly against its own codex-accounts/<id>/home instead of the shared runtime mirror + auth.json hot-swap: - codex-home-paths: syncSystemCodexResourcesIntoManagedHome links system resources into any managed home (ownership-marker discipline; never symlinks into / mutates ~/.codex). - runtime-home-service: prepareForCodexLaunch / prepareForRateLimitFetch / syncForCurrentSelection route the per-account home directly and skip the shared-home hot-swap + token read-back; each home keeps its own auth in place (fixes GAP-5 concurrent auth race). Session discovery scans every per-account home. - hook-service / hook-trust-promotion: install/getStatus/refresh accept a runtimeHomePath so hooks + RPC-granted trust land in the per-account home. - service: config mirror into a self-contained home uses the trust- preserving merge so granted hook/project trust survives account switches. - codex-session-root-dedup: rank codex-accounts/<id>/home as canonical managed alongside the shared runtime home. Flag-OFF and the system-default real-home (null) lane are unchanged; the nested-Orca CODEX_HOME===ORCA_CODEX_HOME daemon strip (#5370) is preserved. Sandboxed tests only; ~/.codex is never mutated. * fix(codex): validate per-account home ownership * fix(codex): keep managed rollouts discoverable across real-home opt-out WI-4 lossless migration/rollback validation for pre-E shared-mirror managed accounts. Session discovery gated the per-account home scan on the real-home flag, so opting back out (flag OFF) hid every rollout an account accumulated while the flag was ON — the data stayed on disk but vanished from the AI Vault until the flag flipped back on. Scan a managed host home whenever it holds a sessions/ tree, independent of the flag; a never-enabled install keeps its homes credential-only so opt-out stays byte-identical to today. Forward migration was already lossless (the shared mirror is always scanned) and the opt-out credential read-back already refuses to overwrite a fresher per-account token; add tests locking all three invariants. Sandboxed tests only; ~/.codex is never touched. * fix(codex): migrate stranded shared auth on E takeover * test(e2e): isolate Electron from developer Codex home * test(codex): add real-account validation harness * fix(codex): finish C and E matcher composition * fix(codex): bound validation harness shutdown * test(codex): isolate hook lifecycle user data * test(codex): cover realistic account-home migration * fix(codex): keep standalone home tripwire active * test(codex): fingerprint system auth in validation reports * fix(codex): bind managed homes to account ownership * fix(codex): normalize Windows trust source identity * fix(codex): make Windows trust upgrade transactional * test(codex): use TypeScript pipeline for validation scripts * test(codex): run validation modules through native node * test(codex): allow slow Windows tripwire startup * fix(codex): survive lingering Windows codex login processes in add-account On Windows, codex login can keep running (with descendants) after it has written auth.json, holding OS handles on the per-account managed home (log/codex-login.log). That made doAddAccount's post-login cleanup fail with ENOTEMPTY (rmSync) and left an orphaned codex-accounts/<id>/home. - runCodexLogin now watches for auth.json on Windows and force-kills the login process tree (taskkill /t) if it lingers past a short grace period; the forced exit is treated as a successful login. The 120s timeout path also kills the whole tree instead of only the direct child. macOS/Linux behavior is unchanged. - safeRemoveManagedHome now removes homes with rmSync maxRetries / retryDelay (mirroring the local-worktree-filesystem Windows policy) and no longer lets a cleanup failure mask the original add error. - run-codex-real-account-validation.mjs accepts --temp-parent / ORCA_CODEX_VALIDATION_TEMP_PARENT so the disposable root can live outside %USERPROFILE% on Windows, and fails with an actionable message before creating anything when the temp parent is inside the primary home. The real-home guard is unchanged. * fix(codex): preserve managed-account MCP .credentials.json on per-account-home migration (#8440) Codex file-mode MCP OAuth tokens live in $CODEX_HOME/.credentials.json, keyed by MCP server URL with no account identity of their own. The legacy shared-mirror -> per-account-home migration only carried auth.json, so an existing managed account with authed MCP servers had its tokens stranded on upgrade and silently needed re-auth. Carry the shared mirror's .credentials.json into the same identity-proven per-account home alongside auth.json: only into the single uniquely-matched active account (no cross-account leak), only when the destination has none yet (never clobber a newer file the account authed in its own home), atomic 0600, absent-source no-op. New MCP auth already lands in the per-account home since that home is CODEX_HOME. * fix(codex): preserve Windows reauthentication login flow * test(codex): build real-account validation harness cross-platform on Windows The harness built its app with execFileSync('npx', ['electron-vite', ...]), but npx resolves to a .cmd shim on Windows that execFileSync cannot launch (ENOENT), so the harness could not build its own app there and required --skip-build with a prebuilt out/main/index.js. Extract resolveElectronViteBuildCommand(repoRoot): it runs the repository-local electron-vite JS entry (node_modules/electron-vite/bin/electron-vite.js) with the current Node binary (process.execPath), which resolves identically on macOS, Linux, and Windows with no shell. It throws a clear error if the local entry is missing (install deps or pass --skip-build). --skip-build behavior is unchanged. Add regression coverage asserting the build command uses process.execPath and the repo-local JS entry (not npx), and that a missing entry fails clearly. * fix(codex): version the MCP creds migration independently of the auth marker The auth carry and the MCP .credentials.json carry (#8440) shared one existence-only v1 marker, so any build that stamped the auth-only marker first would strand the MCP store forever. The MCP carry now concludes via its own per-account-mcp-creds-migration-v1.json marker and runs even when the auth marker is already present; ordering is code-enforced instead of landing-discipline-enforced. Also isolate per-account read failures: one stale or deleted account home no longer aborts the whole migration. The broken account stays in the unique-identity ambiguity gate via its stored fields but is never read or written, so the active account still migrates. * fix(codex): fail corrupt managed auth.json without echoing credential bytes A raw JSON.parse SyntaxError from loadOAuthCredentials could carry auth file fragments into logs and the add/reauth error surface. Throw a sanitized error instead; filesystem errors still propagate unchanged. * fix(mobile): give the pairing runtime a disposable home for the E2E boot guard The main-process guard now refuses to start with ORCA_E2E_USER_DATA_DIR set but the real user home, and this was the one caller not updated — the temporary pairing runtime crashed before emitting its pairing URL. * test(codex): canonicalize harness containment guards and retry cleanup Resolve symlinks before the disposable-root containment checks so a symlinked temp parent cannot smuggle the throwaway home inside the primary home, and give the final cleanup rm Windows retry/force so a briefly lingering codex handle cannot strand the credential-bearing root. * test(codex): add lane-aware containment mode to the real-account harness The Windows gate-D run proved strict zero-event whole-profile containment is structurally unreachable with the real-home flag ON: system-default spawn sites deliberately delete CODEX_HOME so native codex resolves the real ~/.codex, and on Windows the binary ignores the USERPROFILE sandbox. Its own volatile runtime churn (root sqlite/WAL/SHM, tmp/, log/) is the shipped Phase-1 design, not a candidate defect. --lane-aware-containment records those designed events without aborting while every other real-home write — auth.json, config.toml, .credentials.json, hooks.json, sessions/, anything unknown — remains a hard violation and still aborts the run. Default behavior is unchanged (strict); the absolute zero-event claim stays carried by macOS runs, where HOME does sandbox native codex. * test(codex): allow the real-account harness to pin the real-home flag off --system-default-real-home off seeds and env-pins the flag OFF so every codex spawn gets an explicit managed CODEX_HOME and native codex never resolves the OS profile. This is the only Windows configuration where the strict zero-event whole-profile tripwire is reachable, and it matches the stable-rollout default; flag-ON runs keep lane-aware classification. * test(codex): correct the flag-off harness comment to kill-switch rationale The rollout ships all codex-home changes at once (no phased rollout), so flag OFF is the emergency kill-switch lane, not the stable default. * test(e2e): canonicalize the isolated E2E home path The disposable HOME lives under os.tmpdir(), whose spelling is an alias on CI (macOS /var symlink, Windows 8.3 RUNNER~1). Git canonicalizes worktree paths, so worktrees created under the aliased home never matched the app's listing — golden core flows and the packaged crash-survival harness failed with 'worktree created but not found in listing'. Resolve the home to its canonical spelling at creation in both the e2e helper and the packaged-app driver. * fix(codex): address CodeRabbit review on the landing PR - carry envToDelete through the mobile agent-resume startup plan so a real-home Codex resume cannot inherit an ambient CODEX_HOME - strip Orca-owned Codex overrides in the commit-message WSL fallback, matching the host fallback - strip ELECTRON_RUN_AS_NODE in the computer-e2e driver like every other home-isolation caller - drop the unused hooksEnabled parameter from isRealHomeCodexHookLaneUsable * feat(codex): ship real-home routing unconditionally, remove the rollout flag The codexSystemDefaultRealHomeEnabled setting is gone from types and constants and the helper no longer consults settings — the system-default real-home lane and per-account homes ship for everyone in one release. This also un-strands profiles that rc-era builds stamped with false (the setting had no UI, so every stored false was a seeded artifact that would have silently kept those users on the legacy mirror forever). The ORCA_CODEX_SYSTEM_DEFAULT_REAL_HOME env override survives strictly as a test-rig control: the containment harness pins the legacy lane for strict zero-event Windows runs, e2e home isolation pins lanes inside disposable homes, and the legacy-lane test suites now route their per-test lane selection through it. --------- Co-authored-by: OrcaWin <alpha-eng@stably.ai> |
||
|
|
c3ab805d12 |
fix(agent-hooks): drain stdin before hook script early exits so agents never hit EPIPE (#8430)
* Fix hook scripts to drain stdin before any early-exit path Generated agent hook scripts and missing-script launchers could exit successfully before consuming the payload written to their stdin, leaving the writer with a broken pipe (EPIPE/ERROR_BROKEN_PIPE) once the reader closed early. Capture stdin (or drain it via a shared epilogue/fast-path guard) before any whole-script success exit across all POSIX, batch, PowerShell, and Git Bash launcher variants, and add a cross-agent lifecycle test suite plus a live Electron verification script to guard the contract going forward. * Harden hook scripts against unreadable managed scripts and add a Claude/ - Extend the POSIX launcher guard to also require `[ -r ]`, not just `-f`/`-x`, so an executable-but-unreadable managed script still drains stdin instead of erroring or silently misbehaving. - Add a verifier case (`verifyClaudeDevinSkip`) that spins up a local HTTP server and confirms the Claude hook never forwards a request that Devin already imported, catching accidental double-forwarding. - Update installer-utils tests and stdin-lifecycle docs to match the new readable-file guard and the added verification case. * Fix hook-launcher verification to derive script paths from the installed Extract the quoted path from the launcher's `if [ -f '...'` clause instead of reconstructing it via join(home, ...), so missing/failing-script test cases can't silently fall through to the real script if the install layout changes. --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> |
||
|
|
69776e8d2b | Upgrade to TypeScript 7 and Electron 43 (#8189) | ||
|
|
4ead072a16 |
Fix Codex WSL runtime status hooks (#7969)
* Fix Codex WSL runtime status hooks * Harden Codex WSL hook restart handling * Harden Codex WSL hook path handling * Fix Codex hook CLI type boundary |
||
|
|
94662c8445 |
feat(codex): write in-Codex setting changes back to ~/.codex config (#7960)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
2c20089080 |
fix(codex): stop 'hooks pending review' from reappearing on every Orca-launched Codex session (#7896)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
99bc693cd5 |
Fix Codex config paths in managed runtime home (#7157)
* Fix mirrored Codex relative config paths Orca mirrors ~/.codex/config.toml into a managed CODEX_HOME before launching Codex. Relative path-valued Codex settings were then resolved from the runtime home instead of the user's real Codex home, which made config loading fail in Orca while the same CLI worked in a normal terminal. Rewrite known relative path settings to absolute paths rooted at the system Codex home while preserving runtime-owned trust sections. * Dedupe Codex TOML line scanner and include path rewrite in CLI tsconfig * Harden Codex config path rewrite and cover managed account homes - Track multiline arrays in the shared TOML line scanner so array lines are never mistaken for table headers or path keys - Escape control characters and reject lone-surrogate unicode escapes so the rewritten runtime config always stays valid TOML - Extend the rewrite allowlist with profiles.* file settings and debug.config_lockfile.* (both can abort Codex config loading) - Rewrite relative paths when mirroring the canonical config into managed account homes (codex login CODEX_HOMEs), anchoring WSL accounts to the Linux-side ~/.codex with posix join semantics --------- Co-authored-by: Neil <neil@stably.ai> |
||
|
|
61503b7666 |
refactor(command-code): split managed hook script (#6807)
* refactor(command-code): split managed hook script * fix(command-code): include split script in cli typecheck |
||
|
|
4eb3e75b9e |
feat(kimi): Kimi Code sessions in AI Vault + agent status hooks
Adds Kimi Code session parsing for AI Vault and managed Kimi agent status hooks. |
||
|
|
08ba730d8e |
feat(devin): managed hooks, sleeping resume, AI Vault (#5380)
* Revert "fix(terminal): add proportional scroll fallback for sidebar resize" (#937) * fix(sidebar): smoothly animate off-screen worktree reveal on click (#1302) Clicking a worktree card whose row lies outside the sidebar viewport caused an instant jump when scrolling it into view. Switching `scrollToIndex` to `behavior: 'smooth'` turns that minimum-distance scroll into an animated slide while keeping `align: 'auto'` so visible cards still no-op (no re-centering). Co-authored-by: Orca <help@stably.ai> * Avoid local scrollback serialization on shutdown (#1821) * Fix PR refresh coordinator test arguments (#2545) * release: v1.4.31 * release: v1.4.31 * release: v1.4.31 * release: v1.4.31 * release: v1.4.31 * release: v1.4.31 * release: v1.4.31 * release: v1.4.36-rc.6 * release: v1.4.36-rc.6 * release: v1.4.36-rc.6 * ci: gate release-cut to the canonical repo so it skips forks (#4815) The cut job checks out main, bumps package.json's version, and fast-forwards main. On a fork with Actions enabled, the scheduled RC cut runs against the fork's main and diverges it on the version line every slot, so that contributor's PRs back to upstream conflict on package.json even when their change never touches it. Gate the job to github.repository == 'stablyai/orca' so it (and the jobs that depend on it) no-op on forks. Canonical scheduled and manual cuts are unaffected. * feat(hooks): install Devin managed status hooks * feat(devin): address hook review, resume, and UI polish - Parse Devin config.json as JSONC; warn on read_config_from overlap - Windows hook command uses forward slashes; APPDATA fallback - Add devin to sleeping-agent resume and UI registries (plan 003/004) - Add hook-service and hook-config-json tests Closes follow-up for plans 002–004 on feat/add-devin-agent. * feat(devin): scan ATIF transcripts for AI Vault Register devin in AI_VAULT_AGENTS, discover ~/.local/share/devin/cli/transcripts (or DEVIN_HOME), parse ATIF JSON sessions, and build devin --resume commands. * docs(devin): clarify stdin-after-start vs bracketed paste * fix(devin): use JSONC for remote install, add partial+APPDATA tests - installRemote: replace readHooksJsonRemote (JSON.parse) with readTextFileRemote + parseJsonc for JSONC compatibility on SSH - Add partial status test (some hooks missing → state:'partial') - Add Windows APPDATA config path test with fallback * fix(devin): address CodeRabbit review — sessionId fallback, parseJsonc errors, comment, i18n * Fix Devin integration edge cases Co-authored-by: Orca <help@stably.ai> * Package Devin JSONC parser dependency Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com> Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Co-authored-by: Orca <help@stably.ai> Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Trevin Chow <trevin@trevinchow.com> Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com> |
||
|
|
f888acdb65 |
Revert Codex launch homes to shared runtime (#4400)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
ec01ffb986 | Preserve Codex runtime config preferences (#3944) | ||
|
|
a00c96ff03 |
Add OpenClaude agent support
Adds OpenClaude as a distinct CLI agent across detection, launch, settings, status, hooks, orchestration, telemetry identifiers, notifications, and README badges. Installs OpenClaude hooks under its own ~/.openclaude config root, handles StopFailure API/model-error events so statuses clear correctly, and keeps OpenClaude tab/status icons distinct from Claude. |
||
|
|
6bf69c3638 |
feat: add amp agent status hook integration (#2864)
* Add Amp agent hook service and /hook/amp status pipeline - Register Amp across managed and remote hook installers so it installs, removes, and reports like other agents. - Add a dedicated Amp plugin service that writes a managed plugin file, preserves user-authored plugins, and exposes consistent status detection. - Wire Amp endpoints and payload normalization through relay/listener, including agent/start, tool call/result, and end/cancel handling. - Extend IPC/preload/web/renderer contracts with ampStatus plus UI catalog label/icon support. - Add tests for plugin installation/removal/status, remote installer behavior, and server acceptance/normalization of Amp hook events. * Fix Amp hook ordering and status normalization Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com> Co-authored-by: Orca <help@stably.ai> |
||
|
|
a6f9a5826e |
Add Command Code agent status tracking
Adds Command Code hook installation, status normalization, launch seeding, and terminal-output fallback detection for working/done sidebar status. Includes review hardening for long-running tool repaint cadence and prompt sanitization across split ANSI chunks. |
||
|
|
a2c71461b4 |
Isolate Codex hooks in Orca runtime home (#2350)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
d4703bd1ab | Restore agent hook opt-out controls (#2778) | ||
|
|
28ba9151a5 | Revert "Add agent hook opt-out controls" (#2739) | ||
|
|
4f81953d10 | feat: add agent hook opt-out controls (#2714) | ||
|
|
d546af1b51 |
refactor to clean up the codebase (#412)
* chore: clean up repo root for faster README visibility - Delete unused images (debug_orca.png, orca_3d.jpg, screenshot.png) - Delete stale design docs from docs/ - Move tsconfig sub-configs, electron-builder config, and vitest config to config/ - Move file-drag.gif to docs/assets/ and design doc to docs/ - Update all path references in package.json, tsconfig.json, and moved configs * fix: remove stale worktree dialog callback dependency |