Skip to main content

oxios_kernel/
session_context.rs

1//! Session-level context for managing conversation state across Seed executions.
2//!
3//! Introduced by RFC-020 Phase 1. Holds state that persists across multiple
4//! Seed executions within a single user session.
5
6use crate::memory::RecallTiming;
7use crate::project::ProjectId;
8
9/// Session-level context for managing conversation state.
10///
11/// Holds project associations and recall timing.
12///
13/// Created when a new session starts, passed to `AgentRuntime::execute()`.
14#[derive(Debug)]
15pub struct SessionContext {
16    /// Proactive recall timing tracker (session-scoped).
17    /// Tracks message count and topic changes to decide when
18    /// to trigger proactive memory injection.
19    pub recall_timing: Option<RecallTiming>,
20
21    /// Primary project for this session (sets CWD, provides main context).
22    pub primary_project_id: Option<ProjectId>,
23
24    /// Secondary projects for cross-project work.
25    pub secondary_project_ids: Vec<ProjectId>,
26}
27
28impl SessionContext {
29    /// Create a new session context with default settings.
30    pub fn new() -> Self {
31        Self {
32            recall_timing: Some(RecallTiming::new()),
33            primary_project_id: None,
34            secondary_project_ids: Vec::new(),
35        }
36    }
37
38    /// Create a session context with a primary project.
39    pub fn with_project(project_id: ProjectId) -> Self {
40        Self {
41            recall_timing: Some(RecallTiming::new()),
42            primary_project_id: Some(project_id),
43            secondary_project_ids: Vec::new(),
44        }
45    }
46
47    /// Create a session context with multiple projects.
48    pub fn with_projects(primary: ProjectId, secondary: Vec<ProjectId>) -> Self {
49        Self {
50            recall_timing: Some(RecallTiming::new()),
51            primary_project_id: Some(primary),
52            secondary_project_ids: secondary,
53        }
54    }
55
56    /// Get all project IDs (primary first, then secondary).
57    pub fn all_project_ids(&self) -> Vec<ProjectId> {
58        let mut ids = Vec::new();
59        if let Some(primary) = self.primary_project_id {
60            ids.push(primary);
61        }
62        ids.extend(self.secondary_project_ids.iter().copied());
63        ids
64    }
65
66    /// Whether this session has any project context.
67    pub fn has_project(&self) -> bool {
68        self.primary_project_id.is_some()
69    }
70}
71
72impl Default for SessionContext {
73    fn default() -> Self {
74        Self::new()
75    }
76}