weavatrix_rust/operations/catalog/
mod.rs1use blazingly_json::{Map, Value, json};
2use serde::Serialize;
3
4mod definitions;
5mod profile;
6mod schema;
7mod validation;
8
9pub use profile::ToolProfile;
10
11#[derive(Debug, Clone, Serialize)]
12#[serde(rename_all = "camelCase")]
13pub struct ToolDefinition {
14 pub name: &'static str,
15 pub description: &'static str,
16 pub input_schema: Value,
17}
18
19#[must_use]
20pub fn catalog() -> Vec<ToolDefinition> {
21 definitions::SPECS
22 .iter()
23 .filter(|spec| capability_is_compiled(spec.name))
24 .map(|spec| tool(spec.name, spec.description, spec.required))
25 .collect()
26}
27
28#[must_use]
29pub fn catalog_for_profile(profile: ToolProfile) -> Vec<ToolDefinition> {
30 catalog()
31 .into_iter()
32 .filter(|tool| profile.allows(tool.name))
33 .collect()
34}
35
36#[allow(clippy::needless_bool)]
37fn capability_is_compiled(tool: &str) -> bool {
38 if tool == "find_duplicates" {
39 cfg!(feature = "clone")
40 } else if matches!(
41 tool,
42 "change_impact"
43 | "git_history"
44 | "cross_repo_git"
45 | "verified_change"
46 | "graph_diff"
47 | "select_tests"
48 ) {
49 cfg!(feature = "git")
50 } else if tool == "search_code" {
51 cfg!(feature = "search")
52 } else if matches!(tool, "semantic_link" | "seo_link_suggestions") {
53 cfg!(feature = "semantic")
54 } else if tool == "vector_search" {
55 cfg!(feature = "vector")
56 } else if tool == "memory_context" {
57 cfg!(feature = "memory")
58 } else {
59 true
60 }
61}
62
63fn tool(
64 tool_name: &'static str,
65 description: &'static str,
66 required: &[&'static str],
67) -> ToolDefinition {
68 let mut properties = Map::from_iter([(
69 "output_format".to_owned(),
70 json!({
71 "type": "string",
72 "enum": ["text", "json"],
73 "default": "json"
74 }),
75 )]);
76 for name in schema::optional_fields(tool_name) {
77 properties.insert((*name).to_owned(), schema::field_schema(tool_name, name));
78 }
79 for name in required {
80 let schema = schema::field_schema(tool_name, name);
81 properties.insert((*name).to_owned(), schema);
82 }
83 let required = required
84 .iter()
85 .map(|value| json!(value))
86 .collect::<Vec<_>>();
87 ToolDefinition {
88 name: tool_name,
89 description,
90 input_schema: json!({
91 "type": "object",
92 "additionalProperties": true,
93 "properties": properties,
94 "required": required
95 }),
96 }
97}