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