orchai/src-tauri/src/lib.rs

123 lines
4.4 KiB
Rust
Raw Normal View History

mod commands;
mod db;
mod error;
mod models;
mod services;
use std::sync::{Arc, Mutex};
use tauri::Manager;
pub struct AppState {
pub db: Arc<Mutex<rusqlite::Connection>>,
pub encryption_key: [u8; 32],
pub http_client: reqwest::Client,
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_notification::init())
.setup(|app| {
let db_dir = app.path().app_data_dir()?;
std::fs::create_dir_all(&db_dir)?;
let db_path = db_dir.join("orchai.db");
let conn = db::init(&db_path).expect("Failed to initialize database");
let key_path = db_dir.join("orchai.key");
let encryption_key = load_or_generate_key(&key_path)?;
let http_client = reqwest::Client::new();
let db_arc = Arc::new(Mutex::new(conn));
app.manage(AppState {
db: db_arc.clone(),
encryption_key,
http_client: http_client.clone(),
});
// Start background poller
services::poller::start(
db_arc.clone(),
encryption_key,
http_client,
app.handle().clone(),
);
// Start agent orchestrator
services::orchestrator::start(db_arc.clone(), app.handle().clone());
// Start agent task runner
services::task_runner::start(db_arc, app.handle().clone());
Ok(())
})
.invoke_handler(tauri::generate_handler![
commands::agent::create_agent,
commands::agent::list_agents,
commands::agent::get_agent,
commands::agent::update_agent,
commands::agent::delete_agent,
commands::agent::improve_agent_prompt,
commands::project::create_project,
commands::project::list_projects,
commands::project::get_project,
commands::project::update_project,
commands::project::delete_project,
commands::credential::set_tuleap_credentials,
commands::credential::get_tuleap_credentials,
commands::credential::delete_tuleap_credentials,
commands::credential::test_tuleap_connection,
commands::tracker::add_tracker,
commands::tracker::list_trackers,
commands::tracker::update_tracker,
commands::tracker::remove_tracker,
commands::tracker::get_tracker_fields,
commands::tracker::list_processed_tickets,
commands::poller::manual_poll,
commands::poller::get_queue_status,
commands::notification::list_notifications,
commands::notification::mark_notification_read,
commands::notification::mark_all_notifications_read,
commands::module::list_project_modules,
commands::module::set_project_module_enabled,
commands::orchestrator::get_ticket_result,
commands::orchestrator::retry_ticket,
commands::orchestrator::cancel_ticket,
commands::live_agent::create_live_session,
commands::live_agent::list_live_sessions,
commands::live_agent::list_live_messages,
commands::live_agent::send_live_message,
commands::task::create_agent_task,
commands::task::list_agent_tasks,
commands::task::retry_agent_task,
commands::task::cancel_agent_task,
commands::worktree::list_worktrees,
commands::worktree::get_worktree_diff,
commands::worktree::apply_fix_to_branch,
commands::worktree::delete_worktree_cmd,
commands::worktree::list_local_branches,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
fn load_or_generate_key(path: &std::path::Path) -> Result<[u8; 32], Box<dyn std::error::Error>> {
use rand::RngCore;
if path.exists() {
let bytes = std::fs::read(path)?;
if bytes.len() != 32 {
return Err("Invalid key file size".into());
}
let mut key = [0u8; 32];
key.copy_from_slice(&bytes);
Ok(key)
} else {
let mut key = [0u8; 32];
rand::rngs::OsRng.fill_bytes(&mut key);
std::fs::write(path, key)?;
Ok(key)
}
}