better chat list view + anchor to bottom. sqlite db for chats + LIFO-ordered
This commit is contained in:
+15
-61
@@ -1,23 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QtQml>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "chatstore.hpp"
|
||||
|
||||
class QQmlEngine;
|
||||
class QJSEngine;
|
||||
class QNetworkReply;
|
||||
|
||||
namespace ZShell {
|
||||
namespace ZShell::llm {
|
||||
|
||||
class LlmClient;
|
||||
|
||||
// QML-facing facade. Persistence lives in ChatStore, network streaming in
|
||||
// LlmClient; this class only wires them together and exposes the
|
||||
// application-wide state.
|
||||
class Chat : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
@@ -29,27 +28,22 @@ class Chat : public QObject {
|
||||
Q_PROPERTY(QStringList availableModels READ availableModels NOTIFY availableModelsChanged)
|
||||
Q_PROPERTY(int contextSize READ contextSize NOTIFY contextSizeChanged)
|
||||
Q_PROPERTY(QString lastError READ lastError NOTIFY lastErrorChanged)
|
||||
Q_PROPERTY(ChatStore* chats READ chats CONSTANT)
|
||||
Q_PROPERTY(ZShell::llm::ChatStore* chats READ chats CONSTANT)
|
||||
Q_PROPERTY(QString streamingChatId READ streamingChatId NOTIFY streamingChatIdChanged)
|
||||
|
||||
public:
|
||||
explicit Chat(QObject* parent = nullptr);
|
||||
~Chat();
|
||||
|
||||
[[nodiscard]] bool busy() const { return m_busy; }
|
||||
[[nodiscard]] QString endpoint() const { return m_endpoint; }
|
||||
[[nodiscard]] QString model() const { return m_model; }
|
||||
[[nodiscard]] QStringList availableModels() const { return m_availableModels; }
|
||||
[[nodiscard]] int contextSize() const { return m_contextSize; }
|
||||
[[nodiscard]] int lastTokenCount() const { return m_lastTokenCount; }
|
||||
[[nodiscard]] bool busy() const;
|
||||
[[nodiscard]] QString endpoint() const;
|
||||
[[nodiscard]] QString model() const;
|
||||
[[nodiscard]] QStringList availableModels() const;
|
||||
[[nodiscard]] int contextSize() const;
|
||||
[[nodiscard]] QString lastError() const { return m_lastError; }
|
||||
[[nodiscard]] ChatStore* chats() const { return m_store; }
|
||||
[[nodiscard]] QString streamingChatId() const { return m_streamingChatId; }
|
||||
[[nodiscard]] ChatSession* streamingSession() const { return m_active; }
|
||||
[[nodiscard]] QString streamingChatId() const;
|
||||
|
||||
Q_INVOKABLE void send(const QString& chatId, const QString& content);
|
||||
Q_INVOKABLE void stop();
|
||||
Q_INVOKABLE void clearConversation(const QString& chatId);
|
||||
Q_INVOKABLE void dismissError();
|
||||
Q_INVOKABLE void refreshModels();
|
||||
Q_INVOKABLE void selectModel(const QString& id);
|
||||
@@ -67,51 +61,11 @@ class Chat : public QObject {
|
||||
void streamingChatIdChanged();
|
||||
|
||||
private:
|
||||
void beginAssistant();
|
||||
void endStream();
|
||||
void finalize();
|
||||
void fail(const QString& message);
|
||||
void handleLine(const QByteArray& line);
|
||||
void drainBuffer();
|
||||
void probeContextSize();
|
||||
void setContextSize(int size);
|
||||
void updateTokenUsage(const QJsonObject& data);
|
||||
static void trimHistory(ChatSession* session, int contextSize);
|
||||
|
||||
void shortRequest(
|
||||
const QString& tag,
|
||||
const QString& systemPrompt,
|
||||
const QString& userText,
|
||||
std::function<void(QString result)> onResult);
|
||||
void requestTitle(const QString& chatId, const QString& userText);
|
||||
void requestIcon(const QString& chatId, const QString& userText);
|
||||
static QString titleFrom(const QString& content);
|
||||
static QString completionsPath(const QString& endpoint, const QString& subpath);
|
||||
static QString serverErrorMessage(
|
||||
const QByteArray& body, const QString& fallback);
|
||||
static void setBusy(Chat* chat, bool value);
|
||||
static void setStreamingChatId(Chat* chat, const QString& id);
|
||||
|
||||
QNetworkAccessManager m_manager;
|
||||
ChatStore* m_store = nullptr;
|
||||
QNetworkReply* m_reply = nullptr;
|
||||
QByteArray m_buffer;
|
||||
ChatSession* m_active = nullptr;
|
||||
ChatMessage* m_streaming = nullptr;
|
||||
QString m_pendingClearChatId;
|
||||
bool m_busy = false;
|
||||
QString m_endpoint;
|
||||
QString m_model;
|
||||
QStringList m_availableModels;
|
||||
LlmClient* m_client = nullptr;
|
||||
QString m_lastError;
|
||||
QString m_streamingChatId;
|
||||
double m_temperature = 0.7;
|
||||
int m_contextSize = 0;
|
||||
int m_lastTokenCount = 0;
|
||||
|
||||
static Chat* s_instance;
|
||||
|
||||
friend class ChatStore;
|
||||
};
|
||||
|
||||
} // namespace ZShell
|
||||
} // namespace ZShell::llm
|
||||
|
||||
Reference in New Issue
Block a user