feat: show paused sessions as gray, add agent count to session name

- Fetch paused status from session/{id}/paused file
- Gray dot indicator for paused sessions (green otherwise)
- Session names now show agent count: 'ollie (2)'
- Fixed rename to use baseName for sessions (without count suffix)
This commit is contained in:
Levi Neely 2026-08-03 18:12:01 +02:00
parent 22a2208526
commit 566aeddecc
2 changed files with 19 additions and 17 deletions

View File

@ -114,6 +114,9 @@ ApplicationWindow {
// Add session node (always expanded for full overview)
var sessionId = sess.id || ""
var sessionName = sess.name || sessionId
var agents = sess.agents || []
var agentCount = agents.length
var displayLabel = agentCount > 0 ? sessionName + " (" + agentCount + ")" : sessionName
sessionTreeModel.append({
type: "session",
id: sessionId,
@ -121,10 +124,10 @@ ApplicationWindow {
expanded: true,
state: sess.state || "",
model: sess.model || "",
displayName: sessionName,
displayName: displayLabel,
baseName: sessionName, // For rename operations
connectionColor: ollie.sessionConnectionColor(sessionId)
})
var agents = sess.agents || []
for (var j = 0; j < agents.length; ++j) {
var agent = agents[j]
sessionTreeModel.append({
@ -160,7 +163,8 @@ ApplicationWindow {
var item = sessionTreeModel.get(index)
if (item.type === "session" || item.type === "agent") {
renamingIndex = index
renamingText = item.displayName
// Use baseName for sessions (without agent count), displayName for agents
renamingText = item.type === "session" ? (item.baseName || item.displayName) : item.displayName
}
}
@ -168,14 +172,13 @@ ApplicationWindow {
if (renamingIndex < 0) return
var item = sessionTreeModel.get(renamingIndex)
var newName = renamingText.trim()
var oldName = item.displayName
// For sessions, compare against baseName (without count)
var oldName = item.type === "session" ? (item.baseName || item.displayName) : item.displayName
if (newName !== "" && newName !== oldName) {
var success = false
if (item.type === "session") {
success = ollie.renameSession(item.id, newName)
if (success) {
sessionTreeModel.set(renamingIndex, { id: newName, displayName: newName })
}
// Don't update displayName here - let refreshSessions rebuild with count
} else if (item.type === "agent") {
success = ollie.renameAgent(item.parentId, item.agentId, newName)
if (success) {
@ -183,8 +186,6 @@ ApplicationWindow {
}
}
if (!success) {
// Reset to old name and show error
sessionTreeModel.set(renamingIndex, { displayName: oldName })
renameErrorDialog.itemType = item.type
renameErrorDialog.attemptedName = newName
renameErrorDialog.open()

View File

@ -172,14 +172,12 @@ QString Ollie9pClient::sessionConnectionColor(const QString &sessionId) const
for (const QVariant &v : m_sessions) {
const QVariantMap s = v.toMap();
if (s.value("id").toString() != sessionId) continue;
const QVariantList agents = s.value("agents").toList();
if (agents.isEmpty()) return "gray";
int connected = 0;
for (const QVariant &a : agents)
if (a.toMap().value("connected").toBool()) ++connected;
if (connected == 0) return "red";
if (connected == agents.size()) return "green";
return "yellow";
// Paused sessions show gray (RPC connection intentionally stopped)
if (s.value("paused").toBool()) return "gray";
// Session maintains its own RPC connection, independent of agent count.
// For now, assume connected if not paused. Agent-level connection
// status is tracked separately for per-agent indicators.
return "green";
}
return "gray";
}
@ -311,6 +309,9 @@ void Ollie9pClient::refreshSessions()
session["cwd"] = parts.size() > 2 ? parts[2] : "";
session["backend"] = parts.size() > 3 ? parts[3] : "";
session["model"] = parts.size() > 4 ? parts[4] : "";
// Check if session is paused
QString pausedStr = QString::fromUtf8(run9p({"read", "session/" + sessionId + "/paused"})).trimmed();
session["paused"] = (pausedStr == "true");
QVariantList agents;
for (const QString &name : QString::fromUtf8(run9p({"ls", "session/" + sessionId + "/agent"})).trimmed().split('\n', Qt::SkipEmptyParts)) {
if (name == "new") continue;