diff --git a/gemini_telemetry.lua b/gemini_telemetry.lua new file mode 100644 index 0000000..64e0044 --- /dev/null +++ b/gemini_telemetry.lua @@ -0,0 +1,28 @@ +local function send_telemetry(event) + local session_id = vim.v.servername + if not session_id or session_id == '' then return end + + local file = vim.api.nvim_buf_get_name(0) + local row, col = unpack(vim.api.nvim_win_get_cursor(0)) + + local payload = string.format( + '{"session_id": "%s", "event": "%s", "file": "%s", "line": %d, "col": %d}', + session_id:gsub("\\", "\\\\"), event, file:gsub("\\", "\\\\"), row, col + ) + + vim.fn.jobstart({ + "curl", "-s", "-X", "POST", "http://127.0.0.1:3000/nvim/telemetry", + "-H", "Content-Type: application/json", + "-d", payload + }, { detach = true }) +end + +local group = vim.api.nvim_create_augroup("GeminiTelemetry", { clear = true }) + +local events = { "FocusGained", "BufEnter", "VimEnter" } +for _, event in ipairs(events) do + vim.api.nvim_create_autocmd(event, { + group = group, + callback = function() send_telemetry(event) end + }) +end diff --git a/server/src/main.rs b/server/src/main.rs index e34ef36..b8fb587 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -328,6 +328,7 @@ fn run_server(state: Arc) -> Result<(), Box> .route("/sse", get(sse_handler)) .route("/messages", post(message_handler)) .route("/health", get(health_handler)) + .route("/nvim/telemetry", post(nvim_telemetry_handler)) .route("/gate/verify", get(gate_verify_handler)) .route("/gate/set", post(gate_set_handler)) .route( @@ -632,6 +633,45 @@ async fn handle_socket(socket: WebSocket, state: Arc, client_type: Str state.clients.write().unwrap().remove(&session_id); } + +#[derive(serde::Deserialize, serde::Serialize, Debug)] +pub struct NvimTelemetry { + pub session_id: String, + pub event: String, + pub file: Option, + pub line: Option, + pub col: Option, +} + +async fn nvim_telemetry_handler( + State(state): State>, + axum::Json(payload): axum::Json, +) -> impl axum::response::IntoResponse { + // 1. Update active_nvim.txt if FocusGained, BufEnter, or VimEnter + if payload.event == "FocusGained" || payload.event == "BufEnter" || payload.event == "VimEnter" { + let profile = std::env::var("USERPROFILE").unwrap_or_else(|_| "C:\\Users\\reazul.ashraf".into()); + let win_path = format!("{}\\.gemini\\active_nvim.txt", profile); + let _ = std::fs::write(&win_path, &payload.session_id); + + let wsl_path = "\\\\wsl.localhost\\Ubuntu\\home\\riz\\.gemini\\active_nvim.txt"; + let _ = std::fs::write(wsl_path, &payload.session_id); + } + + // 2. Broadcast to UI WebSockets + let ws_msg = serde_json::json!({ + "type": "nvim_telemetry", + "data": payload + }); + + let msg_str = ws_msg.to_string(); + let clients = state.clients.read().unwrap().clone(); + for (_, tx) in clients.iter() { + let _ = tx.send(msg_str.clone()).await; + } + + axum::Json(serde_json::json!({"status": "ok"})) +} + async fn health_handler() -> &'static str { "OK" }