Skip to main content

vv_agent/tools/base/
spec.rs

1use std::sync::Arc;
2use std::time::Duration;
3
4use serde_json::{json, Value};
5
6use super::ToolContext;
7use crate::tools::{ToolApprovalRule, ToolMetadata};
8use crate::types::{Metadata, ToolArguments, ToolExecutionResult};
9
10pub type ToolHandler =
11    Arc<dyn Fn(&mut ToolContext, &ToolArguments) -> ToolExecutionResult + Send + Sync + 'static>;
12pub type SubTaskRunner = Arc<
13    dyn Fn(crate::types::SubTaskRequest) -> crate::types::SubTaskOutcome + Send + Sync + 'static,
14>;
15
16#[derive(Clone)]
17pub struct ToolSpec {
18    pub name: String,
19    pub handler: ToolHandler,
20    pub description: String,
21    pub schema: Value,
22    pub kind: ToolSpecKind,
23    pub strict_schema: bool,
24    pub exposure: crate::tools::ToolExposure,
25    pub timeout: Option<Duration>,
26    pub approval: ToolApprovalRule,
27    pub tool_metadata: Option<ToolMetadata>,
28    pub metadata: Metadata,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum ToolSpecKind {
33    Function,
34    Agent,
35    BackgroundAgent,
36    Handoff,
37}
38
39impl ToolSpec {
40    pub fn new(
41        name: impl Into<String>,
42        description: impl Into<String>,
43        handler: ToolHandler,
44    ) -> Self {
45        let name = name.into();
46        let fallback_description = description.into();
47        let schema = crate::tools::schemas::schema_for(&name).unwrap_or_else(|| {
48            json!({
49                "type": "function",
50                "function": {
51                    "name": name,
52                    "description": fallback_description,
53                    "parameters": {
54                        "type": "object",
55                        "properties": {},
56                        "required": [],
57                        "additionalProperties": false
58                    },
59                }
60            })
61        });
62        let schema = crate::tools::argument_validation::close_object_schemas(&schema);
63        let description = schema["function"]["description"]
64            .as_str()
65            .unwrap_or(&fallback_description)
66            .to_string();
67        Self {
68            schema,
69            name,
70            handler,
71            description,
72            kind: ToolSpecKind::Function,
73            strict_schema: true,
74            exposure: crate::tools::ToolExposure::Direct,
75            timeout: None,
76            approval: ToolApprovalRule::default(),
77            tool_metadata: None,
78            metadata: Metadata::new(),
79        }
80    }
81}
82
83#[derive(Debug, Clone, thiserror::Error)]
84#[error("tool not found: {0}")]
85pub struct ToolNotFoundError(pub String);