ToolCall.tsx previously imported highlight.js statically, pulling the
entire hljs bundle into the main Chat chunk and preventing Vite from
splitting it into the lazy markdown chunk.
Now hljs is dynamically imported and loaded on first use. This:
- Removes the Vite build warning about mixed static/dynamic imports
- Reduces the Chat chunk by ~1.6 KB
- Consolidates hljs into the lazy markdown chunk
- Renders unhighlighted text instantly, then re-renders with syntax
highlighting once hljs loads (typically < 100ms)
Images sent by the user were transmitted to the gateway correctly but
not shown in the chat UI, making it appear as if attachments were lost.
Now image blocks are included in the user message for immediate visual
feedback.
Closes#14
- Move extractText and extractThinking from useGateway and useSecondarySession into shared lib
- Add comprehensive unit tests (13 tests) for both functions
- Eliminate code duplication between the two hooks
Add a clientId option that can be set via:
- VITE_CLIENT_ID env var at build time
- Advanced section in the login screen at runtime
- Stored in localStorage with other credentials
Defaults to 'webchat' for backward compatibility. Users can set it
to 'openclaw-control-ui' to use OpenClaw's dangerouslyDisableDeviceAuth
bypass without post-install patching.
Closes#11
- ChatInput: add aria-labels to remove file, send shortcut toggle, and stop buttons
- CodeBlock: add aria-labels to word wrap, line numbers, and collapse/expand buttons
- Header: add aria-labels to session info, copy, close, and compact buttons
Add token/password auth mode toggle on the login screen.
When password mode is selected, sends { password } instead of
{ token } in the WebSocket connect handshake.
Also adds clipboard utility tests and fixes credential test
to include authMode field.
When OpenClaw's webchat relays user messages, it wraps them in metadata
(conversation info JSON block + UTC timestamp prefix). This strips the
envelope at render time so users see only their actual text.
- Add hasWebchatEnvelope() and stripWebchatEnvelope() to systemEvent.ts
- Chain webchat + webhook stripping via stripAll() helper in ChatMessage
- Fix 'webhook' label only appearing for actual webhook messages, not
for envelope-stripped webchat messages
Co-authored-by: togotago <drewmfleury@gmail.com>
System events now render as compact pills (label + chevron + timestamp)
that expand on click to reveal the full message content.
- Collapsed (default): rounded-full pill with Zap icon, label, ChevronDown,
and timestamp. Clean single-line appearance.
- Expanded (on click): rounded-xl container with full message text shown
below in whitespace-pre-wrap. Chevron rotates 180deg.
- Added cursor-pointer and hover:bg-pc-elevated/50 for discoverability.
- Removed always-visible truncated text from collapsed state for a cleaner
default appearance.
Co-authored-by: togotago <drewmfleury@gmail.com>
- Generate Ed25519 keypair via Web Crypto API
- Persist keypair in IndexedDB (survives page reloads)
- Sign connect payload with device private key
- Include device object in connect params (id, publicKey, signature, signedAt)
- Handle NOT_PAIRED error with 'pairing' connection status
- Show pairing-pending banner with instructions to run openclaw devices approve
- Extract nonce from connect.challenge for v2 payload signing
- Add i18n translations for pairing banner in all 8 languages
Closes#6
- Add copyToClipboard utility with execCommand fallback for HTTP deployments (#76)
- Replace all navigator.clipboard.writeText calls with copyToClipboard
- Session rename now persists server-side via sessions.patch (#78)
- Pass onRename callback from App to Sidebar
Code blocks longer than 25 lines are now automatically collapsed,
showing only the first 10 lines with a gradient fade and a
'Show all N lines' button. Click to expand/collapse.
Also fixes version sync (package.json now matches v1.63.4)
and shows line count in the language header for long blocks.
Swipe right from the left edge to open the sidebar,
swipe left to close it. Standard mobile UX pattern
with edge detection, vertical drift rejection, and
time-based velocity check.
- Double-click session name in sidebar to rename inline
- Pencil icon on hover for discoverability
- Custom names persisted in localStorage
- Enter to confirm, Escape to cancel, blur to save
- Clear name to revert to auto-generated display name
- Search filter respects custom names
- i18n for all 8 languages