Skip to repository content297 lines · 9.7 KB · rust
tenant.openagents/omega
No repository description is available.
OpenAgents Git authority 2026-07-28T01:50:17.648Z Public web read
NIP-34 coordinate
30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omegaMaintainersHidden in public view
References2 branches · 1 tag
Read-only clone
git clone https://openagents.com/git/tenant.openagents/omega.gitBrowse files
feature_flags.rs
1// Makes the derive macro's reference to `::feature_flags::FeatureFlagValue`
2// resolve when the macro is invoked inside this crate itself.
3extern crate self as feature_flags;
4
5mod flags;
6mod settings;
7mod store;
8
9use std::cell::RefCell;
10use std::rc::Rc;
11use std::sync::LazyLock;
12
13use gpui::{App, Context, Global, Subscription, Window};
14
15pub use feature_flags_macros::EnumFeatureFlag;
16pub use flags::*;
17pub use settings::{FeatureFlagsSettings, generate_feature_flags_schema};
18pub use store::*;
19
20pub static ZED_DISABLE_STAFF: LazyLock<bool> = LazyLock::new(|| {
21 std::env::var("ZED_DISABLE_STAFF").is_ok_and(|value| !value.is_empty() && value != "0")
22});
23
24impl Global for FeatureFlagStore {}
25
26pub trait FeatureFlagValue:
27 Sized + Clone + Eq + Default + std::fmt::Debug + Send + Sync + 'static
28{
29 /// Every possible value for this flag, in the order the UI should display them.
30 fn all_variants() -> &'static [Self];
31
32 /// A stable identifier for this variant used when persisting overrides.
33 fn override_key(&self) -> &'static str;
34
35 fn from_wire(wire: &str) -> Option<Self>;
36
37 /// Human-readable label for use in the configuration UI.
38 fn label(&self) -> &'static str {
39 self.override_key()
40 }
41
42 /// The variant that represents "on" — what the store resolves to when
43 /// staff rules, `enabled_for_all`, or a server announcement apply.
44 ///
45 /// For enum flags this is usually the same as [`Default::default`] (the
46 /// variant marked `#[default]` in the derive). [`PresenceFlag`] overrides
47 /// this so that `default() == Off` (the "unconfigured" state) but
48 /// `on_variant() == On` (the "enabled" state).
49 fn on_variant() -> Self {
50 Self::default()
51 }
52}
53
54/// Default value type for simple on/off feature flags.
55///
56/// The fallback value is [`PresenceFlag::Off`] so that an absent / unknown
57/// flag reads as disabled; the `on_variant` override pins the "enabled"
58/// state to [`PresenceFlag::On`] so staff / server / `enabled_for_all`
59/// resolution still lights the flag up.
60#[derive(Clone, Copy, Default, PartialEq, Eq, Debug)]
61pub enum PresenceFlag {
62 On,
63 #[default]
64 Off,
65}
66
67/// Presence flags deref to a `bool` so call sites can use `if *flag` without
68/// spelling out the enum variant — or pass them anywhere a `&bool` is wanted.
69impl std::ops::Deref for PresenceFlag {
70 type Target = bool;
71
72 fn deref(&self) -> &bool {
73 match self {
74 PresenceFlag::On => &true,
75 PresenceFlag::Off => &false,
76 }
77 }
78}
79
80impl FeatureFlagValue for PresenceFlag {
81 fn all_variants() -> &'static [Self] {
82 &[PresenceFlag::On, PresenceFlag::Off]
83 }
84
85 fn override_key(&self) -> &'static str {
86 match self {
87 PresenceFlag::On => "on",
88 PresenceFlag::Off => "off",
89 }
90 }
91
92 fn label(&self) -> &'static str {
93 match self {
94 PresenceFlag::On => "On",
95 PresenceFlag::Off => "Off",
96 }
97 }
98
99 fn from_wire(_: &str) -> Option<Self> {
100 Some(PresenceFlag::On)
101 }
102
103 fn on_variant() -> Self {
104 PresenceFlag::On
105 }
106}
107
108/// To create a feature flag, implement this trait on a trivial type and use it as
109/// a generic parameter when called [`FeatureFlagAppExt::has_flag`].
110///
111/// Feature flags are enabled for members of Zed staff by default. To disable this behavior
112/// so you can test flags being disabled, set ZED_DISABLE_STAFF=1 in your environment,
113/// which will force Zed to treat the current user as non-staff.
114pub trait FeatureFlag {
115 const NAME: &'static str;
116
117 /// The type of value this flag can hold. Use [`PresenceFlag`] for simple
118 /// on/off flags.
119 type Value: FeatureFlagValue;
120
121 /// Returns whether this feature flag is enabled for Zed staff.
122 fn enabled_for_staff() -> bool {
123 true
124 }
125
126 /// Returns whether this feature flag is enabled for everyone.
127 ///
128 /// This is generally done on the server, but we provide this as a way to entirely enable a feature flag client-side
129 /// without needing to remove all of the call sites.
130 fn enabled_for_all() -> bool {
131 false
132 }
133
134 /// Subscribes the current view to changes in the feature flag store, so
135 /// that any mutation of flags or overrides will trigger a re-render.
136 ///
137 /// The returned subscription is immediately detached; use [`observe_flag`]
138 /// directly if you need to hold onto the subscription.
139 fn watch<V: 'static>(cx: &mut Context<V>) {
140 cx.observe_global::<FeatureFlagStore>(|_, cx| cx.notify())
141 .detach();
142 }
143}
144
145pub trait FeatureFlagViewExt<V: 'static> {
146 /// Fires the callback whenever the resolved [`T::Value`] transitions.
147 fn observe_flag<T: FeatureFlag, F>(&mut self, window: &Window, callback: F) -> Subscription
148 where
149 F: Fn(T::Value, &mut V, &mut Window, &mut Context<V>) + Send + Sync + 'static;
150
151 fn when_flag_enabled<T: FeatureFlag>(
152 &mut self,
153 window: &mut Window,
154 callback: impl Fn(&mut V, &mut Window, &mut Context<V>) + Send + Sync + 'static,
155 );
156}
157
158impl<V> FeatureFlagViewExt<V> for Context<'_, V>
159where
160 V: 'static,
161{
162 fn observe_flag<T: FeatureFlag, F>(&mut self, window: &Window, callback: F) -> Subscription
163 where
164 F: Fn(T::Value, &mut V, &mut Window, &mut Context<V>) + 'static,
165 {
166 let mut last_value: Option<T::Value> = None;
167 self.observe_global_in::<FeatureFlagStore>(window, move |v, window, cx| {
168 let value = cx.flag_value::<T>();
169 if last_value.as_ref() == Some(&value) {
170 return;
171 }
172 last_value = Some(value.clone());
173 callback(value, v, window, cx);
174 })
175 }
176
177 fn when_flag_enabled<T: FeatureFlag>(
178 &mut self,
179 window: &mut Window,
180 callback: impl Fn(&mut V, &mut Window, &mut Context<V>) + Send + Sync + 'static,
181 ) {
182 if self
183 .try_global::<FeatureFlagStore>()
184 .is_some_and(|f| f.has_flag::<T>(self))
185 {
186 self.defer_in(window, move |view, window, cx| {
187 callback(view, window, cx);
188 });
189 return;
190 }
191 let subscription = Rc::new(RefCell::new(None));
192 let inner = self.observe_global_in::<FeatureFlagStore>(window, {
193 let subscription = subscription.clone();
194 move |v, window, cx| {
195 let has_flag = cx.global::<FeatureFlagStore>().has_flag::<T>(cx);
196 if has_flag {
197 callback(v, window, cx);
198 subscription.take();
199 }
200 }
201 });
202 subscription.borrow_mut().replace(inner);
203 }
204}
205
206#[derive(Debug)]
207pub struct OnFlagsReady {
208 pub is_staff: bool,
209}
210
211pub trait FeatureFlagAppExt {
212 fn update_flags(&mut self, staff: bool, flags: Vec<String>);
213 fn set_staff(&mut self, staff: bool);
214 fn has_flag<T: FeatureFlag>(&self) -> bool;
215 fn flag_value<T: FeatureFlag>(&self) -> T::Value;
216 fn is_staff(&self) -> bool;
217
218 /// Whether feature flag overrides from settings are honored for the
219 /// current user. Overrides are a staff-only affordance.
220 fn feature_flag_overrides_enabled(&self) -> bool;
221
222 fn on_flags_ready<F>(&mut self, callback: F) -> Subscription
223 where
224 F: FnMut(OnFlagsReady, &mut App) + 'static;
225
226 fn observe_flag<T: FeatureFlag, F>(&mut self, callback: F) -> Subscription
227 where
228 F: FnMut(T::Value, &mut App) + 'static;
229}
230
231impl FeatureFlagAppExt for App {
232 fn update_flags(&mut self, staff: bool, flags: Vec<String>) {
233 let store = self.default_global::<FeatureFlagStore>();
234 store.update_server_flags(staff, flags);
235 }
236
237 fn set_staff(&mut self, staff: bool) {
238 let store = self.default_global::<FeatureFlagStore>();
239 store.set_staff(staff);
240 }
241
242 fn has_flag<T: FeatureFlag>(&self) -> bool {
243 self.try_global::<FeatureFlagStore>()
244 .map(|store| store.has_flag::<T>(self))
245 .unwrap_or_else(|| FeatureFlagStore::has_flag_default::<T>())
246 }
247
248 fn flag_value<T: FeatureFlag>(&self) -> T::Value {
249 self.try_global::<FeatureFlagStore>()
250 .and_then(|store| store.try_flag_value::<T>(self))
251 .unwrap_or_default()
252 }
253
254 fn is_staff(&self) -> bool {
255 self.try_global::<FeatureFlagStore>()
256 .map(|store| store.is_staff())
257 .unwrap_or(false)
258 }
259
260 fn feature_flag_overrides_enabled(&self) -> bool {
261 self.try_global::<FeatureFlagStore>()
262 .map_or(false, |store| store.overrides_enabled())
263 }
264
265 fn on_flags_ready<F>(&mut self, mut callback: F) -> Subscription
266 where
267 F: FnMut(OnFlagsReady, &mut App) + 'static,
268 {
269 self.observe_global::<FeatureFlagStore>(move |cx| {
270 let store = cx.global::<FeatureFlagStore>();
271 if store.server_flags_received() {
272 callback(
273 OnFlagsReady {
274 is_staff: store.is_staff(),
275 },
276 cx,
277 );
278 }
279 })
280 }
281
282 fn observe_flag<T: FeatureFlag, F>(&mut self, mut callback: F) -> Subscription
283 where
284 F: FnMut(T::Value, &mut App) + 'static,
285 {
286 let mut last_value: Option<T::Value> = None;
287 self.observe_global::<FeatureFlagStore>(move |cx| {
288 let value = cx.flag_value::<T>();
289 if last_value.as_ref() == Some(&value) {
290 return;
291 }
292 last_value = Some(value.clone());
293 callback(value, cx);
294 })
295 }
296}
297