Commit Graph

248 Commits

Author SHA1 Message Date
Leynier Gutiérrez González 231bad8e19
feat(file-explorer): add gitignored visibility toggle (#2022) 2026-05-17 18:33:47 -04:00
Leynier Gutiérrez González a99929e42e
fix: preserve slashes in branch-created worktrees (#2091) 2026-05-17 18:19:43 -04:00
Brennan Benson e671606fff
Add Copilot agent hook status support (#2027)
Co-authored-by: Orca <help@stably.ai>
2026-05-17 13:05:24 -07:00
Jinjing 40e903d833
fix: address review findings (#2138) 2026-05-16 22:56:42 -07:00
Jinjing d603242766
fix: address review findings (#2130) 2026-05-16 17:13:01 -07:00
Jinjing e957b86197
Add configurable Open In applications (#2110)
* feat: add configurable Open In menu

Implements configurable Open In applications in worktree context menus with persisted settings, preload/API wiring, and renderer controls/tests.\n\nDesign doc: docs/configurable-open-in-menu.md

* fix: address review findings
2026-05-16 15:34:40 -07:00
Neil 312677132e
fix: speed up Codex draft prefill (#2105) 2026-05-16 13:58:17 -07:00
Jinwoo Hong ab53fb5c9e
feat: add source control git graph (#1969)
Co-authored-by: Orca <help@stably.ai>
2026-05-16 04:44:44 -04:00
Jinjing 77264240c8
Add crash report submission flow (#2012)
* feat: add crash report submission flow

* Capture crash-report breadcrumbs

- Add a memory-only crash breadcrumb ring buffer and persist snapshots only
  when a crash report is recorded
- Include sanitized recent activity in crash diagnostics and tests
- Prevent dismissing or closing the crash dialog while submission is in flight

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

* fix: address auto-review findings

* chore: remove crash report preview artifact

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-15 23:59:03 -07:00
Neil 64cf1d5d56
Add Azure DevOps Repos hosted review support
Add Azure DevOps Repos hosted review lookup, preflight, and shared hosted-review plumbing.
2026-05-15 23:13:58 -07:00
Neil e7eb42659c
Add primary selection middle-click paste
Closes #1898
2026-05-15 22:49:41 -07:00
Neil 2ead67c650
Label macOS dev Dock instances by branch (#2068)
* fix: label macOS dev Dock instances

* fix: keep dev badge visible in Dock labels

* chore: clean up dev identity plumbing

* feat: add stable-name dev command
2026-05-15 22:46:13 -07:00
Jinjing b609aa2bec
Fix Codex terminal orchestration (#2039) 2026-05-15 20:31:28 -07:00
Diego Lorente del Castillo 2ad01ead7d
feat(file-explorer): show gitignored files with dimmed italic decoration (#1941)
* feat(file-explorer): show gitignored files with dimmed italic decoration

Surfaces `.gitignore`d files in the right-sidebar file explorer with an
italicised, dimmed filename and a CircleSlash icon in the same trailing
slot used by the git status letter. A tracked change always wins — the
ignored decoration only applies when no other git status is present.

Gated behind a new `showGitIgnoredFiles` global setting (default on) so
heavy SSH workspaces can keep the smaller payload by skipping
`--ignored=matching` on `git status`.

`ignoredPaths` lives as a peer field on GitStatusResult rather than an
extension of GitFileStatus/GitStagingArea, so Source Control's
staging-area grouping is untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(file-explorer): trim redundant comments from gitignored decoration

Removes duplicated "Why:" explanations that ended up restating the same
backward-compat rationale across five files (relay, ssh provider, runtime
git commands, RPC handler, renderer git client) plus a few comments that
narrated the mechanism the code already shows.

Net: -39 lines of comment across 10 files; no behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(file-explorer): drop remaining comments from gitignored decoration

The code reads well without them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* review: harden gitignored file decorations

- clear ignored decoration cache when ignored status is disabled or omitted
- keep ignored decoration state scoped across worktree and runtime cleanup
- add coverage for local, SSH, runtime, relay, and Explorer precedence

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-05-15 18:58:08 -07:00
Neil 5bcfa27581
Add Ctrl+Tab recent tab switcher (#1916) 2026-05-15 18:49:08 -07:00
Jinwoo Hong 727ccf7c69
Add browser page annotations (#1979)
Co-authored-by: Orca <help@stably.ai>
2026-05-15 18:39:32 -07:00
Neil c4cd233ae5
Add Hermes CLI status support (#1984)
## Summary
- add managed Hermes CLI hook plugin installation and status reporting
- normalize Hermes events into Orca agent status, tools, approvals, and completion states
- expose Hermes status through IPC/preload/web APIs and remote hook installation

## Verification
- targeted Vitest slice: 10 files, 291 tests passed
- pnpm run tc:node, tc:web, tc:cli passed
- oxlint passed with 0 warnings / 0 errors
- git diff --check passed
- GitHub checks passed: verify, e2e / e2e
2026-05-15 18:32:37 -07:00
Neil 99df02b923
Add GitHub PR file viewed tracking (#1914) 2026-05-15 18:28:13 -07:00
Jinjing 60be1605e6
Add skills discovery page (#1999)
* WIP: uncommitted changes before rebase

* fix: address review findings

* fix: address CI failures
2026-05-15 17:33:04 -07:00
Brennan Benson bf85d51bc1
Add workspace lineage grouping (#1885)
Co-authored-by: Orca <help@stably.ai>
2026-05-15 17:21:00 -07:00
Jinwoo Hong bce3ef1776
Add OpenCode usage analytics (#1986)
Co-authored-by: Orca <help@stably.ai>
2026-05-15 16:33:15 -07:00
Brennan Benson f5cc8196f9
Clean up old workspaces (#1873)
Co-authored-by: Orca <help@stably.ai>
2026-05-15 14:00:23 -07:00
Neil e7f3bb6034
Add Grok agent support 2026-05-15 13:52:39 -07:00
Brennan Benson e5c394b09b
Add pull request creation flow (#1960)
Co-authored-by: Orca <help@stably.ai>
2026-05-15 13:36:06 -07:00
Jinjing 194e7d36d7
feat(automations): manage external automation jobs (#1976)
* feat(automations): manage external automation jobs

* fix: restore worktree activity status compatibility
2026-05-15 13:18:05 -07:00
Jinwoo Hong 6c4bcf7ea6
feat(ssh): make remote workspaces first-class (#1876)
Co-authored-by: Orca <help@stably.ai>
2026-05-15 12:32:07 -07:00
Brennan Benson 60fdd11114
Migrate agent pane identity to stable leaf ids (#1909)
Co-authored-by: Orca <help@stably.ai>
2026-05-15 12:10:06 -07:00
Prateek Rungta e42c78107c
Mobile: replace presence-lock banner with loud overlay + collapsible chip (#1899)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
2026-05-15 11:47:13 -07:00
Jinjing 82214e86ee
Revert "Add project notes (#1861)" (#1945)
This reverts commit c73fd2c90b.
2026-05-15 11:46:06 -07:00
Neil 96f0c683eb
Support multiple Linear workspaces (#1917) 2026-05-15 11:32:46 -07:00
Jinjing 35e13a04b1
Add worktree Open in editor button (#1929)
* Add worktree open-in editor button

Implements the Open in menu flow from docs/open-in-worktree-button.md, including shell IPC validation and sidebar menu integration.

* Move worktree open action into menu

Updates the design to remove the card button and show VS Code under a single Open in context-menu item.

* Shorten worktree file manager labels
2026-05-15 11:05:21 -07:00
Jinwoo Hong 618f39d179
Add web runtime client support 2026-05-15 05:44:25 -04:00
Leynier Gutiérrez González b030257c3b
feat(source-control): AI commit message generation (#1487)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: brennanb2025 <brennankbenson@gmail.com>
2026-05-15 02:18:46 -07:00
Neil f81b3f219f
Add Gitea hosted review support 2026-05-15 01:56:05 -07:00
Neil 2d44ee83b4
Add Space manager V2 safeguards 2026-05-14 23:30:22 -07:00
Jinwoo Hong a22717bb35
Refactor runtime app architecture (#1878)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 23:13:37 -07:00
Neil cb58b109e0
feat: add workspace space analyzer (#1877) 2026-05-14 17:29:58 -07:00
Brennan Benson be72e64a47
Improve source control discard flow (#1870)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 15:20:53 -07:00
Brennan Benson fdf7d9e97a
feat(onboarding): add feature wall tour (#1772)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 15:20:49 -07:00
Neil bca39bc928
Add GitLab and Bitbucket hosted review support (#1839)
* feat(gitlab): add foundational glab runner, types, and issue operations

First slice of GitLab support, mirroring src/main/github/ structurally
without refactoring the working GitHub path.

- runner: add glabExecFileAsync parallel to ghExecFileAsync (same WSL
  routing and retry policy; HTTP-status / network classification is
  provider-agnostic so the existing helpers are reused).
- types: GitLabProjectRef carries host alongside path so self-hosted
  instances and nested groups round-trip through the IPC layer. Mirror
  shapes for MR/issue/work-item/comment/file/assignable-user.
- gitlab/gl-utils: concurrency limiter, error classification, project-ref
  resolution honoring upstream/origin preference, and known-host
  discovery via `glab auth status` so non-gitlab.com remotes are
  recognized after the user authenticates.
- gitlab/mappers: pipeline-job → check-status mapping, MR state
  resolution (including draft inferred from `Draft:`/`WIP:` title
  prefix), and pipeline rollup.
- gitlab/issues: full issue CRUD via `glab api` against URL-encoded
  project paths, with the same upstream/origin preference semantics as
  the GitHub side.

63 unit tests passing across gl-utils / mappers / issues. Both
typecheck:node and typecheck:web clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): preflight glab auth check and URL parser

- preflight: probe `glab --version` + `glab auth status` alongside the
  existing gh checks. PreflightStatus.glab is optional so renderer call
  sites that only render git/gh keep typechecking; consumers gating on
  GitLab affordances opt in via `glab?.authenticated`.
- gitlab-links: parse GitLab issue and merge-request URLs honoring (a)
  arbitrary self-hosted hosts via the project-internal `/-/` separator
  rather than locking to gitlab.com, (b) nested group paths, and (c)
  GitLab's `!42` MR convention alongside `#42`.

26 unit tests added (5 new preflight cases, 21 URL-parser cases). Full
typecheck (node + cli + web) clean. Pre-existing runtime/orchestration
test failures unrelated to this branch — Node 25 vs the project's
pinned Node 24 engine.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): MR list/get + paginated `glab api -i` helper

Lean mirror of github/client.ts focused on the workspace-from-MR
keystone. Adopts GitLab-native filter semantics (Open / Merged /
Closed / All) instead of porting GitHub's search-DSL — that path is
covered by the upcoming My Todos surface.

- gl-utils: glabApiWithHeaders + parseGlabApiResponse for strict
  pagination via X-Total / X-Total-Pages on `glab api -i` output.
  CRLF / LF tolerant; status line never leaks into the headers map.
- types: MRListState, GitLabPagedResult<T>, ListMergeRequestsResult.
- mappers: mapMRToWorkItem + mapIssueToWorkItem produce the unified
  GitLabWorkItem shape the picker consumes. isCrossRepository derived
  from source_project_id !== target_project_id; deterministic id
  fallback when the per-MR detail endpoint omits global id.
- client: getAuthenticatedViewer, getMergeRequest (with head pipeline
  rolled up), getMergeRequestForBranch (mirrors github/getPRForBranch
  semantics including refs/heads/ stripping and detached-HEAD guard),
  listMergeRequests (paginated), getWorkItemByProjectRef (paste-URL
  flow). Re-exports issues + projectRef helpers so callers don't have
  to know the gl-utils module split.

35 new tests (98 total in src/main/gitlab/), full typecheck clean.
Tests split into client.test.ts + client-mr.test.ts to stay under the
oxlint max-lines budget — matches github/client*.test.ts pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): worktrees:resolveMrBase IPC + linkedGitLab* persistence

The workspace-from-MR keystone. Mirror of worktrees:resolvePrBase
shape and semantics — caller passes mrIid (with optional source_branch
/ isCrossRepository hints), handler returns either a remote/branch
ref (same-project MRs) or a SHA fetched from
refs/merge-requests/<iid>/head (fork MRs).

- types: linkedGitLabMR / linkedGitLabIssue on Worktree + WorktreeMeta.
  Marked optional so existing test fixtures and persisted older
  worktrees that pre-date these fields keep typechecking and loading
  without a migration.
- persistence: getDefaultWorktreeMeta initializes both fields to null.
- worktree-logic: mergeWorktree carries them through from meta.
- worktrees IPC: resolveMrBase mirrors resolvePrBase. Resolves the
  GitLab project via getProjectRef + known-host discovery, fetches the
  MR work-item to derive source_branch + isCrossRepository when those
  hints aren't provided, and uses GitLab's refs/merge-requests/<iid>/head
  for fork MRs (parallel of GitHub's refs/pull/<N>/head).
- tests: 6 fixture updates for the new optional fields. Full
  typecheck (node + cli + web) clean; 165 tests passing across
  src/main/gitlab/, preflight, worktree-logic, and gitlab-links.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): IPC channels + preload bindings (gl.*)

Wire the GitLab backend to the renderer. Lean v1 surface — issues
CRUD, MR list/get/getForBranch, viewer, project slug, paste-URL
work-item lookup. Skips workItemDetails / listWorkItems-combined /
listTodos until the matching backend pieces land.

- main/ipc/gitlab.ts: thirteen handlers under the `gitlab:*` channel
  prefix with the same assertRegisteredRepo guard the gh handlers use.
  listIssues unwraps the structured result envelope to bare items[]
  to match window.api.gh.listIssues' shape; consumers that need the
  classified error can graduate to the envelope later.
- main/ipc/register-core-handlers.ts: register alongside gh.
- preload/api-types.ts: typed `gl: { ... }` block parallel to the
  existing `gh: { ... }`. Imports the new GitLab types so renderer
  code consuming the preload gets full inference.
- preload/index.ts: runtime `gl: { ... }` exposes wired to ipcRenderer.

Full typecheck (node + cli + web) clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): workspace-from-MR via paste-URL (keystone end-to-end)

The first user-visible GitLab moment. Pasting a GitLab issue or MR URL
into the workspace name field now resolves through the full pipeline
to a created workspace with the right base ref and linkedGitLab*
persisted. The dedicated GitLab tab + state-filter chips remain a
follow-up; everything below it is wired.

- shared/lib/new-workspace.ts: LinkedWorkItemSummary.type accepts
  `'mr'` alongside `'issue' | 'pr'`. Renderer code that switches on
  type explicitly handles each kind.
- ui store slice: NewWorkspaceDraft mirrors the new linked slots so
  drafts persist GitLab selections across navigation. Optional fields
  for backward compatibility with drafts saved before this branch.
- useComposerState:
  - linkedGitLabIssue / linkedGitLabMR state, draft persistence,
    repo-switch reset, applyWorktreeMeta wiring.
  - applyLinkedGitLabWorkItem mirrors applyLinkedWorkItem; reuses
    getLinkedWorkItemSuggestedName by structurally projecting the
    GitLab item onto the helper's input shape.
  - handleSmartGitLabItemSelect parallels handleSmartGitHubItemSelect:
    for picked MRs, calls window.api.worktrees.resolveMrBase to
    resolve the base ref (refs/merge-requests/<iid>/head for fork
    MRs) and threads it through handleBaseBranchMrSelect.
  - "was MR !N" reset hint when a repo switch wipes a GitLab
    selection — `!N` matches gitlab.com's MR-reference convention.
- preload: window.api.worktrees.resolveMrBase + window.api.gl.* are
  already in. ComposerCardProps grows onSmartGitLabItemSelect (+
  optional onBaseBranchMrSelect).
- SmartWorkspaceNameField:
  - Paste-URL detection: parseGitLabIssueOrMRLink (host-agnostic via
    `/-/` separator) → window.api.gl.workItemByPath → row in the
    dropdown → click → forwarded to onGitLabItemSelect.
  - SmartWorkspaceNameSelection union, RowEntry union, RowIcon,
    RowLabel, SelectionIcon all carry the gitlab-mr / gitlab-issue
    kinds. MR rows show `!N` prefix; issue rows show `#N`.
  - Tab UI not added in this commit — paste-URL works in 'smart'
    mode, the dedicated tab + Open/Merged/Closed/All chips lands
    in a follow-up.
- NewWorkspaceComposerCard: forwards onSmartGitLabItemSelect to the
  picker.

Full typecheck (node + cli + web) clean. 165 unit tests passing in
affected files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): GitLab tab in SmartWorkspaceNameField with state filter

The discoverable demo path. The picker now has a "GitLab" tab — when
selected it lists the project's MRs filtered by state via
`gitlab:listMRs`, with an Open / Merged / Closed / All chip strip
that mirrors gitlab.com's MR-page tab strip. Paste-URL detection in
'smart' mode is unchanged; the new tab simply makes the surface
discoverable without requiring a URL.

- SmartNameMode gains 'gitlab'; Gitlab icon (lucide) added to the
  MODES array between GitHub and Branch.
- MrStateFilter / MR_STATE_FILTERS centralizes the four chip values
  so the labels stay GitLab-native (Open vs the GraphQL 'opened').
- listMRs effect: fires when mode === 'gitlab' and no GitLab URL is
  in the input, with the current state filter and a page-1 fetch
  bounded by RESULT_LIMIT.
- Paste-URL effect now coexists with the list effect: it owns
  gitlabItems while a URL is in the input, the list effect owns it
  otherwise. Switching tabs no longer clears the list.
- Chip strip rendered above the popover's CommandList only when
  mode === 'gitlab'. Buttons use the same Button component the rest
  of the picker uses for visual consistency.

Full typecheck (node + cli + web) clean. 165 unit tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): GitLab source on Tasks screen

The Tasks screen now offers GitLab as a third source alongside GitHub
and Linear. Selecting it surfaces MRs and issues for the primary
selected repo with a state filter (Open / Merged / Closed / All) that
mirrors gitlab.com's MR-page tab strip. Skips cross-repo aggregation,
search DSL, and Projects mode for v1 — those layers are GitHub-API-
shaped and would need a parallel store slice that is not worth porting
ahead of the actual demand for them.

- shared/types: GlobalSettings.defaultTaskSource accepts 'gitlab'.
- TaskPage:
  - TaskSource union grows a 'gitlab' member; SOURCE_OPTIONS adds the
    Gitlab icon between GitHub and Linear so the toolbar order matches
    SmartWorkspaceNameField for cross-surface consistency.
  - GITLAB_TASK_FILTERS centralizes the four chip values.
  - Per-source state slim (matches Linear's pattern) — gitlabFilter,
    gitlabItems, gitlabLoading, gitlabError, gitlabRefreshNonce.
  - Data-fetch effect runs Promise.all over `window.api.gl.listMRs`
    and `window.api.gl.listIssues` for the primary repo, merges and
    sorts by updatedAt desc. 'merged' filter skips the issue fetch
    (GitLab issues are 'opened' / 'closed' only).
  - Filter bar block parallel to Linear's, with chips + a refresh
    icon-button.
  - List block: 5-column grid (ID / Title / Type+State / Updated /
    Open-link). Row click opens the web URL — the GitLabItemDialog
    is a follow-up commit, but the row affordance is enough for the
    Tasks-screen demo.
  - GitLab MRs render as `!N`; issues render as `#N` to match
    gitlab.com's reference convention.

Full typecheck (node + cli + web) clean. 165 unit tests still
passing in affected files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): GitLabItemDialog (minimal) + Tasks screen wiring

Clicking a GitLab row on the Tasks screen now opens a side-sheet
preview with the item's title, state, author, and description body
rendered as markdown. "Open in browser" footer button stays as the
escape hatch; opening from the row is dialog-first now (matching the
GitHub side's row-click-to-dialog pattern). Files / comments /
pipeline tabs are deferred — they mirror substantial GitHub-side
surface area (work-item-details ~550 lines, GitHubItemDialog 2680
lines) and are not blocking the demo.

- types: MRInfo and GitLabIssueInfo gain optional description /
  author / authorAvatarUrl. Optional because list endpoints strip
  them; populated on detail-endpoint reads (`getMR` / `getIssue`).
- mappers: mapMRInfo and mapGitLabIssueInfo now pass description /
  author / avatar through when present. Skipped (rather than
  defaulted to '') so callers can distinguish "no body authored"
  from "this came from a list".
- GitLabItemDialog: new ~200-line side sheet. Fetches the detail
  payload via `window.api.gl.mr` / `gl.issue` on open; renders
  CommentMarkdown for the description (reused from the GitHub
  side); falls back to "No description." when the body is blank.
  State badge tones picked locally — GitLab's MR state space is
  wider than GitHub's so coupling them buys nothing.
- TaskPage: GitLab row now uses a div role=button with keyboard
  handling so the inner Open-in-browser <button> nests cleanly
  (HTML disallows nested <button>s, React would warn). Row click
  sets gitlabDialogItem; the small ExternalLink icon stops
  propagation so it still opens the URL.

Full typecheck (node + cli + web) clean. 165 unit tests passing in
affected files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): My Todos cross-project view on Tasks screen

The GitLab tab now has a Project | My Todos sub-toggle. "My Todos"
fetches gitlab.com/dashboard/todos via `glab api todos?state=pending`
and surfaces them in a separate table — action / title / project /
updated. This is the closest GitLab-native equivalent of GitHub's
notifications/inbox and lands in lieu of porting GitHub's search-DSL
which doesn't translate.

- shared/types: GitLabTodo type with action_name, target_type/iid,
  target_url, project_path, author, updated_at. action_name kept as
  open-ended string because new GitLab versions extend the verb set.
- gitlab/client.ts: listTodos uses `glab api --paginate todos?state=
  pending&per_page=50`. User-scoped — cwd doesn't matter, but the
  IPC path-validation guard still requires *some* registered repo
  path so we keep the signature consistent with the rest of gl.*.
- IPC: `gitlab:todos` channel; preload `gl.todos`.
- TaskPage:
  - gitlabView ('project' | 'todos') gates which list to render.
  - Sub-toggle row above the chip strip; chips are hidden on the
    Todos view since pending state has no Open/Merged/Closed axis.
  - Refresh button serves both views (uses gitlabRefreshNonce).
  - Todos table: 5-col grid, action verb (snake_case → spaces),
    target title, project path (mono font for repo-likeness),
    updated date, open-link icon. Row click opens target_url.

Full typecheck (node + cli + web) clean. 165 unit tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): gitlabProjects settings (recents auto-tracked) + tests

Settings persistence for GitLab project preferences plus tests for
the surface added since the last green run.

- shared/types: GitLabProjectSettings { pinned, recent } and an
  optional GlobalSettings.gitlabProjects slot. Optional for
  backward compat with profiles saved before this branch — the
  persistence merge fills the empty default.
- shared/gitlab-projects: pure helper computeNextGitLabRecents that
  prepends-and-dedupes by host+path, caps at GITLAB_RECENTS_MAX
  (10). Pulled out of the IPC handler so it tests without mocking
  Store.
- gitlab IPC: workItemByPath handler now pushes the resolved
  project ref onto recents on success. 404 / auth-fail lookups
  do not pollute the list — recents reflects projects the user
  actually read.

Tests added (12 new, 177 total passing in affected files):
- gitlab-projects.test: prepend, dedupe, host-vs-host distinct,
  cap at max, no input mutation.
- client.test: listTodos mapping, defensive state coercion,
  empty-on-error fallback, missing-target field defaults.
- mappers.test: description / author / authorAvatarUrl pass-
  through on both mapMRInfo and mapGitLabIssueInfo, plus the
  "absent vs blank" distinguishing assertion.
- mappers-workitem.test (split): mapMRToWorkItem + mapIssueToWorkItem
  cases moved out of mappers.test.ts to keep both files under the
  oxlint max-lines budget.

Full typecheck (node + cli + web) clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): combined listWorkItems IPC + TaskPage refactor

Centralize the MR + issue merge logic that TaskPage was doing inline
into a single backend function and IPC channel. Future callers (the
picker's GitLab tab, any new widget) get the merge / sort / state-
mapping rule for free. The TaskPage effect drops from 60 lines of
inline orchestration to a single call.

- gitlab/issues: listIssues now accepts an IssueListState so the
  combined caller can ask for closed / all instead of always opened.
  CLI fallback path picks the right --opened / --closed / --all flag
  per glab version. Existing callers keep the 'opened' default.
- gitlab/client: listWorkItems(state, page, perPage, preference) fans
  out listMergeRequests + a raw issues fetch in parallel, merges by
  updatedAt desc, returns a GitLabPagedResult<GitLabWorkItem>.
  Bypasses listIssues for the issues side because IssueInfo strips
  updated_at — the combined sort needs it.
  state='merged' skips the issues fetch entirely (issues don't have
  a merged lifecycle).
- IPC: new gitlab:listWorkItems handler.
- preload: gl.listWorkItems alongside gl.listMRs.
- TaskPage: GitLab fetch effect now calls gl.listWorkItems and stops
  re-implementing the merge. Same UX, fewer moving parts.

Tests added (8 new in client-work-items.test.ts; +1 fix to
issues.test.ts for the new url-param order):
- merge ordering by updatedAt desc
- 'merged' state skips issues fetch
- closed / all state pass-through
- not_found envelope when project ref unresolved
- mr-error vs issue-side success interleaving
- combined error surfacing on either side failing

Full typecheck (node + cli + web) clean. 117 unit tests passing in
src/main/gitlab/ and src/shared/gitlab-projects.test.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): work-item-details + dialog Conversation/Pipeline tabs

Task 3 lean version. The minimal description-only dialog grows two
new tabs (Conversation / Pipeline) and four footer actions
(close / reopen / merge / comment). Files-tab and inline review-
comment positioning stay deferred — they mirror substantial GitHub-
side surface (GitHubItemDialog is 2680 lines, work-item-details.ts is
551) and the v1 demo doesn't need them.

- shared/types: GitLabPipelineJob (id, name, stage, status, webUrl,
  duration), GitLabWorkItemDetails (item + body + comments[] +
  pipelineJobs?[]). Mirrors GitHubWorkItemDetails layout.
- main/gitlab/work-item-details: getWorkItemDetails(repoPath, iid,
  type) fans out parallel reads — issue: detail + discussions; MR:
  detail + discussions, then pipeline jobs follow-up keyed off
  head_pipeline.id. Discussion → MRComment flatten skips system
  notes (auto-generated activity entries) so the conversation tab
  shows only user content. Inline-review position carried through
  as `path` + `line` for v1.5 to consume.
- main/gitlab/client: closeMR / reopenMR / mergeMR / addMRComment
  mutations. mergeMR accepts the same 'merge' | 'squash' | 'rebase'
  union as the GitHub side; close/reopen treat "already X" stderr
  as success since the desired state is reached.
- IPC: gitlab:workItemDetails, closeMR, reopenMR, mergeMR,
  addMRComment channels; preload `gl.*` bindings parallel.
- GitLabItemDialog rewrite: three Tabs (Description / Conversation /
  Pipeline-MRs-only) + footer with comment composer + state-aware
  Merge / Close / Reopen buttons. Cmd/Ctrl+Enter sends the comment
  to match gitlab.com's textarea shortcut. Refresh icon in the
  header re-fetches via a refreshNonce. eslint-disable max-lines on
  the dialog matches the GitHub-side equivalent's reasoning.

Full typecheck (node + cli + web) clean. 184 unit tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): sidebar icon, Smart-mix MRs, Integrations card, "Project MRs" rename

Four follow-up fixes that surfaced from smoke-testing:

- SidebarNav: GitLab icon next to GitHub / Linear in the Tasks-row
  shortcut strip; clicks open the Tasks page already filtered to the
  GitLab source. ui.ts taskPageData.taskSource union grows to accept
  'gitlab' so the openTaskPage call typechecks.
- SmartWorkspaceNameField: list-MRs effect now fires in 'smart' mode
  too, not just on the dedicated GitLab tab. The mixed picker
  surfaces the user's project MRs alongside GitHub items. Paste-URL
  effect still wins when a GitLab URL is in the input — the list
  effect bails on parsedGlLink !== null.
- TaskPage: GitLab toggle relabels "Project" → "Project MRs" so the
  pairing with "My Todos" reads more clearly.
- IntegrationsPane: new GitLab card mirroring the GitHub card —
  status badge (checking / connected / not-installed / not-
  authenticated), install link to gitlab.com/gitlab-org/cli, copy-
  ready `glab auth login` block, learn-more link to the auth/login
  doc, re-check button. Search-entry registered so settings search
  finds it. eslint-disable max-lines justified by the same pattern
  that already lives there for GitHub + Linear.
- preload: PreflightStatus.glab is optional on the type so older
  payloads typecheck; consumers gate on the optional chain.

Full typecheck (node + cli + web) clean. 184 unit tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(gitlab): multi-repo aggregation on Tasks screen

Mirrors GitHub's cross-repo behavior. Previously the GitLab tab only
queried the first selected repo; now it fans out to every eligible
selected repo in parallel and merges results sorted by updatedAt
desc. The repo selector at the top of Tasks is the project picker —
it's the same one the GitHub tab uses, so the selection model is
consistent across providers.

- TaskPage gitlab fetch effect: Promise.allSettled across all
  selectedRepos that aren't SSH-relay (folder-mode repos and remote
  worktrees fall through). Each repo's project is resolved from its
  own git remote by the main process; non-GitLab repos return
  not_found which the renderer drops silently so a mixed selection
  (GitHub + GitLab repos) doesn't surface false errors on the GitLab
  tab.
- Per-row repoId tagging stays correct — items keep their source
  repo's id through the merge, which matters for the dialog repoPath
  resolution below.
- Banner display: only shown when EVERY eligible repo failed; partial
  failure is signaled by the row count being lower, not a banner that
  overshadows working repos.
- GitLabItemDialog repoPath: derived from the clicked item's
  source repo (selectedRepos.find by repoId) instead of primaryRepo.
  Without this, clicking an item from a non-primary repo would route
  the detail fetch through the wrong repo's remote.

Full typecheck (node + cli + web) clean. 117 unit tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(gitlab): swap MR icon to GitMerge for visual distinction

GitPullRequest (curved-merge) reads similar to GitBranch (forking
line) at the small sizes we use in the picker — feedback was that
MR rows looked like branch rows. GitMerge (arrow-merge-into-line)
reads as its own thing and matches gitlab.com's MR iconography, so
users coming from the web UI find it familiar.

GitHub PRs keep GitPullRequest — that matches github.com and keeps
provider attribution distinct from GitLab MRs at a glance:
  GitHub PR: GitPullRequest (curved merge)
  GitLab MR: GitMerge (arrow merge)
  Branch:    GitBranch (fork)
  Issue:     CircleDot (provider-agnostic)

- SmartWorkspaceNameField RowIcon + SelectionIcon: gitlab-mr →
  GitMerge. github-pr stays GitPullRequest.
- GitLabItemDialog header icon: GitMerge for MRs.

Full typecheck (node + cli + web) clean. 117 unit tests passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(gitlab): split shared types + preload into per-provider files

Pre-emptive merge-conflict reduction. The two recent main syncs
each surfaced ~5 conflicts, all in the same handful of central
files where every provider lands code. Moving the GitLab footprint
into provider-scoped files cuts the conflict surface roughly in half
without changing any runtime behavior.

- shared/gitlab-types.ts (new, 272 lines): every standalone GitLab
  type that previously lived in shared/types.ts —
  GitLabProjectRef / MRState / MRMergeableState / MRCheckDetail /
  MRInfo / GitLabReaction / MRComment / GitLabCommentResult /
  GitLabIssueInfo / GitLabViewer / GitLabAssignableUser /
  GitLabWorkItem / GitLabMRFile / GitLabProjectSettings /
  GitLabTodo[TargetType] / GitLabPipelineJob /
  GitLabWorkItemDetails / GitLabIssueUpdate / MRListState /
  GitLabPagedResult / ListMergeRequestsResult.
- shared/types.ts: re-exports the GitLab types so existing call
  sites importing from '../shared/types' keep working unchanged.
  GitLabProjectSettings additionally imported locally for the
  GlobalSettings.gitlabProjects field. Worktree.linkedGitLabMR /
  WorktreeMeta.linkedGitLabIssue / GlobalSettings.defaultTaskSource
  union member stay here — they're entangled with non-GitLab
  structs and moving them out would just shuffle the conflict
  vector to a different file.
- preload/gitlab.ts (new, 106 lines): the entire gl.* runtime
  binding block — viewer / projectSlug / mrForBranch / mr /
  listMRs / listWorkItems / issue / listIssues / createIssue /
  updateIssue / addIssueComment / listLabels /
  listAssignableUsers / todos / workItemDetails / closeMR /
  reopenMR / mergeMR / addMRComment / workItemByPath. Exported as
  `glApi`.
- preload/index.ts: imports `glApi` and inlines as `gl: glApi`,
  shrinking the file by ~95 lines.

Net: the two files most prone to conflict on upstream sync
(shared/types.ts, preload/index.ts) lose ~360 lines of
GitLab-specific code that now live in their own files where main's
non-GitLab edits can't touch them.

Full typecheck (node + cli + web) clean. 190 unit tests passing
in src/main/gitlab/, src/shared/gitlab-projects.test.ts,
src/main/ipc/{preflight,worktree-logic}.test.ts,
src/renderer/src/lib/gitlab-links.test.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(gitlab): satisfy pnpm pre-flight (lint + handler-registration test)

- TaskPage: lift the selected-repos identity key into a useMemo so the
  GitLab fetch effect's dep array no longer holds a complex expression
  (oxlint exhaustive-deps).
- register-core-handlers.test: mock ./gitlab alongside ./github / ./linear
  so registerGitLabHandlers doesn't try to call ipcMain.handle in a unit
  test that fakes only individual handler modules.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(source-control): add Bitbucket hosted review support

* fix(source-control): align hosted review lookup with provider model

---------

Co-authored-by: Emilian Stoilkov <emilian.stoilkov@qaiware.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 15:09:52 -07:00
Jinwoo Hong 151040f05f
Add desktop-backed mobile voice dictation (#1869)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 14:36:44 -07:00
Jinwoo Hong c73fd2c90b
Add project notes (#1861)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 13:33:24 -07:00
Jinwoo Hong 1948458fb0
Add local automations workflow (#1806)
* Add local automations

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

* Add local automations workflow

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-14 02:31:52 -04:00
Jinjing d08a1b9525
fix: route terminal file drops by tab (#1804) 2026-05-13 22:15:46 -07:00
Dmytro Roman ac7ac81137
feat(main): Add droid to AgentHooks and sidebar agents status (#1695)
Co-authored-by: Orca <help@stably.ai>
Co-authored-by: brennanb2025 <brennankbenson@gmail.com>
2026-05-13 21:30:13 -07:00
Neil 75d5a65633
Add notebook preview support (#1725)
* Add notebook preview support

* Fix notebook reopen and browser routing

* Add editable runnable notebooks

* Restore notebook highlighting and defer source serialization

* Mark notebook editor beta

* Fix notebook Python syntax highlighting

* Improve notebook cell controls and dark editing

* Fix notebook focus and save shortcuts

* Fix restored notebook file loads

* Harden notebook perf and output rendering

* Fix notebook source toggle shutdown noise

* Harden notebook execution trust prompt
2026-05-13 19:28:19 -07:00
Brennan Benson 6e482a00d7
fix(terminal): set paneKey env on CLI-spawned terminals so agent status surfaces (#1727)
Co-authored-by: Orca <help@stably.ai>
2026-05-13 16:20:59 -07:00
Jinjing 5a6b2994ea
fix: address review findings (#1770) 2026-05-13 16:14:50 -07:00
Jinwoo Hong aa0a1d2ed9
feat(ssh): preserve remote PTY sessions across app close (#1706)
Co-authored-by: Orca <help@stably.ai>
2026-05-12 21:09:51 -07:00
Jinwoo Hong 406304c5e2
Add Floating Terminal (#1724)
* Add floating terminal surface

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

* Move floating terminal into native window

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

* Polish floating terminal native window

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

* Revert "Polish floating terminal native window"

This reverts commit c7e4bdf4d4b2bb0d638c06843623d5174201d7fc.

* Revert "Move floating terminal into native window"

This reverts commit 0fa1f5c493929abc2b3e1225195c1c072b0c9515.

* Adjust floating terminal default position

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

* Polish floating terminal hide and placement

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

* Fix floating terminal IPC test mocks

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-05-12 18:06:42 -07:00