assistant panel: Show if env var with API key is set (#16453)

This makes it easier to debug why resetting a key doesn't work. We now
show when the key is set via an env var and if so, we disable the
reset-key button and instead give instructions.

![screenshot-2024-08-19-11 22
05@2x](https://github.com/user-attachments/assets/6c75dc82-cb61-4661-9647-f77fca8fdf41)


Release Notes:

- N/A

Co-authored-by: Bennet <bennet@zed.dev>
This commit is contained in:
Thorsten Ball 2024-08-19 11:34:58 +02:00 committed by GitHub
parent 14fa4abce4
commit f651333896
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 68 additions and 18 deletions

View file

@ -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()