tool_useful/
tool.rs

1//! Core tool trait and metadata.
2
3use crate::{ToolCall, ToolResult, ToolSchema};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7/// Metadata about a tool
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct ToolMetadata {
10    pub name: String,
11    pub description: String,
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub category: Option<String>,
14    #[serde(default, skip_serializing_if = "Vec::is_empty")]
15    pub tags: Vec<String>,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub version: Option<String>,
18    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
19    pub extra: HashMap<String, serde_json::Value>,
20}
21
22impl ToolMetadata {
23    pub fn new(name: impl Into<String>, description: impl Into<String>) -> Self {
24        Self {
25            name: name.into(),
26            description: description.into(),
27            category: None,
28            tags: Vec::new(),
29            version: None,
30            extra: HashMap::new(),
31        }
32    }
33
34    pub fn with_category(mut self, category: impl Into<String>) -> Self {
35        self.category = Some(category.into());
36        self
37    }
38
39    pub fn with_tag(mut self, tag: impl Into<String>) -> Self {
40        self.tags.push(tag.into());
41        self
42    }
43
44    pub fn with_tags<I, S>(mut self, tags: I) -> Self
45    where
46        I: IntoIterator<Item = S>,
47        S: Into<String>,
48    {
49        self.tags.extend(tags.into_iter().map(|t| t.into()));
50        self
51    }
52
53    pub fn with_version(mut self, version: impl Into<String>) -> Self {
54        self.version = Some(version.into());
55        self
56    }
57}
58
59/// Core trait for all tools
60pub trait Tool: Send + Sync {
61    fn metadata(&self) -> ToolMetadata;
62    fn schema(&self) -> ToolSchema;
63    fn name(&self) -> &str {
64        "unknown"
65    }
66}
67
68/// Trait for tools that can be constructed from raw arguments
69pub trait FromToolCall: Tool + Sized {
70    fn from_tool_call(call: &ToolCall) -> ToolResult<Self>;
71}