vtcode_commons/
errors.rs

1use std::borrow::Cow;
2
3use anyhow::{Error, Result};
4
5/// Formats an error into a user-facing description. This allows extracted
6/// components to present consistent error messaging without depending on the
7/// CLI presentation layer.
8pub trait ErrorFormatter: Send + Sync {
9    /// Render the error into a user-facing string.
10    fn format_error(&self, error: &Error) -> Cow<'_, str>;
11}
12
13/// Reports non-fatal errors to an observability backend.
14pub trait ErrorReporter: Send + Sync {
15    /// Capture the provided error for later inspection.
16    fn capture(&self, error: &Error) -> Result<()>;
17
18    /// Convenience helper to capture a simple message.
19    fn capture_message(&self, message: impl Into<Cow<'static, str>>) -> Result<()> {
20        let message: Cow<'static, str> = message.into();
21        self.capture(&Error::msg(message))
22    }
23}
24
25/// Error reporting implementation that drops every event. Useful for tests or
26/// when a consumer does not yet integrate with error monitoring.
27#[derive(Debug, Default, Clone, Copy)]
28pub struct NoopErrorReporter;
29
30impl ErrorReporter for NoopErrorReporter {
31    fn capture(&self, _error: &Error) -> Result<()> {
32        Ok(())
33    }
34}
35
36/// Default formatter that surfaces the error's display output.
37#[derive(Debug, Default, Clone, Copy)]
38pub struct DisplayErrorFormatter;
39
40impl ErrorFormatter for DisplayErrorFormatter {
41    fn format_error(&self, error: &Error) -> Cow<'_, str> {
42        Cow::Owned(format!("{error}"))
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn formatter_uses_display() {
52        let formatter = DisplayErrorFormatter;
53        let error = Error::msg("test error");
54        assert_eq!(formatter.format_error(&error), "test error");
55    }
56
57    #[test]
58    fn noop_reporter_drops_errors() {
59        let reporter = NoopErrorReporter;
60        let error = Error::msg("test");
61        assert!(reporter.capture(&error).is_ok());
62        assert!(reporter.capture_message("message").is_ok());
63    }
64}