Commit Graph

3543 Commits

Author SHA1 Message Date
Peter Steinberger
b9fa1ffa27 feat(gateway): system change history RPC and Ask OpenClaw recent-changes panel (#111286)
* feat(gateway): system change history RPC and Ask OpenClaw recent-changes panel

* test(gateway): fix journal fixtures, split custodian page tests, refresh docs map

* chore: quiet lint on journal reader tests and custodian harness
2026-07-19 02:38:05 -07:00
Peter Steinberger
ba06fe1541 feat(ui): author avatar chips on user messages (incl. queued) (#111309)
* feat(ui): author avatar chips on user messages with gravatar and initials fallback

Renders a small author avatar on user-authored chat messages, including
queued/pending sends, so multi-user gateways show at a glance who wrote
which prompt. Resolution: profile avatar URL (when available) -> Gravatar
by SHA-256 email hash (d=404) -> deterministic initials with stable color.
Assistant/tool output stays unmarked, and messages without sender identity
render unchanged, keeping single-user gateways visually identical.

* fix(ui): clear avatar fallback state on image load; document gravatar tradeoff

* fix(ui): gate email-hash avatars behind a gateway proxy base URL

Without a same-origin proxy base the email tier is disabled outright, so
rendering a transcript can never disclose hashed sender emails or viewer
IPs to a third-party avatar host. The gateway-side proxy route (follow-up)
supplies the base and becomes the only avatar fetch path.

* fix(ui): restrict profile avatar URLs to same-origin relative paths

* fix(ui): validate profile avatar URLs with the URL parser, not string prefixes

Backslashes normalize to slashes and tabs/newlines are stripped by browser
URL parsing, so startsWith checks can be bypassed into cross-origin fetches.
Resolving against a probe origin and requiring the origin to survive is
parser-equivalent and closes the class.
2026-07-19 02:08:05 -07:00
Peter Steinberger
918f6615d0 feat(ui): Swarm progress widget — dot grid per swarm group (#110325) (#111297)
* feat(ui): Swarm progress widget — dot grid per swarm group (#110325)

* fix(ui): keep swarm renderer internals private
2026-07-19 01:19:56 -07:00
Peter Steinberger
430147fc89 feat(ui): approval UX overhaul — inline cards, fair queue, shortcuts, badges (#110989)
* feat(ui): overhaul approval experience

* fix(ui): guard approval shortcuts against key auto-repeat and keep scoped errors on enqueue

* fix(ui): arm approval shortcuts after focus settles and scope error clearing to the settled request

* fix(ui): approval hardening — modifier-chord shortcuts, pinned active card, badge fallback, quiet countdown

* fix(ui): scope approval errors per request

* style(ui): format approval queue test

* fix(ui): tolerate missing approval overlays

* perf(ui): lazy-load approval modal controls

* fix(ui): satisfy approval lazy-load guards

* style(ui): satisfy approval card lint
2026-07-19 01:18:09 -07:00
Peter Steinberger
3a5da4faa8 feat(ui): live agent activity subtitles on running sidebar sessions (#111221)
* feat(ui): live agent activity subtitles on running sidebar sessions

* refactor(ui): lazy-load narration controller off the startup chunk, unexport test-only symbols

* chore(ui): raise startup JS budget to 312 KiB for the lazy narration feature

* test(ui): restore real timers after narration controller cases
2026-07-19 01:08:06 -07:00
Peter Steinberger
0f95e66b7f feat(talk): add durable client voice sessions (#111216)
Live-append voice transcripts into the agent session and persist a per-agent SQLite call record across relay and client transcript paths.

Add run-scoped spoken confirmation for high-impact actions, mutation digests, bootstrap-context injection, talk.client.transcript and talk.client.close protocol methods, and Control UI adoption. This adds zero new configuration.

Co-authored-by: Clifton King <clifton@users.noreply.github.com>
2026-07-19 01:06:49 -07:00
Peter Steinberger
9d2f5d4dbb feat(ui): enable Swarm toggle in Labs (#110325) (#111267) 2026-07-19 00:27:06 -07:00
Peter Steinberger
9aa6e672a7 fix(custodian): show mode-appropriate guidance and defaults (#111263)
* fix(custodian): align option-card defaults

* test(custodian): preserve default confirm choice
2026-07-19 00:17:09 -07:00
Peter Steinberger
aae5b0f041 feat(ui): hold-to-record dictation on the composer mic button (#111114)
* feat(ui): add hold-to-record dictation

* chore: drop changelog edit (release generation owns CHANGELOG.md)

* fix(ui): preserve composer controls after rebase

* fix(ui): preserve dictation pointer capture

* fix(ui): finish dictation on cancellation

* docs(ui): note transcription-relay event envelope contract at the dictation parser

* test(ui): complete realtime-talk-input mock factory for shared-registry workers

* test(ui): isolate composer mocks across workers

* test(ui): isolate shared chat module mocks

* test(ui): type shared chat spies
2026-07-19 00:03:09 -07:00
Alix-007
aaacee8166 fix(ui): prevent stale sidebar attention refreshes (#111061) 2026-07-18 23:37:20 -07:00
Peter Steinberger
5e4a324f22 fix(ui): report WhatsApp logout no-ops (#105929)
* fix(ui): report WhatsApp logout no-ops

* test(ui): align WhatsApp logout E2E with channels hub
2026-07-18 23:22:22 -07:00
Alix-007
2320f338bf fix(ui): recover stalled Nostr profile requests (#111093)
* fix(ui): bound Nostr profile requests

* fix(ui): clarify Nostr timeout outcome

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 23:16:25 -07:00
Peter Steinberger
6eb569ed6e fix(ui): chat message copy and canvas buttons render as boxed buttons in light mode (#111230)
The copy-as-markdown and open-in-canvas actions under chat messages carried
the global .btn chrome; the light-theme .btn background override outranks the
chat footer's ghost-button reset, so both buttons rendered as large boxed
squares (44px touch targets made them worse on narrow viewports) while the
hide button next to them stayed a small ghost icon. Render them bare in chat
so the footer ghost rules own their look; the boxed variant remains for the
file preview and connect-command surfaces.
2026-07-18 22:58:48 -07:00
Peter Steinberger
932e8be06c feat(agents): canonical agent creation with Custodian hatch flow (#111052)
* refactor(agents): centralize agent creation

* feat(ui): add new agent hatch flow

* refactor(agents): keep creation paths lean

* fix(agents): hide internal creation types
2026-07-18 22:50:02 -07:00
Jason (Json)
2f7da3057c feat(mcp-apps): support bounded model context updates (#111212)
* feat(mcp-apps): support model context updates

* fix(mcp-apps): satisfy protocol and runtime guards
2026-07-18 23:08:35 -06:00
Peter Steinberger
721aee1f19 feat(gateway): attribute prompts to authenticated users (#111207) 2026-07-18 21:37:57 -07:00
Jason (Json)
060b30f23a fix(ui): ignore malformed tool stream entries (#111145)
Prevent malformed transient tool-stream entries from aborting Control UI chat reconciliation while preserving valid tool message order and rendering.
2026-07-18 22:21:11 -06:00
Peter Steinberger
c2a9579c59 fix(ui): composer small-width polish — single-line placeholder, matched talk split-button (#111150) 2026-07-18 20:06:52 -07:00
Jason (Json)
7d62a277ff fix(ui): teardown MCP Apps before unmount (#111124)
* fix(ui): teardown MCP Apps before unmount

* fix(ui): keep MCP teardown helpers internal
2026-07-18 20:25:46 -06:00
Peter Steinberger
62c5a8b888 fix(gateway): make scope errors machine-readable across clients (#111013)
* fix(gateway): consume structured scope errors

* docs(gateway): clarify tools error boundary

* refactor(gateway): unify node admin policy
2026-07-18 17:53:45 -07:00
Peter Steinberger
6c2973dee4 feat(ui): automatic session attention states in the sidebar (#111035)
* feat(ui): automatic session attention states in the sidebar (question, approval, failed run)

* test(ui): split attention presentation and read-marker cases under line budgets

* fix(ui): restore precise chat-pane test-support signatures
2026-07-18 17:43:59 -07:00
Peter Steinberger
dcffb3f66f fix(ui): restore Control UI E2E coverage (#111036)
* fix(ui): restore control ui e2e coverage

* test(ui): align e2e coverage with thread labels

* test(ui): wait for fake talk channel readiness

* chore: keep release note in PR body
2026-07-18 17:26:26 -07:00
Peter Steinberger
e3ae52b792 feat(ui): microphone picker on the composer talk button (#111043)
* feat(ui): add composer microphone picker

* fix(ui): single check indicator in mic picker, matching house radio-menu pattern

* fix(ui): keep System default focusable during mic discovery; update composer contract test for picker caret
2026-07-18 17:25:55 -07:00
Peter Steinberger
b550c2cf9a feat(ui): add realtime Talk camera controls (#111042) 2026-07-18 17:03:32 -07:00
Jason (Json)
7c070d6df6 feat: allow standalone MCP Apps to use bound tools and resources (#110515)
* Gateway: enable ticketed MCP App bridge

* Gateway: make MCP App operation switch exhaustive

* refactor(gateway): drop no-op MCP App route change

* fix(gateway): enforce standalone MCP App tool authority

* docs(gateway): clarify standalone MCP App ticket authority

* fix(gateway): require standalone MCP App initialization

* refactor(gateway): keep standalone route load explicit
2026-07-18 17:50:37 -06:00
Peter Steinberger
65915bcd26 fix(ui): openknot/dash dark theme AA contrast for text-bearing fills (#111003) 2026-07-19 00:42:37 +01:00
Peter Steinberger
ec998a0f3f feat(canvas): export widgets as PNG — copy or download from the card menu (#110992)
* feat(canvas): export widgets as PNG — copy to clipboard or download from the card menu

* fix(ui): widget-export lint, knip, and lines-budget cleanup
2026-07-19 00:39:59 +01:00
Alex Knight
66aa22e4e8 fix(ui): keep session rosters consistent (#108249)
Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>
2026-07-19 09:06:32 +10:00
Peter Steinberger
bb7b2bca68 feat(ui): finish the chat session → thread rename across the Control UI (#110973)
* feat(ui): finish the chat session → thread rename across the Control UI

Completes the #110933 creation-surface rename mechanically: Threads page
(title, filters, archive/delete/rename/pin menus, transcript search),
sidebar labels and menus, welcome suggestion, palette category, tools
availability copy, workboard lifecycle/card strings, dreaming history,
board/diff/workspace-rail chrome, and the untitled main/channel fallback
names. Technical identifiers stay: Session ID, session keys, terminal
sessions, protocol wording. Living docs updated (control-ui.md);
historical release notes left as shipped.

* style(ui): format session-management e2e

* fix(ui): finish thread rename in navigation labels and stale test literals

Codex review caught the palette Threads entry and the Worktrees owner
column still saying Session; CI caught test literals asserting the old
copy (Threads page overview tile, filter tooltips, group counts, catalog
terminal notice, create-rejection error, workboard lifecycle hint). Also
completes the usage-stat cluster (Threads + hints) and the tool-catalog
group label. Native app strings (iOS/Android/macOS) keep session wording
and reconcile through their own i18n pipelines as a follow-up.
2026-07-18 23:15:13 +01:00
clawsweeper[bot]
b88646cf78 feat(webchat): reply-to a message with hydrated reply context (#110791)
* feat(webchat): reply-to a message with hydrated reply context

Control UI replies now carry the target transcript id as replyToId on
chat.send. The Gateway resolves the replied-to message from session
history and hydrates the channel-agnostic ReplyToId/ReplyToBody/
ReplyToSender envelope fields, so agents receive reply_to_id,
has_reply_context, and the untrusted reply-target block exactly like
Discord replies (mirrors #90263). Reply targets without a persisted
transcript id keep the inline-quote fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(webchat): keep non-reply chat.send dispatch ordering and satisfy CI gates

* docs(webchat): match reply-context doc to webchat conversation-info policy

* fix(webchat): hydrate reply bodies from display-visible content only

---------

Co-authored-by: openclaw-clawsweeper[bot] <openclaw-clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-07-18 15:57:59 -06:00
Peter Steinberger
8ff1512454 feat(ui): sidebar rows use full width; actions overlay with a hover fade (#110959)
Session-row titles run to the sidebar edge instead of reserving the hover
action cluster's width in-flow. The trailing aside overlays the row
(pointer-events off at rest so link clicks pass through) and the link
content fades out beneath the surfaced controls via a mask, which stays
correct over rest/hover/active/selected backgrounds. Rows with a child
toggle keep it rightmost; actions land at the link edge either way. Child
rows keep the in-flow aside since their runtime trail is resting content.
Touch keeps actions visible, so the fade is permanent there.
2026-07-18 22:47:46 +01:00
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