Десктоп
Окно Tauri 2, внутри которого живёт ядро snens как дочерний процесс. Один установщик, одно обновление: ядро, тулы, плагин памяти и клиент едут вместе.
Раскладка после установки
Windows, установка per-user, без UAC:
%LOCALAPPDATA%\snens\
├── snens-desktop.exe окно (Tauri)
├── snens.exe ядро: HTTP/API + статика клиента
├── memory.exe плагин долгой памяти
├── tools\ read, edit, grep, run, shot, web, desk…
└── web\ собранный клиент
Данные и конфиг — в %APPDATA%\snens, как у обычного snens: установка их не касается, удаление не трогает. Ссылки на тулы ядро раскладывает в bin/ в каталоге данных, а не установки: бандл только для чтения и перезаписывается обновлением, а bin/ — производная раскладка (на Windows — жёсткие ссылки, на unix — симлинки).
Почему ядро — сайдкар, а не служба
На Windows служба требует администратора и живёт в сессии 0, где нет ни профиля пользователя, ни UI. Поэтому ядро — обычный дочерний процесс окна, без консольного окна: у snens-desktop.exe стоит атрибут windows_subsystem = "windows", у дочернего ядра — CREATE_NO_WINDOW. Жизнь процесса привязана к окну.
Обновление одно на всё: сайдкары — часть бандла. На машине человека не нужны ни cargo, ни node, ни rustc.
Один процесс отдаёт и API, и клиент: snens serve умеет отдавать web/, поэтому отдельный vite в поставке не участвует. Окно всегда грузит свой клиент даже при подключении к чужому ядру — иначе экран подключения приезжал бы с сервера.
Трей и закрытие окна
Меню трея: «Открыть окно», «Перезагрузить интерфейс», «Выход (остановит ядро)». Крестик окна прячет окно, а не завершает приложение: ядро держит долгие ходы и подагентов. Выход — явный пункт меню, он же гасит ядро, чтобы следующая установка могла перезаписать файлы.
Пейринг: ядро на другом устройстве
Два режима, переключаются в настройках клиента (раздел «соединение»), а не флагами запуска:
- Локальное ядро (по умолчанию) — оболочка поднимает сайдкар на свободном порту, ждёт ready-файл с фактическим адресом и открывает окно на нём. Такое соединение на диск не сохраняется: при следующем запуске порт будет другой.
- Удалённое ядро — окно показывает форму подключения: адрес и код из
snens pairна сервере. Адрес и токен ложатся в файл конфигурации приложения (%APPDATA%\ch.svuvi.snens\connection.json), и при следующем запуске оболочка своё ядро не поднимает. «Вернуться к своему ядру» стирает этот файл.
После смены соединения оболочка пересоздаёт окно: перезагрузка страницы оставила бы клиент на старом адресе. Токен попадает в окно инжектом, а не через localStorage.
Коды пейринга и отзыв устройств — Привилегии и доверие.
Первый запуск
- Установщик кладёт бандл в профиль пользователя и запускает приложение.
- Оболочка поднимает ядро и открывает окно на нём — экрана с адресом и токеном нет.
- Провайдер (адрес, модель, ключ) задаётся в настройках клиента. Пока его нет, ядро уже работает и отвечает: первый ход вернёт ошибку про ненайденный ключ, а не «сервер не запустился».
- Если ядро живёт на другом устройстве, в разделе «соединение» выбирается удалённый режим и вводится код с сервера.
Где лежат установщик и манифест
latest.json— манифест обновления, его читаетtauri-plugin-updaterпри старте окна;- каталог версии рядом с манифестом — неизменяемые артефакты этой версии (установщик и его подпись).
Адрес манифеста зашит в конфигурацию приложения, ключ проверки подписи — тоже. Каталог версии не перезаписывается: человек на прошлой версии ещё может качать её артефакт.
Сборка релиза
TAURI_SIGNING_PRIVATE_KEY_PATH=~/.config/snens/updater.key scripts/release.sh --check
TAURI_SIGNING_PRIVATE_KEY_PATH=~/.config/snens/updater.key scripts/release.sh
Скрипт делает четыре шага: раскладывает сайдкары и клиент (scripts/desktop-stage.sh — единственное место, где записано «что куда кладётся», бинарники получают суффикс target-triple), собирает бандлы nsis/appimage/deb с подписью, генерирует latest.json, затем копирует всё в каталог раздачи, выставляя каталогам 0755, файлам 0644.
Что нужно, чтобы собрать:
- ключ подписи updater'а: без него скрипт не начнёт, а приложение не примет обновление; ключ живёт только на машине релиза, в git его нет;
- сборка идёт на Windows — на сервере без glib/webkit бандл не собирается;
- тулы собираются
cargo build --release --workspace, клиент —npm run buildв каталоге клиента.
Версия берётся из desktop/tauri.conf.json — её меняют перед релизом, она же попадает в манифест.
Откат — установщик прошлой версии из её каталога; данные и конфиг установка не трогает.