File size: 2,722 Bytes
182efca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""Pydantic request/response models for the CAD review API."""
from __future__ import annotations

from pydantic import BaseModel, Field


# --- Request models ---

class DistanceRequest(BaseModel):
    """Request to measure distance between two parts."""
    part_a_id: str
    part_b_id: str


# --- Response models ---

class UploadResponse(BaseModel):
    job_id: str
    status: str
    exterior_filename: str
    interior_filename: str


class SampleFileResponse(BaseModel):
    filename: str
    size: int


class SamplePairResponse(BaseModel):
    id: str
    name: str
    exterior: SampleFileResponse
    interior: SampleFileResponse


class StepProgress(BaseModel):
    step: str
    status: str  # pending, running, completed
    progress_pct: int = 0


class JobStatus(BaseModel):
    job_id: str
    status: str  # pending, running, completed, failed
    steps: list[StepProgress] = []
    error: str | None = None

# Rebuild to resolve forward reference
JobStatus.model_rebuild()


class AssemblyNodeResponse(BaseModel):
    id: str
    name: str
    is_assembly: bool
    is_leaf: bool
    classification: str = "unknown"
    num_faces: int = 0
    num_solids: int = 0
    bounding_box: dict | None = None
    children: list[AssemblyNodeResponse] = []

AssemblyNodeResponse.model_rebuild()


class GroupInfoResponse(BaseModel):
    name: str  # "exterior" or "interior"
    part_count: int
    part_ids: list[str]
    part_names: list[str]


class AssemblyTreeResponse(BaseModel):
    root: AssemblyNodeResponse
    groups: list[GroupInfoResponse] = []


class ProximityPairResponse(BaseModel):
    part_a_id: str
    part_a_name: str
    part_b_id: str
    part_b_name: str
    min_distance_mm: float
    point_a: list[float]
    point_b: list[float]
    status: str  # collision, near, ok


class ProximityResponse(BaseModel):
    pairs: list[ProximityPairResponse]
    collision_count: int
    near_count: int


class DistanceMeasurementResponse(BaseModel):
    distance_mm: float
    point_a: list[float]
    point_b: list[float]


class ComplianceResultResponse(BaseModel):
    rule_id: str
    rule_name: str
    passed: bool
    severity: str
    measured_value: float | None = None
    threshold_value: float | None = None
    unit: str = "mm"
    message: str = ""
    affected_parts: list[str] = []


class ComplianceRuleResponse(BaseModel):
    id: str
    name: str
    description: str
    type: str
    severity: str


class ComplianceResponse(BaseModel):
    results: list[ComplianceResultResponse]
    pass_count: int
    fail_count: int


class SSEEvent(BaseModel):
    step: str
    status: str
    progress_pct: int = 0
    overall_status: str | None = None
    error: str | None = None