auto-git:

[change] AGENTS.md
 [change] README.md
 [change] docs/tauri-migration.md
This commit is contained in:
2026-05-06 06:00:00 +02:00
parent 514fde9cad
commit 8946f26813
3 changed files with 77 additions and 98 deletions

View File

@@ -2,9 +2,7 @@
## Project Overview
Heimgeist is a local desktop chat app for Ollama. It uses a React/Vite renderer, an Electron desktop shell, a FastAPI backend, SQLite chat storage, Whisper transcription, optional SearXNG web search, and local RAG libraries under the backend.
A future migration to Tauri is planned, but do not begin that migration unless the task explicitly asks for it. Electron support must remain intact until Tauri reaches feature parity.
Heimgeist is a local desktop chat app for Ollama. It uses a React/Vite renderer, a Tauri desktop shell, a FastAPI backend, SQLite chat storage, Whisper transcription, optional SearXNG web search, and local RAG libraries under the backend.
## Important Directories and Entry Points
@@ -14,11 +12,8 @@ A future migration to Tauri is planned, but do not begin that migration unless t
- `src/chatApi.js`, `src/chatGeneration.js`, and `src/backendApi.js` contain backend request and streaming helpers.
- `src/desktop/desktopApi.js` is the renderer platform abstraction for desktop APIs.
- `src/styles.css` contains the main UI styling.
- `electron/` - Electron desktop shell.
- `electron/main.cjs` creates windows, stores settings, handles updates, and implements IPC handlers.
- `electron/preload.cjs` exposes the Electron IPC surface as `window.electronAPI`.
- `src-tauri/` - isolated Tauri migration scaffold.
- `src-tauri/src/main.rs` owns Tauri commands for the renderer `desktopApi` surface.
- `src-tauri/` - Tauri desktop shell.
- `src-tauri/src/main.rs` owns Tauri commands for the renderer `desktopApi` surface, settings persistence, dialogs, path opening, external links, focus events, and update placeholders.
- `src-tauri/tauri.conf.json` points Tauri at the existing Vite renderer.
- `src-tauri/capabilities/` contains Tauri permission grants for enabled plugins.
- `backend/` - FastAPI backend and local processing.
@@ -29,33 +24,28 @@ A future migration to Tauri is planned, but do not begin that migration unless t
- `backend/database.py` points SQLite at `backend/app.db`.
- `scripts/` - development wrappers used by npm scripts.
- `scripts/run-backend.cjs` starts Uvicorn from `backend/.venv`.
- `scripts/run-electron-dev.cjs` waits for Vite and FastAPI, then launches Electron.
- `scripts/run-tauri-dev.cjs` starts or reuses FastAPI, then launches the Tauri dev shell.
- `run.sh` - bootstrap script for local development dependencies and dev startup.
- `vite.config.js` - Vite dev/build configuration. Electron dev uses `127.0.0.1:5173`; Tauri dev uses an additive strict Vite port at `127.0.0.1:5174`.
- `vite.config.js` - Vite dev/build configuration. Tauri dev uses the strict Vite port `127.0.0.1:5174`.
## Run and Build Commands
- `./run.sh` - bootstrap/update Python and npm dependencies, then start the full dev stack.
- `npm run dev` - start backend, Vite renderer, and Electron together.
- `npm run dev` - start or reuse FastAPI on `127.0.0.1:8000`, start the Vite renderer on `127.0.0.1:5174`, then launch Tauri.
- `npm run dev:tauri` - alias for the primary Tauri development workflow.
- `npm run dev:backend` - start FastAPI on `127.0.0.1:8000` with reload. Requires `backend/.venv`.
- `npm run dev:renderer` - start Vite on `127.0.0.1:5173`.
- `npm run dev:renderer:tauri` - start Vite on `127.0.0.1:5174` for Tauri.
- `npm run dev:electron` - wait for Vite and backend health, then start Electron.
- `npm run dev:tauri` - start or reuse FastAPI on `127.0.0.1:8000`, start the Tauri Vite renderer on `127.0.0.1:5174`, then launch the Tauri shell.
- `npm run dev:renderer` - start Vite on `127.0.0.1:5174` for Tauri.
- `npm run dev:tauri:shell` - launch the raw Tauri shell when backend lifecycle is managed separately.
- `npm run build` - build the renderer into `dist/`.
- `npm start` - start Electron against the current app files.
- `npm start` - alias for `npm run dev`.
There are currently no npm `test` or `lint` scripts in `package.json`.
## Architectural Boundaries
- Renderer code should remain platform-neutral where practical. It may call backend HTTP APIs and may call `desktopApi`, but it should not call `window.electronAPI` directly.
- `src/desktop/desktopApi.js` is the renderer's platform abstraction. Add desktop capabilities there first, then back them with Electron IPC. This keeps the future Tauri migration bounded.
- `electron/preload.cjs` is the only file that should expose raw Electron IPC to the renderer.
- `electron/main.cjs` owns desktop concerns: windows, dialogs, shell opening, settings persistence, update checks, and IPC implementations.
- `src-tauri/src/main.rs` owns the Tauri implementation of the same renderer `desktopApi` surface during migration. Keep it additive and do not remove Electron behavior until Tauri reaches parity.
- Renderer code should remain platform-neutral where practical. It may call backend HTTP APIs and may call `desktopApi`, but it should not import or call Tauri APIs directly.
- `src/desktop/desktopApi.js` is the renderer's platform abstraction. Add desktop capabilities there first, then back them with Tauri commands/events.
- `src-tauri/src/main.rs` owns desktop concerns: windows, menus, dialogs, shell opening, settings persistence, update placeholders, focus events, and Tauri command implementations.
- Backend code owns chat/session persistence, Ollama integration, Whisper transcription, web search enrichment, and RAG library processing.
- Backend API contracts should stay stable unless intentionally coordinated with renderer changes. If a response/request shape changes in `backend/schemas.py` or route handlers, update the renderer callers in the same change.
- Keep local RAG job orchestration and generated library state in the backend. Renderer code should use backend endpoints rather than reading library files directly.
@@ -70,28 +60,27 @@ Do not edit or commit generated/runtime data unless the task explicitly requires
- `node_modules/` - npm dependencies.
- `dist/` - Vite build output.
- `__pycache__/`, `*.pyc`, `.DS_Store`, and similar machine-generated files.
- Local app settings files under the Electron user data directory, the Tauri app config directory, or `HEIMGEIST_SETTINGS_FILE`.
- Local app settings files under the Tauri app config directory or `HEIMGEIST_SETTINGS_FILE`.
- Tauri-generated `src-tauri/target/`, `src-tauri/gen/`, and local `src-tauri/Cargo.lock` if generated by local verification.
Avoid broad file operations that traverse these directories. Use ignore patterns with search tools when inspecting the repo.
## Verification Expectations
- Frontend changes: run `npm run build` at minimum. For UI or interaction changes, also run the dev stack and exercise the affected flow in Electron.
- Frontend changes: run `npm run build` at minimum. For UI or interaction changes, also run the dev stack and exercise the affected flow in Tauri.
- Backend changes: run a targeted syntax/import check such as `backend/.venv/bin/python -m py_compile backend/main.py backend/local_rag.py` for touched modules, then start `npm run dev:backend` or the full dev stack and check `GET /health`.
- Desktop bridge/Electron changes: run the full dev stack with `npm run dev` and verify Electron launches, settings load/save, dialogs or shell actions work, and no renderer code bypasses `src/desktop/desktopApi.js`.
- Tauri desktop bridge changes: run `cargo check --manifest-path src-tauri/Cargo.toml` with a temp `CARGO_TARGET_DIR` when useful, run `npm run build`, and if practical run `npm run dev:tauri`. Use a temporary `HEIMGEIST_SETTINGS_FILE` when testing ordinary shared settings behavior; use a temporary `HOME` with a fake Electron settings file when testing first-run import, because `HEIMGEIST_SETTINGS_FILE` intentionally bypasses import.
- Desktop bridge/Tauri changes: run `cargo check --manifest-path src-tauri/Cargo.toml` with a temp `CARGO_TARGET_DIR` when useful, run `npm run build`, and if practical run `npm run dev`. Use a temporary `HEIMGEIST_SETTINGS_FILE` when testing ordinary shared settings behavior; use a temporary `HOME` with a fake legacy settings file when testing first-run import, because `HEIMGEIST_SETTINGS_FILE` intentionally bypasses import.
- API contract changes: verify both sides together. Update backend schemas/routes and renderer callers in the same change, then exercise the affected request path.
- RAG, Whisper, Ollama, or SearXNG changes: note any external services or local models required for verification, and test graceful failure paths when those services are unavailable.
## Future Tauri Migration Guidance
## Tauri Guidance
- Do not start a Tauri migration opportunistically.
- Keep new renderer desktop calls behind `src/desktop/desktopApi.js`; do not spread Electron-specific assumptions through React components.
- Keep Tauri renderer calls behind `src/desktop/desktopApi.js`; do not import Tauri APIs directly in React components.
- When adding desktop capabilities, prefer method names and payloads that could map cleanly to either Electron IPC or Tauri commands.
- Maintain Electron behavior while any Tauri work is incomplete. Electron remains the supported desktop shell until Tauri reaches feature parity for settings, file picking/opening, external links, update flow, window events, backend startup expectations, and packaging.
- During migration, Tauri settings should import Electron settings only on first run when Tauri settings do not already exist. Preserve `HEIMGEIST_SETTINGS_FILE` as an explicit shared override and do not move or rewrite `backend/app.db` or `backend/libraries`.
- Keep renderer desktop calls behind `src/desktop/desktopApi.js`; do not import Tauri APIs directly in React components.
- When adding desktop capabilities, prefer method names and payloads that stay stable for renderer callers.
- Preserve `HEIMGEIST_SETTINGS_FILE` as an explicit shared settings override.
- Keep first-run legacy settings import available when Tauri settings do not already exist.
- Do not move or rewrite `backend/app.db` or `backend/libraries`; the development backend must keep using the existing backend working directory.
- Production-release work still needs backend sidecar packaging, signed updater/changelog parity, bundle metadata, signing/notarization, and installer behavior.
- Avoid refactors that mix migration prep with unrelated feature work. Migration work should be explicit and reviewable.
## Coding and Refactor Guidelines
@@ -107,7 +96,7 @@ Avoid broad file operations that traverse these directories. Use ignore patterns
## Known Fragile Areas
- The Electron bridge is intentionally narrow. Direct `window.electronAPI` use in renderer files will make Tauri migration harder.
- The Tauri bridge is intentionally narrow. Direct `window.__TAURI__` use outside `src/desktop/desktopApi.js` makes desktop behavior harder to reason about.
- `src/App.jsx`, `src/chatGeneration.js`, and backend chat routes share assumptions about streaming, regeneration, attachments, source metadata, and session state.
- `backend/main.py` creates/migrates SQLite tables at import/startup. Schema changes need care because they run against local user data.
- `backend/local_rag.py` coordinates asynchronous jobs, file registration, generated artifacts, and per-library locks. Avoid changes that can start duplicate jobs or corrupt `backend/libraries/`.

