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

241
src/api/types.rs Normal file
View File

@@ -0,0 +1,241 @@
//! Request/response types for the OpenAI-compatible API.
//!
//! All response shapes strictly match the official OpenAI Responses API spec:
//! https://platform.openai.com/docs/api-reference/responses
use serde::{Deserialize, Serialize};
// ─── Request types ───────────────────────────────────────────────────────────
#[derive(Deserialize)]
pub(crate) struct ResponsesRequest {
pub model: Option<String>,
pub input: serde_json::Value,
#[serde(default)]
pub instructions: Option<String>,
#[serde(default)]
pub stream: bool,
#[serde(default = "default_timeout")]
pub timeout: u64,
pub conversation: Option<serde_json::Value>,
#[serde(default = "default_true")]
pub store: bool,
#[serde(default)]
pub temperature: Option<f64>,
#[serde(default)]
pub top_p: Option<f64>,
#[serde(default)]
pub max_output_tokens: Option<u64>,
#[serde(default)]
pub previous_response_id: Option<String>,
#[serde(default)]
pub metadata: Option<serde_json::Value>,
#[serde(default)]
pub user: Option<String>,
}
/// Chat Completions request (OpenAI-compatible).
#[derive(Deserialize)]
pub(crate) struct CompletionRequest {
pub model: Option<String>,
pub messages: Vec<CompletionMessage>,
#[serde(default)]
pub stream: bool,
#[serde(default = "default_timeout")]
pub timeout: u64,
}
#[derive(Deserialize)]
pub(crate) struct CompletionMessage {
pub role: String,
pub content: serde_json::Value,
}
fn default_timeout() -> u64 {
120
}
fn default_true() -> bool {
true
}
// ─── Response types (official OpenAI Responses API shape) ────────────────────
/// Top-level Response object — matches OpenAI exactly.
#[derive(Serialize, Clone)]
pub(crate) struct ResponsesResponse {
pub id: String,
pub object: &'static str,
pub created_at: u64,
pub status: &'static str,
#[serde(serialize_with = "serialize_option_u64")]
pub completed_at: Option<u64>,
pub error: Option<serde_json::Value>,
pub incomplete_details: Option<serde_json::Value>,
pub instructions: Option<String>,
#[serde(serialize_with = "serialize_option_u64")]
pub max_output_tokens: Option<u64>,
pub model: String,
pub output: Vec<ResponseOutput>,
pub parallel_tool_calls: bool,
pub previous_response_id: Option<String>,
pub reasoning: Reasoning,
pub store: bool,
pub temperature: f64,
pub text: TextFormat,
pub tool_choice: &'static str,
pub tools: Vec<serde_json::Value>,
pub top_p: f64,
pub truncation: &'static str,
pub usage: Option<Usage>,
pub user: Option<String>,
pub metadata: serde_json::Value,
/// Proxy extension: opaque thinking verification signature.
/// Present for all models. Required for multi-turn chaining with thinking models.
#[serde(skip_serializing_if = "Option::is_none")]
pub thinking_signature: Option<String>,
/// Proxy extension: the model's internal reasoning/thinking content.
/// Available for all models (Opus, Gemini Flash, Gemini Pro).
#[serde(skip_serializing_if = "Option::is_none")]
pub thinking: Option<String>,
/// Proxy extension: time spent thinking (e.g. "0.041999832s").
#[serde(skip_serializing_if = "Option::is_none")]
pub thinking_duration: Option<String>,
}
#[derive(Serialize, Clone)]
pub(crate) struct ResponseOutput {
#[serde(rename = "type")]
pub output_type: &'static str,
pub id: String,
pub status: &'static str,
pub role: &'static str,
pub content: Vec<OutputContent>,
}
#[derive(Serialize, Clone)]
pub(crate) struct OutputContent {
#[serde(rename = "type")]
pub content_type: &'static str,
pub text: String,
pub annotations: Vec<serde_json::Value>,
}
#[derive(Serialize, Clone)]
pub(crate) struct Usage {
pub input_tokens: u64,
pub input_tokens_details: InputTokensDetails,
pub output_tokens: u64,
pub output_tokens_details: OutputTokensDetails,
pub total_tokens: u64,
}
#[derive(Serialize, Clone)]
pub(crate) struct InputTokensDetails {
pub cached_tokens: u64,
}
#[derive(Serialize, Clone)]
pub(crate) struct OutputTokensDetails {
pub reasoning_tokens: u64,
}
#[derive(Serialize, Clone)]
pub(crate) struct Reasoning {
pub effort: Option<String>,
pub summary: Option<String>,
}
#[derive(Serialize, Clone)]
pub(crate) struct TextFormat {
pub format: TextFormatInner,
}
#[derive(Serialize, Clone)]
pub(crate) struct TextFormatInner {
#[serde(rename = "type")]
pub format_type: &'static str,
}
impl Usage {
/// Estimate token counts from actual text.
/// Uses ~4 chars/token heuristic (standard GPT tokenizer average).
pub fn estimate(input_text: &str, output_text: &str) -> Self {
let input_tokens = (input_text.len() as u64 + 3) / 4;
let output_tokens = (output_text.len() as u64 + 3) / 4;
Self {
input_tokens,
input_tokens_details: InputTokensDetails { cached_tokens: 0 },
output_tokens,
output_tokens_details: OutputTokensDetails {
reasoning_tokens: 0,
},
total_tokens: input_tokens + output_tokens,
}
}
}
impl Default for Usage {
fn default() -> Self {
Self {
input_tokens: 0,
input_tokens_details: InputTokensDetails { cached_tokens: 0 },
output_tokens: 0,
output_tokens_details: OutputTokensDetails {
reasoning_tokens: 0,
},
total_tokens: 0,
}
}
}
impl Default for Reasoning {
fn default() -> Self {
Self {
effort: None,
summary: None,
}
}
}
impl Default for TextFormat {
fn default() -> Self {
Self {
format: TextFormatInner {
format_type: "text",
},
}
}
}
// ─── Helpers ─────────────────────────────────────────────────────────────────
/// Serialize Option<u64> as either the number or JSON null (not omitted).
fn serialize_option_u64<S>(val: &Option<u64>, s: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match val {
Some(v) => s.serialize_u64(*v),
None => s.serialize_none(),
}
}
// ─── Shared types ────────────────────────────────────────────────────────────
#[derive(Deserialize)]
pub(crate) struct TokenRequest {
pub token: String,
}
#[derive(Serialize)]
pub(crate) struct ErrorResponse {
pub error: ErrorDetail,
}
#[derive(Serialize)]
pub(crate) struct ErrorDetail {
pub message: String,
#[serde(rename = "type")]
pub error_type: String,
}