diff --git a/Cargo.lock b/Cargo.lock index 2a33d3d16893655a1a0f81614448875d6b558141..d33f1d02903b717b479d8dfd745ff75d4d49846a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8706,7 +8706,6 @@ dependencies = [ "settings", "smol", "strum 0.27.1", - "theme", "thiserror 2.0.12", "tiktoken-rs", "tokio", diff --git a/crates/language_models/Cargo.toml b/crates/language_models/Cargo.toml index 8a2a681c26ede21ce948b6667b4aaea589724dcf..28cfe69d96d15f26c567e7e61e5ebb5f329371f3 100644 --- a/crates/language_models/Cargo.toml +++ b/crates/language_models/Cargo.toml @@ -28,7 +28,6 @@ convert_case.workspace = true copilot.workspace = true credentials_provider.workspace = true deepseek = { workspace = true, features = ["schemars"] } -editor.workspace = true fs.workspace = true futures.workspace = true google_ai = { workspace = true, features = ["schemars"] } @@ -52,7 +51,6 @@ serde_json.workspace = true settings.workspace = true smol.workspace = true strum.workspace = true -theme.workspace = true thiserror.workspace = true tiktoken-rs.workspace = true tokio = { workspace = true, features = ["rt", "rt-multi-thread"] } diff --git a/crates/language_models/src/provider/anthropic.rs b/crates/language_models/src/provider/anthropic.rs index c9cd56f6328f3070cafe2b7d7ff58f8e5315a3da..ae2d324b6feed83ed98af24fbbe98b1eea481f54 100644 --- a/crates/language_models/src/provider/anthropic.rs +++ b/crates/language_models/src/provider/anthropic.rs @@ -1,14 +1,11 @@ -use crate::api_key::ApiKeyState; -use crate::ui::InstructionListItem; use anthropic::{ ANTHROPIC_API_URL, AnthropicError, AnthropicModelMode, ContentDelta, Event, ResponseContent, ToolResultContent, ToolResultPart, Usage, }; use anyhow::{Result, anyhow}; use collections::{BTreeMap, HashMap}; -use editor::{Editor, EditorElement, EditorStyle}; use futures::{FutureExt, Stream, StreamExt, future, future::BoxFuture, stream::BoxStream}; -use gpui::{AnyView, App, AsyncApp, Context, Entity, FontStyle, Task, TextStyle, WhiteSpace}; +use gpui::{AnyView, App, AsyncApp, Context, Entity, Task}; use http_client::HttpClient; use language_model::{ AuthenticateError, ConfigurationViewTargetAgent, LanguageModel, @@ -23,11 +20,14 @@ use std::pin::Pin; use std::str::FromStr; use std::sync::{Arc, LazyLock}; use strum::IntoEnumIterator; -use theme::ThemeSettings; use ui::{Icon, IconName, List, Tooltip, prelude::*}; +use ui_input::SingleLineInput; use util::{ResultExt, truncate_and_trailoff}; use zed_env_vars::{EnvVar, env_var}; +use crate::api_key::ApiKeyState; +use crate::ui::InstructionListItem; + pub use settings::AnthropicAvailableModel as AvailableModel; const PROVIDER_ID: LanguageModelProviderId = language_model::ANTHROPIC_PROVIDER_ID; @@ -42,7 +42,7 @@ pub struct AnthropicSettings { pub struct AnthropicLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } const API_KEY_ENV_VAR_NAME: &str = "ANTHROPIC_API_KEY"; @@ -123,7 +123,7 @@ impl AnthropicLanguageModelProvider { impl LanguageModelProviderState for AnthropicLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -226,7 +226,7 @@ impl LanguageModelProvider for AnthropicLanguageModelProvider { pub struct AnthropicModel { id: LanguageModelId, model: anthropic::Model, - state: gpui::Entity, + state: Entity, http_client: Arc, request_limiter: RateLimiter, } @@ -823,8 +823,8 @@ fn convert_usage(usage: &Usage) -> language_model::TokenUsage { } struct ConfigurationView { - api_key_editor: Entity, - state: gpui::Entity, + api_key_editor: Entity, + state: Entity, load_credentials_task: Option>, target_agent: ConfigurationViewTargetAgent, } @@ -833,7 +833,7 @@ impl ConfigurationView { const PLACEHOLDER_TEXT: &'static str = "sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; fn new( - state: gpui::Entity, + state: Entity, target_agent: ConfigurationViewTargetAgent, window: &mut Window, cx: &mut Context, @@ -862,11 +862,7 @@ impl ConfigurationView { })); Self { - api_key_editor: cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text(Self::PLACEHOLDER_TEXT, window, cx); - editor - }), + api_key_editor: cx.new(|cx| SingleLineInput::new(window, cx, Self::PLACEHOLDER_TEXT)), state, load_credentials_task, target_agent, @@ -905,31 +901,6 @@ impl ConfigurationView { .detach_and_log_err(cx); } - fn render_api_key_editor(&self, cx: &mut Context) -> impl IntoElement { - let settings = ThemeSettings::get_global(cx); - let text_style = TextStyle { - color: cx.theme().colors().text, - font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features.clone(), - font_fallbacks: settings.ui_font.fallbacks.clone(), - font_size: rems(0.875).into(), - font_weight: settings.ui_font.weight, - font_style: FontStyle::Normal, - line_height: relative(1.3), - white_space: WhiteSpace::Normal, - ..Default::default() - }; - EditorElement::new( - &self.api_key_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - fn should_render_editor(&self, cx: &mut Context) -> bool { !self.state.read(cx).is_authenticated() } @@ -962,18 +933,7 @@ impl Render for ConfigurationView { InstructionListItem::text_only("Paste your API key below and hit enter to start using the agent") ) ) - .child( - h_flex() - .w_full() - .my_2() - .px_2() - .py_1() - .bg(cx.theme().colors().editor_background) - .border_1() - .border_color(cx.theme().colors().border) - .rounded_sm() - .child(self.render_api_key_editor(cx)), - ) + .child(self.api_key_editor.clone()) .child( Label::new( format!("You can also assign the {API_KEY_ENV_VAR_NAME} environment variable and restart Zed."), diff --git a/crates/language_models/src/provider/bedrock.rs b/crates/language_models/src/provider/bedrock.rs index a81e4b30d21f6ecdefc9361017c2d6fd979acced..47dd565f6af64d5ddb1d19cd6ed95ceeffd57cc9 100644 --- a/crates/language_models/src/provider/bedrock.rs +++ b/crates/language_models/src/provider/bedrock.rs @@ -23,12 +23,8 @@ use bedrock::{ }; use collections::{BTreeMap, HashMap}; use credentials_provider::CredentialsProvider; -use editor::{Editor, EditorElement, EditorStyle}; use futures::{FutureExt, Stream, StreamExt, future::BoxFuture, stream::BoxStream}; -use gpui::{ - AnyView, App, AsyncApp, Context, Entity, FontStyle, FontWeight, Subscription, Task, TextStyle, - WhiteSpace, -}; +use gpui::{AnyView, App, AsyncApp, Context, Entity, FontWeight, Subscription, Task}; use gpui_tokio::Tokio; use http_client::HttpClient; use language_model::{ @@ -45,8 +41,8 @@ use serde_json::Value; use settings::{BedrockAvailableModel as AvailableModel, Settings, SettingsStore}; use smol::lock::OnceCell; use strum::{EnumIter, IntoEnumIterator, IntoStaticStr}; -use theme::ThemeSettings; use ui::{Icon, IconName, List, Tooltip, prelude::*}; +use ui_input::SingleLineInput; use util::ResultExt; use crate::AllLanguageModelSettings; @@ -243,7 +239,7 @@ impl State { pub struct BedrockLanguageModelProvider { http_client: AwsHttpClient, handle: tokio::runtime::Handle, - state: gpui::Entity, + state: Entity, } impl BedrockLanguageModelProvider { @@ -366,7 +362,7 @@ impl LanguageModelProvider for BedrockLanguageModelProvider { impl LanguageModelProviderState for BedrockLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -377,7 +373,7 @@ struct BedrockModel { http_client: AwsHttpClient, handle: tokio::runtime::Handle, client: OnceCell, - state: gpui::Entity, + state: Entity, request_limiter: RateLimiter, } @@ -1010,11 +1006,11 @@ pub fn map_to_language_model_completion_events( } struct ConfigurationView { - access_key_id_editor: Entity, - secret_access_key_editor: Entity, - session_token_editor: Entity, - region_editor: Entity, - state: gpui::Entity, + access_key_id_editor: Entity, + secret_access_key_editor: Entity, + session_token_editor: Entity, + region_editor: Entity, + state: Entity, load_credentials_task: Option>, } @@ -1025,7 +1021,7 @@ impl ConfigurationView { const PLACEHOLDER_SESSION_TOKEN_TEXT: &'static str = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; const PLACEHOLDER_REGION: &'static str = "us-east-1"; - fn new(state: gpui::Entity, window: &mut Window, cx: &mut Context) -> Self { + fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { cx.observe(&state, |_, _, cx| { cx.notify(); }) @@ -1051,24 +1047,19 @@ impl ConfigurationView { Self { access_key_id_editor: cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text(Self::PLACEHOLDER_ACCESS_KEY_ID_TEXT, window, cx); - editor + SingleLineInput::new(window, cx, Self::PLACEHOLDER_ACCESS_KEY_ID_TEXT) + .label("Access Key ID") }), secret_access_key_editor: cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text(Self::PLACEHOLDER_SECRET_ACCESS_KEY_TEXT, window, cx); - editor + SingleLineInput::new(window, cx, Self::PLACEHOLDER_SECRET_ACCESS_KEY_TEXT) + .label("Secret Access Key") }), session_token_editor: cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text(Self::PLACEHOLDER_SESSION_TOKEN_TEXT, window, cx); - editor + SingleLineInput::new(window, cx, Self::PLACEHOLDER_SESSION_TOKEN_TEXT) + .label("Session Token (Optional)") }), region_editor: cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text(Self::PLACEHOLDER_REGION, window, cx); - editor + SingleLineInput::new(window, cx, Self::PLACEHOLDER_REGION).label("Region") }), state, load_credentials_task, @@ -1148,41 +1139,6 @@ impl ConfigurationView { .detach_and_log_err(cx); } - fn make_text_style(&self, cx: &Context) -> TextStyle { - let settings = ThemeSettings::get_global(cx); - TextStyle { - color: cx.theme().colors().text, - font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features.clone(), - font_fallbacks: settings.ui_font.fallbacks.clone(), - font_size: rems(0.875).into(), - font_weight: settings.ui_font.weight, - font_style: FontStyle::Normal, - line_height: relative(1.3), - background_color: None, - underline: None, - strikethrough: None, - white_space: WhiteSpace::Normal, - text_overflow: None, - text_align: Default::default(), - line_clamp: None, - } - } - - fn make_input_styles(&self, cx: &Context) -> Div { - let bg_color = cx.theme().colors().editor_background; - let border_color = cx.theme().colors().border; - - h_flex() - .w_full() - .px_2() - .py_1() - .bg(bg_color) - .border_1() - .border_color(border_color) - .rounded_sm() - } - fn should_render_editor(&self, cx: &Context) -> bool { self.state.read(cx).is_authenticated() } @@ -1265,8 +1221,8 @@ impl Render for ConfigurationView { ) ) ) - .child(self.render_static_credentials_ui(cx)) - .child(self.render_common_fields(cx)) + .child(self.render_static_credentials_ui()) + .child(self.region_editor.clone()) .child( Label::new( format!("You can also assign the {ZED_BEDROCK_ACCESS_KEY_ID_VAR}, {ZED_BEDROCK_SECRET_ACCESS_KEY_VAR} AND {ZED_BEDROCK_REGION_VAR} environment variables and restart Zed."), @@ -1287,63 +1243,7 @@ impl Render for ConfigurationView { } impl ConfigurationView { - fn render_access_key_id_editor(&self, cx: &mut Context) -> impl IntoElement { - let text_style = self.make_text_style(cx); - - EditorElement::new( - &self.access_key_id_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - - fn render_secret_key_editor(&self, cx: &mut Context) -> impl IntoElement { - let text_style = self.make_text_style(cx); - - EditorElement::new( - &self.secret_access_key_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - - fn render_session_token_editor(&self, cx: &mut Context) -> impl IntoElement { - let text_style = self.make_text_style(cx); - - EditorElement::new( - &self.session_token_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - - fn render_region_editor(&self, cx: &mut Context) -> impl IntoElement { - let text_style = self.make_text_style(cx); - - EditorElement::new( - &self.region_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - - fn render_static_credentials_ui(&self, cx: &mut Context) -> AnyElement { + fn render_static_credentials_ui(&self) -> AnyElement { v_flex() .my_2() .gap_1p5() @@ -1376,41 +1276,10 @@ impl ConfigurationView { "Enter these credentials below", )), ) - .child( - v_flex() - .gap_0p5() - .child(Label::new("Access Key ID").size(LabelSize::Small)) - .child( - self.make_input_styles(cx) - .child(self.render_access_key_id_editor(cx)), - ), - ) - .child( - v_flex() - .gap_0p5() - .child(Label::new("Secret Access Key").size(LabelSize::Small)) - .child(self.make_input_styles(cx).child(self.render_secret_key_editor(cx))), - ) - .child( - v_flex() - .gap_0p5() - .child(Label::new("Session Token (Optional)").size(LabelSize::Small)) - .child( - self.make_input_styles(cx) - .child(self.render_session_token_editor(cx)), - ), - ) - .into_any_element() - } - - fn render_common_fields(&self, cx: &mut Context) -> AnyElement { - v_flex() - .gap_0p5() - .child(Label::new("Region").size(LabelSize::Small)) - .child( - self.make_input_styles(cx) - .child(self.render_region_editor(cx)), - ) + .child(self.access_key_id_editor.clone()) + .child(self.secret_access_key_editor.clone()) + .child(self.session_token_editor.clone()) + .child(self.region_editor.clone()) .into_any_element() } } diff --git a/crates/language_models/src/provider/cloud.rs b/crates/language_models/src/provider/cloud.rs index a51a96853bcef4225b8815bc58324c7b12f338b9..cf73da02c68b168097c3a4690849a42d5b993bc7 100644 --- a/crates/language_models/src/provider/cloud.rs +++ b/crates/language_models/src/provider/cloud.rs @@ -76,7 +76,7 @@ impl From for AnthropicModelMode { pub struct CloudLanguageModelProvider { client: Arc, - state: gpui::Entity, + state: Entity, _maintain_client_status: Task<()>, } @@ -287,7 +287,7 @@ impl CloudLanguageModelProvider { impl LanguageModelProviderState for CloudLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } diff --git a/crates/language_models/src/provider/copilot_chat.rs b/crates/language_models/src/provider/copilot_chat.rs index b7ece55fed70beae543b9bd55e7635fa6a3fc04d..64a2c65f0d2bcc4240e980922930e24240ce3249 100644 --- a/crates/language_models/src/provider/copilot_chat.rs +++ b/crates/language_models/src/provider/copilot_chat.rs @@ -89,7 +89,7 @@ impl CopilotChatLanguageModelProvider { impl LanguageModelProviderState for CopilotChatLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } diff --git a/crates/language_models/src/provider/deepseek.rs b/crates/language_models/src/provider/deepseek.rs index a8f08a420664b10e4478df0b566382621ffeb760..ec420bfd83b427701ffa6eb13a9eb6035604f0b1 100644 --- a/crates/language_models/src/provider/deepseek.rs +++ b/crates/language_models/src/provider/deepseek.rs @@ -1,13 +1,10 @@ use anyhow::{Result, anyhow}; use collections::{BTreeMap, HashMap}; use deepseek::DEEPSEEK_API_URL; -use editor::{Editor, EditorElement, EditorStyle}; + use futures::Stream; use futures::{FutureExt, StreamExt, future, future::BoxFuture, stream::BoxStream}; -use gpui::{ - AnyView, App, AsyncApp, Context, Entity, FontStyle, SharedString, Task, TextStyle, WhiteSpace, - Window, -}; +use gpui::{AnyView, App, AsyncApp, Context, Entity, SharedString, Task, Window}; use http_client::HttpClient; use language_model::{ AuthenticateError, LanguageModel, LanguageModelCompletionError, LanguageModelCompletionEvent, @@ -21,8 +18,9 @@ use settings::{Settings, SettingsStore}; use std::pin::Pin; use std::str::FromStr; use std::sync::{Arc, LazyLock}; -use theme::ThemeSettings; + use ui::{Icon, IconName, List, prelude::*}; +use ui_input::SingleLineInput; use util::{ResultExt, truncate_and_trailoff}; use zed_env_vars::{EnvVar, env_var}; @@ -527,18 +525,15 @@ impl DeepSeekEventMapper { } struct ConfigurationView { - api_key_editor: Entity, + api_key_editor: Entity, state: Entity, load_credentials_task: Option>, } impl ConfigurationView { fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { - let api_key_editor = cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text("sk-00000000000000000000000000000000", window, cx); - editor - }); + let api_key_editor = + cx.new(|cx| SingleLineInput::new(window, cx, "sk-00000000000000000000000000000000")); cx.observe(&state, |_, _, cx| { cx.notify(); @@ -598,34 +593,6 @@ impl ConfigurationView { .detach_and_log_err(cx); } - fn render_api_key_editor(&self, cx: &mut Context) -> impl IntoElement { - let settings = ThemeSettings::get_global(cx); - let text_style = TextStyle { - color: cx.theme().colors().text, - font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features.clone(), - font_fallbacks: settings.ui_font.fallbacks.clone(), - font_size: rems(0.875).into(), - font_weight: settings.ui_font.weight, - font_style: FontStyle::Normal, - line_height: relative(1.3), - background_color: None, - underline: None, - strikethrough: None, - white_space: WhiteSpace::Normal, - ..Default::default() - }; - EditorElement::new( - &self.api_key_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - fn should_render_editor(&self, cx: &mut Context) -> bool { !self.state.read(cx).is_authenticated() } @@ -653,18 +620,7 @@ impl Render for ConfigurationView { "Paste your API key below and hit enter to start using the assistant", )), ) - .child( - h_flex() - .w_full() - .my_2() - .px_2() - .py_1() - .bg(cx.theme().colors().editor_background) - .border_1() - .border_color(cx.theme().colors().border) - .rounded_sm() - .child(self.render_api_key_editor(cx)), - ) + .child(self.api_key_editor.clone()) .child( Label::new(format!( "Or set the {API_KEY_ENV_VAR_NAME} environment variable." diff --git a/crates/language_models/src/provider/google.rs b/crates/language_models/src/provider/google.rs index 48712e33a7afe4f1b669b551e66423a8c8b2c995..f6ac364611c0e121115a4bd692893ed8bfa89ab3 100644 --- a/crates/language_models/src/provider/google.rs +++ b/crates/language_models/src/provider/google.rs @@ -1,16 +1,12 @@ use anyhow::{Context as _, Result, anyhow}; use collections::BTreeMap; use credentials_provider::CredentialsProvider; -use editor::{Editor, EditorElement, EditorStyle}; use futures::{FutureExt, Stream, StreamExt, future, future::BoxFuture}; use google_ai::{ FunctionDeclaration, GenerateContentResponse, GoogleModelMode, Part, SystemInstruction, ThinkingConfig, UsageMetadata, }; -use gpui::{ - AnyView, App, AsyncApp, Context, Entity, FontStyle, SharedString, Task, TextStyle, WhiteSpace, - Window, -}; +use gpui::{AnyView, App, AsyncApp, Context, Entity, SharedString, Task, Window}; use http_client::HttpClient; use language_model::{ AuthenticateError, ConfigurationViewTargetAgent, LanguageModelCompletionError, @@ -32,8 +28,8 @@ use std::sync::{ atomic::{self, AtomicU64}, }; use strum::IntoEnumIterator; -use theme::ThemeSettings; use ui::{Icon, IconName, List, Tooltip, prelude::*}; +use ui_input::SingleLineInput; use util::{ResultExt, truncate_and_trailoff}; use zed_env_vars::EnvVar; @@ -63,7 +59,7 @@ pub enum ModelMode { pub struct GoogleLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -165,7 +161,7 @@ impl GoogleLanguageModelProvider { impl LanguageModelProviderState for GoogleLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -255,7 +251,7 @@ impl LanguageModelProvider for GoogleLanguageModelProvider { pub struct GoogleLanguageModel { id: LanguageModelId, model: google_ai::Model, - state: gpui::Entity, + state: Entity, http_client: Arc, request_limiter: RateLimiter, } @@ -755,15 +751,15 @@ fn convert_usage(usage: &UsageMetadata) -> language_model::TokenUsage { } struct ConfigurationView { - api_key_editor: Entity, - state: gpui::Entity, + api_key_editor: Entity, + state: Entity, target_agent: language_model::ConfigurationViewTargetAgent, load_credentials_task: Option>, } impl ConfigurationView { fn new( - state: gpui::Entity, + state: Entity, target_agent: language_model::ConfigurationViewTargetAgent, window: &mut Window, cx: &mut Context, @@ -792,11 +788,7 @@ impl ConfigurationView { })); Self { - api_key_editor: cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text("AIzaSy...", window, cx); - editor - }), + api_key_editor: cx.new(|cx| SingleLineInput::new(window, cx, "AIzaSy...")), target_agent, state, load_credentials_task, @@ -835,31 +827,6 @@ impl ConfigurationView { .detach_and_log_err(cx); } - fn render_api_key_editor(&self, cx: &mut Context) -> impl IntoElement { - let settings = ThemeSettings::get_global(cx); - let text_style = TextStyle { - color: cx.theme().colors().text, - font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features.clone(), - font_fallbacks: settings.ui_font.fallbacks.clone(), - font_size: rems(0.875).into(), - font_weight: settings.ui_font.weight, - font_style: FontStyle::Normal, - line_height: relative(1.3), - white_space: WhiteSpace::Normal, - ..Default::default() - }; - EditorElement::new( - &self.api_key_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - fn should_render_editor(&self, cx: &mut Context) -> bool { !self.state.read(cx).is_authenticated() } @@ -890,18 +857,7 @@ impl Render for ConfigurationView { "Paste your API key below and hit enter to start using the assistant", )), ) - .child( - h_flex() - .w_full() - .my_2() - .px_2() - .py_1() - .bg(cx.theme().colors().editor_background) - .border_1() - .border_color(cx.theme().colors().border) - .rounded_sm() - .child(self.render_api_key_editor(cx)), - ) + .child(self.api_key_editor.clone()) .child( Label::new( format!("You can also assign the {GEMINI_API_KEY_VAR_NAME} environment variable and restart Zed."), diff --git a/crates/language_models/src/provider/lmstudio.rs b/crates/language_models/src/provider/lmstudio.rs index f98906f5be1cc811e124c89cf61050fdf98c967d..c0b3509c0e2c9636ca48cdb0de0cc6ed32a2b792 100644 --- a/crates/language_models/src/provider/lmstudio.rs +++ b/crates/language_models/src/provider/lmstudio.rs @@ -2,7 +2,7 @@ use anyhow::{Result, anyhow}; use collections::HashMap; use futures::Stream; use futures::{FutureExt, StreamExt, future::BoxFuture, stream::BoxStream}; -use gpui::{AnyView, App, AsyncApp, Context, Subscription, Task}; +use gpui::{AnyView, App, AsyncApp, Context, Entity, Subscription, Task}; use http_client::HttpClient; use language_model::{ AuthenticateError, LanguageModelCompletionError, LanguageModelCompletionEvent, @@ -41,7 +41,7 @@ pub struct LmStudioSettings { pub struct LmStudioLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -162,7 +162,7 @@ impl LmStudioLanguageModelProvider { impl LanguageModelProviderState for LmStudioLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -635,12 +635,12 @@ fn add_message_content_part( } struct ConfigurationView { - state: gpui::Entity, + state: Entity, loading_models_task: Option>, } impl ConfigurationView { - pub fn new(state: gpui::Entity, cx: &mut Context) -> Self { + pub fn new(state: Entity, cx: &mut Context) -> Self { let loading_models_task = Some(cx.spawn({ let state = state.clone(); async move |this, cx| { diff --git a/crates/language_models/src/provider/mistral.rs b/crates/language_models/src/provider/mistral.rs index b3375e528c29052f3e5451e20c40abf0fe8a10ad..7623f123c60e75a9c1fc6716e56075e4ea5b882b 100644 --- a/crates/language_models/src/provider/mistral.rs +++ b/crates/language_models/src/provider/mistral.rs @@ -1,11 +1,7 @@ use anyhow::{Result, anyhow}; use collections::BTreeMap; -use editor::{Editor, EditorElement, EditorStyle}; use futures::{FutureExt, Stream, StreamExt, future, future::BoxFuture, stream::BoxStream}; -use gpui::{ - AnyView, App, AsyncApp, Context, Entity, FontStyle, SharedString, Task, TextStyle, WhiteSpace, - Window, -}; +use gpui::{AnyView, App, AsyncApp, Context, Entity, SharedString, Task, Window}; use http_client::HttpClient; use language_model::{ AuthenticateError, LanguageModel, LanguageModelCompletionError, LanguageModelCompletionEvent, @@ -22,8 +18,8 @@ use std::pin::Pin; use std::str::FromStr; use std::sync::{Arc, LazyLock}; use strum::IntoEnumIterator; -use theme::ThemeSettings; use ui::{Icon, IconName, List, Tooltip, prelude::*}; +use ui_input::SingleLineInput; use util::{ResultExt, truncate_and_trailoff}; use zed_env_vars::{EnvVar, env_var}; @@ -43,7 +39,7 @@ pub struct MistralSettings { pub struct MistralLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -121,7 +117,7 @@ impl MistralLanguageModelProvider { impl LanguageModelProviderState for MistralLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -215,7 +211,7 @@ impl LanguageModelProvider for MistralLanguageModelProvider { pub struct MistralLanguageModel { id: LanguageModelId, model: mistral::Model, - state: gpui::Entity, + state: Entity, http_client: Arc, request_limiter: RateLimiter, } @@ -694,18 +690,15 @@ struct RawToolCall { } struct ConfigurationView { - api_key_editor: Entity, - state: gpui::Entity, + api_key_editor: Entity, + state: Entity, load_credentials_task: Option>, } impl ConfigurationView { - fn new(state: gpui::Entity, window: &mut Window, cx: &mut Context) -> Self { - let api_key_editor = cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text("0aBCDEFGhIjKLmNOpqrSTUVwxyzabCDE1f2", window, cx); - editor - }); + fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { + let api_key_editor = + cx.new(|cx| SingleLineInput::new(window, cx, "0aBCDEFGhIjKLmNOpqrSTUVwxyzabCDE1f2")); cx.observe(&state, |_, _, cx| { cx.notify(); @@ -770,31 +763,6 @@ impl ConfigurationView { .detach_and_log_err(cx); } - fn render_api_key_editor(&self, cx: &mut Context) -> impl IntoElement { - let settings = ThemeSettings::get_global(cx); - let text_style = TextStyle { - color: cx.theme().colors().text, - font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features.clone(), - font_fallbacks: settings.ui_font.fallbacks.clone(), - font_size: rems(0.875).into(), - font_weight: settings.ui_font.weight, - font_style: FontStyle::Normal, - line_height: relative(1.3), - white_space: WhiteSpace::Normal, - ..Default::default() - }; - EditorElement::new( - &self.api_key_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - fn should_render_editor(&self, cx: &mut Context) -> bool { !self.state.read(cx).is_authenticated() } @@ -825,18 +793,7 @@ impl Render for ConfigurationView { "Paste your API key below and hit enter to start using the assistant", )), ) - .child( - h_flex() - .w_full() - .my_2() - .px_2() - .py_1() - .bg(cx.theme().colors().editor_background) - .border_1() - .border_color(cx.theme().colors().border) - .rounded_sm() - .child(self.render_api_key_editor(cx)), - ) + .child(self.api_key_editor.clone()) .child( Label::new( format!("You can also assign the {API_KEY_ENV_VAR_NAME} environment variable and restart Zed."), diff --git a/crates/language_models/src/provider/ollama.rs b/crates/language_models/src/provider/ollama.rs index 9e9c88dd9914e73fd70d992090d01ae04465dbbc..d3a4289f24f651507ed493af228ac30314d975d6 100644 --- a/crates/language_models/src/provider/ollama.rs +++ b/crates/language_models/src/provider/ollama.rs @@ -2,7 +2,7 @@ use anyhow::{Result, anyhow}; use fs::Fs; use futures::{FutureExt, StreamExt, future::BoxFuture, stream::BoxStream}; use futures::{Stream, TryFutureExt, stream}; -use gpui::{AnyView, App, AsyncApp, Context, Task}; +use gpui::{AnyView, App, AsyncApp, Context, CursorStyle, Entity, Task}; use http_client::HttpClient; use language_model::{ AuthenticateError, LanguageModel, LanguageModelCompletionError, LanguageModelCompletionEvent, @@ -48,7 +48,7 @@ pub struct OllamaSettings { pub struct OllamaLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -209,7 +209,7 @@ impl OllamaLanguageModelProvider { impl LanguageModelProviderState for OllamaLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -322,7 +322,7 @@ pub struct OllamaLanguageModel { model: ollama::Model, http_client: Arc, request_limiter: RateLimiter, - state: gpui::Entity, + state: Entity, } impl OllamaLanguageModel { @@ -623,13 +623,13 @@ fn map_to_language_model_completion_events( } struct ConfigurationView { - api_key_editor: gpui::Entity, - api_url_editor: gpui::Entity, - state: gpui::Entity, + api_key_editor: Entity, + api_url_editor: Entity, + state: Entity, } impl ConfigurationView { - pub fn new(state: gpui::Entity, window: &mut Window, cx: &mut Context) -> Self { + pub fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { let api_key_editor = cx.new(|cx| SingleLineInput::new(window, cx, "63e02e...").label("API key")); @@ -900,7 +900,7 @@ impl Render for ConfigurationView { this.child( ButtonLike::new("connected") .disabled(true) - .cursor_style(gpui::CursorStyle::Arrow) + .cursor_style(CursorStyle::Arrow) .child( h_flex() .gap_2() diff --git a/crates/language_models/src/provider/open_ai.rs b/crates/language_models/src/provider/open_ai.rs index ade2e47ca39ebfdc48806380b541ed7d97d4d3da..3eaaa8b58598328e6e843b1f86b8f4e5cbd04c1e 100644 --- a/crates/language_models/src/provider/open_ai.rs +++ b/crates/language_models/src/provider/open_ai.rs @@ -41,7 +41,7 @@ pub struct OpenAiSettings { pub struct OpenAiLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -119,7 +119,7 @@ impl OpenAiLanguageModelProvider { impl LanguageModelProviderState for OpenAiLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -203,7 +203,7 @@ impl LanguageModelProvider for OpenAiLanguageModelProvider { pub struct OpenAiLanguageModel { id: LanguageModelId, model: open_ai::Model, - state: gpui::Entity, + state: Entity, http_client: Arc, request_limiter: RateLimiter, } @@ -676,12 +676,12 @@ pub fn count_open_ai_tokens( struct ConfigurationView { api_key_editor: Entity, - state: gpui::Entity, + state: Entity, load_credentials_task: Option>, } impl ConfigurationView { - fn new(state: gpui::Entity, window: &mut Window, cx: &mut Context) -> Self { + fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { let api_key_editor = cx.new(|cx| { SingleLineInput::new( window, diff --git a/crates/language_models/src/provider/open_ai_compatible.rs b/crates/language_models/src/provider/open_ai_compatible.rs index 788a412a8232d43e92ec9195132efe21cf73bf00..cca49c982ce6e93614c4574a84ffaa4bd1d8f0c6 100644 --- a/crates/language_models/src/provider/open_ai_compatible.rs +++ b/crates/language_models/src/provider/open_ai_compatible.rs @@ -33,7 +33,7 @@ pub struct OpenAiCompatibleLanguageModelProvider { id: LanguageModelProviderId, name: LanguageModelProviderName, http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -125,7 +125,7 @@ impl OpenAiCompatibleLanguageModelProvider { impl LanguageModelProviderState for OpenAiCompatibleLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -195,7 +195,7 @@ pub struct OpenAiCompatibleLanguageModel { provider_id: LanguageModelProviderId, provider_name: LanguageModelProviderName, model: AvailableModel, - state: gpui::Entity, + state: Entity, http_client: Arc, request_limiter: RateLimiter, } @@ -341,12 +341,12 @@ impl LanguageModel for OpenAiCompatibleLanguageModel { struct ConfigurationView { api_key_editor: Entity, - state: gpui::Entity, + state: Entity, load_credentials_task: Option>, } impl ConfigurationView { - fn new(state: gpui::Entity, window: &mut Window, cx: &mut Context) -> Self { + fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { let api_key_editor = cx.new(|cx| { SingleLineInput::new( window, diff --git a/crates/language_models/src/provider/open_router.rs b/crates/language_models/src/provider/open_router.rs index bbc5c44cdc7835b4402543371d4677520bdcf645..5bfc97c41f60351288ccf08c3a86b4b0947ee997 100644 --- a/crates/language_models/src/provider/open_router.rs +++ b/crates/language_models/src/provider/open_router.rs @@ -1,10 +1,7 @@ use anyhow::{Result, anyhow}; use collections::HashMap; -use editor::{Editor, EditorElement, EditorStyle}; use futures::{FutureExt, Stream, StreamExt, future, future::BoxFuture}; -use gpui::{ - AnyView, App, AsyncApp, Context, Entity, FontStyle, SharedString, Task, TextStyle, WhiteSpace, -}; +use gpui::{AnyView, App, AsyncApp, Context, Entity, SharedString, Task}; use http_client::HttpClient; use language_model::{ AuthenticateError, LanguageModel, LanguageModelCompletionError, LanguageModelCompletionEvent, @@ -20,8 +17,8 @@ use settings::{OpenRouterAvailableModel as AvailableModel, Settings, SettingsSto use std::pin::Pin; use std::str::FromStr as _; use std::sync::{Arc, LazyLock}; -use theme::ThemeSettings; use ui::{Icon, IconName, List, Tooltip, prelude::*}; +use ui_input::SingleLineInput; use util::{ResultExt, truncate_and_trailoff}; use zed_env_vars::{EnvVar, env_var}; @@ -41,7 +38,7 @@ pub struct OpenRouterSettings { pub struct OpenRouterLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -174,7 +171,7 @@ impl OpenRouterLanguageModelProvider { impl LanguageModelProviderState for OpenRouterLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -260,7 +257,7 @@ impl LanguageModelProvider for OpenRouterLanguageModelProvider { pub struct OpenRouterLanguageModel { id: LanguageModelId, model: open_router::Model, - state: gpui::Entity, + state: Entity, http_client: Arc, request_limiter: RateLimiter, } @@ -695,21 +692,19 @@ pub fn count_open_router_tokens( } struct ConfigurationView { - api_key_editor: Entity, - state: gpui::Entity, + api_key_editor: Entity, + state: Entity, load_credentials_task: Option>, } impl ConfigurationView { - fn new(state: gpui::Entity, window: &mut Window, cx: &mut Context) -> Self { + fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { let api_key_editor = cx.new(|cx| { - let mut editor = Editor::single_line(window, cx); - editor.set_placeholder_text( - "sk_or_000000000000000000000000000000000000000000000000", + SingleLineInput::new( window, cx, - ); - editor + "sk_or_000000000000000000000000000000000000000000000000", + ) }); cx.observe(&state, |_, _, cx| { @@ -774,31 +769,6 @@ impl ConfigurationView { .detach_and_log_err(cx); } - fn render_api_key_editor(&self, cx: &mut Context) -> impl IntoElement { - let settings = ThemeSettings::get_global(cx); - let text_style = TextStyle { - color: cx.theme().colors().text, - font_family: settings.ui_font.family.clone(), - font_features: settings.ui_font.features.clone(), - font_fallbacks: settings.ui_font.fallbacks.clone(), - font_size: rems(0.875).into(), - font_weight: settings.ui_font.weight, - font_style: FontStyle::Normal, - line_height: relative(1.3), - white_space: WhiteSpace::Normal, - ..Default::default() - }; - EditorElement::new( - &self.api_key_editor, - EditorStyle { - background: cx.theme().colors().editor_background, - local_player: cx.theme().players().local(), - text: text_style, - ..Default::default() - }, - ) - } - fn should_render_editor(&self, cx: &mut Context) -> bool { !self.state.read(cx).is_authenticated() } @@ -829,18 +799,7 @@ impl Render for ConfigurationView { "Paste your API key below and hit enter to start using the assistant", )), ) - .child( - h_flex() - .w_full() - .my_2() - .px_2() - .py_1() - .bg(cx.theme().colors().editor_background) - .border_1() - .border_color(cx.theme().colors().border) - .rounded_sm() - .child(self.render_api_key_editor(cx)), - ) + .child(self.api_key_editor.clone()) .child( Label::new( format!("You can also assign the {API_KEY_ENV_VAR_NAME} environment variable and restart Zed."), diff --git a/crates/language_models/src/provider/vercel.rs b/crates/language_models/src/provider/vercel.rs index 4b2ebb8a165e4edd6f10908e85a04538b5f3a92c..ad12e5a628779eddf333bdd4f91bddbea016c402 100644 --- a/crates/language_models/src/provider/vercel.rs +++ b/crates/language_models/src/provider/vercel.rs @@ -36,7 +36,7 @@ pub struct VercelSettings { pub struct VercelLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -114,7 +114,7 @@ impl VercelLanguageModelProvider { impl LanguageModelProviderState for VercelLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -195,7 +195,7 @@ impl LanguageModelProvider for VercelLanguageModelProvider { pub struct VercelLanguageModel { id: LanguageModelId, model: vercel::Model, - state: gpui::Entity, + state: Entity, http_client: Arc, request_limiter: RateLimiter, } @@ -363,12 +363,12 @@ pub fn count_vercel_tokens( struct ConfigurationView { api_key_editor: Entity, - state: gpui::Entity, + state: Entity, load_credentials_task: Option>, } impl ConfigurationView { - fn new(state: gpui::Entity, window: &mut Window, cx: &mut Context) -> Self { + fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { let api_key_editor = cx.new(|cx| { SingleLineInput::new( window, diff --git a/crates/language_models/src/provider/x_ai.rs b/crates/language_models/src/provider/x_ai.rs index d75c8ce78c6c9ee86bf838739047470999a85bfe..4e9f5917077086cbbcf7e095eaf58b977e4037ab 100644 --- a/crates/language_models/src/provider/x_ai.rs +++ b/crates/language_models/src/provider/x_ai.rs @@ -36,7 +36,7 @@ pub struct XAiSettings { pub struct XAiLanguageModelProvider { http_client: Arc, - state: gpui::Entity, + state: Entity, } pub struct State { @@ -114,7 +114,7 @@ impl XAiLanguageModelProvider { impl LanguageModelProviderState for XAiLanguageModelProvider { type ObservableEntity = State; - fn observable_entity(&self) -> Option> { + fn observable_entity(&self) -> Option> { Some(self.state.clone()) } } @@ -195,7 +195,7 @@ impl LanguageModelProvider for XAiLanguageModelProvider { pub struct XAiLanguageModel { id: LanguageModelId, model: x_ai::Model, - state: gpui::Entity, + state: Entity, http_client: Arc, request_limiter: RateLimiter, } @@ -357,12 +357,12 @@ pub fn count_xai_tokens( struct ConfigurationView { api_key_editor: Entity, - state: gpui::Entity, + state: Entity, load_credentials_task: Option>, } impl ConfigurationView { - fn new(state: gpui::Entity, window: &mut Window, cx: &mut Context) -> Self { + fn new(state: Entity, window: &mut Window, cx: &mut Context) -> Self { let api_key_editor = cx.new(|cx| { SingleLineInput::new( window,