View File

@@ -1,10 +1,10 @@
# Heimgeist
Heimgeist is a local desktop chat client for Ollama. It combines an Electron + React renderer with a FastAPI backend, stores chat history in SQLite, supports optional SearXNG-backed web search, and can enrich prompts with context from local library indexes.
Heimgeist is a local desktop chat client for Ollama. It combines a Tauri + React renderer with a FastAPI backend, stores chat history in SQLite, supports optional SearXNG-backed web search, and can enrich prompts with context from local library indexes.
## Features
- Local desktop chat UI with Electron
- Local desktop chat UI with Tauri
- Ollama-backed chat with streaming and non-streaming replies
- Persistent chat sessions and automatic title generation
- Edit-and-regenerate flow for earlier user messages
@@ -25,7 +25,7 @@ When files are added or removed, Heimgeist automatically rebuilds the local RAG
## Stack
- Frontend: Electron, React, Vite
- Frontend: Tauri, React, Vite
- Backend: FastAPI, SQLAlchemy, SQLite
- Search enrichment: SearXNG + page fetching/reranking
- Local RAG pipeline: corpus build, enrichment, embedding, and retrieval helpers under `backend/rag/`
@@ -80,9 +80,10 @@ npm run dev
│ ├── database.py
│ ├── schemas.py
│ └── requirements.txt
├── electron/
│ ├── main.cjs
── preload.cjs
├── src-tauri/
│ ├── src/main.rs
── tauri.conf.json
│ └── capabilities/
├── src/
│ ├── App.jsx
│ ├── LibraryManager.jsx

