From 4723dbe696e904fe485f272a89072a87ad590ad6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 27 Jan 2026 10:58:05 -0500 Subject: [PATCH] cloud_llm_client: Move `Plan` type into `cloud_api_types` (#47778) This PR moves the `Plan` type out of `cloud_llm_client` and into `cloud_api_types`. Release Notes: - N/A --- Cargo.lock | 7 ++- crates/agent/Cargo.toml | 1 + crates/agent/src/thread.rs | 3 +- crates/agent_ui/Cargo.toml | 1 + crates/agent_ui/src/agent_configuration.rs | 2 +- crates/agent_ui/src/agent_panel.rs | 2 +- crates/ai_onboarding/Cargo.toml | 2 +- .../src/agent_panel_onboarding_content.rs | 2 +- crates/ai_onboarding/src/ai_onboarding.rs | 2 +- crates/ai_onboarding/src/ai_upsell_card.rs | 2 +- .../src/edit_prediction_onboarding_content.rs | 2 +- crates/client/src/test.rs | 4 +- crates/client/src/user.rs | 7 +-- crates/cloud_api_types/src/cloud_api_types.rs | 25 +------- crates/cloud_api_types/src/plan.rs | 59 +++++++++++++++++++ .../cloud_llm_client/src/cloud_llm_client.rs | 29 --------- crates/language_models/Cargo.toml | 1 + crates/language_models/src/provider/cloud.rs | 3 +- crates/title_bar/Cargo.toml | 2 +- crates/title_bar/src/title_bar.rs | 2 +- 20 files changed, 87 insertions(+), 71 deletions(-) create mode 100644 crates/cloud_api_types/src/plan.rs diff --git a/Cargo.lock b/Cargo.lock index 4ed076538df56f295adafca2af9e2441286aedcc..22fcbe70aba995b8c6ceddd6bc6d25c185ed08ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -164,6 +164,7 @@ dependencies = [ "chrono", "client", "clock", + "cloud_api_types", "cloud_llm_client", "collections", "context_server", @@ -351,6 +352,7 @@ dependencies = [ "chrono", "client", "clock", + "cloud_api_types", "cloud_llm_client", "collections", "command_palette_hooks", @@ -497,7 +499,7 @@ name = "ai_onboarding" version = "0.1.0" dependencies = [ "client", - "cloud_llm_client", + "cloud_api_types", "component", "gpui", "language_model", @@ -9069,6 +9071,7 @@ dependencies = [ "bedrock", "chrono", "client", + "cloud_api_types", "cloud_llm_client", "collections", "component", @@ -17100,7 +17103,7 @@ dependencies = [ "channel", "chrono", "client", - "cloud_llm_client", + "cloud_api_types", "collections", "db", "git_ui", diff --git a/crates/agent/Cargo.toml b/crates/agent/Cargo.toml index 578dbe7869972f4eb9c43103ba9d492d524f7001..83bac27f76d1ef6ddbd9e69598a0b8044f0a4bae 100644 --- a/crates/agent/Cargo.toml +++ b/crates/agent/Cargo.toml @@ -26,6 +26,7 @@ agent_settings.workspace = true anyhow.workspace = true chrono.workspace = true client.workspace = true +cloud_api_types.workspace = true cloud_llm_client.workspace = true collections.workspace = true context_server.workspace = true diff --git a/crates/agent/src/thread.rs b/crates/agent/src/thread.rs index 5e7145f7d9b5b986ee3c626bf85b572077fb946b..9bd6b97b35a5932ce17f144b4eb86507d5a39654 100644 --- a/crates/agent/src/thread.rs +++ b/crates/agent/src/thread.rs @@ -18,7 +18,8 @@ use agent_settings::{ use anyhow::{Context as _, Result, anyhow}; use chrono::{DateTime, Utc}; use client::UserStore; -use cloud_llm_client::{CompletionIntent, Plan}; +use cloud_api_types::Plan; +use cloud_llm_client::CompletionIntent; use collections::{HashMap, HashSet, IndexMap}; use fs::Fs; use futures::stream; diff --git a/crates/agent_ui/Cargo.toml b/crates/agent_ui/Cargo.toml index 5ad35c41a1033b031e345fec95bc12c6fac62056..289e66164d5012dcb5ce6e69d73774b5cca04b76 100644 --- a/crates/agent_ui/Cargo.toml +++ b/crates/agent_ui/Cargo.toml @@ -43,6 +43,7 @@ audio.workspace = true buffer_diff.workspace = true chrono.workspace = true client.workspace = true +cloud_api_types.workspace = true cloud_llm_client.workspace = true collections.workspace = true command_palette_hooks.workspace = true diff --git a/crates/agent_ui/src/agent_configuration.rs b/crates/agent_ui/src/agent_configuration.rs index 4e6f38a1eb9e9739f8e55366ec7c6f551bae86c8..c5e5aebcfde6be2d5df73431d9cc193e9d067d89 100644 --- a/crates/agent_ui/src/agent_configuration.rs +++ b/crates/agent_ui/src/agent_configuration.rs @@ -9,7 +9,7 @@ use std::{ops::Range, sync::Arc}; use agent::ContextServerRegistry; use anyhow::Result; use client::zed_urls; -use cloud_llm_client::{Plan, PlanV2}; +use cloud_api_types::{Plan, PlanV2}; use collections::HashMap; use context_server::ContextServerId; use editor::{Editor, MultiBufferOffset, SelectionEffects, scroll::Autoscroll}; diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index c502735dd98cc1412ba0bb826dac6acf88f0e76d..46722607033d978f297d906ee342d74469314fd7 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -37,7 +37,7 @@ use anyhow::{Result, anyhow}; use assistant_slash_command::SlashCommandWorkingSet; use assistant_text_thread::{TextThread, TextThreadEvent, TextThreadSummary}; use client::UserStore; -use cloud_llm_client::{Plan, PlanV2}; +use cloud_api_types::{Plan, PlanV2}; use editor::{Anchor, AnchorRangeExt as _, Editor, EditorEvent, MultiBuffer}; use extension::ExtensionEvents; use extension_host::ExtensionStore; diff --git a/crates/ai_onboarding/Cargo.toml b/crates/ai_onboarding/Cargo.toml index 8fb0570e5cf3da5f5f3d6249f76b42f15b8eed7d..a83188ca456fee48efb8d180d5dbc01264792bf8 100644 --- a/crates/ai_onboarding/Cargo.toml +++ b/crates/ai_onboarding/Cargo.toml @@ -16,7 +16,7 @@ default = [] [dependencies] client.workspace = true -cloud_llm_client.workspace = true +cloud_api_types.workspace = true component.workspace = true gpui.workspace = true language_model.workspace = true diff --git a/crates/ai_onboarding/src/agent_panel_onboarding_content.rs b/crates/ai_onboarding/src/agent_panel_onboarding_content.rs index b14fd0d8684f2a18a7dfa47045daabb2f4712a0a..50f66b8f21c1552deda3601ae6d91af98f34a274 100644 --- a/crates/ai_onboarding/src/agent_panel_onboarding_content.rs +++ b/crates/ai_onboarding/src/agent_panel_onboarding_content.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use client::{Client, UserStore}; -use cloud_llm_client::{Plan, PlanV2}; +use cloud_api_types::{Plan, PlanV2}; use gpui::{Entity, IntoElement, ParentElement}; use language_model::{LanguageModelRegistry, ZED_CLOUD_PROVIDER_ID}; use ui::prelude::*; diff --git a/crates/ai_onboarding/src/ai_onboarding.rs b/crates/ai_onboarding/src/ai_onboarding.rs index fa01ec65fa5ef39e96108f75f49f000e71d93748..e22df18e4a0f2f2ab1d9b5443e8f9794ce202946 100644 --- a/crates/ai_onboarding/src/ai_onboarding.rs +++ b/crates/ai_onboarding/src/ai_onboarding.rs @@ -10,7 +10,7 @@ pub use agent_api_keys_onboarding::{ApiKeysWithProviders, ApiKeysWithoutProvider pub use agent_panel_onboarding_card::AgentPanelOnboardingCard; pub use agent_panel_onboarding_content::AgentPanelOnboarding; pub use ai_upsell_card::AiUpsellCard; -use cloud_llm_client::{Plan, PlanV2}; +use cloud_api_types::{Plan, PlanV2}; pub use edit_prediction_onboarding_content::EditPredictionOnboarding; pub use plan_definitions::PlanDefinitions; pub use young_account_banner::YoungAccountBanner; diff --git a/crates/ai_onboarding/src/ai_upsell_card.rs b/crates/ai_onboarding/src/ai_upsell_card.rs index 001825b30d53f68026660638ddbd80d16e7ecfa0..ed071d0350492dde414935b0725480112f81a5ce 100644 --- a/crates/ai_onboarding/src/ai_upsell_card.rs +++ b/crates/ai_onboarding/src/ai_upsell_card.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use client::{Client, UserStore, zed_urls}; -use cloud_llm_client::{Plan, PlanV2}; +use cloud_api_types::{Plan, PlanV2}; use gpui::{AnyElement, App, Entity, IntoElement, RenderOnce, Window}; use ui::{CommonAnimationExt, Divider, Vector, VectorName, prelude::*}; diff --git a/crates/ai_onboarding/src/edit_prediction_onboarding_content.rs b/crates/ai_onboarding/src/edit_prediction_onboarding_content.rs index e11bfdffa29451187c36e38a5ca335c8a45e3a51..2b67b14ee1f766ac59b4b5359ba14a0563b3e37d 100644 --- a/crates/ai_onboarding/src/edit_prediction_onboarding_content.rs +++ b/crates/ai_onboarding/src/edit_prediction_onboarding_content.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use client::{Client, UserStore}; -use cloud_llm_client::{Plan, PlanV2}; +use cloud_api_types::{Plan, PlanV2}; use gpui::{Entity, IntoElement, ParentElement}; use ui::prelude::*; diff --git a/crates/client/src/test.rs b/crates/client/src/test.rs index 7d7ae2a2db917e462e8718a745ff06c0da4e46e3..fb7a1fa9606ea2d2e52e5dad44ee27640420a383 100644 --- a/crates/client/src/test.rs +++ b/crates/client/src/test.rs @@ -1,7 +1,7 @@ use crate::{Client, Connection, Credentials, EstablishConnectionError, UserStore}; use anyhow::{Context as _, Result, anyhow}; -use cloud_api_client::{AuthenticatedUser, GetAuthenticatedUserResponse, PlanInfo}; -use cloud_llm_client::{CurrentUsage, PlanV2, UsageData, UsageLimit}; +use cloud_api_client::{AuthenticatedUser, GetAuthenticatedUserResponse, PlanInfo, PlanV2}; +use cloud_llm_client::{CurrentUsage, UsageData, UsageLimit}; use futures::{StreamExt, stream::BoxStream}; use gpui::{AppContext as _, Entity, TestAppContext}; use http_client::{AsyncBody, Method, Request, http}; diff --git a/crates/client/src/user.rs b/crates/client/src/user.rs index b7a3ef09efef4f35b571d3ed8e055b57b6f7fa8e..cfbeeaac8a0a55d633000d9ae164b7025d8caea2 100644 --- a/crates/client/src/user.rs +++ b/crates/client/src/user.rs @@ -2,10 +2,9 @@ use super::{Client, Status, TypedEnvelope, proto}; use anyhow::{Context as _, Result}; use chrono::{DateTime, Utc}; use cloud_api_client::websocket_protocol::MessageToClient; -use cloud_api_client::{GetAuthenticatedUserResponse, PlanInfo}; +use cloud_api_client::{GetAuthenticatedUserResponse, Plan, PlanInfo}; use cloud_llm_client::{ - EDIT_PREDICTIONS_USAGE_AMOUNT_HEADER_NAME, EDIT_PREDICTIONS_USAGE_LIMIT_HEADER_NAME, Plan, - UsageLimit, + EDIT_PREDICTIONS_USAGE_AMOUNT_HEADER_NAME, EDIT_PREDICTIONS_USAGE_LIMIT_HEADER_NAME, UsageLimit, }; use collections::{HashMap, HashSet, hash_map::Entry}; use derive_more::Deref; @@ -669,7 +668,7 @@ impl UserStore { pub fn plan(&self) -> Option { #[cfg(debug_assertions)] if let Ok(plan) = std::env::var("ZED_SIMULATE_PLAN").as_ref() { - use cloud_llm_client::PlanV2; + use cloud_api_client::PlanV2; return match plan.as_str() { "free" => Some(Plan::V2(PlanV2::ZedFree)), diff --git a/crates/cloud_api_types/src/cloud_api_types.rs b/crates/cloud_api_types/src/cloud_api_types.rs index b3fd5d4b4db584e737467b89b5cbe68705712800..e118c909e282067b8ea452558bc4350bddbaac47 100644 --- a/crates/cloud_api_types/src/cloud_api_types.rs +++ b/crates/cloud_api_types/src/cloud_api_types.rs @@ -1,9 +1,10 @@ +mod plan; mod timestamp; pub mod websocket_protocol; -use cloud_llm_client::Plan; use serde::{Deserialize, Serialize}; +pub use crate::plan::*; pub use crate::timestamp::Timestamp; pub const ZED_SYSTEM_ID_HEADER_NAME: &str = "x-zed-system-id"; @@ -26,28 +27,6 @@ pub struct AuthenticatedUser { pub accepted_tos_at: Option, } -#[derive(Debug, PartialEq, Serialize, Deserialize)] -pub struct PlanInfo { - pub plan_v2: cloud_llm_client::PlanV2, - pub subscription_period: Option, - pub usage: cloud_llm_client::CurrentUsage, - pub trial_started_at: Option, - pub is_account_too_young: bool, - pub has_overdue_invoices: bool, -} - -impl PlanInfo { - pub fn plan(&self) -> Plan { - Plan::V2(self.plan_v2) - } -} - -#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)] -pub struct SubscriptionPeriod { - pub started_at: Timestamp, - pub ended_at: Timestamp, -} - #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct AcceptTermsOfServiceResponse { pub user: AuthenticatedUser, diff --git a/crates/cloud_api_types/src/plan.rs b/crates/cloud_api_types/src/plan.rs new file mode 100644 index 0000000000000000000000000000000000000000..63f8f58df7d9df6b366be5c344c0fca19da14ff8 --- /dev/null +++ b/crates/cloud_api_types/src/plan.rs @@ -0,0 +1,59 @@ +use serde::{Deserialize, Serialize}; + +use crate::Timestamp; + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Plan { + V2(PlanV2), +} + +#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum PlanV2 { + #[default] + ZedFree, + ZedPro, + ZedProTrial, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct PlanInfo { + pub plan_v2: PlanV2, + pub subscription_period: Option, + pub usage: cloud_llm_client::CurrentUsage, + pub trial_started_at: Option, + pub is_account_too_young: bool, + pub has_overdue_invoices: bool, +} + +impl PlanInfo { + pub fn plan(&self) -> Plan { + Plan::V2(self.plan_v2) + } +} + +#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)] +pub struct SubscriptionPeriod { + pub started_at: Timestamp, + pub ended_at: Timestamp, +} + +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + use serde_json::json; + + use super::*; + + #[test] + fn test_plan_v2_deserialize_snake_case() { + let plan = serde_json::from_value::(json!("zed_free")).unwrap(); + assert_eq!(plan, PlanV2::ZedFree); + + let plan = serde_json::from_value::(json!("zed_pro")).unwrap(); + assert_eq!(plan, PlanV2::ZedPro); + + let plan = serde_json::from_value::(json!("zed_pro_trial")).unwrap(); + assert_eq!(plan, PlanV2::ZedProTrial); + } +} diff --git a/crates/cloud_llm_client/src/cloud_llm_client.rs b/crates/cloud_llm_client/src/cloud_llm_client.rs index a03b4f3ebbc53340d4eb403eb5d8597c5040a369..227f8c1c9f69d148f351120daf0f0f2b6b98de31 100644 --- a/crates/cloud_llm_client/src/cloud_llm_client.rs +++ b/crates/cloud_llm_client/src/cloud_llm_client.rs @@ -74,20 +74,6 @@ impl FromStr for UsageLimit { } } -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Plan { - V2(PlanV2), -} - -#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum PlanV2 { - #[default] - ZedFree, - ZedPro, - ZedProTrial, -} - #[derive( Debug, PartialEq, Eq, Hash, Clone, Copy, Serialize, Deserialize, EnumString, EnumIter, Display, )] @@ -337,23 +323,8 @@ pub struct UsageData { #[cfg(test)] mod tests { - use pretty_assertions::assert_eq; - use serde_json::json; - use super::*; - #[test] - fn test_plan_v2_deserialize_snake_case() { - let plan = serde_json::from_value::(json!("zed_free")).unwrap(); - assert_eq!(plan, PlanV2::ZedFree); - - let plan = serde_json::from_value::(json!("zed_pro")).unwrap(); - assert_eq!(plan, PlanV2::ZedPro); - - let plan = serde_json::from_value::(json!("zed_pro_trial")).unwrap(); - assert_eq!(plan, PlanV2::ZedProTrial); - } - #[test] fn test_usage_limit_from_str() { let limit = UsageLimit::from_str("unlimited").unwrap(); diff --git a/crates/language_models/Cargo.toml b/crates/language_models/Cargo.toml index 3b0cf3a31d0718f89994c4cd3cb2bf82f4ec4408..ae944f29eb7ab78bec2c3d0575bc641b308e63db 100644 --- a/crates/language_models/Cargo.toml +++ b/crates/language_models/Cargo.toml @@ -21,6 +21,7 @@ aws_http_client.workspace = true bedrock.workspace = true chrono.workspace = true client.workspace = true +cloud_api_types.workspace = true cloud_llm_client.workspace = true collections.workspace = true component.workspace = true diff --git a/crates/language_models/src/provider/cloud.rs b/crates/language_models/src/provider/cloud.rs index 642b8c7bc3ad191346cd53c5500b4780478df3cb..9f4beba6ac54ea0e20f9d95de9acdda338642e08 100644 --- a/crates/language_models/src/provider/cloud.rs +++ b/crates/language_models/src/provider/cloud.rs @@ -3,9 +3,10 @@ use anthropic::AnthropicModelMode; use anyhow::{Context as _, Result, anyhow}; use chrono::{DateTime, Utc}; use client::{Client, UserStore, zed_urls}; +use cloud_api_types::{Plan, PlanV2}; use cloud_llm_client::{ CLIENT_SUPPORTS_STATUS_MESSAGES_HEADER_NAME, CLIENT_SUPPORTS_X_AI_HEADER_NAME, CompletionBody, - CompletionEvent, CountTokensBody, CountTokensResponse, ListModelsResponse, Plan, PlanV2, + CompletionEvent, CountTokensBody, CountTokensResponse, ListModelsResponse, SERVER_SUPPORTS_STATUS_MESSAGES_HEADER_NAME, ZED_VERSION_HEADER_NAME, }; use feature_flags::{CloudThinkingToggleFeatureFlag, FeatureFlagAppExt as _}; diff --git a/crates/title_bar/Cargo.toml b/crates/title_bar/Cargo.toml index 01d737b72db4acc7ef4dcd13e9d9bde06001d74f..b322d2c51e7886f95ba82bfe2830067425607f8c 100644 --- a/crates/title_bar/Cargo.toml +++ b/crates/title_bar/Cargo.toml @@ -36,7 +36,7 @@ call.workspace = true channel.workspace = true chrono.workspace = true client.workspace = true -cloud_llm_client.workspace = true +cloud_api_types.workspace = true db.workspace = true git_ui.workspace = true gpui = { workspace = true, features = ["screen-capture"] } diff --git a/crates/title_bar/src/title_bar.rs b/crates/title_bar/src/title_bar.rs index 17998c4173f13d2338cb3e78e18e02006ad0e4be..ad4b9407ce3f36028b9b491c808be1cd98c75b21 100644 --- a/crates/title_bar/src/title_bar.rs +++ b/crates/title_bar/src/title_bar.rs @@ -21,7 +21,7 @@ use crate::application_menu::{ use auto_update::AutoUpdateStatus; use call::ActiveCall; use client::{Client, UserStore, zed_urls}; -use cloud_llm_client::{Plan, PlanV2}; +use cloud_api_types::{Plan, PlanV2}; use gpui::{ Action, AnyElement, App, Context, Corner, Element, Entity, FocusHandle, Focusable, InteractiveElement, IntoElement, MouseButton, ParentElement, Render,