Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:33:35.671Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

session.rs

148 lines · 4.4 KB · rust
1use db::kvp::KeyValueStore;
2use gpui::{App, AppContext as _, Context, Subscription, Task, WindowId};
3use util::ResultExt;
4
5pub struct Session {
6    session_id: String,
7    old_session_id: Option<String>,
8    old_window_ids: Option<Vec<WindowId>>,
9}
10
11const SESSION_ID_KEY: &str = "session_id";
12const SESSION_WINDOW_STACK_KEY: &str = "session_window_stack";
13
14impl Session {
15    pub async fn new(session_id: String, db: KeyValueStore) -> Self {
16        let old_session_id = db.read_kvp(SESSION_ID_KEY).ok().flatten();
17
18        db.write_kvp(SESSION_ID_KEY.to_string(), session_id.clone())
19            .await
20            .log_err();
21
22        let old_window_ids = db
23            .read_kvp(SESSION_WINDOW_STACK_KEY)
24            .ok()
25            .flatten()
26            .and_then(|json| serde_json::from_str::<Vec<u64>>(&json).ok())
27            .map(|vec: Vec<u64>| {
28                vec.into_iter()
29                    .map(WindowId::from)
30                    .collect::<Vec<WindowId>>()
31            });
32
33        Self {
34            session_id,
35            old_session_id,
36            old_window_ids,
37        }
38    }
39
40    #[cfg(any(test, feature = "test-support"))]
41    pub fn test() -> Self {
42        Self {
43            session_id: uuid::Uuid::new_v4().to_string(),
44            old_session_id: None,
45            old_window_ids: None,
46        }
47    }
48
49    #[cfg(any(test, feature = "test-support"))]
50    pub fn test_with_old_session(old_session_id: String) -> Self {
51        Self {
52            session_id: uuid::Uuid::new_v4().to_string(),
53            old_session_id: Some(old_session_id),
54            old_window_ids: None,
55        }
56    }
57
58    pub fn id(&self) -> &str {
59        &self.session_id
60    }
61}
62
63pub struct AppSession {
64    session: Session,
65    _serialization_task: Task<()>,
66    _subscriptions: Vec<Subscription>,
67}
68
69impl AppSession {
70    pub fn new(session: Session, cx: &Context<Self>) -> Self {
71        let _subscriptions = vec![cx.on_app_quit(Self::app_will_quit)];
72
73        let _serialization_task = if cfg!(not(any(test, feature = "test-support"))) {
74            let db = KeyValueStore::global(cx);
75            cx.spawn(async move |_, cx| {
76                // Disabled in tests: the infinite loop bypasses "parking forbidden" checks,
77                // causing tests to hang instead of panicking.
78                {
79                    let mut current_window_stack = Vec::new();
80                    loop {
81                        if let Some(windows) = cx.update(|cx| window_stack(cx))
82                            && windows != current_window_stack
83                        {
84                            store_window_stack(db.clone(), &windows).await;
85                            current_window_stack = windows;
86                        }
87
88                        cx.background_executor()
89                            .timer(std::time::Duration::from_millis(500))
90                            .await;
91                    }
92                }
93            })
94        } else {
95            Task::ready(())
96        };
97
98        Self {
99            session,
100            _subscriptions,
101            _serialization_task,
102        }
103    }
104
105    fn app_will_quit(&mut self, cx: &mut Context<Self>) -> Task<()> {
106        if let Some(window_stack) = window_stack(cx) {
107            let db = KeyValueStore::global(cx);
108            cx.background_spawn(async move { store_window_stack(db, &window_stack).await })
109        } else {
110            Task::ready(())
111        }
112    }
113
114    pub fn id(&self) -> &str {
115        self.session.id()
116    }
117
118    pub fn last_session_id(&self) -> Option<&str> {
119        self.session.old_session_id.as_deref()
120    }
121
122    #[cfg(any(test, feature = "test-support"))]
123    pub fn replace_session_for_test(&mut self, session: Session) {
124        self.session = session;
125    }
126
127    pub fn last_session_window_stack(&self) -> Option<Vec<WindowId>> {
128        self.session.old_window_ids.clone()
129    }
130}
131
132fn window_stack(cx: &App) -> Option<Vec<u64>> {
133    Some(
134        cx.window_stack()?
135            .into_iter()
136            .map(|window| window.window_id().as_u64())
137            .collect(),
138    )
139}
140
141async fn store_window_stack(db: KeyValueStore, windows: &[u64]) {
142    if let Ok(window_ids_json) = serde_json::to_string(windows) {
143        db.write_kvp(SESSION_WINDOW_STACK_KEY.to_string(), window_ids_json)
144            .await
145            .log_err();
146    }
147}
148
Served at tenant.openagents/omega Member data and write actions are omitted.