diff --git a/gui/ChatPane.qml b/gui/ChatPane.qml index cb188b0..98f90fa 100644 --- a/gui/ChatPane.qml +++ b/gui/ChatPane.qml @@ -706,7 +706,7 @@ Item { font.pixelSize: 14 implicitWidth: 28 implicitHeight: 28 - onClicked: dbus.react(paneRoot.sessionId, modelData.emoji) + onClicked: dbus.reactTo(paneRoot.sessionId, block.responseId, modelData.emoji) ToolTip.text: modelData.tip ToolTip.visible: hovered } diff --git a/gui/chatblockmodel.cpp b/gui/chatblockmodel.cpp index 9cfb5b0..50eb5cb 100644 --- a/gui/chatblockmodel.cpp +++ b/gui/chatblockmodel.cpp @@ -64,6 +64,8 @@ QVariant ChatBlockModel::data(const QModelIndex &index, int role) const return block.name; case ContentRole: return block.content; + case ResponseIdRole: + return block.responseId; case SubBlocksRole: if (block.cachedContent != block.content) { block.cachedSubBlocks = parseSubBlocks(block.content); @@ -102,6 +104,7 @@ QHash ChatBlockModel::roleNames() const {ContentRole, "blockContent"}, {SubBlocksRole, "subBlocks"}, {FormattedContentRole, "formattedContent"}, + {ResponseIdRole, "responseId"}, }; } @@ -174,7 +177,8 @@ void ChatBlockModel::updateVisibleWindow() for (int i = 0; i < commonCount; ++i) { if (m_blocks[i].content != newBlocks[i].content || m_blocks[i].type != newBlocks[i].type || - m_blocks[i].name != newBlocks[i].name) { + m_blocks[i].name != newBlocks[i].name || + m_blocks[i].responseId != newBlocks[i].responseId) { firstDiff = i; break; } @@ -228,7 +232,7 @@ QList ChatBlockModel::parseBlocks(const QString &text) const QList blocks; if (text.isEmpty()) return blocks; - // Block headers: [user], [assistant], [reasoning], [call:name], [tool:name], [error], [info] msg + // Block headers: [user], [assistant:id], [reasoning], [call:name], etc. static const QRegularExpression headerRe( R"(^\[(user|assistant|reasoning|call|tool|error|info)(?::([^\]]*))?\](.*)$)", QRegularExpression::MultilineOption); @@ -280,7 +284,10 @@ QList ChatBlockModel::parseBlocks(const QString &text) const else if (typeStr == "error") b.type = ChatBlock::Error; else if (typeStr == "info") b.type = ChatBlock::Info; - b.name = name; + if (b.type == ChatBlock::Assistant) + b.responseId = name; + else + b.name = name; b.content = content; blocks.append(b); } diff --git a/gui/chatblockmodel.h b/gui/chatblockmodel.h index 23fd929..1bd3369 100644 --- a/gui/chatblockmodel.h +++ b/gui/chatblockmodel.h @@ -18,8 +18,9 @@ struct ChatBlock { }; Type type; - QString name; // tool/call name, empty for others - QString content; // raw text content + QString name; // tool/call name, empty for others + QString responseId; // stable assistant response ID + QString content; // raw text content mutable QVariantList cachedSubBlocks; // cached parseSubBlocks result mutable QString cachedContent; // content when subBlocks were cached }; @@ -51,6 +52,7 @@ public: ContentRole, SubBlocksRole, // QVariantList of sub-block maps FormattedContentRole, // pre-formatted HTML for call/tool expanded view + ResponseIdRole, }; explicit ChatBlockModel(QObject *parent = nullptr); diff --git a/gui/main-kf5.qml b/gui/main-kf5.qml index 7102dbc..f9ba6d4 100644 --- a/gui/main-kf5.qml +++ b/gui/main-kf5.qml @@ -1531,7 +1531,7 @@ ApplicationWindow { font.pixelSize: 14 implicitWidth: 28 implicitHeight: 28 - onClicked: dbus.react(paneRoot.sessionId, modelData.emoji) + onClicked: dbus.reactTo(paneRoot.sessionId, block.responseId, modelData.emoji) ToolTip.text: modelData.tip ToolTip.visible: hovered } diff --git a/plasmoid/plugin/olliedbusclient.cpp b/plasmoid/plugin/olliedbusclient.cpp index 6e4b0fd..5ec51ab 100644 --- a/plasmoid/plugin/olliedbusclient.cpp +++ b/plasmoid/plugin/olliedbusclient.cpp @@ -463,6 +463,12 @@ bool OllieDBusClient::react(const QString &sessionId, const QString &emoji) return true; } +bool OllieDBusClient::reactTo(const QString &sessionId, const QString &responseId, const QString &emoji) +{ + m_iface->asyncCall("ReactTo", sessionId, responseId, emoji); + return true; +} + bool OllieDBusClient::interrupt(const QString &sessionId) { m_iface->asyncCall("Interrupt", sessionId); diff --git a/plasmoid/plugin/olliedbusclient.h b/plasmoid/plugin/olliedbusclient.h index 96e7dc3..46db08a 100644 --- a/plasmoid/plugin/olliedbusclient.h +++ b/plasmoid/plugin/olliedbusclient.h @@ -54,6 +54,7 @@ public: Q_INVOKABLE bool setConfig(const QString &sessionId, const QString &key, const QString &value); Q_INVOKABLE bool submit(const QString &sessionId, const QString &prompt); Q_INVOKABLE bool react(const QString &sessionId, const QString &emoji); + Q_INVOKABLE bool reactTo(const QString &sessionId, const QString &responseId, const QString &emoji); Q_INVOKABLE bool interrupt(const QString &sessionId); Q_INVOKABLE QStringList listBackends(); Q_INVOKABLE QStringList listModels(const QString &sessionId);