gui: chat stream always-on while agent is selected

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.
This commit is contained in:
Levi Neely 2026-08-09 00:14:32 +02:00
parent 93eba4442d
commit 3525637d60
1 changed files with 7 additions and 19 deletions

View File

@ -14,8 +14,12 @@ Ollie9pClient::Ollie9pClient(QObject *parent)
m_9p = new Lib9pClient(this); m_9p = new Lib9pClient(this);
m_9p->connectDefault(); m_9p->connectDefault();
// Chat stream — one-shot, reads agent chat log. Starts/stops with agent switch. // Chat stream — guarded, reads agent chat log. Runs continuously while
m_chat = new NativeStreamer(NativeStreamer::Oneshot, this); // 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) { connect(m_chat, &NativeStreamer::dataReady, this, [this](const QByteArray &data) {
if (!data.isEmpty()) if (!data.isEmpty())
emit chatReceived(QString::fromUtf8(data)); emit chatReceived(QString::fromUtf8(data));
@ -223,13 +227,6 @@ void Ollie9pClient::handleEvent(const QString &eventLine)
m_agentStateValues[key] = payloadStr; m_agentStateValues[key] = payloadStr;
emit agentStateChanged(sidStr, aidStr, payloadStr); emit agentStateChanged(sidStr, aidStr, payloadStr);
emit activeStateChanged(); 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 { } else {
// Non-active agent: need to check cache // Non-active agent: need to check cache
const QString sidStr = sessionId.toString(); 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_activeSessionId.isEmpty() || m_agentId.isEmpty() || prompt.trimmed().isEmpty()) return false;
if (!m_9p || !m_9p->isConnected()) 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()); return m_9p->write(agentPath() + "/prompt", prompt.toUtf8());
} }
@ -686,11 +678,7 @@ void Ollie9pClient::startActiveAgentStreams()
if (!m_daemonConnected) return; if (!m_daemonConnected) return;
if (m_activeSessionId.isEmpty() || m_agentId.isEmpty()) return; if (m_activeSessionId.isEmpty() || m_agentId.isEmpty()) return;
// Chat stream is demand-driven: started on submit(), stopped on idle. m_chat->start(agentPath() + "/chat");
// 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_state->start(agentPath() + "/statewait"); m_state->start(agentPath() + "/statewait");
} }