Repository navigation
Conversation
* fix(native-chat): reserve pending chips before checking dropped files A local file drop checked each file before adding it, with nothing in the composer meanwhile: Send during the check went without the file, which then landed in the next draft; unmounting mid-check lost it; and files queued behind an input-method composition were lost on unmount. Drops now reserve a pending chip per file before the check, so Send waits as it already does for server-upload drops. The prepared attachment travels through the existing composition queue as one operation, settles into its draft scope after unmount, releases its chips when refused or disabled, and reads the scope's current image capability when it applies. * test(native-chat): server-upload chip calls carry no options without paste * refactor(native-chat): move the composer's image chip list into its own hook Main's server-owned paste pushed the attachments hook past the file length limit. * fix(native-chat): a pending attachment chip shows a spinner and its name, not a stacked icon A local drop now waits as a pending chip, which drew the kind icon, the file name and a centered spinner on top of each other. Without a thumbnail the chip shows the spinner above the name; with one, the dimmed picture keeps a spinner strip along its bottom. * test(native-chat): a pending chip shows its name and spinner, no kind icon
… like the phone (stablyai#29120) * feat(native-chat): one queue header that becomes the pause row; no composer Resume or send dialog The queued cards now sit under one header row on desktop and phone: "Queued" and the count normally, and "Paused" with the count, Clear all and Resume while the host holds the queue after a Stop. A chevron folds only the cards; the choice is local to the view and resets when the queue empties. The composer's Send no longer turns into a second Resume, and a message sent into a paused queue no longer asks "Send message?": it sends, its accepted turn lifts the pause, and the cards follow it. Clear all deletes every card through the existing per-card delete. No wire or host change. * test(mobile): find the background-tasks strip's toggle inside the strip, not the queue header's * Make queued Clear all atomic across clients * Show queued message failures in collapsed headers * Use per-card delete for paused queue Clear all * Join repeated paused queue Clear actions * fix(native-chat): a queue action still on its way greys its controls, like the phone The desktop kept in-flight queue actions only in refs (one per card, one for Resume, a joined promise for Clear all), so on a slow or remote host pressing Clear all, Delete, Steer or Send changed nothing on screen until the host answered. One keyed in-flight set, held as a ref and as render state, now covers cards, Resume and Clear all; Clear marks every card it deletes. * fix(native-chat): Resume and Clear all refuse each other in the queue guard; the steer chord skips a card already on its way Resume and Clear all now hold one shared in-flight key, so each refuses the other in the guard rather than only in the drawn state, and both header buttons grey on it. Cmd/Ctrl+Enter returns false when the newest card's action (or a Clear deleting it) is still out, so the chord no longer scrolls to the latest with nothing sent. Test controllers gain the new fields. * test(native-chat): move the slow Clear all test into its own file The queued-list test file passed its line limit; the in-flight test and the held-write render it needs now live beside it, and the list test file is back to the base's helpers. * fix(native-chat): Clear all waits out a card's own action instead of skipping the card Clear all now greys while any card in the queue has its own Steer or Delete on its way, and once that settles it claims every card. Before, it stayed enabled and quietly left the busy cards out, so a failed Delete left a card behind after Clear all, and with every card busy the click did nothing. * chore(native-chat): one comment for Clear all's availability rule * test(native-chat): update held-start queue fixture after main merge
* fix(mobile): edit queued messages in place * fix(mobile): use the platform input font size for queued edits * fix(mobile): handle missing host support while probing queued edits * Keep phone queued edits owned through save settlement * Keep phone queued edits local to mounted chat * fix(mobile): retire queued editor when its card disappears * fix(mobile): retain queued edits while reconnecting * test(mobile): await reconnect timer inside act callback * fix(mobile): publish queued edit transport after commit * test(mobile): await queued Edit inside act callbacks * fix(mobile): hand a stale queued Save to the composer and reopen on the newer text * fix(mobile): close an unchanged queued Save locally and keep stale typing in its own chat * fix(mobile): explain disconnected queued edit refusal * fix(mobile): combine queued session contract imports
…ai#28655) * feat(native-chat): image messages wait in the queue like text A message with images now queues behind the running turn and the cards ahead of it, instead of skipping the queue. Cards show an image icon and count, an image-only card names its image, and editing a card's text keeps its images. The host publishes no card holding an image to a client that has not advertised agent-session.queued-image-cards.v1, since released clients edit by copying a card's text and deleting the card. * test(native-chat): an image follow-up queues like text * fix(native-chat): project queued images before phone frame limits * fix(native-chat): preserve image sends from older clients * Clarify direct text recovery at send admission * fix(native-chat): expose queued image names to keyboard users
…and fit the force-delete button to its notice (stablyai#29878) * fix(sidebar): let kept-branch toast bodies fill the toast width * fix(sidebar): close the force-delete menu when its toast is hidden in the stack * fix(sidebar): keep focus out of a hidden toast after its menu auto-closes When the toast stack hid a kept-branch or delete-failure toast, the menu closed but Radix returned focus to the chevron inside the now invisible toast, so Enter or ArrowDown reopened the menu floating over the app with the "Always ..." item focused. - Skip the close focus return while the toast is hidden. - Refuse to open the menu while its toast is hidden. - Treat toasts past Sonner's visible-toast limit (data-visible=false) as hidden too. * fix(toasts): stop a folded toast's hidden overflow from re-expanding the stack * fix(toasts): clip a folded toast to its card instead of disabling its content The pointer-events rule left the unstyled star-nag card, which Sonner never fades, visible below the stack but dead to the pointer. Clipping the folded toast removes the overhang for every toast type, visible or not, so nothing of a folded toast can sit outside the stack and re-expand it.
…drop the floating 'Agent is working' pill (stablyai#29972)
…ntity rekey (stablyai#30005) Main's Store.migrateWorktreeIdentity re-keys every stored layout field before it sends the rename event the window re-keys on, so the window's save only mirrors it. The new oracle checks main's migrated layout model equals the model of the window's post-rekey save and the model's identityRenamed transition; the first-work test pins migrate-before-notify.
…newest release defines it in (stablyai#30000)
…ver keeps running (stablyai#30006) A paired runtime (orca serve, managed SSH/WSL orcad) owns its terminals and keeps them after this client quits, so only SSH relay terminals, which a relay kills after its grace period, still raise the quit warning. Window close is unchanged. Fixes stablyai#29916
…stead of guessing this computer (stablyai#30009) * fix(renderer): resolveOwner keeps folder and project-group twins ambiguous; deprecate the runtime-owner aliases * test(store): folder and project-group twins in the twin suite; no-host folder delete refuses * fix review: a folder's own SSH connection names its owner despite twin project groups
…e stand-in (stablyai#30011) * test(e2e): open and close structured chat tabs through an isolated Claude stub * test(e2e): satisfy changed-code lint in the structured chat stub
…#30012) The hostScope annotation on terminal list, worktree list and worktree ps named --host local / --host ssh:<id> as the follow-up for an omitted host, but none of those commands accept --host. Those hosts are reached through the runtime that answered, so no flag selects them: report a null selector and say so in the human scope line. Paired servers keep --environment. Fixes stablyai#29901
…tablyai#30014) On a headless server (orca serve, orcad) files.open and files.openDiff answer with the bare renderer_unavailable token, which the CLI printed as-is. Translate it in the CLI into a clear message with next steps, keeping a stable renderer_unavailable code. The wire answer is unchanged because the mobile app keys its preview fallback on it. Fixes stablyai#29822
stablyai#30002) * chore(ci): ratchet renderer importers of the deprecated runtime-owner resolvers getRuntimeEnvironmentIdForWorktree and resolveRuntimeOwnerForWorktree read a worktree two hosts publish as not-a-runtime, which callers treat as local. The 62 renderer files importing them are grandfathered; the list may only shrink. * ci: register the deprecated runtime-owner ratchet step in the preflight phase map
…9089) * fix(native-chat): paste a copied file into Chat the way dropping it attaches it Copying an image file in Finder and pasting into Chat typed the file name and attached nothing: the paste only attached a bitmap from the clipboard. Copied files now go through the composer's drop route, on both the app-menu paste and the paste event. Fixes STA-10652 * refactor(native-chat): share the paste guards with the copied-files branch * test(native-chat): late paste results stay dropped when the image waits for the clipboard read * Keep copied attachments pending through preparation and composition * Update file drop fixture settlement results * Keep pending attachment capability current within its draft scope * fix(native-chat): reserve pending chips before checking dropped files A local file drop checked each file before adding it, with nothing in the composer meanwhile: Send during the check went without the file, which then landed in the next draft; unmounting mid-check lost it; and files queued behind an input-method composition were lost on unmount. Drops now reserve a pending chip per file before the check, so Send waits as it already does for server-upload drops. The prepared attachment travels through the existing composition queue as one operation, settles into its draft scope after unmount, releases its chips when refused or disabled, and reads the scope's current image capability when it applies. * test(native-chat): server-upload chip calls carry no options without paste * refactor(native-chat): move the composer's image chip list into its own hook Main's server-owned paste pushed the attachments hook past the file length limit. * fix(native-chat): a screenshot picture pastes as a picture on macOS, even beside its saved file macOS lists a screenshot tool's saved file beside its picture, so the paste read as a file copy and attached nothing once the file was gone. Only a Finder copy also names its files as text. * fix(native-chat): a macOS right-click paste lets the clipboard tell Finder files from a screenshot The paste event hides Finder's file names, so a path-backed picture reserves its chip at once and the native clipboard decides: named files go to the drop route, a screenshot's picture is saved from the clipboard. Both paste routes now share the clipboard-picture save. * test(native-chat): move the paste hook's test probe into its own fixtures file The paste tests outgrew the test file length limit. * test(native-chat): hand the paste probe's hook result out after render * test(native-chat): give the remote image paste probe the copied-files callback * fix(native-chat): a pending attachment chip shows a spinner and its name, not a stacked icon A local drop now waits as a pending chip, which drew the kind icon, the file name and a centered spinner on top of each other. Without a thumbnail the chip shows the spinner above the name; with one, the dimmed picture keeps a spinner strip along its bottom. * test(native-chat): a pending chip shows its name and spinner, no kind icon * fix(native-chat): a macOS file paste keeps its own chips until the clipboard decides A macOS paste of Finder files reserved one placeholder chip, asked the native clipboard whether it held files or a screenshot picture, and then started a separate attach for the files. Removing the placeholder did not cancel that attach, and leaving the chat before the answer lost the paste. The paste now reserves one chip per copied file before asking, and captures the drop route's intake (owner, destination, chips) at the same moment. Files continue those exact chips through the existing local check or server upload, so removal cancels by the original chip and an unmounted composer still finishes into its draft. A picture keeps the first chip and drops the rest. Ordinary drops and the picker keep their fresh-admission checks. * test(native-chat): a macOS file paste survives removal, unmount and disable through the real intake Drives the real pending cache, composer attachments, external intake and paste hook with a delayed clipboard answer: removed chips never attach (before or after the answer, through input-method composition), an unmount finishes both the local and paired-server routes into the original draft with the original chip IDs, and disabling the composer meanwhile does not bring the paste back.
…' visit recency (stablyai#30015) Converting an SSH host drops its relay-era rows, but recency stayed under ssh:<target>|<id> keys, which the next startup prune discards because no row matches them any more. Re-key that host's visits to runtime:<env>|<id> in the same update, keeping the newer visit on a collision.
…SH host moves again (stablyai#27285) (stablyai#30017) * fix(ssh): link a folder workspace the server kept from an earlier move instead of conflicting (stablyai#27285) * fix(ssh): resolve a server folder's host before linking it, and read folder lease owners * fix(ssh): name a linked folder workspace in the connect's left-behind warning
* feat(native-chat): choose which agents open as a chat Settings → Chat gets a Providers list. Each agent the host can open as a chat has a switch; off opens that agent in a terminal instead. Only choices the user makes are saved. Unchosen: Claude and Codex on, others on when their CLI is installed on this computer. The renderer's route and the host's launch-mode decision both read one rule, so the tab menu, shortcuts, CLI, orchestration and relayed phone launches agree. * fix: keep chat provider settings with the other chat settings types * test: route input carries this computer's detected agents * fix(chat): resolve provider choices from their owning computer * test(chat): use checked native inventory fixtures * Fix launch preparation lifetime and execution host startup * fix(chat): keep unchosen providers on without discovery * test(chat): type provider routing fixtures against store contracts * test(chat): align shared launch fixture with private settings reader * test(chat): give the structured-session RPC fixture the private settings reader The host now reads saved chat choices through requireStore().getSettings(); the shared RPC fixture only had getClientSettings, so the launch-mode reader saw no settings and create support refused Claude. The fixture now follows each test's client settings. * fix: preserve provider choice and cached native inventory
…rder, and SSH/WSL host state, checked against the window in dev and test (stablyai#30018) * feat(sidebar): main publishes desktop focus, pins, project and host order, and SSH/WSL host state, checked against the window in dev and test * fix(sidebar): read pins through the host-filtered metadata helper; name pins as workspaces
…ly) (stablyai#30019) * Record chat tab opens, closes and host-listed chats in main (dark, layout-owner build only) A chat tab the window opens, closes, or adds and removes from a host listing of this machine's chats now reaches main as openAgentSessionTab, closeTabs or setTabProps under the window's ids, so the window's save no longer teaches main a chat tab. openAgentSessionTab takes the window's place, creation time and new split group, and the same open again changes nothing. Switch-off builds are unchanged. * test(layout): a paired server's chat tabs send nothing to main (dark) * fix(layout): keep a windowless host's chat-tab saves as they were; send synced chat opens in tab order (dark) Only a window's openAgentSessionTab (main marks it drawn on layout.apply) takes the new rules: a repeat changes nothing, a taken id is refused, and a workspace with no group takes the window's. A windowless host's own saves mint a fresh group and keep a chat whose id another tab holds, as before. A host listing's new chats are recorded in tab order, so each open's anchor already reached main. * refactor(layout): one rule set for a chat tab open; the windowless caller names only a group it holds (dark) Drops the per-sender drawn flag. The windowless save passes its remembered active group only when the workspace still holds it, so it mints a fresh group as before. Refusing a taken chat tab id is gated on the build switch: shipped builds still save the duplicate id.
…tart or turn signed out (stablyai#28467) * feat(acp): a sign-in prompt on an ACP agent's stderr ends the start or turn signed out An agent that waits for a browser sign-in prints a link on stderr and blocks for minutes. A launch spec can now name that line (signInPrompt); the connection then closes with a typed sign-in failure through the existing process owner, so a start reads notSignedIn and a running turn fails signed out instead of settling unknown. The matched line, which carries the sign-in URL, never enters the retained stderr tail, errors or diagnostics. * Prevent sign-in URLs leaking from long stderr lines * fix(acp): a stderr line cut at the cap that is not a recognised prompt is dropped, so its URL never reaches the kept tail
…pting (stablyai#30025) * fix(ssh): a host that needs a password waits for the user at launch instead of prompting Restores the persisted 'last sign-in needed a typed credential' flag that the relay removal (stablyai#27214) stopped writing, and at launch marks those hosts as awaiting sign-in so background reconnects (startup restore, managed-server status checks and tunnels) refuse without dialing instead of opening the password dialog. The user's own Connect lifts it and prompts. The terminal toast shows the refusal as an SSH state, not a bug to report. Co-Authored-By: Claude <noreply@anthropic.com> * test(ssh): give the raw-connected fixture the cache query; annotate the harness-shaped registration Co-Authored-By: Claude <noreply@anthropic.com> * refactor(terminal): keep the sign-in branch out of the toast component Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
… against the window in dev and test (stablyai#30027) * feat(sidebar): main keeps one live set of paired-server rows, checked against the window in dev and test * fix(sidebar): settle review findings; main also publishes paired-server host facts
…tablyai#28455) * feat(acp): an agent can enforce the permission mode itself through a session config option An optional launch-spec field names the session config option and its ask/full values. Every new or reopened session gets the value for the chat's full-access posture before it is exposed, and a refusal fails the start. With the field present Orca no longer answers permission requests for the person. No agent sets it yet. * fix(acp): reject unconfirmed permission mode during acquisition * feat(acp): an agent enforcing the permission mode itself runs the chat's own mode The launch spec maps each chat permission mode to its session option value; a start sets the value for the mode the host launches with (ask when it names none), replacing the global Agent Permissions full-access read. A mid-chat change takes effect through the host's existing restart of a child launched with another mode before the next send. * Keep ACP session acquisition within the line limit * fix(acp): a chat's permission mode goes to the agent's mode-category option, whatever the agent names it
…#30008) * fix(mobile): the chat's Working line uses desktop's spinner (turning circle, hourglass under reduced motion) * fix(mobile): keep working animations off interaction queue
…tablyai#30029) Naming a chat runs a one-shot agent CLI request in the chat's folder, and the CLI saves it beside the user's chats. Session History listed it, and opening it from a phone resumed the naming request instead of the chat. Fixes stablyai#29973 Co-authored-by: Claude <noreply@anthropic.com>
stablyai#30028) On a host with no window, chat tabs live only in the runtime's session snapshot. A forced rebuild from the saved session (closing a saved editor tab, an expired SSH reattach) dropped them, and every terminal-only group merge removed them from the tab order. Refs stablyai#29968 Co-authored-by: Claude <noreply@anthropic.com>
…the window in dev and test (stablyai#30026) * feat(sidebar): main produces per-workspace PR facts, checked against the window in dev and test Co-Authored-By: Claude <noreply@anthropic.com> * refactor(sidebar): share the PR cache key candidates instead of splitting an import Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
…on retap and revisit (stablyai#30033) * fix(mobile): prevent markdown and file tab reload and screen flicker on retap and revisit * fix(mobile): preserve newer saves and refresh document metadata * test(mobile): supply current document state in recorded reads --------- Co-authored-by: Neil <neil@stably.ai>
…top renames (stablyai#30037) A desktop connected to a remote Orca server kept its own copy of a tab's manual name, and ranked its saved-session title (a resumed Codex chat) above the live title the server publishes. So orca terminal rename on the server never showed on a resumed tab, and a desktop rename never reached the server. The server now publishes the tab's manual name as an optional customTitle on each terminal surface, and the desktop mirror adopts it. Desktop renames go to the server: terminal.rename by handle, plus session.tabs.setTabProps customTitle by tab id for panes that are asleep or starting. Older servers omit customTitle and strip the new param, so the desktop keeps its own name with them, as before. Fixes stablyai#29975
…i#30379) * fix(drops): name extensionless dropped images by their bytes A file dropped onto a remote workspace with no extension (some drag sources hand images over as `noname`) now gets the extension its PNG/JPEG/GIF/WebP signature declares, so the agent sees `noname.png`. Repo icon detection reuses the same signature check. Fixes stablyai#30378 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(drops): sniff extensionless images only for .orca/drops and chat attachments Explorer imports into a user-picked remote folder keep the name, matching local imports. Chat attachments on a paired server now use the staged name so they get the extension too. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Neil <neil@stably.ai>
* Open file links beside their source tab's group Clicking a file link in a terminal or agent chat now opens the file in an editor next to that tab, not in whichever group happens to have focus. A new "Open in this group" row pins the file to the source group when that group has neighbors. - Capture the source tab at click time, so focus changes during path resolution don't redirect the file. - Rank candidate groups by adjacency: a neighbor already showing the file, then a neighbor showing an editor, then any neighbor, then the source group. - "Open in this group" never falls back to a browser, system app, or other group. If the group is gone or the target is not an editor, it shows a toast and does nothing. - Line reveals target the exact view that was opened, and are dropped if that view closes before the editor applies them. * rm scratch files * Preserve empty split panes during tab reconciliation Reconciliation removed every empty group, so an empty split pane the user had made beside a tab was collapsed on the next pass. A file link opened from that tab then landed in the source group instead of the empty pane. Reconciliation now removes only groups that stale-tab cleanup emptied, and keeps panes that were already empty. Tests cover terminal and agent-session sources in both worktree and folder workspaces. * Preserve runtime owner for local file links
…k, layout-owner build only) (stablyai#30439) * fix(layout): a CLI split whose pane main closes before it mounts answers at once (dark, layout-owner build only) * test(layout): the closed-before-mount split fails because of the close
…ght seams from their defining modules (stablyai#30440) The three ipc modules re-exported symbols owned elsewhere. Importers and test mocks now name the defining module, and the re-export lines are gone (no barrels).
…ting would stamp (stablyai#30445) A tab restored before its worktree catalog loads gets a placeholder row. SSH placeholders had no host, and a server's nested-SSH placeholder carried only runtime:E, so an ssh: host selection found no matching owner and routed the terminal as a direct dial from this desktop. Stamp the SSH target, and the server proxying it, from the repo row; leave a repo id that lives on several hosts unstamped.
…s the whole page and clicks land under the cursor (stablyai#30437) * fix(browser): a remote viewer larger than the host's browser pane sees the whole page and clicks land under the cursor Fixes stablyai#30341 * test: note why the screencast double is cast * fix(browser): drop guest frames until the fitted size is applied; forget the cached CSS size when the frame size changes * fix(browser): keep a press's release and markup inside the letterboxed remote frame * fix(browser): resume live frames once fitted metrics land; remeasure the page after its frame size changes
…its own host's copy (stablyai#30447) applyCreatedWorktree merged a create into any same-id row, so a local create could inherit a server twin's stamp (or wipe it). Lineage refresh stamped a server's reply with the focused host and replaced every same-id row, overwriting the local twin. Both now match id and host, and the lineage reply is stamped with the transport it came from.
…e-SSH (stablyai#30441) * fix(open-in): open a managed server's workspace in VS Code over Remote-SSH (stablyai#30332) * fix(open-in): only open a server workspace over SSH when its files are on that host; validate the SSH link; let process-host quote code.cmd * test(open-in): expect the workspace ref in the source-control Open in payload * fix(open-in): pin an SSH-access server's editor host to the settings it was verified on
…nd cancel, on every Orca sign-in button (stablyai#30410) * fix(cloud-auth): show the browser sign-in wait and offer its link from Relay sign-in Clicking 'Sign in for Relay' handed the sign-in page to the OS browser and then showed nothing, so a browser that never came forward looked like a dead button, and the 5-minute wait ended silently. The Relay sign-in row now shows the wait with a Copy sign-in link button, and a wait that times out toasts. STA-10940 * fix(cloud-auth): show the sign-in wait on every Orca sign-in button The waiting text and Copy sign-in link now come from one shared notice used by Mobile Relay, Orca Account, Artifacts (settings, page and publish popover), Share Skills, the unexpected sign-out card and dev tools. The copyable link is dropped as soon as the browser answers, and a copy with no waiting link reports a failure instead of doing nothing. STA-10940 * refactor(cloud-auth): main owns the waiting sign-in link; renderer only mirrors it The notice now shows exactly while main holds a live link: main announces the link when the browser wait starts and clears it the moment the browser answers, so 'Waiting for sign-in in your browser' no longer outlives the wait during the token exchange. Only the newest attempt may publish its link, so an older attempt reporting late cannot replace or later wipe it. The renderer's separate pending flag and its resets are gone. STA-10940 * fix(cloud-auth): tolerate a sign-in link read that returns no promise The app-wide IPC tests stub every bridge method as returning nothing, and the one-time link read called .then on that result. STA-10940 * fix(cloud-auth): a torn-down link subscription ignores its late snapshot; restore auth bridge tests A window's one-time sign-in link read could land after its subscription was disposed and overwrite a newer value from the replacement subscription. The auth-status refresh tests the earlier rewrite dropped are back, alongside the link cases. STA-10940 * feat(cloud-auth): sign-in buttons show Signing in… with copy-link and cancel links Every Orca sign-in button greys out to 'Signing in…' with a spinner until the sign-in ends. While the browser has not answered, a line offers 'Copy sign-in link' and 'Cancel'; Cancel aborts the browser wait so a lost tab never locks the button. Main owns the in-flight sign-in (waiting on the browser, then finishing) and every window mirrors it. STA-10940
…g unpriced models (stablyai#30421) normalizeModelForPricing was an ordered chain of regexes in which a new point release fell through to its major: claude-sonnet-5-5 was billed as Sonnet 5 (cache reads at $0.20 instead of $0.10), and any future opus-5-x / fable-5-x would be too. claude-haiku-5-5 matched nothing and silently added $0 to a total that showed no caveat. The resolver now parses family + major + optional minor (family-first and legacy version-first IDs) and only accepts an exact MODEL_PRICING key, so an unknown version is unpriced rather than borrowing another model's rates. The deliberate opus-4.x -> 4.8 and sonnet-4.x -> 4.6 fallbacks go with it. Adds Sonnet 5.5 and Mythos 5/5.1 rows. Haiku 5.5 stays unpriced: it reprices a whole request above 100K prompt tokens, which daily totals cannot express. The Claude summary now carries hasUnpricedModels (as Codex has since stablyai#22073), and both panes share one unpricedCostLabel helper for the caveat. Fixes stablyai#30338
…tablyai#30446) * Check sign-in duplicates against the listed account identity A managed account folder's current Claude login can differ from the identity saved for it. The account list shows the current login, but the duplicate check compared the saved identity, so a sign-in could be missed or wrongly flagged. Duplicate detection now uses the same listed accounts as the account list, and the duplicate helper accepts account summaries. Tests cover a folder whose login email changed, and one where only the organization changed. * Tolerate invalid Claude account rows during sign-in
… Haiku 5.5 (stablyai#30427) * fix(usage): price Claude long-context requests per request, and price Haiku 5.5 Haiku 5.5 bills a whole request at higher rates once its prompt (input plus cache reads and writes) exceeds 100K tokens. Claude usage was only kept as daily totals, so that could not be priced and Haiku 5.5 stayed unpriced. The existing Sonnet 4.5/4 200K tier had the opposite problem: it was applied as a marginal threshold to each day's totals, so a day of short requests could be surcharged and a single long request was under-charged (the Claude side of STA-8117, fixed for Codex in stablyai#22360). Each turn is now classified when it is aggregated, against its own model's threshold, and daily and per-location rows carry the long-context subset as an optional `longContext` field. A streamed turn that grows across the threshold moves its whole share in the resume correction. estimateCostUsd takes one token object and bills that subset at the long-context rates and the rest at base, replacing the per-bucket tiering. Saved per-file projections carry a projection version; files from an older version are reparsed on the next scan, so history picks up the split without touching the signed cache schema. * fix(usage): keep the projection version out of the integrity hash Hashing it made older inline reports fail validation and show the 'could not be validated' error; the scanner's version check alone decides reparse.
stablyai#30450) * feat(sidebar): the owning host raises the workspace unread flag (dark) * fix(sidebar): phone session open clears and spares the flag; refresh views; blur rescan * fix(sidebar): throttle failed view retries, resend failed empty views, hold presence one refresh longer * test(sidebar): switch-on window writes neither the unread flag nor a stamp
stablyai#30456) * fix(native-chat): clicking Send or Stop keeps focus in the composer A click focused the Send/Stop button; when it disabled (empty draft after the turn, or while a Stop is in flight) Chromium dropped focus to <body>. A pointer press on it no longer moves focus, matching Enter. Adds an e2e regression with a turn-capable Claude stub. Fixes STA-10897. * Tighten comments
… PowerShell (stablyai#30424) * fix(windows): codex and claude get a prompt's double quotes in Windows PowerShell Windows PowerShell 5.1 (and pwsh before 7.3) does not escape an embedded `"` when it builds a native program's command line, so every quote in a launch prompt was dropped, and quotes could split the prompt into extra arguments. Orca's PowerShell codex and claude wrappers now escape their arguments at runtime for the PowerShell that is actually running, through one shared __OrcaNativeArgs function. pwsh 7.3+ already escapes, so it gets the text untouched. * fix(windows): escape agent args for .cmd shims under pwsh 7.3+ too pwsh 7.3+ defaults to the Windows argument mode, which still passes .cmd/.bat targets the Legacy way, so a codex or claude .cmd shim kept dropping quotes there. The function now takes the program it escapes for and names the modes that escape by themselves, and anchors the 5.1 trailing-backslash fix at the true end of the text (`$` also matched before a final newline). Tests now run the real codex wrapper with a quoted prompt, cover pwsh's Legacy mode and the newline case, and pin the claude wrapper's call. * fix(windows): strip comment lines from the PowerShell bootstrap payload The shared escaping function pushed the encoded bootstrap to 27,324 of the 28,000-character budget, leaving almost no room for a startup command to ride in -EncodedCommand, so short commands fell back to stdin (the path stablyai#7236 broke). Comment lines document the source but only spend that budget in the payload; dropping them frees 3,732 encoded characters, more headroom than main had. * fix(windows): quote agent args with "" where cmd.exe or Windows PowerShell reads them Escaping embedded quotes as \" let pwsh 7.3+'s .cmd quoting expose a prompt's `&` to cmd.exe, which then ran the rest as a command. Where cmd.exe reads the line, or Windows PowerShell counts quotes naively, the function now quotes the argument itself and writes each quote as "", as process-host's windows-command-line.ts already does. That also delivers text 5.1 used to strip, so its special cases go away. The codex and claude wrappers now come as one fragment with the function they call, the bootstrap test pins the startup-command budget instead of restating the strip, and the cwd-restore comment leaves the payload too. --------- Co-authored-by: Orca Worker <orca-worker@localhost>
…ds, pinned by an acceptance table (stablyai#30451) * refactor(renderer): one owner adapter for the deprecated-resolver folds, pinned by an acceptance table resolveOwnerWithLegacyFallback answers as resolveOwner for a named host and for rows that carry a host stamp, and keeps the deprecated answer (single focused runtime included) for missing and unstamped rows. A full-owner acceptance table pins all matrix cases and asserts the only changes from the deprecated resolver are the designed ones: twins and contested SSH hosts become ambiguous, and a stale hub stamp routes through the server that names the target. * refactor(renderer): the fold adapter shares resolveOwner's named-host rule Clean-code pass: one namedHostForOwnerRef for both resolvers, floating counts as host evidence, and the acceptance test drops non-null assertions.
…ion control holds in both layout builds (stablyai#30432) The control record named a pane no window or main holds. A layout-owner build keeps resume records on main's panes, so a record for no pane only exists when loaded from a profile. Relaunch instead of reload, seed that record into the stopped profile, and read the CLI tab's PTY from main's inventory, which both builds report.
…t guest (stablyai#30452) * fix(browser): switch client-hosted profiles with staged guest replacement Squashed from stablyai#30351 by @oliver-mee onto the current main. Fixes stablyai#30350 * fix(browser): fence staged profile guests, release switch grants, carry host profile metadata - A fence during automation retirement now revokes and stops the staged guest. - A failed or late-settling switch releases its execution-host grant so the page can be recreated. - Staging cleanup failures before handover stay visible to executor close. - createPage/restorePage carry host-owned profile metadata to profile-switch-v1 desktops, so recovery and restore can rebuild a switched page. * fix(browser): roll back a switch whose replacement died, and report a lost old guest * fix(browser): resolve client-hosted pages before the server-local target path when switching profiles * fix(browser): a staged profile-switch guest owns downloads it starts while loading * fix(browser): keep the original placement until a timed-out switch settles * fix(browser): rebind the original guest before releasing a rolled-back staged guest * test(browser): type the harness guest release mock * fix(browser): release the replaced generation's download transfers when a switch commits * fix(browser): admit file transfers from a staged profile-switch guest while its switch is pending * fix(browser): release only the replaced generation's download transfers after a switch * refactor(shared): import BrowserNetworkExecutionHost from its own module, no re-export * fix(browser): adopt a profile switch the client finished after the caller timed out --------- Co-authored-by: Oliver Mee <102673257+oliver-mee@users.noreply.github.com>
…owner resolver (stablyai#30458) Open-in owner, execution-host platform facts, doc-preview grants and the activation PTY inventory read the owner through resolveOwnerWithLegacyFallback. Open in now refuses a twin instead of launching it as this desktop's checkout; the others keep reading a twin as not server-owned. A row whose only repo row is a server proxying its SSH target routes through that server. The creation-action policy stays until browser creation folds with it. Deprecated importers 57 -> 53.
…efore startup continues (dark, layout-owner build only) (stablyai#30429) * refactor(orcad): move startOrcad's option and handle types into their own module Move-only: frees room in orcad-entry.ts for the layout-owner load repair. * fix(orcad): run main's duplicate-terminal pane repair at orcad startup (layout-owner build only) orcad builds its own runtime and never called the load-time repair, so an orcad host kept a terminal drawn in two panes. * test(orcad): type the hoisted test state without an assertion * fix(orcad): await the startup pane repair so it lands before reconcile and RPC * fix(startup): desktop awaits the duplicate-terminal repair before the window and RPC start (layout-owner build only)
…e holds (dark, layout-owner build only) (stablyai#30473) * fix(layout): editor file records keyed by path and owner, so two hosts' files at one path stay apart (layout-owner build only) Opening a runtime-environment file at a path a local file already held replaced the local record, the stored-session patch and unsaved drafts matched by path alone, a move took every owner's record of the path, and closing a bare-path tab removed both owners' records. * fix(mobile): a windowless host's editor tab under its owned id shows as active, and retiring it clears the active file (layout-owner build only) * fix(layout): a layout change's tab and pane holds end 15 s after it was sent when main never answers (layout-owner build only) * fix(layout): main's view reads and prunes keep an active file under its owned id (layout-owner build only)
…-page readers off the deprecated owner resolver (stablyai#30478) Thirteen read-routing callers (#4, #5, #10-#20 of the round-3 caller list) read the owner through runtimeEnvironmentIdWithLegacyFallbackUnlessTwin. A workspace two hosts publish is no longer searched on either host. The focus-read ratchet now counts the legacy-fallback adapter, which reads the focused runtime inside an object literal its discovery skipped; the five F1 entries that blind spot pruned come back. Deprecated importers 53 -> 40.
…h/connection/ and ssh/targets/ (stablyai#30479) * refactor(ssh): move the ssh-connection and ssh-target cluster into ssh/connection/ and ssh/targets/ Pure git mv plus import and path-literal rewrites. ssh-connection-utils stays put; the next PR splits it. Co-Authored-By: Claude <noreply@anthropic.com> * test(e2e): keep the release-checkout import at the v1.4.218 path Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
12.10.1 repairs a global-virtual-store slot an interrupted install left without dependency links (pnpm/pnpm#16642); 12.12 adds addMissingPeerTypes. The CI store-mode and terminal-perf gates follow the pin they were measured against, and mobile/ and config/audit-tools record the same pnpm.
… a host's own re-dials (stablyai#30487) * fix(relay): judge the reserve watch's 503 rule on non-drain 503s, not a host's own re-dials The watch counted every director 503, and on 2026-10-18 ~98% were host-rate-limited re-dials that grow with traffic, so it flipped production-gce-c7 back twice with no fault. It now uses the roll ladder's non-drain measure (request_count 503s less drain-return deferrals and host-rate-limited / host-in-flight re-dials from the director's runtime metrics) for both the background and the live samples. A judged minute no runtime-metrics line covers is unverifiable, not zero. Co-Authored-By: Claude <noreply@anthropic.com> * fix(relay): state the reserve watch's metrics coverage honestly and share the metrics read limit Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upstream
Summary
ELI5 When the phone reconnects to a terminal, a timer left over from the previous connection could still fire and re-fit the screen to an old layout. Now each connection cleans up after itself, so only the current one can resize the screen. ## What Changed New `createMobile
Note
innocarpe/orcamainuntil the upstream PR is merged.