1#![deny(warnings)]
2#![deny(clippy::all)]
3
4pub mod fetch;
7pub mod haiku;
8pub mod search;
9pub mod tools;
10pub mod types;
11
12use agentic_config::types::AnthropicServiceConfig;
13use agentic_config::types::ExaServiceConfig;
14use agentic_config::types::WebRetrievalConfig;
15use tokio::sync::OnceCell;
16
17pub struct WebTools {
22 pub(crate) http: reqwest::Client,
24 pub(crate) exa: exa_async::Client<exa_async::ExaConfig>,
26 pub(crate) anthropic: OnceCell<anthropic_async::Client<anthropic_async::AnthropicConfig>>,
28 pub(crate) cfg: WebRetrievalConfig,
30 pub(crate) anthropic_cfg: AnthropicServiceConfig,
32}
33
34impl WebTools {
35 #[must_use]
40 #[expect(
41 clippy::expect_used,
42 reason = "reqwest client build failure is rare (TLS/resolver init) and fatal; matches reqwest::Client::new() pattern"
43 )]
44 pub fn with_config(
45 cfg: WebRetrievalConfig,
46 exa_cfg: &ExaServiceConfig,
47 anthropic_cfg: AnthropicServiceConfig,
48 ) -> Self {
49 let exa_config = exa_async::ExaConfig::new().with_api_base(&exa_cfg.base_url);
51 Self {
52 http: reqwest::Client::builder()
53 .connect_timeout(std::time::Duration::from_secs(5))
54 .timeout(std::time::Duration::from_secs(cfg.request_timeout_secs))
55 .build()
56 .expect("reqwest client"),
57 exa: exa_async::Client::with_config(exa_config),
58 anthropic: OnceCell::new(),
59 cfg,
60 anthropic_cfg,
61 }
62 }
63
64 #[must_use]
69 pub fn new() -> Self {
70 Self::with_config(
71 WebRetrievalConfig::default(),
72 &ExaServiceConfig::default(),
73 AnthropicServiceConfig::default(),
74 )
75 }
76}
77
78impl Default for WebTools {
79 fn default() -> Self {
80 Self::new()
81 }
82}
83
84pub use tools::build_registry;
86
87#[cfg(test)]
88impl WebTools {
89 pub(crate) fn with_http_client(http: reqwest::Client) -> Self {
91 let exa_cfg = ExaServiceConfig::default();
92 let exa_config = exa_async::ExaConfig::new().with_api_base(&exa_cfg.base_url);
93 Self {
94 http,
95 exa: exa_async::Client::with_config(exa_config),
96 anthropic: OnceCell::new(),
97 cfg: WebRetrievalConfig::default(),
98 anthropic_cfg: AnthropicServiceConfig::default(),
99 }
100 }
101}