@@ -12,11 +12,13 @@ use crate::UserAuthConfigFile;
1212pub struct ToolsConfig {
1313 #[ serde( default , skip_serializing_if = "WebSearchConfig::is_default" ) ]
1414 pub web_search : WebSearchConfig ,
15+ #[ serde( default , skip_serializing_if = "WebFetchConfig::is_default" ) ]
16+ pub web_fetch : WebFetchConfig ,
1517}
1618
1719impl ToolsConfig {
1820 pub fn is_empty ( & self ) -> bool {
19- self . web_search . is_default ( )
21+ self . web_search . is_default ( ) && self . web_fetch . is_default ( )
2022 }
2123}
2224
@@ -49,6 +51,29 @@ impl WebSearchConfig {
4951 }
5052}
5153
54+ /// Selects how Devo exposes web fetch for a provider/model.
55+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Serialize , Deserialize , Default ) ]
56+ #[ serde( rename_all = "snake_case" ) ]
57+ pub enum WebFetchMode {
58+ Disabled ,
59+ Provider ,
60+ #[ default]
61+ Local ,
62+ }
63+
64+ /// Configures the effective `web_fetch` capability.
65+ #[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize , Default ) ]
66+ pub struct WebFetchConfig {
67+ #[ serde( default , skip_serializing_if = "is_default_web_fetch_mode" ) ]
68+ pub mode : WebFetchMode ,
69+ }
70+
71+ impl WebFetchConfig {
72+ pub fn is_default ( & self ) -> bool {
73+ self . mode == WebFetchMode :: Local
74+ }
75+ }
76+
5277/// Local third-party search provider configuration.
5378#[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
5479pub struct LocalWebSearchProviderConfig {
@@ -88,6 +113,26 @@ impl ResolvedWebSearchConfig {
88113 }
89114}
90115
116+ /// Fully resolved web fetch behavior for one model invocation.
117+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Serialize , Deserialize , Default ) ]
118+ #[ serde( tag = "mode" , rename_all = "snake_case" ) ]
119+ pub enum ResolvedWebFetchConfig {
120+ Disabled ,
121+ Provider ,
122+ #[ default]
123+ Local ,
124+ }
125+
126+ impl ResolvedWebFetchConfig {
127+ pub fn is_local ( self ) -> bool {
128+ matches ! ( self , Self :: Local )
129+ }
130+
131+ pub fn is_provider ( self ) -> bool {
132+ matches ! ( self , Self :: Provider )
133+ }
134+ }
135+
91136/// Local search service plus user-scoped API key for one turn.
92137#[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
93138pub struct ResolvedLocalWebSearchConfig {
@@ -114,6 +159,19 @@ pub fn resolve_web_search_config(
114159 }
115160}
116161
162+ pub fn resolve_web_fetch_config (
163+ global : & WebFetchConfig ,
164+ provider_override : Option < & WebFetchConfig > ,
165+ binding_override : Option < & WebFetchConfig > ,
166+ ) -> ResolvedWebFetchConfig {
167+ let effective = binding_override. or ( provider_override) . unwrap_or ( global) ;
168+ match effective. mode {
169+ WebFetchMode :: Disabled => ResolvedWebFetchConfig :: Disabled ,
170+ WebFetchMode :: Provider => ResolvedWebFetchConfig :: Provider ,
171+ WebFetchMode :: Local => ResolvedWebFetchConfig :: Local ,
172+ }
173+ }
174+
117175fn resolve_local_web_search (
118176 global : & WebSearchConfig ,
119177 effective : & WebSearchConfig ,
@@ -167,6 +225,10 @@ fn is_default_web_search_mode(mode: &WebSearchMode) -> bool {
167225 * mode == WebSearchMode :: Provider
168226}
169227
228+ fn is_default_web_fetch_mode ( mode : & WebFetchMode ) -> bool {
229+ * mode == WebFetchMode :: Local
230+ }
231+
170232#[ cfg( test) ]
171233mod tests {
172234 use std:: collections:: BTreeMap ;
0 commit comments