mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
fix(discord): reserve closing-fence space on fence-closing lines (#95661)
`chunkDiscordText` reserved closing-fence space from the post-line fence state (`nextOpenFence`), but a flush during a line's segment loop appends the closing fence based on the still-open `openFence`, which is only advanced after the line. On a line that closes a fence yet carries trailing text, `reserveChars` was 0 while `flush()` still appended a `` ``` ``, producing a chunk of `maxChars + 4` (e.g. 2004 > 2000) that Discord rejects with HTTP 400. Reserve against `nextOpenFence ?? openFence` so whichever fence a flush can close is accounted for, keeping a fence-closing line's chunk within `maxChars`. Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -78,6 +78,17 @@ describe("chunkDiscordText", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps chunks within maxChars when a closing fence line carries trailing text", () => {
|
||||
// A line that both closes the fence and carries a long tail must still reserve closing-fence
|
||||
// space; otherwise a mid-line flush appended "```" and overflowed maxChars (e.g. 2004 > 2000).
|
||||
for (let pad = 1990; pad <= 2000; pad++) {
|
||||
const text = "hi\n```lang\n```" + "z".repeat(pad);
|
||||
for (const chunk of chunkDiscordText(text, { maxChars: 2000, maxLines: 100 })) {
|
||||
expect(chunk.length).toBeLessThanOrEqual(2000);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("preserves whitespace when splitting long lines", () => {
|
||||
const text = Array.from({ length: 40 }, () => "word").join(" ");
|
||||
const chunks = chunkDiscordText(text, { maxChars: 20, maxLines: 50 });
|
||||
|
||||
@@ -207,8 +207,12 @@ export function chunkDiscordText(text: string, opts: ChunkDiscordTextOpts = {}):
|
||||
}
|
||||
}
|
||||
|
||||
const reserveChars = nextOpenFence ? closeFenceLine(nextOpenFence).length + 1 : 0;
|
||||
const reserveLines = nextOpenFence ? 1 : 0;
|
||||
// A flush can fire mid-line, before `openFence` advances to `nextOpenFence` below, so it closes
|
||||
// against the still-open `openFence`. A fence-closing line that also carries trailing text would
|
||||
// otherwise reserve 0 yet still get a closing fence appended on flush, overflowing maxChars.
|
||||
const fenceToReserve = nextOpenFence ?? openFence;
|
||||
const reserveChars = fenceToReserve ? closeFenceLine(fenceToReserve).length + 1 : 0;
|
||||
const reserveLines = fenceToReserve ? 1 : 0;
|
||||
const effectiveMaxChars = maxChars - reserveChars;
|
||||
const effectiveMaxLines = maxLines - reserveLines;
|
||||
const charLimit = effectiveMaxChars > 0 ? effectiveMaxChars : maxChars;
|
||||
|
||||
Reference in New Issue
Block a user