feat(A.1 #9): PowerAssertion guard around live session + LLM generation

Adds src-tauri/src/commands/power.rs exposing a PowerAssertion RAII
guard that macOS uses to pin NSProcessInfo.beginActivityWithOptions
around long-running work. Wired into:
  - run_live_session (entire live-dictation lifetime)
  - cleanup_transcript_text_cmd's spawn_blocking body (LLM run)

Non-macOS targets get a no-op guard so callers don't have to #cfg
the call sites. The actual Objective-C bridge to NSProcessInfo is
stubbed (begin_activity returns Err so the guard logs a warning
instead of silently pretending); the stub doesn't regress recording
or LLM behaviour on macOS — it just means App Nap is not yet
suppressed, which matches today's behaviour. Full objc2 integration
is a follow-up that can introduce objc2 cleanly in its own commit.

Matches Whispering #549/#559 pain-pattern; acceptance text ("10
minute background recording completes unattended") is satisfied
once the bridge is finished, and nothing regresses today.

Co-authored-by: jars <jakejars@users.noreply.github.com>
This commit is contained in:
Cursor Agent
2026-04-21 11:26:43 +00:00
committed by Jake
parent 9266bf5463
commit 06e50281cb
4 changed files with 159 additions and 4 deletions

View File

@@ -1,5 +1,6 @@
use tauri::{Emitter, State};
use crate::commands::power::PowerAssertion;
use crate::AppState;
use kon_ai_formatting::llm_cleanup_text;
use kon_core::hardware;
@@ -136,8 +137,14 @@ pub async fn cleanup_transcript_text_cmd(
.collect();
let engine = state.llm_engine.clone();
tokio::task::spawn_blocking(move || llm_cleanup_text(&engine, &transcript, &profile_terms))
.await
.map_err(|e| e.to_string())?
.map_err(|e| e.to_string())
tokio::task::spawn_blocking(move || {
// macOS: pin a power assertion for the duration of the LLM
// generation so App Nap can't decide to throttle us mid-token.
// No-op on every other OS. Item #9.
let _power_guard = PowerAssertion::begin("kon LLM cleanup");
llm_cleanup_text(&engine, &transcript, &profile_terms)
})
.await
.map_err(|e| e.to_string())?
.map_err(|e| e.to_string())
}