hippmem_engine/
list_api.rs1use crate::{Engine, EngineResult, ListInput, ListItem, ListOutput};
4
5impl Engine {
6 pub fn list(&self, input: ListInput) -> EngineResult<ListOutput> {
11 let limit = input.limit.clamp(1, 100);
12
13 let units = crate::retrieve_api::load_all_units(self.store.db_arc());
15
16 let mut items: Vec<ListItem> = units
18 .iter()
19 .filter(|u| {
20 if let Some(ref ct) = input.content_type {
21 u.content.content_type == *ct
22 } else {
23 true
24 }
25 })
26 .map(|u| ListItem {
27 id: u.id,
28 content_preview: u.content.raw.chars().take(100).collect(),
29 content_type: u.content.content_type,
30 created_at: u.created_at,
31 importance: u.understanding.importance.value(),
32 stage: u.stage,
33 lifecycle: u.lifecycle.clone(),
34 edge_count: u.links.len(),
35 })
36 .collect();
37
38 items.sort_by_key(|item| std::cmp::Reverse(item.id));
40
41 let total = items.len() as u64;
42
43 let start_idx = if let Some(cursor) = input.cursor {
45 items
47 .iter()
48 .position(|item| item.id.0 == cursor)
49 .map(|p| p + 1) .unwrap_or_else(|| {
51 items
53 .binary_search_by(|item| {
54 cursor.cmp(&item.id.0)
56 })
57 .unwrap_or_else(|insert_point| insert_point)
58 })
59 } else {
60 0
61 };
62
63 let end_idx = (start_idx + limit).min(items.len());
64 let has_more = end_idx < items.len();
65 let page: Vec<ListItem> = if start_idx < items.len() {
66 items.drain(start_idx..end_idx).collect()
67 } else {
68 Vec::new()
69 };
70
71 let next_cursor = if has_more {
72 page.last().map(|item| item.id.0)
73 } else {
74 None
75 };
76
77 Ok(ListOutput {
78 items: page,
79 next_cursor,
80 total,
81 })
82 }
83}