Skip to main content

algocline_app/service/
mod.rs

1mod config;
2mod eval;
3mod eval_store;
4mod logging;
5pub(crate) mod path;
6mod pkg;
7pub mod resolve;
8mod run;
9mod scenario;
10mod transcript;
11
12#[cfg(test)]
13mod tests;
14
15use std::path::Path;
16use std::sync::Arc;
17
18use algocline_engine::{Executor, SessionRegistry};
19
20pub use config::{AppConfig, LogDirSource};
21pub use resolve::{QueryResponse, SearchPath};
22
23// ─── Application Service ────────────────────────────────────────
24
25/// Tracks which sessions are eval sessions and their strategy name.
26type EvalSessions = std::sync::Mutex<std::collections::HashMap<String, String>>;
27
28/// Tracks session_id → strategy name for all strategy-based sessions (advice, eval).
29type SessionStrategies = std::sync::Mutex<std::collections::HashMap<String, String>>;
30
31#[derive(Clone)]
32pub struct AppService {
33    executor: Arc<Executor>,
34    registry: Arc<SessionRegistry>,
35    log_config: AppConfig,
36    /// Package search paths in priority order (first = highest).
37    search_paths: Vec<resolve::SearchPath>,
38    /// session_id → strategy name for eval sessions (cleared on completion).
39    eval_sessions: Arc<EvalSessions>,
40    /// session_id → strategy name for log/stats tracking (cleared on session completion).
41    session_strategies: Arc<SessionStrategies>,
42}
43
44impl AppService {
45    pub fn new(
46        executor: Arc<Executor>,
47        log_config: AppConfig,
48        search_paths: Vec<resolve::SearchPath>,
49    ) -> Self {
50        Self {
51            executor,
52            registry: Arc::new(SessionRegistry::new()),
53            log_config,
54            search_paths,
55            eval_sessions: Arc::new(std::sync::Mutex::new(std::collections::HashMap::new())),
56            session_strategies: Arc::new(std::sync::Mutex::new(std::collections::HashMap::new())),
57        }
58    }
59
60    /// Returns the log directory, or an error if file logging is unavailable.
61    fn require_log_dir(&self) -> Result<&Path, String> {
62        self.log_config
63            .log_dir
64            .as_deref()
65            .ok_or_else(|| "File logging is not available (no writable log directory)".to_string())
66    }
67}