dcad 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. dcad-0.1.0/.github/workflows/ci.yml +51 -0
  2. dcad-0.1.0/.github/workflows/publish.yml +38 -0
  3. dcad-0.1.0/.gitignore +43 -0
  4. dcad-0.1.0/CHANGELOG.md +9 -0
  5. dcad-0.1.0/CONTRIBUTING.md +138 -0
  6. dcad-0.1.0/LICENSE +21 -0
  7. dcad-0.1.0/PKG-INFO +183 -0
  8. dcad-0.1.0/README.md +152 -0
  9. dcad-0.1.0/benchmarks/cases.py +85 -0
  10. dcad-0.1.0/benchmarks/run_benchmarks.py +104 -0
  11. dcad-0.1.0/packages/cadpy/README.md +44 -0
  12. dcad-0.1.0/packages/cadpy/pyproject.toml +23 -0
  13. dcad-0.1.0/packages/cadpy/src/cadpy/__init__.py +34 -0
  14. dcad-0.1.0/packages/cadpy/src/cadpy/analysis.py +683 -0
  15. dcad-0.1.0/packages/cadpy/src/cadpy/api.py +6 -0
  16. dcad-0.1.0/packages/cadpy/src/cadpy/assembly.py +436 -0
  17. dcad-0.1.0/packages/cadpy/src/cadpy/assembly_composition.py +1269 -0
  18. dcad-0.1.0/packages/cadpy/src/cadpy/assembly_export.py +974 -0
  19. dcad-0.1.0/packages/cadpy/src/cadpy/assembly_flatten.py +249 -0
  20. dcad-0.1.0/packages/cadpy/src/cadpy/assembly_spec.py +458 -0
  21. dcad-0.1.0/packages/cadpy/src/cadpy/cad_ref_syntax.py +141 -0
  22. dcad-0.1.0/packages/cadpy/src/cadpy/catalog.py +570 -0
  23. dcad-0.1.0/packages/cadpy/src/cadpy/cli_logging.py +58 -0
  24. dcad-0.1.0/packages/cadpy/src/cadpy/file_metadata.py +61 -0
  25. dcad-0.1.0/packages/cadpy/src/cadpy/generation.py +2351 -0
  26. dcad-0.1.0/packages/cadpy/src/cadpy/generation_status.py +179 -0
  27. dcad-0.1.0/packages/cadpy/src/cadpy/glb.py +1137 -0
  28. dcad-0.1.0/packages/cadpy/src/cadpy/glb_mesh_payload.py +431 -0
  29. dcad-0.1.0/packages/cadpy/src/cadpy/glb_topology.py +499 -0
  30. dcad-0.1.0/packages/cadpy/src/cadpy/lookup.py +243 -0
  31. dcad-0.1.0/packages/cadpy/src/cadpy/metadata.py +513 -0
  32. dcad-0.1.0/packages/cadpy/src/cadpy/py.typed +1 -0
  33. dcad-0.1.0/packages/cadpy/src/cadpy/render.py +97 -0
  34. dcad-0.1.0/packages/cadpy/src/cadpy/reporting.py +133 -0
  35. dcad-0.1.0/packages/cadpy/src/cadpy/selector_types.py +18 -0
  36. dcad-0.1.0/packages/cadpy/src/cadpy/source_hash.py +62 -0
  37. dcad-0.1.0/packages/cadpy/src/cadpy/step_artifact.py +367 -0
  38. dcad-0.1.0/packages/cadpy/src/cadpy/step_artifacts.py +245 -0
  39. dcad-0.1.0/packages/cadpy/src/cadpy/step_export.py +386 -0
  40. dcad-0.1.0/packages/cadpy/src/cadpy/step_hash.py +12 -0
  41. dcad-0.1.0/packages/cadpy/src/cadpy/step_metadata.py +321 -0
  42. dcad-0.1.0/packages/cadpy/src/cadpy/step_scene.py +2626 -0
  43. dcad-0.1.0/packages/cadpy/src/cadpy/step_targets.py +483 -0
  44. dcad-0.1.0/packages/cadpy/src/cadpy/stl.py +33 -0
  45. dcad-0.1.0/packages/cadpy/src/cadpy/threemf.py +565 -0
  46. dcad-0.1.0/packages/cadpy/src/cadpy/validators.py +119 -0
  47. dcad-0.1.0/pyproject.toml +86 -0
  48. dcad-0.1.0/scripts/publish.sh +23 -0
  49. dcad-0.1.0/scripts/setup-dev.sh +20 -0
  50. dcad-0.1.0/scripts/test-install.sh +33 -0
  51. dcad-0.1.0/skills/cad/LICENSE +21 -0
  52. dcad-0.1.0/skills/cad/SKILL.md +102 -0
  53. dcad-0.1.0/skills/cad/UPSTREAM_SHA +1 -0
  54. dcad-0.1.0/skills/cad/agents/openai.yaml +4 -0
  55. dcad-0.1.0/skills/cad/references/build123d-modeling.md +155 -0
  56. dcad-0.1.0/skills/cad/references/cad-brief.md +130 -0
  57. dcad-0.1.0/skills/cad/references/inspection-and-validation.md +143 -0
  58. dcad-0.1.0/skills/cad/references/parameters.md +138 -0
  59. dcad-0.1.0/skills/cad/references/positioning.md +260 -0
  60. dcad-0.1.0/skills/cad/references/repair-loop.md +169 -0
  61. dcad-0.1.0/skills/cad/references/snapshot-review.md +84 -0
  62. dcad-0.1.0/skills/cad/references/step-generation.md +59 -0
  63. dcad-0.1.0/skills/cad/references/supported-exports.md +75 -0
  64. dcad-0.1.0/skills/cad/requirements.txt +2 -0
  65. dcad-0.1.0/skills/cad/scripts/inspect/__main__.py +15 -0
  66. dcad-0.1.0/skills/cad/scripts/inspect/cli.py +15 -0
  67. dcad-0.1.0/skills/cad/scripts/inspect/inspect_refs/__init__.py +1 -0
  68. dcad-0.1.0/skills/cad/scripts/inspect/inspect_refs/cli.py +641 -0
  69. dcad-0.1.0/skills/cad/scripts/inspect/inspect_refs/inspect.py +988 -0
  70. dcad-0.1.0/skills/cad/scripts/snapshot/__init__.py +1 -0
  71. dcad-0.1.0/skills/cad/scripts/snapshot/__main__.py +1242 -0
  72. dcad-0.1.0/skills/cad/scripts/snapshot/runtime/render.html +20 -0
  73. dcad-0.1.0/skills/cad/scripts/snapshot/runtime/snapshot-render.js +4168 -0
  74. dcad-0.1.0/skills/cad/scripts/step/__init__.py +1 -0
  75. dcad-0.1.0/skills/cad/scripts/step/__main__.py +16 -0
  76. dcad-0.1.0/skills/cad/scripts/step/cli.py +137 -0
  77. dcad-0.1.0/skills/step-parts/LICENSE +21 -0
  78. dcad-0.1.0/skills/step-parts/SKILL.md +70 -0
  79. dcad-0.1.0/skills/step-parts/agents/openai.yaml +4 -0
  80. dcad-0.1.0/skills/step-parts/references/step-parts-api.md +74 -0
  81. dcad-0.1.0/skills/step-parts/scripts/download_step_part.py +208 -0
  82. dcad-0.1.0/src/derive_cad/__about__.py +1 -0
  83. dcad-0.1.0/src/derive_cad/__init__.py +3 -0
  84. dcad-0.1.0/src/derive_cad/cad/__init__.py +0 -0
  85. dcad-0.1.0/src/derive_cad/cad/inspect.py +202 -0
  86. dcad-0.1.0/src/derive_cad/cad/render.py +112 -0
  87. dcad-0.1.0/src/derive_cad/cad/runner.py +139 -0
  88. dcad-0.1.0/src/derive_cad/cad/sandbox.py +61 -0
  89. dcad-0.1.0/src/derive_cad/cad/script_safety.py +49 -0
  90. dcad-0.1.0/src/derive_cad/cad/validation.py +174 -0
  91. dcad-0.1.0/src/derive_cad/cli/__init__.py +0 -0
  92. dcad-0.1.0/src/derive_cad/cli/app.py +63 -0
  93. dcad-0.1.0/src/derive_cad/cli/commands_cmd.py +127 -0
  94. dcad-0.1.0/src/derive_cad/cli/init_cmd.py +7 -0
  95. dcad-0.1.0/src/derive_cad/cli/inspect_cmd.py +11 -0
  96. dcad-0.1.0/src/derive_cad/cli/open_cmd.py +76 -0
  97. dcad-0.1.0/src/derive_cad/cli/passthrough.py +44 -0
  98. dcad-0.1.0/src/derive_cad/cli/run_cmd.py +154 -0
  99. dcad-0.1.0/src/derive_cad/cli/setup.py +190 -0
  100. dcad-0.1.0/src/derive_cad/cli/snapshot_cmd.py +12 -0
  101. dcad-0.1.0/src/derive_cad/cli/step_cmd.py +12 -0
  102. dcad-0.1.0/src/derive_cad/config/__init__.py +0 -0
  103. dcad-0.1.0/src/derive_cad/config/models.py +47 -0
  104. dcad-0.1.0/src/derive_cad/config/paths.py +36 -0
  105. dcad-0.1.0/src/derive_cad/config/secrets.py +79 -0
  106. dcad-0.1.0/src/derive_cad/config/store.py +43 -0
  107. dcad-0.1.0/src/derive_cad/config/toml_io.py +18 -0
  108. dcad-0.1.0/src/derive_cad/llm/__init__.py +0 -0
  109. dcad-0.1.0/src/derive_cad/llm/brief.py +162 -0
  110. dcad-0.1.0/src/derive_cad/llm/client.py +127 -0
  111. dcad-0.1.0/src/derive_cad/llm/generate.py +285 -0
  112. dcad-0.1.0/src/derive_cad/llm/naming.py +45 -0
  113. dcad-0.1.0/src/derive_cad/llm/prompts.py +208 -0
  114. dcad-0.1.0/src/derive_cad/llm/providers.py +93 -0
  115. dcad-0.1.0/src/derive_cad/llm/repair_loop.py +358 -0
  116. dcad-0.1.0/src/derive_cad/llm/review.py +71 -0
  117. dcad-0.1.0/src/derive_cad/llm/step_parts.py +94 -0
  118. dcad-0.1.0/src/derive_cad/project/__init__.py +0 -0
  119. dcad-0.1.0/src/derive_cad/project/workspace.py +77 -0
  120. dcad-0.1.0/src/derive_cad/skill/__init__.py +11 -0
  121. dcad-0.1.0/src/derive_cad/skill/paths.py +45 -0
  122. dcad-0.1.0/src/derive_cad/skill/runner.py +61 -0
  123. dcad-0.1.0/src/derive_cad/utils/__init__.py +0 -0
  124. dcad-0.1.0/src/derive_cad/utils/errors.py +19 -0
  125. dcad-0.1.0/src/derive_cad/utils/logging.py +114 -0
  126. dcad-0.1.0/tests/cad_scripts.py +23 -0
  127. dcad-0.1.0/tests/conftest.py +8 -0
  128. dcad-0.1.0/tests/test_brief.py +165 -0
  129. dcad-0.1.0/tests/test_cad_runner.py +44 -0
  130. dcad-0.1.0/tests/test_commands_cmd.py +39 -0
  131. dcad-0.1.0/tests/test_config.py +62 -0
  132. dcad-0.1.0/tests/test_export.py +43 -0
  133. dcad-0.1.0/tests/test_generate.py +320 -0
  134. dcad-0.1.0/tests/test_naming.py +32 -0
  135. dcad-0.1.0/tests/test_prompts.py +35 -0
  136. dcad-0.1.0/tests/test_render.py +28 -0
  137. dcad-0.1.0/tests/test_repair.py +27 -0
  138. dcad-0.1.0/tests/test_repair_orchestrator.py +131 -0
  139. dcad-0.1.0/tests/test_review.py +71 -0
  140. dcad-0.1.0/tests/test_script_safety.py +60 -0
  141. dcad-0.1.0/tests/test_secrets.py +69 -0
  142. dcad-0.1.0/tests/test_setup.py +27 -0
  143. dcad-0.1.0/tests/test_skill_paths.py +12 -0
  144. dcad-0.1.0/tests/test_step_parts.py +32 -0
  145. dcad-0.1.0/tests/test_validation.py +74 -0
  146. dcad-0.1.0/tests/test_workspace.py +59 -0
