diff options
Diffstat (limited to 'crates/turtle/src/atuin_daemon')
| -rw-r--r-- | crates/turtle/src/atuin_daemon/client.rs | 46 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/components/history.rs | 8 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/components/mod.rs | 16 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/components/search.rs | 12 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/components/semantic.rs | 8 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/components/sync.rs | 4 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/control/mod.rs | 2 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/control/service.rs | 6 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/daemon.rs | 52 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/events.rs | 2 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/mod.rs | 28 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/search/index.rs | 56 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/search/mod.rs | 2 | ||||
| -rw-r--r-- | crates/turtle/src/atuin_daemon/server.rs | 2 |
14 files changed, 122 insertions, 122 deletions
diff --git a/crates/turtle/src/atuin_daemon/client.rs b/crates/turtle/src/atuin_daemon/client.rs index 45ef19e9..a0a27741 100644 --- a/crates/turtle/src/atuin_daemon/client.rs +++ b/crates/turtle/src/atuin_daemon/client.rs @@ -33,12 +33,12 @@ use crate::atuin_daemon::semantic::{ semantic_client::SemanticClient as SemanticServiceClient, }; -pub struct HistoryClient { +pub(crate) struct HistoryClient { client: HistoryServiceClient<Channel>, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum DaemonClientErrorKind { +pub(crate) enum DaemonClientErrorKind { Connect, Unavailable, Unimplemented, @@ -46,7 +46,7 @@ pub enum DaemonClientErrorKind { } #[must_use] -pub fn classify_error(error: &eyre::Report) -> DaemonClientErrorKind { +pub(crate) fn classify_error(error: &eyre::Report) -> DaemonClientErrorKind { for cause in error.chain() { if cause.downcast_ref::<tonic::transport::Error>().is_some() { return DaemonClientErrorKind::Connect; @@ -67,7 +67,7 @@ pub fn classify_error(error: &eyre::Report) -> DaemonClientErrorKind { // Wrap the grpc client impl HistoryClient { #[cfg(unix)] - pub async fn new(path: String) -> Result<Self> { + pub(crate) async fn new(path: String) -> Result<Self> { use eyre::Context; let log_path = path.clone(); @@ -92,7 +92,7 @@ impl HistoryClient { Ok(HistoryClient { client }) } - pub async fn start_history(&mut self, h: History) -> Result<StartHistoryReply> { + pub(crate) async fn start_history(&mut self, h: History) -> Result<StartHistoryReply> { let req = StartHistoryRequest { command: h.command, cwd: h.cwd, @@ -106,7 +106,7 @@ impl HistoryClient { Ok(self.client.start_history(req).await?.into_inner()) } - pub async fn end_history( + pub(crate) async fn end_history( &mut self, id: String, duration: u64, @@ -117,11 +117,11 @@ impl HistoryClient { Ok(self.client.end_history(req).await?.into_inner()) } - pub async fn status(&mut self) -> Result<StatusReply> { + pub(crate) async fn status(&mut self) -> Result<StatusReply> { Ok(self.client.status(StatusRequest {}).await?.into_inner()) } - pub async fn tail_history(&mut self) -> Result<tonic::Streaming<TailHistoryReply>> { + pub(crate) async fn tail_history(&mut self) -> Result<tonic::Streaming<TailHistoryReply>> { Ok(self .client .tail_history(TailHistoryRequest {}) @@ -129,19 +129,19 @@ impl HistoryClient { .into_inner()) } - pub async fn shutdown(&mut self) -> Result<bool> { + pub(crate) async fn shutdown(&mut self) -> Result<bool> { let resp = self.client.shutdown(ShutdownRequest {}).await?.into_inner(); Ok(resp.accepted) } } -pub struct SearchClient { +pub(crate) struct SearchClient { client: SearchServiceClient<Channel>, } impl SearchClient { #[cfg(unix)] - pub async fn new(path: String) -> Result<Self> { + pub(crate) async fn new(path: String) -> Result<Self> { let log_path = path.clone(); let channel = Endpoint::try_from("http://atuin_local_daemon:0")? .connect_with_connector(service_fn(move |_: Uri| { @@ -165,7 +165,7 @@ impl SearchClient { } #[instrument(skip_all, level = Level::TRACE, name = "daemon_client_search", fields(query = %query, query_id = query_id))] - pub async fn search( + pub(crate) async fn search( &mut self, query: String, query_id: u64, @@ -214,13 +214,13 @@ impl From<Context> for RpcSearchContext { } } -pub struct SemanticClient { +pub(crate) struct SemanticClient { client: SemanticServiceClient<Channel>, } impl SemanticClient { #[cfg(unix)] - pub async fn new(path: String) -> Result<Self> { + pub(crate) async fn new(path: String) -> Result<Self> { let log_path = path.clone(); let channel = Endpoint::try_from("http://atuin_local_daemon:0")? .connect_with_connector(service_fn(move |_: Uri| { @@ -244,11 +244,11 @@ impl SemanticClient { } #[cfg(unix)] - pub async fn from_settings(settings: &Settings) -> Result<Self> { + pub(crate) async fn from_settings(settings: &Settings) -> Result<Self> { Self::new(settings.daemon.socket_path.clone()).await } - pub async fn record_commands( + pub(crate) async fn record_commands( &mut self, captures: Vec<CommandCapture>, ) -> Result<RecordCommandsReply> { @@ -256,7 +256,7 @@ impl SemanticClient { Ok(self.client.record_commands(stream).await?.into_inner()) } - pub async fn command_output( + pub(crate) async fn command_output( &mut self, history_id: String, ranges: Vec<(i64, i64)>, @@ -280,14 +280,14 @@ impl SemanticClient { /// Client for the Control gRPC service. /// /// Used to inject events into a running daemon from external processes. -pub struct ControlClient { +pub(crate) struct ControlClient { client: ControlServiceClient<Channel>, } impl ControlClient { /// Connect to the daemon's control service. #[cfg(unix)] - pub async fn new(path: String) -> Result<Self> { + pub(crate) async fn new(path: String) -> Result<Self> { let log_path = path.clone(); let channel = Endpoint::try_from("http://atuin_local_daemon:0")? .connect_with_connector(service_fn(move |_: Uri| { @@ -312,12 +312,12 @@ impl ControlClient { /// Connect using settings. #[cfg(unix)] - pub async fn from_settings(settings: &Settings) -> Result<Self> { + pub(crate) async fn from_settings(settings: &Settings) -> Result<Self> { Self::new(settings.daemon.socket_path.clone()).await } /// Send an event to the daemon. - pub async fn send_event(&mut self, event: DaemonEvent) -> Result<()> { + pub(crate) async fn send_event(&mut self, event: DaemonEvent) -> Result<()> { let proto_event = daemon_event_to_proto(event); let request = SendEventRequest { event: Some(proto_event), @@ -377,7 +377,7 @@ fn daemon_event_to_proto( /// // Request immediate sync /// emit_event(DaemonEvent::ForceSync).await?; /// ``` -pub async fn emit_event(event: DaemonEvent) -> Result<()> { +pub(crate) async fn emit_event(event: DaemonEvent) -> Result<()> { emit_event_with_settings(event, None).await } @@ -385,7 +385,7 @@ pub async fn emit_event(event: DaemonEvent) -> Result<()> { /// /// If settings are not provided, they will be loaded from the default location. /// If the daemon isn't running, this will silently succeed. -pub async fn emit_event_with_settings( +pub(crate) async fn emit_event_with_settings( event: DaemonEvent, settings: Option<&Settings>, ) -> Result<()> { diff --git a/crates/turtle/src/atuin_daemon/components/history.rs b/crates/turtle/src/atuin_daemon/components/history.rs index 95d34b69..ec41977f 100644 --- a/crates/turtle/src/atuin_daemon/components/history.rs +++ b/crates/turtle/src/atuin_daemon/components/history.rs @@ -36,7 +36,7 @@ const DAEMON_PROTOCOL_VERSION: u32 = 1; /// - Saves completed commands to the database and record store /// - Emits history events for other components (e.g., search indexing) /// - Provides the History gRPC service -pub struct HistoryComponent { +pub(crate) struct HistoryComponent { inner: Arc<HistoryComponentInner>, } @@ -53,7 +53,7 @@ struct HistoryComponentInner { impl HistoryComponent { /// Create a new history component. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { inner: Arc::new(HistoryComponentInner { running: DashMap::new(), @@ -66,7 +66,7 @@ impl HistoryComponent { /// Get the gRPC service for this component. /// /// This returns a tonic service that can be added to a gRPC server. - pub fn grpc_service(&self) -> HistoryServer<HistoryGrpcService> { + pub(crate) fn grpc_service(&self) -> HistoryServer<HistoryGrpcService> { HistoryServer::new(HistoryGrpcService { inner: self.inner.clone(), }) @@ -112,7 +112,7 @@ impl Component for HistoryComponent { /// The gRPC service implementation. /// /// This is a thin wrapper that delegates to the component's shared state. -pub struct HistoryGrpcService { +pub(crate) struct HistoryGrpcService { inner: Arc<HistoryComponentInner>, } diff --git a/crates/turtle/src/atuin_daemon/components/mod.rs b/crates/turtle/src/atuin_daemon/components/mod.rs index 447e31df..5a93fbc1 100644 --- a/crates/turtle/src/atuin_daemon/components/mod.rs +++ b/crates/turtle/src/atuin_daemon/components/mod.rs @@ -14,12 +14,12 @@ //! - [`semantic::SemanticComponent`]: In-memory semantic command captures //! - [`sync::SyncComponent`]: Cloud sync -pub mod history; -pub mod search; -pub mod semantic; -pub mod sync; +pub(crate) mod history; +pub(crate) mod search; +pub(crate) mod semantic; +pub(crate) mod sync; -pub use history::HistoryComponent; -pub use search::SearchComponent; -pub use semantic::SemanticComponent; -pub use sync::SyncComponent; +pub(crate) use history::HistoryComponent; +pub(crate) use search::SearchComponent; +pub(crate) use semantic::SemanticComponent; +pub(crate) use sync::SyncComponent; diff --git a/crates/turtle/src/atuin_daemon/components/search.rs b/crates/turtle/src/atuin_daemon/components/search.rs index 85191cff..17decdad 100644 --- a/crates/turtle/src/atuin_daemon/components/search.rs +++ b/crates/turtle/src/atuin_daemon/components/search.rs @@ -34,7 +34,7 @@ const FRECENCY_REFRESH_INTERVAL_SECS: u64 = 60; /// - Loads history from the database on startup /// - Updates the index when history events occur /// - Provides the Search gRPC service -pub struct SearchComponent { +pub(crate) struct SearchComponent { index: Arc<RwLock<SearchIndex>>, handle: tokio::sync::RwLock<Option<DaemonHandle>>, loader_handle: Option<tokio::task::JoinHandle<()>>, @@ -43,7 +43,7 @@ pub struct SearchComponent { impl SearchComponent { /// Create a new search component. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { index: Arc::new(RwLock::new(SearchIndex::new())), handle: tokio::sync::RwLock::new(None), @@ -53,7 +53,7 @@ impl SearchComponent { } /// Get the gRPC service for this component. - pub fn grpc_service(&self) -> SearchServer<SearchGrpcService> { + pub(crate) fn grpc_service(&self) -> SearchServer<SearchGrpcService> { SearchServer::new(SearchGrpcService { index: self.index.clone(), }) @@ -273,7 +273,7 @@ impl Component for SearchComponent { } /// The gRPC service implementation. -pub struct SearchGrpcService { +pub(crate) struct SearchGrpcService { index: Arc<RwLock<SearchIndex>>, } @@ -395,7 +395,7 @@ fn convert_filter_mode( } #[cfg(windows)] -pub fn with_trailing_slash(s: &str) -> String { +pub(crate) fn with_trailing_slash(s: &str) -> String { if s.ends_with('\\') { s.to_string() } else { @@ -404,7 +404,7 @@ pub fn with_trailing_slash(s: &str) -> String { } #[cfg(not(windows))] -pub fn with_trailing_slash(s: &str) -> String { +pub(crate) fn with_trailing_slash(s: &str) -> String { if s.ends_with('/') { s.to_string() } else { diff --git a/crates/turtle/src/atuin_daemon/components/semantic.rs b/crates/turtle/src/atuin_daemon/components/semantic.rs index a42fd5cb..052c2d73 100644 --- a/crates/turtle/src/atuin_daemon/components/semantic.rs +++ b/crates/turtle/src/atuin_daemon/components/semantic.rs @@ -29,7 +29,7 @@ const MAX_BYTES_PER_SESSION: usize = 32 * 1024 * 1024; const MAX_PENDING_HISTORIES: usize = 128; /// Stores completed command captures and associates them with history events. -pub struct SemanticComponent { +pub(crate) struct SemanticComponent { inner: Arc<SemanticComponentInner>, } @@ -83,7 +83,7 @@ struct SemanticCommandRecord { } impl SemanticComponent { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { inner: Arc::new(SemanticComponentInner { state: Mutex::new(SemanticState::default()), @@ -91,7 +91,7 @@ impl SemanticComponent { } } - pub fn grpc_service(&self) -> SemanticServer<SemanticGrpcService> { + pub(crate) fn grpc_service(&self) -> SemanticServer<SemanticGrpcService> { SemanticServer::new(SemanticGrpcService { inner: self.inner.clone(), }) @@ -452,7 +452,7 @@ impl Display for SessionId { } } -pub struct SemanticGrpcService { +pub(crate) struct SemanticGrpcService { inner: Arc<SemanticComponentInner>, } diff --git a/crates/turtle/src/atuin_daemon/components/sync.rs b/crates/turtle/src/atuin_daemon/components/sync.rs index c76fb71b..93d1024a 100644 --- a/crates/turtle/src/atuin_daemon/components/sync.rs +++ b/crates/turtle/src/atuin_daemon/components/sync.rs @@ -41,14 +41,14 @@ enum SyncState { /// - Implements exponential backoff on sync failures /// - Responds to ForceSync events for immediate sync /// - Emits SyncCompleted/SyncFailed events -pub struct SyncComponent { +pub(crate) struct SyncComponent { task_handle: Option<tokio::task::JoinHandle<()>>, command_tx: Option<mpsc::Sender<SyncCommand>>, } impl SyncComponent { /// Create a new sync component. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { task_handle: None, command_tx: None, diff --git a/crates/turtle/src/atuin_daemon/control/mod.rs b/crates/turtle/src/atuin_daemon/control/mod.rs index afb29c57..23068519 100644 --- a/crates/turtle/src/atuin_daemon/control/mod.rs +++ b/crates/turtle/src/atuin_daemon/control/mod.rs @@ -9,4 +9,4 @@ mod service; tonic::include_proto!("control"); // Re-export the service -pub use service::ControlService; +pub(crate) use service::ControlService; diff --git a/crates/turtle/src/atuin_daemon/control/service.rs b/crates/turtle/src/atuin_daemon/control/service.rs index cb2ff74e..8061a3c2 100644 --- a/crates/turtle/src/atuin_daemon/control/service.rs +++ b/crates/turtle/src/atuin_daemon/control/service.rs @@ -18,18 +18,18 @@ use crate::atuin_daemon::{daemon::DaemonHandle, events::DaemonEvent}; /// /// This service is used by external processes to inject events into the daemon. /// It's not a component - it's part of the daemon's core infrastructure. -pub struct ControlService { +pub(crate) struct ControlService { handle: DaemonHandle, } impl ControlService { /// Create a new control service with the given daemon handle. - pub fn new(handle: DaemonHandle) -> Self { + pub(crate) fn new(handle: DaemonHandle) -> Self { Self { handle } } /// Get a tonic server for this service. - pub fn into_server(self) -> ControlServer<Self> { + pub(crate) fn into_server(self) -> ControlServer<Self> { ControlServer::new(self) } } diff --git a/crates/turtle/src/atuin_daemon/daemon.rs b/crates/turtle/src/atuin_daemon/daemon.rs index 77c0d8a5..3268548e 100644 --- a/crates/turtle/src/atuin_daemon/daemon.rs +++ b/crates/turtle/src/atuin_daemon/daemon.rs @@ -27,7 +27,7 @@ use crate::atuin_daemon::events::DaemonEvent; /// /// This contains all the resources that components and services need access to. /// The state is wrapped in an `Arc` and accessed via [`DaemonHandle`]. -pub struct DaemonState { +pub(crate) struct DaemonState { // Event bus event_tx: broadcast::Sender<DaemonEvent>, @@ -72,7 +72,7 @@ pub struct DaemonState { /// let history = handle.history_db().load(id).await?; /// ``` #[derive(Clone)] -pub struct DaemonHandle { +pub(crate) struct DaemonHandle { state: Arc<DaemonState>, } @@ -83,7 +83,7 @@ impl DaemonHandle { /// /// This is fire-and-forget - if no receivers are listening (which shouldn't /// happen in normal operation), the event is dropped silently. - pub fn emit(&self, event: DaemonEvent) { + pub(crate) fn emit(&self, event: DaemonEvent) { if let Err(e) = self.state.event_tx.send(event) { tracing::warn!("failed to emit event (no receivers?): {e}"); } @@ -94,12 +94,12 @@ impl DaemonHandle { /// Returns a receiver that will receive all events emitted after this call. /// Useful for components that need to listen for events outside of the /// normal `handle_event` callback flow. - pub fn subscribe(&self) -> broadcast::Receiver<DaemonEvent> { + pub(crate) fn subscribe(&self) -> broadcast::Receiver<DaemonEvent> { self.state.event_tx.subscribe() } /// Request graceful shutdown of the daemon. - pub fn shutdown(&self) { + pub(crate) fn shutdown(&self) { self.emit(DaemonEvent::ShutdownRequested); } @@ -109,7 +109,7 @@ impl DaemonHandle { /// /// This acquires a read lock on the settings. For most use cases, clone /// the settings if you need to hold onto them. - pub async fn settings(&self) -> tokio::sync::RwLockReadGuard<'_, Settings> { + pub(crate) async fn settings(&self) -> tokio::sync::RwLockReadGuard<'_, Settings> { self.state.settings.read().await } @@ -117,7 +117,7 @@ impl DaemonHandle { /// /// Components listening for `SettingsReloaded` can then re-read settings /// via `handle.settings()` to pick up the changes. - pub async fn reload_settings(&self) -> Result<()> { + pub(crate) async fn reload_settings(&self) -> Result<()> { let new_settings = Settings::new()?; self.apply_settings(new_settings).await; Ok(()) @@ -127,26 +127,26 @@ impl DaemonHandle { /// /// Use this when settings have already been loaded (e.g., from a file watcher) /// to avoid parsing the config file twice. - pub async fn apply_settings(&self, settings: Settings) { + pub(crate) async fn apply_settings(&self, settings: Settings) { *self.state.settings.write().await = settings; self.emit(DaemonEvent::SettingsReloaded); tracing::info!("settings applied"); } /// Get the encryption key. - pub fn encryption_key(&self) -> &[u8; 32] { + pub(crate) fn encryption_key(&self) -> &[u8; 32] { &self.state.encryption_key } // ---- Database ---- /// Get a reference to the history database. - pub fn history_db(&self) -> &HistoryDatabase { + pub(crate) fn history_db(&self) -> &HistoryDatabase { &self.state.history_db } /// Get a reference to the record store. - pub fn store(&self) -> &SqliteStore { + pub(crate) fn store(&self) -> &SqliteStore { &self.state.store } } @@ -181,7 +181,7 @@ impl std::fmt::Debug for DaemonHandle { /// # Example /// /// ```ignore -/// pub struct MyComponent { +/// pub(crate) struct MyComponent { /// handle: Option<DaemonHandle>, /// } /// @@ -213,7 +213,7 @@ impl std::fmt::Debug for DaemonHandle { /// } /// ``` #[tonic::async_trait] -pub trait Component: Send + Sync { +pub(crate) trait Component: Send + Sync { /// Human-readable name for logging and debugging. fn name(&self) -> &'static str; @@ -257,21 +257,21 @@ pub trait Component: Send + Sync { /// /// Events emitted during handling are queued and processed in subsequent /// iterations, ensuring the loop eventually drains. -pub struct Daemon { +pub(crate) struct Daemon { components: Vec<Box<dyn Component>>, handle: DaemonHandle, } impl Daemon { /// Create a new daemon builder. - pub fn builder(settings: Settings) -> DaemonBuilder { + pub(crate) fn builder(settings: Settings) -> DaemonBuilder { DaemonBuilder::new(settings) } /// Get a clone of the daemon handle. /// /// The handle can be used to emit events, access settings, etc. - pub fn handle(&self) -> DaemonHandle { + pub(crate) fn handle(&self) -> DaemonHandle { self.handle.clone() } @@ -279,7 +279,7 @@ impl Daemon { /// /// This must be called before `run_event_loop()`. It initializes all /// registered components with the daemon handle. - pub async fn start_components(&mut self) -> Result<()> { + pub(crate) async fn start_components(&mut self) -> Result<()> { for component in &mut self.components { tracing::info!(component = component.name(), "starting component"); component @@ -294,7 +294,7 @@ impl Daemon { /// /// This processes events until a ShutdownRequested event is received. /// Components must be started first via `start_components()`. - pub async fn run_event_loop(&mut self) -> Result<()> { + pub(crate) async fn run_event_loop(&mut self) -> Result<()> { let mut event_rx = self.handle.subscribe(); loop { match event_rx.recv().await { @@ -324,7 +324,7 @@ impl Daemon { /// Stop all components. /// /// This performs graceful shutdown of all components. - pub async fn stop_components(&mut self) { + pub(crate) async fn stop_components(&mut self) { for component in &mut self.components { tracing::info!(component = component.name(), "stopping component"); if let Err(e) = component.stop().await { @@ -342,7 +342,7 @@ impl Daemon { /// /// This is a convenience method that starts components, runs the event loop, /// and handles shutdown. It does not return until the daemon is shut down. - pub async fn run(mut self) -> Result<()> { + pub(crate) async fn run(mut self) -> Result<()> { self.start_components().await?; self.run_event_loop().await?; self.stop_components().await; @@ -383,7 +383,7 @@ impl Daemon { /// /// daemon.run().await?; /// ``` -pub struct DaemonBuilder { +pub(crate) struct DaemonBuilder { settings: Settings, store: Option<SqliteStore>, history_db: Option<HistoryDatabase>, @@ -392,7 +392,7 @@ pub struct DaemonBuilder { impl DaemonBuilder { /// Create a new daemon builder with the given settings. - pub fn new(settings: Settings) -> Self { + pub(crate) fn new(settings: Settings) -> Self { Self { settings, store: None, @@ -402,13 +402,13 @@ impl DaemonBuilder { } /// Set the record store. - pub fn store(mut self, store: SqliteStore) -> Self { + pub(crate) fn store(mut self, store: SqliteStore) -> Self { self.store = Some(store); self } /// Set the history database. - pub fn history_db(mut self, db: HistoryDatabase) -> Self { + pub(crate) fn history_db(mut self, db: HistoryDatabase) -> Self { self.history_db = Some(db); self } @@ -416,7 +416,7 @@ impl DaemonBuilder { /// Register a component. /// /// Components are started in registration order and stopped in reverse order. - pub fn component(mut self, component: impl Component + 'static) -> Self { + pub(crate) fn component(mut self, component: impl Component + 'static) -> Self { self.components.push(Box::new(component)); self } @@ -424,7 +424,7 @@ impl DaemonBuilder { /// Build the daemon. /// /// This loads the encryption key and creates the daemon state. - pub async fn build(self) -> Result<Daemon> { + pub(crate) async fn build(self) -> Result<Daemon> { let store = self.store.ok_or_else(|| eyre::eyre!("store is required"))?; let history_db = self .history_db diff --git a/crates/turtle/src/atuin_daemon/events.rs b/crates/turtle/src/atuin_daemon/events.rs index 9a398925..09369512 100644 --- a/crates/turtle/src/atuin_daemon/events.rs +++ b/crates/turtle/src/atuin_daemon/events.rs @@ -15,7 +15,7 @@ use crate::atuin_common::record::RecordId; /// Events are broadcast to all components. Each component decides which /// events it cares about in its `handle_event` implementation. #[derive(Debug, Clone)] -pub enum DaemonEvent { +pub(crate) enum DaemonEvent { // ---- History lifecycle ---- /// A command has started running. HistoryStarted(History), diff --git a/crates/turtle/src/atuin_daemon/mod.rs b/crates/turtle/src/atuin_daemon/mod.rs index aff33307..eac28f78 100644 --- a/crates/turtle/src/atuin_daemon/mod.rs +++ b/crates/turtle/src/atuin_daemon/mod.rs @@ -3,31 +3,31 @@ use crate::atuin_client::record::sqlite_store::SqliteStore; use crate::atuin_client::settings::{Settings, watcher::global_settings_watcher}; use eyre::Result; -pub mod client; -pub mod components; -pub mod control; -pub mod daemon; -pub mod events; -pub mod history; -pub mod search; -pub mod semantic; -pub mod server; +pub(crate) mod client; +pub(crate) mod components; +pub(crate) mod control; +pub(crate) mod daemon; +pub(crate) mod events; +pub(crate) mod history; +pub(crate) mod search; +pub(crate) mod semantic; +pub(crate) mod server; // Re-export core daemon types for convenience -pub use daemon::Daemon; -pub use events::DaemonEvent; +pub(crate) use daemon::Daemon; +pub(crate) use events::DaemonEvent; // Re-export components -pub use components::{HistoryComponent, SearchComponent, SemanticComponent, SyncComponent}; +pub(crate) use components::{HistoryComponent, SearchComponent, SemanticComponent, SyncComponent}; // Re-export client helpers -pub use client::SemanticClient; +pub(crate) use client::SemanticClient; /// Boot the daemon using the new component-based architecture. /// /// This creates a daemon with the standard components (history, search, sync), /// starts the gRPC server with their services, and runs the event loop. -pub async fn boot( +pub(crate) async fn boot( settings: Settings, store: SqliteStore, history_db: HistoryDatabase, diff --git a/crates/turtle/src/atuin_daemon/search/index.rs b/crates/turtle/src/atuin_daemon/search/index.rs index df627e1b..446d7992 100644 --- a/crates/turtle/src/atuin_daemon/search/index.rs +++ b/crates/turtle/src/atuin_daemon/search/index.rs @@ -38,16 +38,16 @@ fn format_uuid_bytes(bytes: &[u8; 16]) -> String { /// Pre-computed frecency data for O(1) lookup. #[derive(Debug, Clone, Default)] -pub struct FrecencyData { +pub(crate) struct FrecencyData { /// Total number of times this command was used. - pub count: u32, + pub(crate) count: u32, /// Most recent usage timestamp (unix seconds). - pub last_used: i64, + pub(crate) last_used: i64, } impl FrecencyData { /// Record a new usage of this command. - pub fn record_use(&mut self, timestamp: i64) { + pub(crate) fn record_use(&mut self, timestamp: i64) { self.count += 1; if timestamp > self.last_used { self.last_used = timestamp; @@ -66,7 +66,7 @@ impl FrecencyData { /// A multiplier of 0.0 disables that component, 1.0 is unchanged, 2.0 doubles weight. /// Values like 0.5 reduce weight by half, 1.5 increases by 50%, etc. #[instrument(level = tracing::Level::TRACE, name = "index_frecency_compute")] - pub fn compute(&self, now: i64, recency_mul: f64, frequency_mul: f64) -> u32 { + pub(crate) fn compute(&self, now: i64, recency_mul: f64, frequency_mul: f64) -> u32 { if self.count == 0 { return 0; } @@ -99,13 +99,13 @@ impl FrecencyData { } /// Data for a unique command. -pub struct CommandData { +pub(crate) struct CommandData { /// History ID of the most recent invocation (16-byte UUID). most_recent_id: [u8; 16], /// Timestamp of the most recent invocation. most_recent_timestamp: i64, /// Pre-computed global frecency. - pub global_frecency: FrecencyData, + pub(crate) global_frecency: FrecencyData, // Pre-computed indexes for O(1) filter lookups // Using HashSet instead of DashSet since CommandData lives inside DashMap (already synchronized) @@ -120,7 +120,7 @@ pub struct CommandData { impl CommandData { /// Create a new CommandData from a history entry. /// Returns None if the history entry has invalid UUIDs. - pub fn new(history: &History, interner: &ThreadedRodeo) -> Option<Self> { + pub(crate) fn new(history: &History, interner: &ThreadedRodeo) -> Option<Self> { let history_id = parse_uuid_bytes(&history.id.0)?; let session = parse_uuid_bytes(&history.session)?; let timestamp = history.timestamp.unix_timestamp(); @@ -152,7 +152,7 @@ impl CommandData { /// Add an invocation from a history entry. /// Returns false if the history entry has invalid UUIDs. - pub fn add_invocation(&mut self, history: &History, interner: &ThreadedRodeo) -> bool { + pub(crate) fn add_invocation(&mut self, history: &History, interner: &ThreadedRodeo) -> bool { let Some(history_id) = parse_uuid_bytes(&history.id.0) else { return false; }; @@ -181,13 +181,13 @@ impl CommandData { } /// Get the most recent history ID for this command. - pub fn most_recent_id(&self) -> String { + pub(crate) fn most_recent_id(&self) -> String { format_uuid_bytes(&self.most_recent_id) } /// Check if any invocation matches a directory filter (exact match). /// O(1) lookup using pre-computed index. - pub fn has_invocation_in_dir(&self, dir: &str, interner: &ThreadedRodeo) -> bool { + pub(crate) fn has_invocation_in_dir(&self, dir: &str, interner: &ThreadedRodeo) -> bool { interner .get(dir) .is_some_and(|spur| self.directories.contains(&spur)) @@ -195,7 +195,7 @@ impl CommandData { /// Check if any invocation matches a directory prefix (workspace/git root). /// O(n) where n = number of unique directories for this command. - pub fn has_invocation_in_workspace(&self, prefix: &str, interner: &ThreadedRodeo) -> bool { + pub(crate) fn has_invocation_in_workspace(&self, prefix: &str, interner: &ThreadedRodeo) -> bool { self.directories .iter() .any(|&spur| interner.resolve(&spur).starts_with(prefix)) @@ -203,7 +203,7 @@ impl CommandData { /// Check if any invocation matches a hostname. /// O(1) lookup using pre-computed index. - pub fn has_invocation_on_host(&self, hostname: &str, interner: &ThreadedRodeo) -> bool { + pub(crate) fn has_invocation_on_host(&self, hostname: &str, interner: &ThreadedRodeo) -> bool { interner .get(hostname) .is_some_and(|spur| self.hosts.contains(&spur)) @@ -211,14 +211,14 @@ impl CommandData { /// Check if any invocation matches a session. /// O(1) lookup using pre-computed index. - pub fn has_invocation_in_session(&self, session: &str) -> bool { + pub(crate) fn has_invocation_in_session(&self, session: &str) -> bool { parse_uuid_bytes(session).is_some_and(|bytes| self.sessions.contains(&bytes)) } } /// Filter mode for search queries. #[derive(Debug, Clone, PartialEq, Eq)] -pub enum IndexFilterMode { +pub(crate) enum IndexFilterMode { /// No filtering - search all commands. Global, /// Filter to commands run in a specific directory. @@ -233,11 +233,11 @@ pub enum IndexFilterMode { /// Context for search queries. #[derive(Debug, Clone, Default)] -pub struct QueryContext { - pub cwd: Option<String>, - pub git_root: Option<String>, - pub hostname: Option<String>, - pub session_id: Option<String>, +pub(crate) struct QueryContext { + pub(crate) cwd: Option<String>, + pub(crate) git_root: Option<String>, + pub(crate) hostname: Option<String>, + pub(crate) session_id: Option<String>, } /// Shareable frecency map: command -> frecency score. @@ -252,7 +252,7 @@ type FrecencyMap = Arc<HashMap<Arc<str>, u32>>; /// Global frecency is precomputed by a background task and used for scoring. /// If frecency data is not available, search still works but without frecency ranking; /// although this should never happen due to precomputing the frecency map. -pub struct SearchIndex { +pub(crate) struct SearchIndex { /// Map from command text to command data. /// Using DashMap for concurrent read/write access, wrapped in Arc for sharing with scorer. /// Keys are Arc<str> to enable zero-copy sharing with frecency_map. @@ -269,7 +269,7 @@ pub struct SearchIndex { impl SearchIndex { /// Create a new empty search index. - pub fn new() -> Self { + pub(crate) fn new() -> Self { let nucleo_config = atuin_nucleo::Config::DEFAULT; // Single column for command text let nucleo = Nucleo::<String>::new(nucleo_config, Arc::new(|| {}), None, 1); @@ -288,7 +288,7 @@ impl SearchIndex { /// /// If the command already exists, updates its invocation data. /// If it's a new command, adds it to both the map and Nucleo. - pub fn add_history(&self, history: &History) { + pub(crate) fn add_history(&self, history: &History) { if is_known_agent(&history.author) { return; } @@ -315,19 +315,19 @@ impl SearchIndex { } /// Add multiple history entries to the index. - pub fn add_histories(&self, histories: &[History]) { + pub(crate) fn add_histories(&self, histories: &[History]) { for history in histories { self.add_history(history); } } /// Get the number of unique commands in the index. - pub fn command_count(&self) -> usize { + pub(crate) fn command_count(&self) -> usize { self.commands.len() } /// Get the number of items in Nucleo (should match command_count). - pub async fn nucleo_item_count(&self) -> u32 { + pub(crate) async fn nucleo_item_count(&self) -> u32 { self.nucleo.read().await.snapshot().item_count() } @@ -336,7 +336,7 @@ impl SearchIndex { /// Returns a list of history IDs (most recent invocation per command). /// Uses precomputed global frecency for scoring if available. #[instrument(skip_all, level = tracing::Level::TRACE, name = "index_search", fields(query = %query))] - pub async fn search( + pub(crate) async fn search( &self, query: &str, filter_mode: IndexFilterMode, @@ -398,7 +398,7 @@ impl SearchIndex { /// - `frequency_score_multiplier`: Weight for frequency component /// - `frecency_score_multiplier`: Overall multiplier for final score #[instrument(skip_all, level = tracing::Level::DEBUG, name = "rebuild_frecency")] - pub async fn rebuild_frecency(&self, search_settings: &Search) { + pub(crate) async fn rebuild_frecency(&self, search_settings: &Search) { let now = OffsetDateTime::now_utc().unix_timestamp(); let mut frecency_map: HashMap<Arc<str>, u32> = HashMap::new(); diff --git a/crates/turtle/src/atuin_daemon/search/mod.rs b/crates/turtle/src/atuin_daemon/search/mod.rs index 4d261956..51b6c6cc 100644 --- a/crates/turtle/src/atuin_daemon/search/mod.rs +++ b/crates/turtle/src/atuin_daemon/search/mod.rs @@ -8,4 +8,4 @@ mod index; tonic::include_proto!("search"); // Re-export the service and index -pub use index::{IndexFilterMode, QueryContext, SearchIndex}; +pub(crate) use index::{IndexFilterMode, QueryContext, SearchIndex}; diff --git a/crates/turtle/src/atuin_daemon/server.rs b/crates/turtle/src/atuin_daemon/server.rs index 23b04342..65272d2a 100644 --- a/crates/turtle/src/atuin_daemon/server.rs +++ b/crates/turtle/src/atuin_daemon/server.rs @@ -16,7 +16,7 @@ use crate::atuin_client::settings::Settings; /// This starts the gRPC server in the background and returns immediately. /// The server will shut down when a ShutdownRequested event is received. #[cfg(unix)] -pub async fn run_grpc_server( +pub(crate) async fn run_grpc_server( settings: Settings, history_service: HistoryServer<HistoryGrpcService>, search_service: SearchServer<SearchGrpcService>, |
