Update assistant config UI (#15630)
 - Remove assisstant_description for now. - Updates assistant config UI - Updates Ollama and zed.dev provider UIs - Updates download icon Release Notes: - N/A --------- Co-authored-by: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com> Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
This commit is contained in:
parent
3bd9a3f478
commit
70b2da78f8
10 changed files with 144 additions and 142 deletions
|
@ -7,9 +7,11 @@ mod role;
|
|||
pub mod settings;
|
||||
|
||||
use anyhow::Result;
|
||||
use client::Client;
|
||||
use client::{Client, UserStore};
|
||||
use futures::{future::BoxFuture, stream::BoxStream};
|
||||
use gpui::{AnyView, AppContext, AsyncAppContext, FocusHandle, SharedString, Task, WindowContext};
|
||||
use gpui::{
|
||||
AnyView, AppContext, AsyncAppContext, FocusHandle, Model, SharedString, Task, WindowContext,
|
||||
};
|
||||
pub use model::*;
|
||||
use project::Fs;
|
||||
pub(crate) use rate_limiter::*;
|
||||
|
@ -20,9 +22,14 @@ use schemars::JsonSchema;
|
|||
use serde::de::DeserializeOwned;
|
||||
use std::{future::Future, sync::Arc};
|
||||
|
||||
pub fn init(client: Arc<Client>, fs: Arc<dyn Fs>, cx: &mut AppContext) {
|
||||
pub fn init(
|
||||
user_store: Model<UserStore>,
|
||||
client: Arc<Client>,
|
||||
fs: Arc<dyn Fs>,
|
||||
cx: &mut AppContext,
|
||||
) {
|
||||
settings::init(fs, cx);
|
||||
registry::init(client, cx);
|
||||
registry::init(user_store, client, cx);
|
||||
}
|
||||
|
||||
pub trait LanguageModel: Send + Sync {
|
||||
|
|
|
@ -483,7 +483,7 @@ impl Render for ConfigurationView {
|
|||
.size_full()
|
||||
.on_action(cx.listener(Self::save_api_key))
|
||||
.children(
|
||||
INSTRUCTIONS.map(|instruction| Label::new(instruction).size(LabelSize::Small)),
|
||||
INSTRUCTIONS.map(|instruction| Label::new(instruction)),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
|
|
|
@ -5,10 +5,12 @@ use crate::{
|
|||
LanguageModelProviderState, LanguageModelRequest, RateLimiter,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _, Result};
|
||||
use client::Client;
|
||||
use client::{Client, UserStore};
|
||||
use collections::BTreeMap;
|
||||
use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
|
||||
use gpui::{AnyView, AppContext, AsyncAppContext, FocusHandle, ModelContext, Subscription, Task};
|
||||
use gpui::{
|
||||
AnyView, AppContext, AsyncAppContext, FocusHandle, Model, ModelContext, Subscription, Task,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{Settings, SettingsStore};
|
||||
|
@ -52,6 +54,7 @@ pub struct CloudLanguageModelProvider {
|
|||
|
||||
pub struct State {
|
||||
client: Arc<Client>,
|
||||
user_store: Model<UserStore>,
|
||||
status: client::Status,
|
||||
_subscription: Subscription,
|
||||
}
|
||||
|
@ -71,12 +74,13 @@ impl State {
|
|||
}
|
||||
|
||||
impl CloudLanguageModelProvider {
|
||||
pub fn new(client: Arc<Client>, cx: &mut AppContext) -> Self {
|
||||
pub fn new(user_store: Model<UserStore>, client: Arc<Client>, cx: &mut AppContext) -> Self {
|
||||
let mut status_rx = client.status();
|
||||
let status = *status_rx.borrow();
|
||||
|
||||
let state = cx.new_model(|cx| State {
|
||||
client: client.clone(),
|
||||
user_store,
|
||||
status,
|
||||
_subscription: cx.observe_global::<SettingsStore>(|_, cx| {
|
||||
cx.notify();
|
||||
|
@ -401,8 +405,9 @@ impl Render for ConfigurationView {
|
|||
const ACCOUNT_SETTINGS_URL: &str = "https://zed.dev/settings";
|
||||
|
||||
let is_connected = self.state.read(cx).is_connected();
|
||||
let plan = self.state.read(cx).user_store.read(cx).current_plan();
|
||||
|
||||
let is_pro = false;
|
||||
let is_pro = plan == Some(proto::Plan::ZedPro);
|
||||
|
||||
if is_connected {
|
||||
v_flex()
|
||||
|
@ -410,7 +415,7 @@ impl Render for ConfigurationView {
|
|||
.max_w_4_5()
|
||||
.child(Label::new(
|
||||
if is_pro {
|
||||
"You have full access to Zed's hosted models from Anthropic, OpenAI, Google through Zed Pro."
|
||||
"You have full access to Zed's hosted models from Anthropic, OpenAI, Google with faster speeds and higher limits through Zed Pro."
|
||||
} else {
|
||||
"You have basic access to models from Anthropic, OpenAI, Google and more through the Zed AI Free plan."
|
||||
}))
|
||||
|
|
|
@ -398,7 +398,7 @@ impl Render for ConfigurationView {
|
|||
.size_full()
|
||||
.on_action(cx.listener(Self::save_api_key))
|
||||
.children(
|
||||
INSTRUCTIONS.map(|instruction| Label::new(instruction).size(LabelSize::Small)),
|
||||
INSTRUCTIONS.map(|instruction| Label::new(instruction)),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
|
|
|
@ -7,7 +7,7 @@ use ollama::{
|
|||
};
|
||||
use settings::{Settings, SettingsStore};
|
||||
use std::{future, sync::Arc, time::Duration};
|
||||
use ui::{prelude::*, ButtonLike, ElevationIndex, Indicator};
|
||||
use ui::{prelude::*, ButtonLike, Indicator};
|
||||
|
||||
use crate::{
|
||||
settings::AllLanguageModelSettings, LanguageModel, LanguageModelId, LanguageModelName,
|
||||
|
@ -17,6 +17,7 @@ use crate::{
|
|||
|
||||
const OLLAMA_DOWNLOAD_URL: &str = "https://ollama.com/download";
|
||||
const OLLAMA_LIBRARY_URL: &str = "https://ollama.com/library";
|
||||
const OLLAMA_SITE: &str = "https://ollama.com/";
|
||||
|
||||
const PROVIDER_ID: &str = "ollama";
|
||||
const PROVIDER_NAME: &str = "Ollama";
|
||||
|
@ -303,81 +304,107 @@ impl ConfigurationView {
|
|||
.update(cx, |state, cx| state.fetch_models(cx))
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn render_download_button(&self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
ButtonLike::new("download_ollama_button")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.child(Label::new("Get Ollama"))
|
||||
.on_click(move |_, cx| cx.open_url(OLLAMA_DOWNLOAD_URL))
|
||||
}
|
||||
|
||||
fn render_retry_button(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
ButtonLike::new("retry_ollama_models")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.child(Label::new("Retry"))
|
||||
.on_click(cx.listener(move |this, _, cx| this.retry_connection(cx)))
|
||||
}
|
||||
|
||||
fn render_next_steps(&self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.p_4()
|
||||
.size_full()
|
||||
.gap_2()
|
||||
.child(
|
||||
Label::new("Once Ollama is on your machine, make sure to download a model or two.")
|
||||
.size(LabelSize::Large),
|
||||
)
|
||||
.child(
|
||||
h_flex().w_full().p_4().justify_center().gap_2().child(
|
||||
ButtonLike::new("view-models")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.child(Label::new("View Available Models"))
|
||||
.on_click(move |_, cx| cx.open_url(OLLAMA_LIBRARY_URL)),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ConfigurationView {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let is_authenticated = self.state.read(cx).is_authenticated();
|
||||
|
||||
if is_authenticated {
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(Indicator::dot().color(Color::Success))
|
||||
.child(Label::new("Ollama configured").size(LabelSize::Small)),
|
||||
)
|
||||
.into_any()
|
||||
} else {
|
||||
v_flex()
|
||||
let ollama_intro = "Get up and running with Llama 3.1, Mistral, Gemma 2, and other large language models with Ollama.";
|
||||
let ollama_reqs =
|
||||
"Ollama must be running with at least one model installed to use it in the assistant.";
|
||||
|
||||
let mut inline_code_bg = cx.theme().colors().editor_background;
|
||||
inline_code_bg.fade_out(0.5);
|
||||
|
||||
v_flex()
|
||||
.size_full()
|
||||
.gap_2()
|
||||
.child(Label::new("To use Ollama models via the assistant, Ollama must be running on your machine with at least one model downloaded.").size(LabelSize::Large))
|
||||
.gap_3()
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.gap_2()
|
||||
.p_1()
|
||||
.child(Label::new(ollama_intro))
|
||||
.child(Label::new(ollama_reqs))
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.child(Label::new("Once installed, try "))
|
||||
.child(
|
||||
div()
|
||||
.bg(inline_code_bg)
|
||||
.px_1p5()
|
||||
.rounded_md()
|
||||
.child(Label::new("ollama run llama3.1")),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.p_4()
|
||||
.justify_center()
|
||||
.pt_2()
|
||||
.justify_between()
|
||||
.gap_2()
|
||||
.child(
|
||||
self.render_download_button(cx)
|
||||
)
|
||||
.child(
|
||||
self.render_retry_button(cx)
|
||||
h_flex()
|
||||
.w_full()
|
||||
.gap_2()
|
||||
.map(|this| {
|
||||
if is_authenticated {
|
||||
this.child(
|
||||
Button::new("ollama-site", "Ollama")
|
||||
.style(ButtonStyle::Subtle)
|
||||
.icon(IconName::ExternalLink)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.icon_color(Color::Muted)
|
||||
.on_click(move |_, cx| cx.open_url(OLLAMA_SITE))
|
||||
.into_any_element(),
|
||||
)
|
||||
} else {
|
||||
this.child(
|
||||
Button::new("download_ollama_button", "Download Ollama")
|
||||
.style(ButtonStyle::Subtle)
|
||||
.icon(IconName::ExternalLink)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.icon_color(Color::Muted)
|
||||
.on_click(move |_, cx| cx.open_url(OLLAMA_DOWNLOAD_URL))
|
||||
.into_any_element(),
|
||||
)
|
||||
}
|
||||
})
|
||||
.child(
|
||||
Button::new("view-models", "All Models")
|
||||
.style(ButtonStyle::Subtle)
|
||||
.icon(IconName::ExternalLink)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.icon_color(Color::Muted)
|
||||
.on_click(move |_, cx| cx.open_url(OLLAMA_LIBRARY_URL)),
|
||||
),
|
||||
)
|
||||
.child(if is_authenticated {
|
||||
// This is only a button to ensure the spacing is correct
|
||||
// it should stay disabled
|
||||
ButtonLike::new("connected")
|
||||
.disabled(true)
|
||||
// Since this won't ever be clickable, we can use the arrow cursor
|
||||
.cursor_style(gpui::CursorStyle::Arrow)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(Indicator::dot().color(Color::Success))
|
||||
.child(Label::new("Connected"))
|
||||
.into_any_element(),
|
||||
)
|
||||
.into_any_element()
|
||||
} else {
|
||||
Button::new("retry_ollama_models", "Connect")
|
||||
.icon_position(IconPosition::Start)
|
||||
.icon(IconName::ArrowCircle)
|
||||
.on_click(cx.listener(move |this, _, cx| this.retry_connection(cx)))
|
||||
.into_any_element()
|
||||
}),
|
||||
)
|
||||
.child(self.render_next_steps(cx))
|
||||
.into_any()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,16 +7,16 @@ use crate::{
|
|||
LanguageModel, LanguageModelId, LanguageModelProvider, LanguageModelProviderId,
|
||||
LanguageModelProviderState,
|
||||
};
|
||||
use client::Client;
|
||||
use client::{Client, UserStore};
|
||||
use collections::BTreeMap;
|
||||
use gpui::{AppContext, EventEmitter, Global, Model, ModelContext};
|
||||
use std::sync::Arc;
|
||||
use ui::Context;
|
||||
|
||||
pub fn init(client: Arc<Client>, cx: &mut AppContext) {
|
||||
pub fn init(user_store: Model<UserStore>, client: Arc<Client>, cx: &mut AppContext) {
|
||||
let registry = cx.new_model(|cx| {
|
||||
let mut registry = LanguageModelRegistry::default();
|
||||
register_language_model_providers(&mut registry, client, cx);
|
||||
register_language_model_providers(&mut registry, user_store, client, cx);
|
||||
registry
|
||||
});
|
||||
cx.set_global(GlobalLanguageModelRegistry(registry));
|
||||
|
@ -24,6 +24,7 @@ pub fn init(client: Arc<Client>, cx: &mut AppContext) {
|
|||
|
||||
fn register_language_model_providers(
|
||||
registry: &mut LanguageModelRegistry,
|
||||
user_store: Model<UserStore>,
|
||||
client: Arc<Client>,
|
||||
cx: &mut ModelContext<LanguageModelRegistry>,
|
||||
) {
|
||||
|
@ -48,10 +49,14 @@ fn register_language_model_providers(
|
|||
registry.register_provider(CopilotChatLanguageModelProvider::new(cx), cx);
|
||||
|
||||
cx.observe_flag::<feature_flags::LanguageModels, _>(move |enabled, cx| {
|
||||
let user_store = user_store.clone();
|
||||
let client = client.clone();
|
||||
LanguageModelRegistry::global(cx).update(cx, move |registry, cx| {
|
||||
if enabled {
|
||||
registry.register_provider(CloudLanguageModelProvider::new(client.clone(), cx), cx);
|
||||
registry.register_provider(
|
||||
CloudLanguageModelProvider::new(user_store.clone(), client.clone(), cx),
|
||||
cx,
|
||||
);
|
||||
} else {
|
||||
registry.unregister_provider(
|
||||
LanguageModelProviderId::from(crate::provider::cloud::PROVIDER_ID.to_string()),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue