Commit Graph
934 Commits
Author SHA1 Message Date
JinjingandOrca 1a66cc99a0 ui(orca-yaml): differentiate first-time vs re-prompt trust dialogs (#1556)
The orca.yaml trust dialog now adapts copy and layout based on whether
this is a first-time approval or a re-prompt after the script changed.
Re-prompts lead with '<repo>'s setup script changed — run the new
version?' so users understand why they're being asked again.

Restyles the 'always trust' checkbox as a card and threads a
previouslyApproved flag from ensureHooksConfirmed into the dialog.

Co-authored-by: Orca <help@stably.ai>
2026-05-07 19:35:13 -07:00
Jinwoo HongandOrca 49b250a0f3 Settings: rephrase phone-fit-hold copy to drop third-party brand name (#1554)
Co-authored-by: Orca <help@stably.ai>
2026-05-07 18:19:42 -07:00
Brennan BensonandOrca 5a2a32b614 feat(agent-dashboard): default-on, remove experimentalAgentDashboard toggle (#1538)
Co-authored-by: Orca <help@stably.ai>
2026-05-07 17:16:51 -07:00
Brennan BensonandOrca 5bb147b897 Remove pty-output developer-permission detector (#1545)
Co-authored-by: Orca <help@stably.ai>
2026-05-07 17:12:35 -07:00
Jinwoo HongandOrca 22b63a0191 Mobile: indefinite phone-fit hold + configurable auto-restore (#1532)
Co-authored-by: Orca <help@stably.ai>
2026-05-07 16:47:31 -07:00
JinjingandOrca 3591d89464 feat(gh-project): drag to resize project view columns (#1551)
Per-scope persisted column widths via fr-weight redistribution between
adjacent column pairs, so the table fits its container without growing.
Also relocates "Start workspace from issue" button into GHEditSection and
expands comment composer with a labeled send button.

Co-authored-by: Orca <help@stably.ai>
2026-05-07 16:32:12 -07:00
Neil e65edd7a74 fix(sidebar): reserve worktree scrollbar gutter
Always reserve the workspace sidebar scrollbar gutter and keep the worktree cards separated from the scrollbar lane.
2026-05-07 16:02:33 -07:00
7fb5363296 feat(cli): tab switch --focus surfaces the browser pane (#1498)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Maciej Kobuszewski <maciej.kobuszewski@pergam.in>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
2026-05-07 01:48:39 -07:00
45d05c3699 Add Kagi search support with encrypted private session links (#1434)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
2026-05-07 00:40:38 -07:00
NeilandOrca ebc38b06e0 Linear: paste only URL as draft on workspace create (#1530)
Co-authored-by: Orca <help@stably.ai>
2026-05-06 23:48:11 -07:00
Neil 7b83b2dcdc fix: avoid repeated macOS privacy prompts (#1524)
* fix: avoid repeated macos privacy prompts

* fix: reduce background worktree permission probes

* chore: pin oxlint for ci

* fix: preserve optional rpc params with zod 4.4

* fix: preserve optional inline rpc params with zod 4.4
2026-05-06 23:30:03 -07:00
Neil 43a258951f fix(feedback): enforce anonymous submissions (#1528) 2026-05-06 23:23:58 -07:00
NeilandOrca 5bdeb018d5 feat(feedback): anonymous opt-in for PR tag + contact (#1521)
* feat(feedback): let anonymous users opt in to PR tag + contact

When 'Submit anonymously' is checked the feedback dialog now smoothly
expands to reveal two optional fields:

- GitHub username \u2014 we'll @-mention them on the fix PR
- Email or x.com handle \u2014 we'll reach out when it's fixed

The animation uses a grid-rows 0fr\u21921fr transition so it expands
naturally without measuring DOM. New fields are forwarded through the
IPC + main-process proxy as 'anonymousGithubLogin' and 'anonymousContact'
so the backend can tell self-typed handles apart from verified gh
identity. Backend changes (slack message + route) ship in
orca-marketing-website.

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

* feat(feedback): split anon contact into email + x.com, tighten copy

Address review:
- move 'all optional' wording up to the top header line
- drop the inline 'we'll tag you on the PR' helper (placeholder says it)
- split the single contact input into two separate inputs (email +
  x.com handle), each with its own placeholder

IPC field rename: anonymousContact \u2192 anonymousEmail + anonymousX. Backend
PR is updated to match before either side ships.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-06 20:08:12 -07:00
NeilandOrca 8d0b7b032a feat(pi): wire pi panes into the unified agent-hooks pipeline (#1501)
Co-authored-by: Orca <help@stably.ai>
2026-05-06 17:26:50 -07:00
buf0-bot[bot]andorca-bug-scan-bot 3e3e30d38a fix: address pr-bug-scan findings from #1410 (#1420)
Extended removeRepo in repos.ts to drop lastVisitedAtByWorktreeId entries belonging to the removed repo, preventing monotonic growth of timestamps for deleted repos.

Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
2026-05-06 17:20:31 -07:00
buf0-bot[bot]andorca-bug-scan-bot 884cc6d622 fix: address pr-bug-scan findings from #1409 (#1422)
Fixed pty-connection passphrase wait gate: added 'disconnected' as terminal status (only after seeing a non-disconnected state) so cancel resolves; added waitTeardowns registry so dispose() actively u

Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
2026-05-06 17:20:28 -07:00
Neilandorca-bug-scan-bot 5dd48c7315 fix: address pr-bug-scan findings from #1396 (#1517)
Fix tab profile use-default fallback to default profile and destroy
all sibling webviews on workspace profile switch.

Reapplied on fresh origin/main; supersedes #1460.

Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
2026-05-06 17:19:26 -07:00
buf0-bot[bot]andnwparker 24b5fe2662 fix: filter DEFAULT_APP_FONT_FAMILY from terminal font picker (#1461)
Rebased buf0-bot #1461 onto current main — the original branch was
71 commits stale and would have reverted #1485 (Cmd/Ctrl+F search) and
#1429 (instant theme transitions).

Co-authored-by: nwparker <nwparker@users.noreply.github.com>
2026-05-06 16:53:04 -07:00
Brennan BensonandOrca 21c3c9f16f refactor(shortcuts): remove Cmd-hold number-badge hint UI (#1412)
Co-authored-by: Orca <help@stably.ai>
2026-05-06 15:27:57 -07:00
9f8bf81c38 feat(source-control): commit, push, pull, and sync actions in panel (#1211)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Alexander Saavedra <mralexsaavedra@gmail.com>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
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: brennanb2025 <brennankbenson@gmail.com>
2026-05-06 15:03:52 -07:00
Jinjing 5c7e5f2f1d fix: default workspaces grouping to projects (#1513) 2026-05-06 14:51:37 -07:00
Jinwoo HongandOrca f4a238b937 fix(terminal): preserve scrollback when captureBuffers runs during a transient empty-render window (#1509)
Co-authored-by: Orca <help@stably.ai>
2026-05-06 13:24:38 -07:00
Brennan BensonandOrca 88f04eb6b3 fix(dashboard): unstick bold codex inline-agent rows after retention (#1494)
Co-authored-by: Orca <help@stably.ai>
2026-05-06 13:10:25 -07:00
Jinwoo HongandOrca bba744a8cb fix(mobile): use neutral camera permission copy (#1504)
Co-authored-by: Orca <help@stably.ai>
2026-05-06 11:45:37 -07:00
Brennan BensonandOrca be2b30f1ad feat(settings): focus search on Cmd/Ctrl+F and fix empty section headers (#1485)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 20:06:42 -07:00
Jinwoo HongandOrca 30b6aaf638 fix(terminal): close SIGKILL race for #217 + preserve scrollback on worktree sleep (#1454)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 19:26:44 -07:00
Jinwoo HongandOrca 087c00b02e Mobile: stabilise connection + terminal-fit fixes + share one RpcClient per host (#1481)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 18:58:13 -07:00
Brennan BensonandOrca c28c06a9c2 fix: focus the right pane after clicking an agent (#1451)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 18:01:47 -07:00
NeilandOrca 806ee58585 fix(pi): prefill linked issue URL via env var to bypass paste-readiness race (#1477)
When the new-workspace draft flow targets pi (e.g. user picks a GH issue
in the smart input + selects pi as the agent), the URL was supposed to
land in pi's input box as an editable draft. It didn't, because pi has
no `--prefill` flag and our bracketed-paste-after-ready path waits for
1.5s of stream silence after `\x1b[?2004h` — pi's startup banner
(Skills/Prompts/Extensions/conflicts) prints continuously for 5+ seconds,
which keeps the quiet-timer resetting until the 8s budget expires and
the paste is dropped. Claude works because of `--prefill`; codex works
because its startup is short enough to hit the quiet window.

Fix mirrors Claude's `--prefill` semantics for pi:

- Orca's pi overlay now installs a tiny `orca-prefill.ts` extension
  alongside the existing titlebar spinner. On `session_start` it reads
  `ORCA_PI_PREFILL` and calls `pi.ui.setEditorText(text)`, then deletes
  the env var so subsequent /new sessions don't re-prefill.
- `TuiAgentConfig` gains `draftPromptEnvVar`; pi sets it to
  `ORCA_PI_PREFILL`.
- `buildAgentDraftLaunchPlan` returns `{ launchCommand: 'pi', env: {...} }`
  for env-var agents; the env is plumbed through `startup.env` into
  `pty:spawn` (already supported by pty-connection.ts).

The launched shell command stays a clean `pi` — no `FOO='...' pi` prefix
typed into the terminal — and the readiness race is sidestepped entirely.

Co-authored-by: Orca <help@stably.ai>
2026-05-05 17:37:05 -07:00
NeilandOrca e49d90bee4 fix(gh-project): diagnose env-shadowed gh tokens in auth errors (#1478)
* fix(gh-project): diagnose env-shadowed gh tokens in auth errors

`gh auth refresh -s project` silently no-ops when GITHUB_TOKEN/GH_TOKEN
is exported in the user's shell — gh prefers env tokens and refuses to
modify them, exiting 0. Users follow the canned remediation, see no
error, retry, and stay stuck.

Add a one-shot `gh auth status` probe (gh:diagnoseAuth IPC) that:

- Detects env-shadowed credentials and rewrites the fix to `unset
  GITHUB_TOKEN` plus a grep to find where it's exported.
- Detects missing gh install, plain missing-scope on a keyring login,
  and SAML SSO authorization.
- Surfaces a tailored multi-button error UI in ProjectViewWrapper and
  ProjectPicker instead of one canned 'Copy command'.

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

* fix(gh-project): address review feedback

- Cross-platform shell guidance: PowerShell commands on Windows
  (Get-ChildItem Env:, Remove-Item Env:, [Environment]::SetEnvironmentVariable)
  via navigator.userAgent platform check.
- Use `window.api.shell.openUrl` for the docs button instead of
  `window.open`, matching SidebarToolbar's external-URL pattern.
- Tighten gh auth status parser: accept single-label hostnames and
  optional trailing colon; recover host from the inline 'Logged in to
  <host>' line so a missed section header never silently drops accounts.
- Add tests for multi-host output and host-recovery fallback.
- Drop dead command/copy locals in ProjectViewWrapper.ErrorState by
  short-circuiting the auth-error case before they're computed.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-05 17:36:27 -07:00
Jinwoo HongandOrca 7f2f39b804 feat(mobile): pairing paste flow + Keychain-backed device tokens + deep link (#1475)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 17:14:08 -07:00
Jinwoo Hong 4140d6a4c0 Revert "feat(mobile): pairing paste flow + Keychain-backed device tokens (#1452)" (#1474)
This reverts commit 55d3a42079.
2026-05-05 16:29:00 -07:00
NeilandOrca d3388603bb feat(new-workspace): inline create-branch row, scoped suggestions, name under Advanced, tab/focus polish (#1469)
* feat(new-workspace): branch-tab create row, scoped empty hints, name under Advanced, focus polish

- Branch tab autocomplete now offers "Create new branch <name>" instead of a
  separate + button + dialog (replaces the original UX from #1408 / #1400).
  Suppressed when the typed query exactly matches an existing branch.
- "Use <X> as workspace name" row is restricted to Smart mode; on dedicated
  source tabs (GitHub/Linear/Branch) it was off-topic noise.
- Per-mode empty-state hints ("search GitHub PRs and issues", "find a branch
  or create a new one", etc.) replace the generic message.
- When a source (PR/issue/Linear/branch) is selected, the auto-derived
  workspace name is exposed as a "Name" input under Advanced where it can be
  reviewed/overridden. With an explicitly typed name the smart input itself
  is the name field, so no duplicated control.
- Forward Tab from the Repo combobox now skips the Smart/GitHub/Branch/Linear
  segmented control and lands directly in the search input. Shift-Tab from
  the input still focuses the active tab trigger so the segmented control is
  reachable in reverse. Implemented via a focusCapture interceptor on
  TabsList that distinguishes outside-entry from intra-list moves and from
  the input's own shift-tab.
- Trigger checkLinearConnection() on mount so the "Connect Linear in
  Settings" hint isn't shown stalely when the composer is the first
  Linear-aware surface to render in the session; gate the disconnected
  message on linearStatusChecked.

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

* fix(new-workspace): Enter commits typed text while results are stale

When the user types faster than the 200ms search debounce, rows and
commandValue still reflect the previous query, so Enter would silently
pick a stale source row (e.g. a PR from the prior letters). Treat
results as stale while loading or while debouncedQuery hasn't caught up
to the input value, and commit the typed text via onValueChange instead.

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

* fix(new-workspace): suppress stale source rows in autocomplete while typing

Source rows (GitHub items / branches / Linear issues) are driven by
debouncedQuery, so they're stale until the user pauses for the 200ms
debounce. The previous attempt only short-circuited Enter in the
input's onKeyDown, but cmdk's Command component has its own Enter
handler that still fires onSelect on the highlighted (stale) row.

Filter source rows out of the rows list itself when debouncedQuery
hasn't caught up to value, leaving only the typed-text row (use-name
in Smart, create-branch in Branches). With no stale rows present,
neither cmdk nor our own handler can pick a wrong source on Enter,
and the popover gives visual feedback (collapses to the typed-text
row) while results catch up.

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

* fix(new-workspace): keep stale results visible, force highlight to typed-text row

Previous attempt removed source rows while debouncedQuery hadn't caught
up to value, which caused funky disappear/reappear flicker as the user
typed (rows present briefly while fresh, gone after the next keystroke).

Keep all source rows visible at all times to preserve continuity, but
control which row is highlighted while stale:
  - Smart/Branches: force highlight onto the typed-text row (use-name /
    create-branch) so cmdk's Enter handler commits the typed text instead
    of a stale issue/PR/branch.
  - GitHub/Linear: no typed-text fallback row exists, so clear the
    highlight; the input's onKeyDown falls through to onPlainEnter rather
    than picking a stale source.

Also fixed the input's Enter handler to fall through to onPlainEnter
when no row matches the (possibly empty) commandValue, so the keypress
isn't inert in the cleared-highlight case.

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

* feat(new-workspace): auto-highlight matching source for #NNN, GH URLs, Linear IDs

When the typed value is unambiguously a source reference, snap the
autocomplete highlight onto the matching source row once it appears
instead of leaving it on the typed-text fallback. Enter then picks the
intended source.

Recognized patterns:
  - GitHub shorthand: #1234
  - GitHub URL: https://github.com/<owner>/<repo>/issues/123 or /pull/123
  - Linear identifier: STA-123 (case-insensitive [A-Z][A-Z0-9_]*-\d+)

Stale-results behavior is unchanged: while debouncedQuery hasn't caught
up to value, the typed-text row stays highlighted (Smart/Branches) or
the highlight is cleared (GitHub/Linear) regardless of intent.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-05 16:27:20 -07:00
Brennan BensonandOrca 8de43cd3b4 fix(sidebar): stamp lastActivityAt on first worktree discovery (#905)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 16:17:51 -07:00
Jinwoo HongandOrca 55d3a42079 feat(mobile): pairing paste flow + Keychain-backed device tokens (#1452)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 16:09:26 -07:00
JinjingandOrca ddb732cf34 Support spritesheet pet imports for Sidekick (#1472)
* WIP: Changes before auto-review fixes

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

* auto-review-fix iteration 1

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

* fix: plumb manifest.fps for detected-frame bundles

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

* fix: address lint errors

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-05 15:56:54 -07:00
buf0-bot[bot]andorca-bug-scan-bot a32b120c11 fix: address pr-bug-scan findings from #1385 (#1462)
Wrapped FirstLaunchBanner handlers' bodies in try/finally so inFlight resets even if fetchSettings rejects, preventing the banner from going permanently inert.

Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
2026-05-05 15:25:56 -07:00
buf0-bot[bot]andorca-bug-scan-bot 7268e3f55c fix: address pr-bug-scan findings from #1442 (#1468)
Fixed two TaskPage resume-state regressions: the debounced GitHub search now persists even when activeTaskPreset is non-null (drops the guard, persists current preset+query), and re-added the mid-sess

Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
2026-05-05 15:21:40 -07:00
3b0dda595d fix: pr-bug-scan findings from #1444 (#1466)
* fix: address pr-bug-scan findings from #1444

Threaded linkedPRNumber through all ChecksPanel force-refresh paths; gated useComposerState's PR-URL-from-name recovery on selected repo slug match; wrapped main-process linkedPR fallback gh pr view i

* fix: satisfy react-hooks/exhaustive-deps in selectedRepoSlug effect

Extract selectedRepo?.path into a const so the effect's only dep is
the path string, removing the missing-dependency warning.

---------

Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
Co-authored-by: Neil <neil@nousresearch.com>
2026-05-05 15:09:28 -07:00
JinjingandOrca 2f79017d18 fix(source-control): hide commit input when there are no uncommitted changes (#1448)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 12:23:26 -07:00
Brennan BensonandOrca 6f2e31afad feat(telemetry): PR 4 — wire 7 core events to call sites (#1433)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:57:51 -07:00
Brennan BensonandOrca 0a2e5aa8f7 Refresh first-launch telemetry banner copy (#1445)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:47:57 -07:00
JinjingandOrca 6a7cd2c9ae fix(github): link create-from-PR worktrees back to their PR (#1444)
When a worktree is created from a PR via the source picker, the new
local branch differs from the PR's head ref, so the branch-keyed PR
lookup misses and the worktree card shows no PR strip. Pass the
worktree's linkedPR number through the IPC call and fall back to a
number-based lookup in the main process. Also recover linkedPR from
a PR URL pasted into the workspace name when the user skips the
source picker. PR strip now wraps the whole row as the PR link.

Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:43:13 -07:00
Jinwoo HongandOrca 705be9e312 feat(status-bar): consolidate memory + sessions into Resource Usage segment (#1415)
Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:38:18 -07:00
JinjingandOrca bb8b9765e1 fix(tasks): align Tasks-page header with sidebar nav row (#1443)
Two related top-band issues:

1. Non-workspace view: Tasks page used pt-3 above its X/source-icons row,
   placing the cluster's center 6px below the sidebar "Tasks" nav row's
   center. Drop to pt-1.5 so both rows center on the same baseline.

2. Workspace view: the strip TaskPage renders to replace the full-width
   titlebar was 42px, but PR #1356 standardized titlebar/titlebar-left/
   right-sidebar header at 36px. Match that with h-9 so the band is
   uniform across columns when a worktree is active.

Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:37:08 -07:00
JinjingandOrca 5ce9c3b481 feat(tasks): remember tasks page resume state across sessions (#1442)
Persist transient Tasks page position (GitHub mode, active preset/query,
Linear preset/query) in PersistedUIState so reopening Tasks restores the
user's working context instead of falling back to defaults. Source, repo
selection, team selection, and active project keep using their existing
settings paths.

Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:19:50 -07:00
14e879a825 fix(layout): align right sidebar to top in non-workspace views (#1356)
* fix(layout): align right sidebar to top in non-workspace views

Wrap the left + center columns in a flex-col that owns the conditional
titlebar, and lift <RightSidebar /> to be a sibling of that wrapper.
The titlebar now spans only the left+center area, so the right sidebar's
own header anchors at the top of the window in landing/settings/tasks
views — matching the workspace-view alignment.

Also gate the titlebar's right-sidebar toggle on !rightSidebarOpen so
it no longer double-renders alongside the close button inside the
right sidebar's own header when the sidebar is open.

Closes #1354

* fix(titlebar): shrink non-workspace .titlebar to 36px

PR #1381 shrank .titlebar-left to 36px but left .titlebar at 42px.
Before the right-sidebar top-alignment fix, the 6px mismatch was
hidden because the right sidebar was pushed below the titlebar in
non-workspace views. With top-alignment, the 36px right-sidebar
header no longer lines up with the 42px titlebar — visible as a
6px seam on the Landing page when the right sidebar is open.

Match all three (titlebar, titlebar-left, right-sidebar header) at
36px so the top strip is uniform across views.

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

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-05-05 11:10:52 -07:00
Jinjing d02481db9b fix: improve github project chip colors (#1439) 2026-05-05 10:39:22 -07:00
NeilandOrca 62e02a3b4c feat(new-workspace): unified source picker + non-submitted URL drafts for agents (#1426)
* Fix new workspace composer focus restore

* Unify new workspace source selection

* WIP: selected source pill in smart workspace name field

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

* fix(new-workspace): truncate source pill so it doesn't expand the dialog

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

* feat(new-workspace): add open-in-browser button to source pill, fix vertical alignment

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

* refactor(new-workspace): drop redundant kind suffix, distinct PR/issue icons, tooltips on pill actions

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

* fix(new-workspace): type linked URL into agent input without auto-submit

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

* fix(new-workspace): use bracketed-paste for draft URL injection so it actually appears in the agent input

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

* feat(agents): per-agent draft injection strategy (codex slow paste, pi/opencode type-chars)

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

* fix(agents): smarter TUI-ready heuristic + bracketed paste for codex/pi/opencode

Replaces per-agent strategy guesswork with a measured readiness check:
title-idle / non-shell-foreground stable for 1.5s / 2.5s minimum floor.
Verified against codex, pi, opencode, claude in a node-pty + xterm-headless
test rig — bracketed paste lands in the input buffer for all four.

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

* refactor(agents): drop unused per-agent draft strategy abstraction

The TUI-ready heuristic in agent-paste-draft.ts works for every tested
agent (claude/codex/pi/opencode), so the AgentDraftInjectionStrategy
field, type-chars + bracketed-paste-slow code paths, and per-agent
overrides are dead. Keep the `agent` arg on pasteDraftWhenAgentReady
for future per-agent escape hatches without touching every call site.

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

* feat(agents): skip draft URL injection for copilot + cursor-agent

Both TUIs open with a 'Do you trust this folder?' menu on first launch
that consumes keystrokes as menu input — pasting a URL there either
selects an arbitrary option or quits the session. Mark them with
skipDraftUrlInjection so the workspace still opens cleanly; the user
types/pastes the URL themselves once past the trust menu.

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

* feat(agents): native --prefill for claude, trust pre-write for cursor/copilot

Replaces the empirical TUI-ready waits with two deterministic mechanisms:

1) `claude --prefill <text>` flag — Claude launches with the URL already in
   its input box, no submit. Eliminates the readiness/paste race entirely
   for the most common agent.
2) DECSET 2004 (`\x1b[?2004h`) detection on the PTY data stream for every
   other agent. That escape is the protocol-level "input layer ready,
   accepting bracketed paste" handshake — emitted by claude/codex/pi/
   opencode/gemini/cursor-agent/copilot the moment the input box mounts.
   We tap it via a sidecar subscription on pty-dispatcher (no interference
   with the primary xterm handler) and paste as soon as it lands. The
   8s budget is now an upper bound, not a target.

Cursor-agent and Copilot's "Do you trust this folder?" menus are bypassed
by writing the same trust artifacts the CLIs themselves write after the
user accepts:
- Cursor: `~/.cursor/projects/<slug>/.workspace-trusted` (slug = abs path
  with leading `/` stripped, remaining `/` → `-`).
- Copilot: append cwd to `trustedFolders` in `~/.copilot/config.json`
  (the same array the bundled `addTrustedFolder` writes).

Verified against the cursor-agent CLI bundle (versions/2026.04.17-787b533/
index.js: `_=".workspace-trusted"`) and the @github/copilot 1.0.32 bundle
(`isFolderTrusted` / `addTrustedFolder` both read/write `trustedFolders`).
Both check via realpath() before string-comparing, so the trust preset
canonicalizes too.

skipDraftUrlInjection is dropped — both agents now get the draft URL
paste once the trust menu is pre-resolved.

Tests: 24 passing across tui-agent-startup, agent-trust-presets,
pty-dispatcher routing.

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

* fix(agents): wait for post-?2004h render burst to settle before paste

OpenCode emits DECSET 2004 at ~500ms during alt-screen setup, then runs
a 1.3s splash render with NO bytes on the PTY, then paints the actual
input box at ~1.85s. Pasting on the bare ?2004h signal lands during the
silent gap and the bytes are dropped.

The fix: take ?2004h as the necessary precondition, then wait for the
TUI's render burst to finish — defined as 1500ms of stream silence
after the most recent post-?2004h byte. This captures both the fast
TUIs (claude/pi/codex emit setup escapes in one burst then go quiet)
and the slow ones (opencode emits, sleeps for the splash, emits again,
then goes quiet).

Verified against opencode/claude/pi in a node-pty rig: paste lands on
the first try with the new strategy. The hard 8s timeout still caps
the wait when an agent fails to launch.

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

* fix(agents): guard agentTrust IPC so stale preload doesn't crash launch

If the preload bundle is older than the renderer (a real situation in
electron-vite dev because preload changes only apply on full restart,
not HMR), `window.api.agentTrust` is undefined and the launch crashes
with "Cannot read properties of undefined (reading 'markTrusted')"
before the worktree even opens.

Guard the call sites in launch-work-item-direct and useComposerState
to skip the trust pre-write when the IPC isn't exposed, and wrap the
invoke in try/catch so an IPC error never blocks the launch — the user
just sees the trust menu and accepts it manually, same as before this
feature shipped.

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

* feat(tasks): route 'Use' through the New Workspace dialog instead of yolo-create

The Use CTA on the Tasks page used to create+activate a worktree
synchronously, which surprised users — the worktree appeared in the
sidebar before they had a chance to confirm name / agent / setup. The
unified New Workspace dialog landed in this branch already supports
opening with a linked work item pre-filled (see openComposerForItem /
openComposerForLinearItem), so just route Use through it.

The launchWorkItemDirect helper stays exported for ProjectViewWrapper,
which has its own UX where the immediate-create flow is the right call.

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

* test(agents): include `agent` field in autohand startup-plan assertion

Merging main brought in the Autohand Code agent test (PR #1382), which
predated this branch's addition of `agent` to AgentStartupPlan.
Aligning the assertion fixes the lone CI test failure on this PR.

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

* refactor(agents): drop unused expectedProcess arg + snapshot sidecar set

Two minor follow-ups from self-review:

1. `pasteDraftWhenAgentReady` no longer reads `expectedProcess` — readiness
   is gated on DECSET 2004 alone now, not on PTY foreground process. Drop
   it from the signature and from the two callers (launch-work-item-direct,
   new-workspace).

2. The pty-dispatcher's sidecar fan-out iterates the live Set, which is
   safe against deleting the current element but not against a watcher
   that synchronously subscribes a sibling. Snapshot via Array.from
   before the loop. Cheap (Set is tiny) and removes the latent footgun.

No behavior change.

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

* test(e2e): match the unified smart-name input's new placeholder

The CreateFromTab refactor in this branch replaced the separate "Workspace
name" Input with a single SmartWorkspaceNameField whose default-mode
placeholder is "Type a name, #1234, branch, GitHub or Linear URL". The
worktree-create e2e test was still anchoring on the old "Workspace name"
text and could not find the input.

Update the placeholder regex to match the new copy. Free-form text typed
into smart mode is treated as a workspace name by submitQuick — same
contract the test used before.

Verified locally: targeted e2e passes in 2.2s.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-05 01:07:52 -07:00
f9120cb2f1 Add custom desktop notification sounds (#1430)
* Add support for custom desktop notification sounds

* perf(notifications): cache custom sound + restart-on-play

Avoids re-reading the configured audio file (up to 10MB) from disk and
re-transferring it over IPC on every notification. Adds a path-only
resolver so repeated dispatches with an unchanged sound skip the heavy
load entirely.

For burst handling, follows the VS Code AccessibilitySignalService /
GNOME canberra pattern: one shared HTMLAudioElement per sound, restarted
from t=0 on each play, with an in-flight guard that drops new plays
while the sound is still ringing. This self-dedupes by the sound's own
duration without any magic time constant — distinct sounds remain free
to overlap. The Test button passes force: true so an explicit user
action always plays through.

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

---------

Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
Co-authored-by: Orca <help@stably.ai>
2026-05-05 01:00:16 -07:00