use axum::{
routing::{get, post},
Router,
};
use std::sync::Arc;
use tokio::sync::RwLock;
mod auth;
mod mapping;
mod routes;
mod telemetry;
use auth::{
agy_binary_path, extract_credentials_candidates, get_binary_sha256, load_expected_sha256,
load_refresh_token, verify_and_bind_credentials, BridgeState,
};
use routes::{anthropic_messages, chat_completions, list_models};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
tracing_subscriber::fmt::init();
tracing::info!("Loading expected SHA256...");
let expected_hash = load_expected_sha256()?;
tracing::info!("Verifying agy binary SHA256...");
let binary_path = agy_binary_path()?;
tracing::info!("Using agy binary at {}", binary_path.display());
let hash = get_binary_sha256(&binary_path)?;
tracing::info!("agy SHA256: {}", hash);
if hash != expected_hash {
anyhow::bail!(
"CRITICAL: agy binary SHA256 hash changed! Expected {}, got {}.",
expected_hash,
hash
);
}
tracing::info!("Extracting OAuth candidates from binary...");
let (client_ids, client_secrets) = extract_credentials_candidates(&binary_path)?;
tracing::info!(
"Found {} client ID and {} client secret candidates.",
client_ids.len(),
client_secrets.len()
);
let refresh_token = load_refresh_token()?;
let (client_id, client_secret) =
verify_and_bind_credentials(&refresh_token, &client_ids, &client_secrets).await?;
let state = Arc::new(RwLock::new(BridgeState {
client_id,
client_secret,
cached_token: None,
token_expiry: 0,
project_id: None,
thought_signature_cache: auth::load_signatures(),
sessions_cache: auth::load_sessions(),
hash_cache: Vec::new(),
}));
use axum::extract::DefaultBodyLimit;
let app = Router::new()
.route("/v1/chat/completions", post(chat_completions))
.route("/v1/messages", post(anthropic_messages))
.route("/messages", post(anthropic_messages))
.route("/v1/models", get(list_models))
.route("/models", get(list_models))
.layer(DefaultBodyLimit::max(15 * 1024 * 1024))
.with_state(state);
let listener = tokio::net::TcpListener::bind("127.0.0.1:8000").await?;
tracing::info!("Starting Rust Antigravity Bridge on http://127.0.0.1:8000");
axum::serve(listener, app).await?;
Ok(())
}