use crate::files::llm_output_extraction::xml_helpers::tolerant_parsing::{
normalize_enum_value, FILE_ACTION_SYNONYMS, LIST_TYPE_SYNONYMS, PRIORITY_SYNONYMS,
SEVERITY_SYNONYMS, STEP_TYPE_SYNONYMS,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum InlineElement {
Text(String),
Emphasis(String),
Code(String),
Link { href: String, text: String },
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Paragraph {
pub content: Vec<InlineElement>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CodeBlock {
pub content: String,
pub language: Option<String>,
pub filename: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TableCell {
pub content: Vec<InlineElement>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Row {
pub cells: Vec<TableCell>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Table {
pub caption: Option<String>,
pub columns: Vec<String>,
pub rows: Vec<Row>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ListType {
Ordered,
Unordered,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ListItem {
pub content: Vec<InlineElement>,
pub nested_list: Option<Box<List>>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct List {
pub list_type: ListType,
pub items: Vec<ListItem>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Heading {
pub level: u8,
pub text: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ContentElement {
Paragraph(Paragraph),
CodeBlock(CodeBlock),
Table(Table),
List(List),
Heading(Heading),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RichContent {
pub elements: Vec<ContentElement>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScopeItem {
pub description: String,
pub count: Option<String>,
pub category: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PlanSummary {
pub context: String,
pub scope_items: Vec<ScopeItem>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FileAction {
Create,
Modify,
Delete,
}
impl FileAction {
pub(super) fn from_str(s: &str) -> Option<Self> {
const VALID: &[&str] = &["create", "modify", "delete"];
match normalize_enum_value(s, VALID, FILE_ACTION_SYNONYMS)?.as_str() {
"create" => Some(Self::Create),
"modify" => Some(Self::Modify),
"delete" => Some(Self::Delete),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum StepType {
#[default]
FileChange,
Action,
Research,
}
impl StepType {
pub(super) fn from_str(s: &str) -> Option<Self> {
const VALID: &[&str] = &["file-change", "action", "research"];
match normalize_enum_value(s, VALID, STEP_TYPE_SYNONYMS)?.as_str() {
"file-change" => Some(Self::FileChange),
"action" => Some(Self::Action),
"research" => Some(Self::Research),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Priority {
Critical,
High,
Medium,
Low,
}
impl Priority {
pub(super) fn from_str(s: &str) -> Option<Self> {
const VALID: &[&str] = &["critical", "high", "medium", "low"];
match normalize_enum_value(s, VALID, PRIORITY_SYNONYMS)?.as_str() {
"critical" => Some(Self::Critical),
"high" => Some(Self::High),
"medium" => Some(Self::Medium),
"low" => Some(Self::Low),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TargetFile {
pub path: String,
pub action: FileAction,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Step {
pub number: u32,
pub kind: StepType,
pub priority: Option<Priority>,
pub title: String,
pub target_files: Vec<TargetFile>,
pub location: Option<String>,
pub rationale: Option<String>,
pub content: RichContent,
pub depends_on: Vec<u32>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PrimaryFile {
pub path: String,
pub action: FileAction,
pub estimated_changes: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ReferenceFile {
pub path: String,
pub purpose: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CriticalFiles {
pub primary_files: Vec<PrimaryFile>,
pub reference_files: Vec<ReferenceFile>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Severity {
Low,
Medium,
High,
Critical,
}
impl Severity {
pub(super) fn from_str(s: &str) -> Option<Self> {
const VALID: &[&str] = &["low", "medium", "high", "critical"];
match normalize_enum_value(s, VALID, SEVERITY_SYNONYMS)?.as_str() {
"low" => Some(Self::Low),
"medium" => Some(Self::Medium),
"high" => Some(Self::High),
"critical" => Some(Self::Critical),
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RiskPair {
pub severity: Option<Severity>,
pub risk: String,
pub mitigation: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Verification {
pub method: String,
pub expected_outcome: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SkillEntry {
pub name: String,
pub reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct McpEntry {
pub name: String,
pub reason: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SkillsMcp {
pub skills: Vec<SkillEntry>,
pub mcps: Vec<McpEntry>,
pub raw_content: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PlanElements {
pub summary: PlanSummary,
pub steps: Vec<Step>,
pub critical_files: CriticalFiles,
pub risks_mitigations: Vec<RiskPair>,
pub verification_strategy: Vec<Verification>,
pub skills_mcp: Option<SkillsMcp>,
}