Cargo.lock 🔗
@@ -318,6 +318,7 @@ dependencies = [
"chrono",
"client",
"collections",
+ "command_palette_hooks",
"ctor",
"editor",
"env_logger",
Marshall Bowers created
This PR adds a new `assistant.enabled` setting that controls whether the
Zed Assistant is enabled.
Some users have requested the ability to disable the AI-related features
in Zed if they don't use them. Changing `assistant.enabled` to `false`
will hide the Assistant icon in the status bar (taking priority over the
`assistant.button` setting) as well as filter out the `assistant:`
actions.
The Assistant is enabled by default.
Release Notes:
- Added an `assistant.enabled` setting to control whether the Assistant
is enabled.
Cargo.lock | 1
assets/settings/default.json | 2
crates/assistant/Cargo.toml | 1
crates/assistant/src/assistant.rs | 56 +++++++++++++++++++++
crates/assistant/src/assistant_panel.rs | 17 ++++++
crates/assistant/src/assistant_settings.rs | 59 ++++++++++-------------
crates/zed/src/zed.rs | 1
7 files changed, 100 insertions(+), 37 deletions(-)
@@ -318,6 +318,7 @@ dependencies = [
"chrono",
"client",
"collections",
+ "command_palette_hooks",
"ctor",
"editor",
"env_logger",
@@ -245,6 +245,8 @@
"assistant": {
// Version of this setting.
"version": "1",
+ // Whether the assistant is enabled.
+ "enabled": true,
// Whether to show the assistant panel button in the status bar.
"button": true,
// Where to dock the assistant panel. Can be 'left', 'right' or 'bottom'.
@@ -14,6 +14,7 @@ anyhow.workspace = true
chrono.workspace = true
client.workspace = true
collections.workspace = true
+command_palette_hooks.workspace = true
editor.workspace = true
fs.workspace = true
futures.workspace = true
@@ -10,11 +10,12 @@ pub use assistant_panel::AssistantPanel;
use assistant_settings::{AssistantSettings, OpenAiModel, ZedDotDevModel};
use chrono::{DateTime, Local};
use client::{proto, Client};
+use command_palette_hooks::CommandPaletteFilter;
pub(crate) use completion_provider::*;
-use gpui::{actions, AppContext, SharedString};
+use gpui::{actions, AppContext, Global, SharedString};
pub(crate) use saved_conversation::*;
use serde::{Deserialize, Serialize};
-use settings::Settings;
+use settings::{Settings, SettingsStore};
use std::{
fmt::{self, Display},
sync::Arc,
@@ -182,10 +183,61 @@ enum MessageStatus {
Error(SharedString),
}
+/// The state pertaining to the Assistant.
+#[derive(Default)]
+struct Assistant {
+ /// Whether the Assistant is enabled.
+ enabled: bool,
+}
+
+impl Global for Assistant {}
+
+impl Assistant {
+ const NAMESPACE: &'static str = "assistant";
+
+ fn set_enabled(&mut self, enabled: bool, cx: &mut AppContext) {
+ if self.enabled == enabled {
+ return;
+ }
+
+ self.enabled = enabled;
+
+ if !enabled {
+ CommandPaletteFilter::update_global(cx, |filter, _cx| {
+ filter.hide_namespace(Self::NAMESPACE);
+ });
+
+ return;
+ }
+
+ CommandPaletteFilter::update_global(cx, |filter, _cx| {
+ filter.show_namespace(Self::NAMESPACE);
+ });
+ }
+}
+
pub fn init(client: Arc<Client>, cx: &mut AppContext) {
+ cx.set_global(Assistant::default());
AssistantSettings::register(cx);
completion_provider::init(client, cx);
assistant_panel::init(cx);
+
+ CommandPaletteFilter::update_global(cx, |filter, _cx| {
+ filter.hide_namespace(Assistant::NAMESPACE);
+ });
+ cx.update_global(|assistant: &mut Assistant, cx: &mut AppContext| {
+ let settings = AssistantSettings::get_global(cx);
+
+ assistant.set_enabled(settings.enabled, cx);
+ });
+ cx.observe_global::<SettingsStore>(|cx| {
+ cx.update_global(|assistant: &mut Assistant, cx: &mut AppContext| {
+ let settings = AssistantSettings::get_global(cx);
+
+ assistant.set_enabled(settings.enabled, cx);
+ });
+ })
+ .detach();
}
#[cfg(test)]
@@ -55,6 +55,11 @@ pub fn init(cx: &mut AppContext) {
|workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
workspace
.register_action(|workspace, _: &ToggleFocus, cx| {
+ let settings = AssistantSettings::get_global(cx);
+ if !settings.enabled {
+ return;
+ }
+
workspace.toggle_panel_focus::<AssistantPanel>(cx);
})
.register_action(AssistantPanel::inline_assist)
@@ -229,6 +234,11 @@ impl AssistantPanel {
_: &InlineAssist,
cx: &mut ViewContext<Workspace>,
) {
+ let settings = AssistantSettings::get_global(cx);
+ if !settings.enabled {
+ return;
+ }
+
let Some(assistant) = workspace.panel::<AssistantPanel>(cx) else {
return;
};
@@ -1217,7 +1227,12 @@ impl Panel for AssistantPanel {
}
fn icon(&self, cx: &WindowContext) -> Option<IconName> {
- Some(IconName::Ai).filter(|_| AssistantSettings::get_global(cx).button)
+ let settings = AssistantSettings::get_global(cx);
+ if !settings.enabled || !settings.button {
+ return None;
+ }
+
+ Some(IconName::Ai)
}
fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
@@ -160,6 +160,7 @@ fn open_ai_url() -> String {
#[derive(Default, Debug, Deserialize, Serialize)]
pub struct AssistantSettings {
+ pub enabled: bool,
pub button: bool,
pub dock: AssistantDockPosition,
pub default_width: Pixels,
@@ -201,42 +202,26 @@ impl AssistantSettingsContent {
AssistantSettingsContent::Versioned(settings) => match settings {
VersionedAssistantSettingsContent::V1(settings) => settings.clone(),
},
- AssistantSettingsContent::Legacy(settings) => {
- if let Some(open_ai_api_url) = settings.openai_api_url.as_ref() {
- AssistantSettingsContentV1 {
- button: settings.button,
- dock: settings.dock,
- default_width: settings.default_width,
- default_height: settings.default_height,
- provider: Some(AssistantProvider::OpenAi {
- default_model: settings
- .default_open_ai_model
- .clone()
- .unwrap_or_default(),
- api_url: open_ai_api_url.clone(),
- }),
- }
- } else if let Some(open_ai_model) = settings.default_open_ai_model.clone() {
- AssistantSettingsContentV1 {
- button: settings.button,
- dock: settings.dock,
- default_width: settings.default_width,
- default_height: settings.default_height,
- provider: Some(AssistantProvider::OpenAi {
+ AssistantSettingsContent::Legacy(settings) => AssistantSettingsContentV1 {
+ enabled: None,
+ button: settings.button,
+ dock: settings.dock,
+ default_width: settings.default_width,
+ default_height: settings.default_height,
+ provider: if let Some(open_ai_api_url) = settings.openai_api_url.as_ref() {
+ Some(AssistantProvider::OpenAi {
+ default_model: settings.default_open_ai_model.clone().unwrap_or_default(),
+ api_url: open_ai_api_url.clone(),
+ })
+ } else {
+ settings.default_open_ai_model.clone().map(|open_ai_model| {
+ AssistantProvider::OpenAi {
default_model: open_ai_model,
api_url: open_ai_url(),
- }),
- }
- } else {
- AssistantSettingsContentV1 {
- button: settings.button,
- dock: settings.dock,
- default_width: settings.default_width,
- default_height: settings.default_height,
- provider: None,
- }
- }
- }
+ }
+ })
+ },
+ },
}
}
@@ -264,6 +249,7 @@ pub enum VersionedAssistantSettingsContent {
impl Default for VersionedAssistantSettingsContent {
fn default() -> Self {
Self::V1(AssistantSettingsContentV1 {
+ enabled: None,
button: None,
dock: None,
default_width: None,
@@ -275,6 +261,10 @@ impl Default for VersionedAssistantSettingsContent {
#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug)]
pub struct AssistantSettingsContentV1 {
+ /// Whether the Assistant is enabled.
+ ///
+ /// Default: true
+ enabled: Option<bool>,
/// Whether to show the assistant panel button in the status bar.
///
/// Default: true
@@ -340,6 +330,7 @@ impl Settings for AssistantSettings {
for value in [default_value].iter().chain(user_values) {
let value = value.upgrade();
+ merge(&mut settings.enabled, value.enabled);
merge(&mut settings.button, value.button);
merge(&mut settings.dock, value.dock);
merge(
@@ -3073,6 +3073,7 @@ mod tests {
notifications::init(app_state.client.clone(), app_state.user_store.clone(), cx);
workspace::init(app_state.clone(), cx);
Project::init_settings(cx);
+ command_palette::init(cx);
language::init(cx);
editor::init(cx);
project_panel::init_settings(cx);