Add setting to disable all AI features (#34896)
https://github.com/user-attachments/assets/674bba41-40ac-4a98-99e4-0b47f9097b6a Release Notes: - Added setting to disable all AI features
This commit is contained in:
parent
939f9fffa3
commit
96f9942791
19 changed files with 308 additions and 68 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -210,6 +210,7 @@ dependencies = [
|
|||
"chrono",
|
||||
"client",
|
||||
"collections",
|
||||
"command_palette_hooks",
|
||||
"component",
|
||||
"context_server",
|
||||
"db",
|
||||
|
@ -6360,6 +6361,7 @@ dependencies = [
|
|||
"buffer_diff",
|
||||
"call",
|
||||
"chrono",
|
||||
"client",
|
||||
"collections",
|
||||
"command_palette_hooks",
|
||||
"component",
|
||||
|
|
|
@ -1076,6 +1076,10 @@
|
|||
// Send anonymized usage data like what languages you're using Zed with.
|
||||
"metrics": true
|
||||
},
|
||||
// Whether to disable all AI features in Zed.
|
||||
//
|
||||
// Default: false
|
||||
"disable_ai": false,
|
||||
// Automatically update Zed. This setting may be ignored on Linux if
|
||||
// installed through a package manager.
|
||||
"auto_update": true,
|
||||
|
|
|
@ -32,6 +32,7 @@ buffer_diff.workspace = true
|
|||
chrono.workspace = true
|
||||
client.workspace = true
|
||||
collections.workspace = true
|
||||
command_palette_hooks.workspace = true
|
||||
component.workspace = true
|
||||
context_server.workspace = true
|
||||
db.workspace = true
|
||||
|
|
|
@ -43,7 +43,7 @@ use anyhow::{Result, anyhow};
|
|||
use assistant_context::{AssistantContext, ContextEvent, ContextSummary};
|
||||
use assistant_slash_command::SlashCommandWorkingSet;
|
||||
use assistant_tool::ToolWorkingSet;
|
||||
use client::{UserStore, zed_urls};
|
||||
use client::{DisableAiSettings, UserStore, zed_urls};
|
||||
use editor::{Anchor, AnchorRangeExt as _, Editor, EditorEvent, MultiBuffer};
|
||||
use feature_flags::{self, FeatureFlagAppExt};
|
||||
use fs::Fs;
|
||||
|
@ -744,6 +744,7 @@ impl AgentPanel {
|
|||
if workspace
|
||||
.panel::<Self>(cx)
|
||||
.is_some_and(|panel| panel.read(cx).enabled(cx))
|
||||
&& !DisableAiSettings::get_global(cx).disable_ai
|
||||
{
|
||||
workspace.toggle_panel_focus::<Self>(window, cx);
|
||||
}
|
||||
|
@ -1665,7 +1666,10 @@ impl Panel for AgentPanel {
|
|||
}
|
||||
|
||||
fn icon(&self, _window: &Window, cx: &App) -> Option<IconName> {
|
||||
(self.enabled(cx) && AgentSettings::get_global(cx).button).then_some(IconName::ZedAssistant)
|
||||
(self.enabled(cx)
|
||||
&& AgentSettings::get_global(cx).button
|
||||
&& !DisableAiSettings::get_global(cx).disable_ai)
|
||||
.then_some(IconName::ZedAssistant)
|
||||
}
|
||||
|
||||
fn icon_tooltip(&self, _window: &Window, _cx: &App) -> Option<&'static str> {
|
||||
|
|
|
@ -31,7 +31,8 @@ use std::sync::Arc;
|
|||
use agent::{Thread, ThreadId};
|
||||
use agent_settings::{AgentProfileId, AgentSettings, LanguageModelSelection};
|
||||
use assistant_slash_command::SlashCommandRegistry;
|
||||
use client::Client;
|
||||
use client::{Client, DisableAiSettings};
|
||||
use command_palette_hooks::CommandPaletteFilter;
|
||||
use feature_flags::FeatureFlagAppExt as _;
|
||||
use fs::Fs;
|
||||
use gpui::{Action, App, Entity, actions};
|
||||
|
@ -43,6 +44,7 @@ use prompt_store::PromptBuilder;
|
|||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{Settings as _, SettingsStore};
|
||||
use std::any::TypeId;
|
||||
|
||||
pub use crate::active_thread::ActiveThread;
|
||||
use crate::agent_configuration::{ConfigureContextServerModal, ManageProfilesModal};
|
||||
|
@ -52,6 +54,7 @@ use crate::slash_command_settings::SlashCommandSettings;
|
|||
pub use agent_diff::{AgentDiffPane, AgentDiffToolbar};
|
||||
pub use text_thread_editor::{AgentPanelDelegate, TextThreadEditor};
|
||||
pub use ui::preview::{all_agent_previews, get_agent_preview};
|
||||
use zed_actions;
|
||||
|
||||
actions!(
|
||||
agent,
|
||||
|
@ -241,6 +244,66 @@ pub fn init(
|
|||
})
|
||||
.detach();
|
||||
cx.observe_new(ManageProfilesModal::register).detach();
|
||||
|
||||
// Update command palette filter based on AI settings
|
||||
update_command_palette_filter(cx);
|
||||
|
||||
// Watch for settings changes
|
||||
cx.observe_global::<SettingsStore>(|app_cx| {
|
||||
// When settings change, update the command palette filter
|
||||
update_command_palette_filter(app_cx);
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
fn update_command_palette_filter(cx: &mut App) {
|
||||
let disable_ai = DisableAiSettings::get_global(cx).disable_ai;
|
||||
CommandPaletteFilter::update_global(cx, |filter, _| {
|
||||
if disable_ai {
|
||||
filter.hide_namespace("agent");
|
||||
filter.hide_namespace("assistant");
|
||||
filter.hide_namespace("zed_predict_onboarding");
|
||||
filter.hide_namespace("edit_prediction");
|
||||
|
||||
use editor::actions::{
|
||||
AcceptEditPrediction, AcceptPartialEditPrediction, NextEditPrediction,
|
||||
PreviousEditPrediction, ShowEditPrediction, ToggleEditPrediction,
|
||||
};
|
||||
let edit_prediction_actions = [
|
||||
TypeId::of::<AcceptEditPrediction>(),
|
||||
TypeId::of::<AcceptPartialEditPrediction>(),
|
||||
TypeId::of::<ShowEditPrediction>(),
|
||||
TypeId::of::<NextEditPrediction>(),
|
||||
TypeId::of::<PreviousEditPrediction>(),
|
||||
TypeId::of::<ToggleEditPrediction>(),
|
||||
];
|
||||
filter.hide_action_types(&edit_prediction_actions);
|
||||
filter.hide_action_types(&[TypeId::of::<zed_actions::OpenZedPredictOnboarding>()]);
|
||||
} else {
|
||||
filter.show_namespace("agent");
|
||||
filter.show_namespace("assistant");
|
||||
filter.show_namespace("zed_predict_onboarding");
|
||||
|
||||
filter.show_namespace("edit_prediction");
|
||||
|
||||
use editor::actions::{
|
||||
AcceptEditPrediction, AcceptPartialEditPrediction, NextEditPrediction,
|
||||
PreviousEditPrediction, ShowEditPrediction, ToggleEditPrediction,
|
||||
};
|
||||
let edit_prediction_actions = [
|
||||
TypeId::of::<AcceptEditPrediction>(),
|
||||
TypeId::of::<AcceptPartialEditPrediction>(),
|
||||
TypeId::of::<ShowEditPrediction>(),
|
||||
TypeId::of::<NextEditPrediction>(),
|
||||
TypeId::of::<PreviousEditPrediction>(),
|
||||
TypeId::of::<ToggleEditPrediction>(),
|
||||
];
|
||||
filter.show_action_types(edit_prediction_actions.iter());
|
||||
|
||||
filter
|
||||
.show_action_types([TypeId::of::<zed_actions::OpenZedPredictOnboarding>()].iter());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn init_language_model_settings(cx: &mut App) {
|
||||
|
|
|
@ -16,7 +16,7 @@ use agent::{
|
|||
};
|
||||
use agent_settings::AgentSettings;
|
||||
use anyhow::{Context as _, Result};
|
||||
use client::telemetry::Telemetry;
|
||||
use client::{DisableAiSettings, telemetry::Telemetry};
|
||||
use collections::{HashMap, HashSet, VecDeque, hash_map};
|
||||
use editor::SelectionEffects;
|
||||
use editor::{
|
||||
|
@ -57,6 +57,17 @@ pub fn init(
|
|||
cx: &mut App,
|
||||
) {
|
||||
cx.set_global(InlineAssistant::new(fs, prompt_builder, telemetry));
|
||||
|
||||
cx.observe_global::<SettingsStore>(|cx| {
|
||||
if DisableAiSettings::get_global(cx).disable_ai {
|
||||
// Hide any active inline assist UI when AI is disabled
|
||||
InlineAssistant::update_global(cx, |assistant, cx| {
|
||||
assistant.cancel_all_active_completions(cx);
|
||||
});
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.observe_new(|_workspace: &mut Workspace, window, cx| {
|
||||
let Some(window) = window else {
|
||||
return;
|
||||
|
@ -141,6 +152,26 @@ impl InlineAssistant {
|
|||
.detach();
|
||||
}
|
||||
|
||||
/// Hides all active inline assists when AI is disabled
|
||||
pub fn cancel_all_active_completions(&mut self, cx: &mut App) {
|
||||
// Cancel all active completions in editors
|
||||
for (editor_handle, _) in self.assists_by_editor.iter() {
|
||||
if let Some(editor) = editor_handle.upgrade() {
|
||||
let windows = cx.windows();
|
||||
if !windows.is_empty() {
|
||||
let window = windows[0];
|
||||
let _ = window.update(cx, |_, window, cx| {
|
||||
editor.update(cx, |editor, cx| {
|
||||
if editor.has_active_inline_completion() {
|
||||
editor.cancel(&Default::default(), window, cx);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_workspace_event(
|
||||
&mut self,
|
||||
workspace: Entity<Workspace>,
|
||||
|
@ -176,7 +207,7 @@ impl InlineAssistant {
|
|||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
let is_assistant2_enabled = true;
|
||||
let is_assistant2_enabled = !DisableAiSettings::get_global(cx).disable_ai;
|
||||
|
||||
if let Some(editor) = item.act_as::<Editor>(cx) {
|
||||
editor.update(cx, |editor, cx| {
|
||||
|
@ -199,6 +230,13 @@ impl InlineAssistant {
|
|||
cx,
|
||||
);
|
||||
|
||||
if DisableAiSettings::get_global(cx).disable_ai {
|
||||
// Cancel any active completions
|
||||
if editor.has_active_inline_completion() {
|
||||
editor.cancel(&Default::default(), window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the Assistant1 code action provider, as it still might be registered.
|
||||
editor.remove_code_action_provider("assistant".into(), window, cx);
|
||||
} else {
|
||||
|
@ -219,7 +257,7 @@ impl InlineAssistant {
|
|||
cx: &mut Context<Workspace>,
|
||||
) {
|
||||
let settings = AgentSettings::get_global(cx);
|
||||
if !settings.enabled {
|
||||
if !settings.enabled || DisableAiSettings::get_global(cx).disable_ai {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ anyhow.workspace = true
|
|||
assistant_tool.workspace = true
|
||||
buffer_diff.workspace = true
|
||||
chrono.workspace = true
|
||||
client.workspace = true
|
||||
collections.workspace = true
|
||||
component.workspace = true
|
||||
derive_more.workspace = true
|
||||
|
|
|
@ -20,14 +20,13 @@ mod thinking_tool;
|
|||
mod ui;
|
||||
mod web_search_tool;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use assistant_tool::ToolRegistry;
|
||||
use copy_path_tool::CopyPathTool;
|
||||
use gpui::{App, Entity};
|
||||
use http_client::HttpClientWithUrl;
|
||||
use language_model::LanguageModelRegistry;
|
||||
use move_path_tool::MovePathTool;
|
||||
use std::sync::Arc;
|
||||
use web_search_tool::WebSearchTool;
|
||||
|
||||
pub(crate) use templates::*;
|
||||
|
|
|
@ -151,6 +151,7 @@ impl Settings for ProxySettings {
|
|||
|
||||
pub fn init_settings(cx: &mut App) {
|
||||
TelemetrySettings::register(cx);
|
||||
DisableAiSettings::register(cx);
|
||||
ClientSettings::register(cx);
|
||||
ProxySettings::register(cx);
|
||||
}
|
||||
|
@ -548,6 +549,33 @@ impl settings::Settings for TelemetrySettings {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether to disable all AI features in Zed.
|
||||
///
|
||||
/// Default: false
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct DisableAiSettings {
|
||||
pub disable_ai: bool,
|
||||
}
|
||||
|
||||
impl settings::Settings for DisableAiSettings {
|
||||
const KEY: Option<&'static str> = Some("disable_ai");
|
||||
|
||||
type FileContent = Option<bool>;
|
||||
|
||||
fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
|
||||
Ok(Self {
|
||||
disable_ai: sources
|
||||
.user
|
||||
.or(sources.server)
|
||||
.copied()
|
||||
.flatten()
|
||||
.unwrap_or(sources.default.ok_or_else(Self::missing_default)?),
|
||||
})
|
||||
}
|
||||
|
||||
fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {}
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn new(
|
||||
clock: Arc<dyn SystemClock>,
|
||||
|
|
|
@ -6,6 +6,7 @@ mod sign_in;
|
|||
use crate::sign_in::initiate_sign_in_within_workspace;
|
||||
use ::fs::Fs;
|
||||
use anyhow::{Context as _, Result, anyhow};
|
||||
use client::DisableAiSettings;
|
||||
use collections::{HashMap, HashSet};
|
||||
use command_palette_hooks::CommandPaletteFilter;
|
||||
use futures::{Future, FutureExt, TryFutureExt, channel::oneshot, future::Shared};
|
||||
|
@ -25,6 +26,7 @@ use node_runtime::NodeRuntime;
|
|||
use parking_lot::Mutex;
|
||||
use request::StatusNotification;
|
||||
use serde_json::json;
|
||||
use settings::Settings;
|
||||
use settings::SettingsStore;
|
||||
use sign_in::{reinstall_and_sign_in_within_workspace, sign_out_within_workspace};
|
||||
use std::collections::hash_map::Entry;
|
||||
|
@ -93,26 +95,34 @@ pub fn init(
|
|||
let copilot_auth_action_types = [TypeId::of::<SignOut>()];
|
||||
let copilot_no_auth_action_types = [TypeId::of::<SignIn>()];
|
||||
let status = handle.read(cx).status();
|
||||
|
||||
let is_ai_disabled = DisableAiSettings::get_global(cx).disable_ai;
|
||||
let filter = CommandPaletteFilter::global_mut(cx);
|
||||
|
||||
match status {
|
||||
Status::Disabled => {
|
||||
filter.hide_action_types(&copilot_action_types);
|
||||
filter.hide_action_types(&copilot_auth_action_types);
|
||||
filter.hide_action_types(&copilot_no_auth_action_types);
|
||||
}
|
||||
Status::Authorized => {
|
||||
filter.hide_action_types(&copilot_no_auth_action_types);
|
||||
filter.show_action_types(
|
||||
copilot_action_types
|
||||
.iter()
|
||||
.chain(&copilot_auth_action_types),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
filter.hide_action_types(&copilot_action_types);
|
||||
filter.hide_action_types(&copilot_auth_action_types);
|
||||
filter.show_action_types(copilot_no_auth_action_types.iter());
|
||||
if is_ai_disabled {
|
||||
filter.hide_action_types(&copilot_action_types);
|
||||
filter.hide_action_types(&copilot_auth_action_types);
|
||||
filter.hide_action_types(&copilot_no_auth_action_types);
|
||||
} else {
|
||||
match status {
|
||||
Status::Disabled => {
|
||||
filter.hide_action_types(&copilot_action_types);
|
||||
filter.hide_action_types(&copilot_auth_action_types);
|
||||
filter.hide_action_types(&copilot_no_auth_action_types);
|
||||
}
|
||||
Status::Authorized => {
|
||||
filter.hide_action_types(&copilot_no_auth_action_types);
|
||||
filter.show_action_types(
|
||||
copilot_action_types
|
||||
.iter()
|
||||
.chain(&copilot_auth_action_types),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
filter.hide_action_types(&copilot_action_types);
|
||||
filter.hide_action_types(&copilot_auth_action_types);
|
||||
filter.show_action_types(copilot_no_auth_action_types.iter());
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -23,6 +23,7 @@ askpass.workspace = true
|
|||
buffer_diff.workspace = true
|
||||
call.workspace = true
|
||||
chrono.workspace = true
|
||||
client.workspace = true
|
||||
collections.workspace = true
|
||||
command_palette_hooks.workspace = true
|
||||
component.workspace = true
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use crate::branch_picker::{self, BranchList};
|
||||
use crate::git_panel::{GitPanel, commit_message_editor};
|
||||
use client::DisableAiSettings;
|
||||
use git::repository::CommitOptions;
|
||||
use git::{Amend, Commit, GenerateCommitMessage, Signoff};
|
||||
use panel::{panel_button, panel_editor_style};
|
||||
use settings::Settings;
|
||||
use ui::{
|
||||
ContextMenu, KeybindingHint, PopoverMenu, PopoverMenuHandle, SplitButton, Tooltip, prelude::*,
|
||||
};
|
||||
|
@ -569,11 +571,13 @@ impl Render for CommitModal {
|
|||
.on_action(cx.listener(Self::dismiss))
|
||||
.on_action(cx.listener(Self::commit))
|
||||
.on_action(cx.listener(Self::amend))
|
||||
.on_action(cx.listener(|this, _: &GenerateCommitMessage, _, cx| {
|
||||
this.git_panel.update(cx, |panel, cx| {
|
||||
panel.generate_commit_message(cx);
|
||||
})
|
||||
}))
|
||||
.when(!DisableAiSettings::get_global(cx).disable_ai, |this| {
|
||||
this.on_action(cx.listener(|this, _: &GenerateCommitMessage, _, cx| {
|
||||
this.git_panel.update(cx, |panel, cx| {
|
||||
panel.generate_commit_message(cx);
|
||||
})
|
||||
}))
|
||||
})
|
||||
.on_action(
|
||||
cx.listener(|this, _: &zed_actions::git::Branch, window, cx| {
|
||||
this.toggle_branch_selector(window, cx);
|
||||
|
|
|
@ -12,6 +12,7 @@ use crate::{
|
|||
use agent_settings::AgentSettings;
|
||||
use anyhow::Context as _;
|
||||
use askpass::AskPassDelegate;
|
||||
use client::DisableAiSettings;
|
||||
use db::kvp::KEY_VALUE_STORE;
|
||||
use editor::{
|
||||
Editor, EditorElement, EditorMode, EditorSettings, MultiBuffer, ShowScrollbar,
|
||||
|
@ -53,7 +54,7 @@ use project::{
|
|||
git_store::{GitStoreEvent, Repository},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{Settings as _, SettingsStore};
|
||||
use settings::{Settings, SettingsStore};
|
||||
use std::future::Future;
|
||||
use std::ops::Range;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -464,9 +465,14 @@ impl GitPanel {
|
|||
};
|
||||
|
||||
let mut assistant_enabled = AgentSettings::get_global(cx).enabled;
|
||||
let mut was_ai_disabled = DisableAiSettings::get_global(cx).disable_ai;
|
||||
let _settings_subscription = cx.observe_global::<SettingsStore>(move |_, cx| {
|
||||
if assistant_enabled != AgentSettings::get_global(cx).enabled {
|
||||
let is_ai_disabled = DisableAiSettings::get_global(cx).disable_ai;
|
||||
if assistant_enabled != AgentSettings::get_global(cx).enabled
|
||||
|| was_ai_disabled != is_ai_disabled
|
||||
{
|
||||
assistant_enabled = AgentSettings::get_global(cx).enabled;
|
||||
was_ai_disabled = is_ai_disabled;
|
||||
cx.notify();
|
||||
}
|
||||
});
|
||||
|
@ -1806,7 +1812,7 @@ impl GitPanel {
|
|||
|
||||
/// Generates a commit message using an LLM.
|
||||
pub fn generate_commit_message(&mut self, cx: &mut Context<Self>) {
|
||||
if !self.can_commit() {
|
||||
if !self.can_commit() || DisableAiSettings::get_global(cx).disable_ai {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4305,8 +4311,10 @@ impl GitPanel {
|
|||
}
|
||||
|
||||
fn current_language_model(cx: &Context<'_, GitPanel>) -> Option<Arc<dyn LanguageModel>> {
|
||||
agent_settings::AgentSettings::get_global(cx)
|
||||
.enabled
|
||||
let is_enabled = agent_settings::AgentSettings::get_global(cx).enabled
|
||||
&& !DisableAiSettings::get_global(cx).disable_ai;
|
||||
|
||||
is_enabled
|
||||
.then(|| {
|
||||
let ConfiguredModel { provider, model } =
|
||||
LanguageModelRegistry::read_global(cx).commit_message_model()?;
|
||||
|
@ -5037,6 +5045,7 @@ mod tests {
|
|||
language::init(cx);
|
||||
editor::init(cx);
|
||||
Project::init_settings(cx);
|
||||
client::DisableAiSettings::register(cx);
|
||||
crate::init(cx);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use anyhow::Result;
|
||||
use client::{UserStore, zed_urls};
|
||||
use client::{DisableAiSettings, UserStore, zed_urls};
|
||||
use copilot::{Copilot, Status};
|
||||
use editor::{
|
||||
Editor, SelectionEffects,
|
||||
|
@ -72,6 +72,11 @@ enum SupermavenButtonStatus {
|
|||
|
||||
impl Render for InlineCompletionButton {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
// Return empty div if AI is disabled
|
||||
if DisableAiSettings::get_global(cx).disable_ai {
|
||||
return div();
|
||||
}
|
||||
|
||||
let all_language_settings = all_language_settings(None, cx);
|
||||
|
||||
match all_language_settings.edit_predictions.provider {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use client::{TelemetrySettings, telemetry::Telemetry};
|
||||
use client::{DisableAiSettings, TelemetrySettings, telemetry::Telemetry};
|
||||
use db::kvp::KEY_VALUE_STORE;
|
||||
use gpui::{
|
||||
Action, App, Context, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
|
||||
|
@ -174,23 +174,25 @@ impl Render for WelcomePage {
|
|||
.ok();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new(
|
||||
"try-zed-edit-prediction",
|
||||
edit_prediction_label,
|
||||
.when(!DisableAiSettings::get_global(cx).disable_ai, |parent| {
|
||||
parent.child(
|
||||
Button::new(
|
||||
"edit_prediction_onboarding",
|
||||
edit_prediction_label,
|
||||
)
|
||||
.disabled(edit_prediction_provider_is_zed)
|
||||
.icon(IconName::ZedPredict)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.icon_color(Color::Muted)
|
||||
.icon_position(IconPosition::Start)
|
||||
.on_click(
|
||||
cx.listener(|_, _, window, cx| {
|
||||
telemetry::event!("Welcome Screen Try Edit Prediction clicked");
|
||||
window.dispatch_action(zed_actions::OpenZedPredictOnboarding.boxed_clone(), cx);
|
||||
}),
|
||||
),
|
||||
)
|
||||
.disabled(edit_prediction_provider_is_zed)
|
||||
.icon(IconName::ZedPredict)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.icon_color(Color::Muted)
|
||||
.icon_position(IconPosition::Start)
|
||||
.on_click(
|
||||
cx.listener(|_, _, window, cx| {
|
||||
telemetry::event!("Welcome Screen Try Edit Prediction clicked");
|
||||
window.dispatch_action(zed_actions::OpenZedPredictOnboarding.boxed_clone(), cx);
|
||||
}),
|
||||
),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
Button::new("edit settings", "Edit Settings")
|
||||
.icon(IconName::Settings)
|
||||
|
|
|
@ -242,6 +242,7 @@ struct PanelEntry {
|
|||
|
||||
pub struct PanelButtons {
|
||||
dock: Entity<Dock>,
|
||||
_settings_subscription: Subscription,
|
||||
}
|
||||
|
||||
impl Dock {
|
||||
|
@ -373,6 +374,12 @@ impl Dock {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn first_enabled_panel_idx_excluding(&self, exclude_name: &str, cx: &App) -> Option<usize> {
|
||||
self.panel_entries.iter().position(|entry| {
|
||||
entry.panel.persistent_name() != exclude_name && entry.panel.enabled(cx)
|
||||
})
|
||||
}
|
||||
|
||||
fn active_panel_entry(&self) -> Option<&PanelEntry> {
|
||||
self.active_panel_index
|
||||
.and_then(|index| self.panel_entries.get(index))
|
||||
|
@ -833,7 +840,11 @@ impl Render for Dock {
|
|||
impl PanelButtons {
|
||||
pub fn new(dock: Entity<Dock>, cx: &mut Context<Self>) -> Self {
|
||||
cx.observe(&dock, |_, _, cx| cx.notify()).detach();
|
||||
Self { dock }
|
||||
let settings_subscription = cx.observe_global::<SettingsStore>(|_, cx| cx.notify());
|
||||
Self {
|
||||
dock,
|
||||
_settings_subscription: settings_subscription,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -554,6 +554,7 @@ pub fn main() {
|
|||
supermaven::init(app_state.client.clone(), cx);
|
||||
language_model::init(app_state.client.clone(), cx);
|
||||
language_models::init(app_state.user_store.clone(), app_state.client.clone(), cx);
|
||||
agent_settings::init(cx);
|
||||
agent_servers::init(cx);
|
||||
web_search::init(cx);
|
||||
web_search_providers::init(app_state.client.clone(), cx);
|
||||
|
|
|
@ -2,6 +2,7 @@ mod preview;
|
|||
mod repl_menu;
|
||||
|
||||
use agent_settings::AgentSettings;
|
||||
use client::DisableAiSettings;
|
||||
use editor::actions::{
|
||||
AddSelectionAbove, AddSelectionBelow, CodeActionSource, DuplicateLineDown, GoToDiagnostic,
|
||||
GoToHunk, GoToPreviousDiagnostic, GoToPreviousHunk, MoveLineDown, MoveLineUp, SelectAll,
|
||||
|
@ -32,6 +33,7 @@ const MAX_CODE_ACTION_MENU_LINES: u32 = 16;
|
|||
|
||||
pub struct QuickActionBar {
|
||||
_inlay_hints_enabled_subscription: Option<Subscription>,
|
||||
_ai_settings_subscription: Subscription,
|
||||
active_item: Option<Box<dyn ItemHandle>>,
|
||||
buffer_search_bar: Entity<BufferSearchBar>,
|
||||
show: bool,
|
||||
|
@ -46,8 +48,28 @@ impl QuickActionBar {
|
|||
workspace: &Workspace,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let mut was_ai_disabled = DisableAiSettings::get_global(cx).disable_ai;
|
||||
let mut was_agent_enabled = AgentSettings::get_global(cx).enabled;
|
||||
let mut was_agent_button = AgentSettings::get_global(cx).button;
|
||||
|
||||
let ai_settings_subscription = cx.observe_global::<SettingsStore>(move |_, cx| {
|
||||
let is_ai_disabled = DisableAiSettings::get_global(cx).disable_ai;
|
||||
let agent_settings = AgentSettings::get_global(cx);
|
||||
|
||||
if was_ai_disabled != is_ai_disabled
|
||||
|| was_agent_enabled != agent_settings.enabled
|
||||
|| was_agent_button != agent_settings.button
|
||||
{
|
||||
was_ai_disabled = is_ai_disabled;
|
||||
was_agent_enabled = agent_settings.enabled;
|
||||
was_agent_button = agent_settings.button;
|
||||
cx.notify();
|
||||
}
|
||||
});
|
||||
|
||||
let mut this = Self {
|
||||
_inlay_hints_enabled_subscription: None,
|
||||
_ai_settings_subscription: ai_settings_subscription,
|
||||
active_item: None,
|
||||
buffer_search_bar,
|
||||
show: true,
|
||||
|
@ -575,7 +597,9 @@ impl Render for QuickActionBar {
|
|||
.children(self.render_preview_button(self.workspace.clone(), cx))
|
||||
.children(search_button)
|
||||
.when(
|
||||
AgentSettings::get_global(cx).enabled && AgentSettings::get_global(cx).button,
|
||||
AgentSettings::get_global(cx).enabled
|
||||
&& AgentSettings::get_global(cx).button
|
||||
&& !DisableAiSettings::get_global(cx).disable_ai,
|
||||
|bar| bar.child(assistant_button),
|
||||
)
|
||||
.children(code_actions_dropdown)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use std::any::{Any, TypeId};
|
||||
|
||||
use client::DisableAiSettings;
|
||||
use command_palette_hooks::CommandPaletteFilter;
|
||||
use feature_flags::{FeatureFlagAppExt as _, PredictEditsRateCompletionsFeatureFlag};
|
||||
use gpui::actions;
|
||||
use language::language_settings::{AllLanguageSettings, EditPredictionProvider};
|
||||
use settings::update_settings_file;
|
||||
use settings::{Settings, SettingsStore, update_settings_file};
|
||||
use ui::App;
|
||||
use workspace::Workspace;
|
||||
|
||||
|
@ -21,6 +22,8 @@ actions!(
|
|||
);
|
||||
|
||||
pub fn init(cx: &mut App) {
|
||||
feature_gate_predict_edits_actions(cx);
|
||||
|
||||
cx.observe_new(move |workspace: &mut Workspace, _, _cx| {
|
||||
workspace.register_action(|workspace, _: &RateCompletions, window, cx| {
|
||||
if cx.has_flag::<PredictEditsRateCompletionsFeatureFlag>() {
|
||||
|
@ -53,27 +56,57 @@ pub fn init(cx: &mut App) {
|
|||
});
|
||||
})
|
||||
.detach();
|
||||
|
||||
feature_gate_predict_edits_rating_actions(cx);
|
||||
}
|
||||
|
||||
fn feature_gate_predict_edits_rating_actions(cx: &mut App) {
|
||||
fn feature_gate_predict_edits_actions(cx: &mut App) {
|
||||
let rate_completion_action_types = [TypeId::of::<RateCompletions>()];
|
||||
let reset_onboarding_action_types = [TypeId::of::<ResetOnboarding>()];
|
||||
let zeta_all_action_types = [
|
||||
TypeId::of::<RateCompletions>(),
|
||||
TypeId::of::<ResetOnboarding>(),
|
||||
zed_actions::OpenZedPredictOnboarding.type_id(),
|
||||
TypeId::of::<crate::ClearHistory>(),
|
||||
TypeId::of::<crate::ThumbsUpActiveCompletion>(),
|
||||
TypeId::of::<crate::ThumbsDownActiveCompletion>(),
|
||||
TypeId::of::<crate::NextEdit>(),
|
||||
TypeId::of::<crate::PreviousEdit>(),
|
||||
];
|
||||
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
filter.hide_action_types(&rate_completion_action_types);
|
||||
filter.hide_action_types(&reset_onboarding_action_types);
|
||||
filter.hide_action_types(&[zed_actions::OpenZedPredictOnboarding.type_id()]);
|
||||
});
|
||||
|
||||
cx.observe_global::<SettingsStore>(move |cx| {
|
||||
let is_ai_disabled = DisableAiSettings::get_global(cx).disable_ai;
|
||||
let has_feature_flag = cx.has_flag::<PredictEditsRateCompletionsFeatureFlag>();
|
||||
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
if is_ai_disabled {
|
||||
filter.hide_action_types(&zeta_all_action_types);
|
||||
} else {
|
||||
if has_feature_flag {
|
||||
filter.show_action_types(rate_completion_action_types.iter());
|
||||
} else {
|
||||
filter.hide_action_types(&rate_completion_action_types);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
|
||||
cx.observe_flag::<PredictEditsRateCompletionsFeatureFlag, _>(move |is_enabled, cx| {
|
||||
if is_enabled {
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
filter.show_action_types(rate_completion_action_types.iter());
|
||||
});
|
||||
} else {
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
filter.hide_action_types(&rate_completion_action_types);
|
||||
});
|
||||
if !DisableAiSettings::get_global(cx).disable_ai {
|
||||
if is_enabled {
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
filter.show_action_types(rate_completion_action_types.iter());
|
||||
});
|
||||
} else {
|
||||
CommandPaletteFilter::update_global(cx, |filter, _cx| {
|
||||
filter.hide_action_types(&rate_completion_action_types);
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue