gui: fix prose-after-fence overwriting finalized code segment
In incrementalAppend(), when a prose line follows a closed code fence, the code checked only whether the last segment was type Text (which code fences also are) and then tried to append. Since the finalized fence HTML ends in </pre> not </div>, it fell into the 'shouldn't happen' branch and overwrote the segment with escapeForHtml(proseLines) — destroying the rendered tool output. Tool blocks are always shaped: ``` <output> ``` <blank> <blank> so the trailing blank lines triggered this on every tool call, leaving only <div>\n</div> in renderedHtml. Fix: gate extension on the segment actually being an in-progress prose segment (trailing </div>). Otherwise start a new prose segment. Verified: tool blocks now render 'hi\nexit: 0', file_glob results, and syntax-highlighted diffs correctly.
This commit is contained in:
parent
ed74d421c3
commit
b6a7d93d0e
|
|
@ -538,20 +538,21 @@ void ChatBlockModel::incrementalAppend(int blockIndex, const QString &line)
|
||||||
const QString defaultColor = getDefaultTextColor();
|
const QString defaultColor = getDefaultTextColor();
|
||||||
const QString escapedLine = line.toHtmlEscaped();
|
const QString escapedLine = line.toHtmlEscaped();
|
||||||
|
|
||||||
if (!block.segments.isEmpty() && block.segments.last().type == BlockSegment::Text
|
// Only extend the last segment if it is an in-progress prose segment
|
||||||
&& !rs.inFence) {
|
// (identified by its trailing </div>). A finalized code fence segment
|
||||||
// Append to existing prose segment — strip closing </div>, add newline + content
|
// ends in </pre> and must not be overwritten.
|
||||||
|
bool canExtend = !block.segments.isEmpty()
|
||||||
|
&& block.segments.last().type == BlockSegment::Text
|
||||||
|
&& block.segments.last().html.endsWith(QStringLiteral("</div>"));
|
||||||
|
|
||||||
|
if (canExtend) {
|
||||||
QString &segHtml = block.segments.last().html;
|
QString &segHtml = block.segments.last().html;
|
||||||
// Remove trailing </div> to append
|
segHtml.chop(6); // remove trailing </div>
|
||||||
if (segHtml.endsWith(QStringLiteral("</div>"))) {
|
segHtml += '\n' + escapedLine + QStringLiteral("</div>");
|
||||||
segHtml.chop(6);
|
|
||||||
segHtml += '\n' + escapedLine + QStringLiteral("</div>");
|
|
||||||
} else {
|
|
||||||
// Shouldn't happen, but fall back to full rebuild
|
|
||||||
segHtml = escapeForHtml(rs.proseLines.join('\n'));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Start a new text segment
|
// Start a new prose segment
|
||||||
|
rs.proseLines.clear();
|
||||||
|
rs.proseLines.append(line);
|
||||||
BlockSegment seg;
|
BlockSegment seg;
|
||||||
seg.type = BlockSegment::Text;
|
seg.type = BlockSegment::Text;
|
||||||
seg.html = QStringLiteral("<div style=\"white-space:pre-wrap;color:") + defaultColor + QStringLiteral("\">")
|
seg.html = QStringLiteral("<div style=\"white-space:pre-wrap;color:") + defaultColor + QStringLiteral("\">")
|
||||||
|
|
|
||||||
Reference in New Issue