Implementation
Overview
The implementation moved from separate assistant prototypes toward one unified desktop product built around one shared engine, one shipped application shell, and host-specific connector crates. The most important implementation story is therefore not four isolated assistants, but the way the Svelte frontend, Tauri backend, engine supervisor, and mode providers work together to deliver multiple workflows through one offline desktop application.
Unified App Shell
The current integrated application lives in app/. Although Code mode remains the clearest baseline workflow, the shipped shell now supports Code, GIMP, Blender, Writer, and Slides inside one consistent interface. The same component tree handles chat, setup, diagnostics, host-app launching, and voice controls across all of these modes.
Mode Configuration and Switching
Modes are configured as structured frontend objects with labels, suggestions, and availability state. On the backend, the mode registry maps each mode to a provider kind: Code uses a local path, GIMP uses MCP, Blender uses a hybrid path, and Writer plus Slides share the LibreOffice MCP family. This was the key step that turned a single assistant UI into a mode-driven platform shell.
Shared UI Components
The live shell is built from reusable components such as Sidebar, WorkspaceHeader, WorkspaceControls, AppModeDropdown, ConversationView, ComposerBar, SetupBanner, SetupPanel, SetupWizard, ModeHelpDrawer, HardwarePanel, ModelInfoPanel, and a startup loading screen. This gives every mode the same visual language even when the underlying execution path is very different.
Streaming Chat Flow
Assistant requests are sent through a unified frontend API using Tauri channels for streaming events. This lets the interface display partial tokens, completion, cancellation, and error events in one consistent conversation view. Streaming is particularly important for local generation because it keeps the product responsive even when heavier models are running on modest hardware.
Local Persistence
The frontend stores chats, current mode chat IDs, and settings in localStorage. Chats are organised per mode rather than as one global list, allowing the user to switch between workflows without losing context. Settings such as runtime preference, selected model, and theme are also persisted locally.
Setup and Availability Gating
The UI does not assume that every host application is installed or ready. Startup and setup checks map host availability into per-mode availability, so GIMP, Blender, Writer, and Slides can be shown as unavailable with a clear reason rather than appearing broken. The same setup state also drives the setup wizard and the startup loading flow.
Assistant Routing and Providers
A major implementation feature is the provider registry in the Rust backend. The assistant request layer receives one unified request and then dispatches it to the correct provider family based on the selected mode. This keeps the UI simple while still allowing each workflow to have a different execution model.
| Provider Family | Modes | Provider Kind | Implementation Role |
|---|---|---|---|
| Code provider | Code | Local | Direct text generation through the shared engine and chat streaming path |
| GIMP provider | GIMP | MCP | Bridge management, tool discovery, tool execution, and undo support |
| Blender provider | Blender | Hybrid | Scene bridge management, local retrieval, and scene-aware assistance |
| LibreOffice provider | Writer and Slides | LibreOffice MCP | Shared office runtime handling, tool filtering, planner-assisted execution, and summaries |
Code Mode and Core Chat Experience
Code mode is the simplest implementation path and the foundation of the unified shell. It uses the shared engine for local text generation and presents the result through the same conversation UI that other modes reuse. It is also the clearest place where the shared shell's voice controls are exposed to the user.
Key Implementation Features
Blocking engine startup handshake: startup is mediated by the supervisor and the readiness contract rather than direct process assumptions, which makes the interface safer on slow or partially configured machines.
Streaming generation: responses are streamed token by token through the Tauri command boundary, allowing the frontend to update the active assistant message incrementally.
Memory and runtime awareness: the inference layer exposes backend status, active model, and memory-pressure information so the UI can warn the user when a selected model is likely to perform badly for tool-backed modes.
Voice Input and Read-Aloud
Voice features were implemented as an extension of the existing SmolPC chat workflow rather than as a separate subsystem from the user's point of view. In the current unified shell, these features appear as an optional microphone button in the composer and a read-aloud control on assistant messages.
Frameworks and Libraries
| Framework / Library | Purpose | How It Was Used |
|---|---|---|
cpal |
Microphone capture | Used in the Tauri layer to record audio from the user's input device at its native sample rate |
rubato |
Audio resampling | Used to convert recorded audio into the 16kHz mono format expected by the local Whisper path |
| Whisper base.en INT8 via OpenVINO | Local speech-to-text | Used through the engine's /v1/audio/transcriptions endpoint on CPU |
rodio |
Audio playback | Used to play returned WAV data locally when the user requests read-aloud on an assistant message |
smolpc-tts-server and KittenTTS |
Local text-to-speech | Used as a detached sidecar behind /v1/audio/speech so TTS stays offline without complicating the main inference process |
Key Features Implementation
Microphone capture and transcription insertion: the app records locally, resamples the audio, sends it to the engine, and inserts the resulting text back into the composer so the user can review it before sending.
Per-message read-aloud: assistant responses can be synthesised on demand and played back locally, with the UI tracking loading, playing, and stop states through a dedicated voice store.
Detached TTS boundary: text-to-speech is isolated behind a sidecar process and the engine API so voice-output problems degrade to an unavailable control instead of destabilising the main chat or runtime-selection path.
GIMP Mode
GIMP mode is implemented as a host-assisted workflow rather than plain text chat. The provider is responsible for preparing the required runtime, detecting GIMP, establishing the MCP session, discovering tools, and executing image-editing actions.
Frameworks and Libraries
| Framework / Library | Purpose | How It Was Used |
|---|---|---|
| Tauri + Rust | Desktop app backend and process orchestration | Used to manage the GIMP bridge runtime, tool execution, and setup flow |
| MCP client layer | Structured tool communication | Used to connect to the GIMP bridge, list tools, and execute actions |
| Shared engine | Local planning and summarisation | Used when natural-language requests need planning or text support before or after a tool action |
Key Features Implementation
Bundled runtime preparation: setup logic prepares or validates the required GIMP-side runtime resources before trying to connect, reducing manual setup for the user.
Connection and tool discovery: the provider connects to the bridge, stores discovered tools, and exposes mode state back to the frontend.
Undo support: GIMP mode is one of the few workflows in the unified app that explicitly exposes undo through the provider interface.
Blender Mode
Blender mode combines a host bridge with local retrieval. This makes it different from both Code mode and GIMP mode: it is not just a tool executor, and it is not just a plain text assistant. Instead, it is designed to answer scene-aware questions and support Blender workflows using both bridge state and local reference material.
Frameworks and Libraries
| Framework / Library | Purpose | How It Was Used |
|---|---|---|
| Tauri + Rust | Backend orchestration and desktop integration | Used to manage the Blender scene bridge and assistant routing |
| Bridge runtime and addon | Scene-aware host communication | Used to retrieve live scene information and expose Blender-specific tooling |
| Local RAG index | Reference retrieval | Used to load local Blender reference documents and enrich responses with relevant context |
Key Features Implementation
Scene bridge startup: the provider starts or connects to a local scene bridge and stores runtime state so Blender mode can remain scene-aware across requests.
RAG-backed assistance: the provider loads a local retrieval index and combines it with live scene information, allowing responses to use both static reference material and current workspace context.
Hybrid execution path: Blender mode can gather scene state, retrieve context, and use the shared engine for generated explanations within one request flow.
LibreOffice Modes
The LibreOffice workflows are implemented through one shared provider family. This reflects the system design decision that office features should share runtime management and tool orchestration instead of being built as completely separate products.
Frameworks and Libraries
| Framework / Library | Purpose | How It Was Used |
|---|---|---|
| Tauri + Rust | Backend orchestration | Used to manage LibreOffice runtime setup, provider state, and assistant execution |
| MCP-backed office runtime | Structured office tool access | Used to connect Writer and Slides workflows to office actions through an allowlisted tool layer |
| Shared engine planner and streamer | Planning and summarisation | Used to decide whether a tool call is needed and to produce short user-facing summaries after a successful office action |
Key Features Implementation
Mode-specific tool filtering: the provider filters the raw office tool list based on the selected mode so that each office workflow only exposes the tools appropriate to that task.
Planner then tool execution: the office executor first uses the engine to decide whether a tool call is needed, then executes the chosen office action, and finally generates a short summary for the user.
Shared provider family: Writer and Slides are grouped under one provider family, which reduces duplication and fits the unified platform architecture.
Packaging, Launch, and Setup Features
The project also includes substantial implementation work for setup preparation, provisioning, and packaging. These pieces matter because the project goal is not only local AI, but local AI that is practical to deploy on school or lab machines.
Root development commands: the workspace exposes npm run check, npm run boundary:check, npm run tauri:dev, npm run runtime:setup:openvino, npm run runtime:setup:python, and the model setup scripts as shared entry points.
App-local packaging scripts: the app workspace adds runtime:setup:dml, engine:build:release, package:offline, and package:offline:bundle for release preparation and offline deployment artefacts.
Offline-first provisioning direction: the current packaging design supports an online installer, offline USB bundles, and a portable-style path, with model discovery and provisioning intended to happen locally rather than through a permanently online dependency.