Skip to main content

soothe_client/
intent_hints.rs

1//! Loop input intent hints.
2
3/// Fast text completion path.
4pub const TEXT_COMPLETION: &str = "text_completion";
5/// Image understanding → text.
6pub const IMAGE_TO_TEXT: &str = "image_to_text";
7/// OCR path.
8pub const OCR: &str = "ocr";
9/// Embedding path.
10pub const EMBED: &str = "embed";
11
12/// Default deliverable phases used by EventClassifier.
13pub const DEFAULT_DELIVERABLE_PHASES: &[&str] = &[
14    "quiz",
15    "goal_completion",
16    "chitchat",
17    "text_completion",
18    "image_to_text",
19    "ocr",
20    "embed",
21];
22
23const REMOVED: &[&str] = &["direct_llm", "quiz", "direct_model"];
24
25/// Validate an intent hint; returns an error string when invalid.
26pub fn validate_loop_input_intent_hint(hint: &str) -> Option<String> {
27    let h = hint.trim();
28    if h.is_empty() {
29        return None;
30    }
31    if REMOVED.contains(&h) {
32        return Some(format!(
33            "intent_hint '{h}' is removed; use text_completion or another supported hint"
34        ));
35    }
36    let ok = matches!(h, TEXT_COMPLETION | IMAGE_TO_TEXT | OCR | EMBED);
37    if ok {
38        None
39    } else {
40        Some(format!("unsupported intent_hint '{h}'"))
41    }
42}
43
44#[cfg(test)]
45mod tests {
46    use super::*;
47
48    #[test]
49    fn accepts_text_completion() {
50        assert!(validate_loop_input_intent_hint(TEXT_COMPLETION).is_none());
51    }
52
53    #[test]
54    fn rejects_removed() {
55        assert!(validate_loop_input_intent_hint("direct_llm").is_some());
56    }
57}