1use anyhow::{Context, Result};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct ModeSelectResponse {
7 pub mode: String,
8 pub reason: String,
9}
10
11pub type AskResponse = String;
13
14#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub struct CommandSuggestion {
17 pub cmd: String,
18 pub description: String,
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct SuggestResponse {
24 pub suggestions: Vec<CommandSuggestion>,
25}
26
27pub fn parse_mode_select(json_str: &str) -> Result<ModeSelectResponse> {
29 let cleaned = extract_json(json_str);
30
31 serde_json::from_str(&cleaned).context("Failed to parse Mode Select response")
32}
33
34pub fn parse_suggest(json_str: &str) -> Result<SuggestResponse> {
36 let cleaned = extract_json(json_str);
37
38 serde_json::from_str(&cleaned).context("Failed to parse Suggest response")
39}
40
41fn extract_json(text: &str) -> String {
43 let text = text.trim();
44
45 if let Some(start) = text.find("```")
47 && let Some(end) = text[start + 3..].find("```")
48 {
49 let json_block = &text[start + 3..start + 3 + end];
50 let json_content = if let Some(newline) = json_block.find('\n') {
51 &json_block[newline + 1..]
52 } else {
53 json_block
54 };
55 return json_content.trim().to_string();
56 }
57
58 if let Some(start) = text.find('{')
60 && let Some(end) = text.rfind('}')
61 && end > start
62 {
63 return text[start..=end].to_string();
64 }
65
66 text.to_string()
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn test_parse_mode_select() {
76 let json = r#"{"mode":"ask","reason":"사용자가 질문을 했습니다"}"#;
77 let result = parse_mode_select(json).unwrap();
78 assert_eq!(result.mode, "ask");
79 assert_eq!(result.reason, "사용자가 질문을 했습니다");
80 }
81
82 #[test]
83 fn test_parse_mode_select_with_markdown() {
84 let json = r#"
85```json
86{"mode":"execute","reason":"실행 요청"}
87```
88 "#;
89 let result = parse_mode_select(json).unwrap();
90 assert_eq!(result.mode, "execute");
91 }
92
93 #[test]
94 fn test_parse_suggest() {
95 let json = r#"
96{
97 "suggestions": [
98 {"cmd": "ls -la", "description": "모든 파일 나열"},
99 {"cmd": "dir", "description": "디렉터리 내용 보기"}
100 ]
101}
102 "#;
103 let result = parse_suggest(json).unwrap();
104 assert_eq!(result.suggestions.len(), 2);
105 assert_eq!(result.suggestions[0].cmd, "ls -la");
106 }
107
108 #[test]
109 fn test_extract_json() {
110 let text = "Some text before\n{\"key\":\"value\"}\nSome text after";
111 let result = extract_json(text);
112 assert_eq!(result, r#"{"key":"value"}"#);
113 }
114
115 #[test]
116 fn test_extract_json_with_code_block() {
117 let text = "```json\n{\"key\":\"value\"}\n```";
118 let result = extract_json(text);
119 assert_eq!(result, r#"{"key":"value"}"#);
120 }
121}