From 3a33c4e42a54581052ac94780cee5c91aff9c92b Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sat, 1 Aug 2026 12:45:33 +0200 Subject: [PATCH] add retry block support: Retry type, header color, expanded default --- gui/chatblockmodel.cpp | 26 ++++++----- gui/chatblockmodel.h | 1 + gui/main.qml | 102 +++++++++++++++++++++-------------------- 3 files changed, 68 insertions(+), 61 deletions(-) diff --git a/gui/chatblockmodel.cpp b/gui/chatblockmodel.cpp index e83dd1d..b2ab05e 100644 --- a/gui/chatblockmodel.cpp +++ b/gui/chatblockmodel.cpp @@ -44,7 +44,7 @@ private: // --- Block Parsing --- const QRegularExpression ChatBlockModel::s_headerRe( - R"(^\[(user|assistant|reasoning|call|tool|error|info)(?::([^\]]*))?\]$)"); + R"(^\[(user|assistant|reasoning|call|tool|error|info|retry)(?::([^\]]*))?\]$)"); ChatBlockModel::ChatBlockModel(QObject *parent) : QAbstractListModel(parent) @@ -64,17 +64,18 @@ QVariant ChatBlockModel::data(const QModelIndex &index, int role) const const ChatBlock &b = m_blocks[index.row()]; switch (role) { - case BlockTypeRole: - switch (b.type) { - case ChatBlock::User: return QStringLiteral("user"); - case ChatBlock::Assistant: return QStringLiteral("assistant"); - case ChatBlock::Reasoning: return QStringLiteral("reasoning"); - case ChatBlock::Call: return QStringLiteral("call"); - case ChatBlock::Tool: return QStringLiteral("tool"); - case ChatBlock::Error: return QStringLiteral("error"); - case ChatBlock::Info: return QStringLiteral("info"); - case ChatBlock::Default: return QStringLiteral("default"); - } + case BlockTypeRole: + switch (b.type) { + case ChatBlock::User: return QStringLiteral("user"); + case ChatBlock::Assistant: return QStringLiteral("assistant"); + case ChatBlock::Reasoning: return QStringLiteral("reasoning"); + case ChatBlock::Call: return QStringLiteral("call"); + case ChatBlock::Tool: return QStringLiteral("tool"); + case ChatBlock::Error: return QStringLiteral("error"); + case ChatBlock::Info: return QStringLiteral("info"); + case ChatBlock::Retry: return QStringLiteral("retry"); + case ChatBlock::Default: return QStringLiteral("default"); + } return {}; case BlockNameRole: return b.name; @@ -257,6 +258,7 @@ void ChatBlockModel::processLine(const QString &line) else if (typeStr == "tool") type = ChatBlock::Tool; else if (typeStr == "error") type = ChatBlock::Error; else if (typeStr == "info") type = ChatBlock::Info; + else if (typeStr == "retry") type = ChatBlock::Retry; else type = ChatBlock::Default; beginInsertRows(QModelIndex(), m_blocks.size(), m_blocks.size()); diff --git a/gui/chatblockmodel.h b/gui/chatblockmodel.h index 5324422..a832e06 100644 --- a/gui/chatblockmodel.h +++ b/gui/chatblockmodel.h @@ -15,6 +15,7 @@ struct ChatBlock { Tool, Error, Info, + Retry, Default }; diff --git a/gui/main.qml b/gui/main.qml index 95913b5..e819448 100644 --- a/gui/main.qml +++ b/gui/main.qml @@ -610,47 +610,50 @@ ApplicationWindow { width: chatView.width - 8 spacing: 2 - property bool blockExpanded: { - switch (blockType) { - case "user": return true - case "assistant": return true - case "tool": return true - case "info": return true - default: return false - } - } + property bool blockExpanded: { + switch (blockType) { + case "user": return true + case "assistant": return true + case "tool": return true + case "info": return true + case "retry": return true + default: return false + } + } // Clickable header Rectangle { Layout.fillWidth: true height: 22 radius: 3 - color: { - var bg = theme.baseColor - if (theme.isDark) { - switch (blockType) { - case "user": return Qt.lighter(bg, 1.8) - case "assistant": return Qt.lighter(bg, 1.5) - case "reasoning": return Qt.lighter(bg, 1.3) - case "call": return Qt.lighter(bg, 1.7) - case "tool": return Qt.lighter(bg, 1.2) - case "error": return Qt.rgba(0.6, 0.15, 0.15, 0.7) - case "info": return Qt.lighter(bg, 1.4) - default: return bg - } - } else { - switch (blockType) { - case "user": return Qt.darker(bg, 1.12) - case "assistant": return Qt.darker(bg, 1.06) - case "reasoning": return Qt.darker(bg, 1.03) - case "call": return Qt.darker(bg, 1.1) - case "tool": return Qt.darker(bg, 1.04) - case "error": return Qt.rgba(1.0, 0.8, 0.8, 0.7) - case "info": return Qt.darker(bg, 1.02) - default: return bg - } - } - } + color: { + var bg = theme.baseColor + if (theme.isDark) { + switch (blockType) { + case "user": return Qt.lighter(bg, 1.8) + case "assistant": return Qt.lighter(bg, 1.5) + case "reasoning": return Qt.lighter(bg, 1.3) + case "call": return Qt.lighter(bg, 1.7) + case "tool": return Qt.lighter(bg, 1.2) + case "error": return Qt.rgba(0.6, 0.15, 0.15, 0.7) + case "info": return Qt.lighter(bg, 1.4) + case "retry": return Qt.rgba(0.6, 0.5, 0.0, 0.5) + default: return bg + } + } else { + switch (blockType) { + case "user": return Qt.darker(bg, 1.12) + case "assistant": return Qt.darker(bg, 1.06) + case "reasoning": return Qt.darker(bg, 1.03) + case "call": return Qt.darker(bg, 1.1) + case "tool": return Qt.darker(bg, 1.04) + case "error": return Qt.rgba(1.0, 0.8, 0.8, 0.7) + case "info": return Qt.darker(bg, 1.02) + case "retry": return Qt.rgba(1.0, 0.9, 0.6, 0.5) + default: return bg + } + } + } MouseArea { anchors.fill: parent @@ -669,20 +672,21 @@ ApplicationWindow { opacity: 0.6 } - Label { - Layout.fillWidth: true - text: { - switch (blockType) { - case "user": return "User" - case "assistant": return "Assistant" + (blockName ? " (" + blockName + ")" : "") - case "reasoning": return "Reasoning" - case "call": return "Call: " + blockName - case "tool": return "Tool: " + blockName - case "error": return "Error" - case "info": return "Info" - default: return "" - } - } + Label { + Layout.fillWidth: true + text: { + switch (blockType) { + case "user": return "User" + case "assistant": return "Assistant" + (blockName ? " (" + blockName + ")" : "") + case "reasoning": return "Reasoning" + case "call": return "Call: " + blockName + case "tool": return "Tool: " + blockName + case "error": return "Error" + case "info": return "Info" + case "retry": return "Retry" + default: return "" + } + } font.pointSize: theme.fontSize > 0 ? theme.fontSize * 0.85 : 11 font.bold: true color: theme.textColor