Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T03:53:56.615Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

workspace_error.rs

205 lines · 5.3 KB · rust
1use std::{sync::Arc, time::Duration};
2
3use gpui::{Action, SharedString};
4use ui::{IconName, IconPosition};
5use zed_actions::OpenBrowser;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ErrorSeverity {
9    Critical,
10    Error,
11    Warning,
12}
13
14impl ErrorSeverity {
15    pub fn auto_dismiss_delay(&self) -> Option<Duration> {
16        match self {
17            ErrorSeverity::Critical => None,
18            ErrorSeverity::Error => Some(Duration::from_secs(30)),
19            ErrorSeverity::Warning => Some(Duration::from_secs(20)),
20        }
21    }
22}
23
24/// The behavior triggered when the user invokes an [`ErrorAction`].
25pub enum ErrorActionHandler {
26    /// Run the provided callback when the action is invoked.
27    /// The notification is still dismissed afterwards by the button's click handler.
28    Action(Box<dyn Action>),
29    /// Dismiss the notification without running any extra logic.
30    Dismiss,
31}
32
33/// An icon to display on an action button, with its position relative to the label.
34///
35/// Bundled together so the position is only carried around when an icon is actually set
36/// — there's no meaningful "position" without an icon to position.
37#[derive(Debug, Clone, Copy)]
38pub struct ActionIcon {
39    pub name: IconName,
40    pub position: IconPosition,
41}
42
43impl ActionIcon {
44    /// Show `name` at the start (left) of the action button label.
45    pub fn start(name: IconName) -> Self {
46        Self {
47            name,
48            position: IconPosition::Start,
49        }
50    }
51
52    /// Show `name` at the end (right) of the action button label.
53    pub fn end(name: IconName) -> Self {
54        Self {
55            name,
56            position: IconPosition::End,
57        }
58    }
59}
60
61pub struct ErrorAction {
62    pub label: SharedString,
63    pub icon: Option<ActionIcon>,
64    pub tooltip: Option<SharedString>,
65    pub handler: ErrorActionHandler,
66}
67
68impl ErrorAction {
69    pub fn new<A: Action + 'static>(label: impl Into<SharedString>, handler: A) -> Self {
70        Self {
71            label: label.into(),
72            icon: None,
73            tooltip: None,
74            handler: ErrorActionHandler::Action(Box::new(handler)),
75        }
76    }
77
78    /// Creates a dismiss-only action labelled "Dismiss".
79    ///
80    /// Useful as a sensible default for [`WorkspaceError::primary_action`] when the error has no
81    /// recovery affordance beyond closing the notification.
82    pub fn dismiss() -> Self {
83        Self {
84            label: "Dismiss".into(),
85            icon: None,
86            tooltip: None,
87            handler: ErrorActionHandler::Dismiss,
88        }
89    }
90
91    /// Show `icon` at the start (left) of the action button label.
92    pub fn with_icon(mut self, icon: IconName) -> Self {
93        self.icon = Some(ActionIcon::start(icon));
94        self
95    }
96
97    /// Show `icon` at the end (right) of the action button label.
98    ///
99    /// Useful for actions that navigate the user elsewhere — for example the trailing
100    /// `⇗` produced by [`Self::link`].
101    pub fn with_end_icon(mut self, icon: IconName) -> Self {
102        self.icon = Some(ActionIcon::end(icon));
103        self
104    }
105
106    pub fn with_tooltip(mut self, tooltip: impl Into<SharedString>) -> Self {
107        self.tooltip = Some(tooltip.into());
108        self
109    }
110
111    pub fn link(label: impl Into<SharedString>, url: impl Into<Arc<str>>) -> Self {
112        Self::new(label, OpenBrowser { url: url.into() }).with_end_icon(IconName::ArrowUpRight)
113    }
114}
115
116pub trait WorkspaceError {
117    fn primary_message(&self) -> SharedString;
118
119    fn secondary_message(&self) -> Option<SharedString> {
120        None
121    }
122
123    /// The primary action shown in the error notification.
124    ///
125    /// If in doubt, use [`ErrorAction::dismiss`].
126    fn primary_action(&self) -> ErrorAction;
127
128    fn secondary_action(&self) -> Option<ErrorAction> {
129        None
130    }
131
132    fn severity(&self) -> ErrorSeverity;
133}
134
135impl WorkspaceError for &'static str {
136    fn primary_message(&self) -> SharedString {
137        self.to_string().into()
138    }
139
140    fn primary_action(&self) -> ErrorAction {
141        ErrorAction::dismiss()
142    }
143
144    fn severity(&self) -> ErrorSeverity {
145        ErrorSeverity::Critical
146    }
147}
148
149impl WorkspaceError for String {
150    fn primary_message(&self) -> SharedString {
151        self.clone().into()
152    }
153
154    fn primary_action(&self) -> ErrorAction {
155        ErrorAction::dismiss()
156    }
157
158    fn severity(&self) -> ErrorSeverity {
159        ErrorSeverity::Critical
160    }
161}
162
163impl WorkspaceError for anyhow::Error {
164    fn primary_message(&self) -> SharedString {
165        format!("{self}").into()
166    }
167
168    fn primary_action(&self) -> ErrorAction {
169        ErrorAction::dismiss()
170    }
171
172    fn severity(&self) -> ErrorSeverity {
173        ErrorSeverity::Critical
174    }
175}
176
177pub struct PortalError {
178    message: String,
179}
180
181impl PortalError {
182    pub fn new(message: impl Into<String>) -> Self {
183        Self {
184            message: message.into(),
185        }
186    }
187}
188
189impl WorkspaceError for PortalError {
190    fn primary_message(&self) -> SharedString {
191        self.message.clone().into()
192    }
193
194    fn severity(&self) -> ErrorSeverity {
195        ErrorSeverity::Critical
196    }
197
198    fn primary_action(&self) -> ErrorAction {
199        ErrorAction::link(
200            "See docs",
201            "https://github.com/OpenAgentsInc/omega#readme",
202        )
203    }
204}
205
Served at tenant.openagents/omega Member data and write actions are omitted.