Misc cleanup + clear language model provider API key editors when API keys are submitted (#38165)
Followup to #38163 along with some other misc cleanups Release Notes: - N/A
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
use crate::api_key::ApiKeyState;
|
||||
use crate::ui::InstructionListItem;
|
||||
use crate::{AllLanguageModelSettings, api_key::ApiKeyState};
|
||||
use anthropic::{
|
||||
AnthropicError, AnthropicModelMode, ContentDelta, Event, ResponseContent, ToolResultContent,
|
||||
ToolResultPart, Usage,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use anyhow::{Result, anyhow};
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use futures::Stream;
|
||||
use futures::{FutureExt, StreamExt, future::BoxFuture, stream::BoxStream};
|
||||
use futures::{FutureExt, Stream, StreamExt, future, future::BoxFuture, stream::BoxStream};
|
||||
use gpui::{AnyView, App, AsyncApp, Context, Entity, FontStyle, Task, TextStyle, WhiteSpace};
|
||||
use http_client::HttpClient;
|
||||
use language_model::{
|
||||
@@ -157,7 +156,7 @@ impl AnthropicLanguageModelProvider {
|
||||
}
|
||||
|
||||
fn settings(cx: &App) -> &AnthropicSettings {
|
||||
&AllLanguageModelSettings::get_global(cx).anthropic
|
||||
&crate::AllLanguageModelSettings::get_global(cx).anthropic
|
||||
}
|
||||
|
||||
fn api_url(cx: &App) -> SharedString {
|
||||
@@ -220,11 +219,7 @@ impl LanguageModelProvider for AnthropicLanguageModelProvider {
|
||||
}
|
||||
|
||||
// Override with available models from settings
|
||||
for model in AllLanguageModelSettings::get_global(cx)
|
||||
.anthropic
|
||||
.available_models
|
||||
.iter()
|
||||
{
|
||||
for model in &AnthropicLanguageModelProvider::settings(cx).available_models {
|
||||
models.insert(
|
||||
model.name.clone(),
|
||||
anthropic::Model::Custom {
|
||||
@@ -363,16 +358,11 @@ impl AnthropicModel {
|
||||
> {
|
||||
let http_client = self.http_client.clone();
|
||||
|
||||
let api_key_and_url = self.state.read_with(cx, |state, cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, cx| {
|
||||
let api_url = AnthropicLanguageModelProvider::api_url(cx);
|
||||
let api_key = state.api_key_state.key(&api_url);
|
||||
(api_key, api_url)
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(err.into())).boxed();
|
||||
}
|
||||
(state.api_key_state.key(&api_url), api_url)
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped").into())).boxed();
|
||||
};
|
||||
|
||||
let beta_headers = self.model.beta_headers();
|
||||
@@ -938,6 +928,10 @@ impl ConfigurationView {
|
||||
return;
|
||||
}
|
||||
|
||||
// url changes can cause the editor to be displayed again
|
||||
self.api_key_editor
|
||||
.update(cx, |editor, cx| editor.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
state
|
||||
|
||||
@@ -2,7 +2,7 @@ use anyhow::{Result, anyhow};
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use futures::Stream;
|
||||
use futures::{FutureExt, StreamExt, future::BoxFuture, stream::BoxStream};
|
||||
use futures::{FutureExt, StreamExt, future, future::BoxFuture, stream::BoxStream};
|
||||
use gpui::{
|
||||
AnyView, App, AsyncApp, Context, Entity, FontStyle, SharedString, Task, TextStyle, WhiteSpace,
|
||||
Window,
|
||||
@@ -26,7 +26,7 @@ use ui::{Icon, IconName, List, prelude::*};
|
||||
use util::ResultExt;
|
||||
use zed_env_vars::{EnvVar, env_var};
|
||||
|
||||
use crate::{AllLanguageModelSettings, api_key::ApiKeyState, ui::InstructionListItem};
|
||||
use crate::{api_key::ApiKeyState, ui::InstructionListItem};
|
||||
|
||||
const PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("deepseek");
|
||||
const PROVIDER_NAME: LanguageModelProviderName = LanguageModelProviderName::new("DeepSeek");
|
||||
@@ -119,7 +119,7 @@ impl DeepSeekLanguageModelProvider {
|
||||
}
|
||||
|
||||
fn settings(cx: &App) -> &DeepSeekSettings {
|
||||
&AllLanguageModelSettings::get_global(cx).deepseek
|
||||
&crate::AllLanguageModelSettings::get_global(cx).deepseek
|
||||
}
|
||||
|
||||
fn api_url(cx: &App) -> &str {
|
||||
@@ -220,16 +220,11 @@ impl DeepSeekLanguageModel {
|
||||
) -> BoxFuture<'static, Result<BoxStream<'static, Result<deepseek::StreamResponse>>>> {
|
||||
let http_client = self.http_client.clone();
|
||||
|
||||
let api_key_and_url = self.state.read_with(cx, |state, cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, cx| {
|
||||
let api_url = DeepSeekLanguageModelProvider::api_url(cx);
|
||||
let api_key = state.api_key_state.key(api_url);
|
||||
(api_key, api_url.to_string())
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(err)).boxed();
|
||||
}
|
||||
(state.api_key_state.key(api_url), api_url.to_string())
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped"))).boxed();
|
||||
};
|
||||
|
||||
let future = self.request_limiter.stream(async move {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use anyhow::{Context as _, Result};
|
||||
use anyhow::{Context as _, Result, anyhow};
|
||||
use collections::BTreeMap;
|
||||
use credentials_provider::CredentialsProvider;
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use futures::{FutureExt, Stream, StreamExt, future::BoxFuture};
|
||||
use futures::{FutureExt, Stream, StreamExt, future, future::BoxFuture};
|
||||
use google_ai::{
|
||||
FunctionDeclaration, GenerateContentResponse, GoogleModelMode, Part, SystemInstruction,
|
||||
ThinkingConfig, UsageMetadata,
|
||||
@@ -37,8 +37,8 @@ use util::ResultExt;
|
||||
use zed_env_vars::EnvVar;
|
||||
|
||||
use crate::api_key::ApiKey;
|
||||
use crate::api_key::ApiKeyState;
|
||||
use crate::ui::InstructionListItem;
|
||||
use crate::{AllLanguageModelSettings, api_key::ApiKeyState};
|
||||
|
||||
const PROVIDER_ID: LanguageModelProviderId = language_model::GOOGLE_PROVIDER_ID;
|
||||
const PROVIDER_NAME: LanguageModelProviderName = language_model::GOOGLE_PROVIDER_NAME;
|
||||
@@ -173,8 +173,12 @@ impl GoogleLanguageModelProvider {
|
||||
})
|
||||
}
|
||||
|
||||
fn settings(cx: &App) -> &GoogleSettings {
|
||||
&crate::AllLanguageModelSettings::get_global(cx).google
|
||||
}
|
||||
|
||||
fn api_url(cx: &App) -> SharedString {
|
||||
let api_url = &AllLanguageModelSettings::get_global(cx).google.api_url;
|
||||
let api_url = &Self::settings(cx).api_url;
|
||||
if api_url.is_empty() {
|
||||
google_ai::API_URL.into()
|
||||
} else {
|
||||
@@ -223,10 +227,7 @@ impl LanguageModelProvider for GoogleLanguageModelProvider {
|
||||
}
|
||||
|
||||
// Override with available models from settings
|
||||
for model in &AllLanguageModelSettings::get_global(cx)
|
||||
.google
|
||||
.available_models
|
||||
{
|
||||
for model in &GoogleLanguageModelProvider::settings(cx).available_models {
|
||||
models.insert(
|
||||
model.name.clone(),
|
||||
google_ai::Model::Custom {
|
||||
@@ -295,16 +296,11 @@ impl GoogleLanguageModel {
|
||||
> {
|
||||
let http_client = self.http_client.clone();
|
||||
|
||||
let api_key_and_url = self.state.read_with(cx, |state, cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, cx| {
|
||||
let api_url = GoogleLanguageModelProvider::api_url(cx);
|
||||
let api_key = state.api_key_state.key(&api_url);
|
||||
(api_key, api_url)
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(err)).boxed();
|
||||
}
|
||||
(state.api_key_state.key(&api_url), api_url)
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped"))).boxed();
|
||||
};
|
||||
|
||||
async move {
|
||||
@@ -820,6 +816,10 @@ impl ConfigurationView {
|
||||
return;
|
||||
}
|
||||
|
||||
// url changes can cause the editor to be displayed again
|
||||
self.api_key_editor
|
||||
.update(cx, |editor, cx| editor.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
state
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{Result, anyhow};
|
||||
use collections::BTreeMap;
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use futures::{FutureExt, Stream, StreamExt, future::BoxFuture, stream::BoxStream};
|
||||
use futures::{FutureExt, Stream, StreamExt, future, future::BoxFuture, stream::BoxStream};
|
||||
use gpui::{
|
||||
AnyView, App, AsyncApp, Context, Entity, FontStyle, SharedString, Task, TextStyle, WhiteSpace,
|
||||
Window,
|
||||
@@ -244,16 +244,11 @@ impl MistralLanguageModel {
|
||||
> {
|
||||
let http_client = self.http_client.clone();
|
||||
|
||||
let api_key_and_url = self.state.read_with(cx, |state, cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, cx| {
|
||||
let api_url = MistralLanguageModelProvider::api_url(cx);
|
||||
let api_key = state.api_key_state.key(&api_url);
|
||||
(api_key, api_url)
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(err)).boxed();
|
||||
}
|
||||
(state.api_key_state.key(&api_url), api_url)
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped"))).boxed();
|
||||
};
|
||||
|
||||
let future = self.request_limiter.stream(async move {
|
||||
@@ -762,6 +757,10 @@ impl ConfigurationView {
|
||||
return;
|
||||
}
|
||||
|
||||
// url changes can cause the editor to be displayed again
|
||||
self.api_key_editor
|
||||
.update(cx, |editor, cx| editor.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
state
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{Result, anyhow};
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use futures::Stream;
|
||||
use futures::{FutureExt, StreamExt, future::BoxFuture};
|
||||
use futures::{FutureExt, StreamExt, future, future::BoxFuture};
|
||||
use gpui::{AnyView, App, AsyncApp, Context, Entity, SharedString, Task, Window};
|
||||
use http_client::HttpClient;
|
||||
use language_model::{
|
||||
@@ -25,7 +25,7 @@ use ui_input::SingleLineInput;
|
||||
use util::ResultExt;
|
||||
use zed_env_vars::{EnvVar, env_var};
|
||||
|
||||
use crate::{AllLanguageModelSettings, api_key::ApiKeyState, ui::InstructionListItem};
|
||||
use crate::{api_key::ApiKeyState, ui::InstructionListItem};
|
||||
|
||||
const PROVIDER_ID: LanguageModelProviderId = language_model::OPEN_AI_PROVIDER_ID;
|
||||
const PROVIDER_NAME: LanguageModelProviderName = language_model::OPEN_AI_PROVIDER_NAME;
|
||||
@@ -113,7 +113,7 @@ impl OpenAiLanguageModelProvider {
|
||||
}
|
||||
|
||||
fn settings(cx: &App) -> &OpenAiSettings {
|
||||
&AllLanguageModelSettings::get_global(cx).openai
|
||||
&crate::AllLanguageModelSettings::get_global(cx).openai
|
||||
}
|
||||
|
||||
fn api_url(cx: &App) -> SharedString {
|
||||
@@ -166,10 +166,7 @@ impl LanguageModelProvider for OpenAiLanguageModelProvider {
|
||||
}
|
||||
|
||||
// Override with available models from settings
|
||||
for model in &AllLanguageModelSettings::get_global(cx)
|
||||
.openai
|
||||
.available_models
|
||||
{
|
||||
for model in &OpenAiLanguageModelProvider::settings(cx).available_models {
|
||||
models.insert(
|
||||
model.name.clone(),
|
||||
open_ai::Model::Custom {
|
||||
@@ -230,16 +227,11 @@ impl OpenAiLanguageModel {
|
||||
{
|
||||
let http_client = self.http_client.clone();
|
||||
|
||||
let api_key_and_url = self.state.read_with(cx, |state, cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, cx| {
|
||||
let api_url = OpenAiLanguageModelProvider::api_url(cx);
|
||||
let api_key = state.api_key_state.key(&api_url);
|
||||
(api_key, api_url)
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(err)).boxed();
|
||||
}
|
||||
(state.api_key_state.key(&api_url), api_url)
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped"))).boxed();
|
||||
};
|
||||
|
||||
let future = self.request_limiter.stream(async move {
|
||||
@@ -744,6 +736,10 @@ impl ConfigurationView {
|
||||
return;
|
||||
}
|
||||
|
||||
// url changes can cause the editor to be displayed again
|
||||
self.api_key_editor
|
||||
.update(cx, |editor, cx| editor.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
state
|
||||
@@ -754,11 +750,8 @@ impl ConfigurationView {
|
||||
}
|
||||
|
||||
fn reset_api_key(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.api_key_editor.update(cx, |input, cx| {
|
||||
input.editor.update(cx, |editor, cx| {
|
||||
editor.set_text("", window, cx);
|
||||
});
|
||||
});
|
||||
self.api_key_editor
|
||||
.update(cx, |input, cx| input.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Result, anyhow};
|
||||
use convert_case::{Case, Casing};
|
||||
use futures::{FutureExt, StreamExt, future::BoxFuture};
|
||||
use futures::{FutureExt, StreamExt, future, future::BoxFuture};
|
||||
use gpui::{AnyView, App, AsyncApp, Context, Entity, SharedString, Task, Window};
|
||||
use http_client::HttpClient;
|
||||
use language_model::{
|
||||
@@ -20,8 +20,8 @@ use ui_input::SingleLineInput;
|
||||
use util::ResultExt;
|
||||
use zed_env_vars::EnvVar;
|
||||
|
||||
use crate::api_key::ApiKeyState;
|
||||
use crate::provider::open_ai::{OpenAiEventMapper, into_open_ai};
|
||||
use crate::{AllLanguageModelSettings, api_key::ApiKeyState};
|
||||
|
||||
#[derive(Default, Clone, Debug, PartialEq)]
|
||||
pub struct OpenAiCompatibleSettings {
|
||||
@@ -98,7 +98,7 @@ impl State {
|
||||
impl OpenAiCompatibleLanguageModelProvider {
|
||||
pub fn new(id: Arc<str>, http_client: Arc<dyn HttpClient>, cx: &mut App) -> Self {
|
||||
fn resolve_settings<'a>(id: &'a str, cx: &'a App) -> Option<&'a OpenAiCompatibleSettings> {
|
||||
AllLanguageModelSettings::get_global(cx)
|
||||
crate::AllLanguageModelSettings::get_global(cx)
|
||||
.openai_compatible
|
||||
.get(id)
|
||||
}
|
||||
@@ -239,16 +239,14 @@ impl OpenAiCompatibleLanguageModel {
|
||||
{
|
||||
let http_client = self.http_client.clone();
|
||||
|
||||
let api_key_and_url = self.state.read_with(cx, |state, _cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, _cx| {
|
||||
let api_url = &state.settings.api_url;
|
||||
let api_key = state.api_key_state.key(api_url);
|
||||
(api_key, state.settings.api_url.clone())
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(err)).boxed();
|
||||
}
|
||||
(
|
||||
state.api_key_state.key(api_url),
|
||||
state.settings.api_url.clone(),
|
||||
)
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped"))).boxed();
|
||||
};
|
||||
|
||||
let provider = self.provider_name.clone();
|
||||
@@ -423,6 +421,10 @@ impl ConfigurationView {
|
||||
return;
|
||||
}
|
||||
|
||||
// url changes can cause the editor to be displayed again
|
||||
self.api_key_editor
|
||||
.update(cx, |input, cx| input.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
state
|
||||
@@ -433,11 +435,8 @@ impl ConfigurationView {
|
||||
}
|
||||
|
||||
fn reset_api_key(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.api_key_editor.update(cx, |input, cx| {
|
||||
input.editor.update(cx, |editor, cx| {
|
||||
editor.set_text("", window, cx);
|
||||
});
|
||||
});
|
||||
self.api_key_editor
|
||||
.update(cx, |input, cx| input.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use anyhow::{Result, anyhow};
|
||||
use collections::HashMap;
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use futures::{FutureExt, Stream, StreamExt, future::BoxFuture};
|
||||
use futures::{FutureExt, Stream, StreamExt, future, future::BoxFuture};
|
||||
use gpui::{
|
||||
AnyView, App, AsyncApp, Context, Entity, FontStyle, SharedString, Task, TextStyle, WhiteSpace,
|
||||
};
|
||||
@@ -27,7 +27,7 @@ use ui::{Icon, IconName, List, Tooltip, prelude::*};
|
||||
use util::ResultExt;
|
||||
use zed_env_vars::{EnvVar, env_var};
|
||||
|
||||
use crate::{AllLanguageModelSettings, api_key::ApiKeyState, ui::InstructionListItem};
|
||||
use crate::{api_key::ApiKeyState, ui::InstructionListItem};
|
||||
|
||||
const PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("openrouter");
|
||||
const PROVIDER_NAME: LanguageModelProviderName = LanguageModelProviderName::new("OpenRouter");
|
||||
@@ -96,7 +96,6 @@ pub struct State {
|
||||
http_client: Arc<dyn HttpClient>,
|
||||
available_models: Vec<open_router::Model>,
|
||||
fetch_models_task: Option<Task<Result<(), LanguageModelCompletionError>>>,
|
||||
settings: OpenRouterSettings,
|
||||
}
|
||||
|
||||
impl State {
|
||||
@@ -171,14 +170,17 @@ impl State {
|
||||
impl OpenRouterLanguageModelProvider {
|
||||
pub fn new(http_client: Arc<dyn HttpClient>, cx: &mut App) -> Self {
|
||||
let state = cx.new(|cx| {
|
||||
cx.observe_global::<SettingsStore>(|this: &mut State, cx| {
|
||||
let current_settings = &AllLanguageModelSettings::get_global(cx).open_router;
|
||||
let settings_changed = current_settings != &this.settings;
|
||||
if settings_changed {
|
||||
this.settings = current_settings.clone();
|
||||
this.authenticate(cx).detach();
|
||||
cx.observe_global::<SettingsStore>({
|
||||
let mut last_settings = OpenRouterLanguageModelProvider::settings(cx).clone();
|
||||
move |this: &mut State, cx| {
|
||||
let current_settings = OpenRouterLanguageModelProvider::settings(cx);
|
||||
let settings_changed = current_settings != &last_settings;
|
||||
if settings_changed {
|
||||
last_settings = current_settings.clone();
|
||||
this.authenticate(cx).detach();
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
})
|
||||
.detach();
|
||||
State {
|
||||
@@ -186,7 +188,6 @@ impl OpenRouterLanguageModelProvider {
|
||||
http_client: http_client.clone(),
|
||||
available_models: Vec::new(),
|
||||
fetch_models_task: None,
|
||||
settings: OpenRouterSettings::default(),
|
||||
}
|
||||
});
|
||||
|
||||
@@ -194,7 +195,7 @@ impl OpenRouterLanguageModelProvider {
|
||||
}
|
||||
|
||||
fn settings(cx: &App) -> &OpenRouterSettings {
|
||||
&AllLanguageModelSettings::get_global(cx).open_router
|
||||
&crate::AllLanguageModelSettings::get_global(cx).open_router
|
||||
}
|
||||
|
||||
fn api_url(cx: &App) -> SharedString {
|
||||
@@ -322,17 +323,11 @@ impl OpenRouterLanguageModel {
|
||||
>,
|
||||
> {
|
||||
let http_client = self.http_client.clone();
|
||||
let api_key_and_url = self.state.read_with(cx, |state, cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, cx| {
|
||||
let api_url = OpenRouterLanguageModelProvider::api_url(cx);
|
||||
let api_key = state.api_key_state.key(&api_url);
|
||||
(api_key, api_url)
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(LanguageModelCompletionError::Other(err)))
|
||||
.boxed();
|
||||
}
|
||||
(state.api_key_state.key(&api_url), api_url)
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped").into())).boxed();
|
||||
};
|
||||
|
||||
async move {
|
||||
@@ -795,6 +790,10 @@ impl ConfigurationView {
|
||||
return;
|
||||
}
|
||||
|
||||
// url changes can cause the editor to be displayed again
|
||||
self.api_key_editor
|
||||
.update(cx, |editor, cx| editor.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
state
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Result, anyhow};
|
||||
use collections::BTreeMap;
|
||||
use futures::{FutureExt, StreamExt, future::BoxFuture};
|
||||
use futures::{FutureExt, StreamExt, future, future::BoxFuture};
|
||||
use gpui::{AnyView, App, AsyncApp, Context, Entity, SharedString, Task, Window};
|
||||
use http_client::HttpClient;
|
||||
use language_model::{
|
||||
@@ -219,16 +219,11 @@ impl VercelLanguageModel {
|
||||
{
|
||||
let http_client = self.http_client.clone();
|
||||
|
||||
let api_key_and_url = self.state.read_with(cx, |state, cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, cx| {
|
||||
let api_url = VercelLanguageModelProvider::api_url(cx);
|
||||
let api_key = state.api_key_state.key(&api_url);
|
||||
(api_key, api_url)
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(err)).boxed();
|
||||
}
|
||||
(state.api_key_state.key(&api_url), api_url)
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped"))).boxed();
|
||||
};
|
||||
|
||||
let future = self.request_limiter.stream(async move {
|
||||
@@ -429,6 +424,10 @@ impl ConfigurationView {
|
||||
return;
|
||||
}
|
||||
|
||||
// url changes can cause the editor to be displayed again
|
||||
self.api_key_editor
|
||||
.update(cx, |editor, cx| editor.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
state
|
||||
@@ -439,11 +438,8 @@ impl ConfigurationView {
|
||||
}
|
||||
|
||||
fn reset_api_key(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.api_key_editor.update(cx, |input, cx| {
|
||||
input.editor.update(cx, |editor, cx| {
|
||||
editor.set_text("", window, cx);
|
||||
});
|
||||
});
|
||||
self.api_key_editor
|
||||
.update(cx, |input, cx| input.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use anyhow::{Result, anyhow};
|
||||
use collections::BTreeMap;
|
||||
use futures::{FutureExt, StreamExt, future::BoxFuture};
|
||||
use futures::{FutureExt, StreamExt, future, future::BoxFuture};
|
||||
use gpui::{AnyView, App, AsyncApp, Context, Entity, Task, Window};
|
||||
use http_client::HttpClient;
|
||||
use language_model::{
|
||||
@@ -219,16 +219,11 @@ impl XAiLanguageModel {
|
||||
{
|
||||
let http_client = self.http_client.clone();
|
||||
|
||||
let api_key_and_url = self.state.read_with(cx, |state, cx| {
|
||||
let Ok((api_key, api_url)) = self.state.read_with(cx, |state, cx| {
|
||||
let api_url = XAiLanguageModelProvider::api_url(cx);
|
||||
let api_key = state.api_key_state.key(&api_url);
|
||||
(api_key, api_url)
|
||||
});
|
||||
let (api_key, api_url) = match api_key_and_url {
|
||||
Ok(api_key_and_url) => api_key_and_url,
|
||||
Err(err) => {
|
||||
return futures::future::ready(Err(err)).boxed();
|
||||
}
|
||||
(state.api_key_state.key(&api_url), api_url)
|
||||
}) else {
|
||||
return future::ready(Err(anyhow!("App state dropped"))).boxed();
|
||||
};
|
||||
|
||||
let future = self.request_limiter.stream(async move {
|
||||
@@ -423,6 +418,10 @@ impl ConfigurationView {
|
||||
return;
|
||||
}
|
||||
|
||||
// url changes can cause the editor to be displayed again
|
||||
self.api_key_editor
|
||||
.update(cx, |editor, cx| editor.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
state
|
||||
@@ -433,11 +432,8 @@ impl ConfigurationView {
|
||||
}
|
||||
|
||||
fn reset_api_key(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
self.api_key_editor.update(cx, |input, cx| {
|
||||
input.editor.update(cx, |editor, cx| {
|
||||
editor.set_text("", window, cx);
|
||||
});
|
||||
});
|
||||
self.api_key_editor
|
||||
.update(cx, |input, cx| input.set_text("", window, cx));
|
||||
|
||||
let state = self.state.clone();
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
|
||||
@@ -9,6 +9,7 @@ use component::{example_group, single_example};
|
||||
use editor::{Editor, EditorElement, EditorStyle};
|
||||
use gpui::{App, Entity, FocusHandle, Focusable, FontStyle, Hsla, TextStyle};
|
||||
use settings::Settings;
|
||||
use std::sync::Arc;
|
||||
use theme::ThemeSettings;
|
||||
use ui::prelude::*;
|
||||
|
||||
@@ -101,6 +102,11 @@ impl SingleLineInput {
|
||||
pub fn text(&self, cx: &App) -> String {
|
||||
self.editor().read(cx).text(cx)
|
||||
}
|
||||
|
||||
pub fn set_text(&self, text: impl Into<Arc<str>>, window: &mut Window, cx: &mut App) {
|
||||
self.editor()
|
||||
.update(cx, |editor, cx| editor.set_text(text, window, cx))
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for SingleLineInput {
|
||||
|
||||
Reference in New Issue
Block a user