cognee_lib/api/notebooks/mod.rs
1//! `cognee_lib::notebooks` — per-user notebook CRUD facade.
2//!
3//! Wraps `cognee_database::NotebookDb` with tutorial seeding and the Python
4//! truthiness-bug compat notes documented in `docs/http-server/routers/notebooks.md`.
5
6pub mod tutorial;
7
8use std::sync::Arc;
9
10use thiserror::Error;
11use uuid::Uuid;
12
13use cognee_database::{
14 DatabaseError, Notebook, NotebookDb, NotebookUpdatePatch, seed_tutorials_if_first_call,
15};
16
17pub use tutorial::{TUTORIAL_BASICS_ID, TUTORIAL_PYTHON_DEV_ID};
18
19// ─── NotebookError ────────────────────────────────────────────────────────────
20
21#[derive(Debug, Error)]
22pub enum NotebookError {
23 #[error("database error: {0}")]
24 Database(#[from] DatabaseError),
25}
26
27// ─── Public API ───────────────────────────────────────────────────────────────
28
29/// List all notebooks for `user_id`.
30///
31/// On the very first call for a new user this seeds the two bundled tutorial
32/// notebooks (idempotent — re-running is safe).
33pub async fn list_notebooks(
34 db: &Arc<dyn NotebookDb>,
35 user_id: Uuid,
36) -> Result<Vec<Notebook>, NotebookError> {
37 seed_tutorials_if_first_call(db.as_ref(), user_id).await?;
38 Ok(db.list_by_owner(user_id).await?)
39}
40
41/// Create a new notebook.
42///
43/// `deletable` is always forced to `true` regardless of the parameter value —
44/// this replicates Python's `deletable=deletable or True` truthiness bug so
45/// the HTTP surface is byte-identical to the Python SDK.
46pub async fn create_notebook(
47 db: &Arc<dyn NotebookDb>,
48 user_id: Uuid,
49 name: String,
50 cells: serde_json::Value,
51 _deletable: bool,
52) -> Result<Notebook, NotebookError> {
53 // Python's create_notebook always ends up with deletable=True due to the
54 // `deletable or True` expression. We replicate the bug for wire compat.
55 Ok(db.create(user_id, name, cells, true).await?)
56}
57
58/// Update a notebook's name and/or cells.
59///
60/// Replicates Python's truthiness-gated assignment:
61/// - `name` is only updated when `patch.name` is `Some` and non-empty.
62/// - `cells` is only updated when `patch.cells` is `Some(Value::Array(v))` with
63/// `v` non-empty — an empty cells list **does not clear cells**.
64pub async fn update_notebook(
65 db: &Arc<dyn NotebookDb>,
66 id: Uuid,
67 user_id: Uuid,
68 patch: NotebookUpdatePatch,
69) -> Result<Option<Notebook>, NotebookError> {
70 Ok(db.update(id, user_id, patch).await?)
71}
72
73/// Delete a notebook. Returns `true` if a row was removed.
74pub async fn delete_notebook(
75 db: &Arc<dyn NotebookDb>,
76 id: Uuid,
77 user_id: Uuid,
78) -> Result<bool, NotebookError> {
79 Ok(db.delete(id, user_id).await?)
80}