use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize)]
pub struct SurgicalContextInput {
pub file_path: String,
pub agent_id: String,
#[serde(default)]
pub symbol: Option<String>,
#[serde(default = "default_radius")]
pub radius: u32,
#[serde(default = "default_true")]
pub include_tests: bool,
}
fn default_radius() -> u32 {
1
}
fn default_true() -> bool {
true
}
#[derive(Clone, Debug, Serialize)]
pub struct SurgicalContextOutput {
pub file_path: String,
pub file_contents: String,
pub line_count: u32,
pub node_id: String,
pub symbols: Vec<SurgicalSymbol>,
#[serde(skip_serializing_if = "Option::is_none")]
pub focused_symbol: Option<SurgicalSymbol>,
pub callers: Vec<SurgicalNeighbour>,
pub callees: Vec<SurgicalNeighbour>,
pub tests: Vec<SurgicalNeighbour>,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Serialize)]
pub struct SurgicalSymbol {
pub name: String,
#[serde(rename = "type")]
pub symbol_type: String,
pub line_start: u32,
pub line_end: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub excerpt: Option<String>,
}
#[derive(Clone, Debug, Serialize)]
pub struct SurgicalNeighbour {
pub node_id: String,
pub label: String,
pub file_path: String,
pub relation: String,
pub edge_weight: f32,
}
#[derive(Clone, Debug, Deserialize)]
pub struct ApplyInput {
pub file_path: String,
pub agent_id: String,
pub new_content: String,
#[serde(default)]
pub description: Option<String>,
#[serde(default = "default_true")]
pub reingest: bool,
}
#[derive(Clone, Debug, Serialize)]
pub struct ApplyOutput {
pub file_path: String,
pub bytes_written: usize,
pub lines_added: i32,
pub lines_removed: i32,
pub reingested: bool,
pub updated_node_ids: Vec<String>,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Deserialize)]
pub struct SurgicalContextV2Input {
pub file_path: String,
pub agent_id: String,
#[serde(default)]
pub symbol: Option<String>,
#[serde(default = "default_radius")]
pub radius: u32,
#[serde(default = "default_true")]
pub include_tests: bool,
#[serde(default = "default_max_connected_files")]
pub max_connected_files: usize,
#[serde(default = "default_max_lines_per_file")]
pub max_lines_per_file: usize,
}
fn default_max_connected_files() -> usize {
5
}
fn default_max_lines_per_file() -> usize {
60
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ConnectedFileSource {
pub node_id: String,
pub label: String,
pub file_path: String,
pub relation_type: String,
pub edge_weight: f32,
pub source_excerpt: String,
pub excerpt_lines: usize,
pub truncated: bool,
}
#[derive(Clone, Debug, Serialize)]
pub struct SurgicalContextV2Output {
pub file_path: String,
pub file_contents: String,
pub line_count: u32,
pub node_id: String,
pub symbols: Vec<SurgicalSymbol>,
#[serde(skip_serializing_if = "Option::is_none")]
pub focused_symbol: Option<SurgicalSymbol>,
pub connected_files: Vec<ConnectedFileSource>,
pub total_lines: usize,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BatchEditItem {
pub file_path: String,
pub new_content: String,
#[serde(default)]
pub description: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct BatchEditResult {
pub file_path: String,
pub success: bool,
pub diff: String,
pub lines_added: i32,
pub lines_removed: i32,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct ApplyBatchInput {
pub agent_id: String,
pub edits: Vec<BatchEditItem>,
#[serde(default = "default_true")]
pub atomic: bool,
#[serde(default = "default_true")]
pub reingest: bool,
}
#[derive(Clone, Debug, Serialize)]
pub struct ApplyBatchOutput {
pub all_succeeded: bool,
pub files_written: usize,
pub files_total: usize,
pub results: Vec<BatchEditResult>,
pub reingested: bool,
pub total_bytes_written: usize,
pub elapsed_ms: f64,
}