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.

refactor: Passing DB references most times than creating a new conn

- Will abort the sync if there is any write err, so that resync or debug
is possible

madclaws 4d6646e5 ef2d7c46

+39 -36
+7 -12
tiles/src/commands/mod.rs
··· 4 4 5 5 use anyhow::{Result, anyhow}; 6 6 use owo_colors::OwoColorize; 7 - use tiles::core; 8 7 use tiles::core::accounts::{ 9 8 RootUser, create_root_account, get_peer_list, get_root_user_details, save_root_account, 10 9 set_nickname, unlink, 11 10 }; 12 - use tiles::core::storage::db::get_db_conn; 11 + use tiles::core::storage::db::Dbconn; 13 12 use tiles::runtime::Runtime; 14 13 use tiles::utils::config::{ 15 14 ConfigProvider, DefaultProvider, get_or_create_config, set_user_data_path, ··· 254 253 Ok(()) 255 254 } 256 255 257 - pub async fn run(runtime: &Runtime, run_args: RunArgs) -> Result<()> { 258 - runtime.run(run_args).await 256 + pub async fn run(runtime: &Runtime, run_args: RunArgs, db_conn: &Dbconn) -> Result<()> { 257 + runtime.run(run_args, db_conn).await 259 258 } 260 259 261 260 pub fn set_data(path: &str) { ··· 338 337 ) 339 338 } 340 339 341 - pub fn show_peers() -> Result<()> { 342 - let db_conn = get_db_conn(&core::storage::db::DBTYPE::COMMON)?; 343 - 344 - let peers = get_peer_list(&db_conn)?; 340 + pub fn show_peers(db_conn: &Dbconn) -> Result<()> { 341 + let peers = get_peer_list(&db_conn.common)?; 345 342 346 343 println!("DID\tNickname\n"); 347 344 for peer in peers { ··· 350 347 Ok(()) 351 348 } 352 349 353 - pub fn unlink_peer(user_id: &str) -> Result<()> { 354 - let db_conn = get_db_conn(&core::storage::db::DBTYPE::COMMON)?; 355 - 356 - if let Err(err) = unlink(&db_conn, user_id) { 350 + pub fn unlink_peer(db_conn: &Dbconn, user_id: &str) -> Result<()> { 351 + if let Err(err) = unlink(&db_conn.common, user_id) { 357 352 println!("{:?}", err) 358 353 } else { 359 354 println!("Succesfully disabled the peer")
+2 -2
tiles/src/core/accounts.rs
··· 12 12 use uuid::Uuid; 13 13 14 14 use crate::{ 15 - core::storage::db::{DBTYPE, Dbconn, get_db_conn}, 16 - utils::config::{get_or_create_config, save_config}, 15 + core::storage::db::Dbconn, 16 + utils::config::{get_app_name, get_or_create_config, save_config}, 17 17 }; 18 18 const ROOT_USER_CONFIG_KEY: &str = "root-user"; 19 19
+12 -1
tiles/src/core/chats.rs
··· 180 180 // TODO: Handle primary key conflict, for now reject it (in a way its impossible to have this scenario, and if its occuring then that means 181 181 // some issue in syncing, so ignore it, by rejecting it), later 182 182 // do LWW based on issuer of UCAN 183 + // 184 + 183 185 let txn = chat_conn.transaction()?; 184 186 { 185 187 let mut stmt = txn.prepare("insert into chats(id, user_id, content, resp_id, role, context_id, created_at, updated_at, row_counter) values (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)")?; ··· 204 206 &chat.id 205 207 ); 206 208 } 207 - Err(err) => log::error!("err in writing row due to {:?}", err), 209 + // NOTE: If any other error occurs and write failed we abort the sync, so the the row_counter doesn't get skipped. 210 + // use RUST_LOG=error tiles to debug the issue 211 + Err(err) => { 212 + log::error!( 213 + "err in writing row due to {:?}, Aborting the sync ....", 214 + err 215 + ); 216 + break; 217 + } 218 + 208 219 Ok(_) => (), 209 220 } 210 221 }
+1 -4
tiles/src/core/mod.rs
··· 5 5 6 6 use anyhow::Result; 7 7 8 - use crate::core::{ 9 - accounts::save_root_account_db, 10 - storage::db::{Dbconn, init_db}, 11 - }; 8 + use crate::core::{accounts::save_root_account_db, storage::db::Dbconn}; 12 9 13 10 pub mod accounts; 14 11 pub mod chats;
+5 -5
tiles/src/main.rs
··· 5 5 use clap::{Args, Parser, Subcommand}; 6 6 use tiles::{ 7 7 core::{ 8 - self, init, 8 + self, 9 9 network::{link, sync}, 10 10 storage::db::init_db, 11 11 }, ··· 213 213 core::init(&db_conn) 214 214 .inspect_err(|e| eprintln!("Tiles core init failed due to {:?}", e))?; 215 215 if !cli.flags.no_repl { 216 - commands::run(&runtime, run_args) 216 + commands::run(&runtime, run_args, &db_conn) 217 217 .await 218 218 .inspect_err(|e| eprintln!("Tiles failed to run due to {:?}", e))?; 219 219 } ··· 229 229 }; 230 230 core::init(&db_conn) 231 231 .inspect_err(|e| eprintln!("Tiles core init failed due to {:?}", e))?; 232 - commands::run(&runtime, run_args) 232 + commands::run(&runtime, run_args, &db_conn) 233 233 .await 234 234 .inspect_err(|e| eprintln!("Tiles failed to run due to {:?}", e))?; 235 235 } ··· 275 275 }, 276 276 Some(Commands::Link(link_args)) => match link_args.command { 277 277 LinkCommands::Enable { ticket } => link(ticket).await?, 278 - LinkCommands::Disable { did } => unlink_peer(&did)?, 278 + LinkCommands::Disable { did } => unlink_peer(&db_conn, &did)?, 279 279 LinkCommands::ListPeers => { 280 - show_peers()?; 280 + show_peers(&db_conn)?; 281 281 } 282 282 }, 283 283 Some(Commands::Sync { did }) => sync(did).await?,
+9 -9
tiles/src/runtime/mlx.rs
··· 1 1 use crate::core::accounts::{User, get_current_user}; 2 2 use crate::core::chats::{Message, save_chat}; 3 - use crate::core::storage::db::get_db_conn; 3 + use crate::core::storage::db::Dbconn; 4 4 use crate::runtime::RunArgs; 5 5 use crate::utils::config::{ConfigProvider, DefaultProvider, get_memory_path, get_model_cache}; 6 6 use crate::utils::hf_model_downloader::*; ··· 70 70 MLXRuntime {} 71 71 } 72 72 73 - pub async fn run(&self, run_args: super::RunArgs) -> Result<()> { 73 + pub async fn run(&self, run_args: super::RunArgs, db_conn: &Dbconn) -> Result<()> { 74 74 let default_modelfile_path = get_default_modelfile(run_args.memory)?; 75 75 let default_modelfile = 76 76 tilekit::modelfile::parse_from_file(default_modelfile_path.to_str().unwrap()).unwrap(); ··· 89 89 } 90 90 }; 91 91 92 - run_model_with_server(self, modelfile, default_modelfile, &run_args).await 92 + run_model_with_server(self, modelfile, default_modelfile, &run_args, db_conn).await 93 93 } 94 94 95 95 #[allow(clippy::zombie_processes)] ··· 228 228 modelfile: Modelfile, 229 229 default_modelfile: Modelfile, 230 230 run_args: &RunArgs, 231 + db_conn: &Dbconn, 231 232 ) -> Result<()> { 232 233 if !cfg!(debug_assertions) { 233 234 let _ = mlx_runtime.start_server_daemon().await.inspect_err(|e| { ··· 238 239 // loading the model from mem-agent via daemon server 239 240 let memory_path = get_memory_path().context("Setting/Retrieving memory_path failed")?; 240 241 match load_model(&modelfile, &default_modelfile, &memory_path).await { 241 - Ok(_) => start_repl(mlx_runtime, &modelfile, run_args).await?, 242 + Ok(_) => start_repl(mlx_runtime, &modelfile, run_args, db_conn).await?, 242 243 Err(err) => return Err(anyhow::anyhow!(err)), 243 244 } 244 245 Ok(()) ··· 248 249 mlx_runtime: &MLXRuntime, 249 250 modelfile: &Modelfile, 250 251 run_args: &RunArgs, 252 + db_conn: &Dbconn, 251 253 ) -> Result<()> { 252 254 let modelname = modelfile 253 255 .from ··· 255 257 .ok_or_else(|| anyhow!("Error getting FROM from modelfile due to"))?; 256 258 257 259 println!("Running {} in interactive mode", modelname); 258 - let common_db_conn = get_db_conn(&crate::core::storage::db::DBTYPE::COMMON)?; 259 - let chat_db_conn = get_db_conn(&crate::core::storage::db::DBTYPE::CHAT)?; 260 - let current_user = get_current_user(&common_db_conn)?; 260 + let current_user = get_current_user(&db_conn.common)?; 261 261 262 262 let config = Config::builder().auto_add_history(true).build(); 263 263 let mut editor = Editor::<TilesHinter, DefaultHistory>::with_config(config).unwrap(); ··· 315 315 &g_reply, 316 316 run_args, 317 317 &prev_response_id, 318 - &chat_db_conn, 318 + &db_conn.chat, 319 319 &current_user, 320 320 &conversations, 321 321 ) ··· 349 349 content: g_reply.clone(), 350 350 }); 351 351 352 - save_chat(&chat_db_conn, &current_user, &g_reply, Some(&response))?; 352 + save_chat(&db_conn.chat, &current_user, &g_reply, Some(&response))?; 353 353 // Display benchmark metrics if available 354 354 if let Some(metrics) = response.metrics { 355 355 bench_metrics.update(metrics);
+3 -3
tiles/src/runtime/mod.rs
··· 1 1 #[allow(unused_imports)] 2 2 use crate::runtime::cpu::CPURuntime; 3 - use crate::runtime::mlx::MLXRuntime; 3 + use crate::{core::storage::db::Dbconn, runtime::mlx::MLXRuntime}; 4 4 use anyhow::Result; 5 5 pub mod cpu; 6 6 pub mod mlx; ··· 17 17 } 18 18 19 19 impl Runtime { 20 - pub async fn run(&self, run_args: RunArgs) -> Result<()> { 20 + pub async fn run(&self, run_args: RunArgs, db_conn: &Dbconn) -> Result<()> { 21 21 match self { 22 - Runtime::Mlx(runtime) => runtime.run(run_args).await, 22 + Runtime::Mlx(runtime) => runtime.run(run_args, db_conn).await, 23 23 Runtime::Cpu(runtime) => runtime.run(run_args).await, 24 24 } 25 25 }