3.3 KiB
AGENTS.md
These instructions cover the Rust runtime in runtime/. They add to the AGENTS.md in the repository
root, which applies here as well.
Rust Runtime (runtime/)
Entry point: runtime/src/main.rs
Key modules:
app_window.rs- Tauri window management, updater integrationdotnet.rs- Launches and manages the .NET sidecar processruntime_api.rs- Axum-based HTTPS API for .NET ↔ Rust communicationcertificate.rs- Generates self-signed TLS certificates for secure IPCsecret.rs- Secure secret storage using OS keyring (Keychain/Credential Manager)clipboard.rs- Cross-platform clipboard operationsfile_data.rs- File processing for RAG (extracts text from PDF, DOCX, XLSX, PPTX, etc.)encryption.rs- AES-256-CBC encryption for sensitive datapandoc.rs- Integration with Pandoc for document conversionlog.rs- Logging infrastructure usingflexi_logger
Every runtime API route requires the API token. require_api_token in runtime_api.rs checks it
for all routes at once, so handlers take no APIToken argument. Register a new route in
create_router, before that call: route_layer protects only the routes registered before it, and
a route added afterward would be open to every process on the machine. The test
every_route_requires_the_api_token reads the routes from create_router and fails for any route
which answers without the token.
Runtime API handlers never block. All calls of the .NET app share one HTTP/2 connection, and the task driving it may wait on exactly the Tokio worker which a blocking handler occupies, so a single blocking handler can hold up the whole app. Therefore:
- File and disk access, the OS keyring, waiting for a
std::sync::Mutex, and CPU-bound work such as loading a tokenizer or scanning text run intokio::task::spawn_blocking. Followrun_qdrant_edge_requestinqdrant_edge_database.rs,prepare_imageandprepare_image_syncinimage.rs, orsanitize_batchinprompt_injection/api.rs. - When an API offers a callback, as the file dialogs do, await the callback instead of calling the
blocking variant; see
await_dialoginfile_actions.rs. - Short, bounded work, such as a single metadata lookup or writing a log line, may stay on the worker.
- When the blocking task fails, answer with an error, never with an empty value the app could take for a valid answer.
- Never keep a
std::sync::MutexGuardalive across an.await, not even with an explicitdropbefore it: the future of the handler is then no longerSend, and Axum refuses it. Scope the guard in a block instead. runtime_api::test_support::assert_runtime_stays_freetests a handler which waits for a lock. Run such a test with#[tokio::test(flavor = "multi_thread", worker_threads = 1)].
IPC Communication Flow
- Rust runtime starts and generates TLS certificate
- Rust starts internal HTTPS API on random port
- Rust launches .NET sidecar, passing: API port, certificate fingerprint, API token, secret key
- .NET reads environment variables and establishes secure HTTPS connection to Rust
- .NET requests an app port from Rust, starts Blazor Server on that port
- Rust opens Tauri webview pointing to localhost:app_port
- Bi-directional communication: .NET ↔ Rust via HTTPS API