#pragma once #include #include #include #include namespace ZShell { class Chat; class ChatMessage : public QObject { Q_OBJECT QML_ELEMENT QML_UNCREATABLE("Chat messages are created by the Chat singleton") Q_PROPERTY(Role role READ role NOTIFY roleChanged) Q_PROPERTY(QString content READ content NOTIFY contentChanged) Q_PROPERTY(QString reasoning READ reasoning NOTIFY reasoningChanged) Q_PROPERTY(bool reasoningActive READ reasoningActive NOTIFY reasoningActiveChanged) Q_PROPERTY(qint64 reasoningElapsedMs READ reasoningElapsedMs NOTIFY elapsedMsChanged) Q_PROPERTY(qint64 contentElapsedMs READ contentElapsedMs NOTIFY elapsedMsChanged) Q_PROPERTY(bool streaming READ streaming NOTIFY streamingChanged) Q_PROPERTY(qint64 timestamp READ timestamp CONSTANT) public: enum class Role : int { User = 0, Assistant }; Q_ENUM(Role) explicit ChatMessage( Role role, const QString& content, qint64 timestamp, QObject* parent = nullptr); [[nodiscard]] Role role() const { return m_role; } [[nodiscard]] QString content() const { return m_content; } [[nodiscard]] QString reasoning() const { return m_reasoning; } [[nodiscard]] bool reasoningActive() const { return m_reasoningActive; } [[nodiscard]] qint64 reasoningElapsedMs() const; [[nodiscard]] qint64 contentElapsedMs() const; [[nodiscard]] bool streaming() const { return m_streaming; } [[nodiscard]] qint64 timestamp() const { return m_timestamp; } void appendContent(const QString& piece); void appendReasoning(const QString& piece); void setReasoning(const QString& value); void setElapsedMs(qint64 reasoningMs, qint64 contentMs); void setStreaming(bool value); Q_SIGNALS: void roleChanged(); void contentChanged(); void reasoningChanged(); void reasoningActiveChanged(); void elapsedMsChanged(); void streamingChanged(); private: void updateReasoningActive(); [[nodiscard]] bool reasoningInFlight() const { return m_reasoningStartedAt > 0 && m_reasoningEndedAt <= 0; } [[nodiscard]] bool contentInFlight() const { return m_contentStartedAt > 0 && m_contentEndedAt <= 0; } QTimer m_timer; Role m_role; QString m_content; QString m_reasoning; bool m_reasoningActive = false; bool m_streaming = false; qint64 m_timestamp; qint64 m_reasoningStartedAt = 0; qint64 m_reasoningEndedAt = 0; qint64 m_contentStartedAt = 0; qint64 m_contentEndedAt = 0; friend class Chat; }; } // namespace ZShell