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
|
@ -1,10 +1 @@
|
||||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-download"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/></svg>
|
||||||
<g clip-path="url(#clip0_430_1270)">
|
|
||||||
<path d="M4.30957 0.857736V4.28922L2.35703 4.28788C2.10067 4.28788 1.86816 4.44057 1.76636 4.67656C1.66511 4.91229 1.71332 5.18633 1.88959 5.37304L5.53269 9.23312C5.77565 9.49028 6.22488 9.49028 6.46784 9.23312L10.1123 5.37277C10.2875 5.18794 10.3354 4.9147 10.2342 4.6763C10.1337 4.44057 9.90066 4.28788 9.66761 4.28788H7.73891L7.73891 0.857736C7.73891 0.383865 7.35504 2.35669e-07 6.88171 2.14979e-07L5.16731 1.4004e-07C4.66906 -0.000267757 4.30957 0.383865 4.30957 0.857736ZM11.1433 11.1187C11.1434 10.6687 10.7595 10.2856 10.2861 10.2856H1.71413C1.23972 10.2856 0.856659 10.6687 0.856659 11.1187C0.856659 11.6169 1.23972 12 1.71386 12H10.2861C10.7595 12 11.1433 11.6169 11.1433 11.1187Z" fill="white"/>
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<clipPath id="clip0_430_1270">
|
|
||||||
<rect width="12" height="12" fill="white"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
|
Before Width: | Height: | Size: 954 B After Width: | Height: | Size: 347 B |
|
@ -34,16 +34,14 @@ use gpui::{
|
||||||
div, percentage, point, svg, Action, Animation, AnimationExt, AnyElement, AnyView, AppContext,
|
div, percentage, point, svg, Action, Animation, AnimationExt, AnyElement, AnyView, AppContext,
|
||||||
AsyncWindowContext, ClipboardItem, Context as _, DismissEvent, Empty, Entity, EventEmitter,
|
AsyncWindowContext, ClipboardItem, Context as _, DismissEvent, Empty, Entity, EventEmitter,
|
||||||
FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ParentElement, Pixels,
|
FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ParentElement, Pixels,
|
||||||
Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Task,
|
Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Task, Transformation,
|
||||||
TextStyleRefinement, Transformation, UpdateGlobal, View, ViewContext, VisualContext, WeakView,
|
UpdateGlobal, View, ViewContext, VisualContext, WeakView, WindowContext,
|
||||||
WindowContext,
|
|
||||||
};
|
};
|
||||||
use indexed_docs::IndexedDocsStore;
|
use indexed_docs::IndexedDocsStore;
|
||||||
use language::{
|
use language::{
|
||||||
language_settings::SoftWrap, Capability, LanguageRegistry, LspAdapterDelegate, Point, ToOffset,
|
language_settings::SoftWrap, Capability, LanguageRegistry, LspAdapterDelegate, Point, ToOffset,
|
||||||
};
|
};
|
||||||
use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry, Role};
|
use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry, Role};
|
||||||
use markdown::{Markdown, MarkdownStyle};
|
|
||||||
use multi_buffer::MultiBufferRow;
|
use multi_buffer::MultiBufferRow;
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use project::{Project, ProjectLspAdapterDelegate};
|
use project::{Project, ProjectLspAdapterDelegate};
|
||||||
|
@ -59,7 +57,6 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
|
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
|
||||||
use theme::ThemeSettings;
|
|
||||||
use ui::TintColor;
|
use ui::TintColor;
|
||||||
use ui::{
|
use ui::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
@ -3035,7 +3032,6 @@ impl Item for ContextHistory {
|
||||||
|
|
||||||
pub struct ConfigurationView {
|
pub struct ConfigurationView {
|
||||||
fallback_handle: FocusHandle,
|
fallback_handle: FocusHandle,
|
||||||
using_assistant_description: View<Markdown>,
|
|
||||||
active_tab: Option<ActiveTab>,
|
active_tab: Option<ActiveTab>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3057,46 +3053,10 @@ impl ActiveTab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We need to remove this once we have proper text and styling
|
|
||||||
const SHOW_CONFIGURATION_TEXT: bool = false;
|
|
||||||
|
|
||||||
impl ConfigurationView {
|
impl ConfigurationView {
|
||||||
fn new(fallback_handle: FocusHandle, cx: &mut ViewContext<Self>) -> Self {
|
fn new(fallback_handle: FocusHandle, _cx: &mut ViewContext<Self>) -> Self {
|
||||||
let usage_description = cx.new_view(|cx| {
|
|
||||||
let text = include_str!("./using-the-assistant.md");
|
|
||||||
|
|
||||||
let settings = ThemeSettings::get_global(cx);
|
|
||||||
let mut base_text_style = cx.text_style();
|
|
||||||
base_text_style.refine(&TextStyleRefinement {
|
|
||||||
font_family: Some(settings.ui_font.family.clone()),
|
|
||||||
font_size: Some(TextSize::XSmall.rems(cx).into()),
|
|
||||||
color: Some(cx.theme().colors().editor_foreground),
|
|
||||||
background_color: Some(gpui::transparent_black()),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
let markdown_style = MarkdownStyle {
|
|
||||||
base_text_style,
|
|
||||||
selection_background_color: { cx.theme().players().local().selection },
|
|
||||||
inline_code: TextStyleRefinement {
|
|
||||||
background_color: Some(cx.theme().colors().background),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
link: TextStyleRefinement {
|
|
||||||
underline: Some(gpui::UnderlineStyle {
|
|
||||||
thickness: px(1.),
|
|
||||||
color: Some(cx.theme().colors().editor_foreground),
|
|
||||||
wavy: false,
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
Markdown::new(text.to_string(), markdown_style.clone(), None, cx, None)
|
|
||||||
});
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
fallback_handle,
|
fallback_handle,
|
||||||
using_assistant_description: usage_description,
|
|
||||||
active_tab: None,
|
active_tab: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3240,24 +3200,21 @@ impl Render for ConfigurationView {
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(Headline::new("Configure your Assistant").size(HeadlineSize::Medium)),
|
||||||
Headline::new("Get Started with the Assistant").size(HeadlineSize::Medium),
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
Label::new("Configure a provider to get started with the assistant. Then create a new context.")
|
|
||||||
.color(Color::Muted),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(Headline::new("Configure providers").size(HeadlineSize::Small))
|
.child(Headline::new("Configure providers").size(HeadlineSize::Small))
|
||||||
|
.child(
|
||||||
|
Label::new(
|
||||||
|
"At least one provider must be configured to use the assistant.",
|
||||||
|
)
|
||||||
|
.color(Color::Muted),
|
||||||
|
)
|
||||||
.child(tabs)
|
.child(tabs)
|
||||||
.children(self.render_active_tab_view(cx)),
|
.children(self.render_active_tab_view(cx)),
|
||||||
)
|
)
|
||||||
.when(SHOW_CONFIGURATION_TEXT, |this| {
|
|
||||||
this.child(self.using_assistant_description.clone())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,11 @@ mod role;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use client::Client;
|
use client::{Client, UserStore};
|
||||||
use futures::{future::BoxFuture, stream::BoxStream};
|
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::*;
|
pub use model::*;
|
||||||
use project::Fs;
|
use project::Fs;
|
||||||
pub(crate) use rate_limiter::*;
|
pub(crate) use rate_limiter::*;
|
||||||
|
@ -20,9 +22,14 @@ use schemars::JsonSchema;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use std::{future::Future, sync::Arc};
|
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);
|
settings::init(fs, cx);
|
||||||
registry::init(client, cx);
|
registry::init(user_store, client, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait LanguageModel: Send + Sync {
|
pub trait LanguageModel: Send + Sync {
|
||||||
|
|
|
@ -483,7 +483,7 @@ impl Render for ConfigurationView {
|
||||||
.size_full()
|
.size_full()
|
||||||
.on_action(cx.listener(Self::save_api_key))
|
.on_action(cx.listener(Self::save_api_key))
|
||||||
.children(
|
.children(
|
||||||
INSTRUCTIONS.map(|instruction| Label::new(instruction).size(LabelSize::Small)),
|
INSTRUCTIONS.map(|instruction| Label::new(instruction)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
|
|
|
@ -5,10 +5,12 @@ use crate::{
|
||||||
LanguageModelProviderState, LanguageModelRequest, RateLimiter,
|
LanguageModelProviderState, LanguageModelRequest, RateLimiter,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context as _, Result};
|
use anyhow::{anyhow, Context as _, Result};
|
||||||
use client::Client;
|
use client::{Client, UserStore};
|
||||||
use collections::BTreeMap;
|
use collections::BTreeMap;
|
||||||
use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
|
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 schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::{Settings, SettingsStore};
|
||||||
|
@ -52,6 +54,7 @@ pub struct CloudLanguageModelProvider {
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
|
user_store: Model<UserStore>,
|
||||||
status: client::Status,
|
status: client::Status,
|
||||||
_subscription: Subscription,
|
_subscription: Subscription,
|
||||||
}
|
}
|
||||||
|
@ -71,12 +74,13 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CloudLanguageModelProvider {
|
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 mut status_rx = client.status();
|
||||||
let status = *status_rx.borrow();
|
let status = *status_rx.borrow();
|
||||||
|
|
||||||
let state = cx.new_model(|cx| State {
|
let state = cx.new_model(|cx| State {
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
|
user_store,
|
||||||
status,
|
status,
|
||||||
_subscription: cx.observe_global::<SettingsStore>(|_, cx| {
|
_subscription: cx.observe_global::<SettingsStore>(|_, cx| {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
@ -401,8 +405,9 @@ impl Render for ConfigurationView {
|
||||||
const ACCOUNT_SETTINGS_URL: &str = "https://zed.dev/settings";
|
const ACCOUNT_SETTINGS_URL: &str = "https://zed.dev/settings";
|
||||||
|
|
||||||
let is_connected = self.state.read(cx).is_connected();
|
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 {
|
if is_connected {
|
||||||
v_flex()
|
v_flex()
|
||||||
|
@ -410,7 +415,7 @@ impl Render for ConfigurationView {
|
||||||
.max_w_4_5()
|
.max_w_4_5()
|
||||||
.child(Label::new(
|
.child(Label::new(
|
||||||
if is_pro {
|
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 {
|
} else {
|
||||||
"You have basic access to models from Anthropic, OpenAI, Google and more through the Zed AI Free plan."
|
"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()
|
.size_full()
|
||||||
.on_action(cx.listener(Self::save_api_key))
|
.on_action(cx.listener(Self::save_api_key))
|
||||||
.children(
|
.children(
|
||||||
INSTRUCTIONS.map(|instruction| Label::new(instruction).size(LabelSize::Small)),
|
INSTRUCTIONS.map(|instruction| Label::new(instruction)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
|
|
|
@ -7,7 +7,7 @@ use ollama::{
|
||||||
};
|
};
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::{Settings, SettingsStore};
|
||||||
use std::{future, sync::Arc, time::Duration};
|
use std::{future, sync::Arc, time::Duration};
|
||||||
use ui::{prelude::*, ButtonLike, ElevationIndex, Indicator};
|
use ui::{prelude::*, ButtonLike, Indicator};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
settings::AllLanguageModelSettings, LanguageModel, LanguageModelId, LanguageModelName,
|
settings::AllLanguageModelSettings, LanguageModel, LanguageModelId, LanguageModelName,
|
||||||
|
@ -17,6 +17,7 @@ use crate::{
|
||||||
|
|
||||||
const OLLAMA_DOWNLOAD_URL: &str = "https://ollama.com/download";
|
const OLLAMA_DOWNLOAD_URL: &str = "https://ollama.com/download";
|
||||||
const OLLAMA_LIBRARY_URL: &str = "https://ollama.com/library";
|
const OLLAMA_LIBRARY_URL: &str = "https://ollama.com/library";
|
||||||
|
const OLLAMA_SITE: &str = "https://ollama.com/";
|
||||||
|
|
||||||
const PROVIDER_ID: &str = "ollama";
|
const PROVIDER_ID: &str = "ollama";
|
||||||
const PROVIDER_NAME: &str = "Ollama";
|
const PROVIDER_NAME: &str = "Ollama";
|
||||||
|
@ -303,81 +304,107 @@ impl ConfigurationView {
|
||||||
.update(cx, |state, cx| state.fetch_models(cx))
|
.update(cx, |state, cx| state.fetch_models(cx))
|
||||||
.detach_and_log_err(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 {
|
impl Render for ConfigurationView {
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
let is_authenticated = self.state.read(cx).is_authenticated();
|
let is_authenticated = self.state.read(cx).is_authenticated();
|
||||||
|
|
||||||
if is_authenticated {
|
let ollama_intro = "Get up and running with Llama 3.1, Mistral, Gemma 2, and other large language models with Ollama.";
|
||||||
v_flex()
|
let ollama_reqs =
|
||||||
.size_full()
|
"Ollama must be running with at least one model installed to use it in the assistant.";
|
||||||
.child(
|
|
||||||
h_flex()
|
let mut inline_code_bg = cx.theme().colors().editor_background;
|
||||||
.gap_2()
|
inline_code_bg.fade_out(0.5);
|
||||||
.child(Indicator::dot().color(Color::Success))
|
|
||||||
.child(Label::new("Ollama configured").size(LabelSize::Small)),
|
v_flex()
|
||||||
)
|
|
||||||
.into_any()
|
|
||||||
} else {
|
|
||||||
v_flex()
|
|
||||||
.size_full()
|
.size_full()
|
||||||
.gap_2()
|
.gap_3()
|
||||||
.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))
|
.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(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.w_full()
|
.w_full()
|
||||||
.p_4()
|
.pt_2()
|
||||||
.justify_center()
|
.justify_between()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(
|
||||||
self.render_download_button(cx)
|
h_flex()
|
||||||
)
|
.w_full()
|
||||||
.child(
|
.gap_2()
|
||||||
self.render_retry_button(cx)
|
.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()
|
.into_any()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,16 @@ use crate::{
|
||||||
LanguageModel, LanguageModelId, LanguageModelProvider, LanguageModelProviderId,
|
LanguageModel, LanguageModelId, LanguageModelProvider, LanguageModelProviderId,
|
||||||
LanguageModelProviderState,
|
LanguageModelProviderState,
|
||||||
};
|
};
|
||||||
use client::Client;
|
use client::{Client, UserStore};
|
||||||
use collections::BTreeMap;
|
use collections::BTreeMap;
|
||||||
use gpui::{AppContext, EventEmitter, Global, Model, ModelContext};
|
use gpui::{AppContext, EventEmitter, Global, Model, ModelContext};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ui::Context;
|
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 registry = cx.new_model(|cx| {
|
||||||
let mut registry = LanguageModelRegistry::default();
|
let mut registry = LanguageModelRegistry::default();
|
||||||
register_language_model_providers(&mut registry, client, cx);
|
register_language_model_providers(&mut registry, user_store, client, cx);
|
||||||
registry
|
registry
|
||||||
});
|
});
|
||||||
cx.set_global(GlobalLanguageModelRegistry(registry));
|
cx.set_global(GlobalLanguageModelRegistry(registry));
|
||||||
|
@ -24,6 +24,7 @@ pub fn init(client: Arc<Client>, cx: &mut AppContext) {
|
||||||
|
|
||||||
fn register_language_model_providers(
|
fn register_language_model_providers(
|
||||||
registry: &mut LanguageModelRegistry,
|
registry: &mut LanguageModelRegistry,
|
||||||
|
user_store: Model<UserStore>,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
cx: &mut ModelContext<LanguageModelRegistry>,
|
cx: &mut ModelContext<LanguageModelRegistry>,
|
||||||
) {
|
) {
|
||||||
|
@ -48,10 +49,14 @@ fn register_language_model_providers(
|
||||||
registry.register_provider(CopilotChatLanguageModelProvider::new(cx), cx);
|
registry.register_provider(CopilotChatLanguageModelProvider::new(cx), cx);
|
||||||
|
|
||||||
cx.observe_flag::<feature_flags::LanguageModels, _>(move |enabled, cx| {
|
cx.observe_flag::<feature_flags::LanguageModels, _>(move |enabled, cx| {
|
||||||
|
let user_store = user_store.clone();
|
||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
LanguageModelRegistry::global(cx).update(cx, move |registry, cx| {
|
LanguageModelRegistry::global(cx).update(cx, move |registry, cx| {
|
||||||
if enabled {
|
if enabled {
|
||||||
registry.register_provider(CloudLanguageModelProvider::new(client.clone(), cx), cx);
|
registry.register_provider(
|
||||||
|
CloudLanguageModelProvider::new(user_store.clone(), client.clone(), cx),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
registry.unregister_provider(
|
registry.unregister_provider(
|
||||||
LanguageModelProviderId::from(crate::provider::cloud::PROVIDER_ID.to_string()),
|
LanguageModelProviderId::from(crate::provider::cloud::PROVIDER_ID.to_string()),
|
||||||
|
|
|
@ -174,7 +174,12 @@ fn init_common(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
supermaven::init(app_state.client.clone(), cx);
|
supermaven::init(app_state.client.clone(), cx);
|
||||||
language_model::init(app_state.client.clone(), app_state.fs.clone(), cx);
|
language_model::init(
|
||||||
|
app_state.user_store.clone(),
|
||||||
|
app_state.client.clone(),
|
||||||
|
app_state.fs.clone(),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
snippet_provider::init(cx);
|
snippet_provider::init(cx);
|
||||||
inline_completion_registry::init(app_state.client.telemetry().clone(), cx);
|
inline_completion_registry::init(app_state.client.telemetry().clone(), cx);
|
||||||
assistant::init(app_state.fs.clone(), app_state.client.clone(), cx);
|
assistant::init(app_state.fs.clone(), app_state.client.clone(), cx);
|
||||||
|
|
|
@ -3467,7 +3467,12 @@ mod tests {
|
||||||
app_state.client.http_client().clone(),
|
app_state.client.http_client().clone(),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
language_model::init(app_state.client.clone(), app_state.fs.clone(), cx);
|
language_model::init(
|
||||||
|
app_state.user_store.clone(),
|
||||||
|
app_state.client.clone(),
|
||||||
|
app_state.fs.clone(),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
assistant::init(app_state.fs.clone(), app_state.client.clone(), cx);
|
assistant::init(app_state.fs.clone(), app_state.client.clone(), cx);
|
||||||
repl::init(
|
repl::init(
|
||||||
app_state.fs.clone(),
|
app_state.fs.clone(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue