""" Free-form command parser for the CI/CD Doctor environment. Converts raw command strings into structured ParsedCommand objects. """ import re from dataclasses import dataclass from typing import Optional @dataclass class ParsedCommand: type: str # "cat" | "echo_append" | "sed" | "pipeline_run" | "pipeline_logs" | "pipeline_status" | "unknown" filename: Optional[str] = None content: Optional[str] = None # for echo >> pattern: Optional[str] = None # for sed: old value replacement: Optional[str] = None # for sed: new value stage: Optional[str] = None # for pipeline logs: which stage def parse_command(command: str) -> ParsedCommand: command = command.strip() # cat if command.startswith("cat "): return ParsedCommand(type="cat", filename=command[4:].strip()) # echo "text" >> filename m = re.match(r'echo\s+"([^"]+)"\s*>>\s*(\S+)', command) if m: return ParsedCommand(type="echo_append", content=m.group(1), filename=m.group(2)) # sed -i 's/old/new/' filename m = re.match(r"sed\s+-i\s+'s/([^/]+)/([^/]*)/'[\s]+(\S+)", command) if m: return ParsedCommand(type="sed", pattern=m.group(1), replacement=m.group(2), filename=m.group(3)) # pipeline run if command == "pipeline run": return ParsedCommand(type="pipeline_run") # pipeline logs [stage] m = re.match(r"pipeline\s+logs(?:\s+(\S+))?\s*$", command) if m: return ParsedCommand(type="pipeline_logs", stage=m.group(1)) # pipeline status if command == "pipeline status": return ParsedCommand(type="pipeline_status") return ParsedCommand(type="unknown")