323 lines
12 KiB
QML
323 lines
12 KiB
QML
// NewAgentDialog.qml — Dialog for creating a new agent in a session
|
|
import QtQuick 2.15
|
|
import QtQuick.Controls 2.15
|
|
import QtQuick.Layouts 1.15
|
|
|
|
Dialog {
|
|
id: root
|
|
title: editMode ? "Agent Settings" : "New Agent"
|
|
width: 420
|
|
modal: false
|
|
x: (parent ? (parent.width - width) / 2 : 0)
|
|
y: (parent ? (parent.height - height) / 2 : 0)
|
|
|
|
// Keep the non-modal dialog visually separate from the application behind it.
|
|
background: Item {
|
|
// A dark offset layer reads as a shadow instead of a bright outline.
|
|
Rectangle {
|
|
x: 4
|
|
y: 6
|
|
width: parent.width
|
|
height: parent.height
|
|
color: Qt.rgba(0, 0, 0, 0.28)
|
|
radius: 4
|
|
}
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
color: theme.windowColor
|
|
border.color: theme.dialogOutlineColor
|
|
border.width: 3
|
|
radius: 4
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
anchors.margins: 3
|
|
color: "transparent"
|
|
border.color: theme.lightColor
|
|
border.width: 1
|
|
radius: 3
|
|
}
|
|
}
|
|
}
|
|
|
|
header: Rectangle {
|
|
implicitHeight: 36
|
|
color: theme.buttonColor
|
|
Text { anchors.centerIn: parent; text: root.title; color: theme.buttonTextColor }
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
cursorShape: Qt.SizeAllCursor
|
|
property point pressPosition
|
|
onPressed: pressPosition = Qt.point(mouse.x, mouse.y)
|
|
onPositionChanged: if (pressed) {
|
|
root.x += mouse.x - pressPosition.x
|
|
root.y += mouse.y - pressPosition.y
|
|
}
|
|
}
|
|
}
|
|
|
|
// Session ID to create the agent in
|
|
property string targetSessionId: ""
|
|
|
|
// Mode: false = create, true = edit existing agent
|
|
property bool editMode: false
|
|
property string editAgentId: ""
|
|
|
|
// Store original config when opened in edit mode for diffing on save.
|
|
property var _originalConfig: ({})
|
|
|
|
// Inherited session working directory, shown as the Directory placeholder.
|
|
property string _inheritedCwd: ""
|
|
|
|
signal agentCreated()
|
|
|
|
// Open in edit mode for an existing agent.
|
|
function openForAgent(sessionId, agentId) {
|
|
editMode = true
|
|
targetSessionId = sessionId
|
|
editAgentId = agentId
|
|
open()
|
|
}
|
|
|
|
contentItem: ColumnLayout {
|
|
spacing: 16
|
|
Layout.margins: 16
|
|
|
|
Label {
|
|
text: root.editMode ? "Agent Settings" : "Agent"
|
|
font.bold: true
|
|
font.pointSize: theme.fontSize > 0 ? theme.fontSize + 1 : Qt.application.font.pointSize + 1
|
|
}
|
|
|
|
Label {
|
|
id: errorLabel
|
|
Layout.fillWidth: true
|
|
visible: text !== ""
|
|
color: "red"
|
|
wrapMode: Text.Wrap
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
Label { text: "Backend:"; Layout.preferredWidth: 80 }
|
|
ComboBox {
|
|
id: backendCombo
|
|
Layout.fillWidth: true
|
|
enabled: ollie.rootBackendsLoaded
|
|
model: ollie.availableBackends
|
|
currentIndex: 0
|
|
editable: true
|
|
onAccepted: backendCombo.editText = backendCombo.currentText
|
|
}
|
|
}
|
|
|
|
ListModel { id: modelList }
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
Label { text: "Model:"; Layout.preferredWidth: 80 }
|
|
ComboBox {
|
|
id: modelCombo
|
|
Layout.fillWidth: true
|
|
enabled: backendCombo.currentIndex >= 0 && backendCombo.currentText.trim() !== "" && ollie.rootModelsLoaded
|
|
model: modelList
|
|
currentIndex: -1
|
|
editable: true
|
|
onAccepted: modelCombo.editText = modelCombo.currentText
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
Label { text: "Profile:"; Layout.preferredWidth: 80 }
|
|
ComboBox {
|
|
id: agentCombo
|
|
Layout.fillWidth: true
|
|
enabled: ollie.rootAgentsLoaded
|
|
model: ollie.availableAgents
|
|
currentIndex: 0
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
Label { text: "Name:"; Layout.preferredWidth: 80 }
|
|
TextField {
|
|
id: aliasField
|
|
Layout.fillWidth: true
|
|
placeholderText: "(auto-generated)"
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
visible: root.editMode
|
|
Label { text: "Directory:"; Layout.preferredWidth: 80 }
|
|
TextField {
|
|
id: cwdField
|
|
Layout.fillWidth: true
|
|
// Empty = inherit the session working directory. The placeholder
|
|
// shows the inherited path so it is clear what "empty" means.
|
|
placeholderText: root._inheritedCwd !== "" ? ("(inherit: " + root._inheritedCwd + ")") : "(inherit session directory)"
|
|
}
|
|
Button {
|
|
text: "Browse..."
|
|
onClicked: {
|
|
var start = cwdField.text || root._inheritedCwd || ""
|
|
var folder = theme.chooseFolder("Select Agent Working Directory", start)
|
|
if (folder !== "")
|
|
cwdField.text = folder
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillWidth: true
|
|
visible: root.editMode && cwdField.text.trim() !== ""
|
|
Item { Layout.preferredWidth: 80 }
|
|
Button {
|
|
text: "Reset to session directory"
|
|
onClicked: cwdField.text = ""
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
if (!ollie.rootBackendsLoaded) ollie.loadRootBackends()
|
|
if (!ollie.rootAgentsLoaded) ollie.loadRootAgents()
|
|
}
|
|
|
|
Connections {
|
|
target: backendCombo
|
|
function onCurrentTextChanged() {
|
|
var be = backendCombo.currentText.trim()
|
|
modelList.clear()
|
|
if (be !== "" && ollie.rootModelsLoaded) {
|
|
var models = ollie.getAvailableModels(be)
|
|
for (var i = 0; i < models.length; ++i) {
|
|
modelList.append({ modelData: models[i] })
|
|
}
|
|
modelCombo.currentIndex = models.length > 0 ? 0 : -1
|
|
} else {
|
|
modelCombo.currentIndex = -1
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
footer: RowLayout {
|
|
Layout.fillWidth: true
|
|
Item { Layout.fillWidth: true }
|
|
Button {
|
|
id: okButton
|
|
text: root.editMode ? "Save" : "OK"
|
|
onClicked: {
|
|
errorLabel.text = ""
|
|
var backend = backendCombo.currentText.trim()
|
|
var model = modelCombo.currentIndex >= 0 ? modelCombo.currentText.trim() : modelCombo.editText.trim()
|
|
var agent = agentCombo.currentText
|
|
var agentAlias = aliasField.text.trim()
|
|
|
|
if (root.editMode) {
|
|
// Edit mode: write only the changed values back via ctl.
|
|
// Profile is applied first because switching it can reset
|
|
// backend/model; backend before model for the same reason.
|
|
var cfg = root._originalConfig
|
|
if (agent !== "" && agent !== cfg.profile) {
|
|
var ep = ollie.updateAgentConfig(root.targetSessionId, root.editAgentId, "profile", agent)
|
|
if (ep) { errorLabel.text = ep; return }
|
|
}
|
|
if (backend !== "" && backend !== cfg.backend) {
|
|
var eb = ollie.updateAgentConfig(root.targetSessionId, root.editAgentId, "backend", backend)
|
|
if (eb) { errorLabel.text = eb; return }
|
|
}
|
|
if (model !== "" && model !== cfg.model) {
|
|
var em = ollie.updateAgentConfig(root.targetSessionId, root.editAgentId, "model", model)
|
|
if (em) { errorLabel.text = em; return }
|
|
}
|
|
if (agentAlias !== "" && agentAlias !== cfg.displayName) {
|
|
var en = ollie.updateAgentConfig(root.targetSessionId, root.editAgentId, "displayName", agentAlias)
|
|
if (en) { errorLabel.text = en; return }
|
|
}
|
|
// Per-agent cwd override: empty value clears it (inherit).
|
|
var cwd = cwdField.text.trim()
|
|
if (cwd !== (cfg.cwdOverride || "")) {
|
|
var ec = ollie.updateAgentConfig(root.targetSessionId, root.editAgentId, "cwd", cwd)
|
|
if (ec) { errorLabel.text = ec; return }
|
|
}
|
|
ollie.refreshSessions()
|
|
root.close()
|
|
return
|
|
}
|
|
|
|
var newAgentId = ollie.createAgent(root.targetSessionId, backend, model, agent, "", agentAlias)
|
|
var err = ollie.lastError()
|
|
if (err === "") {
|
|
// Success: refresh then switch to the newly created agent.
|
|
ollie.refreshSessions()
|
|
ollie.switchAgent(root.targetSessionId, newAgentId)
|
|
root.agentCreated()
|
|
root.close()
|
|
} else {
|
|
errorLabel.text = err
|
|
}
|
|
}
|
|
}
|
|
Button {
|
|
text: "Cancel"
|
|
onClicked: root.close()
|
|
}
|
|
}
|
|
|
|
// Dialogs are display-only until the user clicks a field.
|
|
focus: false
|
|
|
|
onOpened: {
|
|
errorLabel.text = ""
|
|
if (!ollie.rootBackendsLoaded) ollie.loadRootBackends()
|
|
if (!ollie.rootAgentsLoaded) ollie.loadRootAgents()
|
|
|
|
if (editMode && targetSessionId !== "" && editAgentId !== "") {
|
|
// Read current agent config and populate fields.
|
|
var cfg = ollie.readAgentConfig(targetSessionId, editAgentId)
|
|
_originalConfig = cfg
|
|
|
|
// Backend: select or set as editable text.
|
|
var beIdx = ollie.availableBackends.indexOf(cfg.backend || "")
|
|
if (beIdx >= 0) backendCombo.currentIndex = beIdx
|
|
backendCombo.editText = cfg.backend || ""
|
|
|
|
// Rebuild the model list for this backend, then select the current model.
|
|
modelList.clear()
|
|
if (cfg.backend && ollie.rootModelsLoaded) {
|
|
var models = ollie.getAvailableModels(cfg.backend)
|
|
for (var i = 0; i < models.length; ++i)
|
|
modelList.append({ modelData: models[i] })
|
|
var mIdx = models.indexOf(cfg.model || "")
|
|
modelCombo.currentIndex = mIdx
|
|
} else {
|
|
modelCombo.currentIndex = -1
|
|
}
|
|
modelCombo.editText = cfg.model || ""
|
|
|
|
var prIdx = ollie.availableAgents.indexOf(cfg.profile || "")
|
|
agentCombo.currentIndex = prIdx >= 0 ? prIdx : 0
|
|
|
|
aliasField.text = cfg.displayName || ""
|
|
|
|
// cwd: show the override (if any) in the field; the inherited
|
|
// session cwd is shown as the placeholder.
|
|
_inheritedCwd = cfg.sessionCwd || ""
|
|
cwdField.text = cfg.cwdOverride || ""
|
|
} else {
|
|
// Create mode: reset fields.
|
|
aliasField.text = ""
|
|
agentCombo.currentIndex = 0
|
|
modelCombo.currentIndex = -1
|
|
modelCombo.editText = ""
|
|
cwdField.text = ""
|
|
_inheritedCwd = ""
|
|
_originalConfig = ({})
|
|
}
|
|
}
|
|
}
|