Files
z-bar-qt/Plugins/ZShell/Llm/session.hpp
T
2026-08-26 17:10:34 +02:00

116 lines
3.5 KiB
C++

#pragma once
#include "messagemodel.hpp"
#include "message.hpp"
#include <QDateTime>
#include <QObject>
#include <QString>
#include <QtQml>
namespace ZShell::llm {
class LlmClient;
class ChatSession : public QObject {
Q_OBJECT
QML_ELEMENT
QML_UNCREATABLE("Chat sessions are managed by Chat.chats")
Q_PROPERTY(QString id READ id CONSTANT)
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
Q_PROPERTY(QString icon READ icon NOTIFY iconChanged)
Q_PROPERTY(QDateTime createdAt READ createdAt CONSTANT)
Q_PROPERTY(QDateTime updatedAt READ updatedAt NOTIFY updatedAtChanged)
Q_PROPERTY(bool pinned READ pinned NOTIFY pinnedChanged)
Q_PROPERTY(bool loaded READ isLoaded NOTIFY loaded)
Q_PROPERTY(int messageCount READ messageCount NOTIFY messageCountChanged)
Q_PROPERTY(
ZShell::llm::ChatMessageModel* messagesModel READ messagesModel CONSTANT)
public:
explicit ChatSession(const QString& id, QObject* parent = nullptr);
[[nodiscard]] QString id() const { return m_id; }
[[nodiscard]] QString title() const { return m_title; }
[[nodiscard]] QString icon() const { return m_icon; }
[[nodiscard]] QDateTime createdAt() const {
return QDateTime::fromMSecsSinceEpoch(m_createdAt);
}
[[nodiscard]] QDateTime updatedAt() const {
return QDateTime::fromMSecsSinceEpoch(m_updatedAt);
}
[[nodiscard]] qint64 createdAtMs() const { return m_createdAt; }
[[nodiscard]] qint64 updatedAtMs() const { return m_updatedAt; }
[[nodiscard]] bool pinned() const { return m_pinned; }
[[nodiscard]] int messageCount() const { return m_messageCount; }
// The messages model; the first access starts the (async) load
// from the store.
[[nodiscard]] ChatMessageModel* messagesModel();
void ensureLoaded();
// True once the async load from the store has finished.
[[nodiscard]] bool isLoaded() const { return m_loaded; }
// The model without triggering a load (ChatStore use during the
// load itself).
[[nodiscard]] ChatMessageModel* model() const { return m_model; }
void markLoaded();
[[nodiscard]] bool takeClearPending();
[[nodiscard]] LlmClient* client() const;
[[nodiscard]] int lastTokenCount() const { return m_lastTokenCount; }
void setLastTokenCount(int value);
void setTitle(const QString& value);
void setIcon(const QString& value);
void setUpdatedAt(qint64 value);
void setPinned(bool value);
void setMeta(
const QString& title,
qint64 createdAt,
qint64 updatedAt,
int messageCount);
// Replaces the model's rows with `messages` (most recent first).
void adoptMessages(QList<ChatMessage*> messages);
void persist();
void removeMessage(ChatMessage* message);
void clearMessages();
Q_INVOKABLE void sendMessage(const QString& text);
Q_INVOKABLE void retry(ZShell::llm::ChatMessage* target);
Q_INVOKABLE void continueFrom(ZShell::llm::ChatMessage* message);
Q_INVOKABLE void clear();
Q_SIGNALS:
void titleChanged();
void iconChanged();
void updatedAtChanged();
void pinnedChanged();
void messageCountChanged();
// The messages finished loading from the store.
void loaded();
private:
void onModelRowsChanged();
ChatMessage* appendNewest(
ChatMessage::Role role, const QString& content, qint64 timestamp);
void startGeneration(ChatMessage* target);
void setCount(int value);
QString m_id;
QString m_title;
QString m_icon;
qint64 m_createdAt = 0;
qint64 m_updatedAt = 0;
bool m_pinned = false;
int m_messageCount = 0;
ChatMessageModel* m_model = nullptr;
bool m_loadRequested = false;
bool m_loaded = false;
bool m_clearPending = false;
int m_lastTokenCount = 0;
};
} // namespace ZShell::llm