Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T04:49:19.172Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

telemetry.rs

137 lines · 3.7 KB · rust
1use anthropic::ANTHROPIC_API_URL;
2use anyhow::{Context as _, anyhow};
3use gpui::BackgroundExecutor;
4use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest};
5use language_model::{ANTHROPIC_PROVIDER_ID, LanguageModel};
6use std::env;
7use std::sync::Arc;
8use util::ResultExt;
9
10#[derive(Clone, Debug)]
11pub struct AnthropicEventData {
12    pub completion_type: AnthropicCompletionType,
13    pub event: AnthropicEventType,
14    pub language_name: Option<String>,
15    pub message_id: Option<String>,
16}
17
18#[derive(Clone, Debug)]
19pub enum AnthropicCompletionType {
20    Editor,
21    Terminal,
22    Panel,
23}
24
25#[derive(Clone, Debug)]
26pub enum AnthropicEventType {
27    Invoked,
28    Response,
29    Accept,
30    Reject,
31}
32
33impl AnthropicCompletionType {
34    fn as_str(&self) -> &'static str {
35        match self {
36            Self::Editor => "natural_language_completion_in_editor",
37            Self::Terminal => "natural_language_completion_in_terminal",
38            Self::Panel => "conversation_message",
39        }
40    }
41}
42
43impl AnthropicEventType {
44    fn as_str(&self) -> &'static str {
45        match self {
46            Self::Invoked => "invoke",
47            Self::Response => "response",
48            Self::Accept => "accept",
49            Self::Reject => "reject",
50        }
51    }
52}
53
54pub fn report_anthropic_event(
55    model: &Arc<dyn LanguageModel>,
56    event: AnthropicEventData,
57    cx: &gpui::App,
58) {
59    let reporter = AnthropicEventReporter::new(model, cx);
60    reporter.report(event);
61}
62
63#[derive(Clone)]
64pub struct AnthropicEventReporter {
65    http_client: Arc<dyn HttpClient>,
66    executor: BackgroundExecutor,
67    api_key: Option<String>,
68    is_anthropic: bool,
69}
70
71impl AnthropicEventReporter {
72    pub fn new(model: &Arc<dyn LanguageModel>, cx: &gpui::App) -> Self {
73        Self {
74            http_client: cx.http_client(),
75            executor: cx.background_executor().clone(),
76            api_key: model.api_key(cx),
77            is_anthropic: model.provider_id() == ANTHROPIC_PROVIDER_ID,
78        }
79    }
80
81    pub fn report(&self, event: AnthropicEventData) {
82        if !self.is_anthropic {
83            return;
84        }
85        let Some(api_key) = self.api_key.clone() else {
86            return;
87        };
88        let client = self.http_client.clone();
89        self.executor
90            .spawn(async move {
91                send_anthropic_event(event, client, api_key).await.log_err();
92            })
93            .detach();
94    }
95}
96
97async fn send_anthropic_event(
98    event: AnthropicEventData,
99    client: Arc<dyn HttpClient>,
100    api_key: String,
101) -> anyhow::Result<()> {
102    let uri = format!("{ANTHROPIC_API_URL}/v1/log/zed");
103    let request_builder = HttpRequest::builder()
104        .method(Method::POST)
105        .uri(uri)
106        .header("X-Api-Key", api_key)
107        .header("Content-Type", "application/json");
108
109    let serialized_event = serde_json::json!({
110        "completion_type": event.completion_type.as_str(),
111        "event": event.event.as_str(),
112        "metadata": {
113            "language_name": event.language_name,
114            "message_id": event.message_id,
115            "platform": env::consts::OS,
116        }
117    });
118
119    let request = request_builder
120        .body(AsyncBody::from(serialized_event.to_string()))
121        .context("Failed to construct Anthropic telemetry HTTP request body")?;
122
123    let response = client
124        .send(request)
125        .await
126        .context("Failed to send telemetry HTTP request to Anthropic")?;
127
128    if response.status().is_success() {
129        Ok(())
130    } else {
131        Err(anyhow!(
132            "Anthropic telemetry logging failed with HTTP status: {}",
133            response.status()
134        ))
135    }
136}
137
Served at tenant.openagents/omega Member data and write actions are omitted.