File size: 2,175 Bytes
734b5b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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()}