gui: fix incremental parser producing phantom tool_call blocks
When the tail contains only one header (common case during streaming), just update the last block content directly. Fall back to full reparse only when a genuinely new block boundary appears.
This commit is contained in:
parent
7ccce95445
commit
c46f38fc93
|
|
@ -131,29 +131,33 @@ static constexpr int LOAD_MORE_COUNT = 30;
|
|||
|
||||
void ChatBlockModel::reparseIncremental()
|
||||
{
|
||||
// Only re-parse from where the last block started — O(tail) not O(full text)
|
||||
// Fast path: just update the last block's content from the raw text tail.
|
||||
// Only do a full reparse if a new block header appeared.
|
||||
QString tail = m_rawText.mid(m_lastBlockTextOffset);
|
||||
QList<ChatBlock> tailBlocks = parseBlocks(tail);
|
||||
|
||||
// Replace the last block (which may have grown) and append any new blocks
|
||||
if (!m_allBlocks.isEmpty())
|
||||
m_allBlocks.removeLast();
|
||||
m_allBlocks.append(tailBlocks);
|
||||
// Check if a new block header appeared in the NEW portion (after old last-block content)
|
||||
int oldLastBlockLen = m_allBlocks.isEmpty() ? 0 : m_allBlocks.last().content.size();
|
||||
// The header itself is at m_lastBlockTextOffset, content starts after it + newline
|
||||
// Simple heuristic: if the tail contains another header pattern, do full reparse
|
||||
static const QRegularExpression headerRe(
|
||||
R"(^\[(user|assistant|reasoning|call|tool|error|info)(?::([^\]]*))\])",
|
||||
QRegularExpression::MultilineOption);
|
||||
auto it = headerRe.globalMatch(tail);
|
||||
int headerCount = 0;
|
||||
while (it.hasNext()) { it.next(); headerCount++; }
|
||||
|
||||
// Update offset: last block starts at the last header in the tail
|
||||
if (tailBlocks.size() > 1) {
|
||||
// Multiple blocks parsed from tail — advance offset to where the last one starts
|
||||
// Find the last header boundary in m_rawText
|
||||
static const QRegularExpression headerRe(
|
||||
R"(^\[(user|assistant|reasoning|call|tool|error|info)(?::([^\]]*))\])",
|
||||
QRegularExpression::MultilineOption);
|
||||
auto it = headerRe.globalMatch(m_rawText);
|
||||
int lastPos = 0;
|
||||
while (it.hasNext()) {
|
||||
auto match = it.next();
|
||||
lastPos = match.capturedStart();
|
||||
if (headerCount > 1) {
|
||||
// New block boundary appeared — fall back to full reparse
|
||||
reparse();
|
||||
return;
|
||||
}
|
||||
|
||||
// Common case: just the last block grew. Update its content directly.
|
||||
if (!m_allBlocks.isEmpty()) {
|
||||
QList<ChatBlock> tailBlocks = parseBlocks(tail);
|
||||
if (!tailBlocks.isEmpty()) {
|
||||
m_allBlocks.last() = tailBlocks.last();
|
||||
}
|
||||
m_lastBlockTextOffset = lastPos;
|
||||
}
|
||||
|
||||
updateVisibleWindow();
|
||||
|
|
|
|||
Reference in New Issue