feat: initial commit — antigravity proxy with MITM, standalone LS, and snapshot tooling

This commit is contained in:
Nikketryhard
2026-02-14 02:24:35 -06:00
commit d5e7f09225
30 changed files with 9980 additions and 0 deletions

69
src/warmup.rs Normal file
View File

@@ -0,0 +1,69 @@
//! Startup warmup and periodic heartbeat — mimics real webview lifecycle.
//!
//! The real Electron webview calls these methods on startup and then sends
//! Heartbeat every ~30 seconds. Without this, the LS sees a "user" that
//! never initializes and never heartbeats — an obvious bot fingerprint.
use crate::backend::Backend;
use rand::Rng;
use std::sync::Arc;
use std::time::Duration;
use tokio::task::JoinHandle;
use tracing::{debug, info, warn};
/// Run the exact startup sequence the real webview performs on load.
///
/// Called BEFORE accepting any API requests. Each call is fire-and-forget
/// (we don't care if some fail — the LS might not support all methods).
pub async fn warmup_sequence(backend: &Backend) {
info!("Running webview warmup sequence...");
let calls: &[(&str, serde_json::Value)] = &[
("GetStatus", serde_json::json!({})),
("Heartbeat", serde_json::json!({})),
("GetUserStatus", serde_json::json!({})),
("GetCascadeModelConfigs", serde_json::json!({})),
("GetCascadeModelConfigData", serde_json::json!({})),
("GetWorkspaceInfos", serde_json::json!({})),
("GetWorkingDirectories", serde_json::json!({})),
("GetAllCascadeTrajectories", serde_json::json!({})),
("GetMcpServerStates", serde_json::json!({})),
("GetWebDocsOptions", serde_json::json!({})),
("GetRepoInfos", serde_json::json!({})),
("GetAllSkills", serde_json::json!({})),
("InitializeCascadePanelState", serde_json::json!({})),
];
for (method, body) in calls {
match backend.call_json(method, body).await {
Ok((status, _)) => debug!("Warmup {method}: {status}"),
Err(e) => warn!("Warmup {method} failed: {e}"),
}
// Small delay between calls — real webview doesn't blast them instantly
let delay = rand::thread_rng().gen_range(50..200);
tokio::time::sleep(Duration::from_millis(delay)).await;
}
info!("Warmup complete");
}
/// Spawn a background task that sends Heartbeat every ~30s ± jitter.
///
/// Returns a JoinHandle that runs until the task is aborted (on shutdown).
pub fn start_heartbeat(backend: Arc<Backend>) -> JoinHandle<()> {
tokio::spawn(async move {
loop {
// ~30s interval (± 500ms) — matches real setInterval(30000) precision
let interval_ms = rand::thread_rng().gen_range(29_500..30_500);
tokio::time::sleep(Duration::from_millis(interval_ms)).await;
match backend
.call_json("Heartbeat", &serde_json::json!({}))
.await
{
Ok((status, _)) => debug!("Heartbeat: {status}"),
Err(e) => warn!("Heartbeat failed: {e}"),
}
}
})
}