1use crate::auth::ScopedSpace;
6use crate::error::Result;
7use crate::{Engine, FactItem};
8
9#[derive(Debug)]
10pub struct Profile {
11 pub static_facts: Vec<FactItem>,
13 pub dynamic: Vec<String>,
15}
16
17impl Engine {
18 pub fn profile(&mut self, space: &ScopedSpace, limit: usize) -> Result<Profile> {
19 let limit = limit.clamp(1, 50) as i64;
20 let static_facts = {
21 let mut stmt = self.conn.prepare(
22 "SELECT f.id, en.canonical, f.predicate, f.object, f.confidence,
23 f.valid_from, f.valid_until, f.status
24 FROM facts f JOIN entities en ON en.id = f.subject_entity
25 WHERE f.space_id = ?1 AND f.status = 'active'
26 ORDER BY f.access_count DESC, f.confidence DESC, f.id
27 LIMIT ?2",
28 )?;
29 let rows = stmt.query_map(rusqlite::params![space.id(), limit], |r| {
30 Ok(FactItem {
31 fact_id: r.get(0)?,
32 subject: r.get(1)?,
33 predicate: r.get(2)?,
34 object: r.get(3)?,
35 confidence: r.get(4)?,
36 valid_from: r.get(5)?,
37 valid_until: r.get(6)?,
38 status: r.get(7)?,
39 })
40 })?;
41 rows.collect::<std::result::Result<Vec<_>, _>>()?
42 };
43 let dynamic = {
44 let mut stmt = self.conn.prepare(
45 "SELECT substr(content, 1, 200) FROM episodes
46 WHERE space_id = ?1 ORDER BY id DESC LIMIT ?2",
47 )?;
48 let rows = stmt.query_map(rusqlite::params![space.id(), limit], |r| {
49 r.get::<_, String>(0)
50 })?;
51 rows.collect::<std::result::Result<Vec<_>, _>>()?
52 };
53 Ok(Profile {
54 static_facts,
55 dynamic,
56 })
57 }
58}