Skip to main content

zeroclaw_api/
session_keys.rs

1//! Session key normalization shared across infra and memory backends.
2//!
3//! Channel orchestration uses two identifiers derived from a `ChannelMessage`:
4//! one ends up as a JSONL filename (via `SessionStore::session_path`) and as
5//! an in-memory HashMap key for the conversation history cache, while the
6//! same identifier is also passed to `Memory::store`/`Memory::recall` as the
7//! `session_id` filter. Because filesystem-safe sanitization is applied when
8//! writing the JSONL file, every other layer must use the same sanitized form
9//! to keep lookups consistent across daemon restarts and persisted backends.
10
11/// Replace every character outside `[A-Za-z0-9_-]` with `_`. Idempotent.
12///
13/// Callers building session keys must pre-apply this so the runtime HashMap
14/// key, the on-disk JSONL filename, and the `session_id` column in memory
15/// backends all agree.
16pub fn sanitize_session_key(key: &str) -> String {
17    key.chars()
18        .map(|c| {
19            if c.is_alphanumeric() || c == '_' || c == '-' {
20                c
21            } else {
22                '_'
23            }
24        })
25        .collect()
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31
32    #[test]
33    fn replaces_special_characters_with_underscore() {
34        assert_eq!(
35            sanitize_session_key("slack_C123_1.2_user one"),
36            "slack_C123_1_2_user_one"
37        );
38    }
39
40    #[test]
41    fn preserves_alphanumeric_underscore_and_hyphen() {
42        let key = "abc-DEF_123";
43        assert_eq!(sanitize_session_key(key), key);
44    }
45
46    #[test]
47    fn is_idempotent() {
48        let once = sanitize_session_key("whatsapp_123@g.us_alice");
49        let twice = sanitize_session_key(&once);
50        assert_eq!(once, twice);
51    }
52
53    #[test]
54    fn handles_empty_string() {
55        assert_eq!(sanitize_session_key(""), "");
56    }
57
58    #[test]
59    fn preserves_unicode_alphanumeric() {
60        // is_alphanumeric() treats unicode letters/digits as alphanumeric.
61        assert_eq!(sanitize_session_key("user_Алиса"), "user_Алиса");
62    }
63}