vv_agent/memory/session/
parse.rs1use super::{SessionMemory, SessionMemoryEntry};
2
3impl SessionMemory {
4 pub fn parse_extraction_result(&self, raw: &str, cycle: i32) -> Vec<SessionMemoryEntry> {
5 let Some(array_text) = extract_first_json_array(raw) else {
6 return Vec::new();
7 };
8 let Ok(value) = serde_json::from_str::<serde_json::Value>(array_text) else {
9 return Vec::new();
10 };
11 let Some(items) = value.as_array() else {
12 return Vec::new();
13 };
14 items
15 .iter()
16 .filter_map(|item| {
17 let object = item.as_object()?;
18 let content = object.get("content")?.as_str()?.trim();
19 if content.is_empty() {
20 return None;
21 }
22 let category = object
23 .get("category")
24 .and_then(serde_json::Value::as_str)
25 .unwrap_or("key_fact");
26 let importance = object
27 .get("importance")
28 .and_then(serde_json::Value::as_u64)
29 .unwrap_or(5)
30 .min(10) as u8;
31 Some(SessionMemoryEntry::new(
32 category,
33 content,
34 cycle,
35 importance.max(1),
36 ))
37 })
38 .collect()
39 }
40}
41
42fn extract_first_json_array(raw: &str) -> Option<&str> {
43 let start = raw.find('[')?;
44 let mut depth = 0_i32;
45 let mut in_string = false;
46 let mut escaped = false;
47 for (offset, ch) in raw[start..].char_indices() {
48 if escaped {
49 escaped = false;
50 continue;
51 }
52 match ch {
53 '\\' if in_string => escaped = true,
54 '"' => in_string = !in_string,
55 '[' if !in_string => depth += 1,
56 ']' if !in_string => {
57 depth -= 1;
58 if depth == 0 {
59 return Some(&raw[start..start + offset + ch.len_utf8()]);
60 }
61 }
62 _ => {}
63 }
64 }
65 None
66}