fix: restore lost changes
C++ / fmt (pull_request) Failing after 3s
C++ / build (pull_request) Failing after 9s
C++ / clang-tidy (pull_request) Failing after 9s
JS/TS / fmt (pull_request) Successful in 7s
JS/TS / lint (pull_request) Successful in 8s
Python / static (pull_request) Successful in 25s
Rust / build (pull_request) Successful in 50s
Rust / fmt (pull_request) Successful in 30s
Python / verify (pull_request) Successful in 1m44s
Rust / clippy (pull_request) Successful in 45s
C++ / fmt (pull_request) Failing after 3s
C++ / build (pull_request) Failing after 9s
C++ / clang-tidy (pull_request) Failing after 9s
JS/TS / fmt (pull_request) Successful in 7s
JS/TS / lint (pull_request) Successful in 8s
Python / static (pull_request) Successful in 25s
Rust / build (pull_request) Successful in 50s
Rust / fmt (pull_request) Successful in 30s
Python / verify (pull_request) Successful in 1m44s
Rust / clippy (pull_request) Successful in 45s
This commit is contained in:
@@ -20,7 +20,7 @@ BusyIndicator {
|
||||
property int animState
|
||||
property color bgColor: Colors.palette.m3secondaryContainer
|
||||
property color fgColor: Colors.palette.m3primary
|
||||
property real implicitSize: Tokens.font.size.normal * 3
|
||||
property real implicitSize: Tokens.font.body.medium.pointSize * 3
|
||||
property real internalStrokeWidth: strokeWidth
|
||||
readonly property alias progress: manager.progress
|
||||
property real strokeWidth: Tokens.padding.extraSmall * 0.8
|
||||
|
||||
@@ -23,7 +23,7 @@ PersistentProperties {
|
||||
property date dashboardDate: new Date()
|
||||
|
||||
// Sidebar state
|
||||
property int sidebarTab
|
||||
property int sidebarTab: 0
|
||||
property list<string> expandedNotifs: []
|
||||
|
||||
// Utilities state
|
||||
|
||||
@@ -8,7 +8,7 @@ TextArea {
|
||||
|
||||
color: Colors.palette.m3onSurface
|
||||
cursorVisible: !readOnly
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.body.small
|
||||
implicitHeight: contentHeight + topPadding + bottomPadding
|
||||
implicitWidth: contentWidth + leftPadding + rightPadding
|
||||
placeholderTextColor: Colors.palette.m3onSurfaceVariant // No anim cause placeholder is custom
|
||||
|
||||
@@ -11,22 +11,18 @@ TextEdit {
|
||||
|
||||
color: Colors.palette.m3onSurface
|
||||
cursorVisible: !readOnly
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font.family: Config.appearance.font.family.sans
|
||||
font: Tokens.font.body.small
|
||||
renderType: TextField.NativeRendering
|
||||
selectedTextColor: color
|
||||
selectionColor: Qt.alpha(Colors.palette.m3primary, 0.4)
|
||||
verticalAlignment: TextInput.AlignVCenter
|
||||
|
||||
Behavior on color {
|
||||
CAnim {
|
||||
}
|
||||
}
|
||||
cursorDelegate: Item {
|
||||
CAnim {}
|
||||
}
|
||||
cursorDelegate: Item {}
|
||||
Behavior on selectionColor {
|
||||
CAnim {
|
||||
}
|
||||
CAnim {}
|
||||
}
|
||||
|
||||
CustomRect {
|
||||
|
||||
@@ -455,7 +455,7 @@ Item {
|
||||
|
||||
MaterialIcon {
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: Tokens.font.size.large
|
||||
fontStyle: Tokens.font.icon.large
|
||||
text: thumb.fileIcon(thumb.modelData?.mimeType ?? "")
|
||||
visible: !thumb.modelData?.isImage ?? false
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ CustomClippingRect {
|
||||
anchors.leftMargin: Tokens.padding.large
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: Tokens.padding.large
|
||||
font.pointSize: Tokens.font.size.extraLarge
|
||||
fontStyle: Tokens.font.icon.extraLarge
|
||||
text: root.modelData.icon || "check"
|
||||
color: Colors.palette.m3onSurface
|
||||
}
|
||||
@@ -134,7 +134,7 @@ CustomClippingRect {
|
||||
anchors.leftMargin: readOnly ? 0 : Tokens.padding.large
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: readOnly ? Tokens.padding.small : Tokens.padding.extraSmall * 2
|
||||
font.pointSize: Tokens.font.size.normal
|
||||
font: Tokens.font.body.medium
|
||||
text: root.modelData.title || qsTr("New chat")
|
||||
readOnly: true
|
||||
color: Colors.palette.m3onSurface
|
||||
@@ -192,7 +192,7 @@ CustomClippingRect {
|
||||
anchors.topMargin: Tokens.spacing.extraSmall
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.label.small
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
text: qsTr("Created on: %1").arg(root.modelData.createdAt.toLocaleString(Qt.locale("en_US"), "MMM d, yyyy - h:mm AP"))
|
||||
opacity: root.expanded ? 1 : 0
|
||||
@@ -208,7 +208,7 @@ CustomClippingRect {
|
||||
anchors.top: created.bottom
|
||||
anchors.topMargin: Tokens.spacing.small
|
||||
anchors.left: parent.left
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.label.small
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
text: qsTr("Updated on: ")
|
||||
opacity: root.expanded ? 1 : 0
|
||||
@@ -225,7 +225,7 @@ CustomClippingRect {
|
||||
anchors.top: title.bottom
|
||||
anchors.topMargin: Tokens.spacing.extraSmall
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.label.small
|
||||
text: root.modelData.updatedAt.toLocaleString(Qt.locale("en_US"), "MMM d, yyyy - h:mm AP")
|
||||
|
||||
states: State {
|
||||
@@ -256,7 +256,7 @@ CustomClippingRect {
|
||||
y: infoContainer.implicitHeight + topMargin
|
||||
elide: Text.ElideRight
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.body.small
|
||||
maximumLineCount: 1
|
||||
opacity: !root.expanded && !root.slim ? 1 : 0
|
||||
text: root.modelData.messagesModel.lastMessage?.activeGeneration.content.replace(/\s+/g, " ").trim() ?? qsTr("No messages yet")
|
||||
@@ -323,7 +323,7 @@ CustomClippingRect {
|
||||
fillWidth: true
|
||||
shapeMorph: true
|
||||
isRound: true
|
||||
font.pointSize: Tokens.font.size.large
|
||||
font: Tokens.font.icon.medium
|
||||
inactiveColor: Colors.layer(Colors.palette.m3surfaceContainerHighest, 3)
|
||||
inactiveOnColor: Colors.palette.m3onSurfaceVariant
|
||||
|
||||
@@ -336,7 +336,7 @@ CustomClippingRect {
|
||||
isToggle: true
|
||||
fillWidth: true
|
||||
shapeMorph: true
|
||||
font.pointSize: Tokens.font.size.large
|
||||
font: Tokens.font.icon.medium
|
||||
isRound: true
|
||||
inactiveColor: Colors.layer(Colors.palette.m3surfaceContainerHighest, 3)
|
||||
inactiveOnColor: Colors.palette.m3onSurfaceVariant
|
||||
|
||||
@@ -156,7 +156,7 @@ Item {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: modelsContainer.expanded ? "unfold_less" : "unfold_more"
|
||||
animate: true
|
||||
font.pointSize: Tokens.font.size.large
|
||||
fontStyle: Tokens.font.icon.large
|
||||
visible: modelsList.count > 0
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ Item {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
visible: model.selected
|
||||
color: Colors.palette.m3onTertiaryContainer
|
||||
font.pointSize: Tokens.font.size.normal
|
||||
fontStyle: Tokens.font.icon.normal
|
||||
opacity: model.selected ? 1 : 0
|
||||
text: "check"
|
||||
|
||||
@@ -405,7 +405,7 @@ Item {
|
||||
MaterialIcon {
|
||||
text: fabMenuItem.modelData.icon
|
||||
color: Colors.palette.m3onPrimaryContainer
|
||||
font.pointSize: Tokens.font.size.large
|
||||
fontStyle: Tokens.font.icon.large
|
||||
fill: 1
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ pragma Singleton
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import ZShell.Llm
|
||||
import qs.Helpers
|
||||
import qs.Services
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
@@ -20,7 +20,7 @@ Singleton {
|
||||
property bool narrowSidebarExpanded: false
|
||||
property bool windowIsWide: false
|
||||
property ShellScreen screen
|
||||
property bool sidebarVisible: Visibilities.getForActive().sidebar
|
||||
property bool sidebarVisible: ShellState.forActive().sidebar
|
||||
|
||||
onSidebarVisibleChanged: if (!sidebarVisible)
|
||||
fabExpanded = false
|
||||
|
||||
@@ -29,6 +29,7 @@ Item {
|
||||
enabled: root.message.generationCount > 1 && root.message.activeGenerationIndex !== 0
|
||||
icon: "chevron_left"
|
||||
type: IconButton.Tonal
|
||||
isRound: true
|
||||
|
||||
onClicked: {
|
||||
if (!root.edit.readOnly)
|
||||
@@ -40,8 +41,7 @@ Item {
|
||||
IconButton {
|
||||
enabled: false
|
||||
icon: `${root.message.activeGenerationIndex + 1}`
|
||||
label.font.family: Config.appearance.font.family.sans
|
||||
label.font.pointSize: Tokens.font.size.small
|
||||
label.font: Tokens.font.body.small
|
||||
type: IconButton.Text
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ Item {
|
||||
enabled: root.message.generationCount > 1 && root.message.activeGenerationIndex !== root.message.generationCount - 1
|
||||
icon: "chevron_right"
|
||||
type: IconButton.Tonal
|
||||
isRound: true
|
||||
|
||||
onClicked: {
|
||||
if (!root.edit.readOnly)
|
||||
@@ -76,6 +77,7 @@ Item {
|
||||
inactiveOnColor: Colors.palette.m3onSecondary
|
||||
scale: root.edit.readOnly ? 1 : 0
|
||||
visible: !root.isUser
|
||||
isRound: true
|
||||
|
||||
Behavior on scale {
|
||||
Anim {}
|
||||
@@ -91,6 +93,7 @@ Item {
|
||||
inactiveColor: Colors.palette.m3secondary
|
||||
inactiveOnColor: Colors.palette.m3onSecondary
|
||||
scale: root.edit.readOnly ? 1 : 0
|
||||
isRound: true
|
||||
|
||||
Behavior on scale {
|
||||
Anim {}
|
||||
@@ -106,6 +109,7 @@ Item {
|
||||
inactiveColor: Colors.palette.m3tertiary
|
||||
inactiveOnColor: Colors.palette.m3onTertiary
|
||||
visible: root.isUser
|
||||
isRound: true
|
||||
|
||||
onClicked: {
|
||||
root.edit.readOnly = !root.edit.readOnly;
|
||||
|
||||
@@ -10,7 +10,7 @@ TextEditBase {
|
||||
color: Colors.palette.m3onSurface
|
||||
readOnly: true
|
||||
textFormat: Text.MarkdownText
|
||||
font.pointSize: Tokens.font.size.smaller
|
||||
font: Tokens.font.body.small
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
|
||||
onLinkActivated: link => {
|
||||
|
||||
@@ -66,7 +66,7 @@ Item {
|
||||
|
||||
LoadingIndicator {
|
||||
anchors.centerIn: parent
|
||||
implicitSize: Tokens.font.size.extraLarge * 4
|
||||
implicitSize: Tokens.font.icon.extraLarge.pointSize * 4
|
||||
opacity: root.loading ? 1 : 0
|
||||
visible: opacity > 0
|
||||
|
||||
|
||||
@@ -32,8 +32,7 @@ CustomRect {
|
||||
function onHighlightSpans(token, spans) {
|
||||
if (token !== root.highlightToken)
|
||||
return;
|
||||
if (root.code !== root.requestedCode ||
|
||||
root.language !== root.requestedLanguage)
|
||||
if (root.code !== root.requestedCode || root.language !== root.requestedLanguage)
|
||||
return;
|
||||
html = spans.length ? root.highlightedHtml(root.code, spans) : "";
|
||||
colored = root.visible && html.length > 0;
|
||||
@@ -84,15 +83,13 @@ CustomRect {
|
||||
// whitespace kept, mid-line runs collapsed, tabs as single spaces) so the
|
||||
// plain and colored layouts are identical.
|
||||
function plainForDisplay(code): string {
|
||||
return code.split("\n")
|
||||
.map(line => {
|
||||
return code.split("\n").map(line => {
|
||||
const i = line.search(/\S/);
|
||||
if (i < 0)
|
||||
return "";
|
||||
const lead = line.slice(0, i).replace(/\t/g, " ");
|
||||
return lead + line.slice(i).replace(/\s+/g, " ").replace(/\s+$/, "");
|
||||
})
|
||||
.join("\n");
|
||||
}).join("\n");
|
||||
}
|
||||
|
||||
function highlightedHtml(code, spans): string {
|
||||
@@ -136,7 +133,7 @@ CustomRect {
|
||||
refreshTimer.restart();
|
||||
}
|
||||
onVisibleChanged: if (root.visible)
|
||||
refreshTimer.restart();
|
||||
refreshTimer.restart()
|
||||
|
||||
Timer {
|
||||
id: refreshTimer
|
||||
@@ -223,7 +220,7 @@ CustomRect {
|
||||
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
color: root.codeHeaderColor
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.label.small
|
||||
text: CodeIcons.name(root.language)
|
||||
visible: root.language.length > 0
|
||||
}
|
||||
@@ -289,8 +286,7 @@ CustomRect {
|
||||
color: CodeColors.active.normal
|
||||
layer.enabled: true
|
||||
clip: false
|
||||
font.family: Config.appearance.font.family.mono
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.mono.small
|
||||
textFormat: root.colored ? Text.RichText : Text.PlainText
|
||||
text: root.colored ? root.html : root.plainForDisplay(root.code)
|
||||
readOnly: true
|
||||
|
||||
@@ -85,7 +85,7 @@ Item {
|
||||
animateCursor: false
|
||||
color: root.isUser ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||
cursor.color: root.isUser ? Colors.palette.m3onPrimary : Colors.palette.m3primary
|
||||
font.pointSize: Tokens.font.size.smaller
|
||||
font: Tokens.font.body.small
|
||||
readOnly: true
|
||||
selectionColor: Qt.alpha((root.isUser ? Colors.palette.m3onPrimary : Colors.palette.m3primary), 0.4)
|
||||
text: root.isUser ? root.segment.text : ""
|
||||
|
||||
@@ -93,7 +93,7 @@ Item {
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
font.pointSize: Tokens.font.size.large
|
||||
font: Tokens.font.headline.small
|
||||
elide: CustomText.ElideRight
|
||||
color: Colors.palette.m3onErrorContainer
|
||||
|
||||
@@ -120,7 +120,7 @@ Item {
|
||||
isRound: true
|
||||
icon: "close"
|
||||
type: IconButton.Text
|
||||
font.pointSize: Tokens.font.size.large
|
||||
font: Tokens.font.icon.medium
|
||||
|
||||
onClicked: exitAnim.start()
|
||||
}
|
||||
|
||||
@@ -62,13 +62,12 @@ Column {
|
||||
text: modelData.text
|
||||
textFormat: Text.MarkdownText
|
||||
readOnly: true
|
||||
font.bold: true
|
||||
font.pointSize: {
|
||||
font: {
|
||||
if (modelData.level <= 1)
|
||||
return Tokens.font.size.large;
|
||||
return Tokens.font.title.builders.large.weight(Font.Bold).build();
|
||||
if (modelData.level === 2)
|
||||
return Tokens.font.size.normal;
|
||||
return Tokens.font.size.smaller;
|
||||
return Tokens.font.title.builders.medium.weight(Font.Bold).build();
|
||||
return Tokens.font.title.builders.small.weight(Font.Bold).build();
|
||||
}
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ Item {
|
||||
|
||||
required property string latex
|
||||
property color mathColor: Colors.palette.m3onSurface
|
||||
property real fontSize: Tokens.font.size.large
|
||||
property font font: Tokens.font.headline.medium
|
||||
|
||||
implicitHeight: Math.max(equationImage.height, fallbackText.contentHeight) + Tokens.padding.small * 2
|
||||
|
||||
@@ -18,7 +18,7 @@ Item {
|
||||
|
||||
latex: root.latex
|
||||
color: root.mathColor
|
||||
fontPointSize: root.fontSize
|
||||
fontPointSize: root.font.pointSize
|
||||
devicePixelRatio: Screen.devicePixelRatio
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@ Item {
|
||||
|
||||
anchors.centerIn: parent
|
||||
color: root.mathColor
|
||||
font.family: Config.appearance.font.family.mono
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.mono.medium
|
||||
text: root.latex
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
visible: !math.ok
|
||||
|
||||
@@ -231,7 +231,7 @@ MouseArea {
|
||||
|
||||
MaterialIcon {
|
||||
anchors.centerIn: parent
|
||||
font.pointSize: Tokens.font.size.extraLarge
|
||||
fontStyle: Tokens.font.icon.extraLarge
|
||||
text: thumb.fileIcon(thumb.modelData?.mimeType ?? "")
|
||||
visible: !thumb.modelData?.isImage ?? false
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ Item {
|
||||
IconButton {
|
||||
id: expandBtn
|
||||
|
||||
font.pointSize: Tokens.font.size.large
|
||||
font: Tokens.font.icon.medium
|
||||
icon: "keyboard_arrow_down"
|
||||
inactiveOnColor: hovered ? Colors.palette.m3onSurface : Colors.palette.m3outline
|
||||
anchors.centerIn: parent
|
||||
@@ -91,7 +91,7 @@ Item {
|
||||
id: collapsedText
|
||||
|
||||
color: Colors.palette.m3outline
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.label.small
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: Tokens.spacing.medium
|
||||
text: {
|
||||
@@ -139,7 +139,7 @@ Item {
|
||||
CustomText {
|
||||
id: requestHeader
|
||||
text: qsTr("Tool call request")
|
||||
font.pointSize: Tokens.font.size.large
|
||||
font: Tokens.font.headline.medium
|
||||
color: Colors.palette.m3onSurface
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ Item {
|
||||
IconButton {
|
||||
id: toolExpandBtn
|
||||
|
||||
font.pointSize: Tokens.font.size.large
|
||||
font: Tokens.font.icon.medium
|
||||
icon: "keyboard_arrow_down"
|
||||
inactiveOnColor: hovered ? Colors.palette.m3onSurface : Colors.palette.m3outline
|
||||
rotation: toolCall.expanded ? 180 : 0
|
||||
@@ -609,7 +609,7 @@ Item {
|
||||
anchors.topMargin: Tokens.spacing.small
|
||||
anchors.right: parent.right
|
||||
color: Colors.palette.m3outline
|
||||
font.pointSize: Tokens.font.size.small
|
||||
font: Tokens.font.body.small
|
||||
wrapMode: CustomText.WrapAtWordBoundaryOrAnywhere
|
||||
text: segment.modelData.type === LlmSegment.Type.Reasoning ? segment.modelData.text : qsTr("%1 %2").arg(content.prettyTool(segment.modelData)).arg(content.toolTarget(segment.modelData))
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ Singleton {
|
||||
|
||||
function create(parent: Item, props: var): void {
|
||||
chatComp.createObject(parent ?? dummy, props);
|
||||
Visibilities.getForActive().sidebar = false;
|
||||
ShellState.forActive().sidebar = false;
|
||||
ChatState.isWindow = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ Item {
|
||||
|
||||
property int breakpoint: Math.round(Config.sidebar.sizes.width * 2) + Tokens.spacing.medium * 2 + Tokens.padding.medium * 3
|
||||
property color blobColor: Colors.tPalette.m3surfaceContainerLow
|
||||
readonly property int iconSize: Math.round(Tokens.font.size.extraLarge * (96 / 72)) + Tokens.padding.large * 2
|
||||
readonly property int iconSize: Math.round(Tokens.font.icon.extraLarge.pointSize * (96 / 72)) + Tokens.padding.large * 2
|
||||
property alias conversationModel: sidebar.model
|
||||
property bool chatOpen: ChatState.chatSession !== null
|
||||
|
||||
@@ -174,7 +174,7 @@ Item {
|
||||
MaterialIcon {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
text: "chat_bubble_off"
|
||||
font.pointSize: Tokens.font.size.extraLarge
|
||||
fontStyle: Tokens.font.icon.extraLarge
|
||||
color: Colors.tPalette.m3onSurfaceVariant
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Item {
|
||||
Connections {
|
||||
function onIsWindowChanged(): void {
|
||||
if (ChatState.isWindow)
|
||||
root.screenState.dashboardTab = 0;
|
||||
root.screenState.sidebarTab = 0;
|
||||
}
|
||||
|
||||
target: ChatState
|
||||
@@ -46,9 +46,9 @@ Item {
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.top: parent.top
|
||||
implicitWidth: parent.width
|
||||
opacity: root.screenState.dashboardTab === 0 ? 1 : 0
|
||||
opacity: root.screenState.sidebarTab === 0 ? 1 : 0
|
||||
visible: opacity > 0
|
||||
x: root.screenState.dashboardTab === 0 ? 0 : -root.width
|
||||
x: root.screenState.sidebarTab === 0 ? 0 : -root.width
|
||||
|
||||
Behavior on opacity {
|
||||
Anim {}
|
||||
@@ -80,9 +80,9 @@ Item {
|
||||
sourceComponent: Item {
|
||||
id: chatPage
|
||||
|
||||
opacity: root.screenState.dashboardTab === 1 ? 1 : 0
|
||||
opacity: root.screenState.sidebarTab === 1 ? 1 : 0
|
||||
visible: opacity > 0
|
||||
x: root.screenState.dashboardTab === 0 ? root.width : 0
|
||||
x: root.screenState.sidebarTab === 0 ? root.width : 0
|
||||
z: 1
|
||||
|
||||
Behavior on opacity {
|
||||
|
||||
@@ -24,7 +24,7 @@ Item {
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
background: null
|
||||
currentIndex: root.screenState.dashboardTab
|
||||
currentIndex: root.screenState.sidebarTab
|
||||
implicitHeight: contentHeight
|
||||
|
||||
contentItem: RowLayout {
|
||||
@@ -108,7 +108,7 @@ Item {
|
||||
color: tab.current ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||
radius: Tokens.rounding.small
|
||||
|
||||
onClicked: root.screenState.dashboardTab = tab.TabBar.index
|
||||
onClicked: root.screenState.sidebarTab = tab.TabBar.index
|
||||
}
|
||||
|
||||
MaterialIcon {
|
||||
@@ -118,7 +118,7 @@ Item {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
color: tab.current ? Colors.palette.m3primary : Colors.palette.m3onSurfaceVariant
|
||||
fill: tab.current ? 1 : 0
|
||||
font.pointSize: 18
|
||||
fontStyle: Tokens.font.icon.large
|
||||
text: tab.iconName
|
||||
|
||||
Behavior on fill {
|
||||
|
||||
@@ -12,7 +12,6 @@ DialogRowButton {
|
||||
|
||||
property var initialSelect
|
||||
property var selectedItem
|
||||
property var initialSelect
|
||||
|
||||
function keyFor(item: var): string {
|
||||
return item.id;
|
||||
|
||||
@@ -57,7 +57,6 @@ PageBase {
|
||||
icon: "add"
|
||||
last: true
|
||||
label: qsTr("Add entry")
|
||||
last: true
|
||||
model: {
|
||||
const present = new Set(Config.bar.tray.statusIcons.values.map(item => item.id));
|
||||
return Object.keys(root.builtinIcons).filter(id => !present.has(id)).map(id => ({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
qml_module(ZShell
|
||||
URI ZShell
|
||||
INCLUDE_PREFIX core
|
||||
SOURCES
|
||||
writefile.hpp writefile.cpp
|
||||
appdb.hpp appdb.cpp
|
||||
|
||||
@@ -1,36 +1,29 @@
|
||||
#pragma once
|
||||
#include "configobject.hpp"
|
||||
|
||||
#include <qhashfunctions.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmlintegration.h>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace ZShell::config {
|
||||
|
||||
class LlmAppearance : public ConfigObject {
|
||||
Q_OBJECT
|
||||
QML_ANONYMOUS
|
||||
class LlmAppearance : public settings::ObjectNode {
|
||||
CONFIG_NODE(LlmAppearance, settings::ObjectNode)
|
||||
|
||||
CFG_PROPERTY(QString, scheme, QStringLiteral("tokyoNight"))
|
||||
|
||||
public:
|
||||
explicit LlmAppearance(QObject* parent = nullptr) : ConfigObject(parent) {}
|
||||
CONFIG_PROPERTY(QString, scheme, QStringLiteral("tokyoNight"))
|
||||
};
|
||||
|
||||
class Llm : public ConfigObject {
|
||||
Q_OBJECT
|
||||
QML_ANONYMOUS
|
||||
class Llm : public settings::ObjectNode {
|
||||
CONFIG_NODE(Llm, settings::ObjectNode)
|
||||
|
||||
CFG_PROPERTY(QString, endpoint, "http://localhost:8080")
|
||||
CFG_PROPERTY(QString, model, "")
|
||||
CFG_PROPERTY(double, temperature, 0.7)
|
||||
CFG_PROPERTY(bool, tools, true)
|
||||
CFG_PROPERTY(bool, sandbox, true)
|
||||
CFG_PROPERTY(bool, enabled, true)
|
||||
CONFIG_PROPERTY(QString, endpoint, "http://localhost:8080")
|
||||
CONFIG_PROPERTY(QString, model, "")
|
||||
CONFIG_PROPERTY(double, temperature, 0.7)
|
||||
CONFIG_PROPERTY(bool, tools, true)
|
||||
CONFIG_PROPERTY(bool, sandbox, true)
|
||||
CONFIG_PROPERTY(bool, enabled, true)
|
||||
CONFIG_SUBOBJECT(LlmAppearance, appearance)
|
||||
|
||||
public:
|
||||
explicit Llm(QObject* parent = nullptr)
|
||||
: ConfigObject(parent), m_appearance(new LlmAppearance(this)) {}
|
||||
};
|
||||
|
||||
} // namespace ZShell::config
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "dock.hpp"
|
||||
#include "general.hpp"
|
||||
#include "launcher.hpp"
|
||||
#include "llm.hpp"
|
||||
#include "lock.hpp"
|
||||
#include "notifs.hpp"
|
||||
#include "osd.hpp"
|
||||
@@ -42,6 +43,7 @@ class ConfigRoot : public settings::RootNode {
|
||||
CONFIG_SUBOBJECT(Dock, dock)
|
||||
CONFIG_SUBOBJECT(General, general)
|
||||
CONFIG_SUBOBJECT(Launcher, launcher)
|
||||
CONFIG_SUBOBJECT(Llm, llm)
|
||||
CONFIG_SUBOBJECT(Lock, lock)
|
||||
CONFIG_SUBOBJECT(Notifs, notifs)
|
||||
CONFIG_SUBOBJECT(Osd, osd)
|
||||
|
||||
@@ -1,38 +1,14 @@
|
||||
# cmark-gfm: markdown -> block structure (pkg-config; no CMake config
|
||||
# package is installed).
|
||||
pkg_check_modules(CMARK_GFM REQUIRED IMPORTED_TARGET libcmark-gfm)
|
||||
|
||||
# tree-sitter runtime for code block highlighting (grammars are
|
||||
# dlopen()'d at runtime and optional).
|
||||
pkg_check_modules(TREE_SITTER REQUIRED IMPORTED_TARGET tree-sitter)
|
||||
|
||||
# JKQTMathText (JKQtPlotter) for LaTeX rendering. The config files live
|
||||
# in a shared JKQTPlotter6 directory, not one named after the package.
|
||||
find_path(JKQTPlotter6_CMAKE_DIR
|
||||
NAMES JKQTMathText6Config.cmake
|
||||
HINTS /usr/lib/cmake/JKQTPlotter6 /usr/local/lib/cmake/JKQTPlotter6
|
||||
DOC "Directory containing the JKQtPlotter cmake package files")
|
||||
find_package(JKQTMathText6 REQUIRED PATHS "${JKQTPlotter6_CMAKE_DIR}")
|
||||
|
||||
# --- tree-sitter grammar discovery (configure time) ---
|
||||
#
|
||||
# Discover installed tree-sitter grammars — system packages
|
||||
# (libtree-sitter-<lang>.so) and the parsers Neovim's nvim-treesitter
|
||||
# installs (~/.local/share/nvim/site/parser/*.so) — and pair each with
|
||||
# highlight queries. Query sources, in priority order:
|
||||
# 1. vendored highlight-queries/*.scm (version-pinned; see the
|
||||
# per-file source headers, MIT),
|
||||
# 2. Neovim's own queries (version-matched to its parsers),
|
||||
# 3. tree-sitter/highlighting from GitHub (cached in the build dir).
|
||||
# The result is embedded as highlight-queries.hpp. Re-run cmake to pick
|
||||
# up grammars installed later.
|
||||
#
|
||||
# Candidate entry points are read from the .so with `nm` rather than
|
||||
# assumed to be tree_sitter_<id>; a missing entry point just makes that
|
||||
# candidate fail at runtime.
|
||||
function(_ts_entry_point out file)
|
||||
# OUTPUT_VARIABLE + OUTPUT_QUIET loses the output on CMake 4, so
|
||||
# capture through a temp file.
|
||||
get_filename_component(_ts_nm_base "${file}" NAME)
|
||||
set(_ts_nm_file "${CMAKE_CURRENT_BINARY_DIR}/ts-entry-${_ts_nm_base}")
|
||||
execute_process(
|
||||
@@ -44,8 +20,6 @@ function(_ts_entry_point out file)
|
||||
if(_ts_nm_rc EQUAL 0 AND EXISTS "${_ts_nm_file}")
|
||||
file(READ "${_ts_nm_file}" _ts_nm_out)
|
||||
file(REMOVE "${_ts_nm_file}" "${_ts_nm_file}.err")
|
||||
# The library also exports the external scanner functions; the
|
||||
# entry point is the one without the _external suffix.
|
||||
string(REGEX MATCHALL " T tree_sitter_[A-Za-z0-9_]+" _ts_syms "${_ts_nm_out}")
|
||||
foreach(_ts_s IN LISTS _ts_syms)
|
||||
string(REPLACE " T " "" _ts_s "${_ts_s}")
|
||||
@@ -58,22 +32,11 @@ function(_ts_entry_point out file)
|
||||
set(${out} "${_ts_sym}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Append a query text to <files> (PARENT_SCOPE) unless it duplicates a
|
||||
# hash in <hashes>. The text is written to the build tree right away:
|
||||
# the s-expression `;` comments would split CMake list items and the
|
||||
# query `(` `)` break bracket arguments, so query text only ever lives
|
||||
# in variables and files, never in lists.
|
||||
# Expand Neovim's "; inherits:" directives by appending the inherited
|
||||
# query set's highlights file (recursively; a visited set prevents
|
||||
# cycles). Several languages are stubs that inherit the real query
|
||||
# (html inherits html_tags, qmljs inherits ecma, ...).
|
||||
function(_ts_expand_inherits query_dir text outVar)
|
||||
set(result "${text}")
|
||||
set(_visited "")
|
||||
set(_depth 0)
|
||||
while(_depth LESS 8)
|
||||
# Do not match the leading `;`: a MATCHALL result that itself
|
||||
# contains a semicolon is re-split into list items.
|
||||
string(REGEX MATCHALL "inherits:[ \t]*[A-Za-z0-9_]+" _inh "${result}")
|
||||
if(NOT _inh)
|
||||
break()
|
||||
@@ -99,7 +62,6 @@ function(_ts_expand_inherits query_dir text outVar)
|
||||
endfunction()
|
||||
|
||||
function(_ts_add_query sid text filesVar hashesVar)
|
||||
# filesVar/hashesVar hold the caller's variable names.
|
||||
set(files "${${filesVar}}")
|
||||
set(hashes "${${hashesVar}}")
|
||||
string(SHA256 _ts_qh "${text}")
|
||||
@@ -115,7 +77,7 @@ function(_ts_add_query sid text filesVar hashesVar)
|
||||
set(${hashesVar} "${hashes}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
set(_ts_candidates "") # entries: <id>|<cmake-safe id>|<lib>|<symbol>
|
||||
set(_ts_candidates "")
|
||||
file(GLOB _ts_sys_files
|
||||
"/usr/lib/libtree-sitter-*.so" "/usr/local/lib/libtree-sitter-*.so")
|
||||
foreach(_ts_file IN LISTS _ts_sys_files)
|
||||
@@ -164,20 +126,13 @@ set(_ts_vendored
|
||||
foreach(_ts_id IN LISTS _ts_ids)
|
||||
string(REPLACE "-" "_" _ts_sid "${_ts_id}")
|
||||
|
||||
# Query candidates in priority order (deduped; identical texts are
|
||||
# skipped, the nvim site and plugin copies are usually the same
|
||||
# file).
|
||||
set(_ts_qfiles "")
|
||||
set(_ts_qhashes "")
|
||||
if(_ts_id STREQUAL "cpp")
|
||||
# The C++ grammar is a superset of C and its query only covers
|
||||
# the C++ delta; base C coverage comes from the C query.
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/highlight-queries/c.scm" _ts_qa)
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/highlight-queries/cpp.scm" _ts_qb)
|
||||
_ts_add_query(${_ts_sid} "${_ts_qa}\n${_ts_qb}" _ts_qfiles _ts_qhashes)
|
||||
elseif(_ts_id STREQUAL "typescript" OR _ts_id STREQUAL "tsx")
|
||||
# The TS grammars reuse the JS node names; the JS query usually
|
||||
# compiles against them and gives full coverage.
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/highlight-queries/javascript.scm" _ts_qa)
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/highlight-queries/typescript.scm" _ts_qb)
|
||||
_ts_add_query(${_ts_sid} "${_ts_qa}\n${_ts_qb}" _ts_qfiles _ts_qhashes)
|
||||
@@ -195,10 +150,6 @@ foreach(_ts_id IN LISTS _ts_ids)
|
||||
endif()
|
||||
endforeach()
|
||||
if(NOT _ts_qfiles)
|
||||
# Last resort: fetch from the tree-sitter/highlighting repo.
|
||||
# Version-skewed against locally installed grammars, so only
|
||||
# used when nothing local exists. Cached; offline builds simply
|
||||
# drop the language.
|
||||
set(_ts_dl "${CMAKE_CURRENT_BINARY_DIR}/ts-query-downloads/${_ts_sid}.scm")
|
||||
if(NOT EXISTS "${_ts_dl}")
|
||||
file(DOWNLOAD
|
||||
@@ -219,7 +170,6 @@ foreach(_ts_id IN LISTS _ts_ids)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# Emit query sources.
|
||||
set(_ts_qn 0)
|
||||
set(_ts_q_ptrs "")
|
||||
foreach(_ts_qfile IN LISTS _ts_qfiles)
|
||||
@@ -232,7 +182,6 @@ foreach(_ts_id IN LISTS _ts_ids)
|
||||
string(APPEND _hl_header
|
||||
"inline constexpr const char* const q_${_ts_sid}[] = { ${_ts_q_ptrs} };\n")
|
||||
|
||||
# Emit library candidates (system package first, then Neovim).
|
||||
string(APPEND _hl_header "inline constexpr Candidate cand_${_ts_sid}[] = {\n")
|
||||
set(_ts_nc 0)
|
||||
foreach(_ts_c IN LISTS _ts_candidates)
|
||||
@@ -248,8 +197,7 @@ foreach(_ts_id IN LISTS _ts_ids)
|
||||
endforeach()
|
||||
string(APPEND _hl_header "};\n")
|
||||
if(_ts_nc EQUAL 0)
|
||||
# Queries but no library: pointless, drop the language.
|
||||
string(APPEND _hl_header "") # (arrays stay; grammar row is skipped)
|
||||
string(APPEND _hl_header "")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
@@ -263,8 +211,6 @@ endforeach()
|
||||
string(APPEND _hl_header "};\n}\n")
|
||||
file(WRITE "${HIGHLIGHT_QUERIES_HPP}" "${_hl_header}")
|
||||
|
||||
# Embed the vendored Latin Modern fonts (GUST Font License; provenance
|
||||
# in fonts/latinmodern/GUST-FONT-LICENSE.txt) as byte arrays.
|
||||
set(LM_FONTS
|
||||
lmroman10-regular
|
||||
lmroman10-italic
|
||||
@@ -314,4 +260,3 @@ qml_module(ZShell-llm
|
||||
)
|
||||
|
||||
target_include_directories(ZShell-llm PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(ZShell-llm PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../Config)
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#include "chat.hpp"
|
||||
|
||||
#include "config.hpp"
|
||||
#include "filetool.hpp"
|
||||
#include "llm.hpp"
|
||||
#include "llmclient.hpp"
|
||||
#include "shelltool.hpp"
|
||||
#include "webfetchtool.hpp"
|
||||
|
||||
#include "config/rootnodes.hpp"
|
||||
#include "config/llm.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace ZShell::llm {
|
||||
@@ -15,14 +16,12 @@ Chat::Chat(QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_store(new ChatStore(this))
|
||||
, m_client(new LlmClient(this)) {
|
||||
if (!config::Config::instance()) new config::Config();
|
||||
|
||||
m_store->setLlmClient(m_client);
|
||||
m_client->tools()->registerTool(new WebFetchTool(m_client->tools()));
|
||||
m_client->tools()->registerTool(new FileReadTool(m_client->tools()));
|
||||
m_client->tools()->registerTool(new ShellTool(m_client, m_client->tools()));
|
||||
|
||||
const auto* llm = config::Config::instance()->llm();
|
||||
const auto* llm = config::ConfigSingleton::instance()->llm();
|
||||
m_client->setEndpoint(llm->endpoint());
|
||||
m_client->setModel(llm->model());
|
||||
m_client->setTemperature(llm->temperature());
|
||||
@@ -144,7 +143,7 @@ bool Chat::toolsEnabled() const {
|
||||
|
||||
void Chat::setToolsEnabled(bool value) {
|
||||
m_client->setToolsEnabled(value);
|
||||
if (auto* config = config::Config::instance())
|
||||
if (auto* config = config::ConfigSingleton::instance())
|
||||
config->llm()->set_tools(value);
|
||||
}
|
||||
|
||||
@@ -154,7 +153,7 @@ bool Chat::sandboxEnabled() const {
|
||||
|
||||
void Chat::setSandboxEnabled(bool value) {
|
||||
m_client->setSandboxEnabled(value);
|
||||
if (auto* config = config::Config::instance())
|
||||
if (auto* config = config::ConfigSingleton::instance())
|
||||
config->llm()->set_sandbox(value);
|
||||
}
|
||||
|
||||
@@ -195,7 +194,8 @@ void Chat::refreshFromServer() {
|
||||
void Chat::selectModel(const QString& id) {
|
||||
if (id.isEmpty()) return;
|
||||
m_client->setModel(id);
|
||||
if (auto* config = config::Config::instance()) config->llm()->set_model(id);
|
||||
if (auto* config = config::ConfigSingleton::instance())
|
||||
config->llm()->set_model(id);
|
||||
}
|
||||
|
||||
} // namespace ZShell::llm
|
||||
|
||||
Reference in New Issue
Block a user