//! Per-agent notification pollers — shared library half. //! //! Two binaries ship from this crate, one per notification host: //! //! - **`hive-forge-notify`** — the hive's internal Forgejo. Always //! deployed; the behaviour predates this split and is unchanged. //! - **`hive-github-notify`** — github.com, for agents that have a PAT. //! //! They are separate *binaries* rather than one process with two loops so //! the deployment can choose: an agent module installs the GitHub unit or //! it doesn't, and the decision lives in the module rather than in a cargo //! feature. A feature flag would unify across the workspace — enabling it //! for one consumer changes feature resolution for the whole graph and //! stops the two builds sharing any cached crate — which is a permanent //! cost for something a second binary expresses for free. //! //! Everything except the host-specific calls (list unread, mark read, //! resolve own login) is shared and lives here: classification, wake //! formatting, the tolerant parse, delivery dedupe, and the todo upsert. //! The host differences live behind [`source::Source`]. pub mod notify; pub mod source; /// Re-exported so a binary can spell it once at the crate root alongside /// the other things it needs to build a client; it is a property of the /// poller, not of the notification format. pub use notify::HTTP_TIMEOUT_SECS; /// Retry policy for the harness's in-agent socket. Deliberately fail-fast: /// both callers are inside the poll loop and both treat a failed request as /// "leave the thread unread and try again next tick", so the poll interval /// *is* the retry — a second, in-request backoff would only stack sleeps on /// top of it and delay the rest of the batch. That is the opposite /// trade-off from the serve loop's client, which rides out a hive-c0re /// restart because its callers have no natural retry of their own. pub const TODO_SOCKET_RETRY: hive_sock_client::Retry = hive_sock_client::Retry::None; /// Resolve the harness's in-agent todo socket from the environment, falling /// back to the well-known path. Shared by both binaries so they can't drift /// on where they deliver. #[must_use] pub fn agent_socket() -> std::path::PathBuf { std::env::var_os("HIVE_AGENT_SOCKET").map_or_else( || std::path::PathBuf::from(hive_agent_sock::DEFAULT_AGENT_SOCKET), std::path::PathBuf::from, ) } /// Install the tracing subscriber both binaries use: `RUST_LOG` when set, /// `info` otherwise. pub fn init_tracing() { tracing_subscriber::fmt() .with_env_filter( tracing_subscriber::EnvFilter::try_from_env("RUST_LOG") .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")), ) .init(); } /// Read `HYPERHIVE_STATE_DIR`, the directory holding the agent's /// credentials (`forge-token`, `github-token`). Empty when unset, which /// makes the token paths relative and the read fail — the callers treat /// that as "not configured" and settle. #[must_use] pub fn state_dir() -> String { std::env::var("HYPERHIVE_STATE_DIR").unwrap_or_default() }