dsh-cad 0.2.0

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 (113) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +190 -0
  3. package/README.zh-CN.md +173 -0
  4. package/cordis.patch.yml +3 -0
  5. package/lib/b64.js +12 -0
  6. package/lib/cad_connector/builtin-executor.js +55 -0
  7. package/lib/cad_connector/builtin.js +8 -0
  8. package/lib/cad_connector/executor.js +76 -0
  9. package/lib/cad_connector/freecad-executor.js +398 -0
  10. package/lib/cad_connector/freecad.js +8 -0
  11. package/lib/cad_connector/fusion360-executor.js +398 -0
  12. package/lib/cad_connector/fusion360.js +8 -0
  13. package/lib/cad_connector/gstarcad3d.js +8 -0
  14. package/lib/cad_connector/index.js +20 -0
  15. package/lib/cad_connector/onshape.js +8 -0
  16. package/lib/cad_connector/solidworks.js +8 -0
  17. package/lib/cad_connector/types.js +6 -0
  18. package/lib/cad_connector/zw3d.js +8 -0
  19. package/lib/client.js +4117 -0
  20. package/lib/client.js.map +7 -0
  21. package/lib/convert/dcprt.js +38 -0
  22. package/lib/convert/detect.js +22 -0
  23. package/lib/convert/dxf.js +124 -0
  24. package/lib/convert/index.js +70 -0
  25. package/lib/convert/obj.js +106 -0
  26. package/lib/convert/png.js +114 -0
  27. package/lib/convert/step-worker.mjs +61 -0
  28. package/lib/convert/step.js +66 -0
  29. package/lib/convert/stl.js +110 -0
  30. package/lib/convert/svg.js +101 -0
  31. package/lib/demo-bracket.brep +668 -0
  32. package/lib/demo-flange.brep +709 -0
  33. package/lib/demo-shaft.brep +516 -0
  34. package/lib/feature_script/dc_asm.js +17 -0
  35. package/lib/feature_script/dc_engineering.js +19 -0
  36. package/lib/feature_script/dc_prt.js +21 -0
  37. package/lib/feature_script/index.js +7 -0
  38. package/lib/image/profile.js +218 -0
  39. package/lib/index.js +77 -0
  40. package/lib/modeling/assembly.js +63 -0
  41. package/lib/modeling/bin-format.js +80 -0
  42. package/lib/modeling/bin-store.js +67 -0
  43. package/lib/modeling/client.js +117 -0
  44. package/lib/modeling/document.js +55 -0
  45. package/lib/modeling/drawing.js +324 -0
  46. package/lib/modeling/hlr.cjs +328 -0
  47. package/lib/modeling/modeling-worker.cjs +235 -0
  48. package/lib/modeling/occt-adapter.cjs +271 -0
  49. package/lib/routes.js +142 -0
  50. package/lib/store.js +68 -0
  51. package/lib/tools/cad-freecad.js +160 -0
  52. package/lib/tools/cad-fusion.js +138 -0
  53. package/lib/tools/cad-image.js +121 -0
  54. package/lib/tools/cad-info.js +92 -0
  55. package/lib/tools/cad-model.js +816 -0
  56. package/lib/tools/cad-view.js +112 -0
  57. package/lib/tools/util.js +25 -0
  58. package/lib/types/b64.d.ts +8 -0
  59. package/lib/types/cad/builtin.d.ts +3 -0
  60. package/lib/types/cad/freecad.d.ts +3 -0
  61. package/lib/types/cad/fusion360.d.ts +3 -0
  62. package/lib/types/cad/gstarcad3d.d.ts +3 -0
  63. package/lib/types/cad/index.d.ts +8 -0
  64. package/lib/types/cad/onshape.d.ts +3 -0
  65. package/lib/types/cad/solidworks.d.ts +3 -0
  66. package/lib/types/cad/types.d.ts +21 -0
  67. package/lib/types/cad/zw3d.d.ts +3 -0
  68. package/lib/types/cad_connector/builtin-executor.d.ts +9 -0
  69. package/lib/types/cad_connector/builtin.d.ts +3 -0
  70. package/lib/types/cad_connector/executor.d.ts +69 -0
  71. package/lib/types/cad_connector/freecad-executor.d.ts +55 -0
  72. package/lib/types/cad_connector/freecad.d.ts +3 -0
  73. package/lib/types/cad_connector/fusion360-executor.d.ts +11 -0
  74. package/lib/types/cad_connector/fusion360.d.ts +3 -0
  75. package/lib/types/cad_connector/gstarcad3d.d.ts +3 -0
  76. package/lib/types/cad_connector/index.d.ts +8 -0
  77. package/lib/types/cad_connector/onshape.d.ts +3 -0
  78. package/lib/types/cad_connector/solidworks.d.ts +3 -0
  79. package/lib/types/cad_connector/types.d.ts +21 -0
  80. package/lib/types/cad_connector/zw3d.d.ts +3 -0
  81. package/lib/types/convert/dcprt.d.ts +14 -0
  82. package/lib/types/convert/detect.d.ts +7 -0
  83. package/lib/types/convert/dxf.d.ts +3 -0
  84. package/lib/types/convert/index.d.ts +9 -0
  85. package/lib/types/convert/obj.d.ts +7 -0
  86. package/lib/types/convert/png.d.ts +8 -0
  87. package/lib/types/convert/step.d.ts +4 -0
  88. package/lib/types/convert/stl.d.ts +7 -0
  89. package/lib/types/convert/svg.d.ts +8 -0
  90. package/lib/types/feature_script/dc_asm.d.ts +40 -0
  91. package/lib/types/feature_script/dc_engineering.d.ts +55 -0
  92. package/lib/types/feature_script/dc_prt.d.ts +37 -0
  93. package/lib/types/feature_script/index.d.ts +7 -0
  94. package/lib/types/image/profile.d.ts +28 -0
  95. package/lib/types/index.d.ts +18 -0
  96. package/lib/types/modeling/assembly.d.ts +17 -0
  97. package/lib/types/modeling/bin-format.d.ts +42 -0
  98. package/lib/types/modeling/bin-store.d.ts +20 -0
  99. package/lib/types/modeling/client.d.ts +125 -0
  100. package/lib/types/modeling/document.d.ts +26 -0
  101. package/lib/types/modeling/drawing.d.ts +38 -0
  102. package/lib/types/routes.d.ts +27 -0
  103. package/lib/types/store.d.ts +18 -0
  104. package/lib/types/tools/cad-freecad.d.ts +10 -0
  105. package/lib/types/tools/cad-fusion.d.ts +8 -0
  106. package/lib/types/tools/cad-image.d.ts +8 -0
  107. package/lib/types/tools/cad-info.d.ts +6 -0
  108. package/lib/types/tools/cad-model.d.ts +13 -0
  109. package/lib/types/tools/cad-view.d.ts +10 -0
  110. package/lib/types/tools/util.d.ts +4 -0
  111. package/lib/types/types.d.ts +142 -0
  112. package/lib/types.js +25 -0
  113. package/package.json +91 -0
