diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 1a81a2d..e3be42c 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -1941,6 +1941,46 @@ pub async fn confirm_action_items( Ok(()) } +/// Suggests 1-8 short topical tags from the transcript (T8.3, FR-SEARCH-2) — +/// same LLM path/prompt assembly as generate_summary, just a much shorter +/// non-streamed reply. Suggestions are NOT saved automatically; the caller +/// reviews/merges them and still calls set_tags to persist, same as a +/// manually typed tag. +#[tauri::command] +pub async fn generate_tags( + state: State<'_, AppState>, + meeting_id: MeetingId, +) -> WaResult> { + let guard = state.session.lock().await; + if guard.as_ref().is_some_and(|s| s.meeting_id == meeting_id) { + return Err(WaError::new( + "llm", + "cannot generate tags while this meeting is still recording — wait until it's stopped", + )); + } + drop(guard); + + let settings = load_settings(); + let provider = llm_provider_from_settings(&settings).ok_or_else(|| { + WaError::new( + "llm", + "no LLM provider is configured — enable one in Settings first", + ) + })?; + + let meeting = state + .store + .get_meeting(&meeting_id) + .await + .map_err(|e| WaError::new("storage", e.to_string()))?; + let prompt = build_prompt(&meeting, None); + let text = format!("{}\n\n{}", prompt.metadata, prompt.transcript); + provider + .suggest_tags(&text) + .await + .map_err(|e| WaError::new("llm", e.to_string())) +} + // ---- Calendar / .pst (Phase 6) ---- /// Import events + attendees from a `.pst` (T6.1/T6.2, FR-CAL-1). The