mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
c8dba6d72caa60aeb663ec0cd525d0216e485f63
10
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a40183389b |
feat: bound direct SSH reconnect fan-out and recovery (#11003)
* docs: design for direct SSH reconnect fan-out Capture the implementation-ready plan for host-qualified, epoch-fenced SSH reconnect recovery after two rounds of multi-model LLM counsel review. * docs: reconcile SSH reconnect fan-out design * docs: close reconnect design consistency gaps * feat: implement bounded direct SSH reconnect recovery * fix: bound direct SSH retry settlement * fix: harden direct SSH reconnect authority * fix: preserve split SSH retry ownership * fix: preserve SSH split continuation authority * docs: record final SSH reconnect validation * fix: preserve SSH authority through retained and detached state * fix: retain SSH authority across delayed split mounts * fix: close SSH authority recovery gaps * fix: fence stale SSH transport replacement * fix: serialize SSH target teardown * fix: settle SSH teardown failures before reconnect * fix: retire failed SSH reset sessions * test: reconcile current main E2E contracts * fix: close direct SSH reconnect review gaps * fix: fence stale SSH reconnect side effects * fix: close final SSH reconnect lifecycle gaps * test: stabilize current-main reliability gates * test: prove plugin navigation containment * test: make plugin navigation oracle authoritative * test: make plugin navigation oracle deterministic * ci: allow sharded e2e suite to finish * test: wait for runtime pane publication * test: classify pane readiness by error code * test: select close persistence terminal by tab identity * docs: mark reconnect implementation validated --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> |
||
|
|
97cb32c1cc |
fix(terminal): release an abandoned synchronized-output frame on reveal (STA-2694) (#10907)
* fix(terminal): release an abandoned synchronized-output frame on reveal Alt-screen agent TUIs (OpenCode/OpenTUI, Codex, grok) bracket every repaint in `?2026h … ?2026l`. Hiding a pane mid-bracket — which a worktree switch or cold-park lands on routinely, since these brackets are written many times a second — leaves xterm's `decPrivateModes.synchronizedOutput` latched. RenderService.refreshRows checks that latch *before* rendering, so while it holds, every repaint Orca owns is a no-op: the forced render-pause repaint, the plain `refresh()` fallback, and the shared glyph-atlas rebuild all render zero rows while the xterm buffer is perfectly correct. Release the latch at the two reveal repaint entry points so those repaints actually paint. Also adds an OpenCode-shaped alt-screen e2e fixture and spec. The existing inline-TUI convergence spec covers the normal-buffer shape (live block glued to the bottom, history scrolling into scrollback); this covers the full-screen alternate-buffer shape, where nothing scrolls and so no row ever self-heals through the scroll path. Scope note: xterm arms a 1s watchdog that clears this latch on its own, so this closes a bounded window rather than the whole STA-2694 report. The e2e spec passes with and without the production change for that reason; the unit tests are what pin the behavior. Refs STA-2694. * fix(terminal): clear the render model on the plain-refocus repaint path `schedulePaneRevealPresent` — the atlas-preserving path a plain window refocus takes — only called `terminal.refresh()`. xterm's renderers are diff-based: `_updateModel` early-continues on any cell whose code/fg/bg/ext still match the cached model, so a refresh repaints nothing for a pane whose buffer never changed. When an occluded window loses its canvas contents while that model stays populated, the refresh skips exactly the cells that went stale and the pane keeps compositing pre-hide pixels — until a window resize reallocates the model, which is the repair users find by hand. Clear the model first (`RenderService.clear()` → renderer `clear()` → `_clearModel(true)`) so the refresh becomes a guaranteed full repaint. That drops cached cells and glyph vertices but NOT the texture atlas, which is shared by every same-config terminal and whose mid-stream wipe re-arms xterm's page-merge garble race (xterm.js #4480) — the reason this path is atlas-preserving in the first place. Also covers the DOM-renderer fallback in `resetWebglTextureAtlas`: `clearTextureAtlas()` is what invalidated the model on the WebGL path, so a pane without an addon had nothing invalidate it and hit the same skip. Scope note: the e2e spec guards buffer/geometry convergence across the hide/reveal boundaries and adds idle-agent and headful desktop-hide cases, but it cannot observe a stale canvas — both oracles built for that (canvas-vs-buffer ink sampling, screenshot-vs-forced-repaint) were proven blind by injecting the defect, and the spec header documents why. The unit tests pin the ordering and the atlas-preservation invariant. Refs STA-2694. Co-authored-by: Orca <help@stably.ai> * docs(terminal): hand off the STA-2694 reveal-artifact investigation Records both fixed defects with their xterm mechanisms, the reveal/wake call graph, why every e2e oracle for a stale canvas was proven blind, how to arm the in-app render-desync sentinel on real hardware, and the one unverified lead (dimension staleness) that would explain why a window resize specifically is the repair users find. Refs STA-2694. Co-authored-by: Orca <help@stably.ai> * Revert "fix(terminal): clear the render model on the plain-refocus repaint path" This reverts commit |
||
|
|
b232df732b | fix(terminal): make remote agent sessions host-authoritative (#9687) | ||
|
|
f9f3cd2fbe | fix(terminal): prevent reconnect from killing live daemon sessions (#9804) | ||
|
|
cc44acaaa3 | Fix Windows ConPTY OSC color reply leaks at the PTY owner (#9651) | ||
|
|
c0f0810dd9 |
Fix native Windows PTY startup query handling (#9500)
* Fix native Windows PTY startup query handling * Fix daemon boot smoke protocol lookup * Fix Windows daemon repro protocol lookup |
||
|
|
7adda25b0a |
fix(daemon): retire empty current-generation daemons (#9277)
* fix(daemon): retire empty current-generation daemons Co-authored-by: Orca <help@stably.ai> * fix(daemon): retire empty daemons on disconnect Co-authored-by: Orca <help@stably.ai> * test(daemon): authenticate Windows lifecycle harness Co-authored-by: Orca <help@stably.ai> * test(daemon): assert remaining shutdown budget Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai> |
||
|
|
1def694e80 |
Add native chat skill picker with host-aware discovery (#9480)
* Add native chat skill and command picker with host-aware discovery Adds a unified, keyboard-first skill and command picker to native chat that: - Uses agent-native invocation syntax (slash for Claude/OpenClaude/Grok, dollar for Codex) - Discovers skills only on the pane's execution host (local, WSL, SSH-unavailable, or runtime) - Groups or separates commands and skills per agent configuration - Deduplicates by canonical path but preserves visibility through all contributing roots - Handles IME composition, loading states, and errors without claiming PTY-level control - Records picker telemetry (open, item accepted, send classification, discovery outcomes) - Extends shared agent profiles to define per-agent skill grammars and source ownership * Remove obsolete reference and design documentation Clean up stale design specs, implementation plans, and investigation notes from docs/reference/. These documents predate the current implementation and are no longer actively maintained or referenced by the codebase. * Extract shared skill discovery utilities and add skill invocation envelo - Move skill comparison and source classification to shared module for native/WSL reuse - Extract display text sanitization to prevent control/zero-width character spoofing - Add native-chat command envelope parser and surfacer for skill invocations - Extend discovery timeout backstop to account for WSL metadata read sequence * Localize skill picker UI for Spanish, Japanese, Korean, Chinese Translate skill picker UI strings including commands, skills, loading states, error messages, and scope labels for the new skill picker feature across four language locales. * Fix skill picker bugs and improve code robustness - Fix i18n plural handling: rename `count` to `sourceCount` to prevent unintended plural-key resolution in localized strings - Fix skill discovery array mutations: copy `root.providers` to prevent bugs during dedup merge - Fix image attachments being silently dropped when message text starts with /skill or agent prefix - Extract `quoteBashString` utility for WSL command code reuse across builders - Add line-separator safety characters (0x2028/0x2029) to skill display filter - Remove stale doc reference links and clarify inline comments * Add reference docs for git compatibility and headless Linux server setup Track previously untracked operational guides in `docs/reference/` that explain Git binary compatibility requirements across host types and how to run `orca serve` on headless Linux. Update AGENTS.md and README.md to link to these references. |
||
|
|
25ecf2eea2 |
fix: reconcile SSH repo rows after host re-add (#8201)
Co-authored-by: Orca <help@stably.ai> |
||
|
|
299bc421e2 |
feat(mobile-pairing): combobox with manual network address entry (#6501)
* docs(spec): manual network address entry for mobile pairing
* docs(plan): manual network address entry for mobile pairing
* docs(plan): fix two test-spec issues in Task 1
* feat(mobile-pairing): add parseManualNetworkAddress validator
* docs(plan): fix buildComboboxEntries filter rule
* feat(mobile-pairing): buildComboboxEntries for network interface combobox
* feat(mobile-pairing): combobox with manual address entry
* docs(spec): align buildComboboxEntries behavior with corrected plan
* fix(mobile-pairing): use text-destructive token for inline error
* fix(mobile-pairing): route Use row through translate() with i18next interpolation
* refactor(mobile-pairing): extract NetworkInterfaceCombobox shared by MobileHero and Settings section
The Popover + Command + manual-entry UX lived only in the Settings →
Mobile → Network Interface section. The mobile pairing screen
("Step 2 of 2 — Pair this computer") had its own copy of the same
Select-based dropdown that did not support manual address entry. A
user trying to pair with a Tailscale MagicDNS hostname from the
pairing screen could not enter it.
Extract the typeable combobox into a shared
`NetworkInterfaceCombobox` component. Both surfaces now render the
same Popover + Command with manual address entry, the `Use "..."`
row, the inline validation error, and the `(custom)` trigger label.
Settings keeps its own Generate QR button, Refresh + Tooltip, and
Tailnet accordion around the combobox. The pairing screen keeps its
existing layout (label + combobox + refresh icon).
Net deletion: ~160 lines. Net behavior gain: manual address entry is
now reachable from both surfaces, not only Settings.
* style(ui): give CommandInput a visible background so the search box is not lost
The Popover content above the CommandList renders the cmdk CommandInput
with only a thin bottom border. Against a white popover background it
visually disappears, especially in the mobile pairing screen where the
popover sits inside a dark phone mockup. Add a subtle `bg-muted/30` +
`py-1` so the input row is unambiguous, without changing the input's
shape or behavior.
* fix(mobile-pairing): drop cmdk CommandItem, use plain buttons inside Popover
In `pnpm dev` HMR cycle the cmdk CommandItem `onSelect` dispatch was
unreliable — clicking the item fired the synthetic event but the parent
React state never received it, so the trigger label never updated after
the user picked a manual address or a refreshed interface.
Replace the `Command` + `CommandItem` primitives inside
NetworkInterfaceCombobox with a native `<input>` + `<button>` list
wrapped by Radix `Popover`. The list now responds to the user's first
click without any intermediate effect that could be skipped in dev mode.
The combobox keeps the same props contract, the same placeholder, the
same inline validation, and the same `Use "<address>"` row at the
bottom of the list.
Update MobileNetworkInterfaceSection.test.tsx selectors from
`role=option` (cmdk's) to `role=button` so the integration test still
asserts the right element. All 479 feature tests still pass.
* debug(mobile-pairing): log handleSelect* invocations to confirm click path
* fix(mobile-pairing): commit on pointerdown to beat Radix Popover close race
In dev mode Radix Popover's close-on-pointerdown handler occasionally
fires before React's synthetic click dispatch reaches the option button,
so the parent's selectedAddress never updates after the user picks a
manual address. Bind the commit handler to pointerdown (synchronous,
before any pointer-up / click synthesis) and call event.preventDefault()
to avoid text-selection side effects. Keep onClick as a fallback so
keyboard / touch / programmatic-dispatch paths still work.
* fix(mobile-pairing): keep manually-typed addresses across network refresh
`selectRefreshedNetworkAddress` used to fall back to the first OS
interface whenever `currentAddress` wasn't in the OS-enumerated
list — so a user who typed a Tailscale MagicDNS name saw their
selection snap back to LAN every time `loadNetworkInterfaces`
returned. Treat manual entries as sticky by passing an
`isManual` flag from the caller; `selectRefreshedNetworkAddress`
now keeps the address when the caller says the user typed it.
`MobilePage` tracks `addressIsManual` alongside
`selectedAddress`: `handleAddressChange` flips it on when the
picked address is not in the OS list, and `loadNetworkInterfaces`
passes it through so refresh keeps the choice.
* chore(mobile-pairing): remove debug logs and sync new-combobox-listbox i18n key
* fix(mobile-pairing): address CodeRabbit review on manual-address lifecycle
Three real bugs from review, plus a regression test:
1. NetworkInterfaceCombobox in MobileHero was disabled when
`networkInterfaces.length === 0`, which locked users out of the
only path to type a manual address during a transient empty
discovery. Pass `disabled={false}` and let the combobox's
own empty-state copy explain the situation.
2. `selectRefreshedNetworkAddress` returned `undefined` whenever
`interfaces.length === 0`, even if the user had a manual
address and `currentAddressIsManual` was true. Keep the manual
address so a recovering discovery doesn't clobber it.
3. `loadNetworkInterfaces` could rewrite `selectedAddress` (e.g.
when a refresh swaps to a freshly-discovered tailnet) but never
updated `addressIsManual`, so the next refresh could revert
the user back to LAN. Re-derive `addressIsManual` from the
new address after every refresh.
Adds a regression test in
`mobile-network-interface-selection.test.ts` exercising the
empty-refresh + manual path.
* style(mobile-pairing): trim disabled-false comment to two lines
* refactor(mobile-pairing): replace typeable combobox with select + custom-address dialog
The Settings/MobileHero network selector used a Popover+search-input hybrid
that looked uneven and hid its validation error behind the open popover.
Replace it with a plain Select of discovered interfaces plus an
'Add custom address…' footer row that opens a small dialog for entering a
Tailscale hostname or static IP. Drops the 'MagicDNS' jargon for plainer
copy, keeps the '(custom)' trigger label, and routes all strings through
translate() with real es/ja/ko/zh translations. Removes the now-dead
buildComboboxEntries helper. Also adds the missing scrollbar-sleek class
the old list omitted (was failing pnpm lint).
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: ppw-stack <ppw-stack@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
|