vtcode_core/tool_policy/
model.rs1use anyhow::Result;
2use indexmap::{IndexMap, IndexSet};
3use serde::{Deserialize, Serialize};
4
5use super::{McpPolicyStore, ToolPolicy};
6
7#[derive(Debug, Clone, PartialEq)]
9pub enum ToolExecutionDecision {
10 Allowed,
12 Denied,
14 DeniedWithFeedback(String),
16}
17
18impl ToolExecutionDecision {
19 pub fn is_allowed(&self) -> bool {
20 matches!(self, Self::Allowed)
21 }
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct ToolPolicyConfig {
27 pub version: u32,
29 pub available_tools: Vec<String>,
31 pub policies: IndexMap<String, ToolPolicy>,
33 #[serde(default)]
35 pub constraints: IndexMap<String, ToolConstraints>,
36 #[serde(default)]
38 pub mcp: McpPolicyStore,
39 #[serde(default)]
41 pub approval_cache: ApprovalCacheConfig,
42}
43
44impl Default for ToolPolicyConfig {
45 fn default() -> Self {
46 Self {
47 version: 1,
48 available_tools: Vec::new(),
49 policies: IndexMap::new(),
50 constraints: IndexMap::new(),
51 mcp: McpPolicyStore::default(),
52 approval_cache: ApprovalCacheConfig::default(),
53 }
54 }
55}
56
57#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
59pub struct ApprovalCacheConfig {
60 #[serde(default)]
62 pub allowed: IndexSet<String>,
63 #[serde(default)]
65 pub prefixes: IndexSet<String>,
66 #[serde(default)]
68 pub regexes: IndexSet<String>,
69}
70
71pub const APPROVAL_CACHE_MAX_ENTRIES: usize = 256;
76
77impl ApprovalCacheConfig {
78 pub fn trim_to_budget(&mut self) -> bool {
81 let mut trimmed = false;
82 for collection in [&mut self.allowed, &mut self.prefixes, &mut self.regexes] {
83 while collection.len() > APPROVAL_CACHE_MAX_ENTRIES {
84 let _ = collection.shift_remove_index(0);
85 trimmed = true;
86 }
87 }
88 trimmed
89 }
90}
91
92pub trait PermissionPromptHandler: Send + Sync {
97 fn prompt_tool_permission(&mut self, tool_name: &str) -> Result<ToolExecutionDecision>;
99}
100
101#[derive(Debug, Clone, Default, Serialize, Deserialize)]
103pub struct ToolConstraints {
104 #[serde(default)]
106 pub allowed_modes: Option<Vec<String>>,
107 #[serde(default)]
109 pub max_results_per_call: Option<usize>,
110 #[serde(default)]
112 pub max_items_per_call: Option<usize>,
113 #[serde(default)]
115 pub default_response_format: Option<String>,
116 #[serde(default)]
118 pub max_bytes_per_read: Option<usize>,
119 #[serde(default)]
121 pub max_response_bytes: Option<usize>,
122 #[serde(default)]
124 pub allowed_url_schemes: Option<Vec<String>>,
125 #[serde(default)]
127 pub denied_url_hosts: Option<Vec<String>>,
128}