Repository navigation
Upstream sync: OpenMausBot 0.1.94 (ff01be8a) - #116
Merged
Merged
Conversation
The composer is one flex row: attach, the Full access and place chips, the editor, the mic. The editor is the only child that can shrink, so with a bot's settings panel open beside the chat (or a small window) it collapsed to a few pixels; its placeholder then stacked one or two letters per line and the auto-grow made the whole box tall to fit them. Below a 30rem composer width the row wraps and the editor takes a full line of its own above the chips, with the mic/send group pushed to the right of the chip line. Tailwind container query on the composer box, same mechanism the chat header uses to fold its chips. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…els open Measured on a dev instance at the 1100x780 default and the 840x620 minimum, with the settings panel, the inspector and both open. Three things broke, all from rows or columns that could not shrink: - Chat and group headers: the chip group is shrink-0, so with a panel beside the chat (~330px column) the name truncated to nothing and the rename pencil landed under the find button. The row now wraps below 30rem — name line on top, chips underneath on the right. The query lives on a child row: a container query never matches the container. - Two side panels: bot settings deliberately keep the inspector or computer panel open (their controls open settings), but two static panels plus the sidebar left the default window a sliver of chat with letters stacked vertically. Until the window is 2xl (1536px) wide, settings now floats over the chat as a sheet and the other panel is still there when it closes. New useMediaQuery hook; the global :focus-visible ring is suppressed on the sheet container. - Composer: shipped in the previous commit (editor on its own line). Everything else checked at both sizes held up: sidebar, Tools panel, attention inbox, Settings modal, group setup card. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…able beside any panel
Omkar's second pass on OMB2 found three more breaks and asked for the
header to be simplified now that threads live in the sidebar:
- Header: the thread chip is gone; find, copy/download transcript, the
token counter and the inspector move into one "more" menu that opens
on hover (SidebarPopoverMenu gains a downward placement). Model, call
and computer stay as buttons. Four controls instead of eight, so the
row no longer runs under a side panel.
- Sidebar: while a side panel is open and the window is narrower than
1280px, the sidebar folds to its avatar rail; the saved density is
untouched and returns when the panel closes. The default 1100px window
keeps a ~600px chat with settings, inspector or the computer panel open.
- Panels sit beside the chat from 768px up instead of covering the
whole window below 1024px ("why does the whole thing hide behind
this?"); with the rail that leaves a 350px chat at the 840px minimum.
- The composer's chip group and the header's control group may wrap
instead of overflowing.
Verified over CDP on a dev instance at 1100, 974 and 840 wide with
settings, inspector, computer panel and the menu open.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…export labels Omkar looked for the share button in the new menu. The two export actions now sit under a small "Share" heading with the wording the share menu used before — "Copy as Markdown" and "Download as .md" — and the sheet is wide enough that neither clips. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Conflicts: - ChatView header controls: keep find/export in the header menu (this branch) and take main's Stop condition, which also covers a bot waiting on teammates. - usageSummary: take main's labelled compact figure (usageChip) so the menu keeps the unit, per bfd419a. - Sidebar: keep main's new TeamMenuItems and this branch's collapseToIcons prop. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…row-wrap fix(desktop): keep the chat usable at every window size, and fold the header into one menu
…90% (milind-soni#2118) * WIP: control plane reclaims idle tunnels, capacity error, alert (unreviewed) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Control plane: fix the reclaim race, re-check before DNS delete, observe by default - The sweep's claim only takes a row still marked for deletion, or whose installation was revoked or removed. A row its owner took back (provisioned again) after the sweep chose it is left alone. New race test; it fails without the guard. - Re-check that the tunnel is still idle right before the DNS record is deleted, so a reconnect mid-cleanup keeps the hostname. - OMB_TUNNEL_RECLAIM defaults to observe (unset or invalid); production starts in observe. An invalid tuning value falls back to its default with a log instead of failing every request. - Migration 0006 tags only the 2026-10-01 10:00-10:30Z operator batch as reclaims, using its own mark time. - Ship OMB_CLEANUP_SWEEP_LIMIT=4 until Workers Paid is confirmed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Control plane README: observe by default; sweep size per plan Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Control plane test: pin the Workers Paid sweep size explicitly wrangler.jsonc ships OMB_CLEANUP_SWEEP_LIMIT=4, so the second half of the sweep-limit test passes 20 itself instead of relying on the shipped value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Role names: Super admin, Admin, User in UI and server messages Owner decision: show Postiz's role names everywhere people read them. Display text only; stored roles, API values and permission checks stay owner/admin/member. Changed English strings drop their stale translations so other languages fall back to English. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Docs: describe roles as Super admin, Admin and User Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Role names: keep "owner" and "Full access" where the app means the account holder The app has two roles, shown as Admin and User. Its "owner" is the person who holds the server or computer, not a third role, so "super admin" was wrong in the proposal note, pairing hints, sign-in refusal, command-permission refusals and the self-hosting and people docs. Restore owner wording, and say "Full access" where the text is about how a device is paired. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The session/prompt idle guard (default 180 s) failed the turn and killed the child whenever an agent sent nothing for that long. Qwen Code 0.24 is routinely silent longer than that while working: it emits no ACP updates while compressing history, while backing off a rate limit (60 s up to 5 min per wait, 10 retries), or while one model request runs (its OpenAI/Anthropic SDK timeout is 600 s). Long turns were cut off mid-work and the user's retry redid everything. Raise the default to 15 minutes, above the longest normal silence. A real wedge (the OpenCode hang from milind-soni#1595) still trips, just later, and Stop still ends it at once. OPENMAUS_ACP_PROMPT_IDLE_TIMEOUT_MS still overrides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ACP has no "still working" message, so a silent agent was a spinner with no explanation until the stuck guard killed it. While a prompt is quiet, the driver now probes the agent and posts a plain-words notice whenever the answer changes: - retrying: read from the agent's own debug log (Qwen, with QWEN_DEBUG_LOG_FILE=1): "Qwen hit a rate limit (HTTP 429) and is retrying (attempt 2). Next try in 20 s." - compressing: when the log says so explicitly. - waiting on its model: the process tree holds an open TCP connection. - busy: CPU time is climbing without output. - no request open: briefly normal (an SDK sleeping between retries looks exactly like this), so it is only called "may be stuck" after 3 min. New lines in the agent's log also restart the prompt's idle deadline, so a turn that is visibly retrying is never stopped as stuck, and the final stuck error now says what the agent last looked like. Verified end to end against real Qwen Code 0.24.7 and a fake model endpoint: constant 429s (retry notices, turn kept alive), a 90 s slow model (one waiting notice, then the answer), and a SIGSTOPped process (stopped at the limit with its last-seen state). iOS and Android now keep notice rows visible as their own row, like desktop does, instead of folding them into tool runs or hiding them with tool calls off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…meout fix(acp): stop killing quiet agents, and tell the user what they're doing
chore(release): bump version to 0.1.93
… of the digest (milind-soni#2139) * fix(digest): count tool calls by identity, not by the chip's command line The turn digest keyed its tool tally on the activity chip's display title. That title is a tool name only for some drivers: Codex titles a commandExecution chip with the whole command line and the ACP core prefers `rawInput.command` over the call's own name, because in a transcript the command is the useful label. So a reported digest read [digest] · tools: memory_update ×2 (1 failed), list_routines ×1, propose_routine_action ×1, /bin/zsh -lc "jq '.routines[]? | select(.id==… {id,name,resultThreadId,sourceThreadId,delivery,destination,resul […] ×1 Two defects, one cause. The command text — paths, ids — rode into a row that is FTS-indexed and replayed into rebuilt context, and unlike `tool.summary` the title is neither bounded nor redacted by the driver. And keying on the command meant counts never aggregated: every distinct invocation was its own bucket, so a turn that ran one tool twelve times said twelve tools and the noise competed for the eight MAX_TOOLS slots. Command-titled chips now count under one `shell` identity, and the rendered line names what ran from `tool.summary`, which drivers already bound and redact. `nameIsCommand` — the predicate the renderer has used for this exact distinction since ToolActivity needed it — moves to shared/tool-name.ts so both readers share one answer instead of guessing twice. The transcript chip is unchanged: it still shows the command, which is what makes it readable. Only the aggregate record changes. Not fixed here: drivers/codex.ts:1078 stores that title uncapped, where every other driver slices to 80 — that bounds a stored field and changes the chip label, so it is its own call. Verified: server/digest.test.ts (2 new cases, red before green), digest.e2e, digest-control.e2e, verify-steps, DigestChip — 100 pass; tsc -b and tsc -p tsconfig.server.json clean; oxlint clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix(digest): keep the shell bucket's command out of the rendered line The phones split the digest's tools part after "×N" / "(N failed)" (ios DigestSummary, android TurnDigest). A trailing "(command)" made Android drop the whole tools list to one unparsed line with no call count, and iOS merge the shell entry into the next one. The redacted sample stays in the stored digest. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ni#2135) * feat(companion): let a phone with computer access preview a bot's Local VM Allow POST /api/bots/:id/local-computer/screenshot through the sidecar, behind the same per-device computer-access capability as the cloud desktop (off by default, toggled in Settings → Remote access). Only the still is reachable: the VM's lifecycle routes stay host-only. The 403 now says "computer access" since it covers both kinds of computer. * feat(ios): show a bot's Local VM on demand, even while it is idle ComputerView now asks for a Local VM still every 30 s while it is on screen (every 3 s while the bot works and the stream has gone quiet), the desktop panel's cadence, and shows whichever of that and the streamed frame is newer. A 403 explains where to allow computer access on the Mac; a 409 for a conversation not on the Local VM, or a 404 from an older computer, leaves the existing behaviour alone. Polling stops in the background. Adds the client call, a strict data-URL decoder, tests, and pt-BR strings. * docs: describe Local VM stills on the phone behind computer access * test: isolated fixture for the iOS Local VM view A disposable fake-engine server, a synthetic docker that serves PNG stills, and the companion sidecar, so the phone's Local VM view and its computer-access gate can be checked from a simulator without a real VM. * fix(ios): picture the opened thread's Local VM and follow access changes live - Project the bot onto the thread the view was opened from, so a task thread pictures its own computer (and its own seat in pool mode). - Keep checking at the idle cadence while computer access is off, so turning it on at the Mac shows up without leaving the view; revoking it clears the picture. Only the sidecar's "computer access is off" 403 is read as that. - Stamp a still when it was requested, and label the last picture when a refresh fails instead of letting it pass for current. - Move CloudDesktopSession's doc comment back onto it; say in the docs that the thread check is the client's and that polling keeps the VM from being reclaimed as idle, like the desktop panel. * fix(ios): caption a streamed frame when computer access is off; ignore a stale 401 With access off, a streamed frame of a working bot could stay on screen and hide the access notice. The frame stays (the stream is not gated), captioned with the notice. A screenshot 401 from the previous computer, landing after a switch, no longer marks the new session unauthorized. * test: abort the iOS Local VM fixture cleanly during server startup A signal during startup now aborts the launch, which stops the server child and removes its data directory, instead of leaving both behind. * feat(server,companion): relay a Local VM's live desktop to a phone holding control Add POST /api/bots/:id/local-computer/join. It answers only a loopback caller (the address carries the VNC password), only for a conversation on the Local VM, and only while a person holds that bot's computer, so a phone never drives the VM alongside the bot. The companion allows it behind the per-device computer-access capability and rewrites its loopback noVNC address into the same device-scoped relay path the VPS viewer already uses. * feat(ios): an RFB client and the calls to take a Local VM and join its desktop RFBClient is the protocol half of VNC, bytes in and bytes out: 3.3/3.7/3.8, None and VNC authentication (CommonCrypto DES), BGRX true colour, and Raw, CopyRect and DesktopSize, with pointer and key events. Partial updates are applied only once whole. CompanionClient gains control take/release under a lease, the Local VM join, viewer-close, and the authenticated WebSocket request for the relayed viewer; the join only accepts the sidecar's relay path, never a host. * feat(ios): take control of a bot's Local VM from the phone Take control under the Local VM's picture takes the bot's computer under a fresh lease and opens the relayed desktop full screen: the live picture with a pointer ring, a trackpad (swipe to move, tap to click, two fingers to right-click or scroll, hold to drag), the system keyboard, and a menu of keys and chords. Hand Back, or the app leaving the foreground, closes the viewer and releases the lease so the bot is never locked out behind an unused hold. The verification fixture gains an offline password-protected RFB desktop that records pointer and key events and paints each click, and a status endpoint for them and the control hold. * fix: bind a phone's Local VM desktop to its control lease, and harden the client Review findings on the phone control path: - The join now requires the caller's own control lease (not just any hold) and a JSON content type. A new read-only control action, check, says whether a lease still holds; the sidecar asks it every 3 s for each relayed Local VM viewer and closes the relay as soon as the answer is no (released or taken over from the Mac), failing closed on any error. A Local VM viewer without a lease is never handed to the device. - The phone keeps one lease per computer and bot across launches, so a session the app never handed back can be retaken and released; releases on any failure after asking; and finishes handing back in a background task. - RFBClient refuses desktops over 8192 px a side, copies overlapping rectangles in place, and consumes its buffer in O(1). - The read loop holds the desktop only weakly; the trackpad no longer jumps when a swipe starts; the disconnected state says what to do. - Docs no longer claim leaving the screen hands back, and note that in shared Local VM mode a hold pauses only that bot, as on the Mac. * fix(ios): ignore a stale 401 from the previous computer in Local VM control calls too The same guard the screenshot poll has: a control call answered by the computer the phone has since switched away from must not mark the new session unauthorized. * fix(ios): hand back a take that lands after the person left; leave another holder alone - The take runs in a task the view keeps, cancelled on leaving the screen or backgrounding. If it lands after that, the computer is handed straight back instead of opening a desktop nobody is looking at. - Hand-back after a failure runs in a task of its own, so cancelling the take cannot cancel the release. - When someone else already holds the computer there is nothing of ours to release, so no viewer-close is sent that could disturb theirs. * fix(ios): hand a Local VM back through the computer that granted its lease Session.withClient read self.client on every call. Settings can switch computers while ComputerView stays up, so a take acquired on one computer could join the viewer, or hand back, through the next one: the first computer stayed paused under a lease it never saw released. takeLocalVm now captures the client once, keys the lease on that client's connection, and returns it with the lease. ComputerView keeps it in the control state and passes it to both hand-back paths, including the one for a take that lands after the person left. Calls still go down the current route while that computer is the active one, so a route failover mid-control does not send the release to a dead address. * fix(ios): keep Take control disabled until the hand-back has finished handBack() cleared the control state before awaiting the release, so Take control came back the moment the desktop closed. The lease id is reused per bot and computer, so a take started during that window held the same lease the pending release was about to give up: the in-flight closeViewer and release would then close the new viewer and release the new hold. ComputerView now keeps a handingBack flag for the duration of the release; the button is disabled and takeControl() refuses to start while it is set. The take that lands after the person left already waits inside takingControl, so it needed no change. * feat(server,ios): drive a Local VM from a phone paired with the server directly A phone paired with `openmausbot serve` itself (a headless server behind Tailscale Serve or a tunnel) has no companion sidecar, so nothing rewrote the VM's noVNC address for it: the join route answered 404 to any caller but loopback, and the app accepted only the sidecar's relay path. The join now answers a directly paired phone with the server's own authenticated desktop proxy (/api/desktop-viewer/local/<target>/websockify), bound to the phone's control lease and to the conversation whose VM seat the join picked, plus the VNC password. The loopback address never leaves the server. The proxy settles the seat once at open, then re-checks the lease and the session every few seconds and closes the socket when either lapses; hand-back (viewer-close) closes that bot's lease-bound viewers at once and leaves the session's other viewers alone. Computer access is the pairing's scope: Full access may, chat-only is answered 403, which the app shows as computer access being off with a note about re-pairing. The app accepts this proxy shape alongside the relay shape, carries the lease binding on the socket, asks for no subprotocol from the proxy, and sends viewer-close as JSON so the harness acts on it. The sidecar path is unchanged: a loopback join still gets the raw address to rewrite. * Refuse phone control of unreserved Local VM pool seats * fix(ios): shrink the trackpad while the keyboard is up, so the desktop stays full width On a phone the desktop is drawn as wide as the screen, so it needs only a couple of hundred points of height. With the keyboard open, the 230-point trackpad left less than that, and the picture shrank. The trackpad now collapses to a short strip while typing: the desktop keeps its full width, and a click is still one swipe away, which typing into a desktop needs often (a field to focus, a button after the text). It grows back when the keyboard goes. * fix(ios): collapse the trackpad inside the keyboard's own animation The trackpad shrank on the keyboard button's tap with an animation of its own, while the desktop above only moved when the keyboard arrived and pushed the inset up: two animations, and on a phone the second one came a beat later, so the picture popped into place after the trackpad had settled. The trackpad now follows the keyboard's will-show and will-hide notifications and changes inside their duration, so it, the keyboard and the desktop move as one. The first-responder change is made outside SwiftUI's update pass, where a request can be dropped and the keyboard never comes, and the trackpad's hint fades rather than reflowing. * fix(ios): make room for the keyboard in the trackpad's own transaction SwiftUI's keyboard avoidance and the trackpad's collapse ran on different curves, so for a few frames the screen between them was shorter than the desktop needed, the fit flipped to height-bound, and the picture narrowed before growing back. The view now ignores the keyboard inset and pads its own bottom from the keyboard's reported frame, in the same transaction and on UIKit's keyboard spring, so the keyboard, the trackpad and the desktop move together and the picture keeps its width throughout. The trackpad's hint is cut as the pad shrinks rather than faded, since a fading line rode up over the label while the layout moved, and fades back in only once the pad has grown again. * fix(ios): fade the trackpad hint back in place once the keyboard is gone * chore(verify): show a captured Local VM desktop in the iOS fixture instead of coloured tiles --------- Co-authored-by: Rui Gomes <5658301+ruigomeseu@users.noreply.github.com>
…i#2128) The back button's height was fixed at 44pt while its width came from the chevron plus padding (~34pt), so the glass capsule rendered as an upright oval when there was no unread count. Give it a 44pt minimum width so it is a circle on its own and still widens into a pill with the badge.
(cherry picked from commit c7c6b4e)
(cherry picked from commit 573dc3c)
(cherry picked from commit 74f187d)
…age prep windowsKnownDirs() lists the install locations augmentedPath() scans on top of the inherited PATH, but it didn't include Docker Desktop's bin dir. docker.exe still turns up because something else on the machine's PATH usually finds it, but docker-credential-desktop.exe (which docker.exe shells out to for every registry pull) often doesn't, so local VM image prep fails even though "docker" itself looks installed. Adds the standard install path and a regression test modeled on the existing Antigravity one. Fixes milind-soni#2117. (cherry picked from commit eac5c25)
milind-soni#2129) * fix(ios): open conversations on the newest message when it has a table A transcript whose last reply holds a Markdown table (or code block) opened short of the end: the horizontal scroll view the table sits in threw off the height `defaultScrollAnchor(.bottom)` measured on the first pass, and the `initial` scrollTo ran before there was anything to scroll. Scroll to the last row once more after the first layout settles, and again when the thread's page arrives from the computer. * fix(ios): don't pull a reader back down when a thread's page arrives late The settle scroll re-runs when the thread's page arrives, which can be seconds after the push (slow route, reconnect re-hydration). If the reader has already scrolled up to read, that scroll yanked them back to the end. Remember a drag via onScrollPhaseChange (iOS 18+, no-op below) and skip the late scroll once the reader has moved; reset on thread switch.
deploy-composio-broker runs on every push to main, but without the CLOUDFLARE_API_TOKEN secret wrangler aborts and the run ends red, so a missing secret looks like a broken main. Check the token in a first step and run the remaining steps only when it is present; otherwise emit a warning annotation saying the broker was not deployed. The job-level condition, its dependency on control-plane and its absence from the merge gate are unchanged, and the self-test now pins the guard. Refs milind-soni#1914 (cherry picked from commit 8a0655b)
* feat(sidebar): add cross-bot Pinned threads section Implements the feature requested in milind-soni#2142: a global, cross-bot/cross-room aggregate of every pinned thread, alongside the existing pinned-bots section. Reuses the AttentionThread shape and jump action crossBotAttentionThreads already established. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(sidebar): make the Pinned threads panel collapsible Give the new Pinned threads panel the same chevron toggle every bot/group section already has, via the existing collapsedSections mechanism (sidebar-preferences.ts) and a new fixed id (PINNED_THREADS_SECTION_ID). Reuses the existing generic sidebar.section.expand/collapse i18n strings, so no new translations are needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…ni#2110) Copying a failed or missed routine.run card gave the headline plus the (often stale) summary, never the error the card actually shows, and the error text sat outside SelectionContainer so it could not be selected. Include the error in MessageActions.copyableText and wrap it in SelectionContainer. Follow-up to the cross-bot/expansion items from milind-soni#1903, which main already covers via RoutineRunCardView (8caa6bf). Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
…ownloads Reveal completed downloads in the file manager
milind-soni#2125) The Browser panel's expand button only ever called requestFullscreen(). On macOS a full-screen element takes the whole window into native full screen, where the yellow minimize button and Cmd-M are disabled, and clicking the same button again did nothing — its label and icon never changed. The only exits were Esc, the hidden green button or View > Toggle Full Screen, none of which the app pointed to. The button is now a toggle, like the desktop viewer's: a second click calls exitFullscreen(), and a fullscreenchange listener keeps its label ("Full screen" / "Exit full screen") and icon in step with the document, so Esc and the window's own controls leave it right too. A failed exit says to press Esc. Fixes MOCA-266 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(routines): timestamp run thread titles * test(routines): cover timestamped room task titles
* feat(rooms): show live computer/browser session indicator - GroupView.tsx: render "screen" messages (live screenshot frames) inline, same as ChatView already does in 1:1 chats. - GroupView.tsx: give a busy member's avatar badge the place icon (PlaceIcon) instead of a generic dot when that bot is actively in a concrete computer/browser place, mirroring the 1:1 composer's PlaceChip live indicator. Fixes: a bot running a background browser/computer session inside a room gave no visual indication at all that it was happening, even though the server already posted the screen messages to the room's own thread. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(rooms): give the busy-member place badge an accessible label CodeRabbit flagged on PR milind-soni#2119: the place icon on a busy avatar badge conveyed its meaning visually (which computer/browser place a bot is in) but had no screen-reader-accessible text. Reuse the same place.chipAria label PlaceChip already uses for the 1:1 composer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…and-release-lane ci: keep main to one running CI, and give releases their own CI lane
…d-pr-triage Integrate reviewed tools, skills and workspace fixes (Oct 2 batch 2)
… prompts for payers App half of the purchase/activation audit (H3, H9, H10, H11, H12, M6, M8, M9, M17, M18, L3, L8, L9, L10, L11): - One rule (src/lib/cloud-plan.ts) decides what every surface says about the plan. An offer to buy goes only to someone signed out (who is asked "Already have a Cloud plan? Sign in" first) or verified free with no Cloud and no payment being linked. - The Cloud session check no longer blinks to "unavailable": an answer counts for 15 minutes, a failed check keeps the last verified snapshot and says "Checking with OMB Cloud…" after two failures; a longer outage still names the plan last verified (a display-only hint). - An ended sign-in asks to "Sign in again" (signInAgain(): one step, never "signed out" in between), keeping the plan named. - Move to Cloud measures against the plan's largest disk, asks the Admin to grow the disk when it must (POST /api/cloud/desktop/disk), and explains plainly when it cannot fit or cannot grow yet. - Server menu "My Cloud" connects directly; the desktop app pairs a /pair#code= link without a second click; a Cloud's pair page says where its connection starts (capabilities.cloudHome). - Setup steps, payment-being-linked, plan on the Cloud's own Settings, visible sign-in code, after-move routines and phone steps, "+ tax". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… no disk growth assumed - Settings → OMB Cloud on a server in the app's window shows only on an OMB Cloud home (config.cloudHome); main answers cloud-plan:* for the Cloud this account last verified too, so an unavailable or ended sign-in says "checking" or "sign in again on your computer"; a refused state shows where the plan is managed with no buttons that would fail. - Only the Admin's own JSON invalid_token ends a sign-in; a 401/403 page from in between (Cloudflare, a proxy) is a failed check, never "sign in again", and never counts as a revoked token on sign-out or a failed device sign-in. - Move to Cloud counts on a larger disk only when the Admin says it grows (cloud.disk); otherwise today's free space decides and the Cloud's card offers no move it would refuse. An Admin that cannot grow the disk gets its own code and copy with no "try again". - "A plan with a larger disk" only when the move exceeds the plan's whole disk, and never on Max; otherwise "make room on your Cloud". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t opens Customers reported switching every thread a Chief of Staff opens with a teammate from "Ask for approval" by hand. Only Full access flowed down; a Chief on Approve for me or Auto-accept edits left each teammate thread at the teammate's own level (Ask by default). delegatedApprovalMode replaces delegationInheritsFullAccess: work a Chief delegates (coordinate_bots, delegate_bot, a room handoff) starts at the level of the Chief conversation it came from. It only raises (a teammate on a higher level or on Custom keeps its own), a Chief on Ask passes nothing on, and the teammate's engine caps it, stepping down to the next level it has (no Full: Approve for me; Codex has no Auto-accept edits). The thread says where its level came from and the person can still change it there. Tests: unit cases for every rule; a real-server e2e where a Chief on Approve for me brings a teammate in and the teammate's run starts in auto, while a Chief conversation on Ask leaves its teammate on Ask (removing the wiring fails it); 38 room/group/delegation/team files and the Chief, coordination and Full-access suites pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-flows-down A Chief of Staff's approval level flows down to the threads it opens
…se-flow-app Cloud after purchase: steady plan status, calm sign-in expiry, no buy prompts for payers
…he Meadow skin (milind-soni#2173) * feat(skins): add Meadow, the green MausBot skin A ninth skin beside the original eight, which are untouched: white page, faint-green sidebar, mint selected row, green accent and a green-black user bubble with its own inverted @scope context. The contrast gate now measures both inverted bubbles (Daylight and Meadow). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: add the Advanced mode preference Simple is the default for a fresh install; an existing install keeps Advanced so an update never hides a control someone already uses. The default is settled before applySkin writes its own first-run key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(settings): Advanced mode switch in Appearance Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(chat): lock usage and inspector behind Advanced mode In Simple mode the header's More menu still lists Usage and Inspector, disabled under an "In Advanced mode" heading, and an inspector left open closes when Advanced mode is turned off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(model-picker): plain-words picker in Simple mode Simple mode opens the model picker on provider cards, models by name with a one-line hint, effort as Quick / Balanced / Deep / Max, and a "use for new chats too" checkbox in place of the scope toggle. More shows today's full picker in the same popover; Advanced mode opens on it directly. The friendly steps map one-to-one onto the real effort levels, and a level a bot already uses is never hidden. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(settings): put the Advanced mode switch at the top of General Appearance was too hard to find. A paired remote client has no General page, so it keeps the switch in Appearance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(bot-settings): Details/Library bot panel in Simple mode In Simple mode the bot settings panel opens on the bot's avatar and two tabs. Details has Name and Job, the standing instructions (SOUL.md, same save path and drift banner), "Ask me first" / "Decide for me" mapped to the ask and auto approval levels (with the local-computer Auto warning), the bot's skills with the same review-gated on/off switch, and an "All settings" row that opens today's fold-out view with a Back link. Library lists images and files the bot made in the open conversation and jumps to the message; otherwise an empty state. Advanced mode is unchanged. SkillsSection's skill state and review dialog move into useManagedSkills and SkillReviewDialog so both panels share them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(computer-panel): Simple-mode tabs, Works-on grid and centred tab bar Centre the panel's tabs as a pill with close pinned right (both modes). Simple mode shows Computer | Browser | Files: the Browser tab stays when the built-in browser is off and offers to turn it on (same PATCH /api/config as Settings > Experimental, plus the bot's own switch); Files shows the working folder and the files this chat changed, read from the turn digests. The Computer tab gets one Take control / Full screen / Sleep row and a "Where {name} works" 3x2 grid that runs the same selection code as the Works-on picker, including the auto-approve warning for this computer. VPS start/prepare/replace, the backend picker, VM settings link, two desktops, Delete VM, the gear and the Routines card stay Advanced-only; VPS setup becomes one line with a Show advanced controls button. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(routines): week grid with a details drawer and a plain editor The Automations page becomes Routines: one header with the date arrows, range and Today, a Day / Week / List switch, Run logs, and New routine. Webhooks stay in the header in Advanced mode only. Grid chips take the bot's colour as a soft tint with its avatar; paused routines keep their upcoming slots, dashed and labelled Paused. Picking an occurrence rings it and opens a right-hand drawer (an overlay on a narrow window) with the bot, the schedule in words, what to do, where it runs, where results go and the last three runs, plus Run now, Pause/Resume, Edit and the existing join / open / cancel actions. It replaces the details popover and sends the same requests. In Simple mode the editor asks only what should happen, who does it, when, Once / Every day / Weekdays / Every week, and the instructions; everything else sits behind More options, which opens by itself for a routine that already uses one of those settings (a cron schedule, Boat runner, run limit, team goal, attachments). Advanced mode keeps today's editor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(ui): liquid glass surface for centred pop-ups Adds .glass-surface, .glass-card, .glass-rail and .glass-scrim, built only from each skin's own menu, card and ink tokens, so all nine skins get a glass of their own colour and no skin block changes. Reduced transparency falls back to the opaque menu colour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(settings): glass pop-up with You / AI / Computers / Account groups The rail now files every page under a labelled group; the narrow-window picker uses the same groups. Section ids, visibility filters and toggleAppSettings deep links are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(apps): one-view Apps pop-up with tiles and your MCP servers Title Apps, search in the header, All / Connected / MCP servers chips, a three-column tile grid with Connected state and used-by avatars, and the MCP servers section on the same scroll with an on/off switch per server. Connect, accounts, grants and every notice reuse the old logic. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(triggers): Triggers pop-up for webhooks When [source] -> [bot] should [instructions] creates through the same POST /api/webhooks; the list shows name -> bot, deliveries, Copy link and an on/off switch, with the editor, event types, rotation and the delivery log under Advanced options. Webhook actions move into a shared hook so the Automations tab keeps working unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(sidebar): Routines, Triggers and Apps as direct footer rows Replaces the hover Tools menu. Advanced mode keeps Team map behind a small Tools menu (an icon in the avatars-only density); the failed routine dot and the guided tour anchors stay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(chrome): one sidebar top row on the traffic lights; call from the composer - Sidebar header is a single row centred on the macOS traffic lights (trafficLightPosition y=16, 14px buttons -> 46px row): light inset, compact inline server switcher (icon, truncating name, tiny chevron), draggable spacer, buttons as no-drag. Windows/Linux get a 48px row; the icons rail still stacks with the icon-only switcher beneath. - Simple mode keeps only "+" in that row (Expand stays on an icons rail); Advanced keeps collapse and Active Threads. - Chat header: All threads picker is Advanced only; the call button moves out of the header into the composer beside dictation as a Send-sized waveform circle with the same start/hang-up/help behaviour and telemetry. Rooms keep their header group call button. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(model-picker): Simple picker in columns with effort along the bottom Providers sit in a quiet column on the left (More is its last row and carries the "All models, API keys, local models" label), the chosen provider's models fill the right, and a band across the bottom holds "How hard should {bot} think?", the new-chats checkbox and Manage AI accounts. The Simple popover widens to 520px, still clamped to the window; the full picker keeps 420px. Adds an empty state for a provider with no models to list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(settings): five-page Simple settings and safe-area glass pop-ups Simple mode's Settings rail now has at most five pages: General, Appearance, AI (Model providers, API keys, Decision model stacked under headings), Computers (Remote access, Servers, Local VM, Built-in browser) and Account (OMB Cloud, Organization, People, Activity). Usage, Backups, Experimental and Installations stay Advanced-only; a deep link to one of them still opens it as a temporary page, and every other section id maps to its combined page and scrolls that section into view. The remote-client reduced set and the Advanced grouped rail are unchanged. The built-in browser switch moves out of Experimental: it heads the Local VM page in Advanced and is its own block after Local VM on Simple's Computers page, writing the same features.browser setting. Browser profiles move with it; Experimental keeps skill drafting. Settings, Apps and Triggers sit in a safe area that clears the macOS traffic lights and Windows caption buttons (56px top, 24px elsewhere), at min(1040px, 100% - 48px) by min(760px, 100% - top - 24px). The Apps grid sizes its columns by container width, and MCP server rows and the MCP header wrap instead of overflowing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: browser on by default with its own tab switch; leaner header and sidebar - The built-in browser is on unless switched off (an explicit false is kept). The computer panel always shows the Browser tab, with a switch that turns this bot's browser on or off. - The chat header no longer carries All threads; threads live under each bot in the sidebar. - Team map is its own sidebar row in Advanced mode; the Tools menu is gone. - The sidebar's top buttons are smaller. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(place): Auto as the conversation default; no place chip in Simple Simple mode no longer renders the composer's "Where this conversation works" chip: every conversation follows its bot's Works on, which is Auto by default. Advanced keeps the chip. For a bot on Auto, the chip's first row now reads "Auto - Picks the right place for each task" and stays selected while the conversation has no pin, instead of "Follow this bot's setting - Currently Auto". A bot set to a specific place keeps the "Follow this bot's setting" row. The Simple "Where {name} works" card already showed a pin note ending "Change it from the composer", which pointed at the chip Simple no longer has. In Simple it now only names the place, using the grid's labels. There is no one-click "Use Auto" there: the wire task cannot tell a person's pin from one Auto recorded (surfaceSource never leaves the server). New bots already start on Auto on every creation path (New bot dialog, saved defaults template, POST /api/bots, Chief-created bots, package import), so no creation code changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(sidebar): right-align the server switcher beside the top buttons - Top row order is now [lights] [drag space] [server] [buttons]: an empty, draggable flex-1 spacer pushes the compact switcher (max 140px, truncating, chevron kept) up against the buttons, in Simple and Advanced alike. - macOS: the lights span 16-76px on macOS 26; their reserved space is now 72px from the row's 16px inset, so nothing clickable (and no hover background) starts before 88px, 12px clear of them. The browser build's placeholder dots keep the same 12px. - Right padding 16px -> 8px, so the last button sits 8px from the sidebar's edge; buttons stay 2px apart and 2px from the switcher. - In a tight row the switcher gives way first and its button clips instead of spilling onto the buttons; the buttons never shrink or wrap. Its error note now hangs from the row's right end, so it stays inside the sidebar. - Windows/Linux get the same right-aligned order with 16px left padding; the icons rail keeps its stacked layout. - Sidebar.header.test.ts: order, padding and clearance assertions follow the new layout; the Windows/Linux case renders with its real host label. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(model-picker): Simple picker lists every provider, names only, full-width effort The Simple picker's provider column now lists every provider the picker knows (sign-ins, then API keys, then local engines) with no top-3 cap; an API-key provider carries a small key so a sign-in and a pasted key for the same vendor read apart. The More row is gone: a provider shows its suggested models and a quiet "Show all {count} models" row opens the whole list in place, with a search box once it passes 12 models. A provider's local models follow its own (loaded first), and a local engine lists its models the same way. "Set up" on a provider that needs setup is now the only way into the full picker. Model rows show names only, truncated with an ellipsis; a blurb is the row's tooltip. The popover narrows to 380px with a 128px provider column. The "How hard should {bot} think?" label is gone and the effort steps (or a named-variants select) span the whole bottom band, labelled "Reasoning effort" for assistive tech. Escape in the Simple view closes the popover instead of switching to the hidden local pane. Removes the now-unused model.simple.more, model.simple.moreOptions and model.simple.think strings; the no-models note no longer mentions More. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(call): set up a voice in a pop-up; keep Apps bot avatars in their rings Call help: when a call can't start for want of a voice, the help card's "Open agent settings" (which dropped Simple-mode people into the bot's full Advanced settings) is now "Set up voice". It opens VoiceSetupDialog, a centred glass pop-up over the chat holding the bot's own VoiceSettings card (engine, API key and Save, model/server, voice picker, read replies), saved through the same useBotSettingsDerived patch as the Voice section. "All voice settings" closes it and opens the bot's full settings at Voice. If a call becomes possible while it is open, it says so and offers Start call, which starts the call exactly as the call button does. Composer, header and room placements share it; in a room it moves member by member and stays on the last. "Choose This computer" is unchanged. Apps pop-up: a "used by" mascot fills its whole square, so drawn at the ring's own size its corners poked out of the white circle. Each avatar now sits in a fixed 20px clipping disc and is drawn at 16px, which keeps every mascot body, and uploaded images, inside the ring in every skin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(browser): take control implicitly; drop the Take control button The Browser tab no longer has Take control / Return to bot. The page and toolbar are usable whenever the view is connected and no other window holds the browser: - The first real interaction (click, scroll, key, paste, address submit, back/forward/reload, tab actions, Type or paste text) sends take and buffers itself and everything after it until the take resolves, then flushes in order through the input queue and execute(). Hover, a lone modifier or a stray release never takes control. A refused take drops the buffer and shows the server's message in the error bar. - After 8 idle seconds with no key or button held, the panel drains its input and sends release so the bot carries on. Every input restarts the wait. Closing the panel hands back first when nothing is held or unsent; the server's disconnect cleanup covers the rest. - While this viewer holds the browser a small status chip (hand + "You're using the browser") sits where the button was; a take slower than 300ms shows "Waiting for {bot} to finish...". Another window's hold keeps the paused live view. The ⋯ menu is unchanged. The server's exclusive lease is untouched: person and bot input still never interleave. The lease logic lives in src/lib/browser-control.ts, one controller per live-view connection. The input queue gains settle() and size() so a long buffer is fed in batches under its 32-item halt, and its overflow message no longer says "Release control". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(place): Simple notes only a person's pin, with a way back Review fixes for the Simple place change. Clients can now tell an Auto pin from a person's. The task wire gains surfaceAuto, which toWireTask derives from the private surfaceSource and never stores. surfaceSource itself stays on the server. Simple's "Where {name} works" card said "This chat is pinned to ..." under every pin, including the ones Auto records on a chat's first computer or browser turn. Those are most pins, and the person never set them. The note now shows only for a pin that keeps the chat away from the grid's choice and will not move with it: a person's pin, or one from before the server recorded who set it. It stays hidden when the pin matches Works on or Works on is Off. The composer chip is gone from Simple, so the note gets a "Use {place}" button. It clears the chat's pin, and the chat follows the grid's choice again. The button is disabled while a turn runs, since the server refuses that change (409). The client reducer drops surfaceAuto when the person pins or unpins a chat. A person's choice is never marked as Auto's, even before the server answers. Surface prompts no longer send the person to "the conversation's computer selector", which Simple does not show. They name the Computer panel, which both modes have. The select_computer variant now swaps a shared constant, so the two wordings cannot drift apart. Advanced keeps its chip and its note. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(sidebar): show the server switcher as icon + chevron when the top row is tight Review follow-up to ef4a4ab. On macOS in Advanced at the default 320px sidebar the slot between the lights and the three buttons is only 121px, under the switcher's 140px cap, so the drag spacer collapsed to 0 and the pill still ran from just past the lights to the buttons ("This com..."): a 12px nudge, not the move to the right that was asked for. - The spacer and the switcher now sit in one slot that is a named size container (sidebar-top). Below 164px (the 140px cap plus a 24px drag gap) the pill drops its name and shows icon + chevron; title and aria-label keep the full name. Same pattern as the chat header's chathead container. - Result on macOS: Advanced 320px puts the pill 90px past the green light with a 78px drag gap; compact 272px 42px past it; Simple 320px and Advanced from about 364px keep the full name with at least 24px of gap. At the 240px minimum the pill sits at the 12px clearance, chevron intact. - The error note still anchors to the row (container-type does not make the slot its containing block) and stays inside the sidebar. - Sidebar.header.test.ts: the macOS and Windows/Linux row tests now require `relative` on the row, so the note cannot silently lose its anchor; the macOS test checks the slot container, the name's container variant and that the title keeps the name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: Simple picker reaches every account and local model again Review fixes for the Simple model picker. - Every sign-in account is reachable again. When a Claude or OpenAI row has more than one account (two Claude accounts, or Codex and the ChatGPT plan), an Account select sits above its models. The row opens on the account last browsed, else the bot's, else the first one ready to use. The Advanced rail is unchanged. - A signed-out engine that lists local models keeps that list when its row is clicked again: what needs setup no longer depends on the hidden full picker's pane. A quiet "Sign in for {name}'s own models" row leads to the full picker's sign-in. - Browsing to a provider that runs local models, or opening its whole list, looks for local models again. A provider with nothing to list offers "Check again". - A provider the organisation blocks is dimmed, is named "Managed by {org}", and shows the policy text instead of Set up. - Models that share a name (pi's routes) show their route as muted text, and every row's tooltip and spoken name carry the route. - The API key is a badge on the provider mark, and "(API key)" or "(API)" leaves the name, so OpenRouter, Mistral and the Claude key fit the 128px column. - "Show all" stays in place as "Show suggested only" once open, so keyboard focus is not lost. - The named-variants select keeps a short "Reasoning" label. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: keep paired desktops on remote voice settings; focus the voice picker once a key is saved Paired desktops: on a desktop paired to another computer, the call help's "Set up voice" opened the pop-up, whose saves the pairing refuses (the bot update is PATCH /api/bots/:id, a 404 there; engine and key writes are PUT /api/config, a 403), and which had no "Voice output on this Mac" switch. There the button now opens the remote agent settings again, as "Open agent settings" did (a room's member chat first). Those save through the host's /profile route with the card locked. The pop-up stays for everyone else. Focus: the pop-up started in the API key field whenever the engine has one, even with the key saved and only a voice missing. It now starts on the voice picker when VoiceSettings shows it (the engine is set up), else in the first field (the key, or the Chatterbox server). The voice select carries data-voice-picker for this. Tests: paired-desktop cases for a bot's chat and a room; the voice-picker focus case; and a check against the real VoiceSettings that the picker is drawn only once the engine is set up, after the key field. The existing key-field focus test now stubs lookups per selector. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat: Simple picks become the bot's default; Default model in the bot panel - The Simple model picker drops "Use for {bot}'s new chats too": every model, effort or reasoning-mode pick also sets the bot's default, so a new thread starts on what was chosen last. Existing threads keep their model. Advanced keeps its own scope choice. - The bot panel's Details tab gains "Default model" between Instructions and "Before {bot} acts": the same plain-words picker, shown in place (contained) so the scrolling panel cannot clip it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix: browser take-over review fixes (stale input, status pill, Tab, hand-back) Review fixes for implicit browser control (no Take control button). - Stale input: the take reply now says whether the grant waited for the bot's own browser action (BrowserRuntime.take resolves true when agent work was running). If it did, clicks, keys and page-relative toolbar actions made while waiting are dropped instead of replayed on a page that may have moved; an entered address or New tab still runs, and the releases of dropped presses are swallowed. A pill says "{name} was busy, so that wasn't sent. Try again." until the next interaction. - Status at any width: the status moved from the toolbar into a pill over the top of the live view (pointer-events-none), so "You're using the browser" and "Waiting for {name} to finish..." show in words at the default 400px panel. The hint no longer promises the bot carries on: "{name}'s browser tools are paused while you use it. Control goes back to {name} after a few seconds without input." - Repeats during a take: toolbar buttons, the address bar and Restart wait out a take as they wait out a running action, and the controller keeps at most one buffered toolbar action. - macOS shortcuts: keys the server sends as one whole press (shortcuts and discrete keys) no longer count as held, so Cmd+C no longer blocks the hand-back (macOS sends no key-up for a key let go while Cmd is down). - Keyboard: Tab and Shift+Tab pass over the live view until the person clicks or types in the page, so tabbing through the panel neither traps focus nor takes the browser from the bot. - Typing dialog: control stays with the person while "Type or paste text..." is open; closing it restarts the idle wait. - Profiles: opening the switcher hands an idle hold back at once (or as soon as a running action ends) instead of after 8 seconds, and the dialog says why it is locked while another window holds the browser or an action runs. - Server refusals no longer point at a Take control button: a browser an interrupted action left uncertain says "Choose Restart browser... in the browser menu"; other refusals say "Browser control changed. Try again." - Docs: the permissions page and the browser verification checklist describe the new hand-back and stale-input behaviour. Tests: new controller, panel, viewport, runtime and live-server cases for each fix, mutation-checked. Updated because behaviour changed: the status chip test (now the pill, aria-description instead of title, new hint) and browser-live's "Take control" expectation (now "Browser control changed"); the browser-live runtime fake gained interrupted(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(browser): route gates under the browser-on default The owner-only route test assumed the built-in browser was off by default. It now checks both gates: on (the new default) reaches the missing-engine gate, and a browser switched off still refuses first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(smoke): expect the browser on by default in the packaged-server smoke This branch turns the built-in browser on unless someone switches it off, but the packaged-server smoke still required a fresh home to report the browser off ("access remains opt-in"). Package Windows failed on it, and release.yml runs the same check for macOS, Windows and Linux, so the next release would have stopped there. The check stays as strict: a fresh home must still find the bundled engine at the pinned version, and must now report the browser exactly on. docs/browser-packaging.md said the same old default and is updated too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ui): address Simple mode review regressions --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: milind-soni <milindsoni201@gmail.com>
# Conflicts: # src/components/CallView.tsx # src/components/ChatView.tsx # src/locales/en.json
…d-mobile feat: integrate reviewed Live calls on desktop, iOS, and Android
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Milind Soni <46266943+milind-soni@users.noreply.github.com>
…ilind-soni#2188) * feat(phone): Connect your phone, to this computer or your Cloud A paying Cloud customer could only find this computer's phone pairing. It was four clicks deep for a Cloud (Server menu, My Cloud, Settings, Remote access) and nothing said where a phone would connect. - Account menu: "Connect your phone" says where the phone will connect (to this computer, to your Cloud, to this server). It opens Settings -> Remote access, scrolled to the pairing that fits the window, with focus on Pair your phone / Create pairing code. On another server it is shown only to a session that may make a pairing code there. - "Get OpenMausBot for iOS" becomes "Get the phone app": iPhone (App Store) and Android (APK), each as a QR code with its link. - Settings -> OMB Cloud, paid plan: "Use your Cloud on your phone" opens the Cloud in this window on its own phone pairing. It uses a new no-argument cloud-account:connectHomeForPhone IPC that adds the fixed ?desktop-settings=phone, and the pair page carries that on. Before the Cloud is Ready, or if opening it fails, the card gives the two steps. On the Cloud itself the same button opens the pairing directly. - Docs: a three-step "Use your Cloud on your phone" section in docs/ios-companion.md and docs/cloud-pro.md. - Strings translated in all nine packs; source-hashes accepted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(phone): on this computer, offer a paid Ready Cloud first The customer who asked was on their own computer with a paid Cloud. On this computer, "Connect your phone" now offers both destinations when the verified snapshot shows a paid plan (any tier) and a Ready Cloud: - "to your Cloud (always on)" first, doing what Settings -> OMB Cloud's "Use your Cloud on your phone" does (connectHomeForPhone: the Cloud opens in this window at its phone pairing). If that fails, Settings -> OMB Cloud opens, where the card says what to do. - "to this computer" second: the local pairing as before. A paid plan whose Cloud is not Ready keeps the single "to this computer" line, with a note that the Cloud will show there. Free, signed out, lapsed or unverified accounts see only "to this computer". On the Cloud itself and on other servers nothing changes. Get the phone app's dialog offers the same destinations in the same order. Menu items get an optional third line (a note), drawn in the tertiary ink. Two strings added in all ten languages; source-hashes accepted. Docs updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Real merge of milind-soni/OpenMausBot main (4ed952a..ff01be8, 35 upstream pull requests). Our behavior wins on conflict; upstream improvements layered in. Locales merged as a union of keys, rebrand pass run, baseVersion 0.1.94. Kept out or guarded: upstream Cloud flows (Connect your phone to your Cloud, purchase, plans) stay behind CLOUD_SERVICES_ENABLED; upstream App Store and pricing links emptied; Simple mode stays off (Advanced is the only exposed experience); upstream Live call UI and iOS Live call, iOS Local VM take control and the week grid drawer not taken. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hd92V2CX6HCgfX8oYnCgMz
Every /api/live route answers 404 and no OpenAI session can be created unless the server runs with SAGAX_LIVE_CALLS=1; LiveSettings carries `enabled` so clients know. Android shows its Live call button only when the computer reports Live calls enabled. Our voice call engine stays the call path. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hd92V2CX6HCgfX8oYnCgMz
Locales merged as a union of keys, #117's strings winning. Upstream's skills library stays inside the bot's Library > Skills (behind features.skillsLibrary); its separate Settings page is not mounted. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hd92V2CX6HCgfX8oYnCgMz
…nts allows, Sagax data dir in upstream tests Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hd92V2CX6HCgfX8oYnCgMz
…cal VM image cannot capture the guest turn Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hd92V2CX6HCgfX8oYnCgMz
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.
Owner report (GOX, org mode): "Validate that we can add plugins and skills as we want. I'm trying to add the GitHub MCP or even log into GitHub ... and it's not letting me."
What blocked each path, and why
/api/mcp/serversis admin-only, and its screen sits in Connected apps, which is off by default, so members had no UI. The list is server-wide, so one OAuth token or PAT served every person. GitHub's OAuth has no dynamic client registration, so the sign-in failed withclient_required.withholdHostTools. There was no per-person option.claude plugin marketplace add/installtyped by a bot runs in host Bash, which is denied on an org server (deny beats anySAGAX_CLAUDE_ALLOWrule). The sandbox has noclaude, and an install there would not reach the engine anyway./api/bots/:id/skills*was admin-only (403 for members), and a private repo could not be read.ghin the sandbox, no per-person credential, and Bash is denied on the host. Egress was not the blocker: public internet is open (github.com, codeload, objects, raw, ghcr.io and api.githubcopilot.com are reachable).Fix
SAGAX_GITHUB_CLIENT_IDor Settings > Organization), or a pasted token.principals/<pid>/connections.enc) and written to/workspaceforghandgit.sagax-stdio).org_host_command) or mounted on an org server..mcp.json,.lsp.jsonorbin/, and loaded with--plugin-dir; they also appear in the "/" menu.useis read-only.gh,nodejsandnpm.Tests
org-connections.e2e(OC-1..6), plus unit tests for the person store, GitHub connect, bot plugins, the stdio relay, sandboxd stdio and the UI.typecheck,lint,i18n:check,test:unit(915 files),test:electron, and the related e2e (user-sandbox, member-access, harness-commands, mcp-selection).Deploy
Redeploy the server image (sandboxd is the same image) and rebuild
sagax-sandbox. Perspicax PR (optionalSAGAX_GITHUB_CLIENT_IDpassthrough, docs) is linked separately.🤖 Generated with Claude Code
https://claude.ai/code/session_01Hd92V2CX6HCgfX8oYnCgMz