From 3525637d606db2440772d82b9cb8d336378641a8 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Sun, 9 Aug 2026 00:14:32 +0200 Subject: [PATCH] gui: chat stream always-on while agent is selected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change m_chat from Oneshot to Guarded with the same guard as m_state (daemon connected + session + agent selected). The fd stays open continuously; it closes on agent switch or program exit. Removes the demand-driven start/stop logic from handleEvent() and submit() — no longer needed since streaming doesn't cause layout thrash after the earlier fixes. --- gui/ollie9pclient.cpp | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/gui/ollie9pclient.cpp b/gui/ollie9pclient.cpp index 0dd6075..834cc48 100644 --- a/gui/ollie9pclient.cpp +++ b/gui/ollie9pclient.cpp @@ -14,8 +14,12 @@ Ollie9pClient::Ollie9pClient(QObject *parent) m_9p = new Lib9pClient(this); m_9p->connectDefault(); - // Chat stream — one-shot, reads agent chat log. Starts/stops with agent switch. - m_chat = new NativeStreamer(NativeStreamer::Oneshot, this); + // Chat stream — guarded, reads agent chat log. Runs continuously while + // an agent is selected; stops on agent switch or daemon disconnect. + m_chat = new NativeStreamer(NativeStreamer::Guarded, this); + m_chat->setGuard([this]() { + return m_daemonConnected && !m_activeSessionId.isEmpty() && !m_agentId.isEmpty(); + }); connect(m_chat, &NativeStreamer::dataReady, this, [this](const QByteArray &data) { if (!data.isEmpty()) emit chatReceived(QString::fromUtf8(data)); @@ -223,13 +227,6 @@ void Ollie9pClient::handleEvent(const QString &eventLine) m_agentStateValues[key] = payloadStr; emit agentStateChanged(sidStr, aidStr, payloadStr); emit activeStateChanged(); - - // Demand-driven chat: stop on idle, start on activity. - if (payloadStr == QLatin1String("idle")) { - m_chat->stop(); - } else if (!m_chat->isRunning()) { - m_chat->start(agentPath() + "/chat"); - } } else { // Non-active agent: need to check cache const QString sidStr = sessionId.toString(); @@ -386,11 +383,6 @@ bool Ollie9pClient::submit(const QString &prompt) if (m_activeSessionId.isEmpty() || m_agentId.isEmpty() || prompt.trimmed().isEmpty()) return false; if (!m_9p || !m_9p->isConnected()) return false; - // Start chat stream before submitting — agent will become active. - if (!m_chat->isRunning()) { - m_chat->start(agentPath() + "/chat"); - } - return m_9p->write(agentPath() + "/prompt", prompt.toUtf8()); } @@ -686,11 +678,7 @@ void Ollie9pClient::startActiveAgentStreams() if (!m_daemonConnected) return; if (m_activeSessionId.isEmpty() || m_agentId.isEmpty()) return; - // Chat stream is demand-driven: started on submit(), stopped on idle. - // If the agent is already active (e.g. switching to a busy agent), start chat now. - if (m_activeState != "idle") { - m_chat->start(agentPath() + "/chat"); - } + m_chat->start(agentPath() + "/chat"); m_state->start(agentPath() + "/statewait"); }