#pragma once #include "generation.hpp" #include #include #include #include namespace ZShell::llm { class ChatMessage : public QObject { Q_OBJECT QML_ELEMENT QML_UNCREATABLE("Chat messages are created by the Chat singleton") Q_PROPERTY(Role role READ role CONSTANT) Q_PROPERTY(qint64 timestamp READ timestamp CONSTANT) Q_PROPERTY( int generationCount READ generationCount NOTIFY generationsChanged) Q_PROPERTY( QList generations READ generations NOTIFY generationsChanged) Q_PROPERTY( ZShell::llm::ChatGeneration* activeGeneration READ activeGeneration NOTIFY activeGenerationChanged) Q_PROPERTY( int activeGenerationIndex READ activeGenerationIndex NOTIFY activeGenerationChanged) public: enum class Role : int { User = 0, Assistant }; Q_ENUM(Role) explicit ChatMessage(Role role, qint64 timestamp, QObject* parent = nullptr); [[nodiscard]] Role role() const { return m_role; } [[nodiscard]] qint64 timestamp() const { return m_timestamp; } [[nodiscard]] int generationCount() const { return static_cast(m_generations.size()); } [[nodiscard]] QList generations() const { return m_generations; } [[nodiscard]] ChatGeneration* activeGeneration() const { return generation(m_active); } [[nodiscard]] int activeGenerationIndex() const { return m_active; } [[nodiscard]] ChatGeneration* generation(int index) const { if (index < 0 || index >= m_generations.size()) return nullptr; return m_generations.at(index); } Q_INVOKABLE void setActiveGeneration(int index); Q_INVOKABLE void edit(const QString& newContent); Q_INVOKABLE void retry(); Q_INVOKABLE void generate(); ChatGeneration* addGeneration(qint64 timestamp); ChatGeneration* appendGeneration(qint64 timestamp); void removeGeneration(ChatGeneration* generation); Q_SIGNALS: void generationsChanged(); void activeGenerationChanged(); private: void setActiveInternal(int index); Role m_role; qint64 m_timestamp; QList m_generations; int m_active = -1; }; } // namespace ZShell::llm