aboutsummaryrefslogtreecommitdiffstats
path: root/desktop/modules/assistant/AssistantPage.qml
diff options
context:
space:
mode:
Diffstat (limited to 'desktop/modules/assistant/AssistantPage.qml')
-rw-r--r--desktop/modules/assistant/AssistantPage.qml94
1 files changed, 48 insertions, 46 deletions
diff --git a/desktop/modules/assistant/AssistantPage.qml b/desktop/modules/assistant/AssistantPage.qml
index c6b63fc..832e9be 100644
--- a/desktop/modules/assistant/AssistantPage.qml
+++ b/desktop/modules/assistant/AssistantPage.qml
@@ -14,9 +14,9 @@ import QtQuick.Controls
import "../.."
// The view over AssistantModule: the model settings, the tools' environment,
-// the tools themselves, and the restart that applies them. A field saves on
-// Enter; emptied, it falls back to the daemon's default, which it shows as
-// its placeholder.
+// the tools themselves, and the restart that applies them. Every field and
+// switch edits the module's draft; the header's Save writes it. Emptied, a
+// field falls back to the daemon's default, which it shows as placeholder.
Column {
id: page
spacing: 8
@@ -44,20 +44,24 @@ Column {
color: Theme.text
}
- // A one-line input that saves on Enter and undoes on Escape; edited
- // reports every keystroke, for the add row.
+ // A one-line input reporting every keystroke, which the page turns into
+ // a draft edit. It is not bound to value, which would reset the cursor
+ // and eat a trailing space; it follows the value only when the draft
+ // moves under it (Discard, an add). bad outlines a refused value.
component Field: Rectangle {
id: field
property string value: ""
property string placeholder: ""
- signal commit(string text)
+ property bool bad: false
signal edited(string text)
- // Commit on Enter even when unchanged: the add row's fields track
- // their value as they are typed, so they never differ from it.
- property bool live: false
+ signal accepted
height: 34
radius: 8
color: Theme.surface
+ border.width: field.bad ? 1 : 0
+ border.color: Theme.red
+ onValueChanged: if (ti.text.trim() !== field.value.trim()) ti.text = field.value
+ onBadChanged: if (!field.bad) ti.text = field.value
TextInput {
id: ti
anchors { fill: parent; leftMargin: 10; rightMargin: 10 }
@@ -66,13 +70,9 @@ Column {
selectByMouse: true
color: Theme.text
font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 }
- text: field.value
+ Component.onCompleted: text = field.value
onTextEdited: field.edited(text)
- onAccepted: if (field.live || text !== field.value) field.commit(text)
- Keys.onEscapePressed: event => {
- if (text !== field.value) text = field.value;
- else event.accepted = false;
- }
+ onAccepted: field.accepted()
Text {
anchors.verticalCenter: parent.verticalCenter
width: parent.width
@@ -126,7 +126,7 @@ Column {
anchors { left: parent.left; right: restartBtn.left; rightMargin: 8; verticalCenter: parent.verticalCenter }
wrapMode: Text.Wrap
text: page.asst.pending ? "Saved. The assistant reads these at startup: restart it to apply."
- : "The assistant reads these at startup."
+ : "The assistant reads these at startup: Save, then restart it."
color: Theme.text
font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
}
@@ -245,7 +245,7 @@ Column {
anchors.fill: parent
value: page.v.llm ?? ""
placeholder: page.d.llm ?? ""
- onCommit: t => page.asst.setKey("llm", t.trim() ? page.asst.quote(t.trim()) : null)
+ onEdited: t => page.asst.setKey("llm", t.trim() ? page.asst.quote(t.trim()) : null)
}
}
@@ -258,16 +258,18 @@ Column {
width: 120
value: page.v.temperature !== undefined ? String(page.v.temperature) : ""
placeholder: "the model's preset"
- onCommit: t => {
+ bad: page.asst.invalid["key:temperature"] ?? false
+ onEdited: t => {
const x = Number(t.trim());
- if (t.trim() === "") page.asst.setKey("temperature", null);
- else if (!isNaN(x) && x >= 0 && x <= 2) page.asst.setKey("temperature", String(x));
- else page.asst.error = "Temperature is a number from 0 to 2.";
+ const ok = t.trim() === "" || (!isNaN(x) && x >= 0 && x <= 2);
+ page.asst.markInvalid("key:temperature", !ok);
+ if (ok) page.asst.setKey("temperature", t.trim() === "" ? null : String(x));
}
}
Small {
anchors { left: temp.right; leftMargin: 10; verticalCenter: parent.verticalCenter }
text: "0 to 2; empty uses the llama-server preset's"
+ color: temp.bad ? Theme.red : Theme.subtext
}
}
@@ -280,16 +282,18 @@ Column {
width: 120
value: page.v.tool_rounds !== undefined ? String(page.v.tool_rounds) : ""
placeholder: page.d.tool_rounds !== undefined ? String(page.d.tool_rounds) : ""
- onCommit: t => {
+ bad: page.asst.invalid["key:tool_rounds"] ?? false
+ onEdited: t => {
const n = Number(t.trim());
- if (t.trim() === "") page.asst.setKey("tool_rounds", null);
- else if (Number.isInteger(n) && n >= 0 && n <= 20) page.asst.setKey("tool_rounds", String(n));
- else page.asst.error = "Tool rounds is a whole number from 0 to 20.";
+ const ok = t.trim() === "" || (Number.isInteger(n) && n >= 0 && n <= 20);
+ page.asst.markInvalid("key:tool_rounds", !ok);
+ if (ok) page.asst.setKey("tool_rounds", t.trim() === "" ? null : String(n));
}
}
Small {
anchors { left: rounds.right; leftMargin: 10; verticalCenter: parent.verticalCenter }
- text: "tool round trips per question"
+ text: "a whole number, 0 to 20: tool round trips per question"
+ color: rounds.bad ? Theme.red : Theme.subtext
}
}
@@ -338,6 +342,11 @@ Column {
background: null
padding: 0
text: page.shown("system")
+ // Into the draft as it is typed; the default, or nothing,
+ // unsets the key rather than copying the default in.
+ onTextChanged: if (prompt.text !== page.shown("system"))
+ page.asst.setKey("system", prompt.text.trim() === "" || prompt.text === page.d.system
+ ? null : page.asst.quote(prompt.text))
}
}
}
@@ -345,12 +354,6 @@ Column {
Row {
spacing: 8
Button {
- text: "Save prompt"
- enabled: prompt.text.trim() !== "" && prompt.text !== page.shown("system")
- onClicked: page.asst.setKey("system", prompt.text === page.d.system ? null
- : page.asst.quote(prompt.text))
- }
- Button {
text: "Use the default"
enabled: page.v.system !== undefined
onClicked: page.asst.setKey("system", null)
@@ -374,12 +377,12 @@ Column {
property string confirming: ""
Repeater {
- model: page.asst.envList
+ model: page.asst.envKeys
delegate: Item {
id: envRow
- required property var modelData
- objectName: "env:" + modelData.key
+ required property string modelData
+ objectName: "env:" + modelData
width: page.width
height: 34
@@ -388,25 +391,25 @@ Column {
anchors { left: parent.left; verticalCenter: parent.verticalCenter }
width: 120
elide: Text.ElideRight
- text: envRow.modelData.key
+ text: envRow.modelData
color: Theme.subtext
font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 }
}
Field {
anchors { left: envKey.right; leftMargin: 8; right: envDel.left; rightMargin: 8; top: parent.top; bottom: parent.bottom }
- value: envRow.modelData.value
- onCommit: t => page.asst.setEnv(envRow.modelData.key, t)
+ value: page.asst.envValue(envRow.modelData)
+ onEdited: t => page.asst.setEnv(envRow.modelData, t)
}
Button {
id: envDel
anchors { right: parent.right; verticalCenter: parent.verticalCenter }
danger: true
- text: page.confirming === envRow.modelData.key ? "Confirm" : "Remove"
+ text: page.confirming === envRow.modelData ? "Confirm" : "Remove"
onClicked: {
- if (page.confirming === envRow.modelData.key) {
+ if (page.confirming === envRow.modelData) {
page.confirming = "";
- page.asst.setEnv(envRow.modelData.key, null);
- } else page.confirming = envRow.modelData.key;
+ page.asst.setEnv(envRow.modelData, null);
+ } else page.confirming = envRow.modelData;
}
}
}
@@ -439,9 +442,8 @@ Column {
anchors { left: keyField.right; leftMargin: 8; right: addBtn.left; rightMargin: 8; top: parent.top; bottom: parent.bottom }
value: page.newValue
placeholder: "value"
- live: true
onEdited: t => page.newValue = t
- onCommit: page.addEnv()
+ onAccepted: page.addEnv()
}
Button {
id: addBtn
@@ -474,7 +476,7 @@ Column {
Switch {
id: toolSw
anchors { left: parent.left; verticalCenter: parent.verticalCenter }
- checked: toolRow.modelData.on
+ checked: page.asst.toolOn(toolRow.modelData)
onToggled: page.asst.toggleTool(toolRow.modelData)
}
Column {
@@ -482,7 +484,7 @@ Column {
anchors { left: toolSw.right; leftMargin: 10; right: parent.right; verticalCenter: parent.verticalCenter }
Text {
text: toolRow.modelData.name
- color: toolRow.modelData.on ? Theme.text : Theme.subtext
+ color: page.asst.toolOn(toolRow.modelData) ? Theme.text : Theme.subtext
font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2; bold: true }
}
Small {