From d492b48f32a3810f6e52982753b11ef2270e17fa Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Sun, 4 Jan 2026 18:28:18 -0500 Subject: [PATCH] collab: Remove Supermaven API key issuance (#46044) This PR removes the ability to retrieve a Supermaven API key from Collab. This was staff-gated (at least, on the server), and judging by the logs, no one is using it. Release Notes: - N/A --- Cargo.lock | 2 - crates/collab/Cargo.toml | 2 - crates/collab/src/rpc.rs | 60 +------ crates/proto/proto/app.proto | 6 - crates/proto/proto/zed.proto | 4 +- crates/proto/src/proto.rs | 3 - crates/supermaven/src/messages.rs | 7 - crates/supermaven/src/supermaven.rs | 25 --- crates/supermaven_api/src/supermaven_api.rs | 170 +------------------- 9 files changed, 4 insertions(+), 275 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de94d83793cfdf397099fb24ded02d8cff599e35..ebddead4b980ce1f5c5f7f3c744a9549d0565ac9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3354,7 +3354,6 @@ dependencies = [ "remote", "remote_server", "reqwest 0.11.27", - "reqwest_client", "rpc", "scrypt", "sea-orm", @@ -3369,7 +3368,6 @@ dependencies = [ "sqlx", "strum 0.27.2", "subtle", - "supermaven_api", "task", "telemetry_events", "text", diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 79fc21fe33423d7eb887744b4ad84094a022862e..df4ef2efec1ecc0ef12b4386a9ed7080f6351214 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -44,7 +44,6 @@ prometheus = "0.14" prost.workspace = true rand.workspace = true reqwest = { version = "0.11", features = ["json"] } -reqwest_client.workspace = true rpc.workspace = true scrypt = "0.11" # sea-orm and sea-orm-macros versions must match exactly. @@ -57,7 +56,6 @@ sha2.workspace = true sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "json", "time", "uuid", "any"] } strum.workspace = true subtle.workspace = true -supermaven_api.workspace = true telemetry_events.workspace = true text.workspace = true time.workspace = true diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 9511087af8887a3c799357d06050ce48431b38a6..5350f3a952f2243f0b6b902d8057b53e792dae01 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -32,9 +32,7 @@ use collections::{HashMap, HashSet}; pub use connection_pool::{ConnectionPool, ZedVersion}; use core::fmt::{self, Debug, Formatter}; use futures::TryFutureExt as _; -use reqwest_client::ReqwestClient; use rpc::proto::split_repository_update; -use supermaven_api::{CreateExternalUserRequest, SupermavenAdminApi}; use tracing::Span; use util::paths::PathStyle; @@ -195,7 +193,6 @@ struct Session { peer: Arc, connection_pool: Arc>, app_state: Arc, - supermaven_client: Option>, /// The GeoIP country code for the user. #[allow(unused)] geoip_country_code: Option, @@ -224,6 +221,7 @@ impl Session { } } + #[expect(dead_code)] fn is_staff(&self) -> bool { match &self.principal { Principal::User(user) => user.admin, @@ -237,13 +235,6 @@ impl Session { Principal::Impersonated { user, .. } => user.id, } } - - pub fn email(&self) -> Option { - match &self.principal { - Principal::User(user) => user.email_address.clone(), - Principal::Impersonated { user, .. } => user.email_address.clone(), - } - } } impl Debug for Session { @@ -443,7 +434,6 @@ impl Server { .add_message_handler(update_followers) .add_message_handler(acknowledge_channel_message) .add_message_handler(acknowledge_buffer_version) - .add_request_handler(get_supermaven_api_key) .add_request_handler(forward_mutating_project_request::) .add_request_handler(forward_mutating_project_request::) .add_request_handler(forward_mutating_project_request::) @@ -815,24 +805,6 @@ impl Server { tracing::info!("connection opened"); - let user_agent = format!("Zed Server/{}", env!("CARGO_PKG_VERSION")); - let http_client = match ReqwestClient::user_agent(&user_agent) { - Ok(http_client) => Arc::new(http_client), - Err(error) => { - tracing::error!(?error, "failed to create HTTP client"); - return; - } - }; - - let supermaven_client = this.app_state.config.supermaven_admin_api_key.clone().map( - |supermaven_admin_api_key| { - Arc::new(SupermavenAdminApi::new( - supermaven_admin_api_key.to_string(), - http_client.clone(), - )) - }, - ); - let session = Session { principal: principal.clone(), connection_id, @@ -843,7 +815,6 @@ impl Server { geoip_country_code, system_id, _executor: executor.clone(), - supermaven_client, }; if let Err(error) = this @@ -3654,35 +3625,6 @@ async fn acknowledge_buffer_version( Ok(()) } -/// Get a Supermaven API key for the user -async fn get_supermaven_api_key( - _request: proto::GetSupermavenApiKey, - response: Response, - session: MessageContext, -) -> Result<()> { - let user_id: String = session.user_id().to_string(); - if !session.is_staff() { - return Err(anyhow!("supermaven not enabled for this account"))?; - } - - let email = session.email().context("user must have an email")?; - - let supermaven_admin_api = session - .supermaven_client - .as_ref() - .context("supermaven not configured")?; - - let result = supermaven_admin_api - .try_get_or_create_user(CreateExternalUserRequest { id: user_id, email }) - .await?; - - response.send(proto::GetSupermavenApiKeyResponse { - api_key: result.api_key, - })?; - - Ok(()) -} - /// Start receiving chat updates for a channel async fn join_channel_chat( _request: proto::JoinChannelChat, diff --git a/crates/proto/proto/app.proto b/crates/proto/proto/app.proto index 889086e20090063ee60452bd64ea62f4a08da434..3244057194c28d5aa3812c82d419b3a8ae8bf7f2 100644 --- a/crates/proto/proto/app.proto +++ b/crates/proto/proto/app.proto @@ -68,9 +68,3 @@ message AskPassRequest { message AskPassResponse { string response = 1; } - -message GetSupermavenApiKey {} - -message GetSupermavenApiKeyResponse { - string api_key = 1; -} diff --git a/crates/proto/proto/zed.proto b/crates/proto/proto/zed.proto index b781a06155698505eaeb0a1d19eaaba3e7d3c08d..5c4b2c38e0188dff4fad0cdbd9bd4073009b00d5 100644 --- a/crates/proto/proto/zed.proto +++ b/crates/proto/proto/zed.proto @@ -218,9 +218,6 @@ message Envelope { OpenNewBuffer open_new_buffer = 196; - GetSupermavenApiKey get_supermaven_api_key = 198; - GetSupermavenApiKeyResponse get_supermaven_api_key_response = 199; - TaskContextForLocation task_context_for_location = 203; TaskContext task_context = 204; @@ -464,6 +461,7 @@ message Envelope { reserved 189 to 192; reserved 193 to 195; reserved 197; + reserved 198 to 199; reserved 200 to 202; reserved 205 to 206; reserved 221; diff --git a/crates/proto/src/proto.rs b/crates/proto/src/proto.rs index 840118b0c9d17e3c1889b8138ae70a639930f28e..49147a87b99c325cc90ce41be7f65d3ed357a61a 100644 --- a/crates/proto/src/proto.rs +++ b/crates/proto/src/proto.rs @@ -115,8 +115,6 @@ messages!( (GetReferencesResponse, Background), (GetSignatureHelp, Background), (GetSignatureHelpResponse, Background), - (GetSupermavenApiKey, Background), - (GetSupermavenApiKeyResponse, Background), (GetTypeDefinition, Background), (GetTypeDefinitionResponse, Background), (GetImplementation, Background), @@ -388,7 +386,6 @@ request_messages!( (GetSignatureHelp, GetSignatureHelpResponse), (OpenUnstagedDiff, OpenUnstagedDiffResponse), (OpenUncommittedDiff, OpenUncommittedDiffResponse), - (GetSupermavenApiKey, GetSupermavenApiKeyResponse), (GetTypeDefinition, GetTypeDefinitionResponse), (LinkedEditingRange, LinkedEditingRangeResponse), (ListRemoteDirectory, ListRemoteDirectoryResponse), diff --git a/crates/supermaven/src/messages.rs b/crates/supermaven/src/messages.rs index f515d6353b1b4fb9d194f0d8586348257360e905..9210343587bbb2cbf172a62a2eff73bbbb7cfb72 100644 --- a/crates/supermaven/src/messages.rs +++ b/crates/supermaven/src/messages.rs @@ -1,16 +1,9 @@ use serde::{Deserialize, Serialize}; -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct SetApiKey { - pub api_key: String, -} - // Outbound messages #[derive(Debug, Serialize)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum OutboundMessage { - SetApiKey(SetApiKey), StateUpdate(StateUpdateMessage), #[allow(dead_code)] UseFreeVersion, diff --git a/crates/supermaven/src/supermaven.rs b/crates/supermaven/src/supermaven.rs index 527f4ec37da17c784d3323ebc87a23eb914905ea..f8b4a710e34cef8c2ec8b8bc21db730a12cbf7b5 100644 --- a/crates/supermaven/src/supermaven.rs +++ b/crates/supermaven/src/supermaven.rs @@ -291,31 +291,6 @@ impl SupermavenAgent { let (outgoing_tx, outgoing_rx) = mpsc::unbounded(); - cx.spawn({ - let client = client.clone(); - let outgoing_tx = outgoing_tx.clone(); - async move |this, cx| { - let mut status = client.status(); - while let Some(status) = status.next().await { - if status.is_connected() { - let api_key = client.request(proto::GetSupermavenApiKey {}).await?.api_key; - outgoing_tx - .unbounded_send(OutboundMessage::SetApiKey(SetApiKey { api_key })) - .ok(); - this.update(cx, |this, cx| { - if let Supermaven::Spawned(this) = this { - this.account_status = AccountStatus::Ready; - cx.notify(); - } - })?; - break; - } - } - anyhow::Ok(()) - } - }) - .detach(); - Ok(Self { _process: process, next_state_id: SupermavenCompletionStateId::default(), diff --git a/crates/supermaven_api/src/supermaven_api.rs b/crates/supermaven_api/src/supermaven_api.rs index 539826c8176d0adf0e8ed1fb11ffdec8c15347a9..97e70e58a18fc277d8cb17e2fb8fd3c71b884420 100644 --- a/crates/supermaven_api/src/supermaven_api.rs +++ b/crates/supermaven_api/src/supermaven_api.rs @@ -1,50 +1,20 @@ -use anyhow::{Context as _, Result, anyhow}; +use anyhow::{Context as _, Result}; use futures::AsyncReadExt; use futures::io::BufReader; use http_client::{AsyncBody, HttpClient, Request as HttpRequest}; use paths::supermaven_dir; -use serde::{Deserialize, Serialize}; +use serde::Deserialize; use smol::fs::{self, File}; use std::path::{Path, PathBuf}; use std::sync::Arc; use util::fs::{make_file_executable, remove_matching}; -#[derive(Serialize)] -pub struct GetExternalUserRequest { - pub id: String, -} - -#[derive(Serialize)] -pub struct CreateExternalUserRequest { - pub id: String, - pub email: String, -} - -#[derive(Serialize)] -pub struct DeleteExternalUserRequest { - pub id: String, -} - -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct CreateExternalUserResponse { - pub api_key: String, -} - #[derive(Deserialize)] pub struct SupermavenApiError { pub message: String, } -pub struct SupermavenBinary {} - -pub struct SupermavenAdminApi { - admin_api_key: String, - api_url: String, - http_client: Arc, -} - #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SupermavenDownloadResponse { @@ -53,142 +23,6 @@ pub struct SupermavenDownloadResponse { pub sha256_hash: String, } -#[derive(Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SupermavenUser { - #[expect( - unused, - reason = "This field was found to be unused with serde library bump; it's left as is due to insufficient context on PO's side, but it *may* be fine to remove" - )] - id: String, - #[expect( - unused, - reason = "This field was found to be unused with serde library bump; it's left as is due to insufficient context on PO's side, but it *may* be fine to remove" - )] - email: String, - api_key: String, -} - -impl SupermavenAdminApi { - pub fn new(admin_api_key: String, http_client: Arc) -> Self { - Self { - admin_api_key, - api_url: "https://supermaven.com/api/".to_string(), - http_client, - } - } - - pub async fn try_get_user( - &self, - request: GetExternalUserRequest, - ) -> Result> { - let uri = format!("{}external-user/{}", &self.api_url, &request.id); - - let request = HttpRequest::get(&uri).header("Authorization", self.admin_api_key.clone()); - - let mut response = self - .http_client - .send(request.body(AsyncBody::default())?) - .await - .with_context(|| "Unable to get Supermaven API Key".to_string())?; - - let mut body = Vec::new(); - response.body_mut().read_to_end(&mut body).await?; - - if response.status().is_client_error() { - let error: SupermavenApiError = serde_json::from_slice(&body)?; - if error.message == "User not found" { - return Ok(None); - } else { - anyhow::bail!("Supermaven API error: {}", error.message); - } - } else if response.status().is_server_error() { - let error: SupermavenApiError = serde_json::from_slice(&body)?; - return Err(anyhow!("Supermaven API server error").context(error.message)); - } - - let body_str = std::str::from_utf8(&body)?; - - Ok(Some( - serde_json::from_str::(body_str) - .with_context(|| "Unable to parse Supermaven user response".to_string())?, - )) - } - - pub async fn try_create_user( - &self, - request: CreateExternalUserRequest, - ) -> Result { - let uri = format!("{}external-user", &self.api_url); - - let request = HttpRequest::post(&uri) - .header("Authorization", self.admin_api_key.clone()) - .body(AsyncBody::from(serde_json::to_vec(&request)?))?; - - let mut response = self - .http_client - .send(request) - .await - .with_context(|| "Unable to create Supermaven API Key".to_string())?; - - let mut body = Vec::new(); - response.body_mut().read_to_end(&mut body).await?; - - let body_str = std::str::from_utf8(&body)?; - - if !response.status().is_success() { - let error: SupermavenApiError = serde_json::from_slice(&body)?; - return Err(anyhow!("Supermaven API server error").context(error.message)); - } - - serde_json::from_str::(body_str) - .with_context(|| "Unable to parse Supermaven API Key response".to_string()) - } - - pub async fn try_delete_user(&self, request: DeleteExternalUserRequest) -> Result<()> { - let uri = format!("{}external-user/{}", &self.api_url, &request.id); - - let request = HttpRequest::delete(&uri).header("Authorization", self.admin_api_key.clone()); - - let mut response = self - .http_client - .send(request.body(AsyncBody::default())?) - .await - .with_context(|| "Unable to delete Supermaven User".to_string())?; - - let mut body = Vec::new(); - response.body_mut().read_to_end(&mut body).await?; - - if response.status().is_client_error() { - let error: SupermavenApiError = serde_json::from_slice(&body)?; - if error.message == "User not found" { - return Ok(()); - } else { - anyhow::bail!("Supermaven API error: {}", error.message); - } - } else if response.status().is_server_error() { - let error: SupermavenApiError = serde_json::from_slice(&body)?; - return Err(anyhow!("Supermaven API server error").context(error.message)); - } - - Ok(()) - } - - pub async fn try_get_or_create_user( - &self, - request: CreateExternalUserRequest, - ) -> Result { - let get_user_request = GetExternalUserRequest { - id: request.id.clone(), - }; - - match self.try_get_user(get_user_request).await? { - None => self.try_create_user(request).await, - Some(SupermavenUser { api_key, .. }) => Ok(CreateExternalUserResponse { api_key }), - } - } -} - pub async fn latest_release( client: Arc, platform: &str,