This commit is contained in:
2026-08-21 11:13:18 +08:00
parent beba8744b4
commit 41ed846c23
2028 changed files with 1327194 additions and 293 deletions
+14
View File
@@ -5,6 +5,20 @@ This package rebuilds `cad.cdsl.llm.v1` models through the CDSL-only path:
`sketch_solver -> llm_compiler -> llm_engine -> STEP`
Supported profiles are defined by `SHAPE_GENERATORS` in `sketch_solver.py`.
Supported feature atomic operations are defined by the dispatch in `llm_engine.py`
and their required parameters are defined by `REQUIRED` in `llm_compiler.py`.
Their human-readable contract is in `profile_schema.json`; the complete,
machine-enforced CDSL object contract is in `cdsl_schema.json`.
The Studio only accepts self-contained profile data and requires successful
`engine=cdsl_only` output. It never uses the legacy translator fallback or
`compiler_context`.
## Engine schema maintenance
`profile_schema.json` and `cdsl_schema.json` together are the source of truth
for the engine contract exposed to the CAD Agent and the backend validator.
Any addition, removal, rename, or
parameter-contract change in `sketch_solver.py`, `llm_compiler.py`, or
`llm_engine.py` must update both files in the same change.
`backend/tests/test_profile_schema.py` fails when the registered profiles or
supported atomic operations diverge from the document.
+4 -1
View File
@@ -8,8 +8,9 @@ from __future__ import annotations
from .convert_to_cdsl import convert_sw_json_to_cdsl, write_cdsl_outputs
from .llm_compiler import compile_cdsl
from .llm_engine import run_engine_plan
from .llm_engine import SUPPORTED_ATOMIC_IDS, run_engine_plan
from .rebuild import compare_with_gold, compile_cdsl_to_pack, run_engine, run_rebuild
from .semantic_validation import validate_semantic_cdsl
from .sketch_solver import SHAPE_GENERATORS, resolve_all_sketches
__all__ = [
@@ -23,6 +24,8 @@ __all__ = [
"compare_with_gold",
"resolve_all_sketches",
"SHAPE_GENERATORS",
"SUPPORTED_ATOMIC_IDS",
"validate_semantic_cdsl",
]
__version__ = "1.0.0"
+418
View File
@@ -0,0 +1,418 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://cdsl.local/schema/cad.cdsl.llm.v1",
"title": "CDSL semantic document",
"description": "Complete self-contained CDSL. Runtime-supported operations can be rebuilt by the local CDSL-only engine; deferred operations are retained for future engine implementations.",
"type": "object",
"properties": {
"schema": {"const": "cad.cdsl.llm.v1"},
"schema_version": {"type": "string"},
"kind": {"type": "string", "minLength": 1},
"part_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{3,80}$"},
"meta": {"type": "object"},
"geometry": {
"type": "object",
"properties": {
"sketches": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/sketch"}}
},
"required": ["sketches"],
"additionalProperties": false
},
"features": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/feature"}}
},
"required": ["schema", "geometry", "features"],
"additionalProperties": false,
"$defs": {
"number": {"type": "number"},
"positive": {"type": "number", "exclusiveMinimum": 0},
"positiveInteger": {"type": "integer", "minimum": 1},
"point2": {"type": "array", "items": {"$ref": "#/$defs/number"}, "minItems": 2, "maxItems": 2},
"point3": {"type": "array", "items": {"$ref": "#/$defs/number"}, "minItems": 3, "maxItems": 3},
"circleItem": {
"type": "object",
"properties": {"center": {"$ref": "#/$defs/point2"}, "radius_mm": {"$ref": "#/$defs/positive"}},
"required": ["radius_mm"],
"additionalProperties": false
},
"workplane": {
"type": "object",
"properties": {
"origin_mm": {"$ref": "#/$defs/point3"},
"x_dir": {"$ref": "#/$defs/point3"},
"y_dir": {"$ref": "#/$defs/point3"},
"normal": {"$ref": "#/$defs/point3"}
},
"required": ["origin_mm", "x_dir", "normal"],
"additionalProperties": false
},
"hostFace": {
"type": "object",
"properties": {
"frame": {
"type": "object",
"properties": {
"origin_mm": {"$ref": "#/$defs/point3"},
"x_dir": {"$ref": "#/$defs/point3"},
"y_dir": {"$ref": "#/$defs/point3"},
"normal": {"$ref": "#/$defs/point3"}
},
"required": ["origin_mm", "x_dir", "y_dir", "normal"],
"additionalProperties": false
}
},
"required": ["frame"],
"additionalProperties": false
},
"holePosition": {
"type": "object",
"properties": {"mm": {"$ref": "#/$defs/point3"}},
"required": ["mm"],
"additionalProperties": false
},
"axis": {
"type": "object",
"properties": {"origin_mm": {"$ref": "#/$defs/point3"}, "direction": {"$ref": "#/$defs/point3"}, "selector": {"$ref": "#/$defs/selectorRef"}, "unresolved": {"type": "string", "minLength": 1}},
"anyOf": [{"required": ["origin_mm", "direction"]}, {"required": ["selector"]}, {"required": ["unresolved"]}],
"additionalProperties": false
},
"endCondition": {
"type": "object",
"properties": {
"type": {"type": "string", "minLength": 1},
"solidworks_code": {"type": "integer"},
"reference": {"$ref": "#/$defs/selectorRef"}
},
"required": ["type", "solidworks_code"],
"additionalProperties": false
},
"selectorOrUnresolved": {
"oneOf": [
{"$ref": "#/$defs/selectorRef"},
{"type": "object", "properties": {"unresolved": {"type": "string", "minLength": 1}}, "required": ["unresolved"], "additionalProperties": false}
]
},
"extrudeParams": {
"type": "object",
"properties": {"distance_mm": {"$ref": "#/$defs/number"}, "reverse": {"type": "boolean"}, "reverse_distance_mm": {"$ref": "#/$defs/number"}, "end_condition": {"$ref": "#/$defs/endCondition"}, "reverse_end_condition": {"$ref": "#/$defs/endCondition"}, "draft": {"type": "object"}},
"required": ["distance_mm"],
"additionalProperties": false
},
"revolveParams": {
"type": "object",
"properties": {"angle_deg": {"type": "number", "minimum": 0, "maximum": 360}, "axis": {"$ref": "#/$defs/axis"}, "reverse": {"type": "boolean"}, "end_condition": {"$ref": "#/$defs/endCondition"}},
"required": ["angle_deg", "axis"],
"additionalProperties": false
},
"holeBaseParams": {
"type": "object",
"properties": {
"diameter_mm": {"$ref": "#/$defs/positive"},
"depth_mm": {"$ref": "#/$defs/positive"},
"positions": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/holePosition"}},
"host_face": {"$ref": "#/$defs/hostFace"},
"drill_angle_rad": {"type": "number", "exclusiveMinimum": 0, "exclusiveMaximum": 3.141592653589793}
},
"required": ["diameter_mm", "depth_mm", "positions"]
},
"holeBlindParams": {
"type": "object",
"properties": {
"diameter_mm": {"$ref": "#/$defs/positive"},
"depth_mm": {"$ref": "#/$defs/positive"},
"positions": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/holePosition"}},
"host_face": {"$ref": "#/$defs/hostFace"},
"drill_angle_rad": {"type": "number", "exclusiveMinimum": 0, "exclusiveMaximum": 3.141592653589793}
},
"required": ["diameter_mm", "depth_mm", "positions"],
"additionalProperties": false
},
"holeCountersinkParams": {
"allOf": [
{"$ref": "#/$defs/holeBaseParams"},
{
"type": "object",
"properties": {
"diameter_mm": {"$ref": "#/$defs/positive"}, "depth_mm": {"$ref": "#/$defs/positive"},
"positions": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/holePosition"}},
"host_face": {"$ref": "#/$defs/hostFace"}, "drill_angle_rad": {"type": "number", "exclusiveMinimum": 0, "exclusiveMaximum": 3.141592653589793},
"countersink_diameter_mm": {"$ref": "#/$defs/positive"},
"countersink_angle_rad": {"type": "number", "exclusiveMinimum": 0, "exclusiveMaximum": 3.141592653589793}
},
"required": ["diameter_mm", "depth_mm", "positions", "countersink_diameter_mm", "countersink_angle_rad"],
"additionalProperties": false
}
]
},
"holeCounterboreParams": {
"allOf": [
{"$ref": "#/$defs/holeBaseParams"},
{
"type": "object",
"properties": {
"diameter_mm": {"$ref": "#/$defs/positive"}, "depth_mm": {"$ref": "#/$defs/positive"},
"positions": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/holePosition"}},
"host_face": {"$ref": "#/$defs/hostFace"}, "drill_angle_rad": {"type": "number", "exclusiveMinimum": 0, "exclusiveMaximum": 3.141592653589793},
"counterbore_diameter_mm": {"$ref": "#/$defs/positive"},
"counterbore_depth_mm": {"$ref": "#/$defs/positive"}
},
"required": ["diameter_mm", "depth_mm", "positions", "counterbore_diameter_mm", "counterbore_depth_mm"],
"additionalProperties": false
}
]
},
"filletParams": {
"type": "object",
"properties": {"radius_mm": {"type": "number", "minimum": 0}, "tangent_propagation": {"type": "boolean"}},
"required": ["radius_mm"],
"additionalProperties": false
},
"chamferParams": {
"type": "object",
"properties": {"distance_mm": {"type": "number", "minimum": 0}, "distance_2_mm": {"type": "number", "minimum": 0}, "angle_rad": {"type": "number", "minimum": 0, "maximum": 3.141592653589793}},
"required": ["distance_mm"],
"additionalProperties": false
},
"linearPatternParams": {
"type": "object",
"properties": {
"source_feature_ids": {"type": "array", "items": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"}},
"direction_1": {"$ref": "#/$defs/point3"},
"spacing_1_mm": {"type": "number", "minimum": 0},
"pattern_count_1": {"type": "integer", "minimum": 1},
"direction_2": {"$ref": "#/$defs/point3"},
"spacing_2_mm": {"type": "number", "minimum": 0},
"pattern_count_2": {"type": "integer", "minimum": 1}
},
"required": ["source_feature_ids", "direction_1", "spacing_1_mm", "pattern_count_1"],
"additionalProperties": false
},
"mirrorPatternParams": {
"type": "object",
"properties": {
"source_feature_ids": {"type": "array", "items": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"}},
"mirror_plane": {"$ref": "#/$defs/selectorOrUnresolved"}
},
"required": ["source_feature_ids", "mirror_plane"],
"additionalProperties": false
},
"referencePlaneParams": {
"type": "object",
"properties": {
"plane": {"oneOf": [{"$ref": "#/$defs/workplane"}, {"type": "object", "properties": {"unresolved": {"type": "string", "minLength": 1}}, "required": ["unresolved"], "additionalProperties": false}]},
"references": {"type": "array", "items": {"$ref": "#/$defs/selectorRef"}},
"derived_from_sketch_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"},
"derived_from_feature_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"},
"plane_inference": {"enum": ["solidworks_origin_plane_order", "parent_reference_plane"]},
"offset_mm": {"type": "number"},
"angle_rad": {"type": "number"},
"reverse": {"type": "boolean"},
"solidworks_type": {"type": "integer"}
},
"required": ["plane"],
"additionalProperties": false
},
"referenceAxisParams": {
"type": "object",
"properties": {"axis": {"$ref": "#/$defs/axis"}},
"required": ["axis"],
"additionalProperties": false
},
"holeWizardParams": {
"type": "object",
"properties": {
"hole_type": {"type": "string", "minLength": 1},
"diameter_mm": {"type": "number", "minimum": 0},
"depth_mm": {"type": "number", "minimum": 0},
"end_condition": {"$ref": "#/$defs/endCondition"},
"positions": {"type": "array", "items": {"$ref": "#/$defs/holePosition"}},
"host_face": {"$ref": "#/$defs/selectorRef"},
"thread": {"type": "object"},
"countersink": {"type": "object"},
"counterbore": {"type": "object"}
},
"required": ["hole_type", "diameter_mm", "depth_mm", "end_condition"],
"additionalProperties": false
},
"selectorRef": {
"type": "object",
"properties": {
"kind": {"enum": ["face", "edge", "axis", "plane", "feature", "vertex", "body"]},
"stable_id": {"type": "string", "minLength": 1},
"owner_feature_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"},
"geometry": {"type": "object"},
"source": {"enum": ["solidworks", "inferred_from_step"]},
"confidence": {"type": "number", "minimum": 0, "maximum": 1}
},
"required": ["kind", "stable_id", "source", "confidence"],
"additionalProperties": false
},
"analyticSegment": {
"type": "object",
"properties": {
"type": {"enum": ["line", "arc", "circle", "bspline"]},
"start": {"$ref": "#/$defs/point2"},
"end": {"$ref": "#/$defs/point2"},
"center": {"$ref": "#/$defs/point2"},
"radius_mm": {"$ref": "#/$defs/positive"},
"clockwise": {"type": "boolean"},
"degree": {"type": "integer", "minimum": 1},
"control_points": {"type": "array", "items": {"$ref": "#/$defs/point2"}},
"knots": {"type": "array", "items": {"$ref": "#/$defs/number"}},
"weights": {"type": "array", "items": {"$ref": "#/$defs/positive"}},
"periodic": {"type": "boolean"}
},
"required": ["type"],
"allOf": [
{"if": {"properties": {"type": {"const": "line"}}}, "then": {"required": ["start", "end"]}},
{"if": {"properties": {"type": {"const": "arc"}}}, "then": {"required": ["start", "end", "center", "radius_mm"]}},
{"if": {"properties": {"type": {"const": "circle"}}}, "then": {"required": ["center", "radius_mm"]}},
{"if": {"properties": {"type": {"const": "bspline"}}}, "then": {"required": ["degree", "control_points", "knots"]}}
],
"additionalProperties": false
},
"analyticContour": {
"type": "object",
"properties": {
"role": {"enum": ["outer", "inner", "open", "unknown"]},
"closed": {"type": "boolean"},
"segments": {"type": "array", "items": {"$ref": "#/$defs/analyticSegment"}}
},
"required": ["role", "closed", "segments"],
"additionalProperties": false
},
"analyticProfile": {
"type": "object",
"properties": {
"type": {"const": "analytic_contours"},
"contours": {"type": "array", "items": {"$ref": "#/$defs/analyticContour"}},
"construction": {"type": "array", "items": {"$ref": "#/$defs/analyticSegment"}}
},
"required": ["type", "contours"],
"additionalProperties": false
},
"feature_atomic_ids": {"enum": ["extrude_add_blind", "extrude_add_two_sided", "extrude_cut_blind", "revolve_add", "revolve_cut", "hole_blind", "hole_countersink", "hole_counterbore", "fillet", "chamfer", "pattern_linear", "pattern_mirror", "reference_plane", "reference_axis", "hole_wizard"]},
"feature": {
"type": "object",
"properties": {
"id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"},
"name": {"type": "string"},
"atomic_id": {"$ref": "#/$defs/feature_atomic_ids"},
"depends_on": {"type": "array", "items": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"}},
"sketch_id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"},
"params": {"type": "object"},
"execution_status": {"enum": ["supported", "deferred"]},
"selectors": {"type": "array", "items": {"$ref": "#/$defs/selectorRef"}},
"unresolved": {"type": "array", "items": {"type": "string", "minLength": 1}}
},
"required": ["id", "atomic_id", "depends_on", "params"],
"additionalProperties": false,
"allOf": [
{"if": {"properties": {"atomic_id": {"const": "extrude_add_blind"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/extrudeParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "extrude_add_two_sided"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/extrudeParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "extrude_cut_blind"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/extrudeParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "revolve_add"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/revolveParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "revolve_cut"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/revolveParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "hole_blind"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/holeBlindParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "hole_countersink"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/holeCountersinkParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "hole_counterbore"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/holeCounterboreParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "fillet"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/filletParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "chamfer"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/chamferParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "pattern_linear"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/linearPatternParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "pattern_mirror"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/mirrorPatternParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "reference_plane"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/referencePlaneParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "reference_axis"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/referenceAxisParams"}}}},
{"if": {"properties": {"atomic_id": {"const": "hole_wizard"}}}, "then": {"properties": {"params": {"$ref": "#/$defs/holeWizardParams"}}}}
]
},
"rectangleBounds": {
"type": "object",
"properties": {"center": {"$ref": "#/$defs/point2"}, "width_mm": {"$ref": "#/$defs/positive"}, "height_mm": {"$ref": "#/$defs/positive"}, "min_mm": {"$ref": "#/$defs/point2"}, "max_mm": {"$ref": "#/$defs/point2"}},
"allOf": [
{"oneOf": [
{"required": ["center", "width_mm", "height_mm"], "not": {"anyOf": [{"required": ["min_mm"]}, {"required": ["max_mm"]}]}},
{"required": ["min_mm", "max_mm"], "not": {"anyOf": [{"required": ["center"]}, {"required": ["width_mm"]}, {"required": ["height_mm"]}]}}
]}
]
},
"rectangleBoundary": {
"type": "object",
"properties": {"type": {"enum": ["rectangle", "rectangle_with_fillets"]}, "center": {"$ref": "#/$defs/point2"}, "width_mm": {"$ref": "#/$defs/positive"}, "height_mm": {"$ref": "#/$defs/positive"}, "min_mm": {"$ref": "#/$defs/point2"}, "max_mm": {"$ref": "#/$defs/point2"}, "fillet_radius_mm": {"$ref": "#/$defs/positive"}},
"allOf": [{"$ref": "#/$defs/rectangleBounds"}],
"additionalProperties": false
},
"profile_type": {"enum": ["circle", "annulus", "circles", "circle_grid", "rectangle", "rectangle_with_circles", "rectangle_with_fillets", "obround", "polygon", "ibone", "rectangle_with_symmetric_notches", "revolve_chamfer", "revolve_chamfer_slanted", "circle_with_arc_notches", "circular_sector_slot", "circle_with_radial_tabs", "filleted_rect_side_slots", "d_shape", "partial_ring", "partial_ring_with_arc_island", "radial_slot", "arc_chain", "patterned_cutouts", "compound_patterned_cutouts", "analytic_contours"]},
"motif_type": {"enum": ["circle", "square", "rectangle", "obround", "cross", "d_shape_polygon", "regular_hexagon", "skew_hexagon", "triangle", "teardrop_polygon", "trapezoid", "annular_sector_polygon"]},
"layout_type": {"enum": ["ring", "angular", "concentric_rings", "disc_grid", "open_arc", "spiral", "cross_lines", "x_field", "twin_strips", "corner_clusters", "diamond_field"]},
"motif": {
"oneOf": [
{"type": "object", "properties": {"type": {"const": "circle"}, "radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "square"}, "width_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "width_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "rectangle"}, "width_mm": {"$ref": "#/$defs/positive"}, "height_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "width_mm", "height_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "obround"}, "length_mm": {"$ref": "#/$defs/positive"}, "width_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "length_mm", "width_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "cross"}, "size_mm": {"$ref": "#/$defs/positive"}, "arm_width_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "size_mm", "arm_width_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "d_shape_polygon"}, "stem_length_mm": {"$ref": "#/$defs/positive"}, "nose_depth_mm": {"$ref": "#/$defs/positive"}, "half_height_mm": {"$ref": "#/$defs/positive"}, "arc_segments": {"$ref": "#/$defs/positiveInteger"}}, "required": ["type", "stem_length_mm", "nose_depth_mm", "half_height_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "regular_hexagon"}, "radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "skew_hexagon"}, "nominal_radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "nominal_radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "triangle"}, "radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "teardrop_polygon"}, "width_mm": {"$ref": "#/$defs/positive"}, "height_mm": {"$ref": "#/$defs/positive"}, "shoulder_fraction": {"type": "number", "exclusiveMinimum": 0, "exclusiveMaximum": 1}, "left_width_mm": {"$ref": "#/$defs/positive"}, "right_width_mm": {"$ref": "#/$defs/positive"}, "tip_height_mm": {"$ref": "#/$defs/positive"}, "bottom_depth_mm": {"$ref": "#/$defs/positive"}, "shoulder_height_mm": {"$ref": "#/$defs/positive"}}, "required": ["type"], "oneOf": [{"required": ["width_mm", "height_mm"], "not": {"anyOf": [{"required": ["left_width_mm"]}, {"required": ["right_width_mm"]}, {"required": ["tip_height_mm"]}, {"required": ["bottom_depth_mm"]}, {"required": ["shoulder_height_mm"]}]}}, {"required": ["left_width_mm", "right_width_mm", "tip_height_mm", "bottom_depth_mm", "shoulder_height_mm"], "not": {"anyOf": [{"required": ["width_mm"]}, {"required": ["height_mm"]}, {"required": ["shoulder_fraction"]}]}}], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "trapezoid"}, "bottom_width_mm": {"$ref": "#/$defs/positive"}, "top_width_mm": {"$ref": "#/$defs/positive"}, "height_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "bottom_width_mm", "top_width_mm", "height_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "annular_sector_polygon"}, "inner_radius_mm": {"$ref": "#/$defs/positive"}, "outer_radius_mm": {"$ref": "#/$defs/positive"}, "half_angle_deg": {"$ref": "#/$defs/positive"}, "arc_segments": {"$ref": "#/$defs/positiveInteger"}}, "required": ["type", "inner_radius_mm", "outer_radius_mm", "half_angle_deg"], "additionalProperties": false}
]
},
"layoutCommon": {
"type": "object",
"properties": {"orientation": {"enum": ["fixed", "radial", "tangential", "snapped_radial", "diagonal_axes"]}, "orientation_offset_deg": {"$ref": "#/$defs/number"}, "orientation_snap_deg": {"$ref": "#/$defs/positive"}}
},
"layout": {
"oneOf": [
{"type": "object", "properties": {"type": {"const": "ring"}, "radius_mm": {"$ref": "#/$defs/positive"}, "count": {"$ref": "#/$defs/positiveInteger"}, "start_angle_deg": {"$ref": "#/$defs/number"}, "angle_step_deg": {"$ref": "#/$defs/number"}, "orientation": {"enum": ["fixed", "radial", "tangential", "snapped_radial", "diagonal_axes"]}, "orientation_offset_deg": {"$ref": "#/$defs/number"}, "orientation_snap_deg": {"$ref": "#/$defs/positive"}}, "required": ["type", "radius_mm", "count"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "angular"}, "radius_mm": {"$ref": "#/$defs/number"}, "count": {"$ref": "#/$defs/positiveInteger"}, "start_angle_deg": {"$ref": "#/$defs/number"}, "angle_step_deg": {"$ref": "#/$defs/number"}, "orientation": {"enum": ["fixed", "radial", "tangential", "snapped_radial", "diagonal_axes"]}, "orientation_offset_deg": {"$ref": "#/$defs/number"}, "orientation_snap_deg": {"$ref": "#/$defs/positive"}}, "required": ["type", "count"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "concentric_rings"}, "rings": {"type": "array", "minItems": 1, "items": {"type": "object", "properties": {"radius_mm": {"$ref": "#/$defs/positive"}, "count": {"$ref": "#/$defs/positiveInteger"}, "start_angle_deg": {"$ref": "#/$defs/number"}, "angle_step_deg": {"$ref": "#/$defs/number"}}, "required": ["radius_mm", "count"], "additionalProperties": false}}, "orientation": {"enum": ["fixed", "radial", "tangential", "snapped_radial", "diagonal_axes"]}, "orientation_offset_deg": {"$ref": "#/$defs/number"}, "orientation_snap_deg": {"$ref": "#/$defs/positive"}}, "required": ["type", "rings"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "disc_grid"}, "count_x": {"$ref": "#/$defs/positiveInteger"}, "count_y": {"$ref": "#/$defs/positiveInteger"}, "spacing_x_mm": {"$ref": "#/$defs/positive"}, "spacing_y_mm": {"$ref": "#/$defs/positive"}, "center_mm": {"$ref": "#/$defs/point2"}, "max_center_radius_mm": {"$ref": "#/$defs/positive"}, "orientation_offset_deg": {"$ref": "#/$defs/number"}}, "required": ["type", "count_x", "count_y", "spacing_x_mm", "spacing_y_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "open_arc"}, "radius_mm": {"$ref": "#/$defs/positive"}, "count": {"$ref": "#/$defs/positiveInteger"}, "start_angle_deg": {"$ref": "#/$defs/number"}, "end_angle_deg": {"$ref": "#/$defs/number"}, "orientation": {"enum": ["fixed", "radial", "tangential", "snapped_radial", "diagonal_axes"]}, "orientation_offset_deg": {"$ref": "#/$defs/number"}, "orientation_snap_deg": {"$ref": "#/$defs/positive"}}, "required": ["type", "radius_mm", "count", "start_angle_deg", "end_angle_deg"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "spiral"}, "count": {"$ref": "#/$defs/positiveInteger"}, "start_radius_mm": {"$ref": "#/$defs/positive"}, "radius_step_mm": {"$ref": "#/$defs/number"}, "start_angle_deg": {"$ref": "#/$defs/number"}, "angle_step_deg": {"$ref": "#/$defs/number"}, "orientation": {"enum": ["fixed", "radial", "tangential", "snapped_radial", "diagonal_axes"]}, "orientation_offset_deg": {"$ref": "#/$defs/number"}, "orientation_snap_deg": {"$ref": "#/$defs/positive"}}, "required": ["type", "count", "start_radius_mm", "radius_step_mm", "angle_step_deg"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "cross_lines"}, "count_per_axis": {"$ref": "#/$defs/positiveInteger"}, "spacing_mm": {"$ref": "#/$defs/positive"}, "orientation_offset_deg": {"$ref": "#/$defs/number"}}, "required": ["type", "count_per_axis", "spacing_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "x_field"}, "levels": {"$ref": "#/$defs/positiveInteger"}, "spacing_mm": {"$ref": "#/$defs/positive"}, "orientation": {"enum": ["fixed", "radial", "tangential", "snapped_radial", "diagonal_axes"]}, "orientation_offset_deg": {"$ref": "#/$defs/number"}, "orientation_snap_deg": {"$ref": "#/$defs/positive"}}, "required": ["type", "levels", "spacing_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "twin_strips"}, "x_offset_mm": {"$ref": "#/$defs/positive"}, "count_y": {"$ref": "#/$defs/positiveInteger"}, "y_start_mm": {"$ref": "#/$defs/number"}, "y_end_mm": {"$ref": "#/$defs/number"}, "orientation_offset_deg": {"$ref": "#/$defs/number"}}, "required": ["type", "x_offset_mm", "count_y", "y_start_mm", "y_end_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "corner_clusters"}, "levels_mm": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/positive"}}, "orientation_offset_deg": {"$ref": "#/$defs/number"}}, "required": ["type", "levels_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "diamond_field"}, "manhattan_radius": {"type": "integer", "minimum": 0}, "spacing_mm": {"$ref": "#/$defs/positive"}, "orientation_offset_deg": {"$ref": "#/$defs/number"}}, "required": ["type", "manhattan_radius", "spacing_mm"], "additionalProperties": false}
]
},
"pattern": {"type": "object", "properties": {"motif": {"$ref": "#/$defs/motif"}, "layout": {"$ref": "#/$defs/layout"}}, "required": ["motif", "layout"], "additionalProperties": false},
"profile": {
"oneOf": [
{"type": "object", "properties": {"type": {"const": "circle"}, "center": {"$ref": "#/$defs/point2"}, "radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "annulus"}, "center": {"$ref": "#/$defs/point2"}, "inner_radius_mm": {"$ref": "#/$defs/positive"}, "outer_radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "inner_radius_mm", "outer_radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "circles"}, "items": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "items"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "circle_grid"}, "radius_mm": {"$ref": "#/$defs/positive"}, "count_x": {"$ref": "#/$defs/positiveInteger"}, "count_y": {"$ref": "#/$defs/positiveInteger"}, "spacing_x_mm": {"$ref": "#/$defs/positive"}, "spacing_y_mm": {"$ref": "#/$defs/positive"}, "origin_mm": {"$ref": "#/$defs/point2"}, "center_mm": {"$ref": "#/$defs/point2"}}, "required": ["type", "radius_mm", "count_x", "count_y", "spacing_x_mm", "spacing_y_mm"], "additionalProperties": false, "oneOf": [{"required": ["origin_mm"], "not": {"required": ["center_mm"]}}, {"required": ["center_mm"], "not": {"required": ["origin_mm"]}}]},
{"type": "object", "properties": {"type": {"const": "rectangle"}, "center": {"$ref": "#/$defs/point2"}, "width_mm": {"$ref": "#/$defs/positive"}, "height_mm": {"$ref": "#/$defs/positive"}, "min_mm": {"$ref": "#/$defs/point2"}, "max_mm": {"$ref": "#/$defs/point2"}}, "required": ["type"], "allOf": [{"$ref": "#/$defs/rectangleBounds"}], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "rectangle_with_circles"}, "boundary": {"$ref": "#/$defs/rectangleBoundary"}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "boundary"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "rectangle_with_fillets"}, "center": {"$ref": "#/$defs/point2"}, "width_mm": {"$ref": "#/$defs/positive"}, "height_mm": {"$ref": "#/$defs/positive"}, "min_mm": {"$ref": "#/$defs/point2"}, "max_mm": {"$ref": "#/$defs/point2"}, "fillet_radius_mm": {"$ref": "#/$defs/positive"}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type"], "allOf": [{"$ref": "#/$defs/rectangleBounds"}], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "obround"}, "center": {"$ref": "#/$defs/point2"}, "length_mm": {"$ref": "#/$defs/positive"}, "width_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "length_mm", "width_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "polygon"}, "vertices": {"type": "array", "minItems": 3, "items": {"$ref": "#/$defs/point2"}}}, "required": ["type", "vertices"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "ibone"}, "body_width_mm": {"$ref": "#/$defs/positive"}, "body_height_mm": {"$ref": "#/$defs/positive"}, "flange_width_mm": {"$ref": "#/$defs/positive"}, "flange_height_mm": {"$ref": "#/$defs/positive"}, "corner_radius_mm": {"$ref": "#/$defs/positive"}, "hole_radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["type", "body_width_mm", "body_height_mm", "flange_width_mm", "flange_height_mm", "corner_radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "rectangle_with_symmetric_notches"}, "width_mm": {"$ref": "#/$defs/positive"}, "height_mm": {"$ref": "#/$defs/positive"}, "notch": {"type": "object", "properties": {"y_start": {"$ref": "#/$defs/number"}, "y_end": {"$ref": "#/$defs/number"}, "depth_mm": {"$ref": "#/$defs/positive"}, "inner_radius_mm": {"$ref": "#/$defs/positive"}, "corner_radius_mm": {"$ref": "#/$defs/positive"}}, "required": ["y_start", "y_end", "depth_mm"], "additionalProperties": false}}, "required": ["type", "width_mm", "height_mm", "notch"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "revolve_chamfer"}, "axis_height_mm": {"$ref": "#/$defs/positive"}, "top_width_mm": {"$ref": "#/$defs/positive"}, "bottom_width_mm": {"$ref": "#/$defs/positive"}, "wall_inset_mm": {"$ref": "#/$defs/number"}, "step_inset_mm": {"$ref": "#/$defs/number"}, "on_axis_side": {"enum": ["left", "right"]}}, "required": ["type", "axis_height_mm", "top_width_mm", "bottom_width_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "revolve_chamfer_slanted"}, "axis_height_mm": {"$ref": "#/$defs/positive"}, "top_width_mm": {"$ref": "#/$defs/positive"}, "wall_inset_mm": {"$ref": "#/$defs/number"}, "wall_height_mm": {"$ref": "#/$defs/positive"}, "wall_width_mm": {"$ref": "#/$defs/positive"}, "on_axis_side": {"enum": ["left", "right"]}}, "required": ["type", "axis_height_mm", "top_width_mm", "wall_height_mm", "wall_width_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "circle_with_arc_notches"}, "outer_radius_mm": {"$ref": "#/$defs/positive"}, "notch_radius_mm": {"$ref": "#/$defs/positive"}, "notch_angles_deg": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/number"}}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "outer_radius_mm", "notch_radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "circular_sector_slot"}, "arc_radius_mm": {"$ref": "#/$defs/positive"}, "slot_half_width_mm": {"$ref": "#/$defs/positive"}, "chord_half_mm": {"$ref": "#/$defs/positive"}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "arc_radius_mm", "slot_half_width_mm", "chord_half_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "circle_with_radial_tabs"}, "outer_radius_mm": {"$ref": "#/$defs/positive"}, "tab_u_half_mm": {"$ref": "#/$defs/positive"}, "tab_v_offset_mm": {"$ref": "#/$defs/number"}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "outer_radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "filleted_rect_side_slots"}, "half_width_mm": {"$ref": "#/$defs/positive"}, "half_height_mm": {"$ref": "#/$defs/positive"}, "corner_radius_mm": {"$ref": "#/$defs/positive"}, "slot_radius_mm": {"$ref": "#/$defs/positive"}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "half_width_mm", "half_height_mm", "corner_radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "d_shape"}, "radius_mm": {"$ref": "#/$defs/positive"}, "chord_sign": {"enum": ["left", "right"]}, "chord_x_mm": {"$ref": "#/$defs/positive"}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "partial_ring"}, "inner_radius_mm": {"$ref": "#/$defs/positive"}, "outer_radius_mm": {"$ref": "#/$defs/positive"}, "half_angle_deg": {"$ref": "#/$defs/positive"}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "inner_radius_mm", "outer_radius_mm"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "partial_ring_with_arc_island"}, "inner_radius_mm": {"$ref": "#/$defs/positive"}, "outer_radius_mm": {"$ref": "#/$defs/positive"}, "half_angle_deg": {"$ref": "#/$defs/positive"}, "island_radius_mm": {"$ref": "#/$defs/positive"}, "island_gap_mm": {"$ref": "#/$defs/positive"}, "center_angles_deg": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/number"}}, "replicas": {"type": "array", "minItems": 1, "items": {"type": "object", "properties": {"center_angle_deg": {"$ref": "#/$defs/number"}}, "required": ["center_angle_deg"], "additionalProperties": false}}}, "required": ["type", "inner_radius_mm", "outer_radius_mm", "island_radius_mm"], "additionalProperties": false, "oneOf": [{"required": ["center_angles_deg"], "not": {"required": ["replicas"]}}, {"required": ["replicas"], "not": {"required": ["center_angles_deg"]}}]},
{"type": "object", "properties": {"type": {"const": "radial_slot"}, "inner_radius_mm": {"$ref": "#/$defs/positive"}, "outer_radius_mm": {"$ref": "#/$defs/positive"}, "start_angle_deg": {"$ref": "#/$defs/number"}, "end_angle_deg": {"$ref": "#/$defs/number"}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "inner_radius_mm", "outer_radius_mm", "start_angle_deg", "end_angle_deg"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "arc_chain"}, "arcs": {"type": "array", "minItems": 2, "items": {"type": "object", "properties": {"center": {"$ref": "#/$defs/point2"}, "radius_mm": {"$ref": "#/$defs/positive"}, "start_angle_deg": {"$ref": "#/$defs/number"}, "end_angle_deg": {"$ref": "#/$defs/number"}}, "required": ["radius_mm", "start_angle_deg", "end_angle_deg"], "additionalProperties": false}}, "circles": {"type": "array", "items": {"$ref": "#/$defs/circleItem"}}}, "required": ["type", "arcs"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "patterned_cutouts"}, "motif": {"$ref": "#/$defs/motif"}, "layout": {"$ref": "#/$defs/layout"}}, "required": ["type", "motif", "layout"], "additionalProperties": false},
{"type": "object", "properties": {"type": {"const": "compound_patterned_cutouts"}, "patterns": {"type": "array", "minItems": 1, "items": {"$ref": "#/$defs/pattern"}}}, "required": ["type", "patterns"], "additionalProperties": false},
{"$ref": "#/$defs/analyticProfile"}
]
},
"sketch": {
"type": "object",
"properties": {"id": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"}, "name": {"type": "string"}, "workplane": {"$ref": "#/$defs/workplane"}, "profile": {"$ref": "#/$defs/profile"}, "role": {"enum": ["profile", "reference"]}, "attachment": {"$ref": "#/$defs/selectorRef"}, "profile_from": {"type": "string", "pattern": "^[A-Za-z0-9_-]{1,80}$"}},
"required": ["id", "workplane", "profile"],
"additionalProperties": false
}
}
}
+15
View File
@@ -37,6 +37,21 @@ from build123d import ( # noqa: E402
)
# Keep this in sync with the execution branches in run_engine_plan. The
# agent-facing schema and its parity test prevent unsupported names reaching
# this low-level dispatcher.
SUPPORTED_ATOMIC_IDS = frozenset({
"extrude_add_blind",
"extrude_add_two_sided",
"extrude_cut_blind",
"revolve_add",
"revolve_cut",
"hole_blind",
"hole_countersink",
"hole_counterbore",
})
def _load(path: Path) -> dict[str, Any]:
return json.loads(path.read_text(encoding="utf-8"))
@@ -0,0 +1,226 @@
{
"schema": "cdsl.engine.schema.v1",
"schema_version": "1.3.0",
"cdsl_json_schema_file": "cdsl_schema.json",
"maintenance_rule": "The semantic CDSL contract is a superset of the current runtime. runtime_supported_atomic_ids and runtime_supported_profiles must stay synchronized with sketch_solver.py, llm_compiler.py and llm_engine.py; deferred entries describe future engine work.",
"coordinate_convention": "All profile dimensions use millimetres. Two-dimensional points are [u, v] in the sketch workplane.",
"runtime_supported_atomic_ids": ["extrude_add_blind", "extrude_add_two_sided", "extrude_cut_blind", "revolve_add", "revolve_cut", "hole_blind", "hole_countersink", "hole_counterbore"],
"runtime_supported_profiles": ["circle", "annulus", "circles", "circle_grid", "rectangle", "rectangle_with_circles", "rectangle_with_fillets", "obround", "polygon", "ibone", "rectangle_with_symmetric_notches", "revolve_chamfer", "revolve_chamfer_slanted", "circle_with_arc_notches", "circular_sector_slot", "circle_with_radial_tabs", "filleted_rect_side_slots", "d_shape", "partial_ring", "partial_ring_with_arc_island", "arc_chain", "radial_slot", "patterned_cutouts", "compound_patterned_cutouts", "complex_arc_shape", "unknown_shape"],
"feature_atomic_ids": {
"extrude_add_blind": {"summary": "Add the closed profile by one signed extrusion distance.", "required_params": ["distance_mm"], "optional_params": ["reverse"], "requires_sketch": true},
"extrude_add_two_sided": {"summary": "Add the closed profile symmetrically on both sides of its workplane.", "required_params": ["distance_mm"], "optional_params": [], "requires_sketch": true},
"extrude_cut_blind": {"summary": "Remove the closed profile by one signed extrusion distance.", "required_params": ["distance_mm"], "optional_params": ["reverse"], "requires_sketch": true},
"revolve_add": {"summary": "Add the closed profile by revolving it around an axis.", "required_params": ["angle_deg", "axis"], "optional_params": ["reverse"], "requires_sketch": true},
"revolve_cut": {"summary": "Remove the closed profile by revolving it around an axis.", "required_params": ["angle_deg", "axis"], "optional_params": ["reverse"], "requires_sketch": true},
"hole_blind": {"summary": "Cut one or more blind cylindrical holes in the current body.", "required_params": ["diameter_mm", "depth_mm", "positions"], "optional_params": ["host_face", "drill_angle_rad"], "position_format": "positions is a non-empty array of objects: [{\"mm\":[u_mm,v_mm,w_mm]}]. A bare coordinate array is invalid.", "requires_sketch": true},
"hole_countersink": {"summary": "Cut one or more blind holes with countersink dimensions.", "required_params": ["diameter_mm", "depth_mm", "positions", "countersink_diameter_mm", "countersink_angle_rad"], "optional_params": ["host_face", "drill_angle_rad"], "position_format": "positions is a non-empty array of objects: [{\"mm\":[u_mm,v_mm,w_mm]}]. A bare coordinate array is invalid.", "requires_sketch": true},
"hole_counterbore": {"summary": "Cut one or more blind holes with counterbore dimensions.", "required_params": ["diameter_mm", "depth_mm", "positions", "counterbore_diameter_mm", "counterbore_depth_mm"], "optional_params": ["host_face", "drill_angle_rad"], "position_format": "positions is a non-empty array of objects: [{\"mm\":[u_mm,v_mm,w_mm]}]. A bare coordinate array is invalid.", "requires_sketch": true},
"fillet": {"summary": "Apply a radius to selected edges or faces.", "required_params": ["radius_mm"], "optional_params": ["tangent_propagation"], "requires_sketch": false, "execution_status": "deferred"},
"chamfer": {"summary": "Apply an equal-distance or angle-distance chamfer to selected edges or faces.", "required_params": ["distance_mm"], "optional_params": ["distance_2_mm", "angle_rad"], "requires_sketch": false, "execution_status": "deferred"},
"pattern_linear": {"summary": "Repeat source features along one or two directions.", "required_params": ["source_feature_ids", "direction_1", "spacing_1_mm", "pattern_count_1"], "optional_params": ["direction_2", "spacing_2_mm", "pattern_count_2"], "requires_sketch": false, "execution_status": "deferred"},
"pattern_mirror": {"summary": "Mirror source features about a selected plane.", "required_params": ["source_feature_ids", "mirror_plane"], "optional_params": [], "requires_sketch": false, "execution_status": "deferred"},
"reference_plane": {"summary": "A named reference plane used by sketches or patterns.", "required_params": ["plane"], "optional_params": [], "requires_sketch": false, "execution_status": "deferred"},
"reference_axis": {"summary": "A named reference axis used by revolve or pattern features.", "required_params": ["axis"], "optional_params": [], "requires_sketch": false, "execution_status": "deferred"},
"hole_wizard": {"summary": "A SolidWorks Hole Wizard feature including its typed dimensional contract and placement selectors.", "required_params": ["hole_type", "diameter_mm", "depth_mm"], "optional_params": ["positions", "host_face", "thread", "countersink", "counterbore"], "requires_sketch": false, "execution_status": "deferred"}
},
"profiles": {
"circle": {
"agent_allowed": true,
"summary": "A single circular closed profile.",
"required": ["radius_mm"],
"optional": ["center"],
"constraints": ["radius_mm > 0", "center defaults to [0, 0]"]
},
"annulus": {
"agent_allowed": true,
"summary": "A concentric ring.",
"required": ["inner_radius_mm", "outer_radius_mm"],
"optional": ["center"],
"constraints": ["0 < inner_radius_mm < outer_radius_mm"]
},
"circles": {
"agent_allowed": true,
"summary": "A non-empty list of circles.",
"required": ["items"],
"item_schema": {"required": ["radius_mm"], "optional": ["center"]}
},
"circle_grid": {
"agent_allowed": true,
"summary": "A rectangular grid of equal circles.",
"required": ["radius_mm", "count_x", "count_y", "spacing_x_mm", "spacing_y_mm"],
"optional": ["origin_mm", "center_mm"],
"constraints": ["radius_mm > 0", "count_x and count_y are integers >= 1", "use origin_mm or center_mm, not both"]
},
"rectangle": {
"agent_allowed": true,
"summary": "An axis-aligned rectangle.",
"one_of": [["center", "width_mm", "height_mm"], ["min_mm", "max_mm"]],
"constraints": ["width_mm > 0 and height_mm > 0 when using center"]
},
"rectangle_with_circles": {
"agent_allowed": true,
"summary": "A rectangle or filleted rectangle with optional internal circles.",
"required": ["boundary"],
"optional": ["circles"],
"nested": {"boundary": "rectangle schema plus optional type=rectangle|rectangle_with_fillets and fillet_radius_mm"}
},
"rectangle_with_fillets": {
"agent_allowed": true,
"summary": "An axis-aligned rectangle with corner fillets and optional internal circles.",
"one_of": [["center", "width_mm", "height_mm"], ["min_mm", "max_mm"]],
"optional": ["fillet_radius_mm", "circles"],
"constraints": ["fillet_radius_mm defaults to 0"]
},
"obround": {
"agent_allowed": true,
"summary": "A horizontal capsule/slot.",
"required": ["length_mm", "width_mm"],
"optional": ["center"],
"constraints": ["length_mm > 0", "width_mm > 0", "center defaults to [0, 0]"]
},
"polygon": {
"agent_allowed": true,
"summary": "A closed straight-edge polygon.",
"required": ["vertices"],
"constraints": ["vertices contains at least three [u, v] points"]
},
"ibone": {
"agent_allowed": true,
"summary": "I-shaped lug with optional four holes.",
"required": ["body_width_mm", "body_height_mm", "flange_width_mm", "flange_height_mm", "corner_radius_mm"],
"optional": ["hole_radius_mm"]
},
"rectangle_with_symmetric_notches": {
"agent_allowed": true,
"summary": "A rectangular plate with four symmetric side notches.",
"required": ["width_mm", "height_mm", "notch"],
"nested": {"notch": {"required": ["y_start", "y_end", "depth_mm"], "optional": ["inner_radius_mm", "corner_radius_mm"]}}
},
"revolve_chamfer": {
"agent_allowed": true,
"summary": "Five-edge trapezoid profile for a revolve cut.",
"required": ["axis_height_mm", "top_width_mm", "bottom_width_mm"],
"optional": ["wall_inset_mm", "step_inset_mm", "on_axis_side"],
"constraints": ["on_axis_side is left or right"]
},
"revolve_chamfer_slanted": {
"agent_allowed": true,
"summary": "Five-edge slanted profile for a revolve cut.",
"required": ["axis_height_mm", "top_width_mm", "wall_height_mm", "wall_width_mm"],
"optional": ["wall_inset_mm", "on_axis_side"],
"constraints": ["on_axis_side is left or right"]
},
"circle_with_arc_notches": {
"agent_allowed": true,
"summary": "A circular boundary with arc-shaped notches.",
"required": ["outer_radius_mm", "notch_radius_mm"],
"optional": ["notch_angles_deg", "circles"],
"constraints": ["notch_angles_deg defaults to [0, 90, 180, 270]"]
},
"circular_sector_slot": {
"agent_allowed": true,
"summary": "A circular-sector boundary with a central rectangular slot.",
"required": ["arc_radius_mm", "slot_half_width_mm", "chord_half_mm"],
"optional": ["circles"]
},
"circle_with_radial_tabs": {
"agent_allowed": true,
"summary": "A circle with two mirrored radial tabs.",
"required": ["outer_radius_mm"],
"optional": ["tab_u_half_mm", "tab_v_offset_mm", "circles"]
},
"filleted_rect_side_slots": {
"agent_allowed": true,
"summary": "A filleted rectangle with one semicircular slot at each side centre.",
"required": ["half_width_mm", "half_height_mm", "corner_radius_mm"],
"optional": ["slot_radius_mm", "circles"]
},
"d_shape": {
"agent_allowed": true,
"summary": "A D-shaped boundary made from one chord and one arc.",
"required": ["radius_mm"],
"optional": ["chord_sign", "chord_x_mm", "circles"],
"constraints": ["chord_sign is left or right"]
},
"partial_ring": {
"agent_allowed": true,
"summary": "An annular sector.",
"required": ["inner_radius_mm", "outer_radius_mm"],
"optional": ["half_angle_deg", "circles"],
"constraints": ["0 < inner_radius_mm < outer_radius_mm"]
},
"partial_ring_with_arc_island": {
"agent_allowed": true,
"summary": "One or more annular sectors with an arc island.",
"required": ["inner_radius_mm", "outer_radius_mm", "island_radius_mm"],
"optional": ["half_angle_deg", "island_gap_mm", "center_angles_deg", "replicas"],
"nested": {"replicas": {"required": ["center_angle_deg"]}}
},
"arc_chain": {
"agent_allowed": true,
"summary": "A closed chain of two or more arcs, commonly used for revolve sections.",
"required": ["arcs"],
"optional": ["circles"],
"item_schema": {"required": ["radius_mm", "start_angle_deg", "end_angle_deg"], "optional": ["center"]},
"constraints": ["arcs contains at least two endpoint-connected arcs"]
},
"radial_slot": {
"agent_allowed": true,
"summary": "A rounded annular sector slot.",
"required": ["inner_radius_mm", "outer_radius_mm", "start_angle_deg", "end_angle_deg"],
"optional": ["circles"],
"constraints": ["0 < inner_radius_mm < outer_radius_mm"]
},
"patterned_cutouts": {
"agent_allowed": true,
"summary": "One procedural cutout motif repeated by one procedural layout.",
"required": ["motif", "layout"],
"nested": {"motif": "See motif_types", "layout": "See layout_types"}
},
"compound_patterned_cutouts": {
"agent_allowed": true,
"summary": "Multiple procedural motif/layout pairs merged into one cutout sketch.",
"required": ["patterns"],
"nested": {"patterns": "Non-empty list of {motif, layout}; see patterned_cutouts."}
},
"complex_arc_shape": {
"agent_allowed": false,
"summary": "Legacy compiler-context fallback only. Never generate it."
},
"analytic_contours": {
"agent_allowed": false,
"summary": "Exact analytic line, arc, circle and B-spline contours emitted by the Evidence v2 converter. Future engines must consume this profile without relying on compiler_context."
},
"unknown_shape": {
"agent_allowed": false,
"summary": "Legacy compiler-context fallback only. Never generate it."
}
},
"motif_types": {
"circle": ["radius_mm"],
"square": ["width_mm"],
"rectangle": ["width_mm", "height_mm"],
"obround": ["length_mm", "width_mm"],
"cross": ["size_mm", "arm_width_mm"],
"d_shape_polygon": ["stem_length_mm", "nose_depth_mm", "half_height_mm"],
"regular_hexagon": ["radius_mm"],
"skew_hexagon": ["nominal_radius_mm"],
"triangle": ["radius_mm"],
"teardrop_polygon": ["width_mm", "height_mm"],
"trapezoid": ["bottom_width_mm", "top_width_mm", "height_mm"],
"annular_sector_polygon": ["inner_radius_mm", "outer_radius_mm", "half_angle_deg"]
},
"layout_types": {
"ring": ["radius_mm", "count"],
"angular": ["count"],
"concentric_rings": ["rings"],
"disc_grid": ["count_x", "count_y", "spacing_x_mm", "spacing_y_mm"],
"open_arc": ["radius_mm", "count", "start_angle_deg", "end_angle_deg"],
"spiral": ["count", "start_radius_mm", "radius_step_mm", "angle_step_deg"],
"cross_lines": ["count_per_axis", "spacing_mm"],
"x_field": ["levels", "spacing_mm"],
"twin_strips": ["x_offset_mm", "count_y", "y_start_mm", "y_end_mm"],
"corner_clusters": ["levels_mm"],
"diamond_field": ["manhattan_radius", "spacing_mm"]
}
}
+13 -9
View File
@@ -38,13 +38,12 @@ def run_rebuild(cdsl: dict[str, Any], out_step: Path, ctx_file: Path | None = No
_sketch_is_cdsl_drawable(s) for s in sketches
)
if all_drawable and not force_exact:
try:
return _run_cdsl_only(cdsl, out_step, gold_step=gold_step)
except Exception as e:
import traceback
traceback.print_exc()
print(f" [WARN] CDSL-only path failed: {e}, falling back")
cdsl_only_error: Exception | None = None
if all_drawable and not force_exact:
try:
return _run_cdsl_only(cdsl, out_step, gold_step=gold_step)
except Exception as e:
cdsl_only_error = e
# 加载 compiler_context(后备路径)
ctx = None
@@ -66,8 +65,13 @@ def run_rebuild(cdsl: dict[str, Any], out_step: Path, ctx_file: Path | None = No
"references": ir.get("references", []),
"validation_hints": ir.get("validation_hints", {}),
}
if ctx is None and not (cdsl.get("compiler_context")):
raise RuntimeError("No compiler_context available and CDSL-only rebuild failed/unavailable")
if ctx is None and not (cdsl.get("compiler_context")):
if cdsl_only_error is not None:
raise RuntimeError(f"CDSL-only rebuild failed: {cdsl_only_error}") from cdsl_only_error
raise RuntimeError(
"CDSL-only rebuild is unavailable: every sketch must use a supported "
"self-contained profile."
)
if ctx is not None:
cdsl["compiler_context"] = ctx
@@ -0,0 +1,103 @@
"""Validation for the complete CDSL v1.1 semantic contract.
The current runtime accepts only a subset of this contract. Keeping this
validator separate lets import tooling preserve a SolidWorks feature history
without claiming that every feature can already be rebuilt locally.
"""
from __future__ import annotations
import json
import re
from functools import lru_cache
from pathlib import Path
from typing import Any
from jsonschema import Draft202012Validator
_ID = re.compile(r"^[A-Za-z0-9_-]{1,80}$")
@lru_cache(maxsize=1)
def _schema() -> dict[str, Any]:
path = Path(__file__).with_name("cdsl_schema.json")
schema = json.loads(path.read_text(encoding="utf-8"))
Draft202012Validator.check_schema(schema)
return schema
@lru_cache(maxsize=1)
def _validator() -> Draft202012Validator:
return Draft202012Validator(_schema())
def _schema_error(document: dict[str, Any]) -> str | None:
validator = _validator()
errors = sorted(validator.iter_errors(document), key=lambda error: (list(error.absolute_path), error.message))
if not errors:
return None
error = errors[0]
location = "$" + "".join(f"[{item}]" if isinstance(item, int) else f".{item}" for item in error.absolute_path)
return f"CDSL schema violation at {location}: {error.message}"
def validate_semantic_cdsl(cdsl: dict[str, Any]) -> dict[str, Any]:
"""Validate a CDSL document without invoking the rebuild compiler.
The return value is intentionally serializable so the batch converter can
write it unchanged into a per-model diagnostic file.
"""
if not isinstance(cdsl, dict):
raise ValueError("CDSL must be a JSON object")
if cdsl.get("schema") != "cad.cdsl.llm.v1":
raise ValueError("Unsupported CDSL schema")
schema_error = _schema_error(cdsl)
if schema_error:
raise ValueError(schema_error)
version = str(cdsl.get("schema_version") or "1.0.0")
if not re.fullmatch(r"1\.[0-9]+\.[0-9]+", version):
raise ValueError("schema_version must be a 1.x.y version")
version_numbers = tuple(int(component) for component in version.split("."))
if version_numbers >= (1, 1, 0) and cdsl.get("meta", {}).get("unit") != "mm":
raise ValueError("CDSL v1.1 requires meta.unit = 'mm'")
sketches = (cdsl.get("geometry") or {}).get("sketches") or []
sketch_ids = {str(sketch.get("id") or "") for sketch in sketches}
if len(sketch_ids) != len(sketches) or not all(_ID.fullmatch(item) for item in sketch_ids):
raise ValueError("Sketch ids must be unique valid CDSL identifiers")
feature_ids: set[str] = set()
deferred: list[str] = []
unresolved: list[dict[str, Any]] = []
for feature in cdsl.get("features") or []:
fid = str(feature.get("id") or "")
if not _ID.fullmatch(fid) or fid in feature_ids:
raise ValueError("Feature ids must be unique valid CDSL identifiers")
for dependency in feature.get("depends_on") or []:
if dependency not in feature_ids:
raise ValueError(f"Feature {fid} has a forward or missing dependency: {dependency}")
sketch_id = feature.get("sketch_id")
if sketch_id is not None and str(sketch_id) not in sketch_ids:
raise ValueError(f"Feature {fid} refers to a missing sketch: {sketch_id}")
if version_numbers >= (1, 1, 0) and feature.get("execution_status") not in {"supported", "deferred"}:
raise ValueError(f"Feature {fid} must declare execution_status")
if feature.get("execution_status") == "deferred":
deferred.append(fid)
for index, selector in enumerate(feature.get("selectors") or []):
owner = selector.get("owner_feature_id")
if owner is not None and owner not in feature_ids:
raise ValueError(f"Feature {fid} selector {index} has a forward or missing owner_feature_id")
if feature.get("unresolved"):
unresolved.append({"feature_id": fid, "reasons": list(feature["unresolved"])})
feature_ids.add(fid)
return {
"schema_version": version,
"feature_count": len(feature_ids),
"sketch_count": len(sketches),
"deferred_feature_ids": deferred,
"unresolved": unresolved,
"future_rebuild_ready": not unresolved,
}
+2 -1
View File
@@ -4,10 +4,11 @@ LLM 只需输出离散决策(type, radius, width …),
求解器负责生成精确的实体和轮廓边坐标
架构注册表模式 每个轮廓类型对应一个生成器函数
"type" 字符串索引新增形状只需 3
"type" 字符串索引新增形状或调整既有 profile 参数契约时
1. def solver_xxx(profile, meta) -> (entities, contour)
2. 注册: SHAPE_GENERATORS["xxx"] = solver_xxx
3. convert 脚本中输出对应的 profile
4. 同步更新 profile_schema.jsonAgent 与后端校验器的公开契约
支持的 profile 类型
- circle: 单个圆