| 123 | } |
| 124 | |
| 125 | QFuture<LLMQore::ToolResult> ReadOriginalHistoryTool::executeAsync(const QJsonObject &input) |
| 126 | { |
| 127 | QString sessionPath; |
| 128 | { |
| 129 | QMutexLocker locker(&m_mutex); |
| 130 | sessionPath = m_currentSessionId; |
| 131 | } |
| 132 | |
| 133 | return QtConcurrent::run([input, sessionPath]() -> LLMQore::ToolResult { |
| 134 | if (sessionPath.isEmpty()) { |
| 135 | throw LLMQore::ToolRuntimeError( |
| 136 | "No active chat session, cannot locate pre-compression history."); |
| 137 | } |
| 138 | |
| 139 | const QString rootPath = resolveRootHistoryPath(sessionPath); |
| 140 | if (rootPath.isEmpty()) { |
| 141 | return LLMQore::ToolResult::text( |
| 142 | "This conversation was never compressed; there is no separate " |
| 143 | "pre-compression history. The messages already in context are the full " |
| 144 | "history."); |
| 145 | } |
| 146 | |
| 147 | const QJsonObject root = readJsonObject(rootPath); |
| 148 | const QJsonArray messages = root.value("messages").toArray(); |
| 149 | |
| 150 | const QString query = input.value("query").toString().trimmed(); |
| 151 | const QString roleFilter = input.value("role").toString().trimmed().toLower(); |
| 152 | const int offset = qMax(0, input.value("offset").toInt(0)); |
| 153 | const int limit = qBound(1, input.value("limit").toInt(20), 200); |
| 154 | |
| 155 | QStringList matched; |
| 156 | int matchCount = 0; |
| 157 | for (int i = 0; i < messages.size(); ++i) { |
| 158 | const QJsonObject msg = messages.at(i).toObject(); |
| 159 | const QString role = roleName(msg.value("role").toInt()); |
| 160 | const QString content = msg.value("content").toString(); |
| 161 | |
| 162 | if (!roleFilter.isEmpty() && role != roleFilter) |
| 163 | continue; |
| 164 | if (!query.isEmpty() && !content.contains(query, Qt::CaseInsensitive)) |
| 165 | continue; |
| 166 | |
| 167 | ++matchCount; |
| 168 | if (matchCount <= offset || matched.size() >= limit) |
| 169 | continue; |
| 170 | |
| 171 | matched.append(QString("[#%1 %2]\n%3").arg(i).arg(role, content)); |
| 172 | } |
| 173 | |
| 174 | const int shown = matched.size(); |
| 175 | QString header = QString("Pre-compression history (%1): %2 matching message(s)") |
| 176 | .arg(rootPath) |
| 177 | .arg(matchCount); |
| 178 | if (shown < matchCount || offset > 0) { |
| 179 | header += QString(", showing %1-%2") |
| 180 | .arg(offset + 1) |
| 181 | .arg(offset + shown); |
| 182 | } |
nothing calls this directly
no test coverage detected