use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize)]
pub struct CodexRequest {
pub model: String,
pub input: Vec<serde_json::Value>,
pub stream: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub instructions: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub tools: Vec<CodexTool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_choice: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temperature: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_output_tokens: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reasoning: Option<ReasoningConfig>,
#[serde(skip_serializing_if = "Option::is_none")]
pub prompt_cache_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub store: Option<bool>,
}
#[derive(Debug, Serialize)]
pub struct CodexTool {
#[serde(rename = "type")]
pub tool_type: String,
pub name: String,
pub description: String,
pub parameters: serde_json::Value,
}
#[derive(Debug, Clone, Serialize)]
pub struct ReasoningConfig {
pub effort: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct SseEvent {
#[serde(rename = "type")]
pub event_type: String,
#[serde(flatten)]
pub data: serde_json::Map<String, serde_json::Value>,
}
#[derive(Debug, Default)]
pub struct ResponseUsage {
pub input_tokens: u64,
pub output_tokens: u64,
pub cached_tokens: u64,
}
impl ResponseUsage {
pub fn from_value(v: &serde_json::Value) -> Self {
let input = v.get("input_tokens").and_then(|v| v.as_u64()).unwrap_or(0);
let output = v.get("output_tokens").and_then(|v| v.as_u64()).unwrap_or(0);
let cached = v
.get("input_tokens_details")
.and_then(|d| d.get("cached_tokens"))
.and_then(|v| v.as_u64())
.unwrap_or(0);
Self {
input_tokens: input,
output_tokens: output,
cached_tokens: cached,
}
}
}