cyclecad 0.2.2 → 0.2.3

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 (69) 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 +168 -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/cam-pipeline.js +840 -0
  32. package/app/js/collaboration-ui.js +995 -0
  33. package/app/js/collaboration.js +1116 -0
  34. package/app/js/connected-fabs-example.js +404 -0
  35. package/app/js/connected-fabs.js +1449 -0
  36. package/app/js/dfm-analyzer.js +1760 -0
  37. package/app/js/marketplace.js +1994 -0
  38. package/app/js/material-library.js +2115 -0
  39. package/app/js/token-dashboard.js +563 -0
  40. package/app/js/token-engine.js +743 -0
  41. package/app/test-agent.html +1801 -0
  42. package/bin/cyclecad-cli.js +662 -0
  43. package/bin/cyclecad-mcp +2 -0
  44. package/bin/server.js +242 -0
  45. package/cycleCAD-Architecture.pptx +0 -0
  46. package/cycleCAD-Investor-Deck.pptx +0 -0
  47. package/demo-mcp.sh +60 -0
  48. package/docs/API-SERVER-SUMMARY.md +375 -0
  49. package/docs/API-SERVER.md +667 -0
  50. package/docs/CAM-EXAMPLES.md +344 -0
  51. package/docs/CAM-INTEGRATION.md +612 -0
  52. package/docs/CAM-QUICK-REFERENCE.md +199 -0
  53. package/docs/CLI-INTEGRATION.md +510 -0
  54. package/docs/CLI.md +872 -0
  55. package/docs/MARKETPLACE-API-SCHEMA.json +564 -0
  56. package/docs/MARKETPLACE-INTEGRATION.md +467 -0
  57. package/docs/MARKETPLACE-SETUP.html +439 -0
  58. package/docs/MCP-SERVER.md +403 -0
  59. package/examples/api-client-example.js +488 -0
  60. package/examples/api-client-example.py +359 -0
  61. package/examples/batch-manufacturing.txt +28 -0
  62. package/examples/batch-simple.txt +26 -0
  63. package/model-marketplace.html +1273 -0
  64. package/package.json +14 -3
  65. package/server/api-server.js +1120 -0
  66. package/server/mcp-server.js +1161 -0
  67. package/test-api-server.js +432 -0
  68. package/test-mcp.js +198 -0
  69. package/~$cycleCAD-Investor-Deck.pptx +0 -0
@@ -0,0 +1,359 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ cycleCAD API Client Example
4
+
5
+ Simple Python client for the cycleCAD REST API.
6
+ Demonstrates how to create a simple part using the API.
7
+
8
+ Usage:
9
+ python3 api-client-example.py
10
+ python3 api-client-example.py --host 0.0.0.0 --port 3000 --api-key YOUR_KEY
11
+
12
+ Requirements:
13
+ pip install requests
14
+ """
15
+
16
+ import requests
17
+ import json
18
+ import argparse
19
+ from typing import Dict, Any, List, Optional
20
+
21
+
22
+ class CycleCADClient:
23
+ """Python client for cycleCAD API Server"""
24
+
25
+ def __init__(self, host: str = 'localhost', port: int = 3000, api_key: Optional[str] = None):
26
+ """
27
+ Initialize the client.
28
+
29
+ Args:
30
+ host: Server hostname (default: localhost)
31
+ port: Server port (default: 3000)
32
+ api_key: Optional API key for authentication
33
+ """
34
+ self.base_url = f'http://{host}:{port}'
35
+ self.api_key = api_key
36
+ self.session = requests.Session()
37
+ self.session.headers.update({
38
+ 'Content-Type': 'application/json',
39
+ })
40
+ if api_key:
41
+ self.session.headers.update({'X-API-Key': api_key})
42
+
43
+ def _request(self, method: str, endpoint: str, data: Optional[Dict] = None) -> Dict[str, Any]:
44
+ """Make HTTP request to API."""
45
+ url = f'{self.base_url}{endpoint}'
46
+
47
+ if method == 'GET':
48
+ response = self.session.get(url)
49
+ elif method == 'POST':
50
+ response = self.session.post(url, json=data)
51
+ elif method == 'DELETE':
52
+ response = self.session.delete(url)
53
+ else:
54
+ raise ValueError(f'Unsupported method: {method}')
55
+
56
+ if response.status_code >= 400:
57
+ try:
58
+ error = response.json()
59
+ raise Exception(f'API Error ({response.status_code}): {error.get("error", response.text)}')
60
+ except:
61
+ raise Exception(f'API Error ({response.status_code}): {response.text}')
62
+
63
+ return response.json()
64
+
65
+ def execute(self, method: str, params: Optional[Dict] = None) -> Dict[str, Any]:
66
+ """Execute a single API command."""
67
+ return self._request('POST', '/api/execute', {
68
+ 'method': method,
69
+ 'params': params or {}
70
+ })
71
+
72
+ def batch(self, commands: List[Dict[str, Any]]) -> Dict[str, Any]:
73
+ """Execute multiple commands in a batch."""
74
+ return self._request('POST', '/api/batch', {
75
+ 'commands': commands
76
+ })
77
+
78
+ def get_schema(self) -> Dict[str, Any]:
79
+ """Get API schema."""
80
+ return self._request('GET', '/api/schema')
81
+
82
+ def get_health(self) -> Dict[str, Any]:
83
+ """Check server health."""
84
+ return self._request('GET', '/api/health')
85
+
86
+ def get_history(self, count: int = 20) -> Dict[str, Any]:
87
+ """Get command history."""
88
+ return self._request('GET', f'/api/history?count={count}')
89
+
90
+ def get_models(self) -> Dict[str, Any]:
91
+ """List all models."""
92
+ return self._request('GET', '/api/models')
93
+
94
+ def get_model(self, model_id: str) -> Dict[str, Any]:
95
+ """Get specific model."""
96
+ return self._request('GET', f'/api/models/{model_id}')
97
+
98
+ def delete_model(self, model_id: str) -> Dict[str, Any]:
99
+ """Delete a model."""
100
+ return self._request('DELETE', f'/api/models/{model_id}')
101
+
102
+
103
+ def example_simple_part(client: CycleCADClient):
104
+ """Example: Create a simple cylindrical part."""
105
+ print("\n" + "="*60)
106
+ print("EXAMPLE 1: Simple Cylindrical Part")
107
+ print("="*60 + "\n")
108
+
109
+ # Start sketch
110
+ print("1. Starting sketch on XY plane...")
111
+ r = client.execute('sketch.start', {'plane': 'XY'})
112
+ print(f" ✓ {r['result']['message']}")
113
+
114
+ # Draw circle
115
+ print("2. Drawing circle (radius 25mm)...")
116
+ r = client.execute('sketch.circle', {
117
+ 'cx': 0,
118
+ 'cy': 0,
119
+ 'radius': 25
120
+ })
121
+ print(f" ✓ Circle created: {r['result']['entityId']}")
122
+ print(f" Area: {r['result']['area']:.2f} mm²")
123
+
124
+ # End sketch and extrude
125
+ print("3. Ending sketch...")
126
+ r = client.execute('sketch.end', {})
127
+ print(f" ✓ {r['result']['message']}")
128
+
129
+ print("4. Extruding to 50mm height...")
130
+ r = client.execute('ops.extrude', {
131
+ 'height': 50,
132
+ 'symmetric': False,
133
+ 'material': 'steel'
134
+ })
135
+ print(f" ✓ Extrusion created: {r['result']['featureId']}")
136
+ print(f" Volume: {r['result']['volume']} mm³")
137
+ print(f" Material: {r['result']['material']}")
138
+
139
+ return r['result']['featureId']
140
+
141
+
142
+ def example_batch_operations(client: CycleCADClient):
143
+ """Example: Create a rectangular part using batch commands."""
144
+ print("\n" + "="*60)
145
+ print("EXAMPLE 2: Batch Operations - Rectangular Part")
146
+ print("="*60 + "\n")
147
+
148
+ commands = [
149
+ {
150
+ 'method': 'sketch.start',
151
+ 'params': {'plane': 'XY'}
152
+ },
153
+ {
154
+ 'method': 'sketch.rect',
155
+ 'params': {'x': 0, 'y': 0, 'width': 60, 'height': 40}
156
+ },
157
+ {
158
+ 'method': 'sketch.end',
159
+ 'params': {}
160
+ },
161
+ {
162
+ 'method': 'ops.extrude',
163
+ 'params': {'height': 30, 'material': 'aluminum'}
164
+ }
165
+ ]
166
+
167
+ print("Executing batch of 4 commands...")
168
+ r = client.batch(commands)
169
+
170
+ if r['ok']:
171
+ print(f"✓ All {r['executed']} commands succeeded in {r['elapsed']}ms")
172
+ for i, result in enumerate(r['results']):
173
+ cmd = commands[i]['method']
174
+ print(f" [{i+1}] {cmd}: {result.get('elapsed', 0)}ms")
175
+ else:
176
+ print(f"✗ Batch failed with {len(r['errors'])} errors")
177
+ for error in r['errors']:
178
+ print(f" [{error['index']}] {error['method']}: {error['error']}")
179
+
180
+
181
+ def example_query_and_validation(client: CycleCADClient):
182
+ """Example: Query model data and validate."""
183
+ print("\n" + "="*60)
184
+ print("EXAMPLE 3: Query and Validation")
185
+ print("="*60 + "\n")
186
+
187
+ # Get available materials
188
+ print("1. Available materials:")
189
+ r = client.execute('query.materials', {})
190
+ for mat in r['result']['materials']:
191
+ print(f" • {mat}")
192
+
193
+ # Get feature list
194
+ print("\n2. Current features:")
195
+ r = client.execute('query.features', {})
196
+ print(f" Total: {r['result']['count']} features")
197
+
198
+ # Validate mass
199
+ print("\n3. Calculating mass for steel part (extrude_...):")
200
+ r = client.execute('validate.mass', {
201
+ 'target': 'extrude_1234567890000',
202
+ 'material': 'steel'
203
+ })
204
+ print(f" Mass: {r['result']['mass']} kg")
205
+
206
+ # Estimate cost
207
+ print("\n4. Estimating manufacturing cost (FDM):")
208
+ r = client.execute('validate.cost', {
209
+ 'target': 'extrude_1234567890000',
210
+ 'process': 'FDM',
211
+ 'material': 'PLA'
212
+ })
213
+ print(f" Estimated cost: ${r['result']['estimatedCost']} USD")
214
+
215
+
216
+ def example_view_operations(client: CycleCADClient):
217
+ """Example: View control commands."""
218
+ print("\n" + "="*60)
219
+ print("EXAMPLE 4: View Operations")
220
+ print("="*60 + "\n")
221
+
222
+ views = ['isometric', 'top', 'front', 'right']
223
+
224
+ for view in views:
225
+ print(f"Setting view to: {view}")
226
+ r = client.execute('view.set', {'view': view})
227
+ print(f" ✓ {r['result']['message']}\n")
228
+
229
+
230
+ def example_export(client: CycleCADClient):
231
+ """Example: Export operations."""
232
+ print("\n" + "="*60)
233
+ print("EXAMPLE 5: Export Operations")
234
+ print("="*60 + "\n")
235
+
236
+ formats = [
237
+ ('stl', {'filename': 'part.stl', 'binary': True}),
238
+ ('obj', {'filename': 'part.obj'}),
239
+ ('gltf', {'filename': 'part.gltf'})
240
+ ]
241
+
242
+ for fmt, params in formats:
243
+ print(f"Exporting to {fmt.upper()}:")
244
+ r = client.execute(f'export.{fmt}', params)
245
+ if r['ok']:
246
+ print(f" ✓ {r['result']['message']}")
247
+ print(f" Filename: {r['result']['filename']}\n")
248
+ else:
249
+ print(f" ✗ Error: {r['error']}\n")
250
+
251
+
252
+ def example_server_info(client: CycleCADClient):
253
+ """Example: Get server information."""
254
+ print("\n" + "="*60)
255
+ print("EXAMPLE 6: Server Information")
256
+ print("="*60 + "\n")
257
+
258
+ print("1. Health check:")
259
+ health = client.get_health()
260
+ print(f" Status: {health['status']}")
261
+ print(f" Version: {health['version']}")
262
+ print(f" Uptime: {health['uptime']} seconds")
263
+ print(f" Commands available: {health['commands']}")
264
+ print(f" Commands executed: {health['commandsExecuted']}")
265
+ print(f" Session ID: {health['sessionId']}")
266
+
267
+ print("\n2. API Schema (first 5 commands):")
268
+ schema = client.get_schema()
269
+ count = 0
270
+ for namespace, data in schema['namespaces'].items():
271
+ print(f"\n Namespace: {namespace}")
272
+ print(f" {data.get('description', 'N/A')}")
273
+ for cmd_name in list(data['commands'].keys())[:3]:
274
+ cmd = data['commands'][cmd_name]
275
+ print(f" • {cmd['method']}")
276
+ count += 1
277
+ if count >= 5:
278
+ break
279
+ if count >= 5:
280
+ break
281
+
282
+ print(f"\n ... and {schema['totalCommands'] - count} more commands")
283
+
284
+ print("\n3. Command history (last 5 commands):")
285
+ history = client.get_history(count=5)
286
+ print(f" Total executed: {history['total']}")
287
+ for entry in history['recent']:
288
+ status = '✓' if entry['ok'] else '✗'
289
+ print(f" [{status}] {entry['method']} ({entry['elapsed']}ms)")
290
+
291
+
292
+ def main():
293
+ parser = argparse.ArgumentParser(
294
+ description='cycleCAD API Client Example'
295
+ )
296
+ parser.add_argument('--host', default='localhost', help='Server host (default: localhost)')
297
+ parser.add_argument('--port', type=int, default=3000, help='Server port (default: 3000)')
298
+ parser.add_argument('--api-key', help='API key for authentication (optional)')
299
+ parser.add_argument('--example', choices=[
300
+ 'all', 'simple', 'batch', 'query', 'view', 'export', 'info'
301
+ ], default='all', help='Which example to run')
302
+
303
+ args = parser.parse_args()
304
+
305
+ print("\n" + "█"*60)
306
+ print("█ cycleCAD API Client — Example Usage")
307
+ print("█"*60)
308
+ print(f"\nConnecting to {args.host}:{args.port}...")
309
+
310
+ try:
311
+ client = CycleCADClient(
312
+ host=args.host,
313
+ port=args.port,
314
+ api_key=args.api_key
315
+ )
316
+
317
+ # Test connection
318
+ health = client.get_health()
319
+ print(f"✓ Connected to cycleCAD API v{health['version']}\n")
320
+
321
+ # Run examples
322
+ examples = {
323
+ 'all': [
324
+ example_server_info,
325
+ example_simple_part,
326
+ example_batch_operations,
327
+ example_query_and_validation,
328
+ example_view_operations,
329
+ example_export
330
+ ],
331
+ 'simple': [example_simple_part],
332
+ 'batch': [example_batch_operations],
333
+ 'query': [example_query_and_validation],
334
+ 'view': [example_view_operations],
335
+ 'export': [example_export],
336
+ 'info': [example_server_info]
337
+ }
338
+
339
+ for example_fn in examples[args.example]:
340
+ try:
341
+ example_fn(client)
342
+ except Exception as e:
343
+ print(f"\n✗ Example failed: {e}")
344
+
345
+ print("\n" + "█"*60)
346
+ print("█ Examples completed!")
347
+ print("█"*60 + "\n")
348
+
349
+ except Exception as e:
350
+ print(f"\n✗ Connection failed: {e}")
351
+ print("\nMake sure the API server is running:")
352
+ print(f" npm run server (from {args.host}:{args.port})")
353
+ return 1
354
+
355
+ return 0
356
+
357
+
358
+ if __name__ == '__main__':
359
+ exit(main())
@@ -0,0 +1,28 @@
1
+ # Manufacturing analysis workflow
2
+ # Run with: ./bin/cyclecad-cli.js --batch examples/batch-manufacturing.txt
3
+
4
+ # Create a bracket shape
5
+ sketch.start --plane XY
6
+ sketch.rect --x 0 --y 0 --width 80 --height 40
7
+ sketch.end
8
+
9
+ # Extrude to create a base
10
+ feature.extrude --height 15
11
+
12
+ # Add a fillet for manufacturing
13
+ feature.fillet --radius 2 --edges all
14
+
15
+ # Check if it's manufacturable
16
+ validate.printability --target extrude_1 --process CNC
17
+
18
+ # Estimate material cost
19
+ validate.cost --target extrude_1 --process CNC --material aluminum
20
+
21
+ # Estimate weight
22
+ validate.mass --target extrude_1 --material aluminum
23
+
24
+ # Design review
25
+ validate.designReview --target extrude_1
26
+
27
+ # Export for manufacturing
28
+ export.stl --filename bracket-cad.stl --binary true
@@ -0,0 +1,26 @@
1
+ # Simple batch script for cycleCAD CLI
2
+ # Run with: ./bin/cyclecad-cli.js --batch examples/batch-simple.txt
3
+
4
+ # Create a cylinder
5
+ shape.cylinder --radius 25 --height 80
6
+
7
+ # Create a box
8
+ shape.box --width 50 --height 40 --depth 30
9
+
10
+ # Start a sketch
11
+ sketch.start --plane XY
12
+
13
+ # Add a circle to the sketch
14
+ sketch.circle --cx 0 --cy 0 --radius 15
15
+
16
+ # End the sketch
17
+ sketch.end
18
+
19
+ # Extrude the sketch
20
+ feature.extrude --height 10
21
+
22
+ # Check dimensions
23
+ validate.dimensions --target extrude_1
24
+
25
+ # Export to STL
26
+ export.stl --filename my-part.stl