Skip to main content

voidcrawl_mcp/tools/
introspect.rs

1//! Pool + session introspection.
2
3use schemars::JsonSchema;
4use serde::Serialize;
5use void_crawl_core::Result;
6
7use crate::server::VoidCrawlServer;
8
9#[derive(Debug, Serialize, JsonSchema)]
10pub struct PoolStatus {
11    pub browsers:          usize,
12    pub tabs_per_browser:  usize,
13    pub max_tabs:          usize,
14    /// Free tab slots right now — how many fetches an agent can fan out
15    /// without queueing. Read this before a big `fetch_many` to size the
16    /// batch. A live snapshot, so it races with concurrent calls; treat it as
17    /// guidance, not a reservation.
18    pub available:         usize,
19    /// Tabs currently checked out (`max_tabs - available`): in-flight fetches
20    /// plus any held session tabs.
21    pub in_flight:         usize,
22    pub tab_max_uses:      u32,
23    pub tab_max_idle_secs: u64,
24    pub sessions_open:     usize,
25}
26
27pub async fn pool_status(server: &VoidCrawlServer) -> Result<PoolStatus> {
28    let pool = server.state().pool().await?;
29    let cfg = pool.config();
30    let sessions_open = server.state().sessions.len().await;
31    let max_tabs = cfg.browsers.saturating_mul(cfg.tabs_per_browser);
32    let available = pool.available_permits().min(max_tabs);
33    Ok(PoolStatus {
34        browsers: cfg.browsers,
35        tabs_per_browser: cfg.tabs_per_browser,
36        max_tabs,
37        available,
38        in_flight: max_tabs.saturating_sub(available),
39        tab_max_uses: cfg.tab_max_uses,
40        tab_max_idle_secs: cfg.tab_max_idle_secs,
41        sessions_open,
42    })
43}