fix connection dot indicators
This commit is contained in:
parent
41f95e84c2
commit
4dabab1f71
|
|
@ -228,6 +228,10 @@ ApplicationWindow {
|
|||
}
|
||||
scrollTimer.start()
|
||||
}
|
||||
function onSessionConnected() {
|
||||
chatModel.appendData("\n[[[info]]]\nsession connected\n[[[end]]]\n")
|
||||
scrollTimer.start()
|
||||
}
|
||||
function onStreamingDone() {
|
||||
chatModel.appendData("\n[[[info]]]\nsession ended\n[[[end]]]\n")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ void NinePConnection::start(const QString &program, const QStringList &args, int
|
|||
m_retryMs = retryMs;
|
||||
m_probe = probe;
|
||||
m_stopRequested = false;
|
||||
m_openMarkerSeen = false;
|
||||
m_retryTimer.stop();
|
||||
if (!m_process)
|
||||
startProcess();
|
||||
|
|
@ -43,6 +44,7 @@ void NinePConnection::startProcess()
|
|||
if (m_stopRequested || m_process)
|
||||
return;
|
||||
m_stderr.clear();
|
||||
m_openMarkerSeen = false;
|
||||
m_process = new QProcess(this);
|
||||
connect(m_process, &QProcess::started, this, &NinePConnection::onStarted);
|
||||
connect(m_process, &QProcess::readyReadStandardOutput, this, &NinePConnection::onStdout);
|
||||
|
|
@ -77,17 +79,19 @@ void NinePConnection::onStderr()
|
|||
if (end < 0) break;
|
||||
const QByteArray line = m_stderr.left(end).trimmed();
|
||||
m_stderr.remove(0, end + 1);
|
||||
if (line == "OLLIE_9P_OPEN")
|
||||
if (line == "OLLIE_9P_OPEN") {
|
||||
m_openMarkerSeen = true;
|
||||
setState(Connected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NinePConnection::onFinished(int exitCode, QProcess::ExitStatus)
|
||||
{
|
||||
if (!m_process) return;
|
||||
m_process->deleteLater();
|
||||
m_process = nullptr;
|
||||
if (m_probe && m_state == Connected && exitCode == 0 && !m_stopRequested) {
|
||||
if (m_probe && m_state == Connected && m_openMarkerSeen && exitCode == 0 && !m_stopRequested) {
|
||||
m_retryTimer.start(m_retryMs);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ private:
|
|||
bool m_stopRequested = false;
|
||||
int m_retryMs = 4000;
|
||||
bool m_probe = false;
|
||||
bool m_openMarkerSeen = false;
|
||||
};
|
||||
|
||||
#endif // NINEPCONNECTION_H
|
||||
|
|
|
|||
|
|
@ -46,11 +46,18 @@ Ollie9pClient::Ollie9pClient(QObject *parent)
|
|||
emit chatReceived(QString::fromUtf8(data));
|
||||
});
|
||||
connect(m_chat, &StreamFsm::died, this, [this]() {
|
||||
// The chat stream closes when the selected session ends. Treat that
|
||||
// existing signal as an immediate disconnect for connection tracking;
|
||||
// the periodic connection probe will confirm or recover it later.
|
||||
if (!m_activeSessionId.isEmpty() && !m_agentId.isEmpty())
|
||||
setAgentConnected(agentKey(m_activeSessionId, m_agentId), false);
|
||||
if (!m_activeSessionId.isEmpty()) {
|
||||
for (const QVariant &value : std::as_const(m_sessions)) {
|
||||
const QVariantMap session = value.toMap();
|
||||
if (session.value("id").toString() != m_activeSessionId) continue;
|
||||
for (const QVariant &agentValue : session.value("agents").toList()) {
|
||||
const QString key = agentKey(m_activeSessionId,
|
||||
agentValue.toMap().value("id").toString());
|
||||
setAgentConnected(key, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
emit streamingDone();
|
||||
});
|
||||
|
||||
|
|
@ -204,21 +211,26 @@ QString Ollie9pClient::sessionConnectionColor(const QString &sessionId) const
|
|||
|
||||
void Ollie9pClient::setAgentConnected(const QString &key, bool connected)
|
||||
{
|
||||
if (m_agentConnected.value(key, false) == connected) return;
|
||||
const bool cached = m_agentConnected.value(key, false);
|
||||
m_agentConnected[key] = connected;
|
||||
bool modelChanged = false;
|
||||
// Update the in-memory model without starting another round of probes.
|
||||
for (QVariant &value : m_sessions) {
|
||||
QVariantMap session = value.toMap();
|
||||
QVariantList agents = session.value("agents").toList();
|
||||
for (QVariant &agentValue : agents) {
|
||||
QVariantMap agent = agentValue.toMap();
|
||||
if (agentKey(session["id"].toString(), agent["id"].toString()) == key)
|
||||
if (agentKey(session["id"].toString(), agent["id"].toString()) == key) {
|
||||
if (agent.value("connected").toBool() != connected)
|
||||
modelChanged = true;
|
||||
agent["connected"] = connected;
|
||||
}
|
||||
agentValue = agent;
|
||||
}
|
||||
session["agents"] = agents;
|
||||
value = session;
|
||||
}
|
||||
if (cached != connected || modelChanged)
|
||||
emit sessionsChanged();
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +256,14 @@ void Ollie9pClient::reconcileAgentConnections()
|
|||
auto *connection = new NinePConnection(this);
|
||||
m_agentConnections.insert(key, connection);
|
||||
connect(connection, &NinePConnection::connected, this, [this, key]() {
|
||||
const bool reconnected = m_seenAgentConnections.contains(key);
|
||||
m_seenAgentConnections.insert(key);
|
||||
setAgentConnected(key, true);
|
||||
if (key == agentKey(m_activeSessionId, m_agentId)) {
|
||||
if (reconnected)
|
||||
emit sessionConnected();
|
||||
startActiveAgentStreams();
|
||||
}
|
||||
});
|
||||
connect(connection, &NinePConnection::disconnected, this, [this, key]() {
|
||||
setAgentConnected(key, false);
|
||||
|
|
@ -457,11 +476,7 @@ void Ollie9pClient::switchAgent(const QString &sessionId, const QString &agentId
|
|||
emit activeAgentIdChanged();
|
||||
emit activeStateChanged();
|
||||
|
||||
// switchAgent is the ONLY path that starts per-agent streams.
|
||||
QString srv = serverAddr();
|
||||
QString bin = ninepBin();
|
||||
m_chat->start(bin, {"-a", srv, "read", agentPath() + "/chat"});
|
||||
m_state->start(bin, {"-a", srv, "read", agentPath() + "/statewait"});
|
||||
startActiveAgentStreams();
|
||||
}
|
||||
|
||||
void Ollie9pClient::loadRootBackends()
|
||||
|
|
@ -691,6 +706,16 @@ void Ollie9pClient::ensureRootDataLoaded()
|
|||
|
||||
// --- Streaming ---
|
||||
|
||||
void Ollie9pClient::startActiveAgentStreams()
|
||||
{
|
||||
if (m_activeSessionId.isEmpty() || m_agentId.isEmpty()) return;
|
||||
|
||||
const QString srv = serverAddr();
|
||||
const QString bin = ninepBin();
|
||||
m_chat->start(bin, {"-a", srv, "read", agentPath() + "/chat"});
|
||||
m_state->start(bin, {"-a", srv, "read", agentPath() + "/statewait"});
|
||||
}
|
||||
|
||||
void Ollie9pClient::stopAgentStreams()
|
||||
{
|
||||
if (m_chat) m_chat->stop();
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <QObject>
|
||||
#include <QVariantList>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#if QT_VERSION_MAJOR >= 6
|
||||
#include <QQmlEngine>
|
||||
#endif
|
||||
|
|
@ -93,6 +94,7 @@ signals:
|
|||
void activeAgentIdChanged();
|
||||
void activeStateChanged();
|
||||
void chatReceived(const QString &text);
|
||||
void sessionConnected();
|
||||
void streamingDone(); // chat process exited (session killed)
|
||||
void rootBackendsLoadedChanged();
|
||||
void availableBackendsChanged();
|
||||
|
|
@ -112,6 +114,7 @@ private:
|
|||
void ensureRootDataLoaded();
|
||||
void setDaemonConnected(bool connected);
|
||||
void startAgentConnections();
|
||||
void startActiveAgentStreams();
|
||||
void reconcileAgentConnections();
|
||||
void stopAgentConnections();
|
||||
|
||||
|
|
@ -131,6 +134,7 @@ private:
|
|||
bool m_daemonConnected = false;
|
||||
QHash<QString, NinePConnection *> m_agentConnections;
|
||||
QHash<QString, bool> m_agentConnected;
|
||||
QSet<QString> m_seenAgentConnections;
|
||||
NinePConnection *m_daemon = nullptr;
|
||||
|
||||
// Streaming FSMs — each wraps a QProcess lifecycle
|
||||
|
|
|
|||
Reference in New Issue