WIP Add copilot disabled setting

This commit is contained in:
Mikayla Maki 2023-03-28 20:52:50 -07:00
parent 0b0c7e4ce9
commit d60ef03d66
2 changed files with 99 additions and 11 deletions

View file

@ -3,8 +3,11 @@ mod sign_in;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use client::Client; use client::Client;
use futures::{future::Shared, FutureExt, TryFutureExt}; use futures::{future::Shared, Future, FutureExt, TryFutureExt};
use gpui::{actions, AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, Task}; use gpui::{
actions, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
Task,
};
use language::{point_from_lsp, point_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, ToPointUtf16}; use language::{point_from_lsp, point_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, ToPointUtf16};
use lsp::LanguageServer; use lsp::LanguageServer;
use node_runtime::NodeRuntime; use node_runtime::NodeRuntime;
@ -17,6 +20,7 @@ use std::{
}; };
use util::{fs::remove_matching, http::HttpClient, paths, ResultExt}; use util::{fs::remove_matching, http::HttpClient, paths, ResultExt};
const COPILOT_AUTH_NAMESPACE: &'static str = "copilot_auth";
actions!(copilot_auth, [SignIn, SignOut]); actions!(copilot_auth, [SignIn, SignOut]);
const COPILOT_NAMESPACE: &'static str = "copilot"; const COPILOT_NAMESPACE: &'static str = "copilot";
@ -42,8 +46,18 @@ pub fn init(client: Arc<Client>, node_runtime: Arc<NodeRuntime>, cx: &mut Mutabl
let status = handle.read(cx).status(); let status = handle.read(cx).status();
cx.update_global::<collections::CommandPaletteFilter, _, _>( cx.update_global::<collections::CommandPaletteFilter, _, _>(
move |filter, _cx| match status { move |filter, _cx| match status {
Status::Authorized => filter.filtered_namespaces.remove(COPILOT_NAMESPACE), Status::Disabled => {
_ => filter.filtered_namespaces.insert(COPILOT_NAMESPACE), filter.filtered_namespaces.insert(COPILOT_NAMESPACE);
filter.filtered_namespaces.insert(COPILOT_AUTH_NAMESPACE);
}
Status::Authorized => {
filter.filtered_namespaces.remove(COPILOT_NAMESPACE);
filter.filtered_namespaces.remove(COPILOT_AUTH_NAMESPACE);
}
_ => {
filter.filtered_namespaces.insert(COPILOT_NAMESPACE);
filter.filtered_namespaces.remove(COPILOT_AUTH_NAMESPACE);
}
}, },
); );
}) })
@ -55,6 +69,7 @@ pub fn init(client: Arc<Client>, node_runtime: Arc<NodeRuntime>, cx: &mut Mutabl
enum CopilotServer { enum CopilotServer {
Downloading, Downloading,
Error(Arc<str>), Error(Arc<str>),
Disabled,
Started { Started {
server: Arc<LanguageServer>, server: Arc<LanguageServer>,
status: SignInStatus, status: SignInStatus,
@ -80,6 +95,7 @@ enum SignInStatus {
pub enum Status { pub enum Status {
Downloading, Downloading,
Error(Arc<str>), Error(Arc<str>),
Disabled,
SignedOut, SignedOut,
SigningIn { SigningIn {
prompt: Option<request::PromptUserDeviceFlow>, prompt: Option<request::PromptUserDeviceFlow>,
@ -122,8 +138,55 @@ impl Copilot {
node_runtime: Arc<NodeRuntime>, node_runtime: Arc<NodeRuntime>,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) -> Self { ) -> Self {
// TODO: Don't eagerly download the LSP // TODO: Make this task resilient to users thrashing the copilot setting
cx.spawn(|this, mut cx| async move { cx.observe_global::<Settings, _>({
let http = http.clone();
let node_runtime = node_runtime.clone();
move |this, cx| {
if cx.global::<Settings>().copilot.as_bool() {
if matches!(this.server, CopilotServer::Disabled) {
cx.spawn({
let http = http.clone();
let node_runtime = node_runtime.clone();
move |this, cx| {
Self::start_language_server(http, node_runtime, this, cx)
}
})
.detach();
}
} else {
// TODO: What else needs to be turned off here?
this.server = CopilotServer::Disabled
}
}
})
.detach();
if !cx.global::<Settings>().copilot.as_bool() {
return Self {
server: CopilotServer::Disabled,
};
}
cx.spawn({
let http = http.clone();
let node_runtime = node_runtime.clone();
move |this, cx| Self::start_language_server(http, node_runtime, this, cx)
})
.detach();
Self {
server: CopilotServer::Downloading,
}
}
fn start_language_server(
http: Arc<dyn HttpClient>,
node_runtime: Arc<NodeRuntime>,
this: ModelHandle<Self>,
mut cx: AsyncAppContext,
) -> impl Future<Output = ()> {
async move {
let start_language_server = async { let start_language_server = async {
let server_path = get_copilot_lsp(http, node_runtime.clone()).await?; let server_path = get_copilot_lsp(http, node_runtime.clone()).await?;
let node_path = node_runtime.binary_path().await?; let node_path = node_runtime.binary_path().await?;
@ -156,11 +219,6 @@ impl Copilot {
} }
} }
}) })
})
.detach();
Self {
server: CopilotServer::Downloading,
} }
} }
@ -324,6 +382,7 @@ impl Copilot {
pub fn status(&self) -> Status { pub fn status(&self) -> Status {
match &self.server { match &self.server {
CopilotServer::Downloading => Status::Downloading, CopilotServer::Downloading => Status::Downloading,
CopilotServer::Disabled => Status::Disabled,
CopilotServer::Error(error) => Status::Error(error.clone()), CopilotServer::Error(error) => Status::Error(error.clone()),
CopilotServer::Started { status, .. } => match status { CopilotServer::Started { status, .. } => match status {
SignInStatus::Authorized { .. } => Status::Authorized, SignInStatus::Authorized { .. } => Status::Authorized,
@ -358,6 +417,7 @@ impl Copilot {
fn authorized_server(&self) -> Result<Arc<LanguageServer>> { fn authorized_server(&self) -> Result<Arc<LanguageServer>> {
match &self.server { match &self.server {
CopilotServer::Downloading => Err(anyhow!("copilot is still downloading")), CopilotServer::Downloading => Err(anyhow!("copilot is still downloading")),
CopilotServer::Disabled => Err(anyhow!("copilot is disabled")),
CopilotServer::Error(error) => Err(anyhow!( CopilotServer::Error(error) => Err(anyhow!(
"copilot was not started because of an error: {}", "copilot was not started because of an error: {}",
error error

View file

@ -58,6 +58,29 @@ pub struct Settings {
pub telemetry_overrides: TelemetrySettings, pub telemetry_overrides: TelemetrySettings,
pub auto_update: bool, pub auto_update: bool,
pub base_keymap: BaseKeymap, pub base_keymap: BaseKeymap,
pub copilot: CopilotSettings,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)]
pub enum CopilotSettings {
#[default]
On,
Off,
}
impl From<CopilotSettings> for bool {
fn from(value: CopilotSettings) -> Self {
match value {
CopilotSettings::On => true,
CopilotSettings::Off => false,
}
}
}
impl CopilotSettings {
pub fn as_bool(&self) -> bool {
<CopilotSettings as Into<bool>>::into(*self)
}
} }
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)] #[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq, Default)]
@ -375,6 +398,8 @@ pub struct SettingsFileContent {
pub auto_update: Option<bool>, pub auto_update: Option<bool>,
#[serde(default)] #[serde(default)]
pub base_keymap: Option<BaseKeymap>, pub base_keymap: Option<BaseKeymap>,
#[serde(default)]
pub copilot: Option<CopilotSettings>,
} }
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
@ -452,6 +477,7 @@ impl Settings {
telemetry_overrides: Default::default(), telemetry_overrides: Default::default(),
auto_update: defaults.auto_update.unwrap(), auto_update: defaults.auto_update.unwrap(),
base_keymap: Default::default(), base_keymap: Default::default(),
copilot: Default::default(),
} }
} }
@ -503,6 +529,7 @@ impl Settings {
merge(&mut self.autosave, data.autosave); merge(&mut self.autosave, data.autosave);
merge(&mut self.default_dock_anchor, data.default_dock_anchor); merge(&mut self.default_dock_anchor, data.default_dock_anchor);
merge(&mut self.base_keymap, data.base_keymap); merge(&mut self.base_keymap, data.base_keymap);
merge(&mut self.copilot, data.copilot);
self.editor_overrides = data.editor; self.editor_overrides = data.editor;
self.git_overrides = data.git.unwrap_or_default(); self.git_overrides = data.git.unwrap_or_default();
@ -681,6 +708,7 @@ impl Settings {
telemetry_overrides: Default::default(), telemetry_overrides: Default::default(),
auto_update: true, auto_update: true,
base_keymap: Default::default(), base_keymap: Default::default(),
copilot: Default::default(),
} }
} }