Download codex-rs/agent-graph-store/src/local.rs from SaylorTwift/codex: direct link, hf CLI and curl.
- Browser
- Download file 11.7 kB
-
https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/agent-graph-store/src/local.rs
- Command line
-
hf download hf://SaylorTwift/codex/codex-rs/agent-graph-store/src/local.rs
-
curl -L -o local.rs https://huggingface.co/SaylorTwift/codex/resolve/main/codex-rs/agent-graph-store/src/local.rs
11.7 kB
| use codex_protocol::ThreadId; | |
| use codex_state::StateRuntime; | |
| use std::sync::Arc; | |
| use crate::AgentGraphStore; | |
| use crate::AgentGraphStoreError; | |
| use crate::AgentGraphStoreFuture; | |
| use crate::ThreadSpawnEdgeStatus; | |
| /// SQLite-backed implementation of [`AgentGraphStore`] using an existing state runtime. | |
| pub struct LocalAgentGraphStore { | |
| state_db: Arc<StateRuntime>, | |
| } | |
| impl std::fmt::Debug for LocalAgentGraphStore { | |
| fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
| f.debug_struct("LocalAgentGraphStore") | |
| .field("sqlite", self.state_db.sqlite()) | |
| .finish_non_exhaustive() | |
| } | |
| } | |
| impl LocalAgentGraphStore { | |
| /// Create a local graph store from an already-initialized state runtime. | |
| pub fn new(state_db: Arc<StateRuntime>) -> Self { | |
| Self { state_db } | |
| } | |
| } | |
| impl AgentGraphStore for LocalAgentGraphStore { | |
| fn upsert_thread_spawn_edge( | |
| &self, | |
| parent_thread_id: ThreadId, | |
| child_thread_id: ThreadId, | |
| status: ThreadSpawnEdgeStatus, | |
| ) -> AgentGraphStoreFuture<'_, ()> { | |
| Box::pin(async move { | |
| self.state_db | |
| .upsert_thread_spawn_edge( | |
| parent_thread_id, | |
| child_thread_id, | |
| to_state_status(status), | |
| ) | |
| .await | |
| .map_err(internal_error) | |
| }) | |
| } | |
| fn set_thread_spawn_edge_status( | |
| &self, | |
| child_thread_id: ThreadId, | |
| status: ThreadSpawnEdgeStatus, | |
| ) -> AgentGraphStoreFuture<'_, ()> { | |
| Box::pin(async move { | |
| self.state_db | |
| .set_thread_spawn_edge_status(child_thread_id, to_state_status(status)) | |
| .await | |
| .map_err(internal_error) | |
| }) | |
| } | |
| fn list_thread_spawn_children( | |
| &self, | |
| parent_thread_id: ThreadId, | |
| status_filter: Option<ThreadSpawnEdgeStatus>, | |
| ) -> AgentGraphStoreFuture<'_, Vec<ThreadId>> { | |
| Box::pin(async move { | |
| if let Some(status) = status_filter { | |
| return self | |
| .state_db | |
| .list_thread_spawn_children_with_status( | |
| parent_thread_id, | |
| to_state_status(status), | |
| ) | |
| .await | |
| .map_err(internal_error); | |
| } | |
| self.state_db | |
| .list_thread_spawn_children(parent_thread_id) | |
| .await | |
| .map_err(internal_error) | |
| }) | |
| } | |
| fn list_thread_spawn_descendants( | |
| &self, | |
| root_thread_id: ThreadId, | |
| status_filter: Option<ThreadSpawnEdgeStatus>, | |
| ) -> AgentGraphStoreFuture<'_, Vec<ThreadId>> { | |
| Box::pin(async move { | |
| match status_filter { | |
| Some(status) => self | |
| .state_db | |
| .list_thread_spawn_descendants_with_status( | |
| root_thread_id, | |
| to_state_status(status), | |
| ) | |
| .await | |
| .map_err(internal_error), | |
| None => self | |
| .state_db | |
| .list_thread_spawn_descendants(root_thread_id) | |
| .await | |
| .map_err(internal_error), | |
| } | |
| }) | |
| } | |
| } | |
| fn to_state_status(status: ThreadSpawnEdgeStatus) -> codex_state::DirectionalThreadSpawnEdgeStatus { | |
| match status { | |
| ThreadSpawnEdgeStatus::Open => codex_state::DirectionalThreadSpawnEdgeStatus::Open, | |
| ThreadSpawnEdgeStatus::Closed => codex_state::DirectionalThreadSpawnEdgeStatus::Closed, | |
| } | |
| } | |
| fn internal_error(err: impl std::fmt::Display) -> AgentGraphStoreError { | |
| AgentGraphStoreError::Internal { | |
| message: err.to_string(), | |
| } | |
| } | |
| mod tests { | |
| use super::*; | |
| use codex_state::DirectionalThreadSpawnEdgeStatus; | |
| use codex_utils_absolute_path::test_support::PathExt; | |
| use pretty_assertions::assert_eq; | |
| use tempfile::TempDir; | |
| struct TestRuntime { | |
| state_db: Arc<StateRuntime>, | |
| _codex_home: TempDir, | |
| } | |
| fn thread_id(suffix: u128) -> ThreadId { | |
| ThreadId::from_string(&format!("00000000-0000-0000-0000-{suffix:012}")) | |
| .expect("valid thread id") | |
| } | |
| async fn state_runtime() -> TestRuntime { | |
| let codex_home = TempDir::new().expect("tempdir should be created"); | |
| let state_db = StateRuntime::init( | |
| codex_state::SqliteConfig::new_for_testing(codex_home.path().abs()), | |
| "test-provider".to_string(), | |
| ) | |
| .await | |
| .expect("state db should initialize"); | |
| TestRuntime { | |
| state_db, | |
| _codex_home: codex_home, | |
| } | |
| } | |
| async fn local_store_upserts_and_lists_direct_children_with_status_filters() { | |
| let fixture = state_runtime().await; | |
| let state_db = fixture.state_db; | |
| let store = LocalAgentGraphStore::new(state_db.clone()); | |
| let parent_thread_id = thread_id(/*suffix*/ 1); | |
| let first_child_thread_id = thread_id(/*suffix*/ 2); | |
| let second_child_thread_id = thread_id(/*suffix*/ 3); | |
| store | |
| .upsert_thread_spawn_edge( | |
| parent_thread_id, | |
| second_child_thread_id, | |
| ThreadSpawnEdgeStatus::Closed, | |
| ) | |
| .await | |
| .expect("closed child edge should insert"); | |
| store | |
| .upsert_thread_spawn_edge( | |
| parent_thread_id, | |
| first_child_thread_id, | |
| ThreadSpawnEdgeStatus::Open, | |
| ) | |
| .await | |
| .expect("open child edge should insert"); | |
| let all_children = store | |
| .list_thread_spawn_children(parent_thread_id, /*status_filter*/ None) | |
| .await | |
| .expect("all children should load"); | |
| assert_eq!( | |
| all_children, | |
| vec![first_child_thread_id, second_child_thread_id] | |
| ); | |
| let open_children = store | |
| .list_thread_spawn_children(parent_thread_id, Some(ThreadSpawnEdgeStatus::Open)) | |
| .await | |
| .expect("open children should load"); | |
| let state_open_children = state_db | |
| .list_thread_spawn_children_with_status( | |
| parent_thread_id, | |
| DirectionalThreadSpawnEdgeStatus::Open, | |
| ) | |
| .await | |
| .expect("state open children should load"); | |
| assert_eq!(open_children, state_open_children); | |
| assert_eq!(open_children, vec![first_child_thread_id]); | |
| let closed_children = store | |
| .list_thread_spawn_children(parent_thread_id, Some(ThreadSpawnEdgeStatus::Closed)) | |
| .await | |
| .expect("closed children should load"); | |
| assert_eq!(closed_children, vec![second_child_thread_id]); | |
| } | |
| async fn local_store_updates_edge_status() { | |
| let fixture = state_runtime().await; | |
| let state_db = fixture.state_db; | |
| let store = LocalAgentGraphStore::new(state_db); | |
| let parent_thread_id = thread_id(/*suffix*/ 10); | |
| let child_thread_id = thread_id(/*suffix*/ 11); | |
| store | |
| .upsert_thread_spawn_edge( | |
| parent_thread_id, | |
| child_thread_id, | |
| ThreadSpawnEdgeStatus::Open, | |
| ) | |
| .await | |
| .expect("child edge should insert"); | |
| store | |
| .set_thread_spawn_edge_status(child_thread_id, ThreadSpawnEdgeStatus::Closed) | |
| .await | |
| .expect("child edge should close"); | |
| let open_children = store | |
| .list_thread_spawn_children(parent_thread_id, Some(ThreadSpawnEdgeStatus::Open)) | |
| .await | |
| .expect("open children should load"); | |
| assert_eq!(open_children, Vec::<ThreadId>::new()); | |
| let closed_children = store | |
| .list_thread_spawn_children(parent_thread_id, Some(ThreadSpawnEdgeStatus::Closed)) | |
| .await | |
| .expect("closed children should load"); | |
| assert_eq!(closed_children, vec![child_thread_id]); | |
| } | |
| async fn local_store_lists_descendants_breadth_first_with_status_filters() { | |
| let fixture = state_runtime().await; | |
| let state_db = fixture.state_db; | |
| let store = LocalAgentGraphStore::new(state_db.clone()); | |
| let root_thread_id = thread_id(/*suffix*/ 20); | |
| let later_child_thread_id = thread_id(/*suffix*/ 22); | |
| let earlier_child_thread_id = thread_id(/*suffix*/ 21); | |
| let closed_grandchild_thread_id = thread_id(/*suffix*/ 23); | |
| let open_grandchild_thread_id = thread_id(/*suffix*/ 24); | |
| let closed_child_thread_id = thread_id(/*suffix*/ 25); | |
| let closed_great_grandchild_thread_id = thread_id(/*suffix*/ 26); | |
| for (parent_thread_id, child_thread_id, status) in [ | |
| ( | |
| root_thread_id, | |
| later_child_thread_id, | |
| ThreadSpawnEdgeStatus::Open, | |
| ), | |
| ( | |
| root_thread_id, | |
| earlier_child_thread_id, | |
| ThreadSpawnEdgeStatus::Open, | |
| ), | |
| ( | |
| earlier_child_thread_id, | |
| open_grandchild_thread_id, | |
| ThreadSpawnEdgeStatus::Open, | |
| ), | |
| ( | |
| later_child_thread_id, | |
| closed_grandchild_thread_id, | |
| ThreadSpawnEdgeStatus::Closed, | |
| ), | |
| ( | |
| root_thread_id, | |
| closed_child_thread_id, | |
| ThreadSpawnEdgeStatus::Closed, | |
| ), | |
| ( | |
| closed_child_thread_id, | |
| closed_great_grandchild_thread_id, | |
| ThreadSpawnEdgeStatus::Closed, | |
| ), | |
| ] { | |
| store | |
| .upsert_thread_spawn_edge(parent_thread_id, child_thread_id, status) | |
| .await | |
| .expect("edge should insert"); | |
| } | |
| let all_descendants = store | |
| .list_thread_spawn_descendants(root_thread_id, /*status_filter*/ None) | |
| .await | |
| .expect("all descendants should load"); | |
| assert_eq!( | |
| all_descendants, | |
| vec![ | |
| earlier_child_thread_id, | |
| later_child_thread_id, | |
| closed_child_thread_id, | |
| closed_grandchild_thread_id, | |
| open_grandchild_thread_id, | |
| closed_great_grandchild_thread_id, | |
| ] | |
| ); | |
| let open_descendants = store | |
| .list_thread_spawn_descendants(root_thread_id, Some(ThreadSpawnEdgeStatus::Open)) | |
| .await | |
| .expect("open descendants should load"); | |
| let state_open_descendants = state_db | |
| .list_thread_spawn_descendants_with_status( | |
| root_thread_id, | |
| DirectionalThreadSpawnEdgeStatus::Open, | |
| ) | |
| .await | |
| .expect("state open descendants should load"); | |
| assert_eq!(open_descendants, state_open_descendants); | |
| assert_eq!( | |
| open_descendants, | |
| vec![ | |
| earlier_child_thread_id, | |
| later_child_thread_id, | |
| open_grandchild_thread_id, | |
| ] | |
| ); | |
| let closed_descendants = store | |
| .list_thread_spawn_descendants(root_thread_id, Some(ThreadSpawnEdgeStatus::Closed)) | |
| .await | |
| .expect("closed descendants should load"); | |
| assert_eq!( | |
| closed_descendants, | |
| vec![closed_child_thread_id, closed_great_grandchild_thread_id] | |
| ); | |
| } | |
| } | |