fix(discord): propagate blockquote context across chunk boundaries#63412
fix(discord): propagate blockquote context across chunk boundaries#63412extrasmall0 wants to merge 2 commits intoopenclaw:mainfrom
Conversation
When chunkDiscordText() flushed a chunk mid-blockquote, the next chunk
started without the leading '>' prefix. Discord renders each message
independently, so continuation lines appeared as plain text outside the
quote block — broken visually.
Fix: track the current blockquote prefix (openBlockquote) in the same
way fenced code blocks are tracked. On flush(), if a blockquote context
is open and we are not inside a fenced block, seed the next chunk's
current buffer with the blockquote prefix so continuation lines render
correctly.
Also add BLOCKQUOTE_RE + getBlockquotePrefix() helpers to support
nested blockquotes ('>>', '>>>', etc.).
Fixes openclaw#63409
Greptile SummaryThis PR introduces However, the unconditional Confidence Score: 4/5Safe to merge after addressing the line-limit flush regression; no security or data concerns. The character-split fix is correct, but the unconditional re-seeding in flush() introduces an empty blockquote line artefact for every maxLines-triggered split — a verifiable regression on the changed code path. No tests were added to catch either the original bug or this new edge case. extensions/discord/src/chunk.ts — specifically the flush() re-seeding block (lines 154-159) and the absence of a companion chunk.test.ts.
|
| // Re-open blockquote context on next chunk so Discord keeps rendering | ||
| // continuation lines inside the quote block. | ||
| if (openBlockquote && !openFence) { | ||
| current = openBlockquote; | ||
| currentLines = 1; | ||
| } |
There was a problem hiding this comment.
Extra empty blockquote line inserted on line-limit splits
When flush() fires because adding the next full line would exceed maxLines (rather than maxChars mid-line), current is seeded to "> " and then the next line (which already carries its own > prefix) is appended with a "\n" delimiter — producing "> \n> actual content". Discord renders that leading > as a separate, visually empty blockquote paragraph before the real content.
The re-seeding is only necessary for character-split continuations (isLineContinuation = true), where the tail segment has no > of its own. For line-boundary splits every continuation line already carries the correct prefix, so re-seeding just adds an artefact.
One way to scope the fix to the case that needs it:
// Only re-seed when the split happens mid-line (character overrun);
// line-boundary splits naturally carry their own > prefix.
if (openBlockquote && !openFence && isLineContinuation) {
current = openBlockquote;
currentLines = 1;
}This would require threading an isLineContinuation flag into flush() (or inlining the re-seed after the call). The current unconditional seeding is a regression for the maxLines-triggered split path.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/discord/src/chunk.ts
Line: 154-159
Comment:
**Extra empty blockquote line inserted on line-limit splits**
When `flush()` fires because adding the next full line would exceed `maxLines` (rather than `maxChars` mid-line), `current` is seeded to `"> "` and then the next line (which already carries its own `>` prefix) is appended with a `"\n"` delimiter — producing `"> \n> actual content"`. Discord renders that leading `> ` as a separate, visually empty blockquote paragraph before the real content.
The re-seeding is only necessary for *character-split* continuations (`isLineContinuation = true`), where the tail segment has no `>` of its own. For line-boundary splits every continuation line already carries the correct prefix, so re-seeding just adds an artefact.
One way to scope the fix to the case that needs it:
```ts
// Only re-seed when the split happens mid-line (character overrun);
// line-boundary splits naturally carry their own > prefix.
if (openBlockquote && !openFence && isLineContinuation) {
current = openBlockquote;
currentLines = 1;
}
```
This would require threading an `isLineContinuation` flag into `flush()` (or inlining the re-seed after the call). The current unconditional seeding is a regression for the `maxLines`-triggered split path.
How can I resolve this? If you propose a fix, please make it concise.| @@ -0,0 +1,302 @@ | |||
| import { chunkMarkdownTextWithMode, type ChunkMode } from "openclaw/plugin-sdk/reply-chunking"; | |||
There was a problem hiding this comment.
No tests for the new chunking logic
chunk.ts is a new file with non-trivial state-machine logic (fenced code blocks, blockquote tracking, long-line splitting, italics rebalancing), but no chunk.test.ts was added. The PR description lists specific cases that should be covered (split within a > blockquote, nested >>, unchanged non-blockquote content). Given the repo's Vitest + V8 coverage threshold of 70%, adding at least the described table-driven cases would prevent future regressions.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/discord/src/chunk.ts
Line: 1
Comment:
**No tests for the new chunking logic**
`chunk.ts` is a new file with non-trivial state-machine logic (fenced code blocks, blockquote tracking, long-line splitting, italics rebalancing), but no `chunk.test.ts` was added. The PR description lists specific cases that should be covered (split within a `>` blockquote, nested `>>`, unchanged non-blockquote content). Given the repo's Vitest + V8 coverage threshold of 70%, adding at least the described table-driven cases would prevent future regressions.
How can I resolve this? If you propose a fix, please make it concise.|
Follow-up here: I addressed Greptile's main regression note in 8879f7b by limiting the blockquote re-seed to continuation splits, so line-boundary flushes no longer produce an empty quoted paragraph at the start of the next chunk. The change now only preserves quote context for the mid-line split case that originally broke rendering. If maintainers want it, I can add a narrow regression test for the line-limit and char-split cases in a follow-up. |
Summary
Fixes #63409
When
chunkDiscordText()flushed a chunk in the middle of a blockquote, the next chunk started without the leading>prefix. Discord renders each message independently, so continuation lines appeared as plain text outside the quote block.Root cause
The chunker already tracks fenced code block state (
openFence) and re-seeds the next chunk with the opening fence line on flush. The same treatment was never applied to blockquote prefixes.Fix
Track the current blockquote prefix (
openBlockquote) using the same pattern:A
BLOCKQUOTE_REhelper extracts the prefix including nested levels (>,>>, etc.). The prefix is updated on each line and cleared when a non-blockquote line is encountered.Behaviour
>blockquote split at chunk boundary>>blockquote split at boundary