* fix(gateway): keep command-list field clamping UTF-16 safe
clampString truncated command names, descriptions, aliases, arg names/descriptions, and choice values/labels with a raw value.slice(0, maxLength). When an emoji (or other astral code point) straddles the clamp limit, the raw slice keeps a dangling high surrogate and emits a lone surrogate over the gateway commands.list protocol result. Route the clamp through the shared truncateUtf16Safe primitive so the boundary code point is dropped whole. Adds a regression test through buildCommandsListResult.
* test(gateway): fold UTF-16 clamp regression into bounds coverage
Co-authored-by: MoerAI <friendnt@g.skku.edu>
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat(webchat): apply model picker changes immediately, drop Save/Discard row
* test(webchat): keep unavailable-default picker assertion
* fix(webchat): render picker check marks only on the selected row
* fix(webchat): lock reasoning and speed while a model switch is pending
* fix(webchat): guard immediate picker patches against stale rollbacks
* docs(webchat): note send gating invariant in picker commit path
* feat(webchat): rare lobster pet variants modeled on real lobster genetics
Extends the sidebar pet's palette ladder with a rare tier: blue (7%),
calico with mottled spots (3%), deep-sea abyss with glowing eye glints
(2%), translucent ghost/albino (1%), and a bicolor split two-tone with
mismatched claws and antennae (1%). Weights loosely mirror real-world
odds (blue ~1 in 2M, calico ~1 in 30M, split ~1 in 50M, ghost ~1 in
100M). Offline mode still greys out every variant's glints. Drops the
unused --lob-dim inline variable.
* feat(webchat): retro grail variant honoring the classic OpenClaw logo
Adds a ~0.5% super-rare 'retro' lobster pet: classic logo red with a
white sticker-outline halo, one oversized raised claw with a pincer
notch (small left pincher stays), determined angled brows, a smirk, and
tall V antennae. The mega claw rides the .lob-claw--r group so wave and
snip acts swing it.
* test: shorten loopback token fixtures below secret-scanner thresholds
* feat: carry gateway client capabilities through the CLI loopback backend
CLI-backed model runs now transport the originating client's declared
capabilities along the existing per-field loopback contract: RunCliAgentParams
gains clientCaps, prepare emits OPENCLAW_MCP_CLIENT_CAPS, the loopback header
template forwards x-openclaw-client-caps, the request context parses and
normalizes it (grant-authenticated callers keep ignoring spoofable headers),
and the loopback tool cache keys on a stable caps serialization so capless and
capped requests never share tool lists. Capability-gated tools such as
show_widget now work on CLI backends; the CLI session binding hash includes
caps, consistent with messageProvider. Cron and command-attempt runs stay
capless (fail closed).
Fixes#102577
Replace the native <select> on the Agents page with an accessible custom
listbox dropdown (openclaw-agent-select) that renders each agent's avatar
image, identity emoji, or initial. Local /avatar/<id> routes are fetched
with the bearer credential and rendered as cached blob URLs when gateway
token auth is active, matching the chat-avatar contract.
Refs #102792, #57067
* fix(googlechat): add 30 s request timeout to withGoogleChatResponse
* fix(googlechat): satisfy ResolvedGoogleChatAccount in api.test.ts
* fix(googlechat): bound control and media requests
Co-authored-by: NIO <nocodet@mail.com>
---------
Co-authored-by: NIO <nocodet@mail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat(ui): merge voice level meter into the stop-voice pill and disambiguate stop controls
* docs(web): describe the live voice pill control in Talk mode
* test(ui): capture dark-mode voice control proof in talk e2e
* fix(ui): keep the live voice pill wide at phone widths
* fix(ui): show the stop glyph instead of a fake listening meter when a talk session errors
* test(ui): assemble the mock talk client secret so scanners do not flag it
* feat(webchat): composer lobster mascot perches on the empty prompt
A decorative OpenClaw lobster (smooth icons.lobster style) sits on the
composer edge while the prompt is idle, ducks away on typing/runs, and
plays personality-weighted idle acts (scuttle, wave, snip, hop, spin,
peek, bubbles, nap with z's; poke to startle). Look and personality are
seeded per session + page load: palette, size, antennae, accessory,
perch, facing, temperament. Decorative contract: aria-hidden, no config,
reduced-motion stays fully static, timers pause on hidden tabs and clean
up on disconnect. Hidden on short-landscape viewports where the composer
scrolls.
Closes#102754
* refactor(webchat): move lobster mascot from composer to sidebar status pet
The composer perch read too close to Claude Code's input mascot. The pet
now lives on the sidebar footer ledge above the connection dot and
mirrors gateway state: idle personality acts when quiet, a faster scurry
pool while runs are active, grey-eyed worried pacing while disconnected,
and a startle on every status flip. Composer wiring reverted; element
renamed openclaw-lobster-pet; hidden in the collapsed rail.
* fix(release): validate prepared npm package sets
Forward-port the beta3 package-set preflight, Telegram, and Parallels validation to main while preserving main's existing Bun install smoke. Recompute decoded proxy response lengths and require artifact tarballs to exactly match the verified manifest.
* fix(release): lock fixture registry proxy origin