A local-first private AI assistant for everyday use. Runs on-device models with encrypted P2P sync, and supports sharing chats publicly on ATProto.
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

wip: fetching delta

madclaws ed66c0a0 034367fe

+79 -5
+16 -2
tilekit/src/modelfile.rs
··· 61 61 } 62 62 } 63 63 64 + #[derive(Debug)] 65 + pub struct RoleError { 66 + pub error: String, 67 + } 68 + 69 + impl std::error::Error for RoleError {} 70 + impl Display for RoleError { 71 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 72 + write!(f, "{}", self.error) 73 + } 74 + } 75 + 64 76 impl FromStr for Role { 65 - type Err = String; 77 + type Err = RoleError; 66 78 fn from_str(s: &str) -> Result<Self, Self::Err> { 67 79 match s.to_lowercase().as_str() { 68 80 "system" => Ok(Role::System), 69 81 "user" => Ok(Role::User), 70 82 "assistant" => Ok(Role::Assistant), 71 - _ => Err("Invalid Role".to_owned()), 83 + _ => Err(RoleError { 84 + error: "Invalid Role".to_owned(), 85 + }), 72 86 } 73 87 } 74 88 }
+63 -3
tiles/src/core/chats.rs
··· 9 9 use crate::runtime::mlx::ChatResponse; 10 10 use crate::utils::get_unix_time_now; 11 11 use anyhow::Result; 12 - use rusqlite::types::{FromSql, FromSqlError, FromSqlResult}; 13 - use rusqlite::{Connection, OptionalExtension}; 12 + use rusqlite::Connection; 13 + use rusqlite::types::FromSqlError; 14 14 use tilekit::modelfile::Role; 15 15 use uuid::Uuid; 16 16 // model the chats table ··· 33 33 pub content: String, 34 34 } 35 35 36 + #[derive(Debug)] 36 37 pub struct Chats { 37 38 pub id: Uuid, 38 39 content: String, ··· 101 102 } 102 103 } 103 104 105 + /// Return list of rows.. 106 + /// encoding is the job of network modules 107 + /// 108 + fn get_delta_since_id(conn: &Connection, user_id: &str, last_entry_id: &str) -> Result<Vec<Chats>> { 109 + let mut stmt = conn.prepare("select id, user_id, content, resp_id, role, context_id, created_at, updated_at from chats where user_id = ?1 and id > ?2 order by id")?; 110 + 111 + let chat_rows = stmt.query_map([user_id, last_entry_id], |row| { 112 + let id: String = row.get(0)?; 113 + let role: String = row.get(4)?; 114 + let created_at: f64 = row.get(6)?; 115 + let updated_at: f64 = row.get(7)?; 116 + let ctx_id: String = row.get(5)?; 117 + let resp_id: String = row.get(3)?; 118 + let resp_id_opt = if resp_id.is_empty() { 119 + None 120 + } else { 121 + Some(resp_id) 122 + }; 123 + let ctx_id_opt = if ctx_id.is_empty() { 124 + None 125 + } else { 126 + Some(Uuid::from_str(&ctx_id).map_err(FromSqlError::other)?) 127 + }; 128 + Ok(Chats { 129 + id: Uuid::from_str(&id).map_err(FromSqlError::other)?, 130 + content: row.get(2)?, 131 + response_id: resp_id_opt, 132 + role: Role::from_str(&role).map_err(FromSqlError::other)?, 133 + user_id: row.get(1)?, 134 + context_id: ctx_id_opt, 135 + created_at: created_at as u64, 136 + updated_at: updated_at as u64, 137 + }) 138 + })?; 139 + 140 + let mut chats: Vec<Chats> = vec![]; 141 + 142 + for chat in chat_rows { 143 + chats.push(chat?); 144 + } 145 + 146 + Ok(chats) 147 + } 148 + 104 149 #[cfg(test)] 105 150 mod tests { 106 151 use std::time::{SystemTime, UNIX_EPOCH}; ··· 112 157 use crate::{ 113 158 core::{ 114 159 accounts::{ACCOUNT, User}, 115 - chats::{get_last_entry_id, save_chat}, 160 + chats::{get_delta_since_id, get_last_entry_id, save_chat}, 116 161 }, 117 162 runtime::mlx::ChatResponse, 118 163 }; ··· 228 273 let saved = get_last_entry_id(&conn, &user.user_id); 229 274 println!("{:?}", saved); 230 275 assert!(saved.unwrap().is_none()) 276 + } 277 + 278 + #[test] 279 + fn test_get_delta_diff() { 280 + let conn = setup_db_schema(); 281 + 282 + let user = create_user(); 283 + let input = "2+2"; 284 + let chat_1 = save_chat(&conn, &user, input, None).expect("chat should be saved"); 285 + let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 286 + let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 287 + let _ = save_chat(&conn, &user, input, None).expect("chat should be saved"); 288 + 289 + let rows = get_delta_since_id(&conn, &user.user_id, &chat_1.id.to_string()).unwrap(); 290 + println!("{:?}", rows); 231 291 } 232 292 233 293 struct SavedChatRow {