fix: trim leading blank lines on first emitted chunk only (#5530)#10612
fix: trim leading blank lines on first emitted chunk only (#5530)#106121kuna wants to merge 1 commit intoopenclaw:mainfrom
Conversation
263309d to
a3ea5b5
Compare
Additional Comments (2)
This PR changes several Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! Prompt To Fix With AIThis is a comment left during a code review.
Path: package.json
Line: 113:120
Comment:
**Caret dependency range**
This PR changes several `@mariozechner/pi-*` dependencies from exact `0.52.6` to `^0.52.6`. That makes installs non-reproducible and can pull in newer versions with API/behavior changes, which is particularly risky here since the PR also relies on `setAutoCompactionRetryHook`/internal session fields. If the intent is just to pick up the current version, keep these pinned to an exact version instead of a caret range.
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/agents/pi-embedded-runner/run/attempt.ts
Line: 523:534
Comment:
**Restoring internal session fields**
`downgradeSystemPromptOneShot()` captures `previousBasePrompt`/`previousRebuild` from `mutableSession._baseSystemPrompt` and later restores them, but those fields are not guaranteed to exist. When they were originally `undefined`, the restore callback sets them back to `undefined` (explicitly), which can change session behavior vs leaving the properties unset (and may break `_rebuildSystemPrompt` lookups if the library expects absence vs undefined). Since this code is intentionally poking internal/private fields, the restore should avoid writing the properties back when they were not present originally (or use the session’s public API only).
How can I resolve this? If you propose a fix, please make it concise. |
a3ea5b5 to
6f5f4ee
Compare
6f5f4ee to
24635ee
Compare
LLM responses frequently begin with \n\n, which survives through sanitizeUserFacingText and reaches the channel as visible blank lines. Root cause: the function used trimmed text for empty-checks but returned the untrimmed 'stripped' variable. Two one-line fixes: 1. Return empty string (not whitespace-only 'stripped') for blank input 2. Apply trimStart() to the final return value Fixes the same issue as openclaw#8052 and openclaw#10612 but at the root cause (sanitizeUserFacingText) rather than scattering trimStart across multiple delivery paths.
) * fix: strip leading whitespace from sanitizeUserFacingText output LLM responses frequently begin with \n\n, which survives through sanitizeUserFacingText and reaches the channel as visible blank lines. Root cause: the function used trimmed text for empty-checks but returned the untrimmed 'stripped' variable. Two one-line fixes: 1. Return empty string (not whitespace-only 'stripped') for blank input 2. Apply trimStart() to the final return value Fixes the same issue as #8052 and #10612 but at the root cause (sanitizeUserFacingText) rather than scattering trimStart across multiple delivery paths. * Changelog: note sanitizeUserFacingText whitespace normalization Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
…nclaw#16158) * fix: strip leading whitespace from sanitizeUserFacingText output LLM responses frequently begin with \n\n, which survives through sanitizeUserFacingText and reaches the channel as visible blank lines. Root cause: the function used trimmed text for empty-checks but returned the untrimmed 'stripped' variable. Two one-line fixes: 1. Return empty string (not whitespace-only 'stripped') for blank input 2. Apply trimStart() to the final return value Fixes the same issue as openclaw#8052 and openclaw#10612 but at the root cause (sanitizeUserFacingText) rather than scattering trimStart across multiple delivery paths. * Changelog: note sanitizeUserFacingText whitespace normalization Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
bfc1ccb to
f92900f
Compare
|
This pull request has been automatically marked as stale due to inactivity. |
|
Closing as AI-assisted stale-fix triage. Linked issue #5530 ("iMessage: leading blank lines in streamed messages") is currently CLOSED and was closed on 2026-02-13T03:32:44Z with state reason NOT_PLANNED. If the underlying bug is still reproducible on current main, please reopen this PR (or open a new focused fix PR) and reference both #5530 and #10612 for fast re-triage. |
|
Closed after AI-assisted stale-fix triage (closed issue duplicate/stale fix). |
…nclaw#16158) * fix: strip leading whitespace from sanitizeUserFacingText output LLM responses frequently begin with \n\n, which survives through sanitizeUserFacingText and reaches the channel as visible blank lines. Root cause: the function used trimmed text for empty-checks but returned the untrimmed 'stripped' variable. Two one-line fixes: 1. Return empty string (not whitespace-only 'stripped') for blank input 2. Apply trimStart() to the final return value Fixes the same issue as openclaw#8052 and openclaw#10612 but at the root cause (sanitizeUserFacingText) rather than scattering trimStart across multiple delivery paths. * Changelog: note sanitizeUserFacingText whitespace normalization Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> (cherry picked from commit 3881af5) # Conflicts: # CHANGELOG.md
…nclaw#16158) * fix: strip leading whitespace from sanitizeUserFacingText output LLM responses frequently begin with \n\n, which survives through sanitizeUserFacingText and reaches the channel as visible blank lines. Root cause: the function used trimmed text for empty-checks but returned the untrimmed 'stripped' variable. Two one-line fixes: 1. Return empty string (not whitespace-only 'stripped') for blank input 2. Apply trimStart() to the final return value Fixes the same issue as openclaw#8052 and openclaw#10612 but at the root cause (sanitizeUserFacingText) rather than scattering trimStart across multiple delivery paths. * Changelog: note sanitizeUserFacingText whitespace normalization Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> (cherry picked from commit 3881af5) # Conflicts: # CHANGELOG.md # src/agents/pi-embedded-helpers/errors.ts
…nclaw#16158) * fix: strip leading whitespace from sanitizeUserFacingText output LLM responses frequently begin with \n\n, which survives through sanitizeUserFacingText and reaches the channel as visible blank lines. Root cause: the function used trimmed text for empty-checks but returned the untrimmed 'stripped' variable. Two one-line fixes: 1. Return empty string (not whitespace-only 'stripped') for blank input 2. Apply trimStart() to the final return value Fixes the same issue as openclaw#8052 and openclaw#10612 but at the root cause (sanitizeUserFacingText) rather than scattering trimStart across multiple delivery paths. * Changelog: note sanitizeUserFacingText whitespace normalization Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
…nclaw#16158) * fix: strip leading whitespace from sanitizeUserFacingText output LLM responses frequently begin with \n\n, which survives through sanitizeUserFacingText and reaches the channel as visible blank lines. Root cause: the function used trimmed text for empty-checks but returned the untrimmed 'stripped' variable. Two one-line fixes: 1. Return empty string (not whitespace-only 'stripped') for blank input 2. Apply trimStart() to the final return value Fixes the same issue as openclaw#8052 and openclaw#10612 but at the root cause (sanitizeUserFacingText) rather than scattering trimStart across multiple delivery paths. * Changelog: note sanitizeUserFacingText whitespace normalization Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
…nclaw#16158) * fix: strip leading whitespace from sanitizeUserFacingText output LLM responses frequently begin with \n\n, which survives through sanitizeUserFacingText and reaches the channel as visible blank lines. Root cause: the function used trimmed text for empty-checks but returned the untrimmed 'stripped' variable. Two one-line fixes: 1. Return empty string (not whitespace-only 'stripped') for blank input 2. Apply trimStart() to the final return value Fixes the same issue as openclaw#8052 and openclaw#10612 but at the root cause (sanitizeUserFacingText) rather than scattering trimStart across multiple delivery paths. * Changelog: note sanitizeUserFacingText whitespace normalization Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> --------- Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
Problem
Anthropic models emit a
"\n\n"text block before thinking blocks. The existing.trimEnd()inemitBlockChunkonly strips trailing whitespace, so leading newlines pass through to iMessage output as blank lines before the agent's response.Root Cause
emitBlockChunk):stripBlockTags(text, state.blockState).trimEnd()preserves leading\n\n.sanitizeUserFacingText):collapseConsecutiveDuplicateBlocks()returnstext(untrimmed) whenblocks.length < 2.Fix
Targeted first-chunk-only trim instead of the broader
.trim()on every chunk (which risks stripping meaningful indentation at chunk boundaries):emitBlockChunk(streaming path)Only the first emitted chunk (when
lastBlockReplyTextis stillundefined) gets leading blank lines stripped. Subsequent chunks use.trimEnd()as before, preserving indentation in code blocks.sanitizeUserFacingText(final text path)Strips leading blank lines after removing
<final>tags but before error detection and collapse logic.Why
/^(?:[ \t]*\n)+/instead of.trim()\n\n indented code→indented code)Testing
sanitizeUserFacingTextverifying leading blank line strippingSupersedes #9285. Closes #5530.
Greptile Overview
Greptile Summary
\n\nshowing up as empty lines), while keeping.trimEnd()behavior for subsequent chunks.sanitizeUserFacingText()to strip leading blank lines after removing<final>tags and adds a unit test covering this behavior.Confidence Score: 3/5