refactor: app logging - script-src access in release

This commit is contained in:
Louis 2025-04-07 02:03:51 +07:00
parent 52290f9ee5
commit baee71dd8e
No known key found for this signature in database
GPG Key ID: 44FA9F4D33C37DE2
11 changed files with 62 additions and 67 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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"
]
}
}

View File

@ -35,7 +35,7 @@ pub fn get_app_configurations<R: Runtime>(app_handle: tauri::AppHandle<R>) -> 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<R: Runtime>(app_handle: tauri::AppHandle<R>) -> 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<R: Runtime>(app_handle: tauri::AppHandle<R>) -> Ap
Ok(content) => match serde_json::from_str::<AppConfiguration>(&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<R: Runtime>(app_handle: tauri::AppHandle<R>) -> 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<St
#[tauri::command]
pub fn get_configuration_file_path<R: Runtime>(app_handle: tauri::AppHandle<R>) -> 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<serde_json::Value> {
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<serde_json::Value> = match contents {

View File

@ -73,7 +73,7 @@ pub fn readdir_sync<R: Runtime>(
}
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<String> = entries
.filter_map(|entry| entry.ok())

View File

@ -17,7 +17,7 @@ pub async fn run_mcp_commands(
app_path: String,
servers_state: Arc<Mutex<HashMap<String, RunningService<RoleClient, ()>>>>,
) -> 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(())
}

View File

@ -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<Result<(), Box<dyn std::error::Error + Send + Sync>>>;
@ -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<dyn std::error::Error + Send + Sync>);
}
Ok(())
@ -196,9 +194,9 @@ pub async fn stop_server() -> Result<(), Box<dyn std::error::Error + Send + Sync
if let Some(handle) = handle_guard.take() {
handle.abort();
info!("Proxy server stopped");
log::info!("Proxy server stopped");
} else {
debug!("No server was running");
log::debug!("No server was running");
}
Ok(())

View File

@ -11,6 +11,7 @@ use tauri_plugin_shell::process::CommandEvent;
use tauri_plugin_shell::ShellExt;
use tauri_plugin_store::StoreExt;
// MCP
use super::{
cmd::{get_jan_data_folder_path, get_jan_extensions_path},
mcp::run_mcp_commands,
@ -39,7 +40,7 @@ pub fn install_extensions(app: tauri::AppHandle, force: bool) -> 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(())
}

View File

@ -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 {

View File

@ -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,

View File

@ -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)
}