package/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # dsh-cad — CAD Plugin for DeepSeek Harness
2
+
3
+ ![dsh-cad banner](docs/img/banner.svg)
4
+
5
+ [![homepage](https://img.shields.io/badge/homepage-dsh--cad-4D6BFE)](https://lau-mars.github.io/dsh-cad/)
6
+ [![dsh plugin](https://img.shields.io/badge/dsh-plugin-4D6BFE)](https://github.com/deepseek-ai/deepseek-harness)
7
+ [![Node](https://img.shields.io/badge/node-%3E%3D%2022-4D6BFE)](https://nodejs.org/)
8
+ [![OCCT](https://img.shields.io/badge/kernel-OCCT-4D6BFE)](https://github.com/donalffons/opencascade.js)
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-4D6BFE)](./LICENSE)
10
+
11
+ English | [简体中文](./README.zh-CN.md)
12
+
13
+ A CAD plugin for [DeepSeek Harness (dsh)](https://github.com/deepseek-ai/deepseek-harness):
14
+ an **embedded 3D/2D CAD viewer** plus a **native parametric modeling tool family**
15
+ (OCCT kernel) in the Web UI, letting the agent build and inspect CAD geometry
16
+ step by step — "model while you watch".
17
+
18
+ ## Preview
19
+
20
+ The CAD editor at startup: the demo L-bracket parsed from the packaged
21
+ `demo-bracket.brep` by OCCT — face + edge rendering, hover measurement of the
22
+ picked face (4,800 mm²), a ViewCube navigation cube in the corner, and
23
+ switchable demo parts (bracket / flange / shaft):
24
+
25
+ ![dsh-cad CAD editor](docs/img/bracket-preview.png)
26
+
27
+ ## Feature Overview
28
+
29
+ | Capability | Description |
30
+ | --- | --- |
31
+ | 🔍 CAD viewing | STL / OBJ / STEP / IGES / BREP / DCPRT (3D), DXF / SVG (2D); interactive in-chat card (orbit / zoom / wireframe / pan) |
32
+ | 🧭 CAD editor interactions | Onshape-style ViewCube (26-zone click-to-orient), hover/click face & edge picking with live measurement (area mm² / length mm), Faces+Edges / Faces / Wireframe render modes, switchable BRep demo parts (bracket / flange / shaft) |
33
+ | 🏗️ Parametric modeling | Primitives (box/cylinder/sphere/cone/torus), profile extrusion, booleans (fuse/cut/common), all-edge fillet, transforms (translate/rotate/mirror) — exact OCCT BRep, not a mesh approximation |
34
+ | 🗂️ Codex-style document tabs | The resident display panel gets a tab strip with a "+" menu: **Part** (Part Studio, the default) / **Assembly** (instance insert/move/remove) / **Drawing** (true hidden-line sheets); tabs are closable and keep their state |
35
+ | 📐 Engineering drawings | GB first-angle layout: front / top / left views + isometric, mesh-projected hidden-line removal (dashed), sheet frame, title block, overall dimensions, standard scale series; exports SVG / DXF |
36
+ | 📐 Geometry measurement | Exact volume (mm³), bounding box, triangle counts, DXF layers |
37
+ | 📤 On-demand export | STEP (parametric) / STL (mesh); files are written only when the user asks |
38
+ | 🖥️ Resident CAD panel | A permanent panel right of the conversation: Codex-style tabs (Part / Assembly / Drawing), tracking the latest model in real time while modeling |
39
+ | ⚡ Zero-copy render pipeline | worker mesh → in-memory binary → three.js typed arrays; zero base64 / zero intermediate files / zero per-step disk writes |
40
+ | 💾 Modeling document persistence | Operation log (JSON) + debounced disk mirror; automatically replayed to restore state after a process restart |
41
+ | 🖼️ Image → profile | PNG sketch/screenshot → Otsu binarization → contour tracing → extrusion-ready polygon (`cad_image_profile`) |
42
+ | 🔌 FreeCAD executor | Run the same op family on an external FreeCAD console (STEP in/out); requires a local FreeCAD install |
43
+
44
+ ## Installation (dev mode)
45
+
46
+ ```sh
47
+ git clone https://github.com/LAU-MARS/dsh-cad.git
48
+ cd dsh-cad
49
+ npm install && npm run build && npm test
50
+
51
+ npm install -g @deepseek-ai/dsh@^0.1.1-rc.2 pnpm # requires Node ≥ 22
52
+ dsh web # let the first launch init the profile, then Ctrl-C
53
+
54
+ dsh plugin --profile web add /path/to/dsh-cad
55
+
56
+ # append to ~/.dsh/profiles/web/cordis.patch.yml:
57
+ # - insert:
58
+ # - id: dsh-cad
59
+ # name: 'dsh-cad'
60
+
61
+ dsh web
62
+ ```
63
+
64
+ ### Version requirements
65
+
66
+ - **Node.js** ≥ 22
67
+ - **dsh CLI** (`@deepseek-ai/dsh`): this plugin is developed against **0.1.0-rc.7**
68
+ (minimum supported version, declared in the `engines` field of `package.json`);
69
+ recommended **≥ 0.1.1-rc.2** (verified 2026-08-31)
70
+
71
+ Set `DEEPSEEK_API_KEY` and you are ready — for example:
72
+
73
+ - “open bracket.stl” → `cad_view`
74
+ - “model a 100×60×5 plate, punch a ⌀20 hole in the middle, R2 fillets on the four
75
+ corners, add a ⌀16 boss 20 tall, export plate.step”
76
+ → `cad_create_prim` + `cad_boolean` + `cad_fillet` + `cad_export`, with the 3D tab
77
+ updating live at every step
78
+ - “build a snowman” → spheres + a cone nose + a cylinder hat (precise `at`/`axis` placement)
79
+ - “add two more b1, one rotated 90 degrees” → `cad_assembly_insert` + `cad_assembly_move`, the Assembly tab updates live
80
+ - “make an A3 drawing of b1 and export dxf” → `cad_drawing` (three views + iso + dashed hidden lines + dimensions) → `cad_export` `.dxf`
81
+
82
+ ## Modeling Tool Family
83
+
84
+ | Tool | Description |
85
+ | --- | --- |
86
+ | `cad_view` | Open a CAD file and render an interactive viewer card |
87
+ | `cad_info` | Read-only geometry metadata (format / counts / bounding box / units / layers) |
88
+ | `cad_create_prim` | Primitives (mm, Z-up); `at` for placement, `axis` for orientation (exact axis-angle rotation) |
89
+ | `cad_extrude_profile` | Extrude a closed XY-plane polygon along +Z into a solid |
90
+ | `cad_boolean` | fuse / cut / common (classic hole punching: plate cut cylinder) |
91
+ | `cad_fillet` | Constant-radius fillet on all sharp edges |
92
+ | `cad_transform` | Translate / Euler rotate / mirror |
93
+ | `cad_volume` | Exact BRep volume (mm³) |
94
+ | `cad_drawing` | Engineering drawing: front/top/left + isometric views, dashed hidden lines, frame, title block, overall dimensions, standard scale, A4/A3 |
95
+ | `cad_assembly_insert` | Insert a body into the assembly as a placed instance (`at` position, `rotate` orientation) |
96
+ | `cad_assembly_move` | Set an instance's absolute placement |
97
+ | `cad_assembly_remove` | Remove an instance from the assembly (the body stays) |
98
+ | `cad_export` | Export STEP / STL / DCPRT (the native replayable part document) to a workspace path; `target: "assembly"` writes the assembly STEP, `target: "drawing"` writes the sheet as SVG / DXF |
99
+ | `cad_delete` | Delete a body |
100
+ | `cad_freecad` | Run an op program on an external FreeCAD executor (optional STEP input / export) |
101
+ | `cad_fusion` | Run an op program on an external Fusion 360 executor (GUI bridge; optional export) |
102
+ | `cad_image_profile` | PNG → contours → extrusion-ready polygon points |
103
+
104
+ After every modeling step: **the same viewer card refreshes in place** (stable viewId +
105
+ versioned URL), and the "3D" tab tracks the latest model in real time.
106
+
107
+ ## Connectors (roadmap)
108
+
109
+ Modeling today runs on the **built-in WebGL-class kernel** (OCCT in the browser —
110
+ zero install). The connectors below refer to **external CAD engines** acting as
111
+ executors for the same tool family, planned for future support:
112
+
113
+ | Connector | Suite | Platform | Status |
114
+ | --- | --- | --- | --- |
115
+ | **Built-in kernel** | CAD modeling kernel based on OCCT + WebGL, runs in the browser — zero install | All platforms (WebGL rendering) | ✅ Built-in |
116
+ | FreeCAD | open-source parametric suite — natural local executor via its Python API (console + GUI window modes) | Windows / macOS / Linux | ✅ Available (needs local install) |
117
+ | Fusion 360 | Autodesk CAD/CAM — resident add-in + spool bridge (no headless; the Fusion window doubles as a viewer) | Windows / macOS | 🧪 Experimental (`cad_fusion`) |
118
+ | SolidWorks | Dassault Systèmes industry-standard 3D CAD, COM/.NET automation | Windows only | 🚧 Windows demo scaffold (`scripts/solidworks-bridge/`) |
119
+ | Onshape | cloud-native SaaS CAD, fully in the browser | All platforms (browser) | 🚧 Planned |
120
+ | ZW3D(中望3D) | ZWSOFT all-in-one CAD/CAM | Windows / Linux | 🚧 Planned |
121
+ | GstarCAD 3D(浩辰3D) | Gstarsoft 3D CAD | Windows | 🚧 Planned |
122
+
123
+ All external engines implement the same **GeometryExecutor contract** (`available()` /
124
+ `run(opProgram) → meshes`), so the WebGL display layer never changes — swapping a
125
+ backend changes only the quality of the produced geometry.
126
+
127
+ ## Architecture
128
+
129
+ ```
130
+ cad_view(path) modeling tools (cad_create_prim, …)
131
+ → import worker (occt-import-js) → modeling worker (opencascade.js WASM)
132
+ → CadScene JSON (base64-f32) → exact BRep geometry + meshing
133
+ → GET /dsh-cad/scene/<id> → in-memory binary scene (f32/u32 packed)
134
+ → GET /dsh-cad/bin/<docId>
135
+ ↓ session presentationMeta (viewId + versioned URL) ↓
136
+ browser card + persistent "3D" tab (three.js / SVG, Z-up, XYZ axes)
137
+ ```
138
+
139
+ - **Two workers**: import (occt-import-js, read-only STEP/IGES/BREP) and modeling
140
+ (opencascade.js 1.1.1, full OCCT) are separate, both lazily started; the `_N`
141
+ suffix convention of embind overloaded constructors is wrapped in
142
+ `src/modeling/occt-adapter.cjs` (all verified at runtime)
143
+ - **Zero-copy pipeline**: modeling scenes use zero base64 / zero large JSON arrays /
144
+ zero per-step disk writes (disk mirror debounced 1.5s, replayed only on service
145
+ restart); `cad_export` is the only explicit file export
146
+ - **Modeling document**: `<workspace>/.dsh-cad/model.json` operation log; all bodies
147
+ are restored by replay after a restart
148
+ - **Client**: esbuild single-file CJS factory (three.js inlined ~560KB, react provided
149
+ by the host module table), Z-up CAD convention, empty scene with XYZ axis labels
150
+ and a ground grid always displayed
151
+
152
+ ## Tests
153
+
154
+ ```sh
155
+ npm test # 41 tests: converters / modeling worker (exact volume assertions) / DCPRT round-trip / FreeCAD executor / image profiles / binary pipeline
156
+ node test/m0-kernel-check.cjs # OCCT kernel API smoke test
157
+ node test/route-check.mjs # JSON scene routing layer
158
+ node test/visual/serve.mjs # browser card/tab visual verification page (http://127.0.0.1:3987)
159
+ ```
160
+
161
+ Representative assertions covered: the boolean-punched volume exactly equals the
162
+ analytic value (28429.20 mm³), L-shaped profile extrusion 3000 mm³, volumes and
163
+ bounding-box flips of sphere/cone/torus placed with `at`/`axis`, 8-byte alignment
164
+ of the binary packing, an STL export round-trip (export → read back by the
165
+ phase-1 parser), and a DCPRT document round-trip (serialize → replay on the
166
+ OCCT worker → exact bounds).
167
+
168
+ ## Known Limitations
169
+
170
+ - DWG (closed-source) is unsupported; DXF bulge arcs are approximated by chords;
171
+ glTF/3MF viewing is not implemented (the structure is reserved)
172
+ - `cad_fillet` is all-edge constant-radius (per-edge selection is unstable under
173
+ embind); chamfer is not implemented
174
+ - Sketch extrusion supports polygon profiles only (arc profiles are constructed by
175
+ boolean combinations of cylinders/tori)
176
+ - dsh framework limitation: an already-mounted single slot (the right-side details
177
+ panel itself) does not respond to components registered later, so the persistent
178
+ view is provided as the "3D" view tab (a list slot, the official composition)
179
+ - The host reads CAD files via node:fs (the platform fs service supports UTF-8 text
180
+ only and cannot carry binary data)
181
+
182
+ ## Contributors
183
+
184
+ Auto-generated from the commit history — thanks to everyone who has contributed!
185
+
186
+ [![Contributors](https://contrib.rocks/image?repo=LAU-MARS/dsh-cad)](https://github.com/LAU-MARS/dsh-cad/graphs/contributors)
187
+
188
+ ## License
189
+
190
+ MIT
@@ -0,0 +1,173 @@
1
+ # dsh-cad — CAD Plugin for DeepSeek Harness
2
+
3
+ ![dsh-cad banner](docs/img/banner.svg)
4
+
5
+ [![homepage](https://img.shields.io/badge/homepage-dsh--cad-4D6BFE)](https://lau-mars.github.io/dsh-cad/)
6
+ [![dsh plugin](https://img.shields.io/badge/dsh-plugin-4D6BFE)](https://github.com/deepseek-ai/deepseek-harness)
7
+ [![Node](https://img.shields.io/badge/node-%3E%3D%2022-4D6BFE)](https://nodejs.org/)
8
+ [![OCCT](https://img.shields.io/badge/kernel-OCCT-4D6BFE)](https://github.com/donalffons/opencascade.js)
9
+ [![License: MIT](https://img.shields.io/badge/license-MIT-4D6BFE)](./LICENSE)
10
+
11
+ [English](./README.md) | 简体中文
12
+
13
+ [DeepSeek Harness (dsh)](https://github.com/deepseek-ai/deepseek-harness) 的 CAD 插件:
14
+ 在 Web UI 中提供**内嵌 3D/2D CAD 查看器**与**原生参数化建模工具族**(OCCT 内核),
15
+ 让 agent 能够"边建边看"地完成 CAD 工作。
16
+
17
+ ## 预览
18
+
19
+ 启动即见的 CAD 编辑器:示例 L 型支架由内置的 `demo-bracket.brep` 经 OCCT
20
+ 解析渲染——面 + 边显示模式、悬停即测(拾取面 4,800 mm²)、角落 ViewCube
21
+ 导航块、支架 / 法兰 / 轴三种示例件一键切换:
22
+
23
+ ![dsh-cad CAD 编辑器](docs/img/bracket-preview.png)
24
+
25
+ ## 功能总览
26
+
27
+ | 能力 | 说明 |
28
+ | --- | --- |
29
+ | 🔍 CAD 查看 | STL / OBJ / STEP / IGES / BREP / DCPRT(3D),DXF / SVG(2D),对话内嵌交互卡片(轨道旋转 / 缩放 / 线框 / 平移) |
30
+ | 🧭 CAD 编辑器交互 | Onshape 风格 ViewCube(26 区域点击定向)、悬停/点选面与边实时测量(面积 mm² / 长度 mm)、面+边 / 面 / 线框三种渲染模式、支架 / 法兰 / 轴 BRep 示例件一键切换 |
31
+ | 🏗️ 参数化建模 | 基本体(box/cylinder/sphere/cone/torus)、轮廓拉伸、布尔(fuse/cut/common)、全边圆角、变换(平移/旋转/镜像)—— OCCT 精确 BRep,非网格近似 |
32
+ | 🗂️ Codex 式文档页签 | 右侧显示区页签栏 + 「+」菜单:**零件**(Part Studio,默认)/ **装配体**(实例插入/移动/移除)/ **工程图**(真实隐藏线图纸),页签可关闭、常驻不丢状态 |
33
+ | 📐 工程图 | GB 第一角布局:主视图 / 俯视图 / 左视图 + 轴测图,网格投影隐藏线消除(虚线)、图框、标题栏、总尺寸标注、标准比例系列;导出 SVG / DXF |
34
+ | 📐 几何测量 | 精确体积(mm³)、包围盒、三角统计、DXF 图层 |
35
+ | 📤 按需导出 | STEP(参数化)/ STL(网格),仅在用户要求时写文件 |
36
+ | 🖥️ 常驻 CAD 显示区 | 会话页右侧常驻面板:Codex 式页签(零件 / 装配体 / 工程图),建模时实时跟踪最新模型 |
37
+ | ⚡ 直通渲染管道 | worker 网格 → 内存二进制 → three.js typed-array,零 base64 / 零中间文件 / 零每步落盘 |
38
+ | 💾 建模文档持久化 | 操作日志(JSON)+ 防抖磁盘镜像,进程重启后自动重放恢复 |
39
+ | 🖼️ 图片 → 轮廓 | PNG 草图/截图 → Otsu 二值化 → 轮廓追踪 → 可直接拉伸的多边形(`cad_image_profile`) |
40
+ | 🔌 FreeCAD 执行器 | 在外部 FreeCAD 控制台运行同一 op 族(STEP 输入/输出闭环);需本地安装 |
41
+
42
+ ## 安装(开发模式)
43
+
44
+ ```sh
45
+ git clone https://github.com/LAU-MARS/dsh-cad.git
46
+ cd dsh-cad
47
+ npm install && npm run build && npm test
48
+
49
+ npm install -g @deepseek-ai/dsh@^0.1.1-rc.2 pnpm # 需要 Node ≥ 22
50
+ dsh web # 首次启动初始化 profile 后 Ctrl-C
51
+
52
+ dsh plugin --profile web add /path/to/dsh-cad
53
+
54
+ # ~/.dsh/profiles/web/cordis.patch.yml 追加:
55
+ # - insert:
56
+ # - id: dsh-cad
57
+ # name: 'dsh-cad'
58
+
59
+ dsh web
60
+ ```
61
+
62
+ ### 版本要求
63
+
64
+ - **Node.js** ≥ 22
65
+ - **dsh CLI**(`@deepseek-ai/dsh`):本项目开发基于 **0.1.0-rc.7**
66
+ (最低支持版本,已在 `package.json` 的 `engines` 字段声明);
67
+ 建议 **≥ 0.1.1-rc.2**(2026-08-31 实测通过)
68
+
69
+ 设置 `DEEPSEEK_API_KEY` 后对话即可使用,例如:
70
+
71
+ - “打开 bracket.stl 看看” → `cad_view`
72
+ - “画一个 100×60×5 的板,中间打 ⌀20 孔,四角 R2 圆角,加 ⌀16 高 20 凸台,导出 plate.step”
73
+ → `cad_create_prim` + `cad_boolean` + `cad_fillet` + `cad_export`,每步 3D 页签实时更新
74
+ - “堆一个雪人” → 球体 + 圆锥鼻子 + 圆柱帽子(`at`/`axis` 精确定位)
75
+ - “再放两个 b1,一个转到 90 度” → `cad_assembly_insert` + `cad_assembly_move`,装配体页签实时更新
76
+ - “给 b1 出一张 A3 工程图,导出 dxf” → `cad_drawing`(三视图 + 轴测 + 虚线隐藏线 + 尺寸标注)→ `cad_export` `.dxf`
77
+
78
+ ## 模型工具族
79
+
80
+ | 工具 | 说明 |
81
+ | --- | --- |
82
+ | `cad_view` | 打开 CAD 文件,渲染交互式查看器卡片 |
83
+ | `cad_info` | 只读几何元信息(格式/数量/包围盒/单位/图层) |
84
+ | `cad_create_prim` | 基本体(mm,Z-up),`at` 定位、`axis` 定向(精确轴角旋转) |
85
+ | `cad_extrude_profile` | XY 平面闭合多边形沿 +Z 拉伸成实体 |
86
+ | `cad_boolean` | fuse / cut / common(经典打孔:plate cut cylinder) |
87
+ | `cad_fillet` | 全锐边等半径圆角 |
88
+ | `cad_transform` | 平移 / 欧拉旋转 / 镜像 |
89
+ | `cad_volume` | 精确 BRep 体积(mm³) |
90
+ | `cad_drawing` | 工程图:主/俯/左 + 轴测四视图,隐藏线(虚线)、图框、标题栏、总尺寸、标准比例,A4/A3 |
91
+ | `cad_assembly_insert` | 将零件以实例插入装配体(`at` 定位、`rotate` 定向) |
92
+ | `cad_assembly_move` | 设置实例绝对位置/姿态 |
93
+ | `cad_assembly_remove` | 从装配体移除实例(零件保留) |
94
+ | `cad_export` | 导出 STEP / STL / DCPRT(原生可重放零件文档)到工作区路径;`target: "assembly"` 导出装配体 STEP,`target: "drawing"` 导出工程图 SVG / DXF |
95
+ | `cad_delete` | 删除 body |
96
+ | `cad_freecad` | 在外部 FreeCAD 执行器上运行 op 程序(可选 STEP 输入/导出) |
97
+ | `cad_fusion` | 在外部 Fusion 360 执行器上运行 op 程序(GUI 桥;可选导出) |
98
+ | `cad_image_profile` | PNG → 轮廓 → 可直接拉伸的多边形点集 |
99
+
100
+ 每步建模后:**同一查看器卡片原地刷新**(稳定 viewId + 版本化 URL),
101
+ "3D" 页签实时跟踪最新模型。
102
+
103
+ ## 连接器(规划中)
104
+
105
+ 建模目前已由**内置的 WebGL 级建模器**承担(浏览器内的 OCCT 内核,零安装);
106
+ 下表连接器指未来以**外部 CAD 引擎作为执行器**驱动同一工具族:
107
+
108
+ | 连接器 | 套件 | 平台 | 状态 |
109
+ | --- | --- | --- | --- |
110
+ | **内置内核** | 基于 OCCT + WebGL 的 CAD 建模内核,浏览器内运行——零安装 | 全平台(WebGL 渲染) | ✅ 内置 |
111
+ | FreeCAD | 开源参数化套件——可经其 Python API 作为本地执行器(控制台 + GUI 窗口双模式) | Windows / macOS / Linux | ✅ 可用(需本地安装) |
112
+ | Fusion 360 | Autodesk CAD/CAM——常驻 Add-In + spool 桥(无 headless,Fusion 窗口即查看器) | Windows / macOS | 🧪 实验性(`cad_fusion`) |
113
+ | SolidWorks | 达索系统的主流 3D CAD,COM/.NET 自动化 | 仅 Windows | 🚧 Windows demo 脚手架(`scripts/solidworks-bridge/`) |
114
+ | Onshape | 云原生 SaaS CAD,完全在浏览器中 | 全平台(浏览器) | 🚧 规划中 |
115
+ | 中望3D(ZW3D) | 中望软件的一体化 CAD/CAM | Windows / Linux | 🚧 规划中 |
116
+ | 浩辰3D | 浩辰软件的 3D CAD | Windows | 🚧 规划中 |
117
+
118
+ 所有外部引擎实现同一 **GeometryExecutor 契约**(`available()` / `run(op程序) → 网格`),
119
+ WebGL 显示层因此永不改变——更换后端只影响生成几何的质量。
120
+
121
+ ## 架构
122
+
123
+ ```
124
+ cad_view(path) 建模工具(cad_create_prim 等)
125
+ → 导入 worker(occt-import-js) → 建模 worker(opencascade.js WASM)
126
+ → CadScene JSON(base64-f32) → BRep 精确几何 + 网格化
127
+ → GET /dsh-cad/scene/<id> → 内存二进制场景(f32/u32 打包)
128
+ → GET /dsh-cad/bin/<docId>
129
+ ↓ 会话 presentationMeta(viewId + 版本化 URL)↓
130
+ 浏览器卡片 + 常驻 "3D" 页签(three.js / SVG,Z-up,XYZ 轴)
131
+ ```
132
+
133
+ - **两个 worker**:导入(occt-import-js,只读 STEP/IGES/BREP)与建模(opencascade.js 1.1.1,
134
+ 完整 OCCT)分离,均惰性启动;embind 重载构造器的 `_N` 后缀约定封装在
135
+ `src/modeling/occt-adapter.cjs`(全部经运行时实证)
136
+ - **直通管道**:建模场景零 base64 / 零 JSON 大数组 / 零每步落盘(磁盘镜像 1.5s 防抖,
137
+ 仅服务重启回放);`cad_export` 是唯一的显式文件导出
138
+ - **建模文档**:`<workspace>/.dsh-cad/model.json` 操作日志,重启后重放恢复全部 body
139
+ - **客户端**:esbuild 单文件 CJS 工厂(three.js 内联 ~560KB,react 由宿主模块表提供),
140
+ Z-up CAD 惯例,带 XYZ 轴标签与地面网格的空场景常驻显示
141
+
142
+ ## 测试
143
+
144
+ ```sh
145
+ npm test # 41 项:转换器 / 建模 worker(体积精确断言)/ DCPRT 往返 / FreeCAD 执行器 / 图片轮廓 / 二进制管道 / 文档持久化
146
+ node test/m0-kernel-check.cjs # OCCT 内核 API 冒烟
147
+ node test/route-check.mjs # JSON 场景路由层
148
+ node test/visual/serve.mjs # 浏览器卡片/页签视觉验证页(http://127.0.0.1:3987)
149
+ ```
150
+
151
+ 覆盖的代表性断言:布尔打孔体积精确等于解析值(28429.20 mm³)、L 型轮廓拉伸
152
+ 3000 mm³、球/锥/环带 `at`/`axis` 定位的体积与包围盒翻转、二进制打包 8 字节对齐、
153
+ STL 导出往返(导出 → 一期解析器读回),以及 DCPRT 文档往返
154
+ (序列化 → OCCT worker 重放 → 精确包围盒)。
155
+
156
+ ## 已知限制
157
+
158
+ - DWG(闭源)不支持;DXF bulge 弧以弦线近似;glTF/3MF 查看未实现(结构已预留)
159
+ - `cad_fillet` 为全边等半径(embind 下按边选择不稳定);chamfer 未实现
160
+ - 草图拉伸仅支持多边形轮廓(圆弧轮廓用布尔组合圆柱/圆环构造)
161
+ - dsh 框架限制:已挂载的 single 槽(右侧 details 面板本体)不响应后注册组件,
162
+ 故常驻显示区以 "3D" 视图页签提供(list 槽,官方组合方式)
163
+ - 宿主读取 CAD 文件使用 node:fs(平台 fs 服务仅支持 UTF-8 文本,无法承载二进制)
164
+
165
+ ## 贡献者
166
+
167
+ 由提交历史自动生成,感谢每一位贡献者!
168
+
169
+ [![Contributors](https://contrib.rocks/image?repo=LAU-MARS/dsh-cad)](https://github.com/LAU-MARS/dsh-cad/graphs/contributors)
170
+
171
+ ## License
172
+
173
+ MIT
@@ -0,0 +1,3 @@
1
+ - insert:
2
+ - id: dsh-cad
3
+ name: 'dsh-cad'
package/lib/b64.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Base64 codecs for typed arrays. Node (host) encodes; the browser card
3
+ * decodes. Kept dependency-free on both sides.
4
+ */
5
+ /** Encode a Float32Array's buffer as base64 (Node, host side). */
6
+ export function encodeF32B64(array) {
7
+ return Buffer.from(array.buffer, array.byteOffset, array.byteLength).toString('base64');
8
+ }
9
+ /** Encode a Uint32Array's buffer as base64 (Node, host side). */
10
+ export function encodeU32B64(array) {
11
+ return Buffer.from(array.buffer, array.byteOffset, array.byteLength).toString('base64');
12
+ }
@@ -0,0 +1,55 @@
1
+ import { createModelClient } from '../modeling/client.js';
2
+ function workerMeshToExecutorMesh(mesh) {
3
+ return {
4
+ bodyId: mesh.bodyId ?? mesh.name,
5
+ name: mesh.name,
6
+ positions: mesh.positions,
7
+ normals: mesh.normals,
8
+ indices: mesh.indices,
9
+ vertexCount: mesh.vertexCount,
10
+ triangleCount: mesh.triangleCount,
11
+ };
12
+ }
13
+ /** The shared WASM kernel always exists in this build. */
14
+ export const BUILTIN_EXECUTOR = {
15
+ id: 'builtin',
16
+ label: 'Built-in OCCT kernel',
17
+ available: () => true,
18
+ run(program) {
19
+ return runOnIsolatedWorker(program);
20
+ },
21
+ };
22
+ async function runOnIsolatedWorker(program) {
23
+ const client = createModelClient();
24
+ try {
25
+ if (program.input !== undefined) {
26
+ throw new Error('the built-in executor does not load input files (use the cad_view/cad_freecad paths)');
27
+ }
28
+ const volumes = {};
29
+ let exported;
30
+ await client.run({ kind: 'reset' });
31
+ for (const op of program.ops) {
32
+ const kind = String(op.kind);
33
+ if (kind === 'volume') {
34
+ const result = await client.run({ kind: 'volume', target: String(op.target) });
35
+ if (result.volume !== undefined)
36
+ volumes[String(op.target)] = result.volume;
37
+ }
38
+ else if (kind === 'export') {
39
+ const result = await client.run({ kind: 'export', target: String(op.target), format: (op.format ?? 'stl') });
40
+ // The worker writes into its WASM filesystem; the export path is
41
+ // surfaced by the cad_export tool path, not here.
42
+ exported = result.bytes !== undefined ? String(op.path ?? '') : undefined;
43
+ }
44
+ else {
45
+ await client.run(op);
46
+ }
47
+ }
48
+ const tessellated = await client.run({ kind: 'tessellate_all' });
49
+ const meshes = (tessellated.meshes ?? []).map(workerMeshToExecutorMesh);
50
+ return { meshes, volumes, exported };
51
+ }
52
+ finally {
53
+ client.dispose();
54
+ }
55
+ }
@@ -0,0 +1,8 @@
1
+ export const BUILTIN_CONNECTOR = {
2
+ id: 'builtin',
3
+ label: 'Built-in kernel (OCCT + WebGL)',
4
+ vendor: 'dsh-cad',
5
+ language: 'webgl',
6
+ status: 'built-in',
7
+ binding: 'opencascade.js 1.1.1 WASM worker; three.js typed-array rendering, zero install',
8
+ };