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

This commit is contained in:
2026-09-30 19:30:06 +02:00
parent 54f966b4ea
commit e8bf8b9727
29 changed files with 201 additions and 268 deletions
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+4 -8
View File
@@ -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
}
+5 -5
View File
@@ -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 {
+3 -3
View File
@@ -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
View File
@@ -1,5 +1,6 @@
qml_module(ZShell
URI ZShell
INCLUDE_PREFIX core
SOURCES
writefile.hpp writefile.cpp
appdb.hpp appdb.cpp
+14 -21
View File
@@ -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
+2
View File
@@ -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)
+2 -57
View File
@@ -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)
+8 -8
View File
@@ -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