From 22980e376a6807935ddb5cd84ab5ae032edce301 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Tue, 4 Aug 2026 16:23:04 +0200 Subject: [PATCH] gui: track all agent states via revision counter for proper QML binding - Add agentStateRevision property that increments on any state change - QML binds to revision to trigger re-evaluation of agentState() calls - All agent dots now show correct live state, not just active agent --- gui/main.qml | 17 ++++++++--------- gui/ollie9pclient.cpp | 4 ++++ gui/ollie9pclient.h | 4 ++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/gui/main.qml b/gui/main.qml index 37454b7..8980271 100644 --- a/gui/main.qml +++ b/gui/main.qml @@ -1125,7 +1125,10 @@ ApplicationWindow { Layout.alignment: Qt.AlignVCenter radius: 4 visible: type !== "header" + // Bind to revision so we re-evaluate when any agent state changes + property int _rev: ollie.agentStateRevision color: { + void(_rev) // force dependency if (type === "session") { var cc = connectionColor || "gray" if (cc === "green") return "#4caf50" @@ -1133,16 +1136,12 @@ ApplicationWindow { if (cc === "red") return "#f44336" return "#9e9e9e" } - // Agent: match top indicator exactly when this is the active agent - if (agentId === ollie.activeAgentId && parentId === ollie.activeSessionId) { - if (ollie.isSessionPaused(ollie.activeSessionId)) return "#9e9e9e" - if (ollie.activeState === "idle") return "#4caf50" - if (ollie.activeState.startsWith("calling")) return "#ff9800" - return "#2196f3" - } - // Non-active agent: gray if paused, green otherwise + // Agent: gray if paused, else state color if (ollie.isSessionPaused(parentId)) return "#9e9e9e" - return "#4caf50" + var s = ollie.agentState(parentId, agentId) + if (s === "idle") return "#4caf50" + if (s.startsWith("calling")) return "#ff9800" + return "#2196f3" } } } diff --git a/gui/ollie9pclient.cpp b/gui/ollie9pclient.cpp index c94323a..f94c71d 100644 --- a/gui/ollie9pclient.cpp +++ b/gui/ollie9pclient.cpp @@ -212,7 +212,9 @@ void Ollie9pClient::handleEvent(const QString &eventLine) const QString aidStr = agentId.toString(); const QString key = agentKey(sidStr, aidStr); m_agentStateValues[key] = payloadStr; + ++m_agentStateRevision; emit agentStateChanged(sidStr, aidStr, payloadStr); + emit agentStateRevisionChanged(); emit activeStateChanged(); } else { // Non-active agent: need to check cache @@ -226,7 +228,9 @@ void Ollie9pClient::handleEvent(const QString &eventLine) if (it != m_agentStateValues.end() && it.value() == payloadStr) return; m_agentStateValues[key] = payloadStr; + ++m_agentStateRevision; emit agentStateChanged(sidStr, aidStr, payloadStr); + emit agentStateRevisionChanged(); } } else if (agentAction == QLatin1String("new") || agentAction == QLatin1String("kill")) { refreshSessions(); diff --git a/gui/ollie9pclient.h b/gui/ollie9pclient.h index 24e79c6..a0c6b68 100644 --- a/gui/ollie9pclient.h +++ b/gui/ollie9pclient.h @@ -34,6 +34,7 @@ class Ollie9pClient : public QObject 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) + Q_PROPERTY(int agentStateRevision READ agentStateRevision NOTIFY agentStateRevisionChanged) public: explicit Ollie9pClient(QObject *parent = nullptr); @@ -52,6 +53,7 @@ public: bool rootModelsLoaded() const { return m_rootModelsLoaded; } QString currentBackend() const { return m_currentBackend; } bool daemonConnected() const { return m_daemonConnected; } + int agentStateRevision() const { return m_agentStateRevision; } Q_INVOKABLE QString agentState(const QString &sessionId, const QString &agentId) const; Q_INVOKABLE QString sessionConnectionColor(const QString &sessionId) const; Q_INVOKABLE void setCurrentBackend(const QString &backend) { @@ -92,6 +94,7 @@ signals: void activeAgentIdChanged(); void activeStateChanged(); void agentStateChanged(const QString &sessionId, const QString &agentId, const QString &state); + void agentStateRevisionChanged(); void chatReceived(const QString &text); void rootBackendsLoadedChanged(); void availableBackendsChanged(); @@ -132,6 +135,7 @@ private: // Agent state cache — updated via delta events QHash m_agentStateValues; + int m_agentStateRevision = 0; // Streaming FSMs — each wraps a QProcess lifecycle StreamFsm *m_chat = nullptr; // Oneshot — reads agent chat log