assistant_tools.rs

  1mod batch_tool;
  2mod code_action_tool;
  3mod code_symbols_tool;
  4mod contents_tool;
  5mod copy_path_tool;
  6mod create_directory_tool;
  7mod create_file_tool;
  8mod delete_path_tool;
  9mod diagnostics_tool;
 10mod edit_file_tool;
 11mod fetch_tool;
 12mod find_path_tool;
 13mod grep_tool;
 14mod list_directory_tool;
 15mod move_path_tool;
 16mod now_tool;
 17mod open_tool;
 18mod read_file_tool;
 19mod rename_tool;
 20mod replace;
 21mod schema;
 22mod symbol_info_tool;
 23mod terminal_tool;
 24mod thinking_tool;
 25mod ui;
 26mod web_search_tool;
 27
 28use std::sync::Arc;
 29
 30use assistant_tool::ToolRegistry;
 31use copy_path_tool::CopyPathTool;
 32use gpui::App;
 33use http_client::HttpClientWithUrl;
 34use language_model::LanguageModelRegistry;
 35use move_path_tool::MovePathTool;
 36use web_search_tool::WebSearchTool;
 37
 38use crate::batch_tool::BatchTool;
 39use crate::code_action_tool::CodeActionTool;
 40use crate::code_symbols_tool::CodeSymbolsTool;
 41use crate::contents_tool::ContentsTool;
 42use crate::create_directory_tool::CreateDirectoryTool;
 43use crate::create_file_tool::CreateFileTool;
 44use crate::delete_path_tool::DeletePathTool;
 45use crate::diagnostics_tool::DiagnosticsTool;
 46use crate::edit_file_tool::EditFileTool;
 47use crate::fetch_tool::FetchTool;
 48use crate::find_path_tool::FindPathTool;
 49use crate::grep_tool::GrepTool;
 50use crate::list_directory_tool::ListDirectoryTool;
 51use crate::now_tool::NowTool;
 52use crate::open_tool::OpenTool;
 53use crate::read_file_tool::ReadFileTool;
 54use crate::rename_tool::RenameTool;
 55use crate::symbol_info_tool::SymbolInfoTool;
 56use crate::terminal_tool::TerminalTool;
 57use crate::thinking_tool::ThinkingTool;
 58
 59pub use create_file_tool::CreateFileToolInput;
 60pub use edit_file_tool::EditFileToolInput;
 61pub use find_path_tool::FindPathToolInput;
 62pub use read_file_tool::ReadFileToolInput;
 63
 64pub fn init(http_client: Arc<HttpClientWithUrl>, cx: &mut App) {
 65    assistant_tool::init(cx);
 66
 67    let registry = ToolRegistry::global(cx);
 68    registry.register_tool(TerminalTool);
 69    registry.register_tool(BatchTool);
 70    registry.register_tool(CreateDirectoryTool);
 71    registry.register_tool(CreateFileTool);
 72    registry.register_tool(CopyPathTool);
 73    registry.register_tool(DeletePathTool);
 74    registry.register_tool(EditFileTool);
 75    registry.register_tool(SymbolInfoTool);
 76    registry.register_tool(CodeActionTool);
 77    registry.register_tool(MovePathTool);
 78    registry.register_tool(DiagnosticsTool);
 79    registry.register_tool(ListDirectoryTool);
 80    registry.register_tool(NowTool);
 81    registry.register_tool(OpenTool);
 82    registry.register_tool(CodeSymbolsTool);
 83    registry.register_tool(ContentsTool);
 84    registry.register_tool(FindPathTool);
 85    registry.register_tool(ReadFileTool);
 86    registry.register_tool(GrepTool);
 87    registry.register_tool(RenameTool);
 88    registry.register_tool(ThinkingTool);
 89    registry.register_tool(FetchTool::new(http_client));
 90
 91    cx.subscribe(
 92        &LanguageModelRegistry::global(cx),
 93        move |registry, event, cx| match event {
 94            language_model::Event::DefaultModelChanged => {
 95                let using_zed_provider = registry
 96                    .read(cx)
 97                    .default_model()
 98                    .map_or(false, |default| default.is_provided_by_zed());
 99                if using_zed_provider {
100                    ToolRegistry::global(cx).register_tool(WebSearchTool);
101                } else {
102                    ToolRegistry::global(cx).unregister_tool(WebSearchTool);
103                }
104            }
105            _ => {}
106        },
107    )
108    .detach();
109}
110
111#[cfg(test)]
112mod tests {
113    use client::Client;
114    use clock::FakeSystemClock;
115    use http_client::FakeHttpClient;
116
117    use super::*;
118
119    #[gpui::test]
120    fn test_builtin_tool_schema_compatibility(cx: &mut App) {
121        settings::init(cx);
122
123        let client = Client::new(
124            Arc::new(FakeSystemClock::new()),
125            FakeHttpClient::with_200_response(),
126            cx,
127        );
128        language_model::init(client.clone(), cx);
129        crate::init(client.http_client(), cx);
130
131        for tool in ToolRegistry::global(cx).tools() {
132            let actual_schema = tool
133                .input_schema(language_model::LanguageModelToolSchemaFormat::JsonSchemaSubset)
134                .unwrap();
135            let mut expected_schema = actual_schema.clone();
136            assistant_tool::adapt_schema_to_format(
137                &mut expected_schema,
138                language_model::LanguageModelToolSchemaFormat::JsonSchemaSubset,
139            )
140            .unwrap();
141
142            let error_message = format!(
143                "Tool schema for `{}` is not compatible with `language_model::LanguageModelToolSchemaFormat::JsonSchemaSubset` (Gemini Models).\n\
144                Are you using `schema::json_schema_for<T>(format)` to generate the schema?",
145                tool.name(),
146            );
147
148            assert_eq!(actual_schema, expected_schema, "{}", error_message)
149        }
150    }
151}