@@ -0,0 +1,51 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ lint-and-test:
10
+ runs-on: ${{ matrix.os }}
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest]
15
+ python-version: ["3.12"]
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Prepare vendored CAD skill
20
+ run: bash scripts/setup-dev.sh
21
+
22
+ - uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install package with dev dependencies
27
+ run: pip install -e ".[dev]"
28
+
29
+ - name: Lint
30
+ run: ruff check .
31
+
32
+ - name: Test
33
+ run: pytest -q
34
+
35
+ package:
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - uses: actions/checkout@v4
39
+
40
+ - name: Prepare vendored CAD skill
41
+ run: bash scripts/setup-dev.sh
42
+
43
+ - uses: actions/setup-python@v5
44
+ with:
45
+ python-version: "3.12"
46
+
47
+ - name: Build wheel
48
+ run: pip install build && python -m build
49
+
50
+ - name: Smoke-test wheel install
51
+ run: bash scripts/test-install.sh dist/dcad-*.whl
@@ -0,0 +1,38 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ push:
7
+ tags:
8
+ - "v*"
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ pypi:
16
+ runs-on: ubuntu-latest
17
+ environment: PYPI_API_TOKEN
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - uses: actions/setup-python@v5
22
+ with:
23
+ python-version: "3.12"
24
+
25
+ - name: Prepare vendored CAD skill
26
+ run: bash scripts/setup-dev.sh
27
+
28
+ - name: Build package
29
+ run: pip install build && python -m build
30
+
31
+ - name: Smoke-test wheel install
32
+ run: bash scripts/test-install.sh dist/dcad-*.whl
33
+
34
+ - name: Publish to PyPI
35
+ uses: pypa/gh-action-pypi-publish@release/v1
36
+ with:
37
+ user: __token__
38
+ password: ${{ secrets.PYPI_API_TOKEN }}
dcad-0.1.0/.gitignore ADDED
@@ -0,0 +1,43 @@
1
+ # Byte-compiled / cache
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ *.egg-info/
8
+ dist/
9
+ build/
10
+ .eggs/
11
+
12
+ # Virtual environments
13
+ .venv/
14
+ .venv-ci/
15
+ venv/
16
+ env/
17
+
18
+ # Test / lint / type-check caches
19
+ .pytest_cache/
20
+ .mypy_cache/
21
+ .ruff_cache/
22
+ .coverage
23
+ htmlcov/
24
+
25
+ # Editors / OS
26
+ .DS_Store
27
+ .idea/
28
+ .vscode/
29
+
30
+ # Local runtime artifacts — never commit generated CAD output or user config
31
+ validation-snapshots/
32
+ *.step
33
+ *.stl
34
+ *.3mf
35
+ *.glb
36
+ *.gltf
37
+ .runs/
38
+ .derivecad.toml
39
+ credentials.toml
40
+
41
+ # Deliberate exception: small tracked fixture files
42
+ !tests/fixtures/*.step
43
+ !tests/fixtures/*.stl
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ - PyPI distribution renamed to `dcad` — install with `pipx install dcad`.
6
+ - Milestone 1: CLI scaffold, layered config, keyring-backed secrets with file fallback,
7
+ `dcad init` setup wizard, sandboxed build123d subprocess execution, STEP/STL/3MF/GLB
8
+ export, deterministic geometry inspection, and `dcad run` wiring the fixed demo
9
+ bracket pipeline end-to-end. CI (lint + test) on macOS/Ubuntu.
@@ -0,0 +1,138 @@
1
+ # Contributing to dcad
2
+
3
+ ## Releasing
4
+
5
+ The PyPI package name is **`dcad`** (users install with `pipx install dcad`).
6
+
7
+ 1. Bump `version` in `pyproject.toml` and `src/derive_cad/__about__.py`.
8
+ 2. Update `CHANGELOG.md`.
9
+ 3. Create a GitHub release (tag = version, e.g. `v0.1.0`).
10
+ 4. The [Publish workflow](.github/workflows/publish.yml) uploads the wheel to PyPI when the
11
+ release is published.
12
+
13
+ Set `PYPI_API_TOKEN` in the repo's `PYPI_API_TOKEN` GitHub environment before the first release.
14
+
15
+ To build and smoke-test locally:
16
+
17
+ ```bash
18
+ bash scripts/publish.sh
19
+ ```
20
+
21
+ To upload manually (requires `PYPI_API_TOKEN`):
22
+
23
+ ```bash
24
+ PYPI_API_TOKEN=... bash scripts/publish.sh --upload
25
+ ```
26
+
27
+ ## Dev setup
28
+
29
+ ```bash
30
+ python3 -m venv .venv
31
+ source .venv/bin/activate
32
+ pip install -e ".[dev]"
33
+ ```
34
+
35
+ `dcad` bundles the vendored `packages/cadpy` and `skills/cad` inside the wheel — one install
36
+ command is enough.
37
+
38
+ Run lint and tests before opening a PR:
39
+
40
+ ```bash
41
+ ruff check .
42
+ pytest -q
43
+ ```
44
+
45
+ `pytest` includes a marked `integration` suite (`tests/test_cad_runner.py`,
46
+ `tests/test_export.py`, `tests/test_render.py`) that runs the real build123d subprocess
47
+ sandbox (and, for `test_render.py`, a real Playwright snapshot render) end-to-end. These are slower
48
+ than the unit tests but are the ones that actually prove the CAD pipeline works — don't skip
49
+ them locally before submitting a PR that touches `cad/`.
50
+
51
+ For a PR that changes prompts (`llm/prompts.py`), upstream repair guidance
52
+ (`skills/cad/references/repair-loop.md`), or the
53
+ brief's validation-target schema (`llm/brief.py`, `cad/validation.py`), also run
54
+ `python benchmarks/run_benchmarks.py` against a real configured provider — see
55
+ `benchmarks/cases.py` and the "What we ported" section below.
56
+
57
+ ## Platform caveats worth knowing before touching `cad/sandbox.py`
58
+
59
+ - **No musllinux/Alpine wheels** for build123d's OCP binding — anything Docker-based needs a
60
+ glibc base image (`python:3.12-slim`, not `-alpine`).
61
+ - **Windows has no `resource` module** — the POSIX memory/CPU resource limits in
62
+ `cad/sandbox.py` are a documented gap on Windows, not silently ignored. The subprocess
63
+ timeout is the cross-platform backstop against runaway generation scripts.
64
+ - **macOS's `RLIMIT_AS` frequently can't be lowered** below the process's already-mapped
65
+ virtual address space (dyld's shared cache alone can reserve several GB), so the memory
66
+ limit in `cad/sandbox.py` is applied best-effort and never blocks launching the subprocess
67
+ if `setrlimit` fails.
68
+
69
+ ## Secrets
70
+
71
+ This project handles real API keys. Never commit real keys, `credentials.toml`, or any
72
+ fixture containing a live secret. Tests exercise the secrets layer against fake/mocked
73
+ keyring backends (see `tests/test_secrets.py`) — no real OS keychain is touched in CI.
74
+
75
+ ## Adding a new LLM provider
76
+
77
+ Add an entry to `PROVIDERS` in `src/derive_cad/llm/providers.py` with its env var name and a
78
+ sensible default model string. Users can already reach any litellm-supported provider via the
79
+ "Other" option in `dcad init`, so a first-class entry here is about a smoother onboarding
80
+ experience, not enabling something otherwise impossible.
81
+
82
+ ## Adding a new export format
83
+
84
+ Register the format in `src/derive_cad/cad/runner.py` (`_SIDECAR_FLAGS`) if
85
+ `skills/cad/scripts/step` supports a matching `--<format>` sidecar flag. Exports run through
86
+ cadpy during `dcad run` via `export_sidecars()` or inline `run_script(..., sidecar_formats=...)`.
87
+
88
+ ## Vendored `skills/cad` and `packages/cadpy`
89
+
90
+ This repo vendors the full upstream CAD skill from
91
+ [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad):
92
+
93
+ - `skills/cad/` — `SKILL.md`, `references/*.md`, `scripts/step`, `scripts/inspect`, `scripts/snapshot`
94
+ - `packages/cadpy/` — STEP generation, selector inspection, assemblies
95
+ - `skills/cad/scripts/packages/cadpy` → `../../../../packages/cadpy` (symlink)
96
+
97
+ Pinned upstream commit: `skills/cad/UPSTREAM_SHA`.
98
+
99
+ `dcad run` orchestrates the SKILL.md 10-step workflow. Low-level tools are exposed as
100
+ `dcad step`, `dcad inspect`, and `dcad snapshot` (passthrough to vendored scripts).
101
+
102
+ Sync from upstream when needed:
103
+
104
+ ```bash
105
+ git clone https://github.com/earthtojake/text-to-cad.git /tmp/text-to-cad-upstream
106
+ cp -R /tmp/text-to-cad-upstream/skills/cad ./skills/cad
107
+ cp -R /tmp/text-to-cad-upstream/packages/cadpy ./packages/cadpy
108
+ ln -sf ../../../../packages/cadpy skills/cad/scripts/packages/cadpy
109
+ ```
110
+
111
+ ## What we ported from earthtojake/text-to-cad's skill docs
112
+
113
+ That project's `skills/cad/SKILL.md` and `references/*.md` document a staged workflow:
114
+ classify the task, write a CAD brief before coding, generate via `scripts/step`, validate
115
+ with `scripts/inspect`, review snapshots, and repair failures per `repair-loop.md`.
116
+ `llm/brief.py`, `cad/validation.py`, `cad/render.py`, and `llm/review.py` implement this
117
+ against dcad's litellm-based CLI; repair prompts load the vendored `repair-loop.md` directly.
118
+
119
+ **Not vendored:** `viewer/`, `skills/cad-viewer` (no embedded CAD Viewer UI). `dcad run`
120
+ uses Playwright snapshots via `skills/cad/scripts/snapshot` for vision review; `dcad open` opens files in the OS default app.
121
+
122
+ **Stretch / optional:** `skills/step-parts` purchasable-parts library (`llm/step_parts.py`
123
+ logs when absent). Assembly codegen and repair prompts load `references/positioning.md`
124
+ when the CAD brief `Task type` indicates an assembly, matching the upstream SKILL.md
125
+ reference triggers.
126
+
127
+ Two additional, smaller pieces were added alongside the port, in response to review of an
128
+ earlier scaffold plan for this repo:
129
+
130
+ - `cad/script_safety.py` — an AST-based import allowlist for LLM-generated scripts, run
131
+ before the sandbox ever executes them. It only catches plain `import`/`from` statements,
132
+ not `__import__()`/`importlib`/`eval`/`exec` obfuscation — layered defense on top of the
133
+ subprocess sandbox in `cad/sandbox.py`, not a replacement for it.
134
+ - `benchmarks/run_benchmarks.py` — ~8 benchmark prompts (`benchmarks/cases.py`) with
135
+ hand-picked expected validation targets, mirroring earthtojake's 10 benchmark prompts.
136
+ Run this against a real configured provider before changing prompts, repair guidance, or
137
+ the validation-target schema. Deliberately **not** part of `pytest -q` or CI: it makes
138
+ real API calls and real LLM output is non-deterministic.
dcad-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HumfDev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
dcad-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,183 @@
1
+ Metadata-Version: 2.4
2
+ Name: dcad
3
+ Version: 0.1.0
4
+ Summary: Text to CAD from your terminal — generate real STEP/STL/3MF/GLB files from plain-language descriptions.
5
+ Project-URL: Homepage, https://github.com/HumfDev/derive-cad
6
+ Project-URL: Repository, https://github.com/HumfDev/derive-cad
7
+ Project-URL: Issues, https://github.com/HumfDev/derive-cad/issues
8
+ Author: HumfDev
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: 3d,build123d,cad,llm,text-to-cad
12
+ Classifier: Environment :: Console
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
15
+ Requires-Python: <3.15,>=3.11
16
+ Requires-Dist: build123d<0.12,>=0.11.1
17
+ Requires-Dist: keyring<26,>=25.6
18
+ Requires-Dist: litellm<2,>=1.83
19
+ Requires-Dist: playwright<2,>=1.49
20
+ Requires-Dist: pydantic<3,>=2.9
21
+ Requires-Dist: questionary<3,>=2.1
22
+ Requires-Dist: rich<16,>=15.0
23
+ Requires-Dist: tomli-w<2,>=1.0
24
+ Requires-Dist: typer<0.27,>=0.26
25
+ Provides-Extra: dev
26
+ Requires-Dist: mypy; extra == 'dev'
27
+ Requires-Dist: pytest-cov; extra == 'dev'
28
+ Requires-Dist: pytest<10,>=9.1; extra == 'dev'
29
+ Requires-Dist: ruff<0.16,>=0.15; extra == 'dev'
30
+ Description-Content-Type: text/markdown
31
+
32
+ # dcad
33
+
34
+ Text to CAD from your terminal. Connect an LLM API key, pick a working folder, and describe
35
+ what you want to build — `dcad` generates real CAD files (STEP, STL, 3MF, GLB) on disk.
36
+
37
+ > **Status: Milestone 2.** `dcad run "your prompt"` sends your description to the
38
+ > configured LLM, which writes a build123d script, runs it through vendored cadpy
39
+ > (`skills/cad/scripts/step`), and retries on failure.
40
+
41
+ ## How it works
42
+
43
+ Before writing any code, the configured LLM produces a CAD brief (persisted as
44
+ `brief.md`) — dimensions, units, features, and a small set of machine-checkable
45
+ validation targets derived from your prompt. It then writes
46
+ [build123d](https://github.com/gumyr/build123d) — a Python parametric CAD library built
47
+ on the OpenCASCADE kernel — which is executed via cadpy to produce a STEP file and
48
+ optional sidecar exports (STL, 3MF, GLB).
49
+
50
+ The result is checked against the brief's validation targets (bounding box, face/solid
51
+ count). When enabled, a rendered snapshot (`snapshots/*.png`) is also reviewed by the
52
+ same LLM; that visual review is **advisory** — deterministic checks decide pass/fail,
53
+ and vision findings are logged without blocking acceptance when validation passes.
54
+ Deterministic failures are classified and repaired per the vendored
55
+ `skills/cad/references/repair-loop.md` — the LLM reads the failure output, classifies it,
56
+ and applies the smallest source fix before rerunning.
57
+
58
+ ## CAD tools (upstream-shaped CLI)
59
+
60
+ `dcad` mirrors the [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad) skill tool layout:
61
+
62
+ ```bash
63
+ dcad run "your prompt" # full SKILL.md workflow (primary UX)
64
+ dcad step model.py -o model.step --stl model.stl
65
+ dcad inspect refs model.step --facts --planes --positioning
66
+ dcad snapshot model.step # Playwright snapshots (requires `.model.step.glb` sidecar)
67
+ dcad open step|stl|recent # open artifacts with your OS default app
68
+ ```
69
+
70
+ The vendored skill lives at `skills/cad/` (see `skills/cad/UPSTREAM_SHA` for the pinned commit).
71
+
72
+ ## Install
73
+
74
+ ```bash
75
+ pipx install dcad
76
+ ```
77
+
78
+ Requires Python 3.11–3.14. [pipx](https://pipx.pypa.io/) keeps `dcad` and its dependencies
79
+ (including the OpenCASCADE binding) isolated from your other Python projects.
80
+
81
+ If `pipx` is not installed yet:
82
+
83
+ ```bash
84
+ brew install pipx
85
+ pipx ensurepath
86
+ ```
87
+
88
+ > **First release:** `dcad` is published to PyPI when a GitHub release is cut. Until then,
89
+ > install from a built wheel with `pipx install /path/to/dcad-*.whl` or follow the source
90
+ > setup below.
91
+
92
+ **From source** (contributors):
93
+
94
+ ```bash
95
+ git clone https://github.com/HumfDev/derive-cad.git
96
+ cd derive-cad
97
+ bash scripts/setup-dev.sh
98
+ python3 -m venv .venv && source .venv/bin/activate
99
+ pip install -e ".[dev]"
100
+ ```
101
+
102
+ Do **not** also run `pip install -e packages/cadpy` — `dcad` already pulls in the vendored
103
+ `cadpy` via `pyproject.toml`. Installing both in one command makes pip treat them as
104
+ conflicting requirements.
105
+
106
+ > **Note:** `dcad` vendors [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)'s
107
+ > `skills/cad/` workflow and `packages/cadpy`. STEP generation and inspection use
108
+ > `skills/cad/scripts/step` and `skills/cad/scripts/inspect`. OpenCASCADE comes via
109
+ > `cadquery-ocp` (~60MB per platform). **Alpine/musl Docker images are not supported**; use
110
+ > `python:3.12-slim` or similar glibc base images.
111
+
112
+ ## Quickstart
113
+
114
+ ```bash
115
+ dcad run "design a phone stand with 45 degree angle"
116
+ ```
117
+
118
+ On first use, `dcad run` launches an interactive setup wizard (LLM provider, model
119
+ dropdown, API key, working folder) and immediately generates your model. Reconfigure any
120
+ time with `dcad init`.
121
+
122
+ `dcad run` creates a named design folder directly in your working directory — for
123
+ example `~/derivecad-projects/phone-stand/model.stl`. The folder name is generated by your
124
+ configured LLM from your prompt (falls back to a slug if naming fails). Each design folder
125
+ contains `model.step`, your configured export formats (default: `model.stl`), the generated
126
+ Python source, `brief.md` (the CAD brief the model wrote before coding),
127
+ `snapshots/*.png` (the rendered views used for visual review), and stdout/stderr logs.
128
+ Open the latest outputs with:
129
+
130
+ ```bash
131
+ dcad open stl # open the most recent STL in your default viewer
132
+ dcad open step # open the most recent STEP file
133
+ dcad open recent # open the most recent run folder in Finder/Files
134
+ ```
135
+
136
+ Supported `open` targets: `step`, `stl`, `3mf`, `glb`, `py`, `recent`.
137
+
138
+ Browse and run any command interactively:
139
+
140
+ ```bash
141
+ dcad commands
142
+ ```
143
+
144
+ ## Supported LLM providers
145
+
146
+ | Provider | Env var | Notes |
147
+ |-----------|---------------------|---------------------------------|
148
+ | OpenAI | `OPENAI_API_KEY` | |
149
+ | Anthropic | `ANTHROPIC_API_KEY` | |
150
+ | Gemini | `GEMINI_API_KEY` | |
151
+ | Groq | `GROQ_API_KEY` | |
152
+ | Ollama | *(none)* | Local, no API key required. |
153
+ | Other | *(you choose)* | Any [litellm](https://github.com/BerriAI/litellm)-supported model string + env var. |
154
+
155
+ API keys are stored in your OS keychain via [`keyring`](https://github.com/jaraco/keyring).
156
+ If no OS keychain backend is available (common in CI/containers/headless Linux), `dcad
157
+ init` falls back to `~/.derivecad/credentials.toml` (mode 600) and warns you that this is
158
+ less secure. An already-set environment variable always takes precedence over stored config.
159
+
160
+ ## Supported output formats
161
+
162
+ STEP, STL, 3MF, GLB.
163
+
164
+ ## Configuration
165
+
166
+ - Global config: `~/.derivecad/config.toml`
167
+ - Per-project override: `.derivecad.toml` in your working folder
168
+ - Precedence: CLI flags > per-project config > env vars (API keys only) > global config > defaults
169
+ - `enable_snapshot_review` (default `true`): set to `false` to skip rendering and reviewing
170
+ a snapshot of each result — the release valve if the extra LLM call's cost/latency isn't
171
+ worth it for your use case. When enabled, vision findings are logged but do not block
172
+ acceptance if deterministic validation already passed. Vision review is also automatically
173
+ skipped (and reported as such) for models with no known vision support.
174
+ - `bbox_tolerance_pct` (default `15.0`): tolerance applied to a brief's bounding-box
175
+ validation targets before a mismatch is treated as a failure.
176
+
177
+ ## Contributing
178
+
179
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
180
+
181
+ ## License
182
+
183
+ MIT
dcad-0.1.0/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # dcad
2
+
3
+ Text to CAD from your terminal. Connect an LLM API key, pick a working folder, and describe
4
+ what you want to build — `dcad` generates real CAD files (STEP, STL, 3MF, GLB) on disk.
5
+
6
+ > **Status: Milestone 2.** `dcad run "your prompt"` sends your description to the
7
+ > configured LLM, which writes a build123d script, runs it through vendored cadpy
8
+ > (`skills/cad/scripts/step`), and retries on failure.
9
+
10
+ ## How it works
11
+
12
+ Before writing any code, the configured LLM produces a CAD brief (persisted as
13
+ `brief.md`) — dimensions, units, features, and a small set of machine-checkable
14
+ validation targets derived from your prompt. It then writes
15
+ [build123d](https://github.com/gumyr/build123d) — a Python parametric CAD library built
16
+ on the OpenCASCADE kernel — which is executed via cadpy to produce a STEP file and
17
+ optional sidecar exports (STL, 3MF, GLB).
18
+
19
+ The result is checked against the brief's validation targets (bounding box, face/solid
20
+ count). When enabled, a rendered snapshot (`snapshots/*.png`) is also reviewed by the
21
+ same LLM; that visual review is **advisory** — deterministic checks decide pass/fail,
22
+ and vision findings are logged without blocking acceptance when validation passes.
23
+ Deterministic failures are classified and repaired per the vendored
24
+ `skills/cad/references/repair-loop.md` — the LLM reads the failure output, classifies it,
25
+ and applies the smallest source fix before rerunning.
26
+
27
+ ## CAD tools (upstream-shaped CLI)
28
+
29
+ `dcad` mirrors the [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad) skill tool layout:
30
+
31
+ ```bash
32
+ dcad run "your prompt" # full SKILL.md workflow (primary UX)
33
+ dcad step model.py -o model.step --stl model.stl
34
+ dcad inspect refs model.step --facts --planes --positioning
35
+ dcad snapshot model.step # Playwright snapshots (requires `.model.step.glb` sidecar)
36
+ dcad open step|stl|recent # open artifacts with your OS default app
37
+ ```
38
+
39
+ The vendored skill lives at `skills/cad/` (see `skills/cad/UPSTREAM_SHA` for the pinned commit).
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ pipx install dcad
45
+ ```
46
+
47
+ Requires Python 3.11–3.14. [pipx](https://pipx.pypa.io/) keeps `dcad` and its dependencies
48
+ (including the OpenCASCADE binding) isolated from your other Python projects.
49
+
50
+ If `pipx` is not installed yet:
51
+
52
+ ```bash
53
+ brew install pipx
54
+ pipx ensurepath
55
+ ```
56
+
57
+ > **First release:** `dcad` is published to PyPI when a GitHub release is cut. Until then,
58
+ > install from a built wheel with `pipx install /path/to/dcad-*.whl` or follow the source
59
+ > setup below.
60
+
61
+ **From source** (contributors):
62
+
63
+ ```bash
64
+ git clone https://github.com/HumfDev/derive-cad.git
65
+ cd derive-cad
66
+ bash scripts/setup-dev.sh
67
+ python3 -m venv .venv && source .venv/bin/activate
68
+ pip install -e ".[dev]"
69
+ ```
70
+
71
+ Do **not** also run `pip install -e packages/cadpy` — `dcad` already pulls in the vendored
72
+ `cadpy` via `pyproject.toml`. Installing both in one command makes pip treat them as
73
+ conflicting requirements.
74
+
75
+ > **Note:** `dcad` vendors [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)'s
76
+ > `skills/cad/` workflow and `packages/cadpy`. STEP generation and inspection use
77
+ > `skills/cad/scripts/step` and `skills/cad/scripts/inspect`. OpenCASCADE comes via
78
+ > `cadquery-ocp` (~60MB per platform). **Alpine/musl Docker images are not supported**; use
79
+ > `python:3.12-slim` or similar glibc base images.
80
+
81
+ ## Quickstart
82
+
83
+ ```bash
84
+ dcad run "design a phone stand with 45 degree angle"
85
+ ```
86
+
87
+ On first use, `dcad run` launches an interactive setup wizard (LLM provider, model
88
+ dropdown, API key, working folder) and immediately generates your model. Reconfigure any
89
+ time with `dcad init`.
90
+
91
+ `dcad run` creates a named design folder directly in your working directory — for
92
+ example `~/derivecad-projects/phone-stand/model.stl`. The folder name is generated by your
93
+ configured LLM from your prompt (falls back to a slug if naming fails). Each design folder
94
+ contains `model.step`, your configured export formats (default: `model.stl`), the generated
95
+ Python source, `brief.md` (the CAD brief the model wrote before coding),
96
+ `snapshots/*.png` (the rendered views used for visual review), and stdout/stderr logs.
97
+ Open the latest outputs with:
98
+
99
+ ```bash
100
+ dcad open stl # open the most recent STL in your default viewer
101
+ dcad open step # open the most recent STEP file
102
+ dcad open recent # open the most recent run folder in Finder/Files
103
+ ```
104
+
105
+ Supported `open` targets: `step`, `stl`, `3mf`, `glb`, `py`, `recent`.
106
+
107
+ Browse and run any command interactively:
108
+
109
+ ```bash
110
+ dcad commands
111
+ ```
112
+
113
+ ## Supported LLM providers
114
+
115
+ | Provider | Env var | Notes |
116
+ |-----------|---------------------|---------------------------------|
117
+ | OpenAI | `OPENAI_API_KEY` | |
118
+ | Anthropic | `ANTHROPIC_API_KEY` | |
119
+ | Gemini | `GEMINI_API_KEY` | |
120
+ | Groq | `GROQ_API_KEY` | |
121
+ | Ollama | *(none)* | Local, no API key required. |
122
+ | Other | *(you choose)* | Any [litellm](https://github.com/BerriAI/litellm)-supported model string + env var. |
123
+
124
+ API keys are stored in your OS keychain via [`keyring`](https://github.com/jaraco/keyring).
125
+ If no OS keychain backend is available (common in CI/containers/headless Linux), `dcad
126
+ init` falls back to `~/.derivecad/credentials.toml` (mode 600) and warns you that this is
127
+ less secure. An already-set environment variable always takes precedence over stored config.
128
+
129
+ ## Supported output formats
130
+
131
+ STEP, STL, 3MF, GLB.
132
+
133
+ ## Configuration
134
+
135
+ - Global config: `~/.derivecad/config.toml`
136
+ - Per-project override: `.derivecad.toml` in your working folder
137
+ - Precedence: CLI flags > per-project config > env vars (API keys only) > global config > defaults
138
+ - `enable_snapshot_review` (default `true`): set to `false` to skip rendering and reviewing
139
+ a snapshot of each result — the release valve if the extra LLM call's cost/latency isn't
140
+ worth it for your use case. When enabled, vision findings are logged but do not block
141
+ acceptance if deterministic validation already passed. Vision review is also automatically
142
+ skipped (and reported as such) for models with no known vision support.
143
+ - `bbox_tolerance_pct` (default `15.0`): tolerance applied to a brief's bounding-box
144
+ validation targets before a mismatch is treated as a failure.
145
+
146
+ ## Contributing
147
+
148
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
149
+
150
+ ## License
151
+
152
+ MIT