mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-16 20:51:43 +00:00
* fix(proxy-capture): truncate inline preview on UTF-8 character boundary
persistEventPayload stores a small UTF-8 preview (dataText) inline for fast CLI
listings and query output, capped at previewLimit bytes (default 8192). It built
the preview with buffer.subarray(0, previewLimit).toString("utf8"), which slices
the buffer at an arbitrary byte offset. For any non-ASCII body (emoji/CJK/accented
text, common in model-provider HTTP traffic), the cut lands mid-multibyte-sequence
and Node emits a trailing U+FFFD replacement char into the stored preview column.
Decode the full buffer first, then truncate with the existing truncateUtf8Prefix
helper (src/utils/utf8-truncate.ts), which backtracks off UTF-8 continuation bytes
so the preview ends on a complete character while staying within the byte budget.
ASCII previews are byte-identical; only malformed trailing U+FFFD is removed.
Co-Authored-By: Claude <noreply@anthropic.com>
* test(proxy-capture): align stub store return type with SharedCaptureBlobRecord
The preview-boundary test stub returned a bare { blobId, sha256, byteLength },
which fails tsgo typecheck against persistPayload's declared
CaptureBlobRecord | SharedCaptureBlobRecord return. Return a complete
SharedCaptureBlobRecord instead. Also use template strings for the multibyte
fixtures to satisfy no-useless-concat. No assertion behavior change.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(proxy-capture): byte-bounded UTF-8 preview, unify store and proxy paths
The prior fix decoded the whole payload with buffer.toString("utf8") before
truncating, an availability regression for large captured payloads, and it left
the proxy-server finishBodyPreviewCapture path on the same byte-subarray decode
that can split a trailing multibyte sequence into U+FFFD.
Add truncateUtf8PrefixFromBuffer: decodes only the byte-bounded prefix and walks
back to verify the trailing multibyte sequence is complete (handles both a hard
byte cap and a buffer already sliced mid-sequence upstream, e.g. a dangling lead
byte). Use it from persistEventPayload (no full-payload decode) and
finishBodyPreviewCapture (same boundary safety), so both preview paths share one
canonical helper.
Add completeUtf8PrefixLength coverage plus proxy-server body-preview regression
tests for dangling-lead, byte-cap, emoji, and oversized-body cases.
Co-Authored-By: Claude <noreply@anthropic.com>
* style(proxy-capture): fix no-useless-assignment and unnecessary template expr
- utf8-truncate.ts: expected is reassigned in every branch, so declare without
the unused initial value (no-useless-assignment).
- proxy-server.body-preview.test.ts: drop the redundant template wrapper around
a single expression (no-unnecessary-template-expression). No behavior change.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(utf8-truncate): clarify completeUtf8PrefixLength byte-budget contract
Document that maxBytes is a byte (not character) limit and that the returned
length is the largest offset that does not split a multibyte sequence.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(proxy-capture): preserve UTF-8 preview boundaries
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>