codetether_agent/voice/
dictation.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct VoiceCommand {
8 pub intent: VoiceIntent,
9 pub raw_transcript: String,
10 pub parameters: Vec<String>,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
15#[serde(rename_all = "snake_case")]
16pub enum VoiceIntent {
17 AutoPilot,
19 FixIssue,
21 ReviewPr,
23 Question,
25 Status,
27 Dictation,
29}
30
31pub fn parse_voice_command(transcript: &str) -> VoiceCommand {
33 let lower = transcript.to_lowercase();
34 let (intent, params) = if lower.starts_with("auto pilot") || lower.starts_with("autopilot") {
35 (VoiceIntent::AutoPilot, extract_params(&lower, "auto pilot"))
36 } else if lower.starts_with("fix issue") {
37 (VoiceIntent::FixIssue, extract_params(&lower, "fix issue"))
38 } else if lower.starts_with("review") {
39 (VoiceIntent::ReviewPr, extract_params(&lower, "review"))
40 } else if lower.starts_with("status") || lower.starts_with("what's the status") {
41 (VoiceIntent::Status, vec!["current".to_string()])
42 } else if lower.starts_with("ask") || lower.ends_with('?') {
43 (VoiceIntent::Question, vec![transcript.to_string()])
44 } else {
45 (VoiceIntent::Dictation, vec![transcript.to_string()])
46 };
47 VoiceCommand {
48 intent,
49 raw_transcript: transcript.to_string(),
50 parameters: params,
51 }
52}
53
54fn extract_params(text: &str, prefix: &str) -> Vec<String> {
55 text.strip_prefix(prefix)
56 .map(|rest| rest.split_whitespace().map(String::from).collect())
57 .unwrap_or_default()
58}