mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
60456107e65fcf261feb6d9f6ce6adb99bc331f4
17
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6933fd70d7 |
fix(packaging): ship Claude agent SDK with desktop builds (#19042)
* fix(packaging): include Claude agent SDK at runtime
* test(packaging): cover spaced runtime imports
* fix(packaging): verify every emitted main file for bare runtime imports
The packaged-main verifier read two fixed entry files, but rolldown hoists
modules shared by two entries into out/main/chunks. jsonc-parser is reached
only from a chunk today, so nothing verified it, and the agent-hooks entry
the list names contributes no coverage at all. An import that migrates into
a chunk would silently stop being checked -- the same blindness that let the
missing Claude agent SDK ship.
Scan every out/main/**/*.js entry in the asar instead, keeping the two
required-file assertions as a build-integrity check. Measured against the
shipped 1.4.198 app: 93 entries in 72ms, reporting the absent SDK and
nothing else.
Also tighten the specifier match with a (?<![.\w]) lookbehind. Orca has
three registry methods of its own named require(), two taking a string key,
so a minified registry.require('public-a') otherwise reads as a bare module
specifier and fails packaging with a confusing error -- a risk the wider
file set would have multiplied. The lookbehind drops nothing real: detection
over the shipped bundle is identical with and without it.
* test(packaging): cover the missing packaged main entry assertion
The required-file check had no test, so the refactor that split it out of
the scanning loop could have dropped it silently. Removing the assertion
now fails this case.
* docs(packaging): name the embedded-source-string limit of the main scan
ssh-relay-deploy builds a probe script for the REMOTE host as a string, and
its require("node-pty") / require("@parcel/watcher") survive into
out/main/index.js, where this scan counts them as desktop-main imports. Both
are packaged, so it is benign today, but a remote-only dependency added to
that script would fail desktop packaging with a false message -- and the two
obvious fixes (ship the remote dep, or weaken the guard) are both wrong.
Separating an embedded string from real code needs a parser.
* test(packaging): pin the exact import shape oxc emits for the SDK
The fixture only carried the spaced `import (` variant, so nothing pinned
the form a shipped build actually contains. Use the real emitted shape --
`p??=import(`@anthropic-ai/claude-agent-sdk`)`, no space, backticks, and the
`??=` that precedes it -- and keep the spaced variant on the second entry so
both stay covered.
* fix(packaging): keep the main scan able to see a spread require
The `(?<![.\w])` lookbehind also rejected `[...require("pkg")]`, because the
third dot of a spread satisfies it. That trade is not symmetric: excluding a
member call costs a loud release-build failure if it ever misfires, but
excluding a real specifier is this guard going blind -- the failure mode the
whole verifier exists to prevent. Readmit a dot that ends a spread.
Zero occurrences in the shipped bundle today, so this was latent. The chunk
test's asar mock now also emits directory nodes, because real listPackage does
and extractFile throws on them -- that makes the `.js` anchor's load-bearing
role something the tests can actually catch.
---------
Co-authored-by: Merge Sim <sim@local>
|
||
|
|
97eb762b27 |
refactor(packaging): prune declaration and source-map artifacts in one walk (#17659)
* refactor(packaging): prune declaration and source-map artifacts in one walk prunePackagedRuntimeTypeDeclarations and prunePackagedRuntimeSourceMaps were byte-identical apart from their regex, and each did its own full recursive walk of packaged Resources/node_modules (~1.7s per walk). Collapse them into prunePackagedRuntimeTypeAndSourceMapArtifacts, which runs a single walk with the OR of both predicates. The two regexes are disjoint (.d.ts.map never ends in .js.map), so one pass deletes exactly the union the two passes deleted. Neither old function had a production caller outside prunePackagedRuntimeNodeModules, so both exports are replaced by the combined one rather than kept as wrappers, which would have reintroduced the duplicate walk. Also moves prunePackagedZodSources ahead of the filename walk: zod/src is removed wholesale, so traversing it first was pure wasted work. The prunes are independent, so the reorder does not change the result. * fix: correct the one-walk rationale and close the .d.mts coverage gap The comment credited predicate disjointness for making the merge safe. That is not the reason and is misleading: it implies a future overlapping predicate would break the collapse. Passes commute because pruneMatchingFiles only deletes files and never removes directories, so the tree it walks is identical each time — verified by running the old two-walk code with the passes reversed and diffing survivors. Also narrow isPrunablePackagedRuntimeArtifact to isPrunableTypeOrSourceMapArtifact (node-pty prebuilds and duplicate sherpa dylibs are prunable runtime artifacts too, but this predicate returns false for them), and add the missing .d.mts fixture so every branch of the (?:c|m)? alternation is exercised against the exact-survivor assertion. |
||
|
|
0293ebe3eb |
perf(packaging): prune JS source maps from all packaged node_modules (#17638)
Generalizes the @linear/sdk-scoped prune to every packaged dependency, matching the existing type-declaration prune's single-predicate walk over Resources/node_modules. Recovers ~1.01 MB beyond the SDK. Nothing in the packaged app enables Node source-map support (no --enable-source-maps, no setSourceMapsEnabled, no source-map-support require), and the CLI launchers strip NODE_OPTIONS, so these maps were never read. Orca's own main-process maps live outside node_modules and already ship as a separate release artifact. |
||
|
|
9f0b94d9b6 | perf(packaging): prune Linear SDK source maps (#17530) | ||
|
|
fd9125ea8c |
feat(native-chat): Codex structured native chat restructure (#16729)
* feat(native-chat): port structured Codex sessions from restructure-recovery Rebuilds the desktop structured native-chat implementation from brennanb2025/native-chat-restructure-recovery (tip 4e31c08db3) on top of current main as a single commit, scoped to the local Codex path. Ported: - Structured agent-session core: durable record store + single-writer lease, canonical journal, agent-session wire host/attach/eviction/subscribers, `agentSession.*` RPC surface (registered via ALL_RPC_METHODS; host-side mobile allowlist included for wire compat), pty write gate, transcript additions, and the Codex app-server adapter/launch resolution. - Renderer: NativeChatStructuredSession view/composer stack, structured launch path with the single-flight guard, local structured session tabs sync, activation gate + structured inventory (read-only `agentSession.handoffStatus` probe), agent-session tabs in the tab strip, AI-vault structured session activation, and the settings pane with the parent Experimental Chat UI toggle plus the nested "Use updated structured native chat" toggle. New sessions require both flags, agent codex, no prompt, and a local non-WSL, non-Windows-host execution host (structured-native-chat-availability). - Fixes 72c013cea6 (verified Codex launch recovery), 8ddbaf5e3d (defer native terminal view switching affordances), and 4e31c08db3 (release the launch gate after a visibility retry) with their regression tests, including the third-launch-after-retry guard case. - Cross-version agent-session wire test + CI lane, packaging entries (proper-lockfile, agent-tooling asar excludes), and the wire-compat doc section. Deliberately not ported: mobile/ changes, the Claude structured runtime (only the claude-transcript-branch-proof and claude-structured-owner-identity leaf modules remain, backing the kept TUI-recovery arms), the terminal↔chat adoption/handoff flow (`agentSession.adoptTerminal`/`requestHandoff`, the handoff request engine, TUI adoption machinery, orca-runtime adoption methods), renderer switching affordances and their dead leftovers, the hook/subagent-status refactor cluster, and unrelated branch changes. The crash-during-acquisition recovery path (restart handoff adjudication, restore/reverse re-acquire, lease schema handoff keys) is kept because every plain direct launch depends on it; a trimmed handoff coordinator exposes only status/restore/close. Branch edits that targeted files main has since split (ipc/pty.ts, worktrees.ts, rpc/methods/terminal.ts, useIpcEvents, pty-connection, store/slices/terminals.ts, runtime-types, web preload) were re-applied to the split modules, preserving main's newer logic (Windows CIM fallback, browser tab close rework, cold-restore resume flow, dispatcher threading). Known seam: the mobile clipboard image-provenance CONSUMER gate ships (agentSession.send refuses unproven mobile image refs with agent_session_image_untrusted) but the producer hunk in rpc/methods/clipboard.ts stays with the unported mobile cluster, so mobile image sends into structured chat fail closed until that side ports. * fix(native-chat): trust only authenticated local image uploads * fix(build): preserve Windows process-tree patch application * test(windows): include process creation time in addon fixture * fix(build): run windows-process-tree node-gyp from the physical package dir gyp expands the node-addon-api dependency by probing node, whose cwd resolves to the package's physical directory in the store, so the emitted target is a store-relative ../../../../node-addon-api@... hop. gyp then resolves that hop against the rebuild cwd; from the node_modules symlink/junction it escapes the store and configure fails with "node_addon_api.gyp not found" (run 32999886072). Rebuild from realpath(package dir) so both bases agree, matching how the package manager itself runs native install scripts. The regression test replays gyp's expansion+resolution against the planned cwd and fails without the fix. * fix(native-chat): keep chat tabs visible through terminal closes and empty-worktree launches Two proven blockers in the native Codex tab contract: closeTerminalTab pre-empted the canonical unified close. With one terminal left it deactivated the worktree on a terminal/editor/browser-only check, blanking a workspace that still held a renderable agent-session tab; with two or more it pre-picked a successor from terminal entities only, re-stamping the group active before closeUnifiedTab's MRU/neighbor repair could land on the chat tab. Successor choice now defers to the unified contract whenever the terminal has a unified row, and deactivation is gated on the unified renderable count (matching leaveWorktreeIfEmpty), with the legacy pre-pick kept only for terminals without a unified row. A structured session created on an empty worktree was published into the host's headless group while preserveLocalLayout froze the local layout, leaving the tab in store but permanently off screen. A preserveLocalLayout owner now always takes client-owned placement — repairing a rendered leaf whose group record is missing, or materializing a rendered group on a truly empty worktree — and applies the client-derived layout repair while still rejecting host-authored layout. Regression tests drive the real store through closeTerminalTab (git worktree and folder workspace) and the real snapshot applier for the empty-worktree adoption states; all fail without the fixes. * fix(native-chat): close stale turns and retry rejected sends * fix(native-chat): retire hosted rows on structured tab activation * fix(native-chat): preserve rpc defaults across main merge * chore: format remote wire compatibility guide * test(native-chat): cover retry after unconfirmed send * fix(native-chat): reload outbox on session switch * docs(settings): disclose structured chat platform limits * fix(native-chat): await Codex launch-home preparation * fix(codex): align child-process allowlist with async trust bridge * test(identity): update inventory for tab surface refactor * fix(windows): preserve process-tree CRLF patch sources * fix(native-chat): anchor an unmatched chat echo where it was sent (#16117) * fix(native-chat): anchor an unmatched chat echo where it was sent The reported symptom was old user messages replaying below every new turn, so the conversation read as scrambled. The cause was not that the echo failed to match a transcript row. Claude consumes a mid-turn send through a `queued_command` attachment and writes no `type:"user"` record for it, so some echoes can never match, and no amount of matching will change that. The cause was WHERE an unmatched echo rendered: buildMobileNativeChatTransientData appended every pending item after the entire transcript, so it re-read below each turn that landed afterwards. Render each echo directly after the transcript row it was sent against, using the baseline the send already captures. An unmatched echo is then at worst a duplicate in the right position rather than a scrambled one, and it stays visible. Echoes sharing an anchor keep send order; a send with no baseline, or one whose anchor folding dropped, still falls back to the tail. Deliberately NOT fixed by deleting the echo. Inferring from send ordering that an echo can never match, then removing it, loses the user's own text for a message the agent did receive, and it cannot fire in the common case anyway - measured drain groups are 1,017 of size 1 against 55 larger. It also escalates an existing gap: the count pass has no baseline-tail guard, unlike the glue pass, while `messages` is a 40-row window that head-trims, resets on reconnect and grows at the front on loadEarlier, so a false landing there would license deleting a DIFFERENT outstanding message. That count-pass gap is real and left for a separate change; anchoring makes its worst case a duplicate in place rather than a scrambled conversation. * fix(native-chat): preserve folded echo anchors * fix(native-chat): preserve forward-folded echo anchors * fix(native-chat): keep leading folded echoes in place * fix(workspace-cleanup): show git status for every row (#16690) * fix(native-chat): refuse structured chat on every Windows execution path canUseStructuredNativeChat only refused win32 when a project runtime resolved, so folder-workspace keys (and other keys with no project runtime) failed open into structured chat on Windows. Fail closed on win32 unconditionally after the host check, matching the settings copy: local macOS/Linux only; Windows/WSL/SSH stay on terminal chat. * fix(native-chat): restore runtime refusals behind the win32 gate |
||
|
|
f7033e0e70 |
build(windows): drop the packaged node-pty prebuild that can silently replace the patch (#16350)
* build(windows): drop the packaged node-pty prebuild that can silently replace the patch node-pty's loader tries build/Release, then build/Debug, then prebuilds/<platform>-<arch>, and swallows every failure in between. Windows packaging ships both the source build and the prebuild, and only the source build carries Orca's job-object exports (listJobProcessIds, terminateJob, assignCurrentProcessToJob). So an ABI mismatch, a truncated file, or an AV quarantine of build/Release/conpty.node degrades the shipped app to the UNPATCHED prebuild: PTY teardown silently falls back to guessing by PID ancestry, with no error anywhere. That is the failure mode that made #16059 hard to see -- an install that looks fine and quietly cannot own a PTY tree. Removing the fallback turns a silent downgrade into a loud load failure. Scoped narrowly: only win32, and only when the source build is actually present, so a build that legitimately has no build/Release keeps something loadable. macOS and Linux prebuilds are untouched -- they have no patched export to lose. Refs #16059. * fix: delete only the stale conpty fallback, not the whole prebuilds tree Review caught a P0 in the first version of this change, and it was the same defect the PR exists to prevent, pointed at a different target. Orca's own patch removes the `conpty_console_list` and winpty `pty` gyp targets, so a Windows source build emits conpty.node and nothing else. conpty_console_list.node, pty.node, winpty.dll and winpty-agent.exe therefore exist ONLY in prebuilds/. Deleting the tree removed them: - the forked console-list agent throws at require, and its caller resolves null with silent: true, so console-membership probing dies with no log anywhere -- a new silent degradation, in a PR whose thesis is "make it loud"; - node-pty still selects winpty below Windows build 18309, so PTY spawn would fail outright on Server 2019 / Win10 LTSC 2019. Now removes only prebuilds/win32-<arch>/conpty{.node,.pdb}, and only when electronArch matches the host arch -- a cross-arch package copies the host's build/Release, so its presence does not mean it matches the target, and deleting the target-arch prebuild would remove the only loadable binary. The old fixture wrote just conpty.node, so it could not see any of this. It now seeds a realistic prebuilds directory, and four tests assert each sibling survives; all four fail against the broad delete. Credit: review counsel. |
||
|
|
057fbfcffc |
perf(windows): read the process table natively instead of forking PowerShell (#15749)
* perf(windows): read the process table natively instead of forking PowerShell Seven independent readers each forked powershell.exe to run Get-CimInstance Win32_Process, with a wmic fallback that Windows 11 24H2 has removed. On a domain-joined host with PowerShell Transcription enabled by policy, one of them running every ~2s recorded ~289GB across 1.4 million files (#15209). The same scan cost ~700ms and ran per pane (#15036), and a Group Policy or AV block turned it into 'unavailable', which callers read as 'no evidence' -- which is how a PTY tree survives its own teardown (#9045, #10475). A Toolhelp32 snapshot answers the same question with no child process. Measured on Windows 11 with 1050 processes, p50/p95: pid+ppid+name 15.9 / 17.5 ms +memory +command line 30.6 / 33.7 ms Get-CimInstance 706 / 723 ms Two upstream defects needed patching, both found by running it on real hardware. The binding requires Spectre-mitigated libraries our agents do not carry (node-pty is patched the same way). And enumeration stopped after 1024 processes: on a host with 1051 the module returned exactly 1024, and the querying process was itself among the 27 missing -- a truncated snapshot silently hides the descendants teardown is looking for, which is the failure this whole change exists to remove. Migrated: the foreground/descendant reader (the #15209 scraper and the teardown identity gate) and the port scanner's PID attribution. NOT migrated: the memory collector and three identity probes, which need Win32_Process.CreationDate and have no native equivalent. Start time is a proxy for identity anyway; an inherited job handle is the real answer, so those belong with the job-object work rather than here. Packaging follows the windows-native-registry contract exactly: optional, absent from onlyBuiltDependencies so macOS/Linux never run node-gyp, win32-only in the packaged runtime. Asserted by the existing contract test, which also stops pinning a whole source literal that only tested its own formatting. * chore(process): ratchet the child_process allowlist down windows-foreground-process-rows.ts no longer spawns anything, so its allowlist line is stale. The guard fails on a stale entry as well as a new one, precisely so a migrated file cannot keep a slot open and hide the next regression in the same path. * fix(ports): import the process-table reader the scanner uses Missing import: the migration replaced the PowerShell call but the new symbol was never imported, so tsc failed. Vitest transpiles without typechecking, which is why the port-scanner suite stayed green. * fix(deps): sync this branch's lockfile with its patch set Same class as the fix on the tip branch: pnpm records a hash per patched dependency, and this branch introduces the windows-process-tree patch without its lockfile entry matching. Every job here failed at install with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH. Verified with --frozen-lockfile, which is what CI runs and what my local runs were not. * test(relay): drive the relay's Windows fixtures from the native snapshot Two relay cases fed a PowerShell CIM payload through a mocked execFile. That reader is gone, so both failed -- deterministically, on every PR run for this branch and the one above it. I did not catch it because my own verification sweep was 'src/main src/shared config/scripts' and never included src/relay. The relay is a first-class consumer of the process table; leaving it out of the sweep is how a deterministic failure survived six review rounds. |
||
|
|
128e3e335e | fix(packaging): prune non-target native binaries (#12174) | ||
|
|
808299cd1f | fix(cli): avoid Windows PATH status timeout (#9483) | ||
|
|
22db5b78d6 |
Fix Windows bundled ConPTY packaging (#6968)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
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> |
||
|
|
9369708f6b |
Add English localization infrastructure (#4995)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
58b5472477 |
fix(packaging): include @parcel/watcher native addon in packaged runtime
Fix packaged runtime inclusion for @parcel/watcher and its platform native subpackages. Adds pruning/tests for packaged resources and a real watcher integration regression test. |
||
|
|
1b363b4d9c |
Add mobile emulator (#4754)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
819998db04 | build: prune packaged runtime node modules (#4020) | ||
|
|
f2da5fc0a2 |
fix: handle Windows asar paths in runtime dep verifier
Fix release-cut Windows packaging by resolving app.asar entries through listPackage before extracting files in the runtime dependency verifier. |
||
|
|
1007686342 |
fix: package runtime node modules
Fix packaged runtime dependency resolution so installed apps ship the node_modules needed by main, CLI, SSH, hooks, and speech runtime paths. |