session pause/resume UI
- Add Pause/Resume toggle to session context menu - Gray agent dots when parent session is paused - Disable input field with 'Session paused' placeholder when paused - Preserve focus on prompt input during tree rebuilds
This commit is contained in:
parent
453cef397f
commit
eedee30332
28
gui/main.qml
28
gui/main.qml
|
|
@ -108,6 +108,8 @@ ApplicationWindow {
|
|||
|
||||
function buildSessionTree() {
|
||||
console.log("buildSessionTree: sessions count = " + ollie.sessions.length)
|
||||
// Preserve focus if prompt input has it
|
||||
var hadFocus = promptInput.activeFocus
|
||||
sessionTreeModel.clear()
|
||||
var sessions = ollie.sessions
|
||||
for (var i = 0; i < sessions.length; ++i) {
|
||||
|
|
@ -147,6 +149,9 @@ ApplicationWindow {
|
|||
}
|
||||
}
|
||||
console.log(" total tree items: " + sessionTreeModel.count)
|
||||
// Restore focus if it was on the prompt input
|
||||
if (hadFocus)
|
||||
promptInput.forceActiveFocus()
|
||||
}
|
||||
|
||||
function toggleExpand(index) {
|
||||
|
|
@ -702,6 +707,17 @@ ApplicationWindow {
|
|||
newAgentDialog.open()
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: ollie.isSessionPaused(root.killTargetSessionId) ? "Resume" : "Pause"
|
||||
onClicked: {
|
||||
if (root.killTargetSessionId) {
|
||||
if (ollie.isSessionPaused(root.killTargetSessionId))
|
||||
ollie.resumeSession(root.killTargetSessionId)
|
||||
else
|
||||
ollie.pauseSession(root.killTargetSessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: "Kill Session"
|
||||
onClicked: {
|
||||
|
|
@ -805,6 +821,9 @@ ApplicationWindow {
|
|||
if (cc === "red") return "#f44336"
|
||||
return "#9e9e9e"
|
||||
}
|
||||
// Agent: check if parent session is paused
|
||||
if (ollie.isSessionPaused(parentId))
|
||||
return "#9e9e9e" // gray when paused
|
||||
// Agent: execution state - query live state
|
||||
var s = ollie.agentState(parentId, agentId) || "idle"
|
||||
if (s === "idle") return "#4caf50"
|
||||
|
|
@ -1052,8 +1071,13 @@ property bool blockExpanded: {
|
|||
TextArea {
|
||||
id: promptInput
|
||||
Layout.fillWidth: true
|
||||
placeholderText: !ollie.activeSessionId ? "No session" : !ollie.activeAgentId ? "No agent" : "Message..."
|
||||
enabled: ollie.activeSessionId !== "" && ollie.activeAgentId !== ""
|
||||
placeholderText: {
|
||||
if (!ollie.activeSessionId) return "No session"
|
||||
if (!ollie.activeAgentId) return "No agent"
|
||||
if (ollie.isSessionPaused(ollie.activeSessionId)) return "Session paused"
|
||||
return "Message..."
|
||||
}
|
||||
enabled: ollie.activeSessionId !== "" && ollie.activeAgentId !== "" && !ollie.isSessionPaused(ollie.activeSessionId)
|
||||
wrapMode: TextEdit.Wrap
|
||||
|
||||
property string _lastText: ""
|
||||
|
|
|
|||
|
|
@ -538,6 +538,50 @@ bool Ollie9pClient::killSession(const QString &sessionId)
|
|||
return proc.exitCode() == 0;
|
||||
}
|
||||
|
||||
bool Ollie9pClient::pauseSession(const QString &sessionId)
|
||||
{
|
||||
if (sessionId.isEmpty()) return false;
|
||||
QString path = "session/" + sessionId + "/ctl";
|
||||
QProcess proc;
|
||||
proc.start(ninepBin(), {"-a", serverAddr(), "write", path});
|
||||
proc.waitForStarted(3000);
|
||||
proc.write("pause");
|
||||
proc.closeWriteChannel();
|
||||
proc.waitForFinished(3000);
|
||||
if (proc.exitCode() == 0) {
|
||||
refreshSessions();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ollie9pClient::resumeSession(const QString &sessionId)
|
||||
{
|
||||
if (sessionId.isEmpty()) return false;
|
||||
QString path = "session/" + sessionId + "/ctl";
|
||||
QProcess proc;
|
||||
proc.start(ninepBin(), {"-a", serverAddr(), "write", path});
|
||||
proc.waitForStarted(3000);
|
||||
proc.write("resume");
|
||||
proc.closeWriteChannel();
|
||||
proc.waitForFinished(3000);
|
||||
if (proc.exitCode() == 0) {
|
||||
refreshSessions();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ollie9pClient::isSessionPaused(const QString &sessionId) const
|
||||
{
|
||||
for (const QVariant &v : m_sessions) {
|
||||
const QVariantMap s = v.toMap();
|
||||
if (s.value("id").toString() == sessionId)
|
||||
return s.value("paused").toBool();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString Ollie9pClient::getConfig()
|
||||
{
|
||||
if (m_activeSessionId.isEmpty()) return {};
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ public:
|
|||
Q_INVOKABLE bool interrupt();
|
||||
Q_INVOKABLE bool kill();
|
||||
Q_INVOKABLE bool killSession(const QString &sessionId);
|
||||
Q_INVOKABLE bool pauseSession(const QString &sessionId);
|
||||
Q_INVOKABLE bool resumeSession(const QString &sessionId);
|
||||
Q_INVOKABLE bool isSessionPaused(const QString &sessionId) const;
|
||||
Q_INVOKABLE QString getConfig();
|
||||
Q_INVOKABLE QStringList getAgents(const QString &sessionId);
|
||||
|
||||
|
|
|
|||
Reference in New Issue