Skip to main content

vv_agent/memory/session/
parse.rs

1use 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}