Commit Graph
32 Commits
Author SHA1 Message Date
Jinjing 6166f6c47a feat(linear): add server-side issue filters for status and other properties (#8021)
Add attribute filters (status, priority, assignee, labels) to the Linear
issues list, applied in GraphQL before pagination so hasMore matches the
filtered set. Thread filters through IPC/RPC/store cache with invalidation
on issue mutations, and mirror GitHub-style filter chrome on TaskPage.
2026-07-09 22:23:56 -07:00
Brennan Benson 7b7a21e3c7 Give agents access to inline Linear ticket screenshots and media (#7484) 2026-07-05 23:55:56 -07:00
NeilandOrca 885badba60 perf(linear): fetch issue comments in one request, not N+1 (#7497)
getIssueComments loaded the issue, then its comments, then awaited c.user
inside a for-loop. Accessing .user on the Linear SDK's Comment model lazily
issues a fresh user(id) GraphQL query, so a comment-heavy issue did issue +
comments + N sequential user round-trips — a visible multi-second stall on
open, burning the complexity-based rate limit and holding one of only 4 shared
Linear concurrency slots (acquire/release) for the whole N*latency window.

Replace with a single rawRequest that fetches each comment's author inline
(first: 50, matching the SDK default page the code already relied on), the same
pattern the rest of this file uses. createdAt is passed through as the ISO
string rawRequest already returns (no re-serialization), and null avatarUrl is
normalized to undefined — output shape is unchanged.

Test asserts one request regardless of comment count and correct author
mapping (present user, null avatar, absent user).

Co-authored-by: Orca <help@stably.ai>
2026-07-05 23:08:43 -07:00
NeilandOrca 46646d7ff1 chore(lint): upgrade oxlint to 1.71 + enable 7 new rules (autofixed backlog) (#6841)
* chore(lint): upgrade oxlint to 1.71 and enable 7 new rules

Upgrade oxlint 1.67.0 -> 1.71.0 (1.72 was blocked by the repo's 3-day
minimum-release-age supply-chain guard; nothing here needs it). The
bump is a no-op on the existing config.

Enable 3 error rules (backlog autofixed to zero in this commit) and
4 warn rules (surface signal without gating CI):

error (autofixed, behavior-preserving):
- unicorn/prefer-node-protocol        (~1531 sites: bare builtin -> node:)
- typescript/no-import-type-side-effects (~36: all-inline-type -> import type)
- unicorn/no-array-reverse            (19: copy-then-reverse -> toReversed)

warn (real signal, current fires are test-only/correct):
- unicorn/no-array-fill-with-reference-type  (aliasing footgun guard)
- typescript/no-unsafe-function-type         (bans bare Function type)
- unicorn/prefer-array-flat-map              (map().flat() -> flatMap())
- unicorn/prefer-regexp-test                 (.match() in bool ctx -> .test())

mobile/.oxlintrc.json extends root, so it inherits all 7; the autofix
ran from root and covered mobile/ too.

Verification (all green): oxlint 0 errors (root+mobile+aux configs),
oxfmt clean, typecheck (node+cli+web), vitest 22795 passed / 0 failed,
builds (electron-vite + web + cli) succeed. node: rewrites confirmed to
skip embedded SSH/CLI string payloads (AST-only); all toReversed sites
verified to operate on fresh copies or write-once locals.

* chore(lint): bump mobile oxlint to 1.71 so inherited rules parse

mobile/ is a standalone pnpm project pinning its own oxlint@1.67, which
lacks unicorn/no-array-fill-with-reference-type (needs >=1.70). Since
mobile/.oxlintrc.json extends the root config, mobile CI's 'cd mobile &&
oxlint' failed to parse the new rule. Bump mobile to match root (1.71).

Verified in mobile/: oxlint 0 errors, oxfmt --check clean, tsc --noEmit
pass, vitest 978 passed / 0 failed.

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-29 22:38:29 -07:00
Jinwoo Hong 972078f2c4 Fix paste ownership, input bounds, and IPC validation
Supersedes #5745, #5746, and #5747.
2026-06-19 17:14:55 -07:00
Trevin ChowandJinjing 2b8d9a43de feat(linear): add project support to agent CLI (#5433)
* feat(linear): add project support to agent CLI

* fix(linear): resolve project names across search pages

* fix(linear): harden agent project support

* fix(linear): address project review feedback

---------

Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
2026-06-15 18:24:53 -07:00
Brennan BensonandOrca e7906969cf Attach Linear issues from the worktree CLI (#5322)
Co-authored-by: Orca <help@stably.ai>
2026-06-13 15:20:08 -07:00
Brennan BensonandOrca 3a2d39cb37 Support full Linear task workflows from the CLI (#5323)
Co-authored-by: Orca <help@stably.ai>
2026-06-13 15:07:44 -07:00
Brennan BensonandOrca 74c961b09f Add Linear write commands for agents (#5165)
Co-authored-by: Orca <help@stably.ai>
2026-06-12 13:29:13 -07:00
buf0-bot[bot]andorca-bug-scan-bot 146da04af2 fix: address pr-bug-scan validated finding from #4683 (#5151)
Isolated CredentialDecryptionError per-item in Linear getClients (client.ts:518) and Jira getClients (client.ts:373) on the 'all' selection so one bad credential no longer collapses healthy workspaces

Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
2026-06-10 23:56:17 -07:00
Brennan BensonandOrca cdc0ca5e53 Add read-only orca linear CLI with trusted launch-prompt pointer (V1) (#5126)
Co-authored-by: Orca <help@stably.ai>
2026-06-10 20:20:50 -07:00
Brennan BensonandOrca ceae167427 Handle integration credential decrypt failures (#4683)
Co-authored-by: Orca <help@stably.ai>
2026-06-10 13:08:09 -07:00
Jinjing a67afb5a04 fix: address review findings (#4853) 2026-06-07 19:50:05 -07:00
Jinwoo HongandOrca 4f18c7e79d Allow Linear context issue lists to load more (#4512)
* Allow Linear context issue lists to load more

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

* Simplify Linear load more footer copy

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

* Page Linear issue reads past backend cap

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

* Align Linear load more footer with GitHub pager

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

* Use pager for Linear issue lists

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

* Avoid phantom Linear issue pages

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

* Fix local Linear issue pagination cap

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

* Fix Linear pagination review issues

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

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-02 21:17:20 -04:00
Jinwoo HongandOrca 135c69d3e8 Add Linear issue load more (#4437)
Co-authored-by: Orca <help@stably.ai>
2026-06-01 23:35:47 -07:00
Jinjing ec14507457 fix: address review findings (#4452) 2026-06-01 23:34:39 -07:00
Jinjing ab3e1b8bc5 Add Linear project and custom view browsing (#3966)
* Add Linear project and custom view browsing

* fix: address review findings
2026-05-30 18:10:06 -07:00
Jinjing 8484830b9e Improve Linear scope selection (#3850) 2026-05-30 12:55:13 -07:00
Jinjing 5783c4192b Improve Linear issue editing flow (#2901)
* fix: address review findings

* fix: update Linear RPC test
2026-05-26 23:15:33 -07:00
Jinjing 6a9be249f5 feat: add external task filter links (#2871) 2026-05-26 20:07:03 -07:00
Jinwoo HongandOrca b1973657ea Add mobile Tasks parity (#2452)
Co-authored-by: Orca <help@stably.ai>
2026-05-21 20:26:07 -07:00
Jinjing 409cd43b42 Add Linear issue estimate editing from details views (#2226)
- Fetch, map, validate, and persist Linear estimates through IPC and RPC
- Add estimate controls with optimistic updates in Linear drawers/workspaces
- Keep user-opened sub-issues visible even when they are outside the list filter
2026-05-17 23:11:48 -07:00
Jinjing 284a7a29c7 fix: address review findings (#2209) 2026-05-17 20:33:15 -07:00
Jinjing 21000624a8 fix: address review findings (#2191) 2026-05-17 17:59:06 -07:00
buf0-bot[bot]andorca-bug-scan-bot 014cc1e4b3 fix: pr-bug-scan validated finding from #1917 (#1961)
Co-authored-by: orca-bug-scan-bot <orca-bug-scan-bot@stably.ai>
2026-05-15 17:01:11 -07:00
Neil 96f0c683eb Support multiple Linear workspaces (#1917) 2026-05-15 11:32:46 -07:00
faf949835f feat(rate-limits): add Gemini and OpenCode Go usage tracking (#1023)
* feat(rate-limits): add Gemini and OpenCode Go usage tracking

- Extend provider union and RateLimitState with 'gemini' and 'opencode-go'
- Add opencodeSessionCookie to GlobalSettings (password input in GeneralPane)
- Add GeminiIcon and OpenCodeGoIcon to status bar icons
- Implement gemini-usage-fetcher: OAuth creds from ~/.gemini/oauth_creds.json,
  auto-refresh expired tokens (including server-side 401 retry), loadCodeAssist
  project resolution, retrieveUserQuota with pro/flash bucket mapping
- Implement opencode-go-usage-fetcher: cookie-based POST to opencode.ai/_server,
  two-step workspace+subscription fetch, regex parse of text/javascript response
- Wire both fetchers into RateLimitService via Promise.allSettled for isolation
- Add formatWindowLabel() replacing hardcoded '5h'/'wk' strings in StatusBar
- Render Gemini and OpenCode Go segments in StatusBar and tooltip
- 28 new tests across fetchers, service, and label formatter

Closes #1022

* fix(persistence): additive merge for statusBarItems on load

New providers (gemini, opencode-go) were invisible to users with existing
settings because the persisted statusBarItems array (without the new entries)
overwrote the defaults. Union saved items with current defaults so new
providers appear automatically after upgrade without user intervention.

* feat(rate-limits): add Gemini multi-bucket usage

Restore provider auth wiring, preserve Gemini model buckets in detailed views, and keep compact status rendering summary-only. Avoid embedding OAuth client secrets by failing closed for auth.json refreshes.

* fix(gemini-oauth): resolve symlinks and use known-path + bundle-dir extraction

Replace the recursive directory walker with two targeted strategies:
1. Known paths: checks explicit Homebrew/Nix/npm layouts without walking.
2. Bundle dir: walks up from the binary to find package.json, then scans
   the bundle dir for hash-named oauth2 chunks.

Also threads the refresh token as a plain string through
tryRefreshTokenFromBundle so both the oauth_creds.json and auth.json
paths share one refresh flow without coupling to either struct.

Windows: uses 'where gemini' and splits on newlines for multi-result output.

* fix(status-bar): fix Gemini bucket display — names, window size, model context

Three issues fixed:

1. windowMinutes was computed as time-remaining-until-reset instead of the
   fixed window size. Gemini buckets are always 1-hour windows; use the
   constant 60 so labels read "93% Pro 1h" instead of "93% 47m".

2. Unknown bucket names now humanize gracefully. Unknown model IDs get the
   "gemini-" prefix stripped and title-cased ("gemini-3.0-ultra" → "3.0 Ultra")
   instead of showing "Unknown (gemini-3.0-ultra)". Added more known model
   mappings (2.0 Flash, 2.0 Flash Lite, 1.5 Pro, 1.5 Flash, Flash Lite).

3. Status bar segment now shows the most-constrained bucket name next to the
   percentage so users know which model is the binding constraint.

Pure unit tests for getBucketName/deriveSessionSummary extracted to
gemini-bucket-helpers.test.ts to keep gemini-usage-fetcher.test.ts
under the 300-line lint limit.

* feat(status-bar): show all Gemini buckets individually in status bar

Instead of showing only the most-constrained bucket summary, render each
bucket by name with its remaining percentage (e.g. "Flash 93% · 3.1 Pro Preview 7%").
Falls back to the session/weekly window display for providers without buckets.

* fix(status-bar): show only Flash and 3.1 Pro Preview buckets in Gemini segment

Filter to the two most relevant buckets (Flash + 3.1 Pro Preview) to avoid
cluttering the bar. Falls back to session summary if neither bucket is present.

* fix(icons): replace GeminiIcon with official 2025 multicolor gradient

The previous icon used a simple linear gradient (blue→purple→red).
The official Google Gemini 2025 icon uses 11 blurred ellipses (feGaussianBlur)
stacked under an alpha mask to produce the characteristic multicolor glow effect.

Each instance gets unique filter/mask IDs via a module-level counter to prevent
ID collisions when the icon is rendered multiple times on the same page.

* feat(opencode): add monthly limits, workspace override, and improved cookie handling

* fix(opencode): show correct status when session cookie is missing

* fix(rate-limits): discard stale data on unavailable and show errors in tooltip

* fix(rate-limits): invalidate stale data when opencode config changes

* fix(security): resolve vulnerabilities and harden rate-limit fetchers

* fix: address critical security, performance and concurrency issues identified during code review

* fix(build): resolve claude rate-limit export and broken type definitions

* fix(build): remove unused code in claude-fetcher after rebase

* Fix claude fetcher

* fix: resolve synchronization, performance, and robustness issues in AI providers

- Convert synchronous file I/O to asynchronous to prevent main process blocking
- Implement concurrency limiting in recursive directory copying to avoid EMFILE errors
- Persist refreshed Gemini OAuth tokens to disk and improve project ID resolution
- Fix OpenCode Go fetcher to correctly handle workspace overrides and robustly resolve IDs
- Refine scraping regexes to handle nested objects and improve resilience
- Update status bar bucket names and fix Gemini model mapping typos
- Ensure proper handling of async operations in background services

* feat(gemini): deduplicate quota buckets and update model mappings

* fix(rate-limits): preserve stale data for Gemini and OpenCode Go on fetch errors

* fix: remove out-of-scope Linear changes and restore files to upstream/main

* fix(opencode-go): handle React Flight wire format and duplicate keys

The opencode.ai page uses React Server Components. Usage keys like
monthlyUsage appear twice: once as `key:$R[N]={...}` with real data
and once as `key:null` inside a billing component. Render order varies,
so on refresh the null could appear first, causing monthly to vanish or
show 100% from a sibling sub-object.

Replace flat regex extraction with extractUsageBlock, which:
- Iterates all occurrences of each key
- Skips null assignments (no { in 30-char window after colon)
- Handles the $R[N]= token between colon and opening brace
- Validates usagePercent + resetInSec as direct fields before accepting

Add regression tests using the real React Flight HTML format.

* fix(rate-limits): address PR review feedback from nwparker

Scope reverts (out-of-scope changes removed):
- Revert codex-accounts async refactor (fs-utils.ts, service.ts)
- Revert filesystem-auth.ts path-auth reordering
- Revert filesystem-mutations.ts bundled changes
- Revert repos.ts handler move; keep only -- separator fix
- Revert relay/fs-handler-git-fallback.ts RegExp try/catch
- Revert fs-handler.ts stat→lstat, useFileDeletion.ts !isRemote guard
- Revert persistence.ts statusBarItems additive merge

Feature fixes:
- Validate opencodeWorkspaceId override with ^(wrk|wk)_[A-Za-z0-9]+$ before URL interpolation
- Remove internal 5-min cache from fetchGeminiRateLimits (service polls already)
- Make saveGeminiCredentials atomic using tmp-file + rename pattern
- Add fetchGeneration counter to OpenCode to discard stale mid-flight results
- Add console.warn on safeStorage decrypt failure in persistence.ts
- Add geminiCliOAuthEnabled opt-in setting (default: false) with UI toggle and risk disclosure
- Use per-candidate AbortControllers in opencode-go fetcher
- Add fragility comments to brace-depth parsers in opencode-go fetcher

Refactor (keep under 300-line lint limit):
- Extract gemini-bucket-formatting.ts from gemini-usage-fetcher.ts
- Extract opencode-go-page-scraper.ts from opencode-go-usage-fetcher.ts

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

* fix(rate-limits): restore OpenCode Go workspace ID regex + cleanup

- opencode-go-usage-fetcher: regex accidentally shipped as `\\s*` (matches
  literal backslash-s) instead of `\s*` during the review-feedback commit,
  breaking workspace ID extraction when no override is configured —
  parseWorkspaceIds always returned []. 10 tests were failing as a result.
- gemini-usage-fetcher: drop unused `_force` parameter left over from the
  removed 5-min internal cache; update service.ts call site.
- codex-accounts test fixtures: add missing `geminiCliOAuthEnabled` to
  createSettings() to fix pre-existing typecheck errors introduced when
  the new setting was added.

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

* test(rate-limits): stabilize Gemini fetcher tests, silence max-lines

- Rewire Gemini fetcher tests to mock the CLI-credential extractor at the
  module boundary instead of stubbing every fs/child_process call. The
  extractor is a self-contained dependency with a simple async contract,
  and was previously being reached through sync-fs mocks that stopped
  matching after the extractor was refactored to node:fs/promises — three
  tests were silently failing as a result. With this change, all 17
  Gemini fetcher tests pass.
- Replace the "proceeds with empty projectId" test (which asserted that an
  empty projectId still hits the quota API — the current fetcher
  correctly short-circuits to an actionable error instead) with a test
  that documents the new behavior, plus an explicit test for the
  geminiCliOAuthEnabled=false unavailable path.
- Add a max-lines disable pragma to service.test.ts matching the one
  already on service.ts, so the rate-limit fetch-ordering contract and
  its tests remain reviewable as a single unit.

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

* fix(codex-accounts): revert runtime-home-service async refactor

The review explicitly asked to drop the codex async refactor from this PR
(fires floating promises from the constructor via void, and the prepare*
helpers no longer block on sync completion — that is a behavior change
around account prep racing with launch that deserves its own design
discussion, not a drive-by).

Earlier reverts removed fs-utils.ts and service.ts but left
runtime-home-service.ts untouched, which was causing the matching
runtime-home-service.test.ts suite (11 tests) to fail in CI. This restores
the file to main so the suite is green and the PR stays scoped to the
Gemini / OpenCode Go feature.

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

---------

Co-authored-by: Orca <help@stably.ai>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-04-29 16:55:32 -07:00
Jinwoo HongandOrca 75c6f25887 feat(linear): add create-issue button for feature parity with GitHub (#1185)
Co-authored-by: Orca <help@stably.ai>
2026-04-27 12:28:09 -07:00
NeilandOrca 193c6ecab3 fix(linear): defer keychain decrypt, cache viewer, add Test connection (#1151)
Co-authored-by: Orca <help@stably.ai>
2026-04-26 21:45:38 -07:00
Jinwoo Hong cc47cad95f feat(tasks): add Linear team selector (#1074) 2026-04-24 21:03:30 -07:00
Jinwoo Hong faed904aae feat(issues): make issues page writable with inline editing (#1017) 2026-04-24 10:41:21 -07:00
Jinwoo Hong e1270486cd feat: add Linear integration (#1007) 2026-04-23 14:54:32 -07:00