mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Add agent graph store interface (#19229)
## Summary Persisted subagent parent/child topology currently leaks through `StateRuntime`'s SQLite-specific thread-spawn helpers. This PR introduces a narrow `AgentGraphStore` boundary so follow-up work can route graph operations through a local or remote store without coupling orchestration code directly to the state DB graph API. ## Changes - Adds the new `codex-agent-graph-store` crate. - Defines a flat `AgentGraphStore` trait for the v1 graph surface: upsert edge, set edge status, list direct children, and list descendants. - Adds public graph types for `ThreadSpawnEdgeStatus`, `AgentGraphStoreError`, and `AgentGraphStoreResult`. - Implements `LocalAgentGraphStore` on top of an existing `codex_state::StateRuntime`, preserving today's SQLite-backed `thread_spawn_edges` behavior. - Registers the crate in Cargo/Bazel metadata. This PR only adds the local contract and implementation; call-site migration and the remote gRPC store are left to the follow-up PRs in the stack. ## Testing - `cargo test -p codex-agent-graph-store` The new unit tests cover local parity with the existing `StateRuntime` graph methods, `Open`/`Closed` filtering, status updates, and stable breadth-first descendant ordering.
This commit is contained in:
committed by
GitHub
Unverified
parent
e20391e567
commit
782191547c
@@ -134,6 +134,15 @@ ON CONFLICT(child_thread_id) DO UPDATE SET
|
||||
.await
|
||||
}
|
||||
|
||||
/// List all direct spawned children of `parent_thread_id`.
|
||||
pub async fn list_thread_spawn_children(
|
||||
&self,
|
||||
parent_thread_id: ThreadId,
|
||||
) -> anyhow::Result<Vec<ThreadId>> {
|
||||
self.list_thread_spawn_children_matching(parent_thread_id, /*status*/ None)
|
||||
.await
|
||||
}
|
||||
|
||||
/// List spawned descendants of `root_thread_id` whose edges match `status`.
|
||||
///
|
||||
/// Descendants are returned breadth-first by depth, then by thread id for stable ordering.
|
||||
@@ -1871,4 +1880,65 @@ mod tests {
|
||||
.expect("all descendants should load");
|
||||
assert_eq!(all_descendants, vec![child_thread_id, grandchild_thread_id]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_spawn_children_without_status_filter_lists_all_statuses() {
|
||||
let codex_home = unique_temp_dir();
|
||||
let runtime = StateRuntime::init(codex_home, "test-provider".to_string())
|
||||
.await
|
||||
.expect("state db should initialize");
|
||||
let parent_thread_id =
|
||||
ThreadId::from_string("00000000-0000-0000-0000-000000000910").expect("valid thread id");
|
||||
let open_child_thread_id =
|
||||
ThreadId::from_string("00000000-0000-0000-0000-000000000911").expect("valid thread id");
|
||||
let closed_child_thread_id =
|
||||
ThreadId::from_string("00000000-0000-0000-0000-000000000912").expect("valid thread id");
|
||||
let future_child_thread_id =
|
||||
ThreadId::from_string("00000000-0000-0000-0000-000000000913").expect("valid thread id");
|
||||
|
||||
runtime
|
||||
.upsert_thread_spawn_edge(
|
||||
parent_thread_id,
|
||||
open_child_thread_id,
|
||||
DirectionalThreadSpawnEdgeStatus::Open,
|
||||
)
|
||||
.await
|
||||
.expect("open child edge insert should succeed");
|
||||
runtime
|
||||
.upsert_thread_spawn_edge(
|
||||
parent_thread_id,
|
||||
closed_child_thread_id,
|
||||
DirectionalThreadSpawnEdgeStatus::Closed,
|
||||
)
|
||||
.await
|
||||
.expect("closed child edge insert should succeed");
|
||||
sqlx::query(
|
||||
r#"
|
||||
INSERT INTO thread_spawn_edges (
|
||||
parent_thread_id,
|
||||
child_thread_id,
|
||||
status
|
||||
) VALUES (?, ?, ?)
|
||||
"#,
|
||||
)
|
||||
.bind(parent_thread_id.to_string())
|
||||
.bind(future_child_thread_id.to_string())
|
||||
.bind("future")
|
||||
.execute(runtime.pool.as_ref())
|
||||
.await
|
||||
.expect("future-status child edge insert should succeed");
|
||||
|
||||
let children = runtime
|
||||
.list_thread_spawn_children(parent_thread_id)
|
||||
.await
|
||||
.expect("all children should load");
|
||||
assert_eq!(
|
||||
children,
|
||||
vec![
|
||||
open_child_thread_id,
|
||||
closed_child_thread_id,
|
||||
future_child_thread_id,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user