Commit Graph

157 Commits

Author SHA1 Message Date
Peter Steinberger
f494f1579a fix(ui): align session PR rows with the composer width (#105604) 2026-07-12 16:03:05 -07:00
Peter Steinberger
c9ec723546 fix(ui): prevent New Session input loss during creation (#105702)
* fix(ui): lock pending new-session drafts

* chore: defer changelog to release generation
2026-07-12 15:28:39 -07:00
Peter Steinberger
238c7973ad feat(chat): native session scroll-back with offset paging and import-aware history (#105688)
* feat(chat): native session scroll-back with import-aware history paging

* fix(chat): page imported session history

* fix(chat): restore terminal import snapshots

* fix(chat): gate cli import resolver on ignore flag to stop history recursion

* fix(chat): correct scroll-back types and drop orphaned recent-messages reader
2026-07-12 13:58:40 -07:00
Shakker
7d8b24a55f test: cover precise settings deep links 2026-07-12 21:46:50 +01:00
vyctorbrzezowski
f69219f768 feat(ui): search settings blocks 2026-07-12 21:46:50 +01:00
Peter Steinberger
29a7654b29 feat(ui): search session transcripts (#105635)
* feat(ui): add session transcript search

* chore(ui): keep release notes in pull request

* chore(ui): sync session search locales

* fix(ui): localize session transcript search

* chore(ui): refresh merged locale metadata
2026-07-12 12:49:06 -07:00
Peter Steinberger
a1c4ef189b fix(ui): explain grayed-out rows in the new-session folder picker (#105605)
* fix(ui): explain grayed-out rows in the new-session folder picker

Disabled device rows now carry a reason tooltip (device offline vs. no
folder-browsing support), the admin-gated folder trigger says it needs an
admin connection, and dimmed dot-directories are labeled as hidden folders.

* chore(i18n): sync locale bundles for new-session picker tooltips
2026-07-12 12:32:05 -07:00
Peter Steinberger
36e81bf45e fix(ui): queued steers appear only above composer (#105603)
* fix(ui): keep queued steers out of transcript

* chore: leave release notes to release flow
2026-07-12 11:42:08 -07:00
Peter Steinberger
73ca64fca6 feat(ui): add a Create PR branch row with rate-limit staleness to session PR chips (#105116)
* feat(ui): add a Create PR branch row with rate-limit staleness to session PR chips

* fix(ui): gate the Create PR row on a pushed branch

* improve(ui): gate the Create PR row on comparable pushed commits and count untracked work

* fix(ui): satisfy spread lint and align branch-row test fixtures

* chore(ui): translate Create PR branch row copy

* chore(ui): drop zh-CN retranslation churn from the aborted backfill

* fix(ui): guard branch diff stats against checkout diff drivers and fail closed without a default branch
2026-07-12 18:23:30 +01:00
Peter Steinberger
879b66ab46 fix(ui): preserve manually entered worktree base (#105351) 2026-07-12 12:59:47 +01:00
Peter Steinberger
83dfb8e78f fix(ui): clear stale new-session worktree base (#105331) 2026-07-12 12:40:39 +01:00
Peter Steinberger
f94a359338 improve(ui): fold the New session target controls into click menus (#105265)
* improve(ui): fold the new-session targets into click menus

The /new target controls become Cursor-style trigger menus instead of an
inline control row: a folder trigger opens the directory browser as a
floating panel (with editable path in its head for manual entry), and a
where trigger opens one menu holding Gateway/node selection plus the
worktree toggle with labeled base-branch/name fields; the agent picker
becomes a menu when several agents exist. Triggers show live labels
(folder basename, node name, a branch badge when a worktree is on), so
the row stays one quiet line even on phones. Menus reuse the shared
session-menu item styles and the chat composer's details/summary
dismissal contract (outside pointerdown, Escape restores trigger focus).
Node-bound drafts no longer show an inert worktree toggle; the item
disappears because managed worktrees are Gateway-only.

* fix(ui): harden the new-session trigger menus

Review fixes: the folder trigger no longer shows the Gateway workspace
basename for node sessions (an empty node folder means that node's
default directory); sibling menus now close on the details toggle so
keyboard-opened menus stay mutually exclusive; and phone menus anchor to
the trigger row full-width so a wide browser panel under a non-leftmost
trigger cannot overflow the viewport.

* fix(ui): keep filesystem roots visible in the folder trigger

folderDisplayName falls back to the raw path so picking '/' (or a drive
root) labels the trigger instead of leaving it blank.

* fix(ui): give the new-session menus the native-select keyboard contract

Opening a menu moves focus to its first item, ArrowUp/Down wrap through
the items (browser rows included), and Home/End jump to the edges,
restoring what the replaced native selects provided. Re-picking the
checked agent no longer resets the draft (the native select never fired
change for the same option).

* fix(ui): keep native key behavior in menu text fields

Menu arrow/Home/End navigation now ignores events from text inputs so
the browser path, base-branch (datalist), and worktree-name fields keep
their native caret and picker behavior.

* fix(ui): let typed paths apply without a directory listing

Admins on hosts without a working fs.listDir keep manual folder entry:
the browser head input tracks a draft path and Use this folder applies a
typed absolute path even when listing fails; shapeless fs.listDir
payloads render as an empty directory instead of crashing the render.
The folder menu also initializes browser state before the focus hook
captures updateComplete, so keyboard-opened menus focus their first row
as advertised.

* fix(ui): apply exactly the shown browser path

Use this folder now applies the head input's absolute path only; the
draft syncs to every listed directory, so browsing is unchanged while an
edited path can never lose to a stale listing.

* fix(ui): let the browser express host-default directories

Review fixes: a cleared path input now applies '' — the host's default
directory (workspace on the Gateway, home on a node) — restoring the
state the replaced clearable folder textbox could express, and directory
results no longer overwrite a path the user typed while the listing was
in flight. E2E covers clearing back to the node default.

* fix(ui): apply the requested directory during browser navigation

loadBrowser assigns the head input the destination it is fetching, so a
mid-flight Use this folder applies where the user is heading instead of
the directory they just left.
2026-07-12 12:09:53 +01:00
Peter Steinberger
c5208f9dfe feat(tooling): enforce indexed access checks in UI tests (#105283) 2026-07-12 11:35:00 +01:00
Peter Steinberger
dba78584ff fix(ui): preserve rejected first message when session send fails (#105261)
* fix(ui): preserve rejected first session message

* chore: leave changelog to release closeout

* fix(protocol): regenerate session create result
2026-07-12 11:09:38 +01:00
Peter Steinberger
842f8f3ee9 feat(ui): auto-load older external-session transcript on scroll (#105209)
* feat(ui): auto-load older catalog transcript on scroll with a stable viewport

* fix(ui): surface the load-older fallback when auto-load is blocked on a short thread

* fix(ui): clamp oversized aggregated tool output in catalog transcripts

* fix(ui): stop catalog auto-pagination when an older read makes no progress

* fix(ui): continue catalog paging through advancing empty pages; exhaust only on a stalled cursor

* fix(ui): detect catalog cursor cycles to bound auto-pagination
2026-07-12 10:52:00 +01:00
Peter Steinberger
a8b104c4e3 feat(mac): swap dashboard titlebar buttons with sidebar state (#105175)
* feat(mac): swap dashboard titlebar buttons with sidebar state

The Control UI reports sidebar collapsed/width over a new openclawNav
WKScriptMessage; the titlebar accessory shows toggle+back/forward
right-aligned to the sidebar edge while expanded, and
toggle+search+new-session while collapsed. Search opens the command
palette and + opens the new-session surface via openclaw:native-*
events. Older gateway bundles that never report keep the shipped
toggle/back/forward layout.

Refs #105129

* docs: describe state-dependent mac titlebar buttons
2026-07-12 10:13:36 +01:00
Vincent Koc
004b7b69c7 fix(ui): align E2E with current interaction contracts (#105206) 2026-07-12 17:01:45 +08:00
Peter Steinberger
17a533ce26 improve(ui): redesign the Automations tab with stats, a table list, and a full-page detail view (#105174)
* feat(ui): redesign Automations tab with stats, table list, and detail tabs

* docs(web): describe redesigned Automations page layout

* fix(ui): global failing-count stat via filtered cron.list and unclipped row menus

* fix(ui): refresh failing-count stat after cron job mutations

* chore(ui): sync locale bundles for automations redesign keys
2026-07-12 09:51:12 +01:00
Peter Steinberger
fecd1ca195 improve(ui): unify the New session draft with the start-screen layout (#105069)
The /new draft page now renders the same welcome block as the empty-chat
start screen, with the draft controls folded in launcher-style: hero on
top, a quiet borderless target row (agent, node, folder, worktree)
directly above the mid-screen composer, and the recent chats below. The
page reuses renderWelcomeState via hint/composer slots so the surfaces
cannot drift apart; the shell treats /new as a chat-like route that owns
its scrolling, with the top inset doubling as the native titlebar drag
band. The welcome is content-sized on this route so a tall draft (open
folder browser, short window) stays scrollable from the top. Also
repairs the stale new-session e2e heading wait (the h1 was removed in

Closes #105068
2026-07-12 09:22:51 +01:00
Peter Steinberger
9cda1af020 fix(ui): open the start screen from the sidebar brand (#105046)
* fix(ui): restore sidebar start-screen navigation

* test(ui): align sidebar proof with automations
2026-07-12 09:09:27 +01:00
Peter Steinberger
6038480915 feat(ui): browse Gateway and node folders from one root (#105114)
* feat(ui): browse Gateway and node folders

* chore: keep changelog release-owned

* chore: refresh native i18n inventory

* refactor(macos): isolate node filesystem commands
2026-07-12 09:07:07 +01:00
Peter Steinberger
cfe95266af feat(ui): redesign cron page as sidebar-first Automations master-detail (#104251)
Rebuilds the Control UI cron page as a sidebar-first Automations master-detail workspace: a task list pane (All/Active/Paused tabs, search, filter popover, curated emoji suggestion cards, scheduler footer) beside a detail pane that edits the selected task inline (prompt, row-style Details/Frequency groups, collapsible Advanced, per-task run history) and shows all-task recent activity when nothing is selected. Create & run now kicks a new task immediately after creation. The modal editor and quick-create wizard are retired; the automation-ideas catalog from #104761 is ported into the new suggestions list. Nav item renamed to Automations and pinned by default; route (/cron) and cron.* RPC contracts unchanged.

Closes #104217

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-12 07:12:26 +01:00
Peter Steinberger
4eb1f5225c feat(ui): add standalone operator approval links (#103698)
* feat(gateway): standalone approval deep-link page

Squash-rebased #103698 segment onto the typed-actions tip on current main.
Adds the tokenless /approve/{id} standalone approval UI served by the
gateway control-UI router, gateway-store ephemeral login fix (selectGateway
only on changed URL), and approval-page i18n strings.

Drift reconciliation: union-merged i18n translation-memory caches and
regenerated locale metadata via control-ui-i18n sync (33 approvalPage keys
remain English fallbacks in minor locales, as on the original branch).

(cherry picked from commit c82f56011bfe9f0debb8ebe052f14590c187340d)
(cherry picked from commit 80f5636a8b67a3d6a5f330620541a39d4ef3fe6f)
(cherry picked from commit a3e300d337a92bf1b593a0bb52b7ec4549910a21)
(cherry picked from commit 860ad01f9658bba54cb3d59644e5e1a032c0bb3f)
(cherry picked from commit d8b697b28a847950a1797da07fc0ae4c24928492)
(cherry picked from commit 8a654e3271fd5721358812f961a7a7bb386d6726)
(cherry picked from commit 2f776d2e7bf910271fcbd9697597f6f5478b0f30)
(cherry picked from commit 14e64e6e4d763be830830801eeec1a6f17441688)
(cherry picked from commit 4df9ec828d0034fdc76540ff0fe341e599b0f281)
(cherry picked from commit e52968f4ab)
(cherry picked from commit 7214fc25013966f99ff4b2d506aa2f5f789e2113)
(cherry picked from commit c6259ff79787c759c136086e1a54c9ead8e89539)
(cherry picked from commit a58d9f271d27481615f0c94a828704c563d5354f)
(cherry picked from commit dcf1cb6d98)

* fix(ui): preserve approval page gateway auth

* fix(ui): keep approval disconnects fail closed

* style(ui): format approval disconnect copy
2026-07-11 19:16:23 -07:00
Peter Steinberger
2829fe107c improve(ui): retire the Overview page for a chat-first start screen (#104819)
* feat(ui): replace Overview page with Connection settings and sidebar attention chips

* feat(ui): open new-session drafts on the chat start screen hero

* refactor(ui): drop old overview-hints paths after rename

* chore(i18n): sync control-ui locale bundles for connection/palette/attention keys

* test(ui): expect attention slot above the sidebar update card

* chore(i18n): re-sync locale bundles after rebase onto main

* test(ui): stub sidebar-attention RPCs in app-sidebar unit tests

* test(ui): use a non-secret-shaped token fixture in connection view test

* refactor(ui): destructure gateway connection in connection settings draft

* refactor(ui): keep connection settings code out of secret-scanner shapes

* test(ui): expect Connection in the settings Connections group

* improve(ui): idle-refresh sidebar attention chips for always-visible windows

* chore(i18n): refresh raw-copy baseline after rebase

* docs(ui): note the unknown-route chat fallback covers retired paths
2026-07-11 18:11:14 -07:00
Peter Steinberger
9a04fb40ce feat(ui): replace composer run-status pill with a transcript working spark (#104768)
* feat(ui): redesign composer run-status indicator as chrome-free status text

* feat(ui): replace run-status text with transcript working spark

* fix(ui): keep working spark through reloads, dodge running tool rows, show mobile interrupted toast

* fix(ui): satisfy lint on tool-stream marker access
2026-07-11 18:08:43 -07:00
Erick Kinnee
43634f616b fix(control-ui): use canonical thinkingDefault key in Quick Config (#104523)
* fix(control-ui): use canonical thinkingDefault key in Quick Config

The Control UI Quick Config panel was reading and writing the
non-canonical key agents.defaults.thinkingLevel, which is rejected
by the gateway's strict Zod schema with INVALID_REQUEST errors.

Fix: read from and write to agents.defaults.thinkingDefault instead.
The schema already defines this key and the runtime already reads it
at cfg.agents?.defaults?.thinkingDefault, so this is purely a UI path
correction with zero runtime changes.

The fast-mode control is left unchanged pending a maintainer decision
on its intended scope (per-agent, per-model, or new global default).

Refs #104501

* test(control-ui): prove quick thinking persistence

* docs(changelog): note Quick Config thinking fix

* chore: keep changelog release-owned

---------

Co-authored-by: Erick Kinnee <erick@ekinnee.dev>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-11 17:40:11 -07:00
Peter Steinberger
3255b3218a feat: unify external sessions with native catalog pagination (#104717)
* feat(gateway): add generic sessions.catalog surface with plugin SDK registration seam

* feat(agents): support one-shot forked CLI session resume with successor rebinding

* feat(anthropic): adopt local Claude CLI sessions into native chats via catalog continue

* feat(codex): register the session catalog provider independently of supervision

* refactor(ui): delete the retired custom Claude/Codex session tab views

* feat(ui): render external session catalogs as native sidebar sessions and chat panes

* docs: describe the unified native session catalog

* fix: harden forked CLI resume and catalog transcript mapping after review

* fix: satisfy strict typecheck for catalog source guard and imported message cast

* chore(i18n): regenerate session catalog locales

* fix(codex): simplify session source guard type

* fix(ui): paginate sidebar session catalogs

* chore(i18n): refresh catalog metadata after main merge

* fix(ui): harden session catalog pagination refresh

* test(agents): use sqlite session accessor in fork tests

* fix(ci): refresh session catalog generated surfaces

* fix(ui): align session catalog locales

* fix: address session catalog review findings

* fix(sessions): roll back failed plugin catalog adoption

* test(sessions): preserve CLI binding literals

* fix(ui): restore native session pagination label

* docs: note external session catalogs

* Revert "docs: note external session catalogs"

This reverts commit cfb503f160.
2026-07-11 17:26:26 -07:00
Vyctor H. Brzezowski
ff6dc43b8b feat(ui): paginate sidebar sessions (#104617)
* feat(ui): paginate sidebar sessions

* fix(ui): collapse sidebar session pages

* fix(ui): space sidebar pagination from footer

* fix(ui): keep required sidebar sessions visible

* fix(ui): reuse translated sidebar actions

* fix(ui): hide ineffective sidebar collapse

* fix(ui): advance sidebar pagination past required rows
2026-07-11 20:35:10 -03:00
Vyctor H. Brzezowski
2833eeece1 fix(ui): overlay chat scroll-to-bottom button (#104744) 2026-07-11 19:36:49 -03:00
Peter Steinberger
da257661f3 fix(ui): hide web sidebar toggles when the macOS titlebar hosts the toggle (#104694) 2026-07-11 13:46:15 -07:00
Peter Steinberger
49ff54e63a refactor(ui): unify chat icon buttons on one borderless design and align top chrome rows (#104574)
* refactor(ui): unify chat icon buttons on the compact boxed design

* refactor(ui): keep chat icon buttons borderless and align top chrome rows
2026-07-11 10:38:51 -07:00
Peter Steinberger
a5aa7bc670 fix(ui): contain the native session sidebar and truncate its rows (#104587)
The Codex/Claude sidebar sections leaked long titles across the row
timestamps and past the sidebar edge because the row body was never a
flex container, so the title span stayed inline and ellipsis rules did
not apply. The sections also rendered every loaded session (Codex swept
up to 100 catalog pages per host every 30s) with no height cap, growing
past the sidebar shell and painting over the footer.

Rows now reuse the regular session-row __text anatomy so titles
ellipsize, the sidebar renders only the newest 10 sessions per host
with a derived truncation note (the full catalog stays on the sessions
page), each section shrinks and scrolls inside the sidebar body, and
the shell body clips as a final guard. The sidebar full-catalog
hydration loop and the one-off __body class are deleted.

Formatting proof: oxfmt --check clean on changed files via Testbox
tbx_01kx92cwpr1x9ccp2fgn441y8h (local hook skipped: no node_modules).

Fixes #104584
2026-07-11 10:33:32 -07:00
Peter Steinberger
c3b426f280 feat: add Claude session fleet (#104528)
* feat: add Claude session fleet

* chore: leave release notes to release automation

* chore: refresh generated catalogs

* fix: satisfy session catalog lint gates
2026-07-11 08:22:59 -07:00
Peter Steinberger
05aecc1d6f feat: show Codex transcripts in the sidebar (#104437)
* feat: show Codex transcripts in sidebar

* fix: clear Codex sidebar on Gateway switch

* chore: leave release notes to release workflow

* chore: refresh native i18n inventory

* fix: satisfy macOS Codex node lint

* fix: refresh native localization inventory

* docs: refresh documentation map

* chore: refresh UI locale metadata
2026-07-11 05:39:29 -07:00
Peter Steinberger
9523a52871 fix(ui): stop sidebar session sections from painting over each other in short windows (#104447) 2026-07-11 04:57:15 -07:00
Peter Steinberger
4fc147105b fix(ui): delay scrolling truncated session titles (#104392)
* fix(ui): delay session title hover scroll

* chore: keep release notes out of PR
2026-07-11 03:36:49 -07:00
Peter Steinberger
0af8467137 feat(workspaces): add agent-composable Workspaces (#104139)
* feat(dashboard): modular dashboard — workspace store, Workspaces tab, sandboxed custom widgets

Squashes openclaw/openclaw#101094 + #101097 + #101098 onto current main and
applies the maintainer review fixes to the backend control plane.

Co-authored-by: 100yenadmin <239388517+100yenadmin@users.noreply.github.com>

* fix(dashboard): UI review fixes — grid, error boundary, embed sandbox, locale

* fix(dashboard): make the CLI and agent broadcasts actually reachable

Three defects only a live run surfaces, all invisible to the unit suites:

- The plugin claimed the CLI command name `dashboard`, which core already owns
  (it opens the Control UI). A plugin CLI group that overlaps a core command is
  dropped at registration behind a `logger.debug`, so the entire CLI face was
  unreachable while `cli.test.ts` kept passing against its own Commander
  program. Renamed to `openclaw workspaces`, matching the tab it drives.

- The manifest never declared `activation.onCommands`, so the CLI root resolved
  to no owning plugin even once the name was free.

- `dashboard.widget.approve` needs `operator.approvals`; the CLI asked for
  `operator.write` on every call. It now requests the approvals scope only for
  the approve call, matching `operator-approvals-client.ts`.

Also: agent tools resolved their broadcast from the plugin runtime's
gateway-request scope, an AsyncLocalStorage set only around gateway RPCs and
plugin HTTP routes. An agent turn started from a channel, cron, or heartbeat
therefore wrote the document without emitting `plugin.dashboard.changed`, so an
open Control UI never saw the edit — the feature's headline promise. The gateway
broadcast is server-lifetime, so the plugin now remembers it in a single slot and
agent tools fall back to it.

* docs(web): document dashboard workspaces, provenance, and the custom-widget sandbox

* fix(dashboard): agent-tool ergonomics + close two approval-boundary gaps

From a source-blind agent driving the dashboard_* tools with nothing but their
schemas, and from a Codex review of the hardening delta.

- dashboard_widget_update could never succeed. It passed its whole parameter
  record to the patch reader, whose allowlist rejects the very `tab`/`id` keys
  the tool's own schema marks required, so every call died on
  "unexpected param: tab". Its test only ran Value.Check against the schema and
  never executed the tool.
- dashboard_data_read surfaced an `rpc` binding as a thrown error, though its
  description promised `binding_client_resolved`. It now returns that as a
  result the model can act on.
- Valid widget kinds and the rpc allowlist were undiscoverable: a model saw only
  "builtin:<name> or custom:<name>" and "Allowlisted gateway read method", then
  brute-forced ~40 calls against errors that named no alternatives. Both schemas
  and both validator errors now enumerate them, and the kind description says
  what each builtin renders and which binding id it reads. widget_move documents
  that grid and toTab are exclusive; widget_scaffold says an operator must
  approve, because no agent tool can.
- workspace.replace could mint a pending registry entry for a name that was
  never scaffolded. An operator could then approve a widget whose code did not
  exist yet, and the agent could write it afterwards. Registry entries now come
  from dashboard_widget_scaffold and nowhere else, and approve refuses a name
  with no manifest on disk.
- dashboard.widget.approve answered with the whole workspace document, so a
  connection holding only operator.approvals could read it through the approvals
  door. It now returns the registry entry it changed.

* fix(dashboard): approval pins the code it approves

Codex review found the scaffold-before-approval gate still nameable rather than
binding: approve only proved that widget.json parsed, and the Control UI loaded a
hardcoded index.html rather than the manifest's entrypoint. An agent could
scaffold a widget, win approval on an innocuous or absent entrypoint, then write
the real payload afterwards — code appearing after the human said yes.

Approval now hashes every servable file in the widget directory and stores the
digests on the registry entry, refusing a manifest whose declared entrypoint is
missing. The asset route re-hashes each file it reads and 404s anything that does
not match, so a file edited or added after approval never reaches a browser. The
Control UI loads the manifest's entrypoint, which is the file that was hashed.

The content-type allowlist moves to manifest.ts so the set of files approval
hashes and the set the route can serve cannot drift apart.

Proof, against a running gateway: scaffold -> 404, approve -> 200, rewrite
index.html -> 404, add late.js -> 404.

* fix(dashboard): parse the approved manifest from the bytes that were hashed

Codex found a TOCTOU in the approval path: it loaded and validated widget.json,
then walked the directory again to compute the digests. An agent could swap
widget.json between the two reads, so the operator validated one entrypoint while
the digest froze — and the Control UI later mounted — a different one.

snapshotApprovedWidget now reads the widget directory once: it hashes every
servable file, parses the manifest out of the same widget.json bytes it hashed,
and requires the declared entrypoint to be among them.

Proof, against a running gateway: approve -> index.html 200; rewrite widget.json
to point at evil.html and drop evil.html in -> both 404.

* fix(dashboard): cap approval asset reads; bound the grid fallback search

Two findings from the fourth Codex pass.

Approval hashes agent-authored files that are untrusted until it runs, and read
each one into memory with no size check — dropping one huge .png into a scaffold
directory would stall or OOM the gateway during approve. Sizes are now checked
before the read, with a 2 MB per-file and 8 MB total cap.

nearestFreeSlot searched one band below the lowest occupied row, so a crowded
layout near the bottom could return y=500 as the closest free slot: a placement
the store rejects, which the UI applies optimistically and then snaps back. The
search now stops at the last row a widget of that height can legally occupy.

* fix(dashboard): refuse oversized widget assets before reading them

Approved widget files stay writable and the asset route is unauthenticated, so
swapping an approved small file for a very large one made every GET buffer the
whole file before the digest check rejected it. The route now refuses anything
past the same per-file cap approval enforces, on the stat it already performs.

* fix(dashboard): enforce widget approval boundaries

* docs(changelog): note modular dashboard workspaces

* fix(dashboard): enforce static custom-widget data boundary

* fix(dashboard): satisfy UI lint

* test(dashboard): avoid legacy proto access

* feat(dashboard): make plugin opt-in

* docs(dashboard): refresh workspaces map

* refactor(workspaces): standardize plugin naming

* fix(workspaces): make widget prompt sends idempotent

* docs(workspaces): fix internal path references

* test(workspaces): make prompt assertion lint-safe

* test(workspaces): type prompt request mock

* fix(workspaces): harden approval and binding boundaries

* test(workspaces): complete stale binding client mock

* fix(workspaces): harden widget file boundaries

* fix(workspaces): scope custom widget capabilities

* fix(workspaces): align approval provenance

* fix(workspaces): close branch contract gaps

* test(workspaces): complete builtin context fixtures

* fix(workspaces): aggregate overview usage

* chore(workspaces): defer release note

* chore(workspaces): refresh i18n metadata

---------

Co-authored-by: 100yenadmin <239388517+100yenadmin@users.noreply.github.com>
2026-07-11 03:30:23 -07:00
Peter Steinberger
adb05e72dc improve(control-ui): move the split-view opener into the top-right toggle cluster (#104341)
* improve(control-ui): move split-view opener into the top-right floating toggle cluster

* test(control-ui): anchor split-view opener e2e assertions to the floating toggle cluster
2026-07-11 02:18:58 -07:00
Peter Steinberger
7bf80dc2c6 chore(tooling): enforce formatting and refresh TypeScript checks (#104239)
* chore(tooling): enforce current formatter and refresh checks

* chore(tooling): keep release changelog formatter-owned

* chore(tooling): retain compatible Node type surface

* ci: enforce formatting for docs-only changes

* ci: isolate docs formatter check

* chore(tooling): apply updated lint and format rules

* chore(tooling): satisfy updated switch lint

* style(ui): apply Linux formatter layout

* test(doctor): match quiet local audio contribution

* test(doctor): assert quiet output only

* test(doctor): follow restored information contract
2026-07-11 01:09:51 -07:00
Peter Steinberger
81ce206ee8 improve(control-ui): move dev branch badge to its own footer strip (#104300)
The sidebar footer icon row got crowded with the inline branch label.
The dev-checkout branch now renders on a slim tinted strip above the
icon bar with a git-branch icon, keeping the full name readable and
the footer controls uncluttered.
2026-07-11 01:05:15 -07:00
Peter Steinberger
ebc848deec feat: sidebar update card (web + macOS) with app-first mac update flow and Sparkle beta track (#104171)
* feat: sidebar update card (web + macOS) with app-first mac update flow and Sparkle beta track

Squashed from claude/update-notification-display-c6cfb9 after semantic merge
with #104178 (channel-aware CLI installs). See PR #104171 body for details.

* chore(i18n): resync generated inventories after rebase

* chore(i18n): resync locale metadata after rebase
2026-07-11 00:34:10 -07:00
Peter Steinberger
7da12cbbe5 feat(ui): sweep a text wave across the active tool row while it runs (#104266) 2026-07-11 00:28:33 -07:00
Peter Steinberger
c16bd0df8d feat(control-ui): show non-main gateway checkout branch in sidebar footer (#104262)
Source-checkout (non-release) gateways now report their git branch in the
Control UI bootstrap config; the sidebar footer renders it in red next to
the connection dot. Package installs, main/master, and detached HEAD never
show it.
2026-07-11 00:25:43 -07:00
Peter Steinberger
f94a7dc183 feat(codex): supervise native Codex sessions (#104045)
* feat(codex): add native session supervision

* fix(codex): harden supervision integration

* fix(codex): preserve locked harness ownership

* fix(codex): fence native session archive

* fix(codex): revalidate archive binding ownership

* feat(codex): integrate supervision runtime

* feat(sessions): preserve harness-owned execution

* feat(sessions): persist harness ownership invariants

* feat(gateway): enforce harness-owned sessions

* feat(setup): enable detected Codex supervision

* feat(mac): expose supervised Codex sessions

* feat(ui): make Codex sessions actionable

* docs(codex): document session supervision

* test(codex): cover integration ownership

* chore(i18n): refresh supervision inventories

* fix(setup): finalize Codex activation atomically

* test(codex): narrow binding store update

* fix(sessions): preserve legacy model locks

* test(macos): serialize Codex catalog fixtures

* fix(sessions): preserve legacy lock admission

* chore(i18n): reconcile supervision metadata

* test(sessions): mark legacy lock fixture

* fix(macos): drain final Codex catalog frame

* docs: leave supervision note to release

* style(macos): satisfy Codex catalog type length

* chore: record session accessor seam owners

* fix(macos): honor configured Codex supervision

* fix(codex): preserve harness-owned model locks

* fix(codex): satisfy supervision lint gates

* chore(i18n): refresh native supervision inventory

* fix(codex): align supervision validation contracts

* fix(codex): close supervision boundary gaps

* fix(codex): preserve supervision activation contracts

* fix(codex): dispose standalone supervision runtime

* fix(codex): pin supervised source connection

* fix(plugins): bind delegated runs to exact session target

* fix(codex): scope supervised sessions to configured agents

* fix(codex): fingerprint effective supervision home

* fix(codex): normalize supervision plugin policy

* fix(codex): keep supervised bindings stable across upgrades

* fix(codex): guard all supervised binding connections

* fix(codex): preserve catalog filters and pending CAS identity

* fix(codex): preserve supervision identity for diagnostics

* fix(codex): bind uncertain commits to supervision connection

* fix(codex): satisfy supervision type boundaries

* fix(macos): reconcile current main validation

* fix(codex): handle absent runtime config in supervision

* fix(doctor): own local audio acceleration check

* fix(codex): satisfy integration lint gates

* fix(codex): satisfy lifecycle safety guards
2026-07-11 00:12:08 -07:00
Peter Steinberger
ae2c6117d3 feat(ui): full-page New session screen with gateway folder browser (#104238)
* feat(gateway): add admin-only fs.listDir host directory listing

* feat(ui): replace new-session dialog with full-page /new screen and folder browser

* fix(ui): drop unnecessary template literal in new-session page

* refactor(ui): rename request token locals for review-bundle hygiene

* fix(ui): preserve typed draft on agent hydration and clear stale folder listings

* fix(ui): gate new-session submit on agent hydration and keep live folder edits

* test(ui): use exact textbox selector in new-session e2e

* test(ui): deep-link new-session e2e so agents.list override supplies workspace

* chore(i18n): translate new-session strings and refresh native inventory

* chore(i18n): reconcile locale metadata after rebase
2026-07-11 00:10:48 -07:00
Peter Steinberger
1d72c0f423 feat(ui): session diff panel showing a session checkout's changes in chat (#104184)
Adds a git-backed session diff panel to the Control UI, complementing the existing PR status chips.

New sessions.diff gateway method (operator.read): resolves the session checkout and returns structured per-file diffs (status, renames, +/- counts, capped unified patch) of branch + uncommitted + untracked work against the default-branch merge base. Hardened against git textconv execution and hardlinked out-of-tree content leaks; handles repos before their first commit via the empty-tree base.

Control UI renders a "Changes" panel in the chat detail sidebar with collapsible per-file diffs, hunk-gap markers, stat chips, and untracked/binary badges, gated on gateway method advertisement. Schemas additive (Swift models regenerated), 20 locales translated.

Closes #104182
2026-07-10 23:57:55 -07:00
Peter Steinberger
0074005682 feat(ui): add Model Providers settings page with auth, quota, and cost per provider (#104061) 2026-07-10 19:31:41 -07:00
Peter Steinberger
0ca8237905 fix(ui): keep raw ids out of sidebar session rows and stop WebKit section overlap (#104062) 2026-07-10 19:14:51 -07:00
Peter Steinberger
62d10f7b84 improve(ui): drag sidebar group headers to reorder custom groups (#103997)
* improve(ui): drag sidebar group headers to reorder custom groups

* test(ui): repair sidebar group e2e for the gateway-owned catalog
2026-07-11 01:39:47 +01:00
Peter Steinberger
6d39ec5152 feat(ui): collapse session PR chips and add a CI monitoring popover (#103853)
* feat(ui): collapse session PR chips and add a CI monitoring popover

* chore(i18n): translate session PR chip strings

* docs(gateway): note Control UI contract shapes ship in lockstep

* chore(i18n): regenerate locale bundles after rebase
2026-07-11 00:37:06 +01:00