desktop: the window installs itself (launcher entry, icon, default.nix)

app/linux/cst-agent-app.{desktop,svg} plus one CMake component ("app") in
app/CMakeLists.txt: `cmake --install --component app` puts the binary in bin/,
the entry in share/applications/ and the icon in hicolor/scalable/apps/. The
entry's file name stays the app_id Qt sets (QGuiApplication::applicationName),
or the launcher draws a generic icon; only the front end installs, the CLI
keeps coming from scripts/bootstrap_linux.sh.

default.nix is that install for nix users: nixpkgs' Qt 6 (qtwayland for a
Wayland session, qtsvg for Breeze's SVG icons), wrapQtAppsHook so the plugins
and QML modules resolve outside a nix-shell and survive nix-collect-garbage,
a filtered src (third_party/ and the build directories are gigabytes this
build never reads), and the version read from include/cst_version.h. doCheck
runs ctest minus test_sandbox, whose Landlock assertion cannot hold inside the
nix build sandbox (the other 40 pass there; make check runs all 41).

Verified: nix-build, nix profile add --file ., then --selftest and --uitest in
a clean environment (no nix-shell, no XDG_* from the session).
This commit is contained in:
WHC
2026-10-11 18:44:31 +08:00
parent 580d533656
commit 2ffe74b37c
7 changed files with 191 additions and 0 deletions
+21
View File
@@ -14,6 +14,10 @@ project(cst-agent-app LANGUAGES C CXX VERSION 0.1.0)
# Inside the repo build (the parent defines the cstcore target, shared with the CLI):
# cmake -B build -DCST_BUILD_APP=ON && cmake --build build --target cst-agent-app
#
# Desktop install (the window, its launcher entry and the icon; the CLI has
# its own installer) -- default.nix installs exactly this component:
# cmake --install build --component app --prefix ~/.local
#
# Extra QML import paths, e.g. a Kirigami installed away from the Qt prefix:
# -DCST_APP_QML_IMPORT=... (added to QML2_IMPORT_PATH / the app's runtime)
@@ -119,6 +123,23 @@ if(CST_APP_GUI)
set_target_properties(cst-agent-app PROPERTIES WIN32_EXECUTABLE TRUE)
endif()
# A desktop install. The icon goes where the theme layout says, so the
# entry's Icon= name finds it, and the entry's file name is the app_id Qt
# sets (QGuiApplication::applicationName) -- rename one and the launcher
# loses the icon. All of it in the "app" component: the CLI keeps coming
# from scripts/bootstrap_linux.sh, and two `cst-agent` in PATH is how a
# version nobody meant to run gets run.
if(NOT ANDROID)
include(GNUInstallDirs)
install(TARGETS cst-agent-app
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT app)
install(FILES linux/cst-agent-app.desktop
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications COMPONENT app)
install(FILES linux/cst-agent-app.svg
DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps
COMPONENT app)
endif()
# --- Android (APK) -----------------------------------------------------
# The engine is compiled in (top-level CMakeLists: -DCST_BUILD_TUI=OFF,
# -DCST_BUILD_WEBUI=OFF, so src/webui_stub.c stands in for the server and
+26
View File
@@ -45,6 +45,31 @@ navigation drawer) so swapping in `org.kde.kirigami` later is a QML-only
change. Point the app at a Kirigami outside the Qt prefix with
`-DCST_APP_QML_IMPORT=/path/to/qml`.
## Install (Linux desktop)
The window installs itself: the binary, a launcher entry and the icon the
launcher draws for it. All three are one CMake component (`app`), so the CLI
keeps coming from `scripts/bootstrap_linux.sh` and the profile never holds two
`cst-agent` of different vintages; the files live in `app/linux/`.
```sh
# NixOS / nix users: PATH + menu entry + icon. The Qt apps hook bakes the
# plugin and QML module paths into the wrapper, so the app runs outside a
# nix-shell and nix-collect-garbage cannot pull Qt out from under it.
nix-build # ./result/bin/cst-agent-app, run it in place
nix profile add --file . # or: ./result/bin/cst-agent-app
nix profile remove cst-agent # uninstall
# anywhere with Qt 6 (Quick/Qml/QuickControls2) and libcurl:
cmake -B build-app -DCST_BUILD_APP=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build-app -j
cmake --install build-app --component app --prefix ~/.local
```
Launched from a menu, the workspace is the directory the app starts in
(`$HOME` there), so sessions land in `~/.agent/sessions`; pass
`--workspace <dir>` to pin another one.
## Why in one process
The engine is a library, not a daemon: `libcstcore.a` (Makefile) / the
@@ -408,6 +433,7 @@ so nothing about it is visible when the app is idle.
file card's open/share through the app's FileProvider
- [x] a turn keeps running with the app off screen (Android foreground service
+ wake lock; nothing to do on a desktop)
- [x] desktop install: launcher entry + icon, `nix profile add --file .`
- [ ] a real turn driven through the window (needs a provider key)
- [ ] SAF file picker, the back gesture, the icon glyphs on the phone
- [ ] Kirigami (the rest of the Breeze look: colors, controls), tray,
+15
View File
@@ -0,0 +1,15 @@
[Desktop Entry]
Type=Application
Name=CST-agent
GenericName=Local coding agent
Comment=The engine in a window: workspace is the directory it is started in
Exec=cst-agent-app
TryExec=cst-agent-app
Icon=cst-agent-app
Terminal=false
StartupNotify=true
# Qt puts the application name in the Wayland app_id / WM_CLASS, so this has to
# stay the file's own name or the launcher draws a generic icon.
StartupWMClass=cst-agent-app
Categories=Development;Utility;
Keywords=agent;ai;assistant;code;
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- The launcher icon: the prompt the CLI shows, on a tile in the window's own
palette (app/qml/Theme.qml). Installed under hicolor/scalable, so the
desktops that want raster sizes render it themselves. -->
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
<rect x="6" y="6" width="116" height="116" rx="26" ry="26"
fill="#15181a" stroke="#343b41" stroke-width="5"/>
<path d="M36 42 L56 64 L36 86" fill="none" stroke="#3daee9" stroke-width="12"
stroke-linecap="round" stroke-linejoin="round"/>
<path d="M69 88 H94" fill="none" stroke="#eff0f1" stroke-width="12"
stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 712 B