use crate::utils::{DeepResearch, ResearchOptions, ResearchResult};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;
use tokio::sync::RwLock;
use tokio::task::JoinHandle;
#[derive(Clone)]
pub struct ResearchSession {
research: Arc<DeepResearch>,
results: Arc<RwLock<Vec<ResearchResult>>>,
total_results: Arc<AtomicUsize>,
task_handle: Arc<RwLock<Option<JoinHandle<Result<()>>>>>,
query: String,
options: Option<ResearchOptions>,
completed: Arc<RwLock<bool>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResearchOutput {
pub session: u32,
pub query: String,
pub results: Vec<ResearchResult>,
pub completed: bool,
pub summary: String,
}
impl ResearchSession {
pub fn new(research: DeepResearch, query: String, options: Option<ResearchOptions>) -> Self {
let results = Arc::new(RwLock::new(Vec::new()));
let total_results = Arc::new(AtomicUsize::new(0));
let completed = Arc::new(RwLock::new(false));
Self {
research: Arc::new(research),
results,
total_results,
task_handle: Arc::new(RwLock::new(None)),
query,
options,
completed,
}
}
pub async fn start(&self) -> Result<()> {
let research = self.research.clone();
let query = self.query.clone();
let options = self.options.clone();
let results = self.results.clone();
let total_results = self.total_results.clone();
let completed = self.completed.clone();
let handle = tokio::spawn(async move {
match research.research(&query, options, results.clone(), total_results.clone()).await {
Ok(()) => {
let mut comp = completed.write().await;
*comp = true;
Ok(())
}
Err(e) => {
let mut comp = completed.write().await;
*comp = true;
Err(anyhow::anyhow!("Research error: {}", e))
}
}
});
let mut task = self.task_handle.write().await;
*task = Some(handle);
Ok(())
}
pub async fn read(&self, session_id: u32) -> ResearchOutput {
let results = self.results.read().await.clone();
let completed = *self.completed.read().await;
let summary = if completed {
format!("Research completed. {} results found.", results.len())
} else {
format!("Research in progress. {} results so far.", results.len())
};
ResearchOutput {
session: session_id,
query: self.query.clone(),
results,
completed,
summary,
}
}
pub async fn kill(&self) -> Result<()> {
let mut task = self.task_handle.write().await;
if let Some(handle) = task.take() {
handle.abort();
}
let mut comp = self.completed.write().await;
*comp = true;
Ok(())
}
pub async fn is_complete(&self) -> bool {
*self.completed.read().await
}
pub async fn results_count(&self) -> usize {
(*self.results.read().await).len()
}
}