Skip to main content

Desktop Runtime Integration (Option A)

Status: Implemented. The .NET sidecar (Holon.DesktopHost) has been removed and replaced by the in-process holon-runtime-core runtime.

Architecture

There is no subprocess, no port, no TCP socket, no health ping loop, and no auth token exchange. The runtime opens once at application startup and is dropped when the process exits.

How it works

State binding

holon_runtime::HolonRuntimeState wraps Arc<tokio::sync::Mutex<Runtime>> and is registered as a Tauri managed state item during setup():

let runtime = HolonRuntimeState::open_and_initialize(&db_path)
.expect("failed to open and initialize Holon runtime");
app.manage(runtime);

Tauri command pattern

Each Tauri async command acquires the mutex, performs a bounded synchronous SQLite operation, and drops the guard before returning:

#[tauri::command]
async fn desktop_runtime_ready(
runtime: tauri::State<'_, HolonRuntimeState>,
) -> Result<RuntimeReadyDiagnosticsResult, String> {
let rt = runtime.lock().await;
let _status = rt.status().map_err(|e| e.to_string())?;
Ok(RuntimeReadyDiagnosticsResult { ready: true, message: "Runtime is ready".to_string() })
}

rusqlite::Connection is Send but not Sync. The Mutex ensures only one command holds the connection at a time. This is correct and performant for a single-user local application.

Database path

Tauri's PathResolver::app_data_dir() provides the platform-appropriate data directory:

PlatformExample path
Windows%APPDATA%\com.holon.desktop\holon.db
macOS~/Library/Application Support/com.holon.desktop/holon.db
Linux~/.local/share/com.holon.desktop/holon.db

Startup sequence

  1. HolonRuntimeState::open_and_initialize(db_path) — opens SQLite with WAL mode, runs migrations, seeds default skill sources
  2. app.manage(runtime) — registers state with Tauri
  3. App window loads; all Tauri commands are available immediately with no warmup delay

Real Desktop Validation

Use npm --prefix ./Frontend/HolonDesktop run test:real-desktop when you need evidence about the actual HolonDesktop shell instead of renderer-only coverage.

This lane currently launches the real dev:light Tauri app on Windows, sets a WebView2 remote debugging port, attaches Playwright to the live WebView2 DOM over CDP, and isolates debug or test app data with HOLON_DESKTOP_E2E_DATA_DIR before the runtime opens holon.db or writes diagnostics.

Treat Frontend/HolonClient/tests/e2e as renderer coverage only. Those tests are still useful for UI regression coverage, but they do not prove that the real Tauri shell started, that window.__TAURI_INTERNALS__ existed, or that Rust host commands and diagnostics responded in the running desktop process.

Each real-desktop run writes host-owned evidence under Frontend/HolonDesktop/tests/real-desktop/artifacts/, including evidence-manifest.json, stdout and stderr logs, screenshots, Playwright trace and results, agent-snapshot.json, and the desktop diagnostics snapshot. Agent or reviewer claims about real desktop behavior should point to those artifacts.

The current smoke floor proves real startup plus workspace navigation and chat request submission. A truthful blocked provider or model outcome is valid evidence for this lane when the session, diagnostics, and visible desktop state are captured clearly. A deterministic provider-backed successful reply still requires a configured provider path or a future dedicated test provider.

Implemented commands

All desktop Tauri commands are wired to real runtime implementations. Every command is desktop_-prefixed; common suffixes are grouped below.

  • runtime_ready, _ping, _version, _health_details, _state_inspection, _agent_diagnostics — lifecycle, health, diagnostics
  • rust_runtime_status — full runtime/status snapshot
  • runtime_list_tools — context-aware tool discovery with schemas and availability
  • runtime_plugin_package_list, _add, _import — plugin package inventory, registration, and import
  • runtime_frozen_tool_proposal_list, _get, _readiness_get, _set_lifecycle, _published_list — frozen-tool proposal inspection and lifecycle
  • runtime_execute_one_shot — status-based one-shot execution
  • runtime_workspace_list, _create, _open, _rename, _remove, _delete, _get_active, _set_active — workspace CRUD and selection
  • runtime_get_observation_status, _set_observation_enabled, _start_observation_session, _stop_observation_session, _renew_observation_lease, _get_observation_capture, _list_observation_captures, _capture_observation, workspace-observation-capture/materialize-target-surface — observation session management, capture, and materialization
  • agentic_sessions_list, _session_get, _agent_session_start, _send_message, _preview_model_routing, _cancel, _resume_events, _continue, _agentic_session_resume — session lifecycle, messaging, cancellation, replay
  • runtime_skill_list, _detail_get, _create, _get, _delete — skill CRUD
  • provider_catalog_get, _statuses_get, _provider_oauth_runtime_state_get, _connect, _runtime_state_clear — provider catalog, status, and OAuth
  • runtime_secret_list_refs, _upsert, _remove — SQLite-backed secret management
  • app_config_get, _set, _workspace_config_get, _set — app and workspace JSON config
  • work_units_list, _work_unit_get — work unit summaries
  • runtime_agent_list, _create, _update, _delete — agent file CRUD
  • terminal_start, _submit, _poll, _stop — subprocess terminal (cmd/bash/zsh)
  • mcp_list_servers, _list_approved, _revoke_server — MCP server config management
  • workflow_list, _get, _create, _put, _validate, _execute, _get_execution, _cancel_execution, _deliver_wait_event — workflow library and execution
  • elegy_distribution_status_get — Elegy CLI and bundled executable readiness diagnostics

See runtime/README.md for the current runtime capability surface. See Known Issues for current limitations on specific command areas.

Full implementation status

All desktop Tauri commands are now wired. Zero stub commands remain.

What was removed

AssetReason
src-tauri/src/sidecar_manager.rsgRPC-over-TCP sidecar manager — replaced by in-process runtime
src-tauri/src/rust_runtime_broker.rsStdio subprocess broker — replaced by in-process runtime
src-tauri/binaries/Holon.DesktopHost-*.exe.NET binary — sidecar process no longer used
Protos/desktop-runtime/v1/desktop_runtime.proto.NET gRPC contract — no loopback IPC needed
desktopHostLifecycle/ test filesTested JS-side sidecar lifecycle coordination
tonic, prost, prost-types, protoc-bin-vendoredgRPC codegen/runtime — not needed
tauri.conf.jsonexternalBinSidecar binary bundle reference
tauri.conf.jsonbeforeBuildCommand (dotnet publish step).NET publish was part of the build

Expansion plan

Each stub command area is a separate workstream. The runtime implementation priority should follow frontend usage — start with workspace CRUD since it is foundational, then provider/auth once the first LLM call is needed.

See runtime/README.md for the current runtime capability surface.