Skip to main content

opendev_repl/handlers/
traits.rs

1//! Core traits for tool handler middleware.
2
3use std::collections::HashMap;
4
5use serde_json::Value;
6
7/// Result of a pre-execution check.
8#[derive(Debug, Clone)]
9pub enum PreCheckResult {
10    /// Allow execution to proceed.
11    Allow,
12    /// Deny execution with a reason.
13    Deny(String),
14    /// Modify the arguments before execution.
15    ModifyArgs(HashMap<String, Value>),
16}
17
18/// Metadata attached to a handler result.
19#[derive(Debug, Clone, Default)]
20pub struct HandlerMeta {
21    /// Files that were changed by this tool execution.
22    pub changed_files: Vec<String>,
23    /// Whether this was a background/server command.
24    pub is_background: bool,
25    /// Operation ID for audit/undo tracking.
26    pub operation_id: Option<String>,
27}
28
29/// Result of post-execution processing.
30#[derive(Debug, Clone)]
31pub struct HandlerResult {
32    /// The (potentially modified) tool output.
33    pub output: Option<String>,
34    /// The (potentially modified) error message.
35    pub error: Option<String>,
36    /// Whether the tool succeeded.
37    pub success: bool,
38    /// Handler metadata.
39    pub meta: HandlerMeta,
40}
41
42/// Trait for tool handler middleware.
43///
44/// Handlers sit between the REPL and tool execution, providing
45/// pre-check (approval), post-processing (formatting), and
46/// side-effect management (file tracking, operation logging).
47pub trait ToolHandler: Send + Sync {
48    /// Tool names this handler manages.
49    fn handles(&self) -> &[&str];
50
51    /// Pre-execution check. Called before the tool runs.
52    ///
53    /// Can approve, deny, or modify the tool call arguments.
54    fn pre_check(&self, tool_name: &str, args: &HashMap<String, Value>) -> PreCheckResult {
55        let _ = (tool_name, args);
56        PreCheckResult::Allow
57    }
58
59    /// Post-execution processing. Called after the tool runs.
60    ///
61    /// Can modify the output, attach metadata, or trigger side effects.
62    fn post_process(
63        &self,
64        tool_name: &str,
65        args: &HashMap<String, Value>,
66        output: Option<&str>,
67        error: Option<&str>,
68        success: bool,
69    ) -> HandlerResult {
70        HandlerResult {
71            output: output.map(|s| s.to_string()),
72            error: error.map(|s| s.to_string()),
73            success,
74            meta: HandlerMeta {
75                changed_files: self.extract_changed_files(tool_name, args),
76                ..Default::default()
77            },
78        }
79    }
80
81    /// Extract file paths changed by this tool (for artifact tracking).
82    fn extract_changed_files(
83        &self,
84        _tool_name: &str,
85        _args: &HashMap<String, Value>,
86    ) -> Vec<String> {
87        Vec::new()
88    }
89}
90
91#[cfg(test)]
92#[path = "traits_tests.rs"]
93mod tests;