Detailed changes
@@ -19,7 +19,7 @@ use settings::{Settings, SettingsStore};
use std::{sync::Arc, time::Duration};
use strum::IntoEnumIterator;
use theme::ThemeSettings;
-use ui::{prelude::*, Icon, IconName};
+use ui::{prelude::*, Icon, IconName, Tooltip};
use util::ResultExt;
const PROVIDER_ID: &str = "anthropic";
@@ -54,8 +54,11 @@ pub struct AnthropicLanguageModelProvider {
state: gpui::Model<State>,
}
+const ANTHROPIC_API_KEY_VAR: &'static str = "ANTHROPIC_API_KEY";
+
pub struct State {
api_key: Option<String>,
+ api_key_from_env: bool,
_subscription: Subscription,
}
@@ -67,6 +70,7 @@ impl State {
delete_credentials.await.ok();
this.update(&mut cx, |this, cx| {
this.api_key = None;
+ this.api_key_from_env = false;
cx.notify();
})
})
@@ -105,18 +109,20 @@ impl State {
.clone();
cx.spawn(|this, mut cx| async move {
- let api_key = if let Ok(api_key) = std::env::var("ANTHROPIC_API_KEY") {
- api_key
+ let (api_key, from_env) = if let Ok(api_key) = std::env::var(ANTHROPIC_API_KEY_VAR)
+ {
+ (api_key, true)
} else {
let (_, api_key) = cx
.update(|cx| cx.read_credentials(&api_url))?
.await?
.ok_or_else(|| anyhow!("credentials not found"))?;
- String::from_utf8(api_key)?
+ (String::from_utf8(api_key)?, false)
};
this.update(&mut cx, |this, cx| {
this.api_key = Some(api_key);
+ this.api_key_from_env = from_env;
cx.notify();
})
})
@@ -128,6 +134,7 @@ impl AnthropicLanguageModelProvider {
pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Self {
let state = cx.new_model(|cx| State {
api_key: None,
+ api_key_from_env: false,
_subscription: cx.observe_global::<SettingsStore>(|_, cx| {
cx.notify();
}),
@@ -537,6 +544,8 @@ impl Render for ConfigurationView {
"Paste your Anthropic API key below and hit enter to use the assistant:",
];
+ let env_var_set = self.state.read(cx).api_key_from_env;
+
if self.load_credentials_task.is_some() {
div().child(Label::new("Loading credentials...")).into_any()
} else if self.should_render_editor(cx) {
@@ -558,7 +567,7 @@ impl Render for ConfigurationView {
)
.child(
Label::new(
- "You can also assign the ANTHROPIC_API_KEY environment variable and restart Zed.",
+ "You can also assign the {ANTHROPIC_API_KEY_VAR} environment variable and restart Zed.",
)
.size(LabelSize::Small),
)
@@ -571,13 +580,21 @@ impl Render for ConfigurationView {
h_flex()
.gap_1()
.child(Icon::new(IconName::Check).color(Color::Success))
- .child(Label::new("API key configured.")),
+ .child(Label::new(if env_var_set {
+ format!("API key set in {ANTHROPIC_API_KEY_VAR} environment variable.")
+ } else {
+ "API key configured.".to_string()
+ })),
)
.child(
Button::new("reset-key", "Reset key")
.icon(Some(IconName::Trash))
.icon_size(IconSize::Small)
.icon_position(IconPosition::Start)
+ .disabled(env_var_set)
+ .when(env_var_set, |this| {
+ this.tooltip(|cx| Tooltip::text(format!("To reset your API key, unset the {ANTHROPIC_API_KEY_VAR} environment variable."), cx))
+ })
.on_click(cx.listener(|this, _, cx| this.reset_api_key(cx))),
)
.into_any()
@@ -14,7 +14,7 @@ use settings::{Settings, SettingsStore};
use std::{future, sync::Arc, time::Duration};
use strum::IntoEnumIterator;
use theme::ThemeSettings;
-use ui::{prelude::*, Icon, IconName};
+use ui::{prelude::*, Icon, IconName, Tooltip};
use util::ResultExt;
use crate::{
@@ -46,9 +46,12 @@ pub struct GoogleLanguageModelProvider {
pub struct State {
api_key: Option<String>,
+ api_key_from_env: bool,
_subscription: Subscription,
}
+const GOOGLE_AI_API_KEY_VAR: &'static str = "GOOGLE_AI_API_KEY";
+
impl State {
fn is_authenticated(&self) -> bool {
self.api_key.is_some()
@@ -61,6 +64,7 @@ impl State {
delete_credentials.await.ok();
this.update(&mut cx, |this, cx| {
this.api_key = None;
+ this.api_key_from_env = false;
cx.notify();
})
})
@@ -90,18 +94,20 @@ impl State {
.clone();
cx.spawn(|this, mut cx| async move {
- let api_key = if let Ok(api_key) = std::env::var("GOOGLE_AI_API_KEY") {
- api_key
+ let (api_key, from_env) = if let Ok(api_key) = std::env::var(GOOGLE_AI_API_KEY_VAR)
+ {
+ (api_key, true)
} else {
let (_, api_key) = cx
.update(|cx| cx.read_credentials(&api_url))?
.await?
.ok_or_else(|| anyhow!("credentials not found"))?;
- String::from_utf8(api_key)?
+ (String::from_utf8(api_key)?, false)
};
this.update(&mut cx, |this, cx| {
this.api_key = Some(api_key);
+ this.api_key_from_env = from_env;
cx.notify();
})
})
@@ -113,6 +119,7 @@ impl GoogleLanguageModelProvider {
pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Self {
let state = cx.new_model(|cx| State {
api_key: None,
+ api_key_from_env: false,
_subscription: cx.observe_global::<SettingsStore>(|_, cx| {
cx.notify();
}),
@@ -422,6 +429,8 @@ impl Render for ConfigurationView {
"Paste your Google AI API key below and hit enter to use the assistant:",
];
+ let env_var_set = self.state.read(cx).api_key_from_env;
+
if self.load_credentials_task.is_some() {
div().child(Label::new("Loading credentials...")).into_any()
} else if self.should_render_editor(cx) {
@@ -443,7 +452,7 @@ impl Render for ConfigurationView {
)
.child(
Label::new(
- "You can also assign the GOOGLE_AI_API_KEY environment variable and restart Zed.",
+ format!("You can also assign the {GOOGLE_AI_API_KEY_VAR} environment variable and restart Zed."),
)
.size(LabelSize::Small),
)
@@ -456,13 +465,21 @@ impl Render for ConfigurationView {
h_flex()
.gap_1()
.child(Icon::new(IconName::Check).color(Color::Success))
- .child(Label::new("API key configured.")),
+ .child(Label::new(if env_var_set {
+ format!("API key set in {GOOGLE_AI_API_KEY_VAR} environment variable.")
+ } else {
+ "API key configured.".to_string()
+ })),
)
.child(
Button::new("reset-key", "Reset key")
.icon(Some(IconName::Trash))
.icon_size(IconSize::Small)
.icon_position(IconPosition::Start)
+ .disabled(env_var_set)
+ .when(env_var_set, |this| {
+ this.tooltip(|cx| Tooltip::text(format!("To reset your API key, unset the {GOOGLE_AI_API_KEY_VAR} environment variable."), cx))
+ })
.on_click(cx.listener(|this, _, cx| this.reset_api_key(cx))),
)
.into_any()
@@ -16,7 +16,7 @@ use settings::{Settings, SettingsStore};
use std::{sync::Arc, time::Duration};
use strum::IntoEnumIterator;
use theme::ThemeSettings;
-use ui::{prelude::*, Icon, IconName};
+use ui::{prelude::*, Icon, IconName, Tooltip};
use util::ResultExt;
use crate::{
@@ -49,9 +49,12 @@ pub struct OpenAiLanguageModelProvider {
pub struct State {
api_key: Option<String>,
+ api_key_from_env: bool,
_subscription: Subscription,
}
+const OPENAI_API_KEY_VAR: &'static str = "OPENAI_API_KEY";
+
impl State {
fn is_authenticated(&self) -> bool {
self.api_key.is_some()
@@ -64,6 +67,7 @@ impl State {
delete_credentials.await.log_err();
this.update(&mut cx, |this, cx| {
this.api_key = None;
+ this.api_key_from_env = false;
cx.notify();
})
})
@@ -92,17 +96,18 @@ impl State {
.api_url
.clone();
cx.spawn(|this, mut cx| async move {
- let api_key = if let Ok(api_key) = std::env::var("OPENAI_API_KEY") {
- api_key
+ let (api_key, from_env) = if let Ok(api_key) = std::env::var(OPENAI_API_KEY_VAR) {
+ (api_key, true)
} else {
let (_, api_key) = cx
.update(|cx| cx.read_credentials(&api_url))?
.await?
.ok_or_else(|| anyhow!("credentials not found"))?;
- String::from_utf8(api_key)?
+ (String::from_utf8(api_key)?, false)
};
this.update(&mut cx, |this, cx| {
this.api_key = Some(api_key);
+ this.api_key_from_env = from_env;
cx.notify();
})
})
@@ -114,6 +119,7 @@ impl OpenAiLanguageModelProvider {
pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut AppContext) -> Self {
let state = cx.new_model(|cx| State {
api_key: None,
+ api_key_from_env: false,
_subscription: cx.observe_global::<SettingsStore>(|_this: &mut State, cx| {
cx.notify();
}),
@@ -476,6 +482,8 @@ impl Render for ConfigurationView {
"Paste your OpenAI API key below and hit enter to use the assistant:",
];
+ let env_var_set = self.state.read(cx).api_key_from_env;
+
if self.load_credentials_task.is_some() {
div().child(Label::new("Loading credentials...")).into_any()
} else if self.should_render_editor(cx) {
@@ -497,7 +505,7 @@ impl Render for ConfigurationView {
)
.child(
Label::new(
- "You can also assign the OPENAI_API_KEY environment variable and restart Zed.",
+ format!("You can also assign the {OPENAI_API_KEY_VAR} environment variable and restart Zed."),
)
.size(LabelSize::Small),
)
@@ -510,13 +518,21 @@ impl Render for ConfigurationView {
h_flex()
.gap_1()
.child(Icon::new(IconName::Check).color(Color::Success))
- .child(Label::new("API key configured.")),
+ .child(Label::new(if env_var_set {
+ format!("API key set in {OPENAI_API_KEY_VAR} environment variable.")
+ } else {
+ "API key configured.".to_string()
+ })),
)
.child(
Button::new("reset-key", "Reset key")
.icon(Some(IconName::Trash))
.icon_size(IconSize::Small)
.icon_position(IconPosition::Start)
+ .disabled(env_var_set)
+ .when(env_var_set, |this| {
+ this.tooltip(|cx| Tooltip::text(format!("To reset your API key, unset the {OPENAI_API_KEY_VAR} environment variable."), cx))
+ })
.on_click(cx.listener(|this, _, cx| this.reset_api_key(cx))),
)
.into_any()