gui: deduplicate sessions from multi-agent index, fix field mapping

- Deduplicate session entries in refreshSessions and onEventReadyRead
  using QSet to skip duplicate session IDs from multi-agent index.
- Fix field mapping: index format is name\tstate\tcwd\tbackend\tmodel\tagent
- Added QSet include
This commit is contained in:
Levi Neely 2026-08-01 20:53:07 +02:00
parent 5fc4ebe64e
commit ef03cdc7f3
1 changed files with 58 additions and 45 deletions

View File

@ -1,6 +1,7 @@
#include "ollie9pclient.h"
#include <QDir>
#include <QSet>
#include <QStandardPaths>
#include <QDebug>
@ -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<QString> 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<QString> 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)