diff --git a/gui/ollie9pclient.cpp b/gui/ollie9pclient.cpp index 0efdbf9..7df9d43 100644 --- a/gui/ollie9pclient.cpp +++ b/gui/ollie9pclient.cpp @@ -1,6 +1,7 @@ #include "ollie9pclient.h" #include +#include #include #include @@ -84,30 +85,36 @@ void Ollie9pClient::setActiveSessionId(const QString &id) void Ollie9pClient::refreshSessions() { - QByteArray out = run9p({"read", "session/idx"}); - // Don't trim — trailing tabs are significant fields - QString raw = QString::fromUtf8(out); + QByteArray out = run9p({"read", "session/idx"}); + // Don't trim — trailing tabs are significant fields + QString raw = QString::fromUtf8(out); - m_sessions.clear(); - if (!raw.isEmpty()) { - for (const QString &line : raw.split('\n', Qt::SkipEmptyParts)) { - QStringList parts = line.split('\t'); - // Skip lines where the first field (session name) is empty - if (parts.isEmpty() || parts[0].isEmpty()) continue; - QVariantMap session; - session["id"] = parts[0]; - session["state"] = parts.size() > 1 ? parts[1] : ""; - session["model"] = parts.size() > 2 ? parts[2] : ""; - session["agent"] = parts.size() > 3 ? parts[3] : ""; - m_sessions.append(session); - } - } - emit sessionsChanged(); + m_sessions.clear(); + QSet seen; + if (!raw.isEmpty()) { + for (const QString &line : raw.split('\n', Qt::SkipEmptyParts)) { + QStringList parts = line.split('\t'); + // Skip lines where the first field (session name) is empty + if (parts.isEmpty() || parts[0].isEmpty()) continue; + QString sid = parts[0]; + if (seen.contains(sid)) continue; // already added (multi-agent) + seen.insert(sid); + QVariantMap session; + session["id"] = sid; + session["state"] = parts.size() > 1 ? parts[1] : ""; + session["cwd"] = parts.size() > 2 ? parts[2] : ""; + session["backend"] = parts.size() > 3 ? parts[3] : ""; + session["model"] = parts.size() > 4 ? parts[4] : ""; + session["agent"] = parts.size() > 5 ? parts[5] : ""; + m_sessions.append(session); + } + } + emit sessionsChanged(); - // Auto-select first session if none active - if (m_activeSessionId.isEmpty() && !m_sessions.isEmpty()) { - setActiveSessionId(m_sessions.first().toMap()["id"].toString()); - } + // Auto-select first session if none active + if (m_activeSessionId.isEmpty() && !m_sessions.isEmpty()) { + setActiveSessionId(m_sessions.first().toMap()["id"].toString()); + } } QString Ollie9pClient::readLog() @@ -535,31 +542,37 @@ void Ollie9pClient::startEventStream() void Ollie9pClient::onEventReadyRead() { - // eventwait returned the full session index — use it directly - QByteArray data = m_eventProc->readAllStandardOutput(); - // Don't trim — trailing tabs are significant fields - QString raw = QString::fromUtf8(data); + // eventwait returned the full session index — use it directly + QByteArray data = m_eventProc->readAllStandardOutput(); + // Don't trim — trailing tabs are significant fields + QString raw = QString::fromUtf8(data); - m_sessions.clear(); - if (!raw.isEmpty()) { - for (const QString &line : raw.split('\n', Qt::SkipEmptyParts)) { - QStringList parts = line.split('\t'); - // Skip lines where the first field (session name) is empty - if (parts.isEmpty() || parts[0].isEmpty()) continue; - QVariantMap session; - session["id"] = parts[0]; - session["state"] = parts.size() > 1 ? parts[1] : ""; - session["model"] = parts.size() > 2 ? parts[2] : ""; - session["agent"] = parts.size() > 3 ? parts[3] : ""; - m_sessions.append(session); - } - } - emit sessionsChanged(); + m_sessions.clear(); + QSet seen; + if (!raw.isEmpty()) { + for (const QString &line : raw.split('\n', Qt::SkipEmptyParts)) { + QStringList parts = line.split('\t'); + // Skip lines where the first field (session name) is empty + if (parts.isEmpty() || parts[0].isEmpty()) continue; + QString sid = parts[0]; + if (seen.contains(sid)) continue; // already added (multi-agent) + seen.insert(sid); + QVariantMap session; + session["id"] = sid; + session["state"] = parts.size() > 1 ? parts[1] : ""; + session["cwd"] = parts.size() > 2 ? parts[2] : ""; + session["backend"] = parts.size() > 3 ? parts[3] : ""; + session["model"] = parts.size() > 4 ? parts[4] : ""; + session["agent"] = parts.size() > 5 ? parts[5] : ""; + m_sessions.append(session); + } + } + emit sessionsChanged(); - // Auto-select first session if none active - if (m_activeSessionId.isEmpty() && !m_sessions.isEmpty()) { - setActiveSessionId(m_sessions.first().toMap()["id"].toString()); - } + // Auto-select first session if none active + if (m_activeSessionId.isEmpty() && !m_sessions.isEmpty()) { + setActiveSessionId(m_sessions.first().toMap()["id"].toString()); + } } void Ollie9pClient::onEventFinished(int, QProcess::ExitStatus)