gui: show error and keep dialog open on agent creation failure

Change createAgent to return error string (empty=success).
Replace standardButtons with custom footer so dialog stays open
on error, showing the message and letting the user adjust values.
This commit is contained in:
Levi Neely 2026-08-03 10:41:32 +02:00
parent e4c702a691
commit 3fd7907359
3 changed files with 47 additions and 22 deletions

View File

@ -367,7 +367,6 @@ ApplicationWindow {
anchors.centerIn: parent anchors.centerIn: parent
width: 420 width: 420
modal: true modal: true
standardButtons: Dialog.Ok | Dialog.Cancel
contentItem: ColumnLayout { contentItem: ColumnLayout {
spacing: 16 spacing: 16
@ -376,6 +375,15 @@ ApplicationWindow {
// --- Agent --- // --- Agent ---
Label { text: "Agent"; font.bold: true; font.pointSize: theme.fontSize > 0 ? theme.fontSize + 1 : Qt.application.font.pointSize + 1 } Label { text: "Agent"; font.bold: true; font.pointSize: theme.fontSize > 0 ? theme.fontSize + 1 : Qt.application.font.pointSize + 1 }
// Error label
Label {
id: newAgentErrorLabel
Layout.fillWidth: true
visible: text !== ""
color: "red"
wrapMode: Text.Wrap
}
// Directory // Directory
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
@ -491,25 +499,40 @@ ApplicationWindow {
} }
} }
onAccepted: { footer: RowLayout {
var cwd = dirField.text.trim() Layout.fillWidth: true
if (cwd === "") { Item { Layout.fillWidth: true }
console.log("New agent: directory is required") Button {
return text: "OK"
} onClicked: {
var backend = backendCombo.currentText.trim() newAgentErrorLabel.text = ""
var model = modelCombo.currentIndex >= 0 ? modelCombo.currentText.trim() : "" var cwd = dirField.text.trim()
var agent = agentCombo.currentText if (cwd === "") {
var remote = remoteField.text.trim() newAgentErrorLabel.text = "Directory is required"
var agentAlias = agentAliasField.text.trim() return
}
var backend = backendCombo.currentText.trim()
var model = modelCombo.currentIndex >= 0 ? modelCombo.currentText.trim() : ""
var agent = agentCombo.currentText
var remote = remoteField.text.trim()
var agentAlias = agentAliasField.text.trim()
var ok = ollie.createAgent(root.newAgentTargetSessionId, cwd, backend, model, agent, remote, agentAlias) var err = ollie.createAgent(root.newAgentTargetSessionId, cwd, backend, model, agent, remote, agentAlias)
if (ok) { if (err === "") {
ollie.refreshSessions() ollie.refreshSessions()
} else { newAgentDialog.close()
console.log("New agent: creation failed") } else {
newAgentErrorLabel.text = err
}
}
}
Button {
text: "Cancel"
onClicked: newAgentDialog.close()
} }
} }
onOpened: newAgentErrorLabel.text = ""
} }
SplitView { SplitView {

View File

@ -570,9 +570,9 @@ bool Ollie9pClient::createQuickSession()
return proc.exitCode() == 0; return proc.exitCode() == 0;
} }
bool Ollie9pClient::createAgent(const QString &sessionId, const QString &cwd, const QString &backend, const QString &model, const QString &agent, const QString &remote, const QString &agentAlias) QString Ollie9pClient::createAgent(const QString &sessionId, const QString &cwd, const QString &backend, const QString &model, const QString &agent, const QString &remote, const QString &agentAlias)
{ {
if (sessionId.isEmpty() || cwd.isEmpty()) return false; if (sessionId.isEmpty() || cwd.isEmpty()) return QStringLiteral("session ID and directory are required");
QStringList agentArgs; QStringList agentArgs;
agentArgs << "cwd=" + cwd; agentArgs << "cwd=" + cwd;
@ -594,10 +594,12 @@ bool Ollie9pClient::createAgent(const QString &sessionId, const QString &cwd, co
QString err = QString::fromUtf8(proc.readAllStandardError()).trimmed(); QString err = QString::fromUtf8(proc.readAllStandardError()).trimmed();
if (err.isEmpty()) if (err.isEmpty())
err = QString::fromUtf8(proc.readAllStandardOutput()).trimmed(); err = QString::fromUtf8(proc.readAllStandardOutput()).trimmed();
if (err.isEmpty())
err = QStringLiteral("agent creation failed");
qDebug() << "createAgent failed:" << err; qDebug() << "createAgent failed:" << err;
return false; return err;
} }
return true; return QString();
} }
bool Ollie9pClient::killAgent(const QString &sessionId, const QString &agentId) bool Ollie9pClient::killAgent(const QString &sessionId, const QString &agentId)

View File

@ -86,7 +86,7 @@ public:
Q_INVOKABLE QStringList getAvailableModels(const QString &backend) const; Q_INVOKABLE QStringList getAvailableModels(const QString &backend) const;
Q_INVOKABLE bool createSession(const QString &cwd, const QString &name, const QString &backend, const QString &model, const QString &agent, const QString &remote, const QString &agentAlias); Q_INVOKABLE bool createSession(const QString &cwd, const QString &name, const QString &backend, const QString &model, const QString &agent, const QString &remote, const QString &agentAlias);
Q_INVOKABLE bool createQuickSession(); Q_INVOKABLE bool createQuickSession();
Q_INVOKABLE bool createAgent(const QString &sessionId, const QString &cwd, const QString &backend, const QString &model, const QString &agent, const QString &remote, const QString &agentAlias); Q_INVOKABLE QString createAgent(const QString &sessionId, const QString &cwd, const QString &backend, const QString &model, const QString &agent, const QString &remote, const QString &agentAlias);
Q_INVOKABLE bool killAgent(const QString &sessionId, const QString &agentId); Q_INVOKABLE bool killAgent(const QString &sessionId, const QString &agentId);
Q_INVOKABLE bool renameSession(const QString &sessionId, const QString &newName); Q_INVOKABLE bool renameSession(const QString &sessionId, const QString &newName);
Q_INVOKABLE bool renameAgent(const QString &sessionId, const QString &agentId, const QString &newName); Q_INVOKABLE bool renameAgent(const QString &sessionId, const QString &agentId, const QString &newName);