Commit Graph

3438 Commits

Author SHA1 Message Date
Peter Steinberger
242093fb00 fix(ui): dark theme AA contrast for coral fills — deepen primary/destructive, add widget accent-fill token (#110957) 2026-07-18 21:56:24 +01:00
Peter Steinberger
42bacaa112 feat(ui): call chat sessions threads and quiet the sidebar sections (#110933)
* feat(ui): call chat sessions threads and quiet the sidebar sections

Thread naming on every creation surface (new-thread page, draft row,
+ tooltips, untitled-thread fallback, New Chat guard toasts). The draft
placeholder now renders as the first item inside the Threads section and
genuinely expands a collapsed section so the header toggle stays honest.
Empty sidebar sections no longer render (Coding keeps its CLI-catalog
exception); expanded section headers reveal their chevron only on
hover/focus while collapsed headers keep chevron + count. The new-thread
button moves from the macOS titlebar strip into the sidebar brand row
next to the agent picker (bigger, offline-aware); the titlebar + renders
only while the rail is collapsed. Mobile drawer shows the new + as well.

* fix(ui): keep empty custom groups and the mid-drag Threads drop target

Empty-section hiding narrows to the Threads zone at rest: user-created
categories stay visible when empty (New group… creation and drag-into-group
flows depend on them), and an empty Threads section reappears while a
session drag is in flight so drag-to-unpin keeps its drop target.

* test(ui): drag-to-unpin targets the sessions surface

The empty Threads section only materializes mid-drag, so Playwright cannot
pre-resolve it as a drop target; the sessions container's drop handler owns
the unpin and sends {pinned:false} without a category reset.
2026-07-18 21:42:52 +01:00
Peter Steinberger
81362bf643 feat(apps,ui): question surface parity and composer takeover (#110681)
* feat(apple): question parity — persistent summaries, skip, reconnect fallback, macOS keyboard

* feat(android): question parity — persistent summaries, skip, reconnect fallback

* feat(ui): question panel replaces composer while expanded

* fix(apps): regenerate question parity contracts

* fix(apps): preserve question reconciliation state

* fix(apps): keep question terminal state monotonic

* test(android): satisfy question test formatting

* fix(security): restore skill audit file reads

* fix(apps): harden question parity edge cases

* fix(apps): preserve expired question summaries

* fix(apps): keep question recovery retries current

* fix(apps): retry stale question recovery snapshots

* fix(android): reset stale question retry budgets

* docs(tools): clarify question composer takeover

* fix(apps): satisfy question recovery release gates

* fix(apps): preserve unknown question outcomes

* fix(apps): harden question action state

* fix(apps): keep unavailable questions terminal

* fix(apps): finalize local question outcomes

* fix(apps): preserve question card API

* fix(apps): reconcile external question answers

* fix(apps): reset question backoff budget

* chore(apps): refresh native i18n inventory

* fix(android): distinguish question skip progress

* fix(android): reconcile locally expired questions

* fix(apps): keep question recovery state fresh

* docs: note question surface parity

* fix(ui): reconcile IME draft before question takeover

* docs: leave question parity notes to release workflow
2026-07-18 21:42:15 +01:00
Peter Steinberger
ef7f4f2a61 feat(ui): Labs settings page for experimental feature toggles (#110359)
* feat(ui): add Labs settings page

* chore(ui): drop changelog entry — release generation owns CHANGELOG

* fix(ui): drop lint suppression, sync Apple i18n catalogs for Labs keys

* ci: retrigger CI on current head

* docs(ui): clarify swarm labs-entry gating comment
2026-07-18 21:08:52 +01:00
Peter Steinberger
1cacb12c4d feat(canvas): give show_widget a design system — theme tokens, base styles, live host theme bridge (#110832) 2026-07-18 21:05:16 +01:00
WhatsSkiLL
1626a1696c fix(ui): clean up timed-out channel wizard starts (#110146)
* fix(ui): clean up timed-out channel wizard starts

* refactor(ui): centralize stale wizard cleanup

Co-authored-by: WhatsSkiLL <284122573+IWhatsskill@users.noreply.github.com>

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 20:59:44 +01:00
Peter Steinberger
09fa5818e8 refactor(ui): render Ask OpenClaw chat through the shared chat presentation layer (#110934) 2026-07-18 20:52:44 +01:00
WhatsSkiLL
2632969aae fix(ui): use clipboard fallback in setup wizards (#110139)
* fix(ui): use clipboard fallback in setup wizards

* test(ui): verify wizard clipboard payloads

Co-authored-by: WhatsSkiLL <284122573+IWhatsskill@users.noreply.github.com>

---------

Co-authored-by: Codex <codex@openai.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: WhatsSkiLL <284122573+IWhatsskill@users.noreply.github.com>
2026-07-18 20:36:30 +01:00
Peter Steinberger
36cba351e5 feat(ui): distinct Apps icon and pairing shortcut on the Apps page (#110909) 2026-07-18 20:17:25 +01:00
Peter Steinberger
41fdcac4d7 fix(ui): drop the Subagent prefix from named sidebar threads (#110891) 2026-07-18 20:17:20 +01:00
WhatsSkiLL
b526af1a7e fix(ui): lock channel wizard controls while busy (#110163)
Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
2026-07-18 20:09:31 +01:00
Peter Steinberger
5fdb0cd24e feat(chat): switch between session transcript branches from the chat header (#110857)
* feat(chat): switch between session transcript branches from the chat header

* fix(chat): type fixes and protocol regen for branch switcher CI
2026-07-18 20:06:36 +01:00
Peter Steinberger
64019bc0c2 refactor(ui): split lobster-pet into look/plans/element modules (#110816)
* refactor(ui): split lobster-pet into look/plans/element modules

Move existing behavior along appearance and seeded visit-planning ownership seams without changing runtime behavior.

Extract only the bounded logo stand-in, WebAudio chirp, and pure render-template helpers while keeping the state machine in the element. Remove the grandfathered max-lines suppression and baseline entry.

* style(ui): format lobster-pet split modules

* fix(ui): keep lobster split internals unexported, refresh i18n raw-copy baseline

knip flags the split's newly exported internals (strangerLookFor,
renderCrabSvg, lobsterPetSpriteStyle, LobsterPasserKind) — they have no
external consumers; the html-text raw-copy baseline is file-keyed, so the
sprite z/Z markup moving into lobster-pet-look.ts needs a regen.

* fix(ui): satisfy lint for the lobster-pet split (param reassign, max-lines)

* fix(ui): keep moved act-profile internals unexported
2026-07-18 20:02:24 +01:00
Peter Steinberger
9a9f5919e5 fix(ui): defer remembered camera auto-enable until talk reaches listening (#110874) 2026-07-18 20:00:40 +01:00
Peter Steinberger
9f5958e75d fix(ui): collapse doubled sidebar footer divider and enlarge settings gear (#110892) 2026-07-18 19:57:23 +01:00
Peter Steinberger
9e0780c5a0 fix(ui): styling sweep — compact number steppers, one accent for check controls, composite-page cleanups (#110845) 2026-07-18 18:34:19 +01:00
Peter Steinberger
f01941559b feat(ui): camera-off glyph and remembered camera state for talk calls (#110817)
* feat(ui): camera-off glyph and remembered camera state for talk calls

* test(ui): rename shadowed lit html binding in composer icon mock

* refactor(ui): split tool icons out of icons.ts to stay under max-lines
2026-07-18 18:25:19 +01:00
Peter Steinberger
a54a292d62 test(ui): fix Node 25+ localStorage crashes in jsdom suites; document PR-open CI drops (#110812)
* test(ui): shim dead Node 25+ WebStorage localStorage in jsdom test setup

Node 25+ ships a default-on global localStorage that is dead without
--localstorage-file (undefined on 26.5; throwing or inert elsewhere). It
shadows jsdom's Storage during vitest global population, so storage-touching
UI tests crash on newer local Node while Linux CI (Node 24) passes — six
files failed locally on Node 26.5. The shared setup now capability-probes
(round-trip, throw-safe), prefers jsdom's own window Storage when only the
global alias is dead, and otherwise installs one in-memory Storage on both
window and globalThis.

Also documents the PR-open CI drop pattern in AGENTS.md: fresh PRs race
GitHub's merge-ref computation and the open-event CI run can drop or die
as startup_failure/BuildFailed (not rerunnable); verify attach and
close/reopen to re-fire.

* fix(test): drop unnecessary String() conversions in localStorage shim
2026-07-18 18:19:44 +01:00
Peter Steinberger
f1a8c04aea fix(cron): clean up recurring jobs converted to one-shot (#110431)
* fix(cron): default updated one-shots to cleanup

* test(cron): type schedule transition fixtures

* chore: leave cron notes to release generation
2026-07-18 18:16:40 +01:00
Peter Steinberger
e9fe7c748b feat(ui): session dashboard shell — board face, chat dock, reset guard (#110728)
* feat(ui): add session dashboard shell

* fix(ui): defer confirmed reset during active runs

* fix(ui): align dashboard shell with shared controls

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-18 10:01:47 -07:00
Jason (Json)
f328250fa9 fix(ui): reject widget command prompts (#110808) 2026-07-18 10:56:41 -06:00
Peter Steinberger
d022b1f560 improve(ui): adopt inset secret-input reveal in login gate and config form (#110810) 2026-07-18 17:43:11 +01:00
Peter Steinberger
9b97ee06ad improve(ui): theme Import card uses the import-tray icon (#110807) 2026-07-18 17:41:56 +01:00
Peter Steinberger
8a66aa76dd feat(ui): session board grid engine and board view (#110644)
* feat(ui): add session board grid view

* fix(ui): use shared board controls

* fix(ui): keep board cell registration type-safe

* chore(ui): drop unused board cell class export
2026-07-18 09:40:41 -07:00
Peter Steinberger
81df196b8d refactor(ui): unify transcript inline UI on one widget card (#110740)
* refactor(ui): unify transcript widget cards

* chore(ui): keep widget-card internals unexported
2026-07-18 09:40:08 -07:00
Peter Steinberger
fd7e444c24 improve(ui): syntax-highlight JSON dumps on the debug page and config issues callout (#110806) 2026-07-18 17:32:28 +01:00
Peter Steinberger
33f9c47e3c fix(ui): label the local-only chat message delete honestly as hide (#110801) 2026-07-18 17:27:51 +01:00
Peter Steinberger
ffb7c98312 fix(ui): drop resting relative ages from agent chip subtitle and footer build chip (#110800) 2026-07-18 17:27:18 +01:00
Peter Steinberger
ef04f351ea fix(ui): keep Web Awesome available-height bound in workboard listbox caps (#110788) 2026-07-18 17:19:39 +01:00
Peter Steinberger
88e5af7097 feat(ui): interleaved sidebar zone with custom session icons and drag ordering (#110682)
* feat(ui): custom session icons with agent-drawable SVG and nav-parity pinned rows

* wip: slice-2 interleaved sidebar zone (pre-review)

* fix(ui): trim icon exports, bypass protocol barrel in startup bundle, regen Swift protocol client

* fix(ui): preserve unknown-agent zone entries on writes, prune entries on any unpin

* fix(ui): reset keeps unloaded session slots; enforce SVG byte cap on canonical form

* fix(ui): archiving a pinned session retires its sidebar zone slot

* fix(ui): persist drag-pinned zone slot only after the pin patch lands

* fix(ui): recompute drop insertion against freshest zone order on pin ack

* fix(ui): consume self-drop events before the zone bailout

* docs(ui): note the non-sidebar unpin pruning contract on pruneSidebarSessionEntry

* refactor(ui): extract pure session-tree projection; drop unused zone type export
2026-07-18 17:13:09 +01:00
Peter Steinberger
a115af2774 feat(ui): add reactive OpenClaw health nudges (#110708)
* feat(ui): add reactive custodian health nudges

* fix(ui): distinguish stopped channels from startup failures

* test(ui): update custodian route gateway fixture

* fix(ui): preserve current channel health failures

* fix(ui): ignore recovered channel errors
2026-07-18 15:44:29 +01:00
Peter Steinberger
0acece4591 feat(chat): rewind and fork a session from a message bubble (#110660)
* feat(chat): rewind and fork a session from a message bubble

* docs(web): document chat rewind and fork bubble actions

* fix(chat): lint cleanups, protocol regen, and test splits for rewind/fork CI

* fix(ui): fit chat rewind disabled styles inside the startup CSS budget
2026-07-18 14:46:34 +01:00
Shakker
e4fd904f8a test: cover hidden catalog polling across reconnects (#110705) 2026-07-18 14:29:38 +01:00
Shakker
b5d9573dca fix: pause hidden session catalog polling 2026-07-18 14:15:51 +01:00
Peter Steinberger
42133d0c3c feat(mac): show native notification permission in dashboard Notifications settings (#110646)
* feat(mac): show native notification permission in dashboard Notifications settings

The Mac app's embedded Control UI showed the web-push section as
Unsupported/Not subscribed even though the app delivers notifications
natively. The dashboard now installs an openclawNotifications WebKit
bridge (status / request-permission / send-test) and the Notifications
settings page renders native permission state with Enable, Open System
Settings, and Send test actions when hosted in the Mac app. Browsers
keep the existing web-push UI. The notifications section renderer moved
out of the oversized config view module.

* fix(ui): break config view import cycle and satisfy lint/deadcode/i18n gates

Move the notifications section props to a leaf contract (no view.ts
type import), unexport the status-event constant, use bracket access
for the injected dunder global, default-case the status switch, and
refresh the native i18n inventory line offset.
2026-07-18 14:13:06 +01:00
Peter Steinberger
d3173f6f91 perf(ui): keep lazy-page CSS out of the Control UI entry stylesheet (#110687)
The entry stylesheet aggregated approval, config, config-quick, and
lobster-pet styles even though every consumer is a lazy route chunk or
lazily defined element, and two small UI landings tipped startup CSS to
exactly the 42.0 KiB budget, failing all QA Smoke profiles on main (run
29643357786). Move each stylesheet to its owning lazy module — pages
already own their CSS this way (chat, agents, cron) — and keep only the
shell's pre-hydration approval booting subset in the entry via the new
approval-boot.css. Startup CSS drops 42.0 -> 36.0 KiB gzip; tighten the
budget 42 -> 38 KiB to lock in the recovery, matching the startup-JS
precedent from #110528.
2026-07-18 13:26:21 +01:00
Peter Steinberger
74880cb56f feat(ui): manage MCP servers directly from Settings → MCP (#110654)
* feat(ui): manage MCP servers directly on the Settings MCP page

* refactor(ui): mcp config section owned by the MCP settings page only

* chore(ui): drop test-only McpServersCard export for knip
2026-07-18 12:54:05 +01:00
Peter Steinberger
39ddf710f0 feat(ui): session unarchive flows with undo toast (#110605)
* feat(ui): session unarchive flows with undo toast

Archiving from the web UI was silent and one-way. Adds a shared single-slot
toast with Undo (restores archive state, pin, and active selection), a sidebar
'View archived' entry into Settings -> Sessions, an Active|Archived segment
replacing the buried archived-only chip, an inline Restore button on archived
chats' disabled composer, and a guarded 'Delete all archived' bulk action that
fully re-enumerates archived sessions (paginated, aborts on any abnormal page)
and passes the protocol archivedOnly guard. No gateway/protocol changes.

* test(ui): adapt archive undo sidebar harness

* fix(ui): unexport ToastOptions and widen test mock casts for CI gates
2026-07-18 12:50:51 +01:00
Peter Steinberger
f98bcb7fa7 perf(ui): drop zod from the Control UI and lazy-load json5 with the config surfaces (#110623)
* perf(ui): drop zod and lazy-load json5 out of Control UI startup

zod's only UI consumer was the custom-theme shape layer, whose deep CSS
validators already re-check every token; replace the two shallow schemas
with a plain record reader and delete the zod jitless CSP shim + test.
Startup keeps one schema library total (typebox, protocol-owned, already
lazy via the approval page).

json5 now loads through a lazy runtime boundary: strict JSON.parse is the
fast path, the parser warms with the config editor and whenever a config
snapshot or raw draft actually needs JSON5 (comments, trailing commas).
The redaction sanitize path parses the authoritative raw once at snapshot
ingestion (async-safe) and submits against the carried parsed fact, so
secret-placeholder handling never races the lazy parser.

Startup JS: 321.8 -> 295.8 KiB gzip, 13 -> 12 requests; budgets ratchet
to 310 KiB / 18 requests.

* fix(ui): gate config submits on pending JSON5 original parse

A JSON5 config racing the first parser load could reach the sanitize step
with a null parsed original and pass redaction placeholders through.
setConfigRawOriginal now parses synchronously whenever the parser is warm
and tracks a pending promise otherwise; submit, auto-save, and teardown
flush paths defer to that promise (teardown keeps its synchronous prefix
when no parse is pending).

* fix(ui): keep teardown config flush synchronous and JSON5 diff cache non-sticky

Teardown flush must dispatch before unload destroys the context; the
gateway's restore-or-reject sentinel contract backs the rare unsanitized
window. Raw-diff parse failures no longer cache while the lazy JSON5
parser is still loading, so a transient cold-parser miss retries on the
next render instead of pinning an empty diff.

* fix(ui): harden lazy JSON5 boundary against double-submit and failed loads

Claim the config busy flag before awaiting a pending JSON5 original parse
so a second click cannot slip past the busy state (autosave overlap is
already serialized by the in-flight registry and drain discipline). A
rejected json5 chunk import now resets the loader for retry, the per-state
pending promise is never-rejecting and self-clearing, and fire-and-forget
warms swallow rejections.

* docs(ui): note autosave entry serialization at the JSON5 parse await

* fix(ui): fill raw pending-changes diff once the lazy JSON5 parser lands

First diff open could race the parser chunk and render an empty list with
nothing scheduling a retry; renderConfig now re-renders when the warm
completes, and the browser test warms the parser in setup to assert the
steady state the view module guarantees in prod.
2026-07-18 12:36:46 +01:00
Peter Steinberger
60cb6d78de perf(ui): lazy-load the lobster pet out of the Control UI startup graph (#110628)
* perf(ui): lazy-load the lobster pet out of the Control UI startup graph

Keep the lightweight lobster contract on the sidebar's static path while idle-loading the heavy pet implementation. Move the logo stand-in custom element into the pet module so both decorative elements upgrade together after the lazy import.

* style(ui): format lobster-pet lazy boundary

* fix(ui): clear the lobster-pet chunk cache on load failure

A rejected import stayed cached forever and surfaced as an unhandled
rejection; clearing it lets a later scheduling call retry.

* fix(ui): retry the lobster-pet chunk once connectivity returns
2026-07-18 12:26:25 +01:00
Peter Steinberger
00257c3093 feat(ui): theme cards preview their real color palettes (#110626) 2026-07-18 12:23:05 +01:00
Peter Steinberger
c989b8a519 fix(ui): settings language picker was oversized and unthemed (#110621)
* fix(ui): settings language picker matches the settings design language

* fix(ui): keep Web Awesome available-height bound in language listbox cap

* fix(ui): restore forced-colors focus outlines for the language picker
2026-07-18 12:16:30 +01:00
Peter Steinberger
3b2797f09b improve(ui): settings cleanup batch — universal config.changed emitter, synced chat prefs, dedupe and copy fixes (#110581)
* fix(gateway): emit config.changed from the reload committer for every accepted write

Agent config_set, CLI, and doctor writes reach the gateway through the file
watcher's reload path, which never broadcast config.changed - only direct RPC
writes did. Move the broadcast to a single onConfigCandidateCommitted hook in
the reload committer so all writers notify connected UIs, including
runtime-skipped commits (writer-intent echo suppression, reload mode off),
and delete the duplicate RPC-side broadcasts.

* feat(ui): sync chat follow-up and commentary prefs across devices

Add chatPersistCommentary and chatFollowUpMode to the ui.prefs sync surface
(schema, types, docs) with clearable null removal for the follow-up override.
Rewrite server-prefs around a descriptor table so a synced pref is one entry
instead of five hand-written code sites. Caption synced rows/sections
(chat prefs, theme, language) and refresh the stale Settings subtitle.

* refactor(ui): dedupe settings constants, drop dead composer branch, refresh copy and docs

Derive the Security tool-profile options from PROFILE_OPTIONS and General's
thinking levels from BASE_THINKING_LEVELS instead of parallel literals.
Remove the unused composer mode:"model" branch, the orphaned
.config-view-toggle CSS family, and stale quick-settings wording. Add static
settings-search entries for the Sessions and Managed Worktrees pages plus a
provenance-row test, and update docs/cli/openclaw.md to describe the current
system-agent config-write policy (denylist roots, route-backing plugin guard,
per-agent routing escalations).

* chore: refresh plugin SDK API baseline after rebase onto current main
2026-07-18 12:10:20 +01:00
Peter Steinberger
31314920ce improve(ui): plugins hub hierarchy, settings section spacing, and grid-aligned secret inputs (#110482)
* improve(ui): align settings section headers, dedupe plugin row status pills, clean hub tab strip

* improve(ui): hub tabs as page nav, one-row plugins toolbar, honest section spacing, inset secret-input reveal
2026-07-18 11:57:36 +01:00
Peter Steinberger
f57a8753da fix(ui): cap sidebar child sessions with show-more, drop Subagent prefix in tree (#110604)
* fix(ui): cap sidebar child sessions at four with show-more, drop Subagent prefix in tree

* test(ui): split child-session cap cases under the max-lines budget
2026-07-18 11:56:16 +01:00
Peter Steinberger
4a96c9da31 feat(ui): link Get the apps from the mobile pairing dialog (#110622) 2026-07-18 11:46:40 +01:00
Peter Steinberger
21c3438ded feat(ui): merge voice and video talk into one button with in-call camera toggle (#110576)
* feat(ui): merge voice and video talk into one button with in-call camera toggle

* fix(ui): avoid stale TS narrowing on talk status re-check in camera toggle
2026-07-18 11:19:34 +01:00
Peter Steinberger
cb785ed95b feat(ui): syntax-highlight the channel health snapshot on the channels settings page (#110613) 2026-07-18 11:19:08 +01:00
Peter Steinberger
8c95ec95ca fix(ui): show sidebar connection state only on sustained disconnect (#110567) 2026-07-18 11:02:38 +01:00
Peter Steinberger
a068d38b66 refactor(plugins)!: remove experimental workspaces plugin (#110416)
* refactor(plugins)!: remove experimental workspaces plugin

* fix(doctor): remove retired workspaces plugin state

* refactor(doctor): settle retired-workspaces cleanup before legacy-state detect

* chore(i18n): leave workflow-owned locale artifacts to the locale refresh

* ci: retrigger after GitHub scheduling outage
2026-07-18 10:56:37 +01:00