Skip to main content

adk_session/
state_utils.rs

1//! Shared state utility functions for session backends.
2//!
3//! These functions implement the three-tier state model used by all session
4//! backends (SQLite, PostgreSQL, Redis). Keys are partitioned by prefix:
5//!
6//! - `app:` → app-level state (prefix stripped)
7//! - `user:` → user-level state (prefix stripped)
8//! - `temp:` → ephemeral, dropped on persistence
9//! - everything else → session-level state
10
11use crate::session::{KEY_PREFIX_APP, KEY_PREFIX_TEMP, KEY_PREFIX_USER};
12use serde_json::Value;
13use std::collections::HashMap;
14
15/// Split a flat state map into (app, user, session) tiers.
16///
17/// Keys with `app:` prefix go to the app tier (prefix stripped).
18/// Keys with `user:` prefix go to the user tier (prefix stripped).
19/// Keys with `temp:` prefix are dropped.
20/// All other keys go to the session tier unchanged.
21pub fn extract_state_deltas(
22    delta: &HashMap<String, Value>,
23) -> (HashMap<String, Value>, HashMap<String, Value>, HashMap<String, Value>) {
24    let mut app = HashMap::new();
25    let mut user = HashMap::new();
26    let mut session = HashMap::new();
27
28    for (key, value) in delta {
29        if let Some(clean) = key.strip_prefix(KEY_PREFIX_APP) {
30            app.insert(clean.to_string(), value.clone());
31        } else if let Some(clean) = key.strip_prefix(KEY_PREFIX_USER) {
32            user.insert(clean.to_string(), value.clone());
33        } else if !key.starts_with(KEY_PREFIX_TEMP) {
34            session.insert(key.clone(), value.clone());
35        }
36    }
37
38    (app, user, session)
39}
40
41/// Merge three state tiers back into a flat map with prefixes restored.
42pub fn merge_states(
43    app: &HashMap<String, Value>,
44    user: &HashMap<String, Value>,
45    session: &HashMap<String, Value>,
46) -> HashMap<String, Value> {
47    let mut merged = session.clone();
48    for (k, v) in app {
49        merged.insert(format!("{KEY_PREFIX_APP}{k}"), v.clone());
50    }
51    for (k, v) in user {
52        merged.insert(format!("{KEY_PREFIX_USER}{k}"), v.clone());
53    }
54    merged
55}