Commit Graph
16275 Commits
Author SHA1 Message Date
Neil 83d57790db chore(cloud-integration): bake dev billing and control-plane URLs into integration builds
config/cloud-build-defaults.json feeds an ORCA_CLOUD_BUILD_DEFAULTS define in main; packaged
builds read no shell env. ORCA_BUILD_BILLING_API_URL / ORCA_BUILD_CLOUD_SANDBOX_URL override at
build time, ORCA_BILLING_API_URL / ORCA_CLOUD_SANDBOX_URL at run time. Public endpoints only.
2026-11-09 04:07:21 -08:00
Neil 125d594560 Merge remote-tracking branch 'origin/nwparker/agent-api-keys' into cloud/integration 2026-11-09 04:06:58 -08:00
Neil 8f54dc5ddc Merge remote-tracking branch 'origin/nwparker/agent-host-sign-in' into cloud/integration 2026-11-09 04:06:58 -08:00
Neil fbeeaf44c2 Merge remote-tracking branch 'private/nwparker/vercel-driver' into cloud/integration
# Conflicts:
#	cloud/apps/billing/src/entitlements.ts
#	cloud/apps/billing/src/index.ts
#	cloud/apps/billing/src/plans.ts
#	cloud/apps/billing/src/seats.ts
#	cloud/apps/billing/src/store.ts
#	cloud/apps/billing/src/stripe.ts
#	cloud/apps/billing/src/usage.ts
#	cloud/apps/billing/src/webhook.ts
#	cloud/apps/billing/test/billing-flow.test.ts
#	cloud/apps/billing/test/seats-grace.test.ts
#	cloud/docs/accounts-billing-design.md
#	config/scripts/ci/unit-selection/check-test-file-runners.mjs
#	src/main/billing/billing-client.ts
#	src/renderer/src/components/billing/plan-billing-fixtures.ts
#	src/renderer/src/components/billing/plans/TeamPlanCard.tsx
#	src/renderer/src/components/billing/team/TeamMembersSection.tsx
#	src/renderer/src/components/billing/team/TeamMembersView.fixture.tsx
#	src/renderer/src/components/billing/team/TeamMembersView.tsx
#	src/renderer/src/i18n/locales/en.json
#	src/renderer/src/main.tsx
#	src/shared/orca-billing.ts
2026-11-09 04:06:58 -08:00
Neil dc71ad438b Merge remote-tracking branch 'private/nwparker/accounts-billing' into cloud/integration 2026-11-09 04:06:35 -08:00
OrcaWinandOrcaWin f637498b34 test: remove obsolete manual tools and duplicate launch coverage (#40317)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 03:57:10 -08:00
Pr1pandNeil 4bb808e650 fix(build): bundle browser-extension-preload as a standalone sandboxed script (#39884)
The browser-extension preload was a main-build Rollup input, so it could be
split into shared CJS chunks that a sandboxed preload cannot require. Build it
with the other guest preloads as a self-contained bundle, and share the
one-byte unminified output options between the preload build and sandboxed
bundles so the extension preload stays one-byte in V8.

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:48:28 -08:00
Yeji HanandNeil d3cf5f7058 fix(linear): include project in Linear issue list and search results (#40194)
Request the project on the shared issue node fields and map it in
mapRawIssueForWorkspace, so list/search rows carry the project the same
way issue detail already did. Detail now reuses the shared mapping.

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:48:17 -08:00
Wooseong KimandNeil 9d4840bad0 fix(codex): close TOML multiline strings on runs of four or five quotes (#40089)
The Codex config line scanner only treated exactly three quotes as the
multiline closer, so a value like '''printf 'ok'''' left the scanner
inside the string and later tables (e.g. [projects."..."]) were missed
when writing project trust. Match toml_parser: a run of 3-5 quotes
closes the string, with up to two quotes belonging to the content.

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:48:08 -08:00
Neil 715020e871 refactor: group editor browser document and simulator owners (#40273)
* refactor: group editor browser document and simulator owners

* refactor: update active simulator reliability command links

* refactor: preserve upstream editor and emulator test retirements
2026-11-09 03:44:32 -08:00
Pr1pandNeil e3d8e7e9cb fix(native-chat): group deferred context rows separately in the usage popover (#39917)
Claude reports deferred categories (MCP tools, system tools loaded on
demand) that sit outside the used total, but summarizeContextUsage
dropped the flag, so the popover listed them as window percentages next
to real usage and the rows summed to well over 100%.

Keep the deferred flag on each summary row and render deferred rows in
their own group under a divider, with token counts instead of a share of
the window and a note that they are not counted in the used total.

Fixes #39878

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:42:24 -08:00
OrcaWinandOrcaWin 8d195ef316 test: remove low-value copy suites and manual status benchmark (#40305)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 03:39:29 -08:00
WenhaoandNeil 9c55e1783a fix(markdown): lower link underlines below descenders (#40218)
Link underlines in Native Chat, the markdown preview and the rich markdown
editor sat 2px below the baseline, so descenders (g, y, p, j) crossed them and
skip-ink broke the line into dashes. Use a 0.25em offset that scales with font
size and zoom, and override the shared renderer's underline-offset-2 in Native
Chat.

Fixes #40217

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:36:59 -08:00
CalvinandNeil 2dc0df462b fix(claude): verify model switches when terminal echoes omit vendor prefix (#40064)
Claude echoes "Set model to Opus 5.5" without the "Claude" vendor prefix,
and never echoes the picker-only " alias" suffix or a raw "claude-" id
prefix. The confirmation observer required every picker-label token, so a
successful switch resolved to unknown and showed "Could not verify the
model change". Normalize the expected label before matching; context
tokens such as 1M are still required.

Fixes #40058

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:36:51 -08:00
Franz FelbererandNeil 00374cc0c2 feat(dashboard): show last messages in agent dialog when no live terminal (#40147)
When a dashboard card has no live PTY (e.g. chat-session tabs), the agent
dialog previously showed only the "preview unavailable" notice. It now also
renders the card's stored last user/agent messages, unclamped and scrollable,
below the notice. The rendering is extracted into AgentCardLastMessages and
shared with the kanban card, which keeps its line clamps.

Fixes #40144

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:31:33 -08:00
Wooseong KimandNeil e408d87584 fix(diff): persist inline / side-by-side diff view via the Default Diff View setting (#40256)
* fix(diff): persist inline / side-by-side diff view via the Default Diff View setting

The file diff and combined diff toolbars toggled inline vs side-by-side only
in local component state (plus a session-only module preference for the
combined diff), so switching worktrees or agent threads reopened the diff in
the saved inline default.

The toggle now writes the existing diffDefaultView setting, and both viewers
derive sideBySide directly from it. The per-view cache and module memory no
longer carry a separate sideBySide value.

Fixes #40241

Co-authored-by: Wooseong Kim <2222333+innocarpe@users.noreply.github.com>

* test(diff): drop the removed sideBySide field from the cached combined-diff view

---------

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:31:20 -08:00
Neil 8dde71250d feat(cloud): self-rotating golden images (refresh before expiry, release builds, smoke-gated atomic swap); Orca Cloud gated on the sandbox capability (#28) 2026-11-09 03:28:58 -08:00
Neil 1382406872 fix(terminal): don't restart every dead saved tab when a worktree opens; log how the daemon exited (#40289)
* fix(terminal): don't restart every dead saved tab when a worktree opens; log how the daemon exited

Opening a worktree mounted every saved terminal tab that had no PTY, and each
hidden mount started a fresh shell or agent. With many finished agent tabs this
started dozens of agents at once and could exhaust a host's process limit.

Saved tabs with no PTY anywhere and nothing queued to start now wait until
they are shown; the existing capped idle warm-up still admits up to four.
The main process now records the daemon's exit code or signal and names it in
the respawn log line.

Fixes #39166

* fix(daemon): forget a predecessor's exit when a replacement daemon launches
2026-11-09 03:26:08 -08:00
Haoyu(Jerry) WuandJerry Wu a972b88124 test(pty): await readiness signals instead of polling with waitFor (#40082)
The plain-shell readiness test polled with vi.waitFor (1s default budget)
for reconcileConfig and the spawn env. Under CPU load the spawn takes over
a second and the test failed with 'expected undefined to be defined'.

Await an explicit reconcile-started signal and the spawn itself, and move
cleanup to onTestFinished so the gate is released and spies/env restored
even when a regressed spawn blocks until the test timeout.

Fixes #40078

Co-authored-by: Jerry Wu <haoyuwu@andrew.cmu.edu>
2026-11-09 03:25:36 -08:00
Manuel Meurer ded69660da fix(native-chat): move the cursor to the composer after Add to chat (#39845)
The composer refuses focus while an overlay is open, and the selection
popover was still open when the quote was appended. Close it first.
2026-11-09 03:25:26 -08:00
Dhruv SingalandNeil f221b40576 fix(tour): allow chat split for agent sessions without a TUI agent tag (#39976)
The native chat split action required the source agent-session tab to carry
a TUI agent tag, so sessions without one (e.g. untagged or non-TUI agents)
could not be split and the tour's split step stalled. Any agent-session tab
in a known group is now a valid split source.

Co-authored-by: Neil <neil@stably.ai>
2026-11-09 03:25:16 -08:00
jp-liu ae79aaa824 fix(ports): keep sticky External Ports header opaque on hover (#40073)
The sticky External Ports header used hover:bg-accent/50, a translucent
background that let scrolled port rows show through on hover. Blend the
accent into the popover color so the hover state stays opaque.

Fixes #40056
2026-11-09 03:25:08 -08:00
NeilandClaude 5ba260911f fix(agents): narrow fs error without a cast
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 03:12:52 -08:00
NeilandClaude dba3995ea8 fix(agents): async vault reads, bounded host list, design-system and review fixes
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 03:12:52 -08:00
NeilandClaude d45abdfc96 feat(agents): store agent API keys and hand them to agent launches on any host
Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-09 03:12:52 -08:00
OrcaWinandOrcaWin 1b123a9293 test: remove low-value work budgets and relocation selftest (#40294)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 03:12:21 -08:00
OrcaWinandOrcaWin 00f109d9e1 test: remove low-value renderer, chain, and native checks (#40287)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 03:10:17 -08:00
Neil 1d99ac6a02 fix(tabs): preserve lastFocusedAt on native chat tabs across host snapshots (#40288)
Host session-tab snapshots rebuild native chat tabs without the
client-owned focus visit, so Cmd+J recents ranked chats last and showed
their creation time.

Fixes #39841
2026-11-09 03:03:37 -08:00
Neil 9922e32a68 feat(cloud): Orca Cloud in the desktop end to end (provider, lease scheduler, upsell, dogfood) (#26)
* feat(sidebar): replace footer Settings and Help icons with an account menu

* fix: keep account menu header on primitive spacing; move focus-read allowance

* fix(sidebar): address account menu review findings

* feat(billing): Cloudflare Worker for Stripe checkout, portal, webhooks, entitlements and usage (#7)

Test-mode-only foundation for paid Orca plans: hosted Checkout/Portal,
signed + idempotent Stripe webhooks that re-read subscriptions, a D1 ledger
for sandbox usage with overage-only Billing meter events, and entitlement
checks for the desktop and the sandbox control plane.

* feat(billing): Plan & billing in the Orca account settings and account menu (#9)

Shows the signed-in account's plan, sandbox hours used and left, and opens
hosted Stripe Checkout (Upgrade) or the Customer Portal (Manage billing) in
the browser. Main mints a short-lived billing token from Orca Cloud auth and
only opens checkout.stripe.com / billing.stripe.com URLs. Hidden until
ORCA_BILLING_API_URL is set; the account menu item is gated on the 'billing'
cloud capability and registers through a local adapter that mirrors the
upcoming account menu API.

* feat(billing): plans and prices from config, opt-in Stripe Tax, real account menu

- Worker: BILLING_PLANS JSON overrides the plan catalog (labels, display price,
  hours, limits); entitlements return the plan list so the desktop shows no
  hardcoded prices. STRIPE_AUTOMATIC_TAX=true adds automatic_tax and tax id
  collection to Checkout (default off). Setup script takes prices from env.
- Desktop: register Plan & billing through the sidebar account menu
  (merged nwparker/sidebar-account-menu) and drop the local adapter.
- Register the billing Worker's tests with the test-runner check.

* feat(billing): Team pricing, opt-in overage, Stripe test-mode e2e, dev deploy (#18)

* feat(billing): Team-only pricing, opt-in overage with spend cap, live Stripe test-mode e2e

- Catalog: Team $50/seat/mo or $480/seat/yr, 60 Standard h/seat/month pooled
  (monthly windows on annual plans), Large 2x, 3 running/seat, 15-min idle sleep;
  Enterprise is contact-only. All numbers/labels in BILLING_PLANS defaults.
- Overage is opt-in (adds the metered item), $0.75/h, monthly spend cap (default
  $25, admin-raisable) enforced in the meter outbox; 80%/100% usage warnings.
- Checkout: plan/interval/seats with adjustable quantity; portal configuration var.
- Workers reject fetch redirect 'error': use 'manual'. Log route errors.
- scripts/stripe-test-setup.ts creates the test catalog + portal configuration;
  scripts/e2e-test-mode.ts drives Checkout (headless, test card), overage, meter,
  cap, annual, test-clock renewal, payment failure and cancel.
- Desktop: Team/Enterprise cards with interval + seats, usage warnings, overage
  toggle + cap; split into copy/offers/usage modules.

* feat(billing): dev deployment config, dev operator keys, return page

- wrangler.dev.jsonc for orca-billing-dev (workers.dev, dev D1, test-mode prices).
- BILLING_DEV_JWKS (issuer orca-billing-dev-test) accepted only when BILLING_ENV
  is not prod, for e2e runs until auth mints billing tokens.
- GET /return: static 'return to Orca' page for Checkout/Portal redirects.
- Design doc: final pricing, dev URL and resources for the control plane.

* feat(billing): team seats follow membership, payment grace + suspend signal, Team UI

Worker
- Seats = org members from Orca Cloud auth (single source of truth; pending invites
  never count; min 1): auth pushes POST /v1/internal/seats, billing pulls
  /v1/internal/billing/org-members at Checkout and in a reconcile cron, fails closed
  (503) if auth is configured but unreachable. No token claim carries a count.
- Proration: adds always_invoice, removals create_prorations (Stripe default).
- Billing admin actions require a token minted in the last 6 minutes.
- Payment failure: past_due_since (migration 0003); new starts stop at once;
  after 96 h (paymentGraceHours) reason payment_grace_expired + suspendRunning on
  check/usage, and GET /v1/internal/suspensions for the control plane.
- Portal config: monthly<->annual + cancel only (seats follow membership).
- e2e: seat add/remove proration, grace expiry -> suspend -> pay -> resume.

Desktop
- Team section + account menu item: members/roles, invite, change role, remove
  with confirm, revoke invites (owners/admins, auth role rules mirrored).
- Payment issue banner with suspension date and Update payment method.

* feat(billing): in-app plans page (#22)

A pricing/plans page reachable from the account menu ("Plan & billing"), the
Settings plan section ("Choose a plan" / "Compare plans"), and any upsell via
openPlansPage(). Everything comes from the billing service's offers: Team
monthly/annual (with the computed annual saving), pooled hours, Large weight,
concurrency, idle sleep, opt-in overage with spend cap, and Enterprise contact.

- States: choose (admin), locked (member), current plan with usage, payment
  failure (status-first), checkout in progress, loading and failure with retry.
- Seats are read-only: one per team member (billing re-reads the count).
- Shared card shell keeps both cards' footers level; sliding interval toggle and
  price fade respect reduced motion; dialog opens without a pre-focused button.
- Worker offers gain per-seat cents and the Large weight for totals.
- Copy matches the marketing /cloud promises: agents keep running, wake in
  seconds, secrets never stored in the VM.

* wip(cloud): Orca Cloud built-in provider wiring

* feat(cloud): no-plan upsell opens the plans page

* feat(cloud): Orca Cloud dogfood fixes (provider persistence, picker label, any-input activity, idle override)

* fix(cloud): live dogfood fixes (snapshot already-deleted, agent egress wildcards, golden image id) + results

* fix(cloud): i18n keys, typed dev JWK, verdict typing

* feat(cloud): billing caps from billing (maxConcurrentSandboxes, per-member), userId on usage; concurrency copy

* feat(cloud): golden image can pin a released orca-server tarball (--release), source build stays the fallback

* fix(cloud): async dev key read, runtime localization catalog
2026-11-09 02:59:02 -08:00
OrcaWinandOrcaWin c38a8e4b9a test: remove low-value wrappers, inventories, and timing checks (#40284)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 02:52:36 -08:00
Neil ccd4592634 refactor: group renderer workspace ownership and navigation (#40230)
* refactor: group renderer workspace ownership and navigation

* refactor: use the defining WSL rewrite store identifier

* refactor: route new upstream consumers to workspace owners

* refactor: consolidate connection owner test imports

* refactor: preserve upstream review-owner test retirement
2026-11-09 02:38:15 -08:00
Neil 576b4684f7 feat(billing): peak-seat billing and abuse limits (#25)
- Seats billed = the period's peak membership: adds above paid seats are charged now
  (always_invoice); removals never credit mid-period and only lower the quantity inside
  seatTrueDownHours of renewal (proration none), so remove/re-add churn can't dodge or
  double-charge. The cron applies deferred decreases from the last pushed count.
- Included hours and caps come from billed seats; per-member concurrency cap
  (member_concurrency_limit); usage attributed to the member who started it.
- Start check returns billed `seats` and the derived caps for the control plane.
- Desktop shows when paid seats drop at renewal; proration copy updated.
- Design doc: seat-fairness decision with the GitHub/Cursor/Slack/Linear comparison.
2026-11-09 02:34:43 -08:00
Neil 33941e6efa fix(remote): sign agents out with their own logout and confirm first
Sign out of Claude/Codex on a host now runs that agent's logout against the
login launches there use, after a confirm dialog, instead of deleting the
host's saved Orca account. The host check asks the CLI in that same login.
2026-11-09 02:33:40 -08:00
Neil 5949b9127e fix(remote): read host labels defensively and await gated spawns in routing test 2026-11-09 02:33:39 -08:00
Neil 700cfcb396 feat(remote): sign agents in from the pane with one browser approval on the host
Starting Claude or Codex on a runtime host where it isn't signed in holds the
launch behind an inline card. Sign in with browser runs the unmodified CLI login
on the host; this computer forwards the browser's localhost callback to it over
a narrowly scoped tunnel, so the token never leaves the host. Adds a verdict-only
host check, agent sign-out in the host menu, and paste/device-code fallbacks.
2026-11-09 02:33:39 -08:00
OrcaWinandOrcaWin a163b9fc5b test: remove low-value copy, inventory, and runner assertions (#40282)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 10:25:23 +00:00
Neil 6130c4d793 feat(cloud): GitHub App repo tokens + billing dev wiring for the sandbox control plane (#20)
* feat(cloud): GitHub App installation tokens for sandbox git (manifest flow, minter, policy refresh)

* feat(cloud): billing dev wiring — shared control-plane token via service binding, grace-expired suspensions, standard/large only
2026-11-09 02:19:24 -08:00
Neil a91ae681f5 feat(cloud): 24h rollover, idle stop and agent auto-resume for Orca Cloud sandboxes (#13)
* feat(cloud): hosted session lease scheduler — 24h rollover, idle stop, agent auto-resume

* refactor: parse restart offers without casts
2026-11-09 02:19:23 -08:00
Neil 4f062602e4 feat(cloud): EnvironmentProviderDriver + HostedSandboxDriver with contract kit and fake control plane (#10) 2026-11-09 02:19:21 -08:00
OrcaWinandOrcaWin 19afa64ee7 test: remove low-value provider and renderer assertions (#40279)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 10:11:48 +00:00
Kelvin Amoaba 0684ef586f feat(i18n): translate the dictation pill, error pill and queued-send copy (#40266)
* fix(dictation): don't throw when the paired web client has no speech catalog

* feat(i18n): translate the dictation pill, error pill and queued-send copy

* fix(i18n): say Chinese queued sends happen automatically
2026-11-09 10:03:37 +00:00
Neil 75c37220b5 fix(terminal): end a dead preserved terminal host's PTYs as host loss (#40095)
* fix(terminal): end a dead preserved terminal host's PTYs as host loss

After an update Orca keeps the previous version's terminal host so agents
survive. That host has no respawn, so when it later died nothing ended its
PTYs: panes stayed connected on a frozen frame and input went nowhere.

Once every reconnect attempt finds its endpoint refused or missing, each of
its PTYs now ends as host loss with history kept, and the pane's restore is
no longer refused because the dead host cannot answer.

Fixes #38432

* fix(terminal): require process-exit proof on POSIX and keep checking until proven

Review follow-ups: an unproven attempt restarts the count instead of ending
the check; on POSIX the old host's pid must also be gone; a proven-gone host
answers 'not live' for every id; one throwing exit listener cannot strand
the remaining sessions.
2026-11-09 02:01:41 -08:00
OrcaWinandOrcaWin f10be535ca test: remove low-value mobile renderer and rate-limit suites (#40188)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 01:46:01 -08:00
Kelvin Amoaba cd2e0cd787 docs(dictation): say why Hold can't see a key release inside a browser page (#40269) 2026-11-09 09:45:46 +00:00
Jinwoo Hong 1b78d1d1d4 fix(orchestration): explain the --terminal and --agent refusal; name chat addresses in terminal commands (#40092) 2026-11-09 09:31:22 +00:00
Kelvin Amoaba e9d762fff4 fix(dictation): a paired phone or browser waits as long as the computer for long cloud dictations (#40238)
* fix(dictation): wait as long as the host's cloud deadline when a paired phone or browser stops

* fix(dictation): compute the host's cloud deadline from its exact sample count
2026-11-09 09:29:04 +00:00
OrcaWinandOrcaWin eb3493acb0 test: remove low-value renderer and budget suites (#40222)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 01:22:00 -08:00
Jinwoo Hong 19b571248d fix(native-chat): pad the sender name chip in orchestration worker cards (#40258)
The compact sender name had no horizontal padding, so its hover fill hugged
the text. Add an inlineChip button size (inline height, px-1.5).
2026-11-09 04:19:43 -05:00
OrcaWinandOrcaWin ef66245430 test: remove low-value WSL and renderer suites (#40237)
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-09 01:15:07 -08:00
Neil f04e06b023 fix(agent-picker): list agents named by the search before other agents' model setups (#39806)
* fix(agent-picker): list agents named by the search before other agents' model setups

Typing "codex" in the agent picker showed OpenCode/Cursor model setups
(e.g. "OpenCode · GPT-5 Codex") above the Codex agent itself, and Enter
picked the first setup. Direct agent matches now render first and are the
Enter target.

* test(agent-picker): assert search highlight and Enter target for named agent

* test(agent-picker): import fireEvent after rebase
2026-11-09 09:13:24 +00:00