Only start IPC server when bridge binary exists or local API is enabled
Details
The IPC named-pipe server was starting unconditionally on every launch,
even when neither the browser extension bridge binary is installed nor
the local API is enabled. This wastes a background thread listening on
a pipe nobody will connect to.
Now guarded: IPC server only starts if FindBridgePath() finds the
privstack-bridge binary (meaning the web clipper extension is installed)
OR if appSettings.ApiEnabled is true (local dev API).
Sort Subsystems tab by category, skip Intent Engine when AI is off
Details
Subsystem items now sorted by category (Core → AI → Services → UI →
Runtime → Plugin), then alphabetically within each group. Previously
items appeared in random insertion order.
Intent Engine's consumer task was starting unconditionally in the
constructor even when AI was disabled. The task sat forever on an empty
channel reader, showing a green "active" dot in the Subsystems tab
despite doing no work. Now only starts when AiEnabled && AiIntentEnabled.
IPC Server still shows active — that's correct, it always runs for
browser extension / CLI pipe connections.
Throttle Dashboard live metrics: stop per-second ReadList spam
Details
The 1-second live metrics timer was calling GetDataMetricsAsync on every
tick regardless of active tab. This triggered ~33 SDK ReadList/Count
calls per second across all plugins (page, task, event, contact, etc.),
saturating the SDK message bus with unnecessary I/O.
- Memory metrics (process-level, no SDK calls) still refresh every 1s
- Data metrics now only run on the Data tab, throttled to every 10s
- Overview tab DataStorageTotal populated on first load only
- Subsystems tab refresh unchanged (local counters, no SDK calls)
Fix Dashboard plugin toggle not rendering + clean up alloc tracking
Details
The ToggleSwitch for enabling/disabling plugins was invisible because
ToggleSwitch in Avalonia does not have Command/CommandParameter properties.
The XAML parser silently dropped the invalid attributes, preventing the
control from rendering.
- Remove invalid Command/CommandParameter from ToggleSwitch
- Switch to two-way IsChecked binding on IsActivated property
- Add OnActivationChanged callback on DashboardPluginItem that fires
when IsActivated changes from the ToggleSwitch
- Wire callback in PopulateLocalPlugins AFTER setting initial value
to avoid re-entrant enable/disable calls during initialization
- Add OnPluginActivationChanged handler that syncs to plugin registry
Also cleans up SubsystemTracker: removed broken heartbeat approach for
long-running task alloc tracking (GC.GetAllocatedBytesForCurrentThread
cannot be queried cross-thread after await resumes on a different thread).
Fix Subsystems tab: use process-level native memory, improve column layout
Details
The "Native Memory" summary card was showing only Rust allocator-tracked
bytes (~126 B), which is misleading when the process uses ~1.4 GB native.
The Rust GlobalAlloc only tracks Rust heap allocations — C/C++ libraries
(SQLCipher, ONNX, Whisper, LLamaSharp) use their own malloc directly.
- Summary "Native Memory" card now uses WorkingSet64 - GC heap (same
calculation as the Overview tab's memory card)
- Per-subsystem memory column renamed to "Tracked Memory" and widened
to accommodate labels like "126 B native" or "7.0 MB managed"
- Memory display now distinguishes native vs managed with explicit labels
- Column widths adjusted (Category 80, Tasks 60, Memory 180, Rate 100)
- Removed broken heartbeat approach for long-running task alloc tracking
(GC.GetAllocatedBytesForCurrentThread can't be queried cross-thread)
Get notified about new releases