View File

@@ -1,74 +1,63 @@
# Tauri Migration Notes
Tauri is now the primary experimental development shell for Heimgeist. Electron remains intact as a fallback until the remaining desktop and packaging gaps are closed.
Tauri is now Heimgeist's active desktop shell for local development. The former desktop shell runtime files and npm scripts have been removed from active development code.
References checked during the spike:
## Current Development Workflow
- Tauri Vite setup: https://v2.tauri.app/start/frontend/vite/
- Tauri JavaScript API: https://v2.tauri.app/reference/javascript/api/
- Tauri CLI: https://v2.tauri.app/reference/cli/
- Tauri dialog plugin: https://v2.tauri.app/plugin/dialog/
- Tauri opener plugin: https://v2.tauri.app/plugin/opener/
- Primary dev command: `npm run dev`.
- Compatibility alias: `npm run dev:tauri`.
- The dev wrapper is `scripts/run-tauri-dev.cjs`.
- The wrapper starts or reuses FastAPI on `127.0.0.1:8000`, waits for `/health`, then launches Tauri.
- The Vite renderer runs on strict port `127.0.0.1:5174`.
- `npm run dev:tauri:shell` launches raw `tauri dev` when the backend lifecycle is managed separately.
## Current Desktop Responsibility Map
| Area | Electron implementation | Tauri status |
| --- | --- | --- |
| Main app window | `BrowserWindow` in `electron/main.cjs`, loading Vite in dev and `dist/index.html` in production | Implemented through `src-tauri/tauri.conf.json`; dev loads the same React/Vite renderer on the Tauri-specific port `5174` |
| Settings window | Separate modal `BrowserWindow` routed to `#/settings` | Later phase: either a second Tauri webview window or the existing in-app settings route |
| Settings persistence | JSON under Electron `app.getPath('userData')`, or `HEIMGEIST_SETTINGS_FILE` when set | Implemented with persistent JSON under Tauri app config, with a first-run Electron settings import when safe |
| Renderer bridge | `electron/preload.cjs` exposes `window.electronAPI`; renderer uses `src/desktop/desktopApi.js` | Implemented: `desktopApi` still prefers Electron and falls back to Tauri commands/listeners |
| File picker | `dialog.showOpenDialog` via `pick-paths` IPC | Implemented through the official Tauri dialog plugin; supports the existing `title`, `filters`, and `multiple` option shape where practical |
| Open file/path | `shell.openPath` via `open-path` IPC | Implemented through the official Tauri opener plugin |
| External links | `shell.openExternal` and `setWindowOpenHandler` | Implemented through the official Tauri opener plugin for `http`, `https`, `mailto`, and `tel` URLs |
| Window focus events | Electron `focus` event forwarded to renderer | Implemented by emitting `window-focused` from Tauri and listening in `desktopApi` |
| App menu | Electron `Menu.buildFromTemplate` | Basic Tauri default menu implemented; detailed Electron menu parity remains later work |
| UI scale | Electron `webContents.setZoomFactor` | Implemented for Tauri/browser-like runtimes through `desktopApi.applyUiScale`, which applies renderer CSS zoom while leaving Electron native zoom unchanged |
| DevTools preference | Electron opens/closes DevTools in dev | Later phase: no clean stable Tauri equivalent is wired yet |
| Updates/changelog | Git-based update check, pull, restart, and local changelog | Later phase: replace with Tauri updater or another signed update flow |
| Backend lifecycle | External Node scripts start FastAPI in dev | Development parity implemented by `scripts/run-tauri-dev.cjs`, which starts or reuses the existing FastAPI dev backend; Python sidecar packaging remains later |
| Packaging | Electron starts from `main` and existing npm scripts | Later phase: Tauri bundle config, icons, signing/notarization, and Python backend sidecar |
## Development Workflow
- Electron development remains unchanged: `npm run dev`.
- Tauri development is now `npm run dev:tauri` or `npm run dev:tauri:full`.
- The Tauri wrapper starts or reuses FastAPI on `127.0.0.1:8000`, waits for `/health`, then launches Tauri.
- Tauri uses its own strict Vite dev port: `127.0.0.1:5174`. This avoids conflicts with the existing Electron renderer port `5173`.
- The raw Tauri shell remains available as `npm run dev:tauri:shell`; use it only when the backend lifecycle is managed separately.
The Tauri dev backend is still the normal FastAPI backend started from the repository root through `scripts/run-backend.cjs`. That keeps chat history and local RAG data in the existing backend locations.
The development backend is still the normal FastAPI backend started from the repository root through `scripts/run-backend.cjs`.
## User Data Continuity
- Chats continue to use `backend/app.db` through the existing FastAPI backend. No database move, rewrite, or migration is part of this step.
- Local RAG libraries continue to use `backend/libraries` through the existing FastAPI backend. No library state is moved or rewritten.
- `HEIMGEIST_SETTINGS_FILE` remains an explicit shared settings override for both Electron and Tauri. When it is set, Tauri reads and writes that file directly and does not perform first-run import.
- Chats continue to use `backend/app.db` through the existing FastAPI backend.
- Local RAG libraries continue to use `backend/libraries` through the existing FastAPI backend.
- No database or library state is moved, rewritten, or migrated by the Tauri shell.
- `HEIMGEIST_SETTINGS_FILE` remains an explicit shared settings override. When set, Tauri reads and writes that file directly and skips first-run import.
- Without `HEIMGEIST_SETTINGS_FILE`, Tauri stores settings in its app config `settings.json`.
- On first Tauri run only, when the Tauri settings file does not exist, Tauri attempts to read Electron settings from the platform config directory, including the existing `Heimgeist/settings.json` path used by Electron.
- If Electron settings are found, Tauri migrates and normalizes them into the Tauri settings path.
- Existing Tauri settings are not replaced by Electron settings.
- On first Tauri run only, when the Tauri settings file does not exist, Tauri attempts to import the historical Electron settings file from the platform config directory, including `Heimgeist/settings.json`.
- Existing Tauri settings are never overwritten by imported settings.
## Current Tauri Scaffold
## Desktop Bridge Surface
- `src-tauri/src/main.rs` registers Tauri commands for settings, dialogs, path opening, external links, focus events, and update placeholders.
- `src-tauri/capabilities/default.json` grants the main window core, dialog, and opener permissions used by the scaffold.
- `src-tauri/tauri.conf.json` points Tauri at the existing Vite renderer on `http://127.0.0.1:5174` in dev and `../dist` for build output.
- `scripts/run-tauri-dev.cjs` is the full Tauri dev wrapper.
- `src/desktop/desktopApi.js` remains the only renderer bridge layer for Electron/Tauri desktop functions.
Renderer code should continue to call only `src/desktop/desktopApi.js` for desktop functions. That bridge owns direct access to the Tauri global and maps the renderer API to Tauri commands/events.
## Intentional Non-Goals
Current Tauri-backed desktop methods:
- No Electron files, scripts, dependencies, or IPC behavior were removed.
- No backend API contracts changed.
- No Python backend sidecar, production backend packaging, or data relocation was added.
- No Tauri updater, changelog parity, or restart flow was implemented.
- `getSettings`
- `setSetting`
- `updateSettings`
- `pickPaths`
- `openPath`
- `openExternalLink`
- `onWindowFocus`
- `offWindowFocus`
- `applyUiScale`
- update/changelog placeholders
## Remaining Gaps Before Electron Removal
## Historical Removal Notes
- Update flow: startup/manual update checks, changelog, restart, and signed release strategy.
- Production backend lifecycle: package the FastAPI backend, set ffmpeg/ffprobe paths, health gate startup, and shut down cleanly.
- DevTools preference: Electron honors `openDevToolsOnStartup`; Tauri currently documents this as an Electron-only setting.
- Settings window parity: Electron still has a separate settings modal; Tauri currently uses the existing renderer route.
- App menu parity: Tauri has a basic default menu, not the full Electron template.
- Packaging: bundle metadata, final icons, signing/notarization, updater channel, and installer behavior.
This pass removed the former Electron runtime and development entry points:
- `electron/main.cjs`
- `electron/preload.cjs`
- `scripts/run-electron-dev.cjs`
- Electron npm metadata, dependencies, and scripts from `package.json`
- Electron-specific branches from `src/desktop/desktopApi.js`
The only remaining Electron references should be historical migration documentation or the Tauri first-run settings import note.
## Remaining Production-Release Tasks
- Replace update/changelog placeholders with a signed Tauri update flow or another release strategy.
- Package the FastAPI backend as a sidecar or equivalent production process.
- Preserve ffmpeg/ffprobe environment handling for packaged audio transcription.
- Add production backend startup health gating and shutdown behavior.
- Finalize bundle metadata, icons, signing, notarization, and installer behavior.
- Decide whether the settings route needs a dedicated Tauri window for production parity.
- Expand the basic Tauri menu if product-specific app menu actions are needed.