vv_agent/tools/base/
spec.rs1use 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);