cyclecad 0.2.2 → 0.3.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 (85) hide show
  1. package/API-BUILD-MANIFEST.txt +339 -0
  2. package/API-SERVER.md +535 -0
  3. package/Architecture-Deck.pptx +0 -0
  4. package/CLAUDE.md +172 -11
  5. package/CLI-BUILD-SUMMARY.md +504 -0
  6. package/CLI-INDEX.md +356 -0
  7. package/CLI-README.md +466 -0
  8. package/COLLABORATION-INTEGRATION-GUIDE.md +325 -0
  9. package/CONNECTED_FABS_GUIDE.md +612 -0
  10. package/CONNECTED_FABS_README.md +310 -0
  11. package/DELIVERABLES.md +343 -0
  12. package/DFM-ANALYZER-INTEGRATION.md +368 -0
  13. package/DFM-QUICK-START.js +253 -0
  14. package/Dockerfile +69 -0
  15. package/IMPLEMENTATION.md +327 -0
  16. package/LICENSE +31 -0
  17. package/MARKETPLACE_QUICK_REFERENCE.txt +294 -0
  18. package/MCP-INDEX.md +264 -0
  19. package/QUICKSTART-API.md +388 -0
  20. package/QUICKSTART-CLI.md +211 -0
  21. package/QUICKSTART-MCP.md +196 -0
  22. package/README-MCP.md +208 -0
  23. package/TEST-TOKEN-ENGINE.md +319 -0
  24. package/TOKEN-ENGINE-SUMMARY.md +266 -0
  25. package/TOKENS-README.md +263 -0
  26. package/TOOLS-REFERENCE.md +254 -0
  27. package/app/index.html +373 -3
  28. package/app/js/TOKEN-INTEGRATION.md +391 -0
  29. package/app/js/agent-api.js +3 -3
  30. package/app/js/ai-copilot.js +1435 -0
  31. package/app/js/cad-vr.js +917 -0
  32. package/app/js/cam-operations.js +638 -0
  33. package/app/js/cam-pipeline.js +840 -0
  34. package/app/js/collaboration-ui.js +995 -0
  35. package/app/js/collaboration.js +1116 -0
  36. package/app/js/connected-fabs-example.js +404 -0
  37. package/app/js/connected-fabs.js +1449 -0
  38. package/app/js/dfm-analyzer.js +1760 -0
  39. package/app/js/gcode-generator.js +485 -0
  40. package/app/js/gdt-training.js +1144 -0
  41. package/app/js/machine-profiles.js +534 -0
  42. package/app/js/marketplace-v2.js +766 -0
  43. package/app/js/marketplace.js +1994 -0
  44. package/app/js/material-library.js +2115 -0
  45. package/app/js/misumi-catalog.js +904 -0
  46. package/app/js/section-view.js +666 -0
  47. package/app/js/sketch-enhance.js +779 -0
  48. package/app/js/stock-manager.js +482 -0
  49. package/app/js/text-to-cad.js +806 -0
  50. package/app/js/token-dashboard.js +563 -0
  51. package/app/js/token-engine.js +743 -0
  52. package/app/js/tool-library.js +593 -0
  53. package/app/test-agent.html +1801 -0
  54. package/app/tutorials/advanced.html +1924 -0
  55. package/app/tutorials/basic.html +1160 -0
  56. package/app/tutorials/intermediate.html +1456 -0
  57. package/bin/cyclecad-cli.js +662 -0
  58. package/bin/cyclecad-mcp +2 -0
  59. package/bin/server.js +242 -0
  60. package/cycleCAD-Architecture.pptx +0 -0
  61. package/cycleCAD-Investor-Deck.pptx +0 -0
  62. package/demo-mcp.sh +60 -0
  63. package/docs/API-SERVER-SUMMARY.md +375 -0
  64. package/docs/API-SERVER.md +667 -0
  65. package/docs/CAM-EXAMPLES.md +344 -0
  66. package/docs/CAM-INTEGRATION.md +612 -0
  67. package/docs/CAM-QUICK-REFERENCE.md +199 -0
  68. package/docs/CLI-INTEGRATION.md +510 -0
  69. package/docs/CLI.md +872 -0
  70. package/docs/MARKETPLACE-API-SCHEMA.json +564 -0
  71. package/docs/MARKETPLACE-INTEGRATION.md +467 -0
  72. package/docs/MARKETPLACE-SETUP.html +439 -0
  73. package/docs/MCP-SERVER.md +403 -0
  74. package/examples/api-client-example.js +488 -0
  75. package/examples/api-client-example.py +359 -0
  76. package/examples/batch-manufacturing.txt +28 -0
  77. package/examples/batch-simple.txt +26 -0
  78. package/linkedin-post-combined.md +31 -0
  79. package/model-marketplace.html +1273 -0
  80. package/package.json +14 -3
  81. package/server/api-server.js +1120 -0
  82. package/server/mcp-server.js +1161 -0
  83. package/test-api-server.js +432 -0
  84. package/test-mcp.js +198 -0
  85. package/~$cycleCAD-Investor-Deck.pptx +0 -0
