Files
z-bar-qt/Plugins/ZShell/Llm/session.cpp
T

151 lines
4.0 KiB
C++

#include "session.hpp"
#include <QDebug>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
namespace ZShell {
ChatSession::ChatSession(const QString& id, QObject* parent)
: QObject(parent), m_id(id) {
}
void ChatSession::setTitle(const QString& value) {
if (m_title == value)
return;
m_title = value;
Q_EMIT titleChanged();
}
void ChatSession::setUpdatedAt(qint64 value) {
if (m_updatedAt == value)
return;
m_updatedAt = value;
Q_EMIT updatedAtChanged();
}
void ChatSession::setCount(int value) {
if (m_messageCount == value)
return;
m_messageCount = value;
Q_EMIT messageCountChanged();
}
void ChatSession::setMeta(
const QString& title,
qint64 createdAt,
qint64 updatedAt,
int messageCount) {
m_title = title;
m_createdAt = createdAt;
m_updatedAt = updatedAt;
m_messageCount = messageCount;
}
void ChatSession::ensureLoaded() {
if (m_loaded || m_path.isEmpty())
return;
m_loaded = true;
loadMessages();
}
void ChatSession::loadMessages() {
QFile file(m_path);
if (file.open(QIODevice::ReadOnly)) {
const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
file.close();
if (doc.isObject()) {
const QJsonObject obj = doc.object();
m_title = obj["title"].toString(m_title);
m_createdAt = obj["createdAt"].toVariant().toLongLong() || m_createdAt;
m_updatedAt = obj["updatedAt"].toVariant().toLongLong() || m_updatedAt;
for (const QJsonValue& value : obj["messages"].toArray()) {
const QJsonObject msg = value.toObject();
const QString content = msg["content"].toString();
const QString reasoning = msg["reasoning"].toString();
if (content.isEmpty() && reasoning.isEmpty())
continue;
auto* message = new ChatMessage(
msg["role"].toString() == "user" ? ChatMessage::Role::User
: ChatMessage::Role::Assistant,
content,
msg["timestamp"].toVariant().toLongLong(),
this);
message->setReasoning(reasoning);
message->setElapsedMs(
msg["reasoningElapsedMs"].toVariant().toLongLong(),
msg["contentElapsedMs"].toVariant().toLongLong());
m_messages.append(message);
}
}
} else {
qWarning() << "ChatSession: failed to load" << m_path << ":"
<< file.errorString();
}
setCount(int(m_messages.size()));
Q_EMIT titleChanged();
Q_EMIT messagesChanged();
}
ChatMessage* ChatSession::appendMessage(
ChatMessage::Role role, const QString& content, qint64 timestamp) {
ensureLoaded();
auto* message = new ChatMessage(role, content, timestamp, this);
m_messages.append(message);
setCount(int(m_messages.size()));
Q_EMIT messagesChanged();
return message;
}
void ChatSession::removeMessage(ChatMessage* message) {
if (!message || !m_messages.removeOne(message))
return;
delete message;
setCount(int(m_messages.size()));
Q_EMIT messagesChanged();
}
void ChatSession::clearMessages() {
ensureLoaded();
if (m_messages.isEmpty())
return;
qDeleteAll(m_messages);
m_messages.clear();
setCount(0);
Q_EMIT messagesChanged();
}
QJsonObject ChatSession::document() {
ensureLoaded();
QJsonArray arr;
for (const auto* message : m_messages) {
QJsonObject messageObj;
messageObj[QStringLiteral("role")] =
message->role() == ChatMessage::Role::User
? QStringLiteral("user")
: QStringLiteral("assistant");
messageObj[QStringLiteral("content")] = message->content();
if (!message->reasoning().isEmpty())
messageObj[QStringLiteral("reasoning")] = message->reasoning();
const qint64 reasoningMs = message->reasoningElapsedMs();
if (reasoningMs > 0)
messageObj[QStringLiteral("reasoningElapsedMs")] = reasoningMs;
const qint64 contentMs = message->contentElapsedMs();
if (contentMs > 0)
messageObj[QStringLiteral("contentElapsedMs")] = contentMs;
messageObj[QStringLiteral("timestamp")] = message->timestamp();
arr.append(messageObj);
}
QJsonObject doc;
doc[QStringLiteral("id")] = m_id;
doc[QStringLiteral("title")] = m_title;
doc[QStringLiteral("createdAt")] = m_createdAt;
doc[QStringLiteral("updatedAt")] = m_updatedAt;
doc[QStringLiteral("messages")] = arr;
return doc;
}
} // namespace ZShell