diff --git a/Cargo.lock b/Cargo.lock index 3f85d955898f1c6391c55cdd01fdffbfc4d242b6..d88eff40b621a72a3216f1da56e5917706655d75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9334,7 +9334,6 @@ dependencies = [ "schemars", "serde", "serde_json", - "settings", "smol", "thiserror 2.0.17", "util", diff --git a/crates/agent_ui/src/buffer_codegen.rs b/crates/agent_ui/src/buffer_codegen.rs index 9857dd8a4752e567b6c22ee0fb5932c79a15d82a..420f8665e349c4e79222cdfa034de44971fab538 100644 --- a/crates/agent_ui/src/buffer_codegen.rs +++ b/crates/agent_ui/src/buffer_codegen.rs @@ -18,6 +18,9 @@ use language_model::{ LanguageModelRequestTool, LanguageModelTextStream, LanguageModelToolChoice, LanguageModelToolUse, Role, TokenUsage, }; +use language_models::provider::anthropic::telemetry::{ + AnthropicCompletionType, AnthropicEventData, AnthropicEventReporter, AnthropicEventType, +}; use multi_buffer::MultiBufferRow; use parking_lot::Mutex; use prompt_store::PromptBuilder; @@ -637,7 +640,7 @@ impl CodegenAlternative { stream: impl 'static + Future>, cx: &mut Context, ) -> Task<()> { - let anthropic_reporter = language_model::AnthropicEventReporter::new(&model, cx); + let anthropic_reporter = AnthropicEventReporter::new(&model, cx); let session_id = self.session_id; let model_telemetry_id = model.telemetry_id(); let model_provider_id = model.provider_id().to_string(); @@ -830,9 +833,9 @@ impl CodegenAlternative { error_message = error_message.as_deref(), ); - anthropic_reporter.report(language_model::AnthropicEventData { - completion_type: language_model::AnthropicCompletionType::Editor, - event: language_model::AnthropicEventType::Response, + anthropic_reporter.report(AnthropicEventData { + completion_type: AnthropicCompletionType::Editor, + event: AnthropicEventType::Response, language_name: language_name.map(|n| n.to_string()), message_id, }); diff --git a/crates/agent_ui/src/inline_assistant.rs b/crates/agent_ui/src/inline_assistant.rs index 3b98e496d4732deaf54be9b4e14da380285f467f..01543b657fc2d00fbf8c68cd96c6329d2f4952d6 100644 --- a/crates/agent_ui/src/inline_assistant.rs +++ b/crates/agent_ui/src/inline_assistant.rs @@ -1,5 +1,6 @@ -use language_model::AnthropicEventData; -use language_model::report_anthropic_event; +use language_models::provider::anthropic::telemetry::{ + AnthropicCompletionType, AnthropicEventData, AnthropicEventType, report_anthropic_event, +}; use std::cmp; use std::mem; use std::ops::Range; @@ -467,8 +468,8 @@ impl InlineAssistant { report_anthropic_event( &model.model, AnthropicEventData { - completion_type: language_model::AnthropicCompletionType::Editor, - event: language_model::AnthropicEventType::Invoked, + completion_type: AnthropicCompletionType::Editor, + event: AnthropicEventType::Invoked, language_name: buffer.language().map(|language| language.name().to_proto()), message_id: None, }, @@ -1105,13 +1106,13 @@ impl InlineAssistant { ( "rejected", "Assistant Response Rejected", - language_model::AnthropicEventType::Reject, + AnthropicEventType::Reject, ) } else { ( "accepted", "Assistant Response Accepted", - language_model::AnthropicEventType::Accept, + AnthropicEventType::Accept, ) }; @@ -1128,8 +1129,8 @@ impl InlineAssistant { report_anthropic_event( &model.model, - language_model::AnthropicEventData { - completion_type: language_model::AnthropicCompletionType::Editor, + AnthropicEventData { + completion_type: AnthropicCompletionType::Editor, event: anthropic_event_type, language_name, message_id, diff --git a/crates/agent_ui/src/terminal_codegen.rs b/crates/agent_ui/src/terminal_codegen.rs index e93d3d3991378ddb4156b264be1f0a5ab4d4faac..19adf2d880607091526e94bb0f8bfbb2d944dfa7 100644 --- a/crates/agent_ui/src/terminal_codegen.rs +++ b/crates/agent_ui/src/terminal_codegen.rs @@ -2,6 +2,9 @@ use crate::inline_prompt_editor::CodegenStatus; use futures::{SinkExt, StreamExt, channel::mpsc}; use gpui::{App, AppContext as _, Context, Entity, EventEmitter, Task}; use language_model::{ConfiguredModel, LanguageModelRegistry, LanguageModelRequest}; +use language_models::provider::anthropic::telemetry::{ + AnthropicCompletionType, AnthropicEventData, AnthropicEventReporter, AnthropicEventType, +}; use std::time::Instant; use terminal::Terminal; use uuid::Uuid; @@ -40,7 +43,7 @@ impl TerminalCodegen { return; }; - let anthropic_reporter = language_model::AnthropicEventReporter::new(&model, cx); + let anthropic_reporter = AnthropicEventReporter::new(&model, cx); let session_id = self.session_id; let model_telemetry_id = model.telemetry_id(); let model_provider_id = model.provider_id().to_string(); @@ -94,9 +97,9 @@ impl TerminalCodegen { error_message = error_message, ); - anthropic_reporter.report(language_model::AnthropicEventData { - completion_type: language_model::AnthropicCompletionType::Terminal, - event: language_model::AnthropicEventType::Response, + anthropic_reporter.report(AnthropicEventData { + completion_type: AnthropicCompletionType::Terminal, + event: AnthropicEventType::Response, language_name: None, message_id, }); diff --git a/crates/agent_ui/src/terminal_inline_assistant.rs b/crates/agent_ui/src/terminal_inline_assistant.rs index d8bcabf276e76c4701894d2830af88171072fe49..89c1ec431386e548dc9188b46fe2f88ffef77668 100644 --- a/crates/agent_ui/src/terminal_inline_assistant.rs +++ b/crates/agent_ui/src/terminal_inline_assistant.rs @@ -17,7 +17,10 @@ use gpui::{App, Entity, Focusable, Global, Subscription, Task, UpdateGlobal, Wea use language::Buffer; use language_model::{ CompletionIntent, ConfiguredModel, LanguageModelRegistry, LanguageModelRequest, - LanguageModelRequestMessage, Role, report_anthropic_event, + LanguageModelRequestMessage, Role, +}; +use language_models::provider::anthropic::telemetry::{ + AnthropicCompletionType, AnthropicEventData, AnthropicEventType, report_anthropic_event, }; use project::Project; use prompt_store::{PromptBuilder, PromptStore}; @@ -312,13 +315,13 @@ impl TerminalInlineAssistant { ( "rejected", "Assistant Response Rejected", - language_model::AnthropicEventType::Reject, + AnthropicEventType::Reject, ) } else { ( "accepted", "Assistant Response Accepted", - language_model::AnthropicEventType::Accept, + AnthropicEventType::Accept, ) }; @@ -335,8 +338,8 @@ impl TerminalInlineAssistant { report_anthropic_event( &model, - language_model::AnthropicEventData { - completion_type: language_model::AnthropicCompletionType::Terminal, + AnthropicEventData { + completion_type: AnthropicCompletionType::Terminal, event: anthropic_event_type, language_name: None, message_id, diff --git a/crates/language_model/Cargo.toml b/crates/language_model/Cargo.toml index 2e802e4205fb82aa89cc6beb67ed9e3e68ed1cf6..911100fc25b498ba5471c85d6177052495974665 100644 --- a/crates/language_model/Cargo.toml +++ b/crates/language_model/Cargo.toml @@ -37,7 +37,6 @@ parking_lot.workspace = true schemars.workspace = true serde.workspace = true serde_json.workspace = true -settings.workspace = true smol.workspace = true thiserror.workspace = true util.workspace = true diff --git a/crates/language_model/src/language_model.rs b/crates/language_model/src/language_model.rs index 2f715007ec4d8c2906c0254d4bb458d056d8585e..ce71cee6bcaf4f7ea1e210cc3756bd3162715f55 100644 --- a/crates/language_model/src/language_model.rs +++ b/crates/language_model/src/language_model.rs @@ -1,16 +1,15 @@ mod api_key; mod model; +mod provider; mod rate_limiter; mod registry; mod request; mod role; -mod telemetry; pub mod tool_schema; #[cfg(any(test, feature = "test-support"))] pub mod fake_provider; -use anthropic::{AnthropicError, parse_prompt_too_long}; use anyhow::{Result, anyhow}; use client::Client; use client::UserStore; @@ -20,10 +19,8 @@ use futures::{StreamExt, future::BoxFuture, stream::BoxStream}; use gpui::{AnyView, App, AsyncApp, Entity, SharedString, Task, Window}; use http_client::{StatusCode, http}; use icons::IconName; -use open_router::OpenRouterError; use parking_lot::Mutex; use serde::{Deserialize, Serialize}; -pub use settings::LanguageModelCacheConfiguration; use std::ops::{Add, Sub}; use std::str::FromStr; use std::sync::Arc; @@ -38,30 +35,10 @@ pub use crate::rate_limiter::*; pub use crate::registry::*; pub use crate::request::*; pub use crate::role::*; -pub use crate::telemetry::*; pub use crate::tool_schema::LanguageModelToolSchemaFormat; +pub use provider::*; pub use zed_env_vars::{EnvVar, env_var}; -pub const ANTHROPIC_PROVIDER_ID: LanguageModelProviderId = - LanguageModelProviderId::new("anthropic"); -pub const ANTHROPIC_PROVIDER_NAME: LanguageModelProviderName = - LanguageModelProviderName::new("Anthropic"); - -pub const GOOGLE_PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("google"); -pub const GOOGLE_PROVIDER_NAME: LanguageModelProviderName = - LanguageModelProviderName::new("Google AI"); - -pub const OPEN_AI_PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("openai"); -pub const OPEN_AI_PROVIDER_NAME: LanguageModelProviderName = - LanguageModelProviderName::new("OpenAI"); - -pub const X_AI_PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("x_ai"); -pub const X_AI_PROVIDER_NAME: LanguageModelProviderName = LanguageModelProviderName::new("xAI"); - -pub const ZED_CLOUD_PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("zed.dev"); -pub const ZED_CLOUD_PROVIDER_NAME: LanguageModelProviderName = - LanguageModelProviderName::new("Zed"); - pub fn init(user_store: Entity, client: Arc, cx: &mut App) { init_settings(cx); RefreshLlmTokenListener::register(client, user_store, cx); @@ -71,6 +48,13 @@ pub fn init_settings(cx: &mut App) { registry::init(cx); } +#[derive(Clone, Debug)] +pub struct LanguageModelCacheConfiguration { + pub max_cache_anchors: usize, + pub should_speculate: bool, + pub min_total_token: u64, +} + /// A completion event from a language model. #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub enum LanguageModelCompletionEvent { @@ -310,165 +294,6 @@ impl LanguageModelCompletionError { } } -impl From for LanguageModelCompletionError { - fn from(error: AnthropicError) -> Self { - let provider = ANTHROPIC_PROVIDER_NAME; - match error { - AnthropicError::SerializeRequest(error) => Self::SerializeRequest { provider, error }, - AnthropicError::BuildRequestBody(error) => Self::BuildRequestBody { provider, error }, - AnthropicError::HttpSend(error) => Self::HttpSend { provider, error }, - AnthropicError::DeserializeResponse(error) => { - Self::DeserializeResponse { provider, error } - } - AnthropicError::ReadResponse(error) => Self::ApiReadResponseError { provider, error }, - AnthropicError::HttpResponseError { - status_code, - message, - } => Self::HttpResponseError { - provider, - status_code, - message, - }, - AnthropicError::RateLimit { retry_after } => Self::RateLimitExceeded { - provider, - retry_after: Some(retry_after), - }, - AnthropicError::ServerOverloaded { retry_after } => Self::ServerOverloaded { - provider, - retry_after, - }, - AnthropicError::ApiError(api_error) => api_error.into(), - } - } -} - -impl From for LanguageModelCompletionError { - fn from(error: anthropic::ApiError) -> Self { - use anthropic::ApiErrorCode::*; - let provider = ANTHROPIC_PROVIDER_NAME; - match error.code() { - Some(code) => match code { - InvalidRequestError => Self::BadRequestFormat { - provider, - message: error.message, - }, - AuthenticationError => Self::AuthenticationError { - provider, - message: error.message, - }, - PermissionError => Self::PermissionError { - provider, - message: error.message, - }, - NotFoundError => Self::ApiEndpointNotFound { provider }, - RequestTooLarge => Self::PromptTooLarge { - tokens: parse_prompt_too_long(&error.message), - }, - RateLimitError => Self::RateLimitExceeded { - provider, - retry_after: None, - }, - ApiError => Self::ApiInternalServerError { - provider, - message: error.message, - }, - OverloadedError => Self::ServerOverloaded { - provider, - retry_after: None, - }, - }, - None => Self::Other(error.into()), - } - } -} - -impl From for LanguageModelCompletionError { - fn from(error: open_ai::RequestError) -> Self { - match error { - open_ai::RequestError::HttpResponseError { - provider, - status_code, - body, - headers, - } => { - let retry_after = headers - .get(http::header::RETRY_AFTER) - .and_then(|val| val.to_str().ok()?.parse::().ok()) - .map(Duration::from_secs); - - Self::from_http_status(provider.into(), status_code, body, retry_after) - } - open_ai::RequestError::Other(e) => Self::Other(e), - } - } -} - -impl From for LanguageModelCompletionError { - fn from(error: OpenRouterError) -> Self { - let provider = LanguageModelProviderName::new("OpenRouter"); - match error { - OpenRouterError::SerializeRequest(error) => Self::SerializeRequest { provider, error }, - OpenRouterError::BuildRequestBody(error) => Self::BuildRequestBody { provider, error }, - OpenRouterError::HttpSend(error) => Self::HttpSend { provider, error }, - OpenRouterError::DeserializeResponse(error) => { - Self::DeserializeResponse { provider, error } - } - OpenRouterError::ReadResponse(error) => Self::ApiReadResponseError { provider, error }, - OpenRouterError::RateLimit { retry_after } => Self::RateLimitExceeded { - provider, - retry_after: Some(retry_after), - }, - OpenRouterError::ServerOverloaded { retry_after } => Self::ServerOverloaded { - provider, - retry_after, - }, - OpenRouterError::ApiError(api_error) => api_error.into(), - } - } -} - -impl From for LanguageModelCompletionError { - fn from(error: open_router::ApiError) -> Self { - use open_router::ApiErrorCode::*; - let provider = LanguageModelProviderName::new("OpenRouter"); - match error.code { - InvalidRequestError => Self::BadRequestFormat { - provider, - message: error.message, - }, - AuthenticationError => Self::AuthenticationError { - provider, - message: error.message, - }, - PaymentRequiredError => Self::AuthenticationError { - provider, - message: format!("Payment required: {}", error.message), - }, - PermissionError => Self::PermissionError { - provider, - message: error.message, - }, - RequestTimedOut => Self::HttpResponseError { - provider, - status_code: StatusCode::REQUEST_TIMEOUT, - message: error.message, - }, - RateLimitError => Self::RateLimitExceeded { - provider, - retry_after: None, - }, - ApiError => Self::ApiInternalServerError { - provider, - message: error.message, - }, - OverloadedError => Self::ServerOverloaded { - provider, - retry_after: None, - }, - } - } -} - #[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum StopReason { diff --git a/crates/language_model/src/provider.rs b/crates/language_model/src/provider.rs new file mode 100644 index 0000000000000000000000000000000000000000..707d8e2d618894e2898e253450dbfbb5e9483bba --- /dev/null +++ b/crates/language_model/src/provider.rs @@ -0,0 +1,12 @@ +pub mod anthropic; +pub mod google; +pub mod open_ai; +pub mod open_router; +pub mod x_ai; +pub mod zed; + +pub use anthropic::*; +pub use google::*; +pub use open_ai::*; +pub use x_ai::*; +pub use zed::*; diff --git a/crates/language_model/src/provider/anthropic.rs b/crates/language_model/src/provider/anthropic.rs new file mode 100644 index 0000000000000000000000000000000000000000..0878be2070fdbb9e57145684f59c962a32bb9fd2 --- /dev/null +++ b/crates/language_model/src/provider/anthropic.rs @@ -0,0 +1,80 @@ +use crate::{LanguageModelCompletionError, LanguageModelProviderId, LanguageModelProviderName}; +use anthropic::AnthropicError; +pub use anthropic::parse_prompt_too_long; + +pub const ANTHROPIC_PROVIDER_ID: LanguageModelProviderId = + LanguageModelProviderId::new("anthropic"); +pub const ANTHROPIC_PROVIDER_NAME: LanguageModelProviderName = + LanguageModelProviderName::new("Anthropic"); + +impl From for LanguageModelCompletionError { + fn from(error: AnthropicError) -> Self { + let provider = ANTHROPIC_PROVIDER_NAME; + match error { + AnthropicError::SerializeRequest(error) => Self::SerializeRequest { provider, error }, + AnthropicError::BuildRequestBody(error) => Self::BuildRequestBody { provider, error }, + AnthropicError::HttpSend(error) => Self::HttpSend { provider, error }, + AnthropicError::DeserializeResponse(error) => { + Self::DeserializeResponse { provider, error } + } + AnthropicError::ReadResponse(error) => Self::ApiReadResponseError { provider, error }, + AnthropicError::HttpResponseError { + status_code, + message, + } => Self::HttpResponseError { + provider, + status_code, + message, + }, + AnthropicError::RateLimit { retry_after } => Self::RateLimitExceeded { + provider, + retry_after: Some(retry_after), + }, + AnthropicError::ServerOverloaded { retry_after } => Self::ServerOverloaded { + provider, + retry_after, + }, + AnthropicError::ApiError(api_error) => api_error.into(), + } + } +} + +impl From for LanguageModelCompletionError { + fn from(error: anthropic::ApiError) -> Self { + use anthropic::ApiErrorCode::*; + let provider = ANTHROPIC_PROVIDER_NAME; + match error.code() { + Some(code) => match code { + InvalidRequestError => Self::BadRequestFormat { + provider, + message: error.message, + }, + AuthenticationError => Self::AuthenticationError { + provider, + message: error.message, + }, + PermissionError => Self::PermissionError { + provider, + message: error.message, + }, + NotFoundError => Self::ApiEndpointNotFound { provider }, + RequestTooLarge => Self::PromptTooLarge { + tokens: parse_prompt_too_long(&error.message), + }, + RateLimitError => Self::RateLimitExceeded { + provider, + retry_after: None, + }, + ApiError => Self::ApiInternalServerError { + provider, + message: error.message, + }, + OverloadedError => Self::ServerOverloaded { + provider, + retry_after: None, + }, + }, + None => Self::Other(error.into()), + } + } +} diff --git a/crates/language_model/src/provider/google.rs b/crates/language_model/src/provider/google.rs new file mode 100644 index 0000000000000000000000000000000000000000..1caee496b519f395dd10744b127bc29ee893849f --- /dev/null +++ b/crates/language_model/src/provider/google.rs @@ -0,0 +1,5 @@ +use crate::{LanguageModelProviderId, LanguageModelProviderName}; + +pub const GOOGLE_PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("google"); +pub const GOOGLE_PROVIDER_NAME: LanguageModelProviderName = + LanguageModelProviderName::new("Google AI"); diff --git a/crates/language_model/src/provider/open_ai.rs b/crates/language_model/src/provider/open_ai.rs new file mode 100644 index 0000000000000000000000000000000000000000..3796eb9a3aef78628c52d92e92fabb3812249e04 --- /dev/null +++ b/crates/language_model/src/provider/open_ai.rs @@ -0,0 +1,28 @@ +use crate::{LanguageModelCompletionError, LanguageModelProviderId, LanguageModelProviderName}; +use http_client::http; +use std::time::Duration; + +pub const OPEN_AI_PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("openai"); +pub const OPEN_AI_PROVIDER_NAME: LanguageModelProviderName = + LanguageModelProviderName::new("OpenAI"); + +impl From for LanguageModelCompletionError { + fn from(error: open_ai::RequestError) -> Self { + match error { + open_ai::RequestError::HttpResponseError { + provider, + status_code, + body, + headers, + } => { + let retry_after = headers + .get(http::header::RETRY_AFTER) + .and_then(|val| val.to_str().ok()?.parse::().ok()) + .map(Duration::from_secs); + + Self::from_http_status(provider.into(), status_code, body, retry_after) + } + open_ai::RequestError::Other(e) => Self::Other(e), + } + } +} diff --git a/crates/language_model/src/provider/open_router.rs b/crates/language_model/src/provider/open_router.rs new file mode 100644 index 0000000000000000000000000000000000000000..809e22f1fec0f2d205caa3ebbcb0baaf129b062c --- /dev/null +++ b/crates/language_model/src/provider/open_router.rs @@ -0,0 +1,69 @@ +use crate::{LanguageModelCompletionError, LanguageModelProviderName}; +use http_client::StatusCode; +use open_router::OpenRouterError; + +impl From for LanguageModelCompletionError { + fn from(error: OpenRouterError) -> Self { + let provider = LanguageModelProviderName::new("OpenRouter"); + match error { + OpenRouterError::SerializeRequest(error) => Self::SerializeRequest { provider, error }, + OpenRouterError::BuildRequestBody(error) => Self::BuildRequestBody { provider, error }, + OpenRouterError::HttpSend(error) => Self::HttpSend { provider, error }, + OpenRouterError::DeserializeResponse(error) => { + Self::DeserializeResponse { provider, error } + } + OpenRouterError::ReadResponse(error) => Self::ApiReadResponseError { provider, error }, + OpenRouterError::RateLimit { retry_after } => Self::RateLimitExceeded { + provider, + retry_after: Some(retry_after), + }, + OpenRouterError::ServerOverloaded { retry_after } => Self::ServerOverloaded { + provider, + retry_after, + }, + OpenRouterError::ApiError(api_error) => api_error.into(), + } + } +} + +impl From for LanguageModelCompletionError { + fn from(error: open_router::ApiError) -> Self { + use open_router::ApiErrorCode::*; + let provider = LanguageModelProviderName::new("OpenRouter"); + match error.code { + InvalidRequestError => Self::BadRequestFormat { + provider, + message: error.message, + }, + AuthenticationError => Self::AuthenticationError { + provider, + message: error.message, + }, + PaymentRequiredError => Self::AuthenticationError { + provider, + message: format!("Payment required: {}", error.message), + }, + PermissionError => Self::PermissionError { + provider, + message: error.message, + }, + RequestTimedOut => Self::HttpResponseError { + provider, + status_code: StatusCode::REQUEST_TIMEOUT, + message: error.message, + }, + RateLimitError => Self::RateLimitExceeded { + provider, + retry_after: None, + }, + ApiError => Self::ApiInternalServerError { + provider, + message: error.message, + }, + OverloadedError => Self::ServerOverloaded { + provider, + retry_after: None, + }, + } + } +} diff --git a/crates/language_model/src/provider/x_ai.rs b/crates/language_model/src/provider/x_ai.rs new file mode 100644 index 0000000000000000000000000000000000000000..3d0f794fa4087a4beeb4a9b6253d016a9b592f0e --- /dev/null +++ b/crates/language_model/src/provider/x_ai.rs @@ -0,0 +1,4 @@ +use crate::{LanguageModelProviderId, LanguageModelProviderName}; + +pub const X_AI_PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("x_ai"); +pub const X_AI_PROVIDER_NAME: LanguageModelProviderName = LanguageModelProviderName::new("xAI"); diff --git a/crates/language_model/src/provider/zed.rs b/crates/language_model/src/provider/zed.rs new file mode 100644 index 0000000000000000000000000000000000000000..0ba793e99aad1caa25f049a96faf02c16e8970fa --- /dev/null +++ b/crates/language_model/src/provider/zed.rs @@ -0,0 +1,5 @@ +use crate::{LanguageModelProviderId, LanguageModelProviderName}; + +pub const ZED_CLOUD_PROVIDER_ID: LanguageModelProviderId = LanguageModelProviderId::new("zed.dev"); +pub const ZED_CLOUD_PROVIDER_NAME: LanguageModelProviderName = + LanguageModelProviderName::new("Zed"); diff --git a/crates/language_model/src/registry.rs b/crates/language_model/src/registry.rs index cf7718f7b102010cc0c8a981a0425583436176b7..bf14fbb0b5804505b33074e6e4cbcc36ddf21fab 100644 --- a/crates/language_model/src/registry.rs +++ b/crates/language_model/src/registry.rs @@ -101,7 +101,7 @@ impl ConfiguredModel { } pub fn is_provided_by_zed(&self) -> bool { - self.provider.id() == crate::ZED_CLOUD_PROVIDER_ID + self.provider.id() == crate::provider::ZED_CLOUD_PROVIDER_ID } } diff --git a/crates/language_models/src/provider/anthropic.rs b/crates/language_models/src/provider/anthropic.rs index 1fd79fb3a93d978d0912abbc4f0688e0bbe846e6..a98a0ce142dfdbaaaddc056ab378455a45147830 100644 --- a/crates/language_models/src/provider/anthropic.rs +++ b/crates/language_models/src/provider/anthropic.rs @@ -1,3 +1,5 @@ +pub mod telemetry; + use anthropic::{ ANTHROPIC_API_URL, AnthropicError, AnthropicModelMode, ContentDelta, CountTokensRequest, Event, ResponseContent, ToolResultContent, ToolResultPart, Usage, @@ -8,7 +10,8 @@ use futures::{FutureExt, Stream, StreamExt, future::BoxFuture, stream::BoxStream use gpui::{AnyView, App, AsyncApp, Context, Entity, Task}; use http_client::HttpClient; use language_model::{ - ApiKeyState, AuthenticateError, ConfigurationViewTargetAgent, EnvVar, IconOrSvg, LanguageModel, + ANTHROPIC_PROVIDER_ID, ANTHROPIC_PROVIDER_NAME, ApiKeyState, AuthenticateError, + ConfigurationViewTargetAgent, EnvVar, IconOrSvg, LanguageModel, LanguageModelCacheConfiguration, LanguageModelCompletionError, LanguageModelCompletionEvent, LanguageModelId, LanguageModelName, LanguageModelProvider, LanguageModelProviderId, LanguageModelProviderName, LanguageModelProviderState, LanguageModelRequest, @@ -28,8 +31,8 @@ use crate::provider::util::{fix_streamed_json, parse_tool_arguments}; pub use settings::AnthropicAvailableModel as AvailableModel; -const PROVIDER_ID: LanguageModelProviderId = language_model::ANTHROPIC_PROVIDER_ID; -const PROVIDER_NAME: LanguageModelProviderName = language_model::ANTHROPIC_PROVIDER_NAME; +const PROVIDER_ID: LanguageModelProviderId = ANTHROPIC_PROVIDER_ID; +const PROVIDER_NAME: LanguageModelProviderName = ANTHROPIC_PROVIDER_NAME; #[derive(Default, Clone, Debug, PartialEq)] pub struct AnthropicSettings { diff --git a/crates/language_model/src/telemetry.rs b/crates/language_models/src/provider/anthropic/telemetry.rs similarity index 95% rename from crates/language_model/src/telemetry.rs rename to crates/language_models/src/provider/anthropic/telemetry.rs index 6d7f4df7f644115cae7b2148f4d78fde19674344..75fb11a81b479635ea02db77a2df8a769e795e01 100644 --- a/crates/language_model/src/telemetry.rs +++ b/crates/language_models/src/provider/anthropic/telemetry.rs @@ -1,8 +1,8 @@ -use crate::ANTHROPIC_PROVIDER_ID; use anthropic::ANTHROPIC_API_URL; use anyhow::{Context as _, anyhow}; use gpui::BackgroundExecutor; use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest}; +use language_model::{ANTHROPIC_PROVIDER_ID, LanguageModel}; use std::env; use std::sync::Arc; use util::ResultExt; @@ -52,7 +52,7 @@ impl AnthropicEventType { } pub fn report_anthropic_event( - model: &Arc, + model: &Arc, event: AnthropicEventData, cx: &gpui::App, ) { @@ -69,7 +69,7 @@ pub struct AnthropicEventReporter { } impl AnthropicEventReporter { - pub fn new(model: &Arc, cx: &gpui::App) -> Self { + pub fn new(model: &Arc, cx: &gpui::App) -> Self { Self { http_client: cx.http_client(), executor: cx.background_executor().clone(), diff --git a/crates/language_models/src/provider/cloud.rs b/crates/language_models/src/provider/cloud.rs index 161ee6e9abd5283dfbe10c4e7c9dc5597fc4b5b9..f9372a4d7ea9c078c58f633cc58bd5597ef49212 100644 --- a/crates/language_models/src/provider/cloud.rs +++ b/crates/language_models/src/provider/cloud.rs @@ -19,12 +19,15 @@ use gpui::{AnyElement, AnyView, App, AsyncApp, Context, Entity, Subscription, Ta use http_client::http::{HeaderMap, HeaderValue}; use http_client::{AsyncBody, HttpClient, HttpRequestExt, Method, Response, StatusCode}; use language_model::{ - AuthenticateError, IconOrSvg, LanguageModel, LanguageModelCacheConfiguration, + ANTHROPIC_PROVIDER_ID, ANTHROPIC_PROVIDER_NAME, AuthenticateError, GOOGLE_PROVIDER_ID, + GOOGLE_PROVIDER_NAME, IconOrSvg, LanguageModel, LanguageModelCacheConfiguration, LanguageModelCompletionError, LanguageModelCompletionEvent, LanguageModelEffortLevel, LanguageModelId, LanguageModelName, LanguageModelProvider, LanguageModelProviderId, LanguageModelProviderName, LanguageModelProviderState, LanguageModelRequest, LanguageModelToolChoice, LanguageModelToolSchemaFormat, LlmApiToken, NeedsLlmTokenRefresh, - PaymentRequiredError, RateLimiter, RefreshLlmTokenListener, + OPEN_AI_PROVIDER_ID, OPEN_AI_PROVIDER_NAME, PaymentRequiredError, RateLimiter, + RefreshLlmTokenListener, X_AI_PROVIDER_ID, X_AI_PROVIDER_NAME, ZED_CLOUD_PROVIDER_ID, + ZED_CLOUD_PROVIDER_NAME, }; use release_channel::AppVersion; use schemars::JsonSchema; @@ -53,8 +56,8 @@ use crate::provider::open_ai::{ }; use crate::provider::x_ai::count_xai_tokens; -const PROVIDER_ID: LanguageModelProviderId = language_model::ZED_CLOUD_PROVIDER_ID; -const PROVIDER_NAME: LanguageModelProviderName = language_model::ZED_CLOUD_PROVIDER_NAME; +const PROVIDER_ID: LanguageModelProviderId = ZED_CLOUD_PROVIDER_ID; +const PROVIDER_NAME: LanguageModelProviderName = ZED_CLOUD_PROVIDER_NAME; #[derive(Default, Clone, Debug, PartialEq)] pub struct ZedDotDevSettings { @@ -568,20 +571,20 @@ impl LanguageModel for CloudLanguageModel { fn upstream_provider_id(&self) -> LanguageModelProviderId { use cloud_llm_client::LanguageModelProvider::*; match self.model.provider { - Anthropic => language_model::ANTHROPIC_PROVIDER_ID, - OpenAi => language_model::OPEN_AI_PROVIDER_ID, - Google => language_model::GOOGLE_PROVIDER_ID, - XAi => language_model::X_AI_PROVIDER_ID, + Anthropic => ANTHROPIC_PROVIDER_ID, + OpenAi => OPEN_AI_PROVIDER_ID, + Google => GOOGLE_PROVIDER_ID, + XAi => X_AI_PROVIDER_ID, } } fn upstream_provider_name(&self) -> LanguageModelProviderName { use cloud_llm_client::LanguageModelProvider::*; match self.model.provider { - Anthropic => language_model::ANTHROPIC_PROVIDER_NAME, - OpenAi => language_model::OPEN_AI_PROVIDER_NAME, - Google => language_model::GOOGLE_PROVIDER_NAME, - XAi => language_model::X_AI_PROVIDER_NAME, + Anthropic => ANTHROPIC_PROVIDER_NAME, + OpenAi => OPEN_AI_PROVIDER_NAME, + Google => GOOGLE_PROVIDER_NAME, + XAi => X_AI_PROVIDER_NAME, } } @@ -1047,12 +1050,10 @@ where fn provider_name(provider: &cloud_llm_client::LanguageModelProvider) -> LanguageModelProviderName { match provider { - cloud_llm_client::LanguageModelProvider::Anthropic => { - language_model::ANTHROPIC_PROVIDER_NAME - } - cloud_llm_client::LanguageModelProvider::OpenAi => language_model::OPEN_AI_PROVIDER_NAME, - cloud_llm_client::LanguageModelProvider::Google => language_model::GOOGLE_PROVIDER_NAME, - cloud_llm_client::LanguageModelProvider::XAi => language_model::X_AI_PROVIDER_NAME, + cloud_llm_client::LanguageModelProvider::Anthropic => ANTHROPIC_PROVIDER_NAME, + cloud_llm_client::LanguageModelProvider::OpenAi => OPEN_AI_PROVIDER_NAME, + cloud_llm_client::LanguageModelProvider::Google => GOOGLE_PROVIDER_NAME, + cloud_llm_client::LanguageModelProvider::XAi => X_AI_PROVIDER_NAME, } } diff --git a/crates/language_models/src/provider/google.rs b/crates/language_models/src/provider/google.rs index 334a5cbe64e6cdefbaa7c15c309ca4632109e323..8fdfb514ac6e872bd24968d33f2c1169401d5a9c 100644 --- a/crates/language_models/src/provider/google.rs +++ b/crates/language_models/src/provider/google.rs @@ -13,9 +13,9 @@ use language_model::{ LanguageModelToolUse, LanguageModelToolUseId, MessageContent, StopReason, }; use language_model::{ - IconOrSvg, LanguageModel, LanguageModelId, LanguageModelName, LanguageModelProvider, - LanguageModelProviderId, LanguageModelProviderName, LanguageModelProviderState, - LanguageModelRequest, RateLimiter, Role, + GOOGLE_PROVIDER_ID, GOOGLE_PROVIDER_NAME, IconOrSvg, LanguageModel, LanguageModelId, + LanguageModelName, LanguageModelProvider, LanguageModelProviderId, LanguageModelProviderName, + LanguageModelProviderState, LanguageModelRequest, RateLimiter, Role, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -33,8 +33,8 @@ use util::ResultExt; use language_model::ApiKeyState; -const PROVIDER_ID: LanguageModelProviderId = language_model::GOOGLE_PROVIDER_ID; -const PROVIDER_NAME: LanguageModelProviderName = language_model::GOOGLE_PROVIDER_NAME; +const PROVIDER_ID: LanguageModelProviderId = GOOGLE_PROVIDER_ID; +const PROVIDER_NAME: LanguageModelProviderName = GOOGLE_PROVIDER_NAME; #[derive(Default, Clone, Debug, PartialEq)] pub struct GoogleSettings { diff --git a/crates/language_models/src/provider/open_ai.rs b/crates/language_models/src/provider/open_ai.rs index 8de1eaaf8465cf48838c49f6b24d3eb16d6e3487..9289c66b2a4c9213826d2d027555511c9746d00e 100644 --- a/crates/language_models/src/provider/open_ai.rs +++ b/crates/language_models/src/provider/open_ai.rs @@ -10,7 +10,8 @@ use language_model::{ LanguageModelProvider, LanguageModelProviderId, LanguageModelProviderName, LanguageModelProviderState, LanguageModelRequest, LanguageModelRequestMessage, LanguageModelToolChoice, LanguageModelToolResultContent, LanguageModelToolUse, - LanguageModelToolUseId, MessageContent, RateLimiter, Role, StopReason, TokenUsage, env_var, + LanguageModelToolUseId, MessageContent, OPEN_AI_PROVIDER_ID, OPEN_AI_PROVIDER_NAME, + RateLimiter, Role, StopReason, TokenUsage, env_var, }; use menu; use open_ai::responses::{ @@ -35,8 +36,8 @@ use util::ResultExt; use crate::provider::util::{fix_streamed_json, parse_tool_arguments}; -const PROVIDER_ID: LanguageModelProviderId = language_model::OPEN_AI_PROVIDER_ID; -const PROVIDER_NAME: LanguageModelProviderName = language_model::OPEN_AI_PROVIDER_NAME; +const PROVIDER_ID: LanguageModelProviderId = OPEN_AI_PROVIDER_ID; +const PROVIDER_NAME: LanguageModelProviderName = OPEN_AI_PROVIDER_NAME; const API_KEY_ENV_VAR_NAME: &str = "OPENAI_API_KEY"; static API_KEY_ENV_VAR: LazyLock = env_var!(API_KEY_ENV_VAR_NAME);