Start separating authentication from connection to collab (#35471)
This pull request should be idempotent, but lays the groundwork for avoiding to connect to collab in order to interact with AI features provided by Zed. Release Notes: - N/A --------- Co-authored-by: Marshall Bowers <git@maxdeviant.com> Co-authored-by: Richard Feldman <oss@rtfeldman.com>
This commit is contained in:
parent
b01d1872cc
commit
f888f3fc0b
46 changed files with 653 additions and 855 deletions
|
@ -44,7 +44,6 @@ ollama = { workspace = true, features = ["schemars"] }
|
|||
open_ai = { workspace = true, features = ["schemars"] }
|
||||
open_router = { workspace = true, features = ["schemars"] }
|
||||
partial-json-fixer.workspace = true
|
||||
proto.workspace = true
|
||||
release_channel.workspace = true
|
||||
schemars.workspace = true
|
||||
serde.workspace = true
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ::settings::{Settings, SettingsStore};
|
||||
use client::{Client, CloudUserStore, UserStore};
|
||||
use client::{Client, UserStore};
|
||||
use collections::HashSet;
|
||||
use gpui::{App, Context, Entity};
|
||||
use language_model::{LanguageModelProviderId, LanguageModelRegistry};
|
||||
|
@ -26,22 +26,11 @@ use crate::provider::vercel::VercelLanguageModelProvider;
|
|||
use crate::provider::x_ai::XAiLanguageModelProvider;
|
||||
pub use crate::settings::*;
|
||||
|
||||
pub fn init(
|
||||
user_store: Entity<UserStore>,
|
||||
cloud_user_store: Entity<CloudUserStore>,
|
||||
client: Arc<Client>,
|
||||
cx: &mut App,
|
||||
) {
|
||||
pub fn init(user_store: Entity<UserStore>, client: Arc<Client>, cx: &mut App) {
|
||||
crate::settings::init_settings(cx);
|
||||
let registry = LanguageModelRegistry::global(cx);
|
||||
registry.update(cx, |registry, cx| {
|
||||
register_language_model_providers(
|
||||
registry,
|
||||
user_store,
|
||||
cloud_user_store,
|
||||
client.clone(),
|
||||
cx,
|
||||
);
|
||||
register_language_model_providers(registry, user_store, client.clone(), cx);
|
||||
});
|
||||
|
||||
let mut openai_compatible_providers = AllLanguageModelSettings::get_global(cx)
|
||||
|
@ -111,17 +100,11 @@ fn register_openai_compatible_providers(
|
|||
fn register_language_model_providers(
|
||||
registry: &mut LanguageModelRegistry,
|
||||
user_store: Entity<UserStore>,
|
||||
cloud_user_store: Entity<CloudUserStore>,
|
||||
client: Arc<Client>,
|
||||
cx: &mut Context<LanguageModelRegistry>,
|
||||
) {
|
||||
registry.register_provider(
|
||||
CloudLanguageModelProvider::new(
|
||||
user_store.clone(),
|
||||
cloud_user_store.clone(),
|
||||
client.clone(),
|
||||
cx,
|
||||
),
|
||||
CloudLanguageModelProvider::new(user_store.clone(), client.clone(), cx),
|
||||
cx,
|
||||
);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use ai_onboarding::YoungAccountBanner;
|
|||
use anthropic::AnthropicModelMode;
|
||||
use anyhow::{Context as _, Result, anyhow};
|
||||
use chrono::{DateTime, Utc};
|
||||
use client::{Client, CloudUserStore, ModelRequestUsage, UserStore, zed_urls};
|
||||
use client::{Client, ModelRequestUsage, UserStore, zed_urls};
|
||||
use cloud_llm_client::{
|
||||
CLIENT_SUPPORTS_STATUS_MESSAGES_HEADER_NAME, CURRENT_PLAN_HEADER_NAME, CompletionBody,
|
||||
CompletionEvent, CompletionRequestStatus, CountTokensBody, CountTokensResponse,
|
||||
|
@ -117,7 +117,6 @@ pub struct State {
|
|||
client: Arc<Client>,
|
||||
llm_api_token: LlmApiToken,
|
||||
user_store: Entity<UserStore>,
|
||||
cloud_user_store: Entity<CloudUserStore>,
|
||||
status: client::Status,
|
||||
accept_terms_of_service_task: Option<Task<Result<()>>>,
|
||||
models: Vec<Arc<cloud_llm_client::LanguageModel>>,
|
||||
|
@ -133,17 +132,14 @@ impl State {
|
|||
fn new(
|
||||
client: Arc<Client>,
|
||||
user_store: Entity<UserStore>,
|
||||
cloud_user_store: Entity<CloudUserStore>,
|
||||
status: client::Status,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Self {
|
||||
let refresh_llm_token_listener = RefreshLlmTokenListener::global(cx);
|
||||
|
||||
Self {
|
||||
client: client.clone(),
|
||||
llm_api_token: LlmApiToken::default(),
|
||||
user_store,
|
||||
cloud_user_store,
|
||||
user_store: user_store.clone(),
|
||||
status,
|
||||
accept_terms_of_service_task: None,
|
||||
models: Vec::new(),
|
||||
|
@ -152,18 +148,12 @@ impl State {
|
|||
recommended_models: Vec::new(),
|
||||
_fetch_models_task: cx.spawn(async move |this, cx| {
|
||||
maybe!(async move {
|
||||
let (client, cloud_user_store, llm_api_token) =
|
||||
this.read_with(cx, |this, _cx| {
|
||||
(
|
||||
client.clone(),
|
||||
this.cloud_user_store.clone(),
|
||||
this.llm_api_token.clone(),
|
||||
)
|
||||
})?;
|
||||
let (client, llm_api_token) = this
|
||||
.read_with(cx, |this, _cx| (client.clone(), this.llm_api_token.clone()))?;
|
||||
|
||||
loop {
|
||||
let is_authenticated =
|
||||
cloud_user_store.read_with(cx, |this, _cx| this.is_authenticated())?;
|
||||
let is_authenticated = user_store
|
||||
.read_with(cx, |user_store, _cx| user_store.current_user().is_some())?;
|
||||
if is_authenticated {
|
||||
break;
|
||||
}
|
||||
|
@ -204,22 +194,19 @@ impl State {
|
|||
}
|
||||
|
||||
fn is_signed_out(&self, cx: &App) -> bool {
|
||||
!self.cloud_user_store.read(cx).is_authenticated()
|
||||
self.user_store.read(cx).current_user().is_none()
|
||||
}
|
||||
|
||||
fn authenticate(&self, cx: &mut Context<Self>) -> Task<Result<()>> {
|
||||
let client = self.client.clone();
|
||||
cx.spawn(async move |state, cx| {
|
||||
client
|
||||
.authenticate_and_connect(true, &cx)
|
||||
.await
|
||||
.into_response()?;
|
||||
client.sign_in_with_optional_connect(true, &cx).await?;
|
||||
state.update(cx, |_, cx| cx.notify())
|
||||
})
|
||||
}
|
||||
|
||||
fn has_accepted_terms_of_service(&self, cx: &App) -> bool {
|
||||
self.cloud_user_store.read(cx).has_accepted_tos()
|
||||
self.user_store.read(cx).has_accepted_terms_of_service()
|
||||
}
|
||||
|
||||
fn accept_terms_of_service(&mut self, cx: &mut Context<Self>) {
|
||||
|
@ -303,24 +290,11 @@ impl State {
|
|||
}
|
||||
|
||||
impl CloudLanguageModelProvider {
|
||||
pub fn new(
|
||||
user_store: Entity<UserStore>,
|
||||
cloud_user_store: Entity<CloudUserStore>,
|
||||
client: Arc<Client>,
|
||||
cx: &mut App,
|
||||
) -> Self {
|
||||
pub fn new(user_store: Entity<UserStore>, client: Arc<Client>, cx: &mut App) -> Self {
|
||||
let mut status_rx = client.status();
|
||||
let status = *status_rx.borrow();
|
||||
|
||||
let state = cx.new(|cx| {
|
||||
State::new(
|
||||
client.clone(),
|
||||
user_store.clone(),
|
||||
cloud_user_store.clone(),
|
||||
status,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
let state = cx.new(|cx| State::new(client.clone(), user_store.clone(), status, cx));
|
||||
|
||||
let state_ref = state.downgrade();
|
||||
let maintain_client_status = cx.spawn(async move |cx| {
|
||||
|
@ -632,11 +606,6 @@ impl CloudLanguageModel {
|
|||
.and_then(|plan| plan.to_str().ok())
|
||||
.and_then(|plan| cloud_llm_client::Plan::from_str(plan).ok())
|
||||
{
|
||||
let plan = match plan {
|
||||
cloud_llm_client::Plan::ZedFree => proto::Plan::Free,
|
||||
cloud_llm_client::Plan::ZedPro => proto::Plan::ZedPro,
|
||||
cloud_llm_client::Plan::ZedProTrial => proto::Plan::ZedProTrial,
|
||||
};
|
||||
return Err(anyhow!(ModelRequestLimitReachedError { plan }));
|
||||
}
|
||||
}
|
||||
|
@ -1281,15 +1250,15 @@ impl ConfigurationView {
|
|||
impl Render for ConfigurationView {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let state = self.state.read(cx);
|
||||
let cloud_user_store = state.cloud_user_store.read(cx);
|
||||
let user_store = state.user_store.read(cx);
|
||||
|
||||
ZedAiConfiguration {
|
||||
is_connected: !state.is_signed_out(cx),
|
||||
plan: cloud_user_store.plan(),
|
||||
subscription_period: cloud_user_store.subscription_period(),
|
||||
eligible_for_trial: cloud_user_store.trial_started_at().is_none(),
|
||||
plan: user_store.plan(),
|
||||
subscription_period: user_store.subscription_period(),
|
||||
eligible_for_trial: user_store.trial_started_at().is_none(),
|
||||
has_accepted_terms_of_service: state.has_accepted_terms_of_service(cx),
|
||||
account_too_young: cloud_user_store.account_too_young(),
|
||||
account_too_young: user_store.account_too_young(),
|
||||
accept_terms_of_service_in_progress: state.accept_terms_of_service_task.is_some(),
|
||||
accept_terms_of_service_callback: self.accept_terms_of_service_callback.clone(),
|
||||
sign_in_callback: self.sign_in_callback.clone(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue