Ports the openclaw.ai hero mascot animation (body float 4s, eye blink 3s,
antenna wiggle 2s, staggered claw snaps 4s) to every product surface that
shows the logo:
- web: ui/public/favicon.svg now carries SMIL animations, so every <img>
usage (login gate, sidebar brand, agent avatar fallback) animates with
no markup changes; CSS animations do not run in <img>-loaded SVGs.
- iOS: new OpenClawMascotView renders the canonical 120x120 vector via
Canvas + TimelineView (30fps, honors Reduce Motion); OpenClawProMark
uses it in onboarding, sidebar, and command center. Static PNG imageset
deleted (watch app keeps its own copy).
- Android: new OpenClawMascot composable (PathParser + infinite
transitions, honors the OS animator scale) replaces the static vector
drawable in onboarding and the chat/shell/voice headers, with tint
support for the monochrome header silhouettes. Drawable deleted.
* fix(cli): shell completion omitted command aliases like capability, chat, and cron create
* fix(cli): route the dead exec-approvals root alias and single-source alias path expansion
* fix(cli): complete nested aliases in Bash
Co-authored-by: Jack-dev-ops <chen.zegui@xydigit.com>
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Jack-dev-ops <chen.zegui@xydigit.com>
Preserve fullOutputPath plus partial-spill metadata when oversized tool-result details are summarized for persistence. This keeps aggregate elision from relabeling capped or source-truncated web_fetch spill files as complete after reload.
Write truncated web_fetch extracted content to owner-only private temp files using the shared Full output footer contract. Spills use the wrapped untrusted-content form, cap recoverable content at 2,000,000 chars, and label capped or source-truncated spills as partial instead of full output.
Keep aggregate elision recoverable by preserving existing spill pointers only when the original model-visible footer already disclosed the path. This commit also keeps partial-spill markers honest, handles JSON-escaped footers, and resolves full-clear markers from the original tool-result message after partial aggregate shrinking.
Summary:
- The PR replaces QA Lab suite gateway `fetchJson` success-path `response.json()` with shared `readProviderJsonResponse` and adds an oversized-response regression test.
- PR surface: Source +1, Tests +33. Total +34 across 2 files.
- Reproducibility: yes. Current main still has the unbounded `response.json()` success path in `fetchJson`, an ... l proof for oversized streamed bodies, early cancellation, normal parsing, and the focused regression test.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(scripts): satisfy oxlint in qa-lab suite gateway bound proof
- PR branch already contained follow-up commit before automerge: fix(qa-lab): bound suite runtime gateway JSON response reads
- PR branch already contained follow-up commit before automerge: chore: drop local proof script from qa-lab gateway bound PR
Validation:
- ClawSweeper review passed for head 8c0eb49fcb.
- Required merge gates passed before the squash merge.
Prepared head SHA: 8c0eb49fcb
Review: https://github.com/openclaw/openclaw/pull/99165#issuecomment-4868175663
Co-authored-by: NIO <nocodet@mail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
* fix(infra): formatDuration rolls over near-boundary values to the next unit
The raw float was checked against the boundary before rounding, so values
like 59.5s, 59m30s, and 23h59m30s rounded up to "60 seconds", "60 minutes",
and "24 hours" in session maintenance warning messages instead of "1 minute",
"1 hour", and "1 day". Round first, then check the unit boundary.
Closes#99978
* fix(infra): fix formatDuration progressive rollover in session maintenance warning
Round seconds first, then promote to the next unit only when the
rounded lower unit reaches its overflow threshold (60s->min, 60m->hr,
24h->day). The previous approach compared raw milliseconds against the
unit boundary before rounding, causing half-unit values like 30s, 30m,
and 12h to promote one unit too early.
Closes#99978
* test(infra): expose formatDuration via testing export for direct verification
* ci: retrigger checks
* ci: retrigger checks
* test(infra): keep duration formatter private
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Allow busy TUI sessions to forward prompts into the configured queue while
keeping queued-turn admission, cancellation, restart, and transcript ownership
consistent across the TUI, Gateway, and followup queue.
Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
* fix(agents): use CJK-aware token estimation for tool results
Preserve the conservative 2 chars/token ratio for non-CJK tool results,
while using the accurate 4 chars/token ratio for CJK-heavy tool results.
This avoids false context-overflow errors for CJK content without changing
behavior for Latin/ASCII tool results.
- Add estimateCjkRatio() helper to cjk-chars.ts
- Choose tool-result chars-per-token based on CJK ratio (threshold 0.5)
- Add regression tests for CJK, mixed, and non-CJK tool results
* fix(agents): cover JSON and fallback payloads in CJK ratio pass
* test(agents): fix type cast for non-serializable tool-result regression
* fix(agents): make CJK tool-result estimates monotonic
---------
Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Expose an opt-in Doctor lint finding for Linux Gateway hosts where a loaded user-level systemd gateway unit has systemd lingering disabled.\n\nValidation:\n- Targeted Doctor health contribution tests passed locally.\n- Exact-head hosted checks passed on 65ec5a0acf, including QA Smoke CI, Real behavior proof, security/CodeQL, check-shrinkwrap, and selected CI shards.\n- Crabbox Azure proof exercised a loaded user systemd gateway unit with Linger=no and observed the expected lint warning.\n\nCo-authored-by: giodl73-repo <166990625+giodl73-repo@users.noreply.github.com>
The non-interactive permission failure surfaces as acpx's
PermissionPromptUnavailableError, not AcpRuntimeError; acpx 0.11.2 throws
it unwrapped (isGenericInternalAcpErrorMessage only matches "Internal
error"). Matches the corrected fact in the acp-agents-setup rewrite.
Pre-commit hook bypassed with formatting proof: repo oxfmt + Mintlify
accordion repair already run on the file (worktree has no node_modules).
* fix(gateway): truncateCloseReason drops partial UTF-8 code point instead of emitting mojibake
Buffer.subarray at a raw byte offset can cut inside a multi-byte UTF-8
sequence. Node decodes the dangling continuation bytes as U+FFFD (3 bytes
each), so the re-encoded result can exceed the intended maxBytes cap —
violating the RFC 6455 close-reason size contract and surfacing garbled
text to clients.
Back up from the cut point to the nearest UTF-8 sequence start before
slicing (UTF-8 continuation bytes match 10xxxxxx; skip them).
Closes#99976
* fix(lint): remove unnecessary non-null assertion on Buffer index
* ci: retrigger checks