| from __future__ import annotations
|
| from dataclasses import dataclass, field, asdict
|
| from pathlib import Path
|
| from typing import Any, Literal
|
| import json, time, uuid
|
|
|
| OperationType = Literal[
|
| "insert_text","whiteout_region","rotate_page","delete_page",
|
| "reorder_pages","highlight","comment","rectangle","redact"
|
| ]
|
|
|
| @dataclass
|
| class PDFOperation:
|
| type: OperationType
|
| page: int | None = None
|
| rect: tuple | None = None
|
| text: str | None = None
|
| position: tuple | None = None
|
| color: tuple | None = None
|
| pages: list | None = None
|
| rotation: int | None = None
|
| author: str = "Local PDF AI Orchestrator"
|
| metadata: dict = field(default_factory=dict)
|
|
|
| @dataclass
|
| class InspectionReport:
|
| page_count: int
|
| metadata: dict
|
| pages: list
|
| ocr_required_pages: list
|
| has_text: bool
|
| has_images: bool
|
|
|
| @dataclass
|
| class JobConfig:
|
| input_pdf: Path
|
| output_dir: Path
|
| run_ocr: bool = False
|
| force_ocr: bool = False
|
| ocr_language: str = "eng"
|
| pipeline: str = "full_document"
|
| operations: list = field(default_factory=list)
|
| job_id: str = field(default_factory=lambda: uuid.uuid4().hex)
|
| keep_intermediate: bool = True
|
|
|
| @dataclass
|
| class JobResult:
|
| job_id: str
|
| success: bool
|
| final_pdf: Path | None
|
| log_file: Path
|
| manifest_file: Path
|
| stages: list
|
| errors: list = field(default_factory=list)
|
|
|
| def to_json(self) -> str:
|
| return json.dumps({
|
| "job_id": self.job_id,
|
| "success": self.success,
|
| "final_pdf": str(self.final_pdf) if self.final_pdf else None,
|
| "log_file": str(self.log_file),
|
| "manifest_file": str(self.manifest_file),
|
| "stages": self.stages,
|
| "errors": self.errors,
|
| }, indent=2)
|
|
|
| def dataclass_to_dict(obj: Any) -> dict:
|
| def convert(v):
|
| if isinstance(v, Path): return str(v)
|
| if isinstance(v, dict): return {k: convert(x) for k, x in v.items()}
|
| if isinstance(v, list): return [convert(x) for x in v]
|
| return v
|
| return {k: convert(v) for k, v in asdict(obj).items()}
|
|
|