everruns_core/capabilities/
claude_tool_search.rs1use super::{Capability, CapabilityLocalization, CapabilityStatus, SystemPromptContext};
19use crate::driver_registry::ToolSearchConfig;
20use async_trait::async_trait;
21
22pub use super::openai_tool_search::DEFAULT_TOOL_SEARCH_THRESHOLD;
23
24pub const CLAUDE_TOOL_SEARCH_CAPABILITY_ID: &str = "claude_tool_search";
26
27pub struct ClaudeToolSearchCapability {
33 threshold: usize,
34}
35
36impl ClaudeToolSearchCapability {
37 pub fn new() -> Self {
38 Self {
39 threshold: DEFAULT_TOOL_SEARCH_THRESHOLD,
40 }
41 }
42
43 pub fn with_threshold(threshold: usize) -> Self {
44 Self { threshold }
45 }
46
47 pub fn tool_search_config(&self) -> ToolSearchConfig {
55 ToolSearchConfig {
56 enabled: true,
57 threshold: self.threshold,
58 }
59 }
60}
61
62pub fn model_supports_native_tool_search(model: &str) -> bool {
72 crate::model_profiles::get_model_profile(&crate::provider::DriverId::Anthropic, model)
73 .is_some_and(|profile| profile.tool_search)
74}
75
76impl Default for ClaudeToolSearchCapability {
77 fn default() -> Self {
78 Self::new()
79 }
80}
81
82#[async_trait]
83impl Capability for ClaudeToolSearchCapability {
84 fn id(&self) -> &str {
85 CLAUDE_TOOL_SEARCH_CAPABILITY_ID
86 }
87
88 fn name(&self) -> &str {
89 "Claude Tool Search"
90 }
91
92 fn description(&self) -> &str {
93 "Enables deferred tool loading for Claude models that support it \
94 (Sonnet 4, Opus 4, Haiku 4.5, and Fable 5 and newer). Reduces token \
95 usage by loading tool schemas on-demand instead of upfront."
96 }
97
98 fn localizations(&self) -> Vec<CapabilityLocalization> {
99 vec![CapabilityLocalization::text(
100 "uk",
101 "Пошук інструментів Claude",
102 "Вмикає відкладене завантаження інструментів для моделей Claude, які його підтримують (Sonnet 4, Opus 4, Haiku 4.5 та Fable 5 і новіші). Зменшує використання токенів, завантажуючи схеми інструментів на вимогу, а не заздалегідь.",
103 )]
104 }
105
106 fn status(&self) -> CapabilityStatus {
107 CapabilityStatus::Available
108 }
109
110 fn category(&self) -> Option<&str> {
111 Some("Optimization")
112 }
113
114 async fn system_prompt_contribution(&self, _ctx: &SystemPromptContext) -> Option<String> {
115 None }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
126 fn test_default_threshold() {
127 let cap = ClaudeToolSearchCapability::new();
128 let config = cap.tool_search_config();
129 assert!(config.enabled);
130 assert_eq!(config.threshold, DEFAULT_TOOL_SEARCH_THRESHOLD);
131 }
132
133 #[test]
134 fn test_custom_threshold() {
135 let cap = ClaudeToolSearchCapability::with_threshold(5);
136 assert_eq!(cap.tool_search_config().threshold, 5);
137 }
138
139 #[test]
140 fn test_native_support_lookup() {
141 assert!(model_supports_native_tool_search("claude-opus-4-8"));
143 assert!(model_supports_native_tool_search("claude-sonnet-5"));
144 assert!(model_supports_native_tool_search("claude-sonnet-4-6"));
145 assert!(model_supports_native_tool_search("claude-haiku-4-5"));
146 assert!(model_supports_native_tool_search("claude-fable-5"));
147 assert!(!model_supports_native_tool_search("claude-3-5-haiku"));
148 assert!(!model_supports_native_tool_search("gpt-5.5"));
150 }
151}