fix: trim leading newlines from streaming/block-flush text output#9285
fix: trim leading newlines from streaming/block-flush text output#92851kuna wants to merge 1 commit intoopenclaw:mainfrom
Conversation
Co-authored-by: Alyx <[email protected]>
Additional Comments (1)
Also note this affects any other callers of Prompt To Fix With AIThis is a comment left during a code review.
Path: src/agents/pi-embedded-helpers/errors.ts
Line: 93:97
Comment:
**Inconsistent trimming on empty**
`collapseConsecutiveDuplicateBlocks()` now trims for the 1-block case, but for the empty/whitespace-only case it still returns the *original* `text` (`if (!trimmed) return text;`). That means callers like `sanitizeUserFacingText()` can still emit leading newlines/spaces when `text` is only whitespace after tag-stripping (e.g., `"\n\n"` or `" "`). If the intent is “no user-facing leading whitespace ever”, this early return should be consistent with the new behavior.
Also note this affects any other callers of `collapseConsecutiveDuplicateBlocks()`.
How can I resolve this? If you propose a fix, please make it concise. |
|
Superseded by #10612, which uses a more targeted approach: strips leading blank lines only on the first emitted chunk (via |
|
Closing in favor of #10612 (targeted first-chunk-only fix). |
|
Superseded by #10612 (targeted first-chunk blank-line trim). |
Problem
iMessage (and likely other channel) responses have 1-2 blank lines prepended before the actual text content when using extended thinking mode.
Root Cause
Anthropic models in extended thinking mode emit a
\n\ntext content block before the thinking block. The streaming/block-flush path preserves these leading newlines because:emitBlockChunk()inpi-embedded-subscribe.tsuses.trimEnd()instead of.trim()— preserves leading newlinescollapseConsecutiveDuplicateBlocks()inpi-embedded-helpers/errors.tsreturns the original untrimmed text when there's only one paragraph block (early returnif (blocks.length < 2) return text;)sanitizeUserFacingText()doesn't trim the final outputThe final payloads path (
extractAssistantText()) is NOT affected because it trims individual content blocks and filters empties.Fixes (defense in depth)
emitBlockChunk:.trimEnd()→.trim()— stops leading newlines at the sourcecollapseConsecutiveDuplicateBlocks: early return now returnstrimmedinstead oftext— fixes the sanitizersanitizeUserFacingText: added.trim()to final return — safety net for all pathsTesting
Fixes #7689
Greptile Overview
Greptile Summary
This PR addresses leading blank lines in streaming/block-flush output (notably in iMessage) by trimming whitespace earlier and adding a defensive trim in the user-facing sanitizer.
Changes are localized to the embedded Pi streaming path (
src/agents/pi-embedded-subscribe.ts) and the shared error/text sanitization helpers (src/agents/pi-embedded-helpers/errors.ts), so the fix should apply across any channels that consume those paths.Confidence Score: 3/5
collapseConsecutiveDuplicateBlocks()still returns the untrimmed original text for the all-whitespace case, which undermines the stated ‘defense in depth’ intent for leading-newline removal in some scenarios.Context used:
dashboard- CLAUDE.md (source)dashboard- AGENTS.md (source)