cognee_http_server/components.rs
1//! `ComponentHandles` — pre-built component instances passed to P2 handlers.
2//!
3//! This struct is a lightweight alternative to `cognee_lib::ComponentManager`
4//! that avoids a dependency cycle: `cognee-lib` may eventually import
5//! `cognee-http-server`, so `cognee-http-server` must not import `cognee-lib`.
6//!
7//! All components are eagerly initialized in `AppState::build`; there is no
8//! lazy caching here (unlike `ComponentManager`'s `RwLock` slots).
9
10use std::sync::Arc;
11
12use cognee_core::CpuPool;
13use cognee_database::AclDb;
14use cognee_database::{CheckpointStore, DatabaseConnection};
15use cognee_delete::DeleteService;
16use cognee_embedding::EmbeddingEngine;
17use cognee_graph::GraphDBTrait;
18use cognee_llm::Llm;
19use cognee_llm::ResponsesClient;
20use cognee_llm::Transcriber;
21use cognee_ontology::{OntologyManager, OntologyResolver};
22use cognee_search::{SearchOrchestrator, SessionManager, SessionStore};
23use cognee_storage::StorageTrait;
24use cognee_vector::VectorDB;
25
26use crate::cloud_client::CloudDeleteClient;
27use crate::notebook_runner::NotebookRunner;
28
29/// Pre-initialized pipeline component handles shared across all P2 handlers.
30///
31/// Obtained from `state.components()`.
32#[derive(Clone)]
33pub struct ComponentHandles {
34 /// SeaORM database connection (implements `IngestDb`, `DeleteDb`).
35 /// The `AclDb` implementation is provided by the closed
36 /// `cognee-access-control` crate and wired through [`Self::acl_db`].
37 pub database: Arc<DatabaseConnection>,
38
39 /// Optional ACL backend. `None` in pure-OSS builds (which do not enforce
40 /// permissions). Wired by the closed cloud assembly to a newtype that
41 /// implements `AclDb` over the shared `DatabaseConnection`.
42 pub acl_db: Option<Arc<dyn AclDb>>,
43
44 /// File storage backend.
45 pub storage: Arc<dyn StorageTrait>,
46
47 /// Fully configured `DeleteService` (with storage + DB wired).
48 pub delete_service: Arc<DeleteService>,
49
50 /// Optional cloud delete proxy used by `POST /api/v1/forget`.
51 pub cloud_client: Option<Arc<dyn CloudDeleteClient>>,
52
53 /// Ontology manager (per-user file storage).
54 pub ontology_manager: Arc<OntologyManager>,
55
56 // ── P4 read-path slots ────────────────────────────────────────────────
57 //
58 // Optional handles wired by embedders that want the full read-path
59 // surface. Each slot is `None` by default; the relevant routers
60 // surface a 500-level error when the corresponding handle is missing.
61 /// Pre-built search orchestrator. `None` means HTTP search is unwired
62 /// — handlers return `SearchError {500, "Internal server error"}`.
63 pub search_orchestrator: Option<Arc<SearchOrchestrator>>,
64
65 /// Configured LLM adapter for `/api/v1/llm/*` handlers.
66 pub llm: Option<Arc<dyn Llm>>,
67
68 /// Transcriber for audio document processing (Whisper). `None` when the
69 /// configured LLM provider does not support audio transcription.
70 pub transcriber: Option<Arc<dyn Transcriber>>,
71
72 /// Knowledge-graph DB used by the visualize router.
73 pub graph_db: Option<Arc<dyn GraphDBTrait>>,
74
75 /// Vector DB handle required by [`cognee_core::TaskContext`] when the
76 /// add / cognify / memify convenience functions route through
77 /// `pipeline::execute` (LIB-06). `None` means the corresponding
78 /// pipeline handlers surface a 500 / 409 envelope at runtime.
79 pub vector_db: Option<Arc<dyn VectorDB>>,
80
81 /// CPU pool used by [`cognee_core::TaskContext`]. Same routing notes
82 /// as [`vector_db`](Self::vector_db).
83 pub thread_pool: Option<Arc<dyn CpuPool>>,
84
85 /// Text embedding engine used by the cognify pipeline (chunks, entities,
86 /// summaries). `None` means the cognify / update handlers surface a 500
87 /// envelope at runtime.
88 pub embedding_engine: Option<Arc<dyn EmbeddingEngine>>,
89
90 /// Ontology resolver passed into the cognify pipeline. `None` means
91 /// the cognify / update handlers fall back to a pass-through
92 /// `NoOpOntologyResolver`, matching the CLI default when no
93 /// `ontology_file_path` is configured.
94 pub ontology_resolver: Option<Arc<dyn OntologyResolver>>,
95
96 /// Backing store for session Q&A history — wires the `session` source
97 /// of `POST /api/v1/recall` (Python `_search_session`,
98 /// `recall.py:146-208`). `None` means session-source recall returns
99 /// empty (matches Python's `is_available` short-circuit at
100 /// `recall.py:170-171`). Reuses the `SessionStore` re-exported by
101 /// `cognee-search` to avoid pulling `cognee-session` into the crate's
102 /// non-dev dependency graph.
103 pub session_store: Option<Arc<dyn SessionStore>>,
104
105 /// Manager for agent-trace sessions and the per-session graph context
106 /// snapshot — wires the `trace` and `graph_context` sources of
107 /// `POST /api/v1/recall` (Python `_search_trace` /
108 /// `_fetch_graph_context`). `None` means both sources return empty.
109 pub session_manager: Option<Arc<SessionManager>>,
110
111 /// Checkpoint store used by improve Stage 4 (`sync_graph_to_session`) to
112 /// persist per-session high-water marks and avoid re-syncing old edges.
113 pub checkpoint_store: Option<Arc<dyn CheckpointStore>>,
114
115 /// OpenAI Responses API client — wires `POST /api/v1/responses`
116 /// (Python `get_responses_router.py`). `None` means the handler
117 /// returns `500` "responses client is not wired" until embedders
118 /// populate it.
119 pub responses_client: Option<Arc<dyn ResponsesClient>>,
120
121 /// Notebook cell execution backend used by
122 /// `POST /api/v1/notebooks/{notebook_id}/{cell_id}/run`. `None` means
123 /// the handler returns 501 — the same envelope it returned in Stage A
124 /// before Stage B landed — preserving wire compatibility for embedders
125 /// that don't want to expose code execution.
126 pub notebook_runner: Option<Arc<dyn NotebookRunner>>,
127}
128
129impl ComponentHandles {
130 /// Return the formatted knowledge-graph data for a dataset as the JSON
131 /// shape `{"nodes": [...], "edges": [...]}`.
132 ///
133 /// Wires to `cognee_graph::get_formatted_graph_data` when both a
134 /// `graph_db` handle and a `dataset_id` are available. When either is
135 /// missing — e.g. the server is running in test mode without backends —
136 /// returns the empty-graph fallback `{"nodes": [], "edges": []}` so that
137 /// the WS frame still has a valid shape.
138 ///
139 /// Python parity: `cognee.modules.graph.methods.get_formatted_graph_data`.
140 pub async fn formatted_graph_data(
141 &self,
142 dataset_id: Option<uuid::Uuid>,
143 user_id: uuid::Uuid,
144 ) -> Result<serde_json::Value, anyhow::Error> {
145 let Some(graph_db) = self.graph_db.as_ref() else {
146 return Ok(serde_json::json!({"nodes": [], "edges": []}));
147 };
148 let Some(did) = dataset_id else {
149 return Ok(serde_json::json!({"nodes": [], "edges": []}));
150 };
151 cognee_graph::get_formatted_graph_data(graph_db.as_ref(), did, user_id)
152 .await
153 .map_err(|e| anyhow::anyhow!("get_formatted_graph_data failed: {e}"))
154 }
155}