165 lines
7.8 KiB
C++
165 lines
7.8 KiB
C++
#ifndef OLLIE9PCLIENT_H
|
|
#define OLLIE9PCLIENT_H
|
|
|
|
#include <QObject>
|
|
#include <QVariantList>
|
|
#include <QHash>
|
|
#include <QSet>
|
|
#include <QTimer>
|
|
#include <QQmlEngine>
|
|
|
|
#include "lib9pclient.h"
|
|
#include "lib9pstreamer.h"
|
|
|
|
// 9P-based client for ollie. Uses native libollie9p for all operations.
|
|
// Streaming files (chat, event) use Lib9pStreamer threads.
|
|
class Ollie9pClient : public QObject
|
|
{
|
|
Q_OBJECT
|
|
QML_ELEMENT
|
|
QML_SINGLETON
|
|
|
|
Q_PROPERTY(QVariantList sessions READ sessions NOTIFY sessionsChanged)
|
|
Q_PROPERTY(QString activeSessionId READ activeSessionId WRITE setActiveSessionId NOTIFY activeSessionIdChanged)
|
|
Q_PROPERTY(QString activeAgentId READ activeAgentId NOTIFY activeAgentIdChanged)
|
|
Q_PROPERTY(QString activeState READ activeState NOTIFY activeStateChanged)
|
|
Q_PROPERTY(bool activeSessionPaused READ activeSessionPaused NOTIFY activeSessionPausedChanged)
|
|
Q_PROPERTY(bool rootBackendsLoaded READ rootBackendsLoaded NOTIFY rootBackendsLoadedChanged)
|
|
Q_PROPERTY(QStringList availableBackends READ availableBackends NOTIFY availableBackendsChanged)
|
|
Q_PROPERTY(bool rootAgentsLoaded READ rootAgentsLoaded NOTIFY rootAgentsLoadedChanged)
|
|
Q_PROPERTY(QStringList availableAgents READ availableAgents NOTIFY availableAgentsChanged)
|
|
Q_PROPERTY(bool workflowsLoaded READ workflowsLoaded NOTIFY workflowsLoadedChanged)
|
|
Q_PROPERTY(QStringList availableWorkflows READ availableWorkflows NOTIFY availableWorkflowsChanged)
|
|
Q_PROPERTY(bool rootModelsLoaded READ rootModelsLoaded NOTIFY rootModelsLoadedChanged)
|
|
Q_PROPERTY(QString currentBackend READ currentBackend WRITE setCurrentBackend NOTIFY currentBackendChanged)
|
|
Q_PROPERTY(bool daemonConnected READ daemonConnected NOTIFY daemonConnectedChanged)
|
|
|
|
public:
|
|
explicit Ollie9pClient(QObject *parent = nullptr);
|
|
~Ollie9pClient();
|
|
|
|
QVariantList sessions() const { return m_sessions; }
|
|
QString activeSessionId() const { return m_activeSessionId; }
|
|
Q_INVOKABLE void setActiveSessionId(const QString &id);
|
|
QString activeAgentId() const { return m_agentId; }
|
|
QString activeState() const { return m_activeState; }
|
|
bool activeSessionPaused() const { return m_activeSessionPaused; }
|
|
|
|
bool rootBackendsLoaded() const { return m_rootBackendsLoaded; }
|
|
QStringList availableBackends() const { return m_availableBackends; }
|
|
bool rootAgentsLoaded() const { return m_rootAgentsLoaded; }
|
|
QStringList availableAgents() const { return m_availableAgents; }
|
|
bool workflowsLoaded() const { return m_workflowsLoaded; }
|
|
QStringList availableWorkflows() const { return m_availableWorkflows; }
|
|
bool rootModelsLoaded() const { return m_rootModelsLoaded; }
|
|
QString currentBackend() const { return m_currentBackend; }
|
|
bool daemonConnected() const { return m_daemonConnected; }
|
|
Q_INVOKABLE QString agentState(const QString &sessionId, const QString &agentId) const;
|
|
Q_INVOKABLE QString sessionConnectionColor(const QString &sessionId) const;
|
|
Q_INVOKABLE int pendingBypassCount(const QString &sessionId, const QString &agentId) const;
|
|
Q_INVOKABLE void setCurrentBackend(const QString &backend) {
|
|
if (m_currentBackend == backend) return;
|
|
m_currentBackend = backend;
|
|
emit currentBackendChanged();
|
|
}
|
|
|
|
Q_INVOKABLE void refreshSessions();
|
|
Q_INVOKABLE QString readLog();
|
|
Q_INVOKABLE QString readLogForSession(const QString &sessionId, const QString &agentId);
|
|
Q_INVOKABLE bool submit(const QString &prompt);
|
|
Q_INVOKABLE bool interrupt();
|
|
Q_INVOKABLE bool kill();
|
|
Q_INVOKABLE bool killSession(const QString &sessionId);
|
|
Q_INVOKABLE bool pauseSession(const QString &sessionId);
|
|
Q_INVOKABLE bool resumeSession(const QString &sessionId);
|
|
Q_INVOKABLE bool isSessionPaused(const QString &sessionId) const;
|
|
Q_INVOKABLE QString getConfig();
|
|
Q_INVOKABLE QStringList getAgents(const QString &sessionId);
|
|
|
|
QString agentKey(const QString &sessionId, const QString &agentId) const;
|
|
Q_INVOKABLE void setActiveAgentId(const QString &agentId);
|
|
Q_INVOKABLE void switchAgent(const QString &sessionId, const QString &agentId);
|
|
Q_INVOKABLE void loadRootBackends();
|
|
Q_INVOKABLE void loadRootAgents();
|
|
Q_INVOKABLE void loadWorkflows();
|
|
Q_INVOKABLE QStringList variantsForWorkflow(const QString &workflow) const;
|
|
Q_INVOKABLE QStringList getAvailableModels(const QString &backend) const;
|
|
Q_INVOKABLE bool createQuickSession();
|
|
Q_INVOKABLE QString createSession(const QString &name, const QString &remote, const QString &cwd = QString(), const QString &workflow = QString(), const QString &variant = QString(), bool yolo = false);
|
|
Q_INVOKABLE QVariantMap readSessionConfig(const QString &sessionName) const;
|
|
Q_INVOKABLE QString updateSessionConfig(const QString &sessionName, const QString &key, const QString &value);
|
|
Q_INVOKABLE void setGoal(const QString &sessionName, const QString &goalText);
|
|
Q_INVOKABLE QString createAgent(const QString &sessionId, const QString &backend, const QString &model, const QString &agent, const QString &remote, const QString &agentAlias);
|
|
Q_INVOKABLE bool killAgent(const QString &sessionId, const QString &agentId);
|
|
Q_INVOKABLE bool renameSession(const QString &sessionId, const QString &newName);
|
|
Q_INVOKABLE bool renameAgent(const QString &sessionId, const QString &agentId, const QString &newName);
|
|
Q_INVOKABLE bool resolveBypass(const QString &sessionId, const QString &agentId, const QString &id, bool approve);
|
|
Q_INVOKABLE QString lastError() const { return m_9p ? m_9p->lastError() : QString(); }
|
|
|
|
signals:
|
|
void sessionsChanged();
|
|
void activeSessionIdChanged();
|
|
void activeAgentIdChanged();
|
|
void activeStateChanged();
|
|
void activeSessionPausedChanged();
|
|
void agentStateChanged(const QString &sessionId, const QString &agentId, const QString &state);
|
|
void chatReceived(const QString &text);
|
|
void bypassRequested(const QString &sessionId, const QString &agentId, const QString &id, const QString &cmd, const QString &cwd);
|
|
void bypassResolved(const QString &sessionId, const QString &agentId);
|
|
void pendingBypassCountChanged(const QString &sessionId, const QString &agentId);
|
|
void rootBackendsLoadedChanged();
|
|
void availableBackendsChanged();
|
|
void rootAgentsLoadedChanged();
|
|
void availableAgentsChanged();
|
|
void workflowsLoadedChanged();
|
|
void availableWorkflowsChanged();
|
|
void rootModelsLoadedChanged();
|
|
void currentBackendChanged();
|
|
void daemonConnectedChanged();
|
|
|
|
private:
|
|
void stopAgentStreams();
|
|
void stopStreams();
|
|
QString agentPath() const;
|
|
void ensureRootDataLoaded();
|
|
void setDaemonConnected(bool connected);
|
|
void startActiveAgentStreams();
|
|
void startEventStream();
|
|
void handleEvent(const QString &eventLine);
|
|
void heartbeat();
|
|
void checkPendingBypass();
|
|
|
|
Lib9pClient *m_9p = nullptr;
|
|
QTimer *m_heartbeatTimer = nullptr;
|
|
|
|
QVariantList m_sessions;
|
|
QString m_activeSessionId;
|
|
QString m_activeState = "idle";
|
|
QString m_agentId;
|
|
bool m_activeSessionPaused = false;
|
|
|
|
// Root data cache
|
|
bool m_rootBackendsLoaded = false;
|
|
QStringList m_availableBackends;
|
|
bool m_rootAgentsLoaded = false;
|
|
QStringList m_availableAgents;
|
|
bool m_workflowsLoaded = false;
|
|
QStringList m_availableWorkflows;
|
|
QHash<QString, QStringList> m_workflowVariants;
|
|
bool m_rootModelsLoaded = false;
|
|
QVariantMap m_rootModels;
|
|
QString m_currentBackend;
|
|
bool m_daemonConnected = false;
|
|
|
|
// Agent state cache — updated via delta events
|
|
QHash<QString, QString> m_agentStateValues;
|
|
|
|
// Pending bypass requests per agent: agentKey -> set of bypass IDs
|
|
QHash<QString, QSet<QString>> m_pendingBypasses;
|
|
|
|
// Native streaming readers
|
|
Lib9pStreamer *m_chat = nullptr; // Guarded — reads agent chat log
|
|
Lib9pStreamer *m_event = nullptr; // Looping — reads server event (includes state changes)
|
|
};
|
|
|
|
#endif // OLLIE9PCLIENT_H
|