feat(gui): handle empty sessions in ollie-gui
- getAgents(): filter out 'new' (agent creation file), return empty list - setActiveSessionId(): skip agent init when no agents exist - submit/interrupt/kill/streams: guard against empty m_agentId - prompt input: disable when no agent, show 'No agent' placeholder
This commit is contained in:
parent
c4d6f2a1b9
commit
6fcef9f60c
24
gui/main.qml
24
gui/main.qml
|
|
@ -193,10 +193,12 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var log = ollie.readLogForSession(ollie.activeSessionId, ollie.activeAgentId)
|
if (ollie.activeAgentId) {
|
||||||
if (log) {
|
var log = ollie.readLogForSession(ollie.activeSessionId, ollie.activeAgentId)
|
||||||
chatModel.appendData(log)
|
if (log) {
|
||||||
chatModel.trimFront(20)
|
chatModel.appendData(log)
|
||||||
|
chatModel.trimFront(20)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
scrollTimer.start()
|
scrollTimer.start()
|
||||||
buildSessionTree()
|
buildSessionTree()
|
||||||
|
|
@ -206,10 +208,12 @@ ApplicationWindow {
|
||||||
target: ollie
|
target: ollie
|
||||||
function onActiveSessionIdChanged() {
|
function onActiveSessionIdChanged() {
|
||||||
chatModel.reset()
|
chatModel.reset()
|
||||||
var log = ollie.readLogForSession(ollie.activeSessionId, ollie.activeAgentId)
|
if (ollie.activeAgentId) {
|
||||||
if (log) {
|
var log = ollie.readLogForSession(ollie.activeSessionId, ollie.activeAgentId)
|
||||||
chatModel.appendData(log)
|
if (log) {
|
||||||
chatModel.trimFront(20)
|
chatModel.appendData(log)
|
||||||
|
chatModel.trimFront(20)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
scrollTimer.start()
|
scrollTimer.start()
|
||||||
// Expand the active session in the tree
|
// Expand the active session in the tree
|
||||||
|
|
@ -886,8 +890,8 @@ property bool blockExpanded: {
|
||||||
TextArea {
|
TextArea {
|
||||||
id: promptInput
|
id: promptInput
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
placeholderText: ollie.activeSessionId ? "Message..." : "No session"
|
placeholderText: !ollie.activeSessionId ? "No session" : !ollie.activeAgentId ? "No agent" : "Message..."
|
||||||
enabled: ollie.activeSessionId !== ""
|
enabled: ollie.activeSessionId !== "" && ollie.activeAgentId !== ""
|
||||||
wrapMode: TextEdit.Wrap
|
wrapMode: TextEdit.Wrap
|
||||||
|
|
||||||
property string _lastText: ""
|
property string _lastText: ""
|
||||||
|
|
|
||||||
|
|
@ -62,25 +62,26 @@ void Ollie9pClient::setActiveSessionId(const QString &id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discover agent ID BEFORE emitting signals
|
// Discover agent ID BEFORE emitting signals
|
||||||
QByteArray out = run9p({"ls", "session/" + id + "/agent"});
|
QStringList agents = getAgents(id);
|
||||||
QString agents = QString::fromUtf8(out).trimmed();
|
|
||||||
if (!agents.isEmpty()) {
|
if (!agents.isEmpty()) {
|
||||||
m_agentId = agents.split('\n').first().trimmed();
|
m_agentId = agents.first();
|
||||||
|
|
||||||
|
// Read initial state immediately (state, not statewait)
|
||||||
|
QByteArray stateOut = run9p({"read", agentPath() + "/state"});
|
||||||
|
QString stateStr = QString::fromUtf8(stateOut).trimmed();
|
||||||
|
if (!stateStr.isEmpty())
|
||||||
|
m_activeState = stateStr;
|
||||||
|
|
||||||
|
emit activeSessionIdChanged();
|
||||||
|
emit activeStateChanged();
|
||||||
|
|
||||||
|
startChatStream();
|
||||||
|
startStateStream();
|
||||||
} else {
|
} else {
|
||||||
m_agentId = "0";
|
// Empty session — no agent yet
|
||||||
|
emit activeSessionIdChanged();
|
||||||
|
emit activeStateChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read initial state immediately (state, not statewait)
|
|
||||||
QByteArray stateOut = run9p({"read", agentPath() + "/state"});
|
|
||||||
QString stateStr = QString::fromUtf8(stateOut).trimmed();
|
|
||||||
if (!stateStr.isEmpty())
|
|
||||||
m_activeState = stateStr;
|
|
||||||
|
|
||||||
emit activeSessionIdChanged();
|
|
||||||
emit activeStateChanged();
|
|
||||||
|
|
||||||
startChatStream();
|
|
||||||
startStateStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ollie9pClient::refreshSessions()
|
void Ollie9pClient::refreshSessions()
|
||||||
|
|
@ -126,7 +127,7 @@ QString Ollie9pClient::readLogForSession(const QString &sessionId, const QString
|
||||||
|
|
||||||
bool Ollie9pClient::submit(const QString &prompt)
|
bool Ollie9pClient::submit(const QString &prompt)
|
||||||
{
|
{
|
||||||
if (m_activeSessionId.isEmpty() || prompt.trimmed().isEmpty()) return false;
|
if (m_activeSessionId.isEmpty() || m_agentId.isEmpty() || prompt.trimmed().isEmpty()) return false;
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.start(ninepBin(), {"-a", serverAddr(), "write", agentPath() + "/prompt"});
|
proc.start(ninepBin(), {"-a", serverAddr(), "write", agentPath() + "/prompt"});
|
||||||
proc.waitForStarted(3000);
|
proc.waitForStarted(3000);
|
||||||
|
|
@ -138,7 +139,7 @@ bool Ollie9pClient::submit(const QString &prompt)
|
||||||
|
|
||||||
bool Ollie9pClient::interrupt()
|
bool Ollie9pClient::interrupt()
|
||||||
{
|
{
|
||||||
if (m_activeSessionId.isEmpty()) return false;
|
if (m_activeSessionId.isEmpty() || m_agentId.isEmpty()) return false;
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.start(ninepBin(), {"-a", serverAddr(), "write", agentPath() + "/ctl"});
|
proc.start(ninepBin(), {"-a", serverAddr(), "write", agentPath() + "/ctl"});
|
||||||
proc.waitForStarted(3000);
|
proc.waitForStarted(3000);
|
||||||
|
|
@ -150,7 +151,7 @@ bool Ollie9pClient::interrupt()
|
||||||
|
|
||||||
bool Ollie9pClient::kill()
|
bool Ollie9pClient::kill()
|
||||||
{
|
{
|
||||||
if (m_activeSessionId.isEmpty()) return false;
|
if (m_activeSessionId.isEmpty() || m_agentId.isEmpty()) return false;
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.start(ninepBin(), {"-a", serverAddr(), "write", agentPath() + "/ctl"});
|
proc.start(ninepBin(), {"-a", serverAddr(), "write", agentPath() + "/ctl"});
|
||||||
proc.waitForStarted(3000);
|
proc.waitForStarted(3000);
|
||||||
|
|
@ -191,10 +192,15 @@ QStringList Ollie9pClient::getAgents(const QString &sessionId)
|
||||||
if (sessionId.isEmpty()) return {};
|
if (sessionId.isEmpty()) return {};
|
||||||
QByteArray out = run9p({"ls", "session/" + sessionId + "/agent"});
|
QByteArray out = run9p({"ls", "session/" + sessionId + "/agent"});
|
||||||
QString raw = QString::fromUtf8(out).trimmed();
|
QString raw = QString::fromUtf8(out).trimmed();
|
||||||
if (raw.isEmpty()) return {"0"}; // default fallback
|
if (raw.isEmpty()) return {};
|
||||||
QStringList agents = raw.split('\n', Qt::SkipEmptyParts);
|
QStringList all = raw.split('\n', Qt::SkipEmptyParts);
|
||||||
for (int i = 0; i < agents.size(); ++i)
|
QStringList agents;
|
||||||
agents[i] = agents[i].trimmed();
|
for (const QString &a : all) {
|
||||||
|
QString name = a.trimmed();
|
||||||
|
// "new" is the agent creation file, not an actual agent
|
||||||
|
if (name != "new")
|
||||||
|
agents.append(name);
|
||||||
|
}
|
||||||
return agents;
|
return agents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,6 +431,7 @@ void Ollie9pClient::ensureRootDataLoaded()
|
||||||
void Ollie9pClient::startChatStream()
|
void Ollie9pClient::startChatStream()
|
||||||
{
|
{
|
||||||
if (m_chatProc) return;
|
if (m_chatProc) return;
|
||||||
|
if (m_activeSessionId.isEmpty() || m_agentId.isEmpty()) return;
|
||||||
m_chatProc = new QProcess(this);
|
m_chatProc = new QProcess(this);
|
||||||
connect(m_chatProc, &QProcess::readyReadStandardOutput, this, &Ollie9pClient::onChatReadyRead);
|
connect(m_chatProc, &QProcess::readyReadStandardOutput, this, &Ollie9pClient::onChatReadyRead);
|
||||||
connect(m_chatProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
connect(m_chatProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
||||||
|
|
@ -437,16 +444,15 @@ void Ollie9pClient::startStateStream()
|
||||||
if (m_stateProc) return;
|
if (m_stateProc) return;
|
||||||
|
|
||||||
// Check if session still exists before starting
|
// Check if session still exists before starting
|
||||||
if (m_activeSessionId.isEmpty()) return;
|
if (m_activeSessionId.isEmpty() || m_agentId.isEmpty()) return;
|
||||||
|
|
||||||
// Re-discover agent ID — directory may have been renamed
|
// Re-discover agent ID — directory may have been renamed
|
||||||
QByteArray out = run9p({"ls", "session/" + m_activeSessionId + "/agent"});
|
QStringList agents = getAgents(m_activeSessionId);
|
||||||
QString agents = QString::fromUtf8(out).trimmed();
|
|
||||||
if (agents.isEmpty()) {
|
if (agents.isEmpty()) {
|
||||||
// Session or agent directory gone — don't start
|
// Session or agent directory gone — don't start
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QString newId = agents.split('\n').first().trimmed();
|
QString newId = agents.first();
|
||||||
if (newId != m_agentId) {
|
if (newId != m_agentId) {
|
||||||
m_agentId = newId;
|
m_agentId = newId;
|
||||||
emit activeAgentIdChanged();
|
emit activeAgentIdChanged();
|
||||||
|
|
|
||||||
Reference in New Issue