use crate::protocol::layers::{HeuristicSignals, HeuristicsSurfaceRef};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize)]
pub struct HeuristicsSurfaceInput {
pub agent_id: String,
#[serde(default)]
pub node_id: Option<String>,
#[serde(default)]
pub file_path: Option<String>,
}
#[derive(Clone, Debug, Serialize)]
pub struct HeuristicsSurfaceOutput {
pub node_id: String,
pub file_path: String,
pub resolved_by: String,
pub heuristic_summary: SurgicalHeuristicSummary,
pub elapsed_ms: f64,
}
#[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>,
#[serde(skip_serializing_if = "Option::is_none")]
pub heuristic_summary: Option<SurgicalHeuristicSummary>,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SurgicalHeuristicSummary {
pub risk_level: String,
pub risk_score: f32,
pub blast_radius_files: usize,
pub blast_radius_risk: String,
pub top_affected: Vec<String>,
pub antibody_hits: usize,
pub heuristic_signals: HeuristicSignals,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ProactiveInsight {
pub severity: String,
pub kind: String,
pub message: String,
pub confidence: f32,
pub evidence: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub suggested_tool: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub suggested_target: Option<String>,
}
#[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>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub proactive_insights: Vec<ProactiveInsight>,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Deserialize)]
pub struct EditPreviewInput {
pub file_path: String,
pub agent_id: String,
pub new_content: String,
#[serde(default)]
pub description: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SourceFileSnapshot {
pub file_path: String,
pub file_exists: bool,
pub content_hash: String,
pub bytes: usize,
pub line_count: usize,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CandidateDiffReport {
pub unified_diff: String,
pub lines_added: i32,
pub lines_removed: i32,
pub bytes_written: usize,
}
#[derive(Clone, Debug, Serialize)]
pub struct EditPreviewOutput {
pub preview_id: String,
pub file_path: String,
pub snapshot: SourceFileSnapshot,
pub diff: CandidateDiffReport,
pub validation: PreviewValidationReport,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Serialize)]
pub struct PreviewValidationReport {
pub source_changed: bool,
pub candidate_is_empty: bool,
pub candidate_equals_source: bool,
pub ready_to_commit: bool,
}
#[derive(Clone, Debug, Deserialize)]
pub struct EditCommitInput {
pub preview_id: String,
pub agent_id: String,
#[serde(default)]
pub confirm: bool,
#[serde(default = "default_true")]
pub reingest: bool,
}
#[derive(Clone, Debug, Serialize)]
pub struct EditCommitOutput {
pub preview_id: String,
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,
#[serde(default)]
pub proof_focused: bool,
}
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,
#[serde(skip_serializing_if = "Option::is_none")]
pub heuristic_summary: Option<SurgicalHeuristicSummary>,
}
#[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>,
#[serde(skip_serializing_if = "Option::is_none")]
pub heuristic_summary: Option<SurgicalHeuristicSummary>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_suggested_tool: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_suggested_target: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_step_hint: Option<String>,
pub proof_state: String,
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,
#[serde(default)]
pub verify: bool,
}
#[derive(Clone, Debug, Serialize)]
pub struct ApplyBatchOutput {
pub batch_id: String,
pub all_succeeded: bool,
pub files_written: usize,
pub files_total: usize,
pub results: Vec<BatchEditResult>,
pub reingested: bool,
pub total_bytes_written: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub verification: Option<VerificationReport>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub proactive_insights: Vec<ProactiveInsight>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_suggested_tool: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_suggested_target: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_step_hint: Option<String>,
pub proof_state: String,
pub status_message: String,
pub active_phase: String,
pub completed_phase_count: usize,
pub phase_count: usize,
pub remaining_phase_count: usize,
pub progress_pct: f32,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_phase: Option<String>,
pub progress_events: Vec<ApplyBatchProgressEvent>,
pub phases: Vec<ApplyBatchPhase>,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ApplyBatchPhase {
pub phase: String,
pub phase_index: usize,
pub status: String,
pub files_completed: usize,
pub files_total: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_file: Option<String>,
pub progress_pct: f32,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_phase: Option<String>,
pub elapsed_ms: f64,
pub message: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ApplyBatchProgressEvent {
pub batch_id: String,
pub event_type: String,
pub phase: String,
pub phase_index: usize,
pub progress_pct: f32,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_file: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_phase: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub proof_state: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_suggested_tool: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_suggested_target: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_step_hint: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub proactive_insights: Vec<ProactiveInsight>,
pub elapsed_ms: f64,
pub message: String,
}
#[derive(Clone, Debug, Serialize)]
pub struct VerificationReport {
pub verdict: String,
pub high_impact_files: Vec<VerificationImpact>,
pub antibodies_triggered: Vec<String>,
pub layer_violations: Vec<String>,
pub total_affected_nodes: usize,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub blast_radius: Vec<BlastRadiusEntry>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tests_run: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tests_passed: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tests_failed: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub test_output: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub compile_check: Option<String>,
pub verify_elapsed_ms: f64,
}
#[derive(Clone, Debug, Serialize)]
pub struct BlastRadiusEntry {
pub file_path: String,
pub reachable_files: usize,
pub risk: String,
pub top_affected: Vec<String>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct ViewInput {
pub file_path: String,
pub agent_id: String,
#[serde(default)]
pub offset: Option<usize>,
#[serde(default)]
pub limit: Option<usize>,
#[serde(default = "default_true")]
pub auto_ingest: bool,
#[serde(default)]
pub max_output_chars: Option<usize>,
}
#[derive(Clone, Debug, Serialize)]
pub struct ViewOutput {
pub file_path: String,
pub content: String,
pub total_lines: usize,
pub offset: usize,
pub lines_returned: usize,
pub auto_ingested: bool,
pub truncated: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub inline_summary: Option<String>,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Deserialize)]
pub struct BatchViewInput {
pub agent_id: String,
pub files: Vec<String>,
#[serde(default = "default_batch_view_lines")]
pub max_lines_per_file: usize,
#[serde(default = "default_true")]
pub summary_mode: bool,
#[serde(default = "default_true")]
pub auto_ingest: bool,
#[serde(default)]
pub max_output_chars: Option<usize>,
}
fn default_batch_view_lines() -> usize {
100
}
#[derive(Clone, Debug, Serialize)]
pub struct BatchViewFileOutput {
pub requested: String,
pub file_path: String,
pub total_lines: usize,
pub lines_returned: usize,
pub auto_ingested: bool,
pub truncated: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub summary: Option<String>,
pub content: String,
}
#[derive(Clone, Debug, Serialize)]
pub struct BatchViewOutput {
pub files_read: usize,
pub total_lines: usize,
pub entries: Vec<BatchViewFileOutput>,
pub truncated: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub inline_summary: Option<String>,
pub elapsed_ms: f64,
}
#[derive(Clone, Debug, Serialize)]
pub struct VerificationImpact {
pub file_path: String,
pub node_id: String,
pub affected_count: usize,
pub risk: String,
pub top_affected: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub heuristic_summary: Option<SurgicalHeuristicSummary>,
#[serde(skip_serializing_if = "Option::is_none")]
pub heuristics_surface_ref: Option<HeuristicsSurfaceRef>,
}