Cargo.lock π
@@ -346,6 +346,7 @@ dependencies = [
"ctor",
"editor",
"env_logger",
+ "feature_flags",
"file_icons",
"fs",
"futures 0.3.28",
Nathan Sobo created
This is still pretty raw, so I'd like to hold off on shipping it to all
users.
Release Notes:
- Hide the prompt library for non-staff until it is in a more complete
state.
Cargo.lock | 1
crates/assistant/Cargo.toml | 1
crates/assistant/src/assistant_panel.rs | 75 ++++++++++++++----------
crates/client/src/user.rs | 7 +
crates/feature_flags/src/feature_flags.rs | 6 ++
5 files changed, 56 insertions(+), 34 deletions(-)
@@ -346,6 +346,7 @@ dependencies = [
"ctor",
"editor",
"env_logger",
+ "feature_flags",
"file_icons",
"fs",
"futures 0.3.28",
@@ -22,6 +22,7 @@ client.workspace = true
collections.workspace = true
command_palette_hooks.workspace = true
editor.workspace = true
+feature_flags.workspace = true
file_icons.workspace = true
fs.workspace = true
futures.workspace = true
@@ -28,6 +28,7 @@ use editor::{
ToOffset as _, ToPoint,
};
use editor::{display_map::FlapId, FoldPlaceholder};
+use feature_flags::{FeatureFlag, FeatureFlagAppExt, FeatureFlagViewExt};
use file_icons::FileIcons;
use fs::Fs;
use futures::future::Shared;
@@ -127,6 +128,12 @@ struct ActiveConversationEditor {
_subscriptions: Vec<Subscription>,
}
+struct PromptLibraryFeatureFlag;
+
+impl FeatureFlag for PromptLibraryFeatureFlag {
+ const NAME: &'static str = "prompt-library";
+}
+
impl AssistantPanel {
const INLINE_PROMPT_HISTORY_MAX_LEN: usize = 20;
@@ -152,6 +159,9 @@ impl AssistantPanel {
let workspace_handle = workspace.clone();
workspace.update(&mut cx, |workspace, cx| {
cx.new_view::<Self>(|cx| {
+ cx.observe_flag::<PromptLibraryFeatureFlag, _>(|_, _, cx| cx.notify())
+ .detach();
+
const CONVERSATION_WATCH_DURATION: Duration = Duration::from_millis(100);
let _watch_saved_conversations = cx.spawn(move |this, mut cx| async move {
let mut events = fs
@@ -1178,38 +1188,38 @@ impl AssistantPanel {
}
fn render_signed_in(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
- let header =
- TabBar::new("assistant_header")
- .start_child(h_flex().gap_1().child(self.render_popover_button(cx)))
- .children(self.active_conversation_editor().map(|editor| {
- h_flex()
- .h(rems(Tab::CONTAINER_HEIGHT_IN_REMS))
- .flex_1()
- .px_2()
- .child(Label::new(editor.read(cx).title(cx)).into_element())
- }))
- .end_child(
- h_flex()
- .gap_2()
- .when_some(self.active_conversation_editor(), |this, editor| {
- let conversation = editor.read(cx).conversation.clone();
- this.child(
- h_flex()
- .gap_1()
- .child(self.render_model(&conversation, cx))
- .children(self.render_remaining_tokens(&conversation, cx)),
- )
- .child(
- ui::Divider::vertical()
- .inset()
- .color(ui::DividerColor::Border),
- )
- })
- .child(
+ let header = TabBar::new("assistant_header")
+ .start_child(h_flex().gap_1().child(self.render_popover_button(cx)))
+ .children(self.active_conversation_editor().map(|editor| {
+ h_flex()
+ .h(rems(Tab::CONTAINER_HEIGHT_IN_REMS))
+ .flex_1()
+ .px_2()
+ .child(Label::new(editor.read(cx).title(cx)).into_element())
+ }))
+ .end_child(
+ h_flex()
+ .gap_2()
+ .when_some(self.active_conversation_editor(), |this, editor| {
+ let conversation = editor.read(cx).conversation.clone();
+ this.child(
h_flex()
.gap_1()
- .child(self.render_inject_context_menu(cx))
- .child(
+ .child(self.render_model(&conversation, cx))
+ .children(self.render_remaining_tokens(&conversation, cx)),
+ )
+ .child(
+ ui::Divider::vertical()
+ .inset()
+ .color(ui::DividerColor::Border),
+ )
+ })
+ .child(
+ h_flex()
+ .gap_1()
+ .child(self.render_inject_context_menu(cx))
+ .children(
+ cx.has_flag::<PromptLibraryFeatureFlag>().then_some(
IconButton::new("show_prompt_manager", IconName::Library)
.icon_size(IconSize::Small)
.on_click(cx.listener(|this, _event, cx| {
@@ -1217,8 +1227,9 @@ impl AssistantPanel {
}))
.tooltip(|cx| Tooltip::text("Prompt Libraryβ¦", cx)),
),
- ),
- );
+ ),
+ ),
+ );
let contents = if self.active_conversation_editor().is_some() {
let mut registrar = DivRegistrar::new(
@@ -192,10 +192,13 @@ impl UserStore {
cx.update(|cx| {
if let Some(info) = info {
- cx.update_flags(info.staff, info.flags);
+ let disable_staff = std::env::var("ZED_DISABLE_STAFF")
+ .map_or(false, |v| v != "" && v != "0");
+ let staff = info.staff && !disable_staff;
+ cx.update_flags(staff, info.flags);
client.telemetry.set_authenticated_user_info(
Some(info.metrics_id.clone()),
- info.staff,
+ staff,
)
}
})?;
@@ -14,6 +14,12 @@ impl FeatureFlags {
impl Global for FeatureFlags {}
+/// To create a feature flag, implement this trait on a trivial type and use it as
+/// a generic parameter when called [`FeatureFlagAppExt::has_flag`].
+///
+/// Feature flags are always enabled for members of Zed staff. To disable this behavior
+/// so you can test flags being disabled, set ZED_DISABLE_STAFF=1 in your environment,
+/// which will force Zed to treat the current user as non-staff.
pub trait FeatureFlag {
const NAME: &'static str;
}