
* Updates to `zed_llm_client-0.8.5` which adds support for `retry_after` when anthropic provides it. * Distinguishes upstream provider errors and rate limits from errors that originate from zed's servers * Moves `LanguageModelCompletionError::BadInputJson` to `LanguageModelCompletionEvent::ToolUseJsonParseError`. While arguably this is an error case, the logic in thread is cleaner with this move. There is also precedent for inclusion of errors in the event type - `CompletionRequestStatus::Failed` is how cloud errors arrive. * Updates `PROVIDER_ID` / `PROVIDER_NAME` constants to use proper types instead of `&str`, since they can be constructed in a const fashion. * Removes use of `CLIENT_SUPPORTS_EXA_WEB_SEARCH_PROVIDER_HEADER_NAME` as the server no longer reads this header and just defaults to that behavior. Release notes for this is covered by #33275 Release Notes: - N/A --------- Co-authored-by: Richard Feldman <oss@rtfeldman.com> Co-authored-by: Richard <richard@zed.dev>
84 lines
2.9 KiB
Rust
84 lines
2.9 KiB
Rust
use crate::ANTHROPIC_PROVIDER_ID;
|
|
use anthropic::ANTHROPIC_API_URL;
|
|
use anyhow::{Context as _, anyhow};
|
|
use client::telemetry::Telemetry;
|
|
use gpui::BackgroundExecutor;
|
|
use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest};
|
|
use std::env;
|
|
use std::sync::Arc;
|
|
use telemetry_events::{AssistantEventData, AssistantKind, AssistantPhase};
|
|
use util::ResultExt;
|
|
|
|
pub fn report_assistant_event(
|
|
event: AssistantEventData,
|
|
telemetry: Option<Arc<Telemetry>>,
|
|
client: Arc<dyn HttpClient>,
|
|
model_api_key: Option<String>,
|
|
executor: &BackgroundExecutor,
|
|
) {
|
|
if let Some(telemetry) = telemetry.as_ref() {
|
|
telemetry.report_assistant_event(event.clone());
|
|
if telemetry.metrics_enabled() && event.model_provider == ANTHROPIC_PROVIDER_ID.0 {
|
|
if let Some(api_key) = model_api_key {
|
|
executor
|
|
.spawn(async move {
|
|
report_anthropic_event(event, client, api_key)
|
|
.await
|
|
.log_err();
|
|
})
|
|
.detach();
|
|
} else {
|
|
log::error!("Cannot send Anthropic telemetry because API key is missing");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn report_anthropic_event(
|
|
event: AssistantEventData,
|
|
client: Arc<dyn HttpClient>,
|
|
api_key: String,
|
|
) -> anyhow::Result<()> {
|
|
let uri = format!("{ANTHROPIC_API_URL}/v1/log/zed");
|
|
let request_builder = HttpRequest::builder()
|
|
.method(Method::POST)
|
|
.uri(uri)
|
|
.header("X-Api-Key", api_key)
|
|
.header("Content-Type", "application/json");
|
|
let serialized_event: serde_json::Value = serde_json::json!({
|
|
"completion_type": match event.kind {
|
|
AssistantKind::Inline => "natural_language_completion_in_editor",
|
|
AssistantKind::InlineTerminal => "natural_language_completion_in_terminal",
|
|
AssistantKind::Panel => "conversation_message",
|
|
},
|
|
"event": match event.phase {
|
|
AssistantPhase::Response => "response",
|
|
AssistantPhase::Invoked => "invoke",
|
|
AssistantPhase::Accepted => "accept",
|
|
AssistantPhase::Rejected => "reject",
|
|
},
|
|
"metadata": {
|
|
"language_name": event.language_name,
|
|
"message_id": event.message_id,
|
|
"platform": env::consts::OS,
|
|
}
|
|
});
|
|
|
|
let request = request_builder
|
|
.body(AsyncBody::from(serialized_event.to_string()))
|
|
.context("Failed to construct Anthropic telemetry HTTP request body")?;
|
|
|
|
let response = client
|
|
.send(request)
|
|
.await
|
|
.context("Failed to send telemetry HTTP request to Anthropic")?;
|
|
|
|
if response.status().is_success() {
|
|
Ok(())
|
|
} else {
|
|
Err(anyhow!(
|
|
"Anthropic telemetry logging failed with HTTP status: {}",
|
|
response.status()
|
|
))
|
|
}
|
|
}
|