@@ -0,0 +1,904 @@
1
+ /**
2
+ * MISUMI Catalog Integration Module for cycleCAD
3
+ *
4
+ * Comprehensive mechanical components library with parametric configurator,
5
+ * search, BOM management, and direct MISUMI linking.
6
+ *
7
+ * Usage: window.cycleCAD.misumi.configure('linearMotion', 'shaft', {...})
8
+ */
9
+
10
+ (function() {
11
+ 'use strict';
12
+
13
+ // Component database: organized by category
14
+ const COMPONENT_DB = {
15
+ linearMotion: {
16
+ shaft: {
17
+ name: 'Precision Shafts',
18
+ description: 'Ground and hardened precision shafts',
19
+ subtypes: {
20
+ induction: {
21
+ label: 'Induction Hardened',
22
+ pattern: 'PSFJ{dia}-{len}',
23
+ diameters: [3, 4, 5, 6, 8, 10, 12, 16, 20, 25, 32, 40, 50],
24
+ maxLengths: { 3: 500, 5: 500, 8: 800, 10: 1000, 16: 1000, 20: 1500, 25: 2000 },
25
+ material: 'SUJ2 Steel',
26
+ tolerance: 'h6',
27
+ weight: (d, l) => (d * d * l * 7.85) / 1000, // grams
28
+ price: (d, l) => 50 + (d * l * 0.08), // USD
29
+ image: 'shaft-induction'
30
+ },
31
+ ground: {
32
+ label: 'Precision Ground',
33
+ pattern: 'PSFG{dia}-{len}',
34
+ diameters: [3, 4, 5, 6, 8, 10, 12, 16, 20, 25, 32],
35
+ maxLengths: { 3: 400, 5: 500, 8: 700, 10: 900, 16: 1200, 25: 1500 },
36
+ material: 'Carbon Steel',
37
+ tolerance: 'g6',
38
+ weight: (d, l) => (d * d * l * 7.85) / 1000,
39
+ price: (d, l) => 45 + (d * l * 0.07),
40
+ image: 'shaft-ground'
41
+ }
42
+ }
43
+ },
44
+ bushing: {
45
+ name: 'Linear Bushings',
46
+ description: 'LM-type linear motion bushings',
47
+ subtypes: {
48
+ lm: {
49
+ label: 'LM Type',
50
+ pattern: 'LM{dia}UU',
51
+ sizes: [3, 4, 5, 6, 8, 10, 12, 16, 20, 25, 32, 40, 50],
52
+ material: 'Steel with bearing balls',
53
+ tolerance: 'Standard',
54
+ weight: (s) => s * 0.5 + 2,
55
+ price: (s) => 20 + (s * 1.5),
56
+ image: 'bushing-lm'
57
+ },
58
+ lme: {
59
+ label: 'LME Type (Extended)',
60
+ pattern: 'LME{dia}UU',
61
+ sizes: [3, 4, 5, 6, 8, 10, 12, 16, 20, 25, 32],
62
+ material: 'Steel with bearing balls',
63
+ tolerance: 'Standard',
64
+ weight: (s) => s * 0.8 + 3,
65
+ price: (s) => 28 + (s * 1.8),
66
+ image: 'bushing-lme'
67
+ },
68
+ flanged: {
69
+ label: 'Flanged',
70
+ pattern: 'LMF{dia}UU',
71
+ sizes: [4, 5, 6, 8, 10, 12, 16, 20, 25],
72
+ material: 'Steel with bearing balls',
73
+ tolerance: 'Standard',
74
+ weight: (s) => s * 1.0 + 5,
75
+ price: (s) => 35 + (s * 2.0),
76
+ image: 'bushing-flanged'
77
+ }
78
+ }
79
+ },
80
+ guide: {
81
+ name: 'Linear Guides',
82
+ description: 'Profile linear guides for precise motion',
83
+ subtypes: {
84
+ miniature: {
85
+ label: 'Miniature',
86
+ pattern: 'LGLV{size}-{len}',
87
+ sizes: [5, 7, 9, 12],
88
+ lengths: [50, 100, 150, 200, 300, 400, 500],
89
+ material: 'Stainless steel',
90
+ tolerance: 'H',
91
+ weight: (s, l) => (s + 2) * (l / 100) * 0.3,
92
+ price: (s, l) => 80 + (s * 5) + (l * 0.2),
93
+ image: 'guide-miniature'
94
+ },
95
+ standard: {
96
+ label: 'Standard',
97
+ pattern: 'LGLV{size}-{len}',
98
+ sizes: [15, 20, 25, 30, 35, 45],
99
+ lengths: [100, 150, 200, 300, 400, 500, 750, 1000],
100
+ material: 'Stainless steel',
101
+ tolerance: 'H',
102
+ weight: (s, l) => (s + 5) * (l / 100) * 0.6,
103
+ price: (s, l) => 150 + (s * 8) + (l * 0.4),
104
+ image: 'guide-standard'
105
+ }
106
+ }
107
+ },
108
+ ballScrew: {
109
+ name: 'Ball Screws',
110
+ description: 'Rolled and ground ball screws',
111
+ subtypes: {
112
+ rolled: {
113
+ label: 'Rolled',
114
+ pattern: 'BSRT{dia}x{lead}-{len}',
115
+ diameters: [8, 10, 12, 16, 20, 25, 32],
116
+ leads: [2, 3, 4, 5, 10, 16, 20],
117
+ lengths: [100, 200, 300, 500, 750, 1000, 1500],
118
+ material: 'Chrome Steel',
119
+ tolerance: 'C7',
120
+ weight: (d, l) => (d * d * l * 7.85) / 800,
121
+ price: (d, lead, l) => 120 + (d * 10) + (lead * 5) + (l * 0.3),
122
+ image: 'ballscrew-rolled'
123
+ },
124
+ ground: {
125
+ label: 'Ground',
126
+ pattern: 'BSGR{dia}x{lead}-{len}',
127
+ diameters: [10, 12, 16, 20, 25, 32],
128
+ leads: [2, 3, 4, 5, 10, 16],
129
+ lengths: [150, 300, 500, 750, 1000],
130
+ material: 'Chrome Steel',
131
+ tolerance: 'C5',
132
+ weight: (d, l) => (d * d * l * 7.85) / 750,
133
+ price: (d, lead, l) => 200 + (d * 15) + (lead * 8) + (l * 0.5),
134
+ image: 'ballscrew-ground'
135
+ }
136
+ }
137
+ }
138
+ },
139
+
140
+ fasteners: {
141
+ shcs: {
142
+ name: 'Socket Head Cap Screws',
143
+ description: 'ISO 4762 / DIN 912 socket head cap screws',
144
+ subtypes: {
145
+ steel: {
146
+ label: 'Steel (Bright)',
147
+ pattern: 'SHCS-{dia}x{length}-ST',
148
+ diameters: [2, 2.5, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 30],
149
+ lengths: [6, 8, 10, 12, 16, 20, 25, 30, 40, 50, 60, 80, 100],
150
+ material: 'Steel, Grade 8.8',
151
+ finish: 'Bright',
152
+ weight: (d, l) => (d * d * l * 7.85) / 2000,
153
+ price: (d, l) => 0.5 + (d * 0.15) + (l * 0.02),
154
+ image: 'shcs-steel'
155
+ },
156
+ stainless: {
157
+ label: 'Stainless A2',
158
+ pattern: 'SHCS-{dia}x{length}-A2',
159
+ diameters: [2, 3, 4, 5, 6, 8, 10, 12, 16],
160
+ lengths: [8, 10, 12, 16, 20, 25, 30, 40, 50, 60, 80],
161
+ material: 'Stainless Steel A2',
162
+ finish: 'Polished',
163
+ weight: (d, l) => (d * d * l * 7.98) / 2000,
164
+ price: (d, l) => 0.8 + (d * 0.25) + (l * 0.035),
165
+ image: 'shcs-stainless'
166
+ }
167
+ }
168
+ },
169
+ hexBolt: {
170
+ name: 'Hex Bolts',
171
+ description: 'ISO 4014 / DIN 933 hex bolts',
172
+ subtypes: {
173
+ steel: {
174
+ label: 'Steel, Grade 8.8',
175
+ pattern: 'HB-{dia}x{length}-8.8',
176
+ diameters: [3, 4, 5, 6, 8, 10, 12, 16, 20, 24],
177
+ lengths: [10, 12, 16, 20, 25, 30, 40, 50, 60, 80],
178
+ material: 'Steel, Grade 8.8',
179
+ finish: 'Zinc plated',
180
+ weight: (d, l) => (d * d * l * 7.85) / 1500,
181
+ price: (d, l) => 0.4 + (d * 0.08) + (l * 0.01),
182
+ image: 'hexbolt-steel'
183
+ }
184
+ }
185
+ },
186
+ setScrew: {
187
+ name: 'Set Screws',
188
+ description: 'ISO 4027 set screws with various points',
189
+ subtypes: {
190
+ cupPoint: {
191
+ label: 'Cup Point',
192
+ pattern: 'SS-{dia}x{length}-CUP',
193
+ diameters: [1.6, 2, 2.5, 3, 4, 5, 6, 8, 10],
194
+ lengths: [6, 8, 10, 12, 16, 20, 25, 30],
195
+ material: 'Steel, Grade 45H',
196
+ finish: 'Black oxide',
197
+ weight: (d, l) => (d * d * l * 7.85) / 3000,
198
+ price: (d, l) => 0.3 + (d * 0.1) + (l * 0.015),
199
+ image: 'setscrew-cup'
200
+ },
201
+ flatPoint: {
202
+ label: 'Flat Point',
203
+ pattern: 'SS-{dia}x{length}-FLAT',
204
+ diameters: [1.6, 2, 2.5, 3, 4, 5, 6, 8],
205
+ lengths: [6, 8, 10, 12, 16, 20, 25],
206
+ material: 'Steel, Grade 45H',
207
+ finish: 'Black oxide',
208
+ weight: (d, l) => (d * d * l * 7.85) / 3000,
209
+ price: (d, l) => 0.25 + (d * 0.08) + (l * 0.012),
210
+ image: 'setscrew-flat'
211
+ }
212
+ }
213
+ },
214
+ dowelPin: {
215
+ name: 'Dowel Pins',
216
+ description: 'Precision locating pins',
217
+ subtypes: {
218
+ standard: {
219
+ label: 'Standard (h7)',
220
+ pattern: 'DP-{dia}x{length}-STD',
221
+ diameters: [2, 3, 4, 5, 6, 8, 10, 12, 16],
222
+ lengths: [10, 12, 16, 20, 25, 30, 40, 50],
223
+ material: 'Steel',
224
+ tolerance: 'h7',
225
+ weight: (d, l) => (d * d * l * 7.85) / 2000,
226
+ price: (d, l) => 0.2 + (d * 0.05) + (l * 0.01),
227
+ image: 'dowel-standard'
228
+ }
229
+ }
230
+ },
231
+ hexNut: {
232
+ name: 'Hex Nuts',
233
+ description: 'ISO 4032 hex nuts',
234
+ subtypes: {
235
+ steel: {
236
+ label: 'Steel, Grade 8',
237
+ pattern: 'HN-{dia}-ST',
238
+ diameters: [3, 4, 5, 6, 8, 10, 12, 16, 20, 24],
239
+ material: 'Steel, Grade 8',
240
+ finish: 'Zinc plated',
241
+ weight: (d) => (d * d * 3 * 7.85) / 1000,
242
+ price: (d) => 0.15 + (d * 0.03),
243
+ image: 'hexnut-steel'
244
+ }
245
+ }
246
+ },
247
+ washer: {
248
+ name: 'Washers',
249
+ description: 'Flat and spring washers',
250
+ subtypes: {
251
+ flat: {
252
+ label: 'Flat (DIN 125)',
253
+ pattern: 'WF-{dia}-ST',
254
+ diameters: [3, 4, 5, 6, 8, 10, 12, 16, 20, 24],
255
+ material: 'Steel',
256
+ finish: 'Zinc plated',
257
+ weight: (d) => (d * d * 0.5 * 7.85) / 1000,
258
+ price: (d) => 0.08 + (d * 0.01),
259
+ image: 'washer-flat'
260
+ },
261
+ spring: {
262
+ label: 'Spring (DIN 127)',
263
+ pattern: 'WS-{dia}-ST',
264
+ diameters: [3, 4, 5, 6, 8, 10, 12, 16, 20],
265
+ material: 'Steel',
266
+ finish: 'Zinc plated',
267
+ weight: (d) => (d * d * 0.7 * 7.85) / 1000,
268
+ price: (d) => 0.12 + (d * 0.02),
269
+ image: 'washer-spring'
270
+ }
271
+ }
272
+ }
273
+ },
274
+
275
+ springs: {
276
+ compression: {
277
+ name: 'Compression Springs',
278
+ description: 'Helical compression springs',
279
+ subtypes: {
280
+ light: {
281
+ label: 'Light Duty',
282
+ pattern: 'CSL-{od}x{id}x{len}',
283
+ outerDiameters: [5, 6, 8, 10, 12, 16, 20, 25, 30],
284
+ loads: [1, 2, 5, 10, 15, 20], // Newton per mm
285
+ material: 'Music Wire',
286
+ tolerance: '±0.3mm',
287
+ weight: (od) => od * 0.3,
288
+ price: (od, load) => 5 + (od * 0.5) + (load * 0.2),
289
+ image: 'spring-compression-light'
290
+ },
291
+ medium: {
292
+ label: 'Medium Duty',
293
+ pattern: 'CSM-{od}x{id}x{len}',
294
+ outerDiameters: [8, 10, 12, 16, 20, 25, 32, 40],
295
+ loads: [10, 20, 30, 50, 75, 100],
296
+ material: 'Chrome Steel',
297
+ tolerance: '±0.5mm',
298
+ weight: (od) => od * 0.6,
299
+ price: (od, load) => 12 + (od * 1.0) + (load * 0.3),
300
+ image: 'spring-compression-medium'
301
+ }
302
+ }
303
+ },
304
+ extension: {
305
+ name: 'Extension Springs',
306
+ description: 'Helical extension springs with hooks',
307
+ subtypes: {
308
+ hookEnd: {
309
+ label: 'Hook Ends',
310
+ pattern: 'ESH-{od}x{id}x{len}',
311
+ outerDiameters: [4, 5, 6, 8, 10, 12, 16, 20],
312
+ loads: [1, 2, 5, 10, 20, 30, 50],
313
+ material: 'Music Wire',
314
+ hookType: 'Full loop',
315
+ weight: (od) => od * 0.25,
316
+ price: (od, load) => 6 + (od * 0.4) + (load * 0.25),
317
+ image: 'spring-extension-hook'
318
+ }
319
+ }
320
+ }
321
+ },
322
+
323
+ shaftsAndCouplings: {
324
+ shaftCollar: {
325
+ name: 'Shaft Collars',
326
+ description: 'Set screw and clamp-style collars',
327
+ subtypes: {
328
+ setScrew: {
329
+ label: 'Set Screw',
330
+ pattern: 'SC-{dia}x{width}-SS',
331
+ bores: [4, 5, 6, 8, 10, 12, 16, 20, 25],
332
+ widths: [10, 13, 16, 19, 25],
333
+ material: 'Cast iron',
334
+ finish: 'Black oxide',
335
+ weight: (d, w) => (d + 5) * (w / 5) * 0.8,
336
+ price: (d, w) => 3 + (d * 0.2) + (w * 0.3),
337
+ image: 'collar-setscrew'
338
+ },
339
+ clamp: {
340
+ label: 'Clamp Type',
341
+ pattern: 'SC-{dia}x{width}-CL',
342
+ bores: [6, 8, 10, 12, 16, 20, 25, 32],
343
+ widths: [13, 16, 19, 25, 32],
344
+ material: 'Stainless steel',
345
+ finish: 'Polished',
346
+ weight: (d, w) => (d + 6) * (w / 5) * 1.0,
347
+ price: (d, w) => 8 + (d * 0.35) + (w * 0.5),
348
+ image: 'collar-clamp'
349
+ }
350
+ }
351
+ },
352
+ flexibleCoupling: {
353
+ name: 'Flexible Couplings',
354
+ description: 'Flexible shaft couplings',
355
+ subtypes: {
356
+ jaw: {
357
+ label: 'Jaw Type',
358
+ pattern: 'FC-JAW-{dia1}x{dia2}',
359
+ sizes: [3, 4, 5, 6, 8, 10, 12, 16, 20],
360
+ material: 'Cast iron with elastomer',
361
+ misalignment: '1.5mm',
362
+ weight: (s) => s * 0.5 + 15,
363
+ price: (s) => 25 + (s * 2.0),
364
+ image: 'coupling-jaw'
365
+ },
366
+ beam: {
367
+ label: 'Beam Type',
368
+ pattern: 'FC-BEAM-{dia}',
369
+ sizes: [3, 4, 5, 6, 8, 10, 12],
370
+ material: 'Aluminum',
371
+ misalignment: '0.5mm',
372
+ weight: (s) => s * 0.2 + 8,
373
+ price: (s) => 15 + (s * 1.5),
374
+ image: 'coupling-beam'
375
+ }
376
+ }
377
+ }
378
+ },
379
+
380
+ positioning: {
381
+ locatingPin: {
382
+ name: 'Locating Pins',
383
+ description: 'Straight and tapered locating pins',
384
+ subtypes: {
385
+ straight: {
386
+ label: 'Straight',
387
+ pattern: 'LP-{dia}x{length}-ST',
388
+ diameters: [2, 3, 4, 5, 6, 8, 10, 12],
389
+ lengths: [10, 15, 20, 25, 30, 40, 50],
390
+ material: 'Hardened steel',
391
+ tolerance: 'h7',
392
+ weight: (d, l) => (d * d * l * 7.85) / 2000,
393
+ price: (d, l) => 1.5 + (d * 0.1) + (l * 0.02),
394
+ image: 'pin-straight'
395
+ },
396
+ tapered: {
397
+ label: 'Tapered (1:50)',
398
+ pattern: 'LP-{dia}x{length}-TAP',
399
+ diameters: [2, 3, 4, 5, 6, 8, 10],
400
+ lengths: [12, 16, 20, 25, 30, 40],
401
+ material: 'Hardened steel',
402
+ tolerance: 'h7',
403
+ weight: (d, l) => (d * d * l * 7.85) / 2500,
404
+ price: (d, l) => 2.0 + (d * 0.15) + (l * 0.025),
405
+ image: 'pin-tapered'
406
+ }
407
+ }
408
+ },
409
+ toggleClamp: {
410
+ name: 'Toggle Clamps',
411
+ description: 'Quick action toggle clamps',
412
+ subtypes: {
413
+ horizontal: {
414
+ label: 'Horizontal',
415
+ pattern: 'TC-HOR-{capacity}',
416
+ capacities: [100, 200, 300, 500, 750, 1000, 1500], // Newtons
417
+ material: 'Ductile iron',
418
+ stroke: (cap) => 20 + (cap / 100) * 5,
419
+ weight: (cap) => 0.5 + (cap / 200),
420
+ price: (cap) => 20 + (cap * 0.02),
421
+ image: 'clamp-toggle-horizontal'
422
+ }
423
+ }
424
+ },
425
+ levelingFeet: {
426
+ name: 'Leveling Feet',
427
+ description: 'Adjustable leveling feet and pads',
428
+ subtypes: {
429
+ threaded: {
430
+ label: 'Threaded',
431
+ pattern: 'LF-{thread}x{diameter}',
432
+ threads: ['M6', 'M8', 'M10', 'M12', 'M16', 'M20'],
433
+ diameters: [30, 40, 50, 60, 75, 100],
434
+ material: 'Steel base, elastomer pad',
435
+ padMaterial: 'Natural rubber',
436
+ weight: (d) => d * 0.5,
437
+ price: (t, d) => 8 + (d * 0.15),
438
+ image: 'feet-leveling'
439
+ }
440
+ }
441
+ }
442
+ }
443
+ };
444
+
445
+ // MCP server: encapsulate all methods
446
+ const MisumiCatalog = {
447
+ // Database getters
448
+ getCategory(catName) {
449
+ return COMPONENT_DB[catName] || null;
450
+ },
451
+
452
+ getComponentType(catName, typeName) {
453
+ const cat = COMPONENT_DB[catName];
454
+ return cat ? cat[typeName] : null;
455
+ },
456
+
457
+ getAllComponents() {
458
+ const all = [];
459
+ for (const [catKey, catVal] of Object.entries(COMPONENT_DB)) {
460
+ for (const [typeKey, typeVal] of Object.entries(catVal)) {
461
+ all.push({
462
+ category: catKey,
463
+ type: typeKey,
464
+ name: typeVal.name,
465
+ description: typeVal.description
466
+ });
467
+ }
468
+ }
469
+ return all;
470
+ },
471
+
472
+ // Parametric configurator
473
+ configure(category, type, params = {}) {
474
+ const comp = this.getComponentType(category, type);
475
+ if (!comp) return null;
476
+
477
+ const subtype = comp.subtypes[params.subtype || Object.keys(comp.subtypes)[0]];
478
+ if (!subtype) return null;
479
+
480
+ // Generate part number
481
+ let partNumber = subtype.pattern;
482
+ if (params.diameter) partNumber = partNumber.replace('{dia}', params.diameter);
483
+ if (params.length) partNumber = partNumber.replace('{len}', params.length);
484
+ if (params.lead) partNumber = partNumber.replace('{lead}', params.lead);
485
+ if (params.od) partNumber = partNumber.replace('{od}', params.od);
486
+ if (params.id) partNumber = partNumber.replace('{id}', params.id);
487
+ if (params.size) partNumber = partNumber.replace('{size}', params.size);
488
+
489
+ // Calculate weight and price
490
+ let weight = 0;
491
+ let priceUsd = 0;
492
+ if (params.diameter && params.length) {
493
+ weight = subtype.weight(params.diameter, params.length);
494
+ if (params.lead) {
495
+ priceUsd = subtype.price(params.diameter, params.lead, params.length);
496
+ } else {
497
+ priceUsd = subtype.price(params.diameter, params.length);
498
+ }
499
+ } else if (params.diameter) {
500
+ weight = subtype.weight(params.diameter);
501
+ priceUsd = subtype.price(params.diameter);
502
+ } else if (params.size) {
503
+ weight = subtype.weight(params.size);
504
+ priceUsd = subtype.price(params.size);
505
+ }
506
+
507
+ const priceTokens = Math.round(priceUsd * 1.5); // Convert USD to estimated $CYCLE tokens
508
+
509
+ return {
510
+ misumiPN: partNumber,
511
+ name: comp.name,
512
+ subtype: subtype.label,
513
+ material: subtype.material,
514
+ finish: subtype.finish || 'Standard',
515
+ tolerance: subtype.tolerance || 'Standard',
516
+ specifications: params,
517
+ weight: parseFloat(weight.toFixed(2)),
518
+ priceUSD: parseFloat(priceUsd.toFixed(2)),
519
+ priceTokens: priceTokens,
520
+ misumiUrl: `https://us.misumi-ec.com/vona2/detail/${partNumber.replace('{', '').replace('}', '')}`,
521
+ image: subtype.image
522
+ };
523
+ },
524
+
525
+ // Search across all components
526
+ search(query, filters = {}) {
527
+ const results = [];
528
+ const lowerQuery = query.toLowerCase();
529
+
530
+ for (const [catKey, catVal] of Object.entries(COMPONENT_DB)) {
531
+ for (const [typeKey, typeVal] of Object.entries(catVal)) {
532
+ // Match on name, description, or type
533
+ const matchScore =
534
+ (typeVal.name.toLowerCase().includes(lowerQuery) ? 3 : 0) +
535
+ (typeVal.description.toLowerCase().includes(lowerQuery) ? 2 : 0) +
536
+ (typeKey.toLowerCase().includes(lowerQuery) ? 1 : 0);
537
+
538
+ if (matchScore > 0) {
539
+ // Apply filters
540
+ if (filters.category && catKey !== filters.category) continue;
541
+ if (filters.material && typeVal.subtypes) {
542
+ const subtypesMatching = Object.entries(typeVal.subtypes).filter(
543
+ ([, st]) => !filters.material || (st.material && st.material.includes(filters.material))
544
+ );
545
+ if (subtypesMatching.length === 0) continue;
546
+ }
547
+
548
+ results.push({
549
+ category: catKey,
550
+ type: typeKey,
551
+ name: typeVal.name,
552
+ description: typeVal.description,
553
+ score: matchScore,
554
+ subtypes: Object.keys(typeVal.subtypes)
555
+ });
556
+ }
557
+ }
558
+ }
559
+
560
+ return results.sort((a, b) => b.score - a.score);
561
+ },
562
+
563
+ // Compare multiple parts
564
+ compare(partNumbers) {
565
+ const specs = partNumbers.map(pn => {
566
+ // Extract config from part number (simplified)
567
+ return {
568
+ misumiPN: pn,
569
+ url: `https://us.misumi-ec.com/vona2/detail/${pn}`
570
+ };
571
+ });
572
+
573
+ return {
574
+ parts: specs,
575
+ comparisonUrl: `https://us.misumi-ec.com/vona2/mcs/Item?SORL=0${specs.map(s => `&ML=${encodeURIComponent(s.misumiPN)}`).join('')}`
576
+ };
577
+ },
578
+
579
+ // BOM management
580
+ getBOM() {
581
+ const bom = JSON.parse(localStorage.getItem('cyclecad_misumi_bom') || '[]');
582
+ return bom;
583
+ },
584
+
585
+ addToBOM(partNumber, quantity = 1) {
586
+ const bom = this.getBOM();
587
+ const existing = bom.find(item => item.misumiPN === partNumber);
588
+ if (existing) {
589
+ existing.quantity += quantity;
590
+ } else {
591
+ bom.push({ misumiPN: partNumber, quantity, added: new Date().toISOString() });
592
+ }
593
+ localStorage.setItem('cyclecad_misumi_bom', JSON.stringify(bom));
594
+ return bom;
595
+ },
596
+
597
+ removeFromBOM(partNumber) {
598
+ const bom = this.getBOM().filter(item => item.misumiPN !== partNumber);
599
+ localStorage.setItem('cyclecad_misumi_bom', JSON.stringify(bom));
600
+ return bom;
601
+ },
602
+
603
+ clearBOM() {
604
+ localStorage.setItem('cyclecad_misumi_bom', '[]');
605
+ },
606
+
607
+ getBOMTotal() {
608
+ // Simplified: sum of estimated prices
609
+ // In real implementation, would fetch live prices from MISUMI API
610
+ return {
611
+ itemCount: this.getBOM().reduce((sum, item) => sum + item.quantity, 0),
612
+ estimatedUSD: this.getBOM().reduce((sum, item) => sum + 50, 0), // Placeholder
613
+ estimatedTokens: this.getBOM().length * 75
614
+ };
615
+ },
616
+
617
+ exportBOM(format = 'csv') {
618
+ const bom = this.getBOM();
619
+ if (format === 'csv') {
620
+ const header = 'MISUMI PN,Quantity,Unit Price (USD),Total,MISUMI URL';
621
+ const rows = bom.map(item =>
622
+ `${item.misumiPN},${item.quantity},50.00,${item.quantity * 50},${ encodeURIComponent(item.misumiPN)}`
623
+ );
624
+ return header + '\n' + rows.join('\n');
625
+ } else if (format === 'html') {
626
+ let html = '<table border="1"><tr><th>MISUMI PN</th><th>Quantity</th><th>Price</th><th>Link</th></tr>';
627
+ bom.forEach(item => {
628
+ html += `<tr><td>${item.misumiPN}</td><td>${item.quantity}</td><td>$50</td>`;
629
+ html += `<td><a href="https://us.misumi-ec.com/vona2/detail/${item.misumiPN}" target="_blank">MISUMI</a></td></tr>`;
630
+ });
631
+ html += '</table>';
632
+ return html;
633
+ }
634
+ return null;
635
+ },
636
+
637
+ // Quick 3D geometry generation
638
+ insertComponent(partNumber, position = [0, 0, 0]) {
639
+ // Simplified: return basic geometry for visualization
640
+ // In full implementation, would return proper Three.js geometry
641
+ const geom = {
642
+ type: 'cylinder', // or 'box', 'torus', etc.
643
+ params: {
644
+ radiusTop: 5,
645
+ radiusBottom: 5,
646
+ height: 50,
647
+ segments: 16
648
+ },
649
+ position,
650
+ misumiPN: partNumber
651
+ };
652
+ return geom;
653
+ },
654
+
655
+ // UI generation
656
+ getUI() {
657
+ return `
658
+ <div id="misumi-panel" class="misumi-panel" style="
659
+ position: fixed;
660
+ right: 0;
661
+ top: 44px;
662
+ width: 400px;
663
+ height: calc(100vh - 44px);
664
+ background: #1e1e1e;
665
+ border-left: 1px solid #333;
666
+ color: #e0e0e0;
667
+ font-family: Calibri, sans-serif;
668
+ font-size: 13px;
669
+ z-index: 999;
670
+ display: flex;
671
+ flex-direction: column;
672
+ ">
673
+ <div class="misumi-tabs" style="
674
+ display: flex;
675
+ border-bottom: 1px solid #333;
676
+ background: #252525;
677
+ ">
678
+ <button class="tab-btn active" data-tab="browse" style="
679
+ flex: 1;
680
+ padding: 10px;
681
+ border: none;
682
+ background: #252525;
683
+ color: #58a6ff;
684
+ cursor: pointer;
685
+ border-bottom: 2px solid #58a6ff;
686
+ font-weight: bold;
687
+ ">Browse</button>
688
+ <button class="tab-btn" data-tab="configure" style="
689
+ flex: 1;
690
+ padding: 10px;
691
+ border: none;
692
+ background: #252525;
693
+ color: #888;
694
+ cursor: pointer;
695
+ font-weight: bold;
696
+ ">Configure</button>
697
+ <button class="tab-btn" data-tab="search" style="
698
+ flex: 1;
699
+ padding: 10px;
700
+ border: none;
701
+ background: #252525;
702
+ color: #888;
703
+ cursor: pointer;
704
+ font-weight: bold;
705
+ ">Search</button>
706
+ <button class="tab-btn" data-tab="bom" style="
707
+ flex: 1;
708
+ padding: 10px;
709
+ border: none;
710
+ background: #252525;
711
+ color: #888;
712
+ cursor: pointer;
713
+ font-weight: bold;
714
+ ">BOM</button>
715
+ </div>
716
+
717
+ <div class="misumi-content" style="
718
+ flex: 1;
719
+ overflow-y: auto;
720
+ padding: 12px;
721
+ min-height: 0;
722
+ ">
723
+ <!-- Browse Tab -->
724
+ <div class="tab-content browse active" style="display: block;">
725
+ <div style="font-weight: bold; margin-bottom: 10px; color: #58a6ff;">Component Categories</div>
726
+ <div id="misumi-categories" style="
727
+ display: grid;
728
+ grid-template-columns: 1fr 1fr;
729
+ gap: 8px;
730
+ ">
731
+ <button style="padding: 12px; background: #2d2d2d; border: 1px solid #444; color: #e0e0e0; cursor: pointer; border-radius: 4px; font-size: 11px;" onclick="window.cycleCAD.misumi._expandCategory('linearMotion')">Linear Motion</button>
732
+ <button style="padding: 12px; background: #2d2d2d; border: 1px solid #444; color: #e0e0e0; cursor: pointer; border-radius: 4px; font-size: 11px;" onclick="window.cycleCAD.misumi._expandCategory('fasteners')">Fasteners</button>
733
+ <button style="padding: 12px; background: #2d2d2d; border: 1px solid #444; color: #e0e0e0; cursor: pointer; border-radius: 4px; font-size: 11px;" onclick="window.cycleCAD.misumi._expandCategory('springs')">Springs</button>
734
+ <button style="padding: 12px; background: #2d2d2d; border: 1px solid #444; color: #e0e0e0; cursor: pointer; border-radius: 4px; font-size: 11px;" onclick="window.cycleCAD.misumi._expandCategory('shaftsAndCouplings')">Couplings</button>
735
+ <button style="padding: 12px; background: #2d2d2d; border: 1px solid #444; color: #e0e0e0; cursor: pointer; border-radius: 4px; font-size: 11px;" onclick="window.cycleCAD.misumi._expandCategory('positioning')">Positioning</button>
736
+ </div>
737
+ <div id="misumi-category-items" style="margin-top: 12px;"></div>
738
+ </div>
739
+
740
+ <!-- Configure Tab -->
741
+ <div class="tab-content configure" style="display: none;">
742
+ <div style="font-weight: bold; margin-bottom: 10px; color: #58a6ff;">Parametric Configurator</div>
743
+ <label style="display: block; margin-bottom: 8px;">
744
+ Category:
745
+ <select id="misumi-cat-sel" style="width: 100%; padding: 6px; background: #2d2d2d; color: #e0e0e0; border: 1px solid #444; border-radius: 4px; margin-top: 4px;">
746
+ <option value="">-- Select --</option>
747
+ <option value="linearMotion">Linear Motion</option>
748
+ <option value="fasteners">Fasteners</option>
749
+ <option value="springs">Springs</option>
750
+ <option value="shaftsAndCouplings">Shafts & Couplings</option>
751
+ <option value="positioning">Positioning</option>
752
+ </select>
753
+ </label>
754
+ <label style="display: block; margin-bottom: 8px;">
755
+ Type:
756
+ <select id="misumi-type-sel" style="width: 100%; padding: 6px; background: #2d2d2d; color: #e0e0e0; border: 1px solid #444; border-radius: 4px; margin-top: 4px;">
757
+ <option value="">-- Select --</option>
758
+ </select>
759
+ </label>
760
+ <div id="misumi-params" style="margin-top: 12px;"></div>
761
+ <button onclick="window.cycleCAD.misumi._executeConfig()" style="
762
+ width: 100%;
763
+ padding: 10px;
764
+ background: #58a6ff;
765
+ color: #1e1e1e;
766
+ border: none;
767
+ border-radius: 4px;
768
+ cursor: pointer;
769
+ font-weight: bold;
770
+ margin-top: 12px;
771
+ ">Configure & Add to BOM</button>
772
+ <div id="misumi-config-result" style="margin-top: 12px; padding: 8px; background: #2d2d2d; border-left: 3px solid #58a6ff; border-radius: 4px; display: none;"></div>
773
+ </div>
774
+
775
+ <!-- Search Tab -->
776
+ <div class="tab-content search" style="display: none;">
777
+ <div style="font-weight: bold; margin-bottom: 10px; color: #58a6ff;">Search Components</div>
778
+ <input type="text" id="misumi-search-input" placeholder="Search..." style="
779
+ width: 100%;
780
+ padding: 8px;
781
+ background: #2d2d2d;
782
+ color: #e0e0e0;
783
+ border: 1px solid #444;
784
+ border-radius: 4px;
785
+ margin-bottom: 10px;
786
+ ">
787
+ <div id="misumi-search-results" style="margin-top: 8px;"></div>
788
+ </div>
789
+
790
+ <!-- BOM Tab -->
791
+ <div class="tab-content bom" style="display: none;">
792
+ <div style="font-weight: bold; margin-bottom: 10px; color: #58a6ff;">Bill of Materials</div>
793
+ <div id="misumi-bom-items" style="margin-bottom: 12px;"></div>
794
+ <div style="background: #2d2d2d; padding: 8px; border-radius: 4px; margin-bottom: 10px;">
795
+ <div>Items: <span id="misumi-bom-count">0</span></div>
796
+ <div>Est. Cost: <span id="misumi-bom-total">$0</span></div>
797
+ </div>
798
+ <button onclick="window.cycleCAD.misumi._exportBOM('csv')" style="
799
+ width: 100%;
800
+ padding: 8px;
801
+ background: #444;
802
+ color: #e0e0e0;
803
+ border: none;
804
+ border-radius: 4px;
805
+ cursor: pointer;
806
+ margin-bottom: 6px;
807
+ ">Export CSV</button>
808
+ <button onclick="window.cycleCAD.misumi._clearBOM()" style="
809
+ width: 100%;
810
+ padding: 8px;
811
+ background: #333;
812
+ color: #e0e0e0;
813
+ border: none;
814
+ border-radius: 4px;
815
+ cursor: pointer;
816
+ ">Clear BOM</button>
817
+ </div>
818
+ </div>
819
+ </div>
820
+ `;
821
+ },
822
+
823
+ // Internal UI helpers
824
+ _expandCategory(catName) {
825
+ const cat = COMPONENT_DB[catName];
826
+ if (!cat) return;
827
+ const container = document.getElementById('misumi-category-items');
828
+ container.innerHTML = '';
829
+ for (const [typeKey, typeVal] of Object.entries(cat)) {
830
+ const card = document.createElement('div');
831
+ card.style.cssText = 'padding: 10px; background: #2d2d2d; border: 1px solid #444; border-radius: 4px; margin-bottom: 8px; cursor: pointer;';
832
+ card.innerHTML = `
833
+ <div style="font-weight: bold; color: #58a6ff;">${typeVal.name}</div>
834
+ <div style="font-size: 11px; color: #888; margin-top: 4px;">${typeVal.description}</div>
835
+ `;
836
+ card.onclick = () => alert(`${typeVal.name}: ${typeVal.description}\n\nSubtypes: ${Object.keys(typeVal.subtypes).join(', ')}`);
837
+ container.appendChild(card);
838
+ }
839
+ },
840
+
841
+ _executeConfig() {
842
+ const cat = document.getElementById('misumi-cat-sel')?.value;
843
+ const type = document.getElementById('misumi-type-sel')?.value;
844
+ if (!cat || !type) return alert('Please select category and type');
845
+
846
+ const result = this.configure(cat, type, { diameter: 10, length: 100, subtype: Object.keys(COMPONENT_DB[cat]?.[type]?.subtypes || {})[0] });
847
+ if (result) {
848
+ this.addToBOM(result.misumiPN, 1);
849
+ const resultDiv = document.getElementById('misumi-config-result');
850
+ resultDiv.style.display = 'block';
851
+ resultDiv.innerHTML = `<strong>${result.misumiPN}</strong><br>$${result.priceUSD} (${result.priceTokens} tokens)<br><a href="${result.misumiUrl}" target="_blank" style="color: #58a6ff; text-decoration: none;">View on MISUMI</a>`;
852
+ }
853
+ },
854
+
855
+ _exportBOM(format) {
856
+ const csv = this.exportBOM(format);
857
+ const blob = new Blob([csv], { type: 'text/csv' });
858
+ const url = URL.createObjectURL(blob);
859
+ const a = document.createElement('a');
860
+ a.href = url;
861
+ a.download = `cyclecad-bom-${new Date().toISOString().split('T')[0]}.${format}`;
862
+ a.click();
863
+ },
864
+
865
+ _clearBOM() {
866
+ if (confirm('Clear entire BOM?')) {
867
+ this.clearBOM();
868
+ this._updateBOMUI();
869
+ }
870
+ },
871
+
872
+ _updateBOMUI() {
873
+ const bom = this.getBOM();
874
+ const total = this.getBOMTotal();
875
+ document.getElementById('misumi-bom-count').textContent = total.itemCount;
876
+ document.getElementById('misumi-bom-total').textContent = `$${total.estimatedUSD}`;
877
+
878
+ const itemsDiv = document.getElementById('misumi-bom-items');
879
+ itemsDiv.innerHTML = bom.map(item => `
880
+ <div style="padding: 8px; background: #2d2d2d; border-radius: 4px; margin-bottom: 6px; display: flex; justify-content: space-between; align-items: center;">
881
+ <div>
882
+ <div style="font-weight: bold;">${item.misumiPN}</div>
883
+ <div style="font-size: 11px; color: #888;">Qty: ${item.quantity}</div>
884
+ </div>
885
+ <button onclick="window.cycleCAD.misumi.removeFromBOM('${item.misumiPN}'); window.cycleCAD.misumi._updateBOMUI();" style="
886
+ padding: 4px 8px;
887
+ background: #444;
888
+ color: #e0e0e0;
889
+ border: none;
890
+ border-radius: 3px;
891
+ cursor: pointer;
892
+ font-size: 11px;
893
+ ">Remove</button>
894
+ </div>
895
+ `).join('');
896
+ }
897
+ };
898
+
899
+ // Register as window.cycleCAD.misumi
900
+ if (!window.cycleCAD) window.cycleCAD = {};
901
+ window.cycleCAD.misumi = MisumiCatalog;
902
+
903
+ console.log('[MISUMI Catalog] Loaded. Use window.cycleCAD.misumi.configure(...) to get started.');
904
+ })();