from __future__ import annotations from dataclasses import dataclass, field from enum import Enum from typing import Any, Literal class SheetType(Enum): """Excel Sheet 的类型(Parser SheetDetector 判定结果)""" FUNCTION = "FUNCTION" SCREEN = "SCREEN" REPORT = "REPORT" DATABASE = "DATABASE" INTERFACE = "INTERFACE" BATCH = "BATCH" MASTER = "MASTER" GENERIC = "GENERIC" class ElementType(Enum): """Impact Agent 抽取的构成要素类型""" FUNCTION = "機能" SCREEN = "画面" REPORT = "帳票" DB = "DB" IF = "IF" BATCH = "バッチ" class RelationType(Enum): """关联类型(Impact Agent 推理结果)""" USE = "利用" REFER = "参照" UPDATE = "更新" OUTPUT = "输出" INPUT = "输入" DEPEND = "依赖" class Confidence(Enum): """置信度等级""" HIGH = "high" MEDIUM = "medium" LOW = "low" class ExtractionMethod(Enum): """Excel 表的抽取方式""" OPENPYXL = "openpyxl" LLM_FROM_FREE_TEXT = "llm_from_free_text" @dataclass class Provenance: file_name: str sheet_name: str row: int # 数据行号(从 1 起:表格为物理行-表头行;自由文本为块序) column: str column_header: str @dataclass class CellFormatting: strikethrough: bool = False font_color: str | None = None bg_color: str | None = None @dataclass class CellComment: author: str text: str source_uri: str @dataclass class CellValue: value: Any provenance: Provenance formatting: CellFormatting | None = None comment: CellComment | None = None @dataclass class ExcelTable: name: str detected_type: SheetType extraction_method: str # 取 ExtractionMethod 的 value(同一常量来源) headers: list[str] rows: list[dict[str, "CellValue"]] @dataclass class ChapterMarker: type: str # "heading" | "bookmark" | "placeholder" name: str level: int @dataclass class ParsedTemplate: file_name: str sections: list[ChapterMarker] placeholders: dict[str, str] styles: dict @dataclass class RuleDocument: file_name: str category: str # "write" | "design" | "ref" markdown_content: str source_path: str file_type: str # "word" | "excel" | "ppt" hash: str @dataclass class ImageAnalysis: """图片分析结果(Parser 组装,StructuredSource 消费)""" image_ref: str description: str confidence: float source_uri: str sheet_name: str anchor_cell: str status: str # "recognized" | "recorded_only" | "failed" nearby_text: str = "" @dataclass class ControllerInfo: name: str class_name: str path: str base_path: str endpoints: list[str] source_uri: str @dataclass class ServiceInfo: name: str class_name: str path: str methods: list[str] source_uri: str @dataclass class EntityInfo: name: str class_name: str path: str table_name: str | None fields: list[str] source_uri: str @dataclass class EndpointInfo: method: str path: str controller: str | None description: str source_uri: str @dataclass class ExistingSystemInfo: controller_layer: list[ControllerInfo] service_layer: list[ServiceInfo] entity_layer: list[EntityInfo] api_endpoints: list[EndpointInfo] source_path: str class ChangeType(Enum): """变更点定位的变更区分(对应要件定義 変更区分 列值)""" NEW = "新規" MODIFIED = "変更" DELETED = "削除" UNCHANGED = "不变" @dataclass class ChangeElement: """变更点定位结果中的一个要素(Impact Agent MVP)""" element_id: str element_type: str # 機能/画面/帳票/DB/IF/バッチ(取 ElementType.value 或表名) name: str change_type: ChangeType existing_mapping: list[str] = field(default_factory=list) # 既存対応 声明值(类名清单) impacted_existing: list[str] = field(default_factory=list) # 确认命中的既有类 evidence: str = "" # 命中的既有类 source_uri / 空 status: str = "ok" # "ok" | "conflict" | "warning" @dataclass class ImpactWarning: """影响调查告警(不阻断,供用户/QA 关注)""" element_id: str issue: str @dataclass class ChangeAnalysis: """变更点定位结果集合(Impact Agent MVP)""" project_type: str # "enhancement"(追加改修) new_elements: list[ChangeElement] modified_elements: list[ChangeElement] deleted_elements: list[ChangeElement] unchanged_elements: list[ChangeElement] warnings: list[ImpactWarning] @dataclass class DesignReference: """既有设计文档命中引用(Type A 确定性交叉引用)""" doc_name: str # 设计文档文件名 identifier: str # 命中的代码/表标识符 snippet: str # 摘录(前后文片段) @dataclass class ImpactReport: """影响调查书(MVP 子集,供 Writer 生成 + 独立下载)""" metadata: dict change_analysis: ChangeAnalysis | None = None summary: dict = field(default_factory=dict) design_references: list[DesignReference] = field(default_factory=list) # 设计文档命中 @dataclass class UnifiedDocument: """FileReader 的统一输出(多格式归一化)""" file_name: str file_type: str # "excel" | "word" | "ppt" | "text" source_path: str content_type: str tables: list[list[list[Any]]] | None = None sheet_names: list[str] | None = None paragraphs: list[dict] | None = None slides: list[dict] | None = None text: str | None = None encoding: str | None = None @dataclass class CodeStructure: """CodeParser 的解析输出""" root_path: str language: str modules: list[dict] classes: list[dict] controllers: list[ControllerInfo] services: list[ServiceInfo] entities: list[EntityInfo] endpoints: list[EndpointInfo] raw_imports: list[dict] @dataclass class ImageDescription: """ImageAnalyzer 的原始识别输出(工具层;业务侧用 ImageAnalysis)""" image_ref: str description: str objects: list[str] ocr_text: str | None confidence: float model: str @dataclass class StructuredSource: tables: list[ExcelTable] template: ParsedTemplate rule_docs: list[RuleDocument] image_analyses: list[ImageAnalysis] existing_system: ExistingSystemInfo | None comments: list[CellComment] design_docs: list[RuleDocument] = field(default_factory=list) # 既有系统设计文档(Type A,仅参考不做写入规则) impact_report: "ImpactReport | None" = None # 影响调查书(生成后回填,门控未提供时为 None) @dataclass class MixedParagraph: """混合 sheet 的一个段落(表格或自由文本)""" kind: Literal["table", "free_text"] matrix: list[list[Any]] | None = None # 该段原始矩阵(调试/重现) table: ExcelTable | None = None # kind="table" 时填充 text: str | None = None # kind="free_text" 时填充(段全文) source_range: tuple[int, int] | None = None # (first_row, last_row) 矩阵 0-based @dataclass class MixedSheet: """混合 sheet 的段落集合""" name: str paragraphs: list[MixedParagraph] = field(default_factory=list)