Skip to main content

vtcode_core/tools/registry/
execution_request.rs

1use serde_json::Value;
2use std::time::Duration;
3
4use super::ToolExecutionError;
5
6/// Controls how unified exec calls should settle before returning to the caller.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub enum ExecSettlementMode {
9    /// Return on the first yield boundary and require explicit follow-up poll/continue calls.
10    #[default]
11    Manual,
12    /// Keep polling pipe-backed sessions until they reach a terminal state.
13    SettleNonInteractive,
14}
15
16impl ExecSettlementMode {
17    #[must_use]
18    pub fn settle_noninteractive(self) -> bool {
19        matches!(self, Self::SettleNonInteractive)
20    }
21}
22
23/// Runtime execution policy snapshot for a single tool call.
24#[derive(Debug, Clone)]
25pub struct ExecutionPolicySnapshot {
26    /// Maximum retry attempts after the initial attempt.
27    pub max_retries: usize,
28    /// Base exponential backoff delay.
29    pub retry_base_delay: Duration,
30    /// Maximum retry backoff delay.
31    pub retry_max_delay: Duration,
32    /// Retry backoff multiplier.
33    pub retry_multiplier: f64,
34    /// Retry jitter ratio in [0.0, 1.0].
35    pub retry_jitter: f64,
36    /// When true, caller already ran preflight validation.
37    pub prevalidated: bool,
38    /// Optional invocation id for cross-surface correlation.
39    pub invocation_id: Option<String>,
40    /// How unified_exec should settle before returning.
41    pub exec_settlement_mode: ExecSettlementMode,
42    /// Whether caller already completed safety gateway admission.
43    pub safety_prevalidated: bool,
44}
45
46impl Default for ExecutionPolicySnapshot {
47    fn default() -> Self {
48        Self {
49            max_retries: 0,
50            retry_base_delay: Duration::from_millis(200),
51            retry_max_delay: Duration::from_secs(2),
52            retry_multiplier: 2.0,
53            retry_jitter: 0.0,
54            prevalidated: false,
55            invocation_id: None,
56            exec_settlement_mode: ExecSettlementMode::Manual,
57            safety_prevalidated: false,
58        }
59    }
60}
61
62impl ExecutionPolicySnapshot {
63    #[must_use]
64    pub fn with_max_retries(mut self, max_retries: usize) -> Self {
65        self.max_retries = max_retries;
66        self
67    }
68
69    #[must_use]
70    pub fn with_prevalidated(mut self, prevalidated: bool) -> Self {
71        self.prevalidated = prevalidated;
72        self
73    }
74
75    #[must_use]
76    pub fn with_invocation_id(mut self, invocation_id: Option<String>) -> Self {
77        self.invocation_id = invocation_id;
78        self
79    }
80
81    #[must_use]
82    pub fn with_exec_settlement_mode(mut self, mode: ExecSettlementMode) -> Self {
83        self.exec_settlement_mode = mode;
84        self
85    }
86
87    #[must_use]
88    pub fn with_safety_prevalidated(mut self, safety_prevalidated: bool) -> Self {
89        self.safety_prevalidated = safety_prevalidated;
90        self
91    }
92}
93
94/// Canonical tool execution request routed through ToolRegistry kernel.
95#[derive(Debug, Clone)]
96pub struct ToolExecutionRequest {
97    pub tool_name: String,
98    pub args: Value,
99    pub policy: ExecutionPolicySnapshot,
100}
101
102impl ToolExecutionRequest {
103    #[must_use]
104    pub fn new(tool_name: impl Into<String>, args: Value) -> Self {
105        Self {
106            tool_name: tool_name.into(),
107            args,
108            policy: ExecutionPolicySnapshot::default(),
109        }
110    }
111
112    #[must_use]
113    pub fn with_policy(mut self, policy: ExecutionPolicySnapshot) -> Self {
114        self.policy = policy;
115        self
116    }
117}
118
119/// Canonical execution result for shared runtime adapters.
120#[derive(Debug, Clone)]
121pub struct ToolExecutionOutcome {
122    pub tool_name: String,
123    pub attempts: u32,
124    pub output: Option<Value>,
125    pub error: Option<ToolExecutionError>,
126}
127
128impl ToolExecutionOutcome {
129    #[must_use]
130    pub fn success(tool_name: impl Into<String>, attempts: u32, output: Value) -> Self {
131        Self {
132            tool_name: tool_name.into(),
133            attempts,
134            output: Some(output),
135            error: None,
136        }
137    }
138
139    #[must_use]
140    pub fn failure(tool_name: impl Into<String>, attempts: u32, error: ToolExecutionError) -> Self {
141        Self {
142            tool_name: tool_name.into(),
143            attempts,
144            output: None,
145            error: Some(error),
146        }
147    }
148
149    #[must_use]
150    pub fn is_success(&self) -> bool {
151        self.error.is_none()
152    }
153}