From 38c7355e439b795c912bf1d2f2fd994d47fc9d40 Mon Sep 17 00:00:00 2001 From: Louis Date: Mon, 7 Apr 2025 02:03:51 +0700 Subject: [PATCH] refactor: app logging - script-src access in release --- package.json | 1 - src-tauri/Cargo.toml | 5 +---- src-tauri/capabilities/default.json | 11 ++++------- src-tauri/src/core/cmd.rs | 16 +++++++-------- src-tauri/src/core/fs.rs | 2 +- src-tauri/src/core/mcp.rs | 6 +++--- src-tauri/src/core/server.rs | 20 +++++++++---------- src-tauri/src/core/setup.rs | 17 ++++++++-------- src-tauri/src/lib.rs | 30 +++++++++++++++-------------- src-tauri/tauri.conf.json | 11 ++++++----- web/hooks/useLoadTheme.ts | 10 +++++----- 11 files changed, 62 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index ea58ead59..2b8b2de15 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "dev:electron": "yarn copy:assets && yarn workspace jan dev", "dev:web:standalone": "concurrently \"yarn workspace @janhq/web dev\" \"wait-on http://localhost:3000 && rsync -av --prune-empty-dirs --include '*/' --include 'dist/***' --include 'package.json' --include 'tsconfig.json' --exclude '*' ./extensions/ web/.next/static/extensions/\"", "dev:web": "yarn workspace @janhq/web dev", - "dev:web:tauri": "IS_TAURI=true yarn workspace @janhq/web dev", "dev:server": "yarn workspace @janhq/server dev", "dev": "concurrently -n \"NEXT,ELECTRON\" -c \"yellow,blue\" --kill-others \"yarn dev:web\" \"yarn dev:electron\"", "install:cortex:linux:darwin": "cd src-tauri/binaries && ./download.sh", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 20df85561..5ef4e7a4e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -21,9 +21,7 @@ tauri-build = { version = "2.0.2", features = [] } serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } log = "0.4" -tauri = { version = "2.1.0", features = [ - "protocol-asset", - 'macos-private-api', +tauri = { version = "2.1.0", features = [ "protocol-asset", "macos-private-api", "test", ] } tauri-plugin-log = "2.0.0-rc" @@ -36,7 +34,6 @@ tauri-plugin-store = "2" hyper = { version = "0.14", features = ["server"] } reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1", features = ["full"] } -tracing = "0.1.41" rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk", branch = "main", features = [ "client", "transport-sse", diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index ca95964ee..0544b1312 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -2,18 +2,15 @@ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "enables the default permissions", - "windows": [ - "main" - ], + "windows": ["main"], "remote": { - "urls": [ - "http://*" - ] + "urls": ["http://*"] }, "permissions": [ "core:default", "shell:allow-spawn", "shell:allow-open", + "log:default", { "identifier": "http:default", "allow": [ @@ -55,4 +52,4 @@ }, "store:default" ] -} \ No newline at end of file +} diff --git a/src-tauri/src/core/cmd.rs b/src-tauri/src/core/cmd.rs index 62f53bf56..0fe706a1a 100644 --- a/src-tauri/src/core/cmd.rs +++ b/src-tauri/src/core/cmd.rs @@ -35,7 +35,7 @@ pub fn get_app_configurations(app_handle: tauri::AppHandle) -> Ap let default_data_folder = default_data_folder_path(app_handle.clone()); if !configuration_file.exists() { - println!( + log::info!( "App config not found, creating default config at {:?}", configuration_file ); @@ -46,7 +46,7 @@ pub fn get_app_configurations(app_handle: tauri::AppHandle) -> Ap &configuration_file, serde_json::to_string(&app_default_configuration).unwrap(), ) { - eprintln!("Failed to create default config: {}", err); + log::error!("Failed to create default config: {}", err); } return app_default_configuration; @@ -56,7 +56,7 @@ pub fn get_app_configurations(app_handle: tauri::AppHandle) -> Ap Ok(content) => match serde_json::from_str::(&content) { Ok(app_configurations) => app_configurations, Err(err) => { - eprintln!( + log::error!( "Failed to parse app config, returning default config instead. Error: {}", err ); @@ -64,7 +64,7 @@ pub fn get_app_configurations(app_handle: tauri::AppHandle) -> Ap } }, Err(err) => { - eprintln!( + log::error!( "Failed to read app config, returning default config instead. Error: {}", err ); @@ -79,7 +79,7 @@ pub fn update_app_configuration( configuration: AppConfiguration, ) -> Result<(), String> { let configuration_file = get_configuration_file_path(app_handle); - println!( + log::info!( "update_app_configuration, configuration_file: {:?}", configuration_file ); @@ -136,7 +136,7 @@ pub fn read_theme(app_handle: tauri::AppHandle, theme_name: String) -> Result(app_handle: tauri::AppHandle) -> PathBuf { let app_path = app_handle.path().app_data_dir().unwrap_or_else(|err| { - eprintln!( + log::error!( "Failed to get app data directory: {}. Using home directory instead.", err ); @@ -215,7 +215,7 @@ pub fn open_file_explorer(path: String) { #[tauri::command] pub fn install_extensions(app: AppHandle) { if let Err(err) = setup::install_extensions(app, true) { - eprintln!("Failed to install extensions: {}", err); + log::error!("Failed to install extensions: {}", err); } } @@ -223,7 +223,7 @@ pub fn install_extensions(app: AppHandle) { pub fn get_active_extensions(app: AppHandle) -> Vec { let mut path = get_jan_extensions_path(app); path.push("extensions.json"); - println!("get jan extensions, path: {:?}", path); + log::info!("get jan extensions, path: {:?}", path); let contents = fs::read_to_string(path); let contents: Vec = match contents { diff --git a/src-tauri/src/core/fs.rs b/src-tauri/src/core/fs.rs index f0ffb9a71..9e77a812c 100644 --- a/src-tauri/src/core/fs.rs +++ b/src-tauri/src/core/fs.rs @@ -73,7 +73,7 @@ pub fn readdir_sync( } let path = resolve_path(app_handle, &args[0]); - println!("Reading directory: {:?}", path); + log::error!("Reading directory: {:?}", path); let entries = fs::read_dir(&path).map_err(|e| e.to_string())?; let paths: Vec = entries .filter_map(|entry| entry.ok()) diff --git a/src-tauri/src/core/mcp.rs b/src-tauri/src/core/mcp.rs index 98bf0ad3b..b73b91f3a 100644 --- a/src-tauri/src/core/mcp.rs +++ b/src-tauri/src/core/mcp.rs @@ -17,7 +17,7 @@ pub async fn run_mcp_commands( app_path: String, servers_state: Arc>>>, ) -> Result<(), String> { - println!( + log::info!( "Load MCP configs from {}", app_path.clone() + "/mcp_config.json" ); @@ -29,7 +29,7 @@ pub async fn run_mcp_commands( .map_err(|e| format!("Failed to parse config: {}", e))?; if let Some(server_map) = mcp_servers.get("mcpServers").and_then(Value::as_object) { - println!("MCP Servers: {server_map:#?}"); + log::info!("MCP Servers: {server_map:#?}"); for (name, config) in server_map { if let Some((command, args)) = extract_command_args(config) { @@ -53,7 +53,7 @@ pub async fn run_mcp_commands( for (_, service) in servers_map.iter() { // Initialize let _server_info = service.peer_info(); - println!("Connected to server: {_server_info:#?}"); + log::info!("Connected to server: {_server_info:#?}"); } Ok(()) } diff --git a/src-tauri/src/core/server.rs b/src-tauri/src/core/server.rs index 359da13da..042ecf135 100644 --- a/src-tauri/src/core/server.rs +++ b/src-tauri/src/core/server.rs @@ -6,7 +6,6 @@ use std::net::SocketAddr; use std::sync::LazyLock; use tokio::sync::Mutex; use tokio::task::JoinHandle; -use tracing::{debug, error, info}; /// Server handle type for managing the proxy server lifecycle type ServerHandle = JoinHandle>>; @@ -24,7 +23,7 @@ struct ProxyConfig { /// Removes a prefix from a path, ensuring proper formatting fn remove_prefix(path: &str, prefix: &str) -> String { - debug!("Processing path: {}, removing prefix: {}", path, prefix); + log::debug!("Processing path: {}, removing prefix: {}", path, prefix); if !prefix.is_empty() && path.starts_with(prefix) { let result = path[prefix.len()..].to_string(); @@ -42,7 +41,6 @@ fn remove_prefix(path: &str, prefix: &str) -> String { fn get_destination_path(original_path: &str, prefix: &str) -> String { let removed_prefix_path = remove_prefix(original_path, prefix); - println!("Removed prefix path: {}", removed_prefix_path); // Special paths don't need the /v1 prefix if !original_path.contains(prefix) || removed_prefix_path.contains("/healthz") @@ -81,7 +79,7 @@ async fn proxy_request( // Build the outbound request let upstream_url = build_upstream_url(&config.upstream, &path); - debug!("Proxying request to: {}", upstream_url); + log::debug!("Proxying request to: {}", upstream_url); let mut outbound_req = client.request(req.method().clone(), &upstream_url); @@ -100,7 +98,7 @@ async fn proxy_request( match outbound_req.body(req.into_body()).send().await { Ok(response) => { let status = response.status(); - debug!("Received response with status: {}", status); + log::debug!("Received response with status: {}", status); let mut builder = Response::builder().status(status); @@ -113,7 +111,7 @@ async fn proxy_request( match response.bytes().await { Ok(bytes) => Ok(builder.body(Body::from(bytes)).unwrap()), Err(e) => { - error!("Failed to read response body: {}", e); + log::error!("Failed to read response body: {}", e); Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::from("Error reading upstream response")) @@ -122,7 +120,7 @@ async fn proxy_request( } } Err(e) => { - error!("Proxy request failed: {}", e); + log::error!("Proxy request failed: {}", e); Ok(Response::builder() .status(StatusCode::BAD_GATEWAY) .body(Body::from(format!("Upstream error: {}", e))) @@ -175,12 +173,12 @@ pub async fn start_server( // Create and start the server let server = Server::bind(&addr).serve(make_svc); - info!("Proxy server started on http://{}", addr); + log::info!("Proxy server started on http://{}", addr); // Spawn server task let server_handle = tokio::spawn(async move { if let Err(e) = server.await { - error!("Server error: {}", e); + log::error!("Server error: {}", e); return Err(Box::new(e) as Box); } Ok(()) @@ -196,9 +194,9 @@ pub async fn stop_server() -> Result<(), Box Result<(), Stri // Attempt to remove extensions folder if extensions_path.exists() { fs::remove_dir_all(&extensions_path).unwrap_or_else(|_| { - println!("Failed to remove existing extensions folder, it may not exist."); + log::info!("Failed to remove existing extensions folder, it may not exist."); }); } @@ -66,7 +67,7 @@ pub fn install_extensions(app: tauri::AppHandle, force: bool) -> Result<(), Stri let path = entry.path(); if path.extension().map_or(false, |ext| ext == "tgz") { - println!("Installing extension from {:?}", path); + log::info!("Installing extension from {:?}", path); let tar_gz = File::open(&path).map_err(|e| e.to_string())?; let gz_decoder = GzDecoder::new(tar_gz); let mut archive = Archive::new(gz_decoder); @@ -132,7 +133,7 @@ pub fn install_extensions(app: tauri::AppHandle, force: bool) -> Result<(), Stri extensions_list.push(new_extension); - println!("Installed extension to {:?}", extension_dir); + log::info!("Installed extension to {:?}", extension_dir); } } fs::write( @@ -186,7 +187,7 @@ pub fn setup_mcp(app: &App) { let servers = state.mcp_servers.clone(); tauri::async_runtime::spawn(async move { if let Err(e) = run_mcp_commands(app_path_str, servers).await { - eprintln!("Failed to run mcp commands: {}", e); + log::error!("Failed to run mcp commands: {}", e); } }); } @@ -252,7 +253,7 @@ pub fn setup_sidecar(app: &App) -> Result<(), String> { while let Some(event) = rx.recv().await { if let CommandEvent::Stdout(line_bytes) = event { let line = String::from_utf8_lossy(&line_bytes); - println!("Outputs: {:?}", line) + log::info!("Outputs: {:?}", line) } } }); @@ -268,7 +269,7 @@ pub fn setup_sidecar(app: &App) -> Result<(), String> { fn copy_dir_all(src: PathBuf, dst: PathBuf) -> Result<(), String> { fs::create_dir_all(&dst).map_err(|e| e.to_string())?; - println!("Copying from {:?} to {:?}", src, dst); + log::info!("Copying from {:?} to {:?}", src, dst); for entry in fs::read_dir(src).map_err(|e| e.to_string())? { let entry = entry.map_err(|e| e.to_string())?; let ty = entry.file_type().map_err(|e| e.to_string())?; @@ -293,10 +294,10 @@ pub fn setup_engine_binaries(app: &App) -> Result<(), String> { .join("resources"); if let Err(e) = copy_dir_all(binaries_dir, app_data_dir.clone()) { - eprintln!("Failed to copy binaries: {}", e); + log::error!("Failed to copy binaries: {}", e); } if let Err(e) = copy_dir_all(themes_dir, app_data_dir.clone()) { - eprintln!("Failed to copy themes: {}", e); + log::error!("Failed to copy themes: {}", e); } Ok(()) } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 85578d680..4e35d3bfe 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,5 +1,6 @@ mod core; use core::{ + cmd::get_jan_data_folder_path, setup::{self, setup_engine_binaries, setup_mcp, setup_sidecar}, state::{generate_app_token, AppState}, }; @@ -11,8 +12,8 @@ use tokio::sync::Mutex; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() - .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_http::init()) + .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_shell::init()) .invoke_handler(tauri::generate_handler![ // FS commands - Deperecate soon @@ -47,25 +48,26 @@ pub fn run() { mcp_servers: Arc::new(Mutex::new(HashMap::new())), }) .setup(|app| { - if cfg!(debug_assertions) { - app.handle().plugin( - tauri_plugin_log::Builder::default() - .level(log::LevelFilter::Info) - .build(), - )?; - } - + app.handle().plugin( + tauri_plugin_log::Builder::default() + .targets([ + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Folder { + path: get_jan_data_folder_path(app.handle().clone()).join("logs"), + file_name: Some("app".to_string()), + }), + if cfg!(debug_assertions) { + tauri_plugin_log::Target::new(tauri_plugin_log::TargetKind::Stdout) + }, + ]) + .build(), + )?; // Install extensions if let Err(e) = setup::install_extensions(app.handle().clone(), false) { - eprintln!("Failed to install extensions: {}", e); + log::error!("Failed to install extensions: {}", e); } - setup_mcp(app); - setup_sidecar(app).expect("Failed to setup sidecar"); - setup_engine_binaries(app).expect("Failed to setup engine binaries"); - Ok(()) }) .on_window_event(|window, event| match event { diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3b44dc079..51e65133a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,13 +1,13 @@ { - "$schema": "../node_modules/@tauri-apps/cli/config.schema.json", + "$schema": "https://schema.tauri.app/config/2", "productName": "Jan", "version": "0.1.0", "identifier": "jan.ai", "build": { "frontendDist": "../web/out", "devUrl": "http://localhost:3000", - "beforeDevCommand": "yarn dev:web:tauri", - "beforeBuildCommand": "yarn build:web" + "beforeDevCommand": "IS_TAURI=true yarn dev:web", + "beforeBuildCommand": "IS_TAURI=true yarn build:web" }, "app": { "macOSPrivateApi": true, @@ -27,9 +27,10 @@ "csp": { "default-src": "'self' customprotocol: asset: http://localhost:* http://127.0.0.1:* ws://localhost:* ws://127.0.0.1:*", "connect-src": "ipc: http://ipc.localhost", - "font-src": ["https://fonts.gstatic.com"], + "font-src": ["https://fonts.gstatic.com blob: data:"], "img-src": "'self' asset: http://asset.localhost blob: data:", - "style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com" + "style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com", + "script-src": "'self' asset: $APPDATA/**.*" }, "assetProtocol": { "enable": true, diff --git a/web/hooks/useLoadTheme.ts b/web/hooks/useLoadTheme.ts index f2fbbf83e..7631ee235 100644 --- a/web/hooks/useLoadTheme.ts +++ b/web/hooks/useLoadTheme.ts @@ -22,7 +22,8 @@ export const useLoadTheme = () => { const setNativeTheme = useCallback( (nativeTheme: NativeThemeProps) => { - if (!('setNativeThemeDark' in window.core.api)) return + if (!window.electronAPI) return + if (nativeTheme === 'dark') { window?.core?.api?.setNativeThemeDark() setTheme('dark') @@ -58,21 +59,20 @@ export const useLoadTheme = () => { setThemeOptions(themesOptions) if (!selectedIdTheme.length) return setSelectedIdTheme('joi-light') - const theme: Theme = JSON.parse( await window.core.api.readTheme({ - theme: selectedIdTheme, + themeName: selectedIdTheme, }) ) setThemeData(theme) setNativeTheme(theme.nativeTheme) applyTheme(theme) - }, []) + }, [selectedIdTheme]) const configureTheme = useCallback(async () => { if (!themeData || !themeOptions) { - await getThemes() + getThemes() } else { applyTheme(themeData) }