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.

Merge pull request #116 from tilesprivacy/fix/health-command

health command upgrade and other QOL changes

authored by

Anandu Pavanan and committed by
GitHub
337f43bf dd08ec99

+137 -26
+2 -2
tiles/src/commands/mod.rs
··· 268 268 } 269 269 } 270 270 } 271 - pub async fn check_health() { 272 - health::check_health().await; 271 + pub async fn check_health() -> Result<()> { 272 + health::check_health().await 273 273 } 274 274 275 275 pub async fn start_server(runtime: &Runtime) {
+27 -22
tiles/src/core/health.rs
··· 1 1 // Contains functions for health checking various dependencies 2 2 3 - use std::{env, process::Command}; 3 + use std::env; 4 + 5 + use anyhow::Result; 4 6 5 - use crate::runtime::mlx::ping; 7 + use crate::{ 8 + daemon::ping, 9 + utils::installer::{UpdateInfo, get_update_info}, 10 + }; 6 11 7 - pub async fn check_health() { 12 + pub async fn check_health() -> Result<()> { 8 13 let os = env::consts::OS; 9 - println!("Running diagnosis..."); 10 - check_python3(); 11 - if os == "macos" { 12 - check_server_status().await 13 - } 14 - } 14 + println!("Running diagnosis...\n"); 15 15 16 - fn check_python3() { 17 - let output = Command::new("python3") 18 - .arg("--version") 19 - .output() 20 - .ok() 21 - .map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string()); 22 - 23 - if let Some(version) = output { 24 - println!("Python3: ✅ {}", version) 16 + println!("Checking for newer version...\n"); 17 + let update_info: UpdateInfo = get_update_info().await?; 18 + if update_info.can_update { 19 + println!("⚠️ Outdated version, try `tiles update`"); 20 + let update_str = format!( 21 + "\tcurrent version - {}\n\tlatest version - {}", 22 + update_info.current_version, update_info.latest_version 23 + ); 24 + println!("{}", update_str); 25 25 } else { 26 - println!("Python3: ❌ hint: Install Python3 for your OS") 26 + println!("✅ Running latest version\n"); 27 27 } 28 + if os == "macos" && !cfg!(debug_assertions) { 29 + check_server_status().await; 30 + } 31 + Ok(()) 28 32 } 33 + 29 34 async fn check_server_status() { 30 - if ping().await.is_ok() { 31 - println!("Model server is UP: ✅") 35 + if ping(None).await.is_ok() { 36 + println!("✅ Daemon is UP") 32 37 } else { 33 - println!("Model server is DOWN: ❌, try `tiles server start`") 38 + println!("❌ Daemon is DOWN, try `tiles daemon start`") 34 39 } 35 40 }
+89
tiles/src/core/network/mod.rs
··· 789 789 } 790 790 Ok(()) 791 791 } 792 + 793 + #[cfg(test)] 794 + mod tests { 795 + 796 + use iroh::{Endpoint, endpoint::presets, endpoint_info::UserData}; 797 + use tokio::sync::mpsc; 798 + 799 + use crate::core::{ 800 + accounts::create_dummy_user, 801 + chats::SyncOp, 802 + network::{ 803 + create_topic_id, fetch_last_row_counter, parse_link_ticket, 804 + ticket::{EndpointUserData, LinkTicket}, 805 + }, 806 + }; 807 + 808 + #[tokio::test] 809 + async fn test_valid_parse_link_ticket_online() { 810 + let topic_id = create_topic_id("test"); 811 + let user = create_dummy_user(); 812 + let usr_data = EndpointUserData::new(&user.user_id, &user.username); 813 + let endpoint = Endpoint::builder(presets::N0) 814 + .user_data_for_address_lookup(UserData::try_from(usr_data.to_string()).unwrap()) 815 + .bind() 816 + .await 817 + .unwrap(); 818 + 819 + let ticket = LinkTicket::new( 820 + topic_id, 821 + endpoint.addr(), 822 + user.user_id.clone(), 823 + user.username.clone(), 824 + ); 825 + 826 + assert!(parse_link_ticket(&ticket.to_string()).is_ok()) 827 + } 828 + 829 + #[tokio::test] 830 + async fn test_invalid_parse_link_ticket_online() { 831 + let topic_id = create_topic_id("test"); 832 + let user = create_dummy_user(); 833 + let usr_data = EndpointUserData::new(&user.user_id, &user.username); 834 + let endpoint = Endpoint::builder(presets::N0) 835 + .user_data_for_address_lookup(UserData::try_from(usr_data.to_string()).unwrap()) 836 + .bind() 837 + .await 838 + .unwrap(); 839 + 840 + let ticket = LinkTicket::new( 841 + topic_id, 842 + endpoint.addr(), 843 + user.user_id.clone(), 844 + user.username.clone(), 845 + ); 846 + 847 + let invalid_ticket = format!("{}xx", ticket); 848 + assert!(parse_link_ticket(&invalid_ticket).is_err()) 849 + } 850 + 851 + #[test] 852 + fn test_invalid_parse_link_ticket_offline() { 853 + let ticket = "kjadkjada"; 854 + 855 + assert!(parse_link_ticket(ticket).is_err()) 856 + } 857 + 858 + #[test] 859 + fn test_valid_parse_link_ticket_offline() { 860 + let ticket = "kjadkja2"; 861 + 862 + assert!(parse_link_ticket(ticket).is_ok()) 863 + } 864 + 865 + #[tokio::test] 866 + async fn test_fetch_last_row_counter() { 867 + { 868 + let (tx, mut rx) = mpsc::channel::<SyncOp>(32); 869 + 870 + let _handler = tokio::spawn(async move { 871 + while let Some(msg) = rx.recv().await { 872 + if let SyncOp::GetLastRowCounter { user_id: _, resp } = msg { 873 + resp.send(Ok(1)).unwrap(); 874 + } 875 + } 876 + }); 877 + assert_eq!(fetch_last_row_counter("did:key:xx", &tx).await.unwrap(), 1); 878 + } 879 + } 880 + }
+18 -1
tiles/src/core/storage/db.rs
··· 3 3 //! Uses sqlite as the underlying database 4 4 //! 5 5 6 - use std::path::PathBuf; 6 + use std::{env, path::PathBuf}; 7 7 8 8 use anyhow::{Result, anyhow}; 9 9 use log::info; ··· 117 117 118 118 fn fetch_passkey() -> Result<String> { 119 119 let app_name = get_app_name(); 120 + // handling db passwords in dev mode separately 121 + // This is to suppress keychain popups during development 122 + 123 + if cfg!(debug_assertions) { 124 + if let Ok(passwd) = env::var("TILES_DEV_DB_PASSWORD") { 125 + return Ok(passwd); 126 + } else { 127 + info!("DB passkey not found in development, creating one.."); 128 + let passwd = create_and_save_passkey(&app_name, "db_passkey")?; 129 + info!( 130 + "Save this password {} as an environment variable with name `TILES_DEV_DB_PASSWORD`", 131 + passwd 132 + ); 133 + return Ok(passwd); 134 + } 135 + } 136 + 120 137 if let Ok(passkey) = get_passkey(&app_name, "db_passkey") { 121 138 Ok(passkey) 122 139 } else {
+1 -1
tiles/src/main.rs
··· 233 233 .inspect_err(|e| eprintln!("Tiles failed to run due to {:?}", e))?; 234 234 } 235 235 Some(Commands::Health) => { 236 - commands::check_health().await; 236 + commands::check_health().await?; 237 237 } 238 238 Some(Commands::Server(server)) => match server.command { 239 239 Some(ServerCommands::Start) => commands::start_server(&runtime).await,