theway_core/agent/context/
collapse.rs1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::agent::session::session::SessionTreeEntry;
7
8pub const COMPACT_CONTEXT_CUSTOM_TYPE: &str = "compact_context";
10
11#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
13#[serde(rename_all = "camelCase")]
14pub struct CompactContext {
15 pub source_session_id: String,
16 pub compact_text: String,
17 pub raw_text_ref: String,
18}
19
20pub fn latest_compact_context(entries: &[SessionTreeEntry]) -> Option<CompactContext> {
22 entries.iter().rev().find_map(compact_context_from_entry)
23}
24
25pub fn compact_context_from_entry(entry: &SessionTreeEntry) -> Option<CompactContext> {
27 let SessionTreeEntry::Custom {
28 custom_type, data, ..
29 } = entry
30 else {
31 return None;
32 };
33 if custom_type != COMPACT_CONTEXT_CUSTOM_TYPE {
34 return None;
35 }
36 parse_compact_context(data.as_ref()?)
37}
38
39pub fn compact_context_text(entry: &SessionTreeEntry) -> Option<String> {
41 compact_context_from_entry(entry)
42 .map(|context| context.compact_text)
43 .filter(|text| !text.trim().is_empty())
44}
45
46fn parse_compact_context(data: &Value) -> Option<CompactContext> {
48 let source_session_id = data
49 .get("sourceSessionId")
50 .and_then(Value::as_str)
51 .unwrap_or_default()
52 .to_string();
53 let compact_text = data
54 .get("compactText")
55 .and_then(Value::as_str)
56 .or_else(|| data.get("text").and_then(Value::as_str))
57 .unwrap_or_default()
58 .to_string();
59 let raw_text_ref = data
60 .get("rawTextRef")
61 .and_then(Value::as_str)
62 .unwrap_or_default()
63 .to_string();
64 if source_session_id.is_empty() && compact_text.trim().is_empty() && raw_text_ref.is_empty() {
65 None
66 } else {
67 Some(CompactContext {
68 source_session_id,
69 compact_text,
70 raw_text_ref,
71 })
72 }
73}