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.
- package/API-BUILD-MANIFEST.txt +339 -0
- package/API-SERVER.md +535 -0
- package/Architecture-Deck.pptx +0 -0
- package/CLAUDE.md +172 -11
- package/CLI-BUILD-SUMMARY.md +504 -0
- package/CLI-INDEX.md +356 -0
- package/CLI-README.md +466 -0
- package/COLLABORATION-INTEGRATION-GUIDE.md +325 -0
- package/CONNECTED_FABS_GUIDE.md +612 -0
- package/CONNECTED_FABS_README.md +310 -0
- package/DELIVERABLES.md +343 -0
- package/DFM-ANALYZER-INTEGRATION.md +368 -0
- package/DFM-QUICK-START.js +253 -0
- package/Dockerfile +69 -0
- package/IMPLEMENTATION.md +327 -0
- package/LICENSE +31 -0
- package/MARKETPLACE_QUICK_REFERENCE.txt +294 -0
- package/MCP-INDEX.md +264 -0
- package/QUICKSTART-API.md +388 -0
- package/QUICKSTART-CLI.md +211 -0
- package/QUICKSTART-MCP.md +196 -0
- package/README-MCP.md +208 -0
- package/TEST-TOKEN-ENGINE.md +319 -0
- package/TOKEN-ENGINE-SUMMARY.md +266 -0
- package/TOKENS-README.md +263 -0
- package/TOOLS-REFERENCE.md +254 -0
- package/app/index.html +373 -3
- package/app/js/TOKEN-INTEGRATION.md +391 -0
- package/app/js/agent-api.js +3 -3
- package/app/js/ai-copilot.js +1435 -0
- package/app/js/cad-vr.js +917 -0
- package/app/js/cam-operations.js +638 -0
- package/app/js/cam-pipeline.js +840 -0
- package/app/js/collaboration-ui.js +995 -0
- package/app/js/collaboration.js +1116 -0
- package/app/js/connected-fabs-example.js +404 -0
- package/app/js/connected-fabs.js +1449 -0
- package/app/js/dfm-analyzer.js +1760 -0
- package/app/js/gcode-generator.js +485 -0
- package/app/js/gdt-training.js +1144 -0
- package/app/js/machine-profiles.js +534 -0
- package/app/js/marketplace-v2.js +766 -0
- package/app/js/marketplace.js +1994 -0
- package/app/js/material-library.js +2115 -0
- package/app/js/misumi-catalog.js +904 -0
- package/app/js/section-view.js +666 -0
- package/app/js/sketch-enhance.js +779 -0
- package/app/js/stock-manager.js +482 -0
- package/app/js/text-to-cad.js +806 -0
- package/app/js/token-dashboard.js +563 -0
- package/app/js/token-engine.js +743 -0
- package/app/js/tool-library.js +593 -0
- package/app/test-agent.html +1801 -0
- package/app/tutorials/advanced.html +1924 -0
- package/app/tutorials/basic.html +1160 -0
- package/app/tutorials/intermediate.html +1456 -0
- package/bin/cyclecad-cli.js +662 -0
- package/bin/cyclecad-mcp +2 -0
- package/bin/server.js +242 -0
- package/cycleCAD-Architecture.pptx +0 -0
- package/cycleCAD-Investor-Deck.pptx +0 -0
- package/demo-mcp.sh +60 -0
- package/docs/API-SERVER-SUMMARY.md +375 -0
- package/docs/API-SERVER.md +667 -0
- package/docs/CAM-EXAMPLES.md +344 -0
- package/docs/CAM-INTEGRATION.md +612 -0
- package/docs/CAM-QUICK-REFERENCE.md +199 -0
- package/docs/CLI-INTEGRATION.md +510 -0
- package/docs/CLI.md +872 -0
- package/docs/MARKETPLACE-API-SCHEMA.json +564 -0
- package/docs/MARKETPLACE-INTEGRATION.md +467 -0
- package/docs/MARKETPLACE-SETUP.html +439 -0
- package/docs/MCP-SERVER.md +403 -0
- package/examples/api-client-example.js +488 -0
- package/examples/api-client-example.py +359 -0
- package/examples/batch-manufacturing.txt +28 -0
- package/examples/batch-simple.txt +26 -0
- package/linkedin-post-combined.md +31 -0
- package/model-marketplace.html +1273 -0
- package/package.json +14 -3
- package/server/api-server.js +1120 -0
- package/server/mcp-server.js +1161 -0
- package/test-api-server.js +432 -0
- package/test-mcp.js +198 -0
- package/~$cycleCAD-Investor-Deck.pptx +0 -0
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
# Connected Fabs Module Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
The Connected Fabs module (`app/js/connected-fabs.js`) implements the "CAD → CAM → Connected Fabs" pipeline from the architecture slide 10. It connects cycleCAD designs to a distributed network of manufacturing partners worldwide.
|
|
5
|
+
|
|
6
|
+
**Module size:** 1,449 lines
|
|
7
|
+
**Key features:** Fab registry, smart routing, job submission, token escrow, webhook simulation
|
|
8
|
+
**Storage:** localStorage (`cyclecad_fab_registry`, `cyclecad_fab_jobs`)
|
|
9
|
+
**Integration:** Hooks into `window.cycleCAD.tokens` for escrow management
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### 1. Load the Module
|
|
16
|
+
Add to `app/index.html` in the `<head>` after other module scripts:
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<script src="js/connected-fabs.js"></script>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### 2. Access the API
|
|
23
|
+
```javascript
|
|
24
|
+
// List all fabs
|
|
25
|
+
window.cycleCAD.fabs.listFabs();
|
|
26
|
+
|
|
27
|
+
// Find best fab for a job
|
|
28
|
+
const results = window.cycleCAD.fabs.findBestFab({
|
|
29
|
+
capability: 'cnc_5axis',
|
|
30
|
+
material: 'aluminum',
|
|
31
|
+
partSize: { x: 500, y: 400, z: 200 },
|
|
32
|
+
maxLeadTime: 5
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Submit a manufacturing job
|
|
36
|
+
const job = window.cycleCAD.fabs.submitJob({
|
|
37
|
+
name: 'Bracket Assembly',
|
|
38
|
+
capability: 'cnc_3axis',
|
|
39
|
+
material: 'steel',
|
|
40
|
+
partSize: { x: 150, y: 100, z: 75 },
|
|
41
|
+
quantity: 10,
|
|
42
|
+
urgency: 'standard',
|
|
43
|
+
description: 'High-precision bracket for automotive'
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// Toggle UI panel
|
|
47
|
+
window.cycleCAD.fabs.togglePanel();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## API Reference
|
|
53
|
+
|
|
54
|
+
### Fab Management
|
|
55
|
+
|
|
56
|
+
#### `registerFab(fabData)`
|
|
57
|
+
Register a new fab shop in the network.
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
const fab = window.cycleCAD.fabs.registerFab({
|
|
61
|
+
name: 'My CNC Shop',
|
|
62
|
+
location: { city: 'Berlin', country: 'DE', lat: 52.52, lng: 13.41 },
|
|
63
|
+
capabilities: ['cnc_3axis', 'cnc_5axis'],
|
|
64
|
+
materials: ['aluminum', 'steel'],
|
|
65
|
+
maxPartSize: { x: 500, y: 500, z: 300 },
|
|
66
|
+
pricing: { cnc_3axis: 0.08, cnc_5axis: 0.15 },
|
|
67
|
+
leadTime: { standard: 5, express: 2 },
|
|
68
|
+
rating: 4.8,
|
|
69
|
+
reviews: 100,
|
|
70
|
+
certifications: ['ISO 9001'],
|
|
71
|
+
description: 'Precision CNC machining'
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### `listFabs(filters?)`
|
|
76
|
+
Get all fabs with optional filtering.
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
// Get all fabs
|
|
80
|
+
window.cycleCAD.fabs.listFabs();
|
|
81
|
+
|
|
82
|
+
// Filter by capability
|
|
83
|
+
window.cycleCAD.fabs.listFabs({ capability: '3d_print_fdm' });
|
|
84
|
+
|
|
85
|
+
// Filter by multiple criteria
|
|
86
|
+
window.cycleCAD.fabs.listFabs({
|
|
87
|
+
capability: 'cnc_5axis',
|
|
88
|
+
country: 'DE',
|
|
89
|
+
minRating: 4.5,
|
|
90
|
+
material: 'titanium'
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
#### `getFab(fabId)`
|
|
95
|
+
Get a specific fab by ID.
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
const fab = window.cycleCAD.fabs.getFab('fab_001');
|
|
99
|
+
console.log(fab.name, fab.rating, fab.capabilities);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### `updateFab(fabId, updates)`
|
|
103
|
+
Update fab information.
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
window.cycleCAD.fabs.updateFab('fab_001', {
|
|
107
|
+
rating: 4.9,
|
|
108
|
+
reviews: 150,
|
|
109
|
+
leadTime: { standard: 4, express: 1 }
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### `removeFab(fabId)`
|
|
114
|
+
Deregister a fab from the network.
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
window.cycleCAD.fabs.removeFab('fab_001');
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
### Smart Routing & Quoting
|
|
123
|
+
|
|
124
|
+
#### `findBestFab(requirements)`
|
|
125
|
+
Find the best fab(s) for a manufacturing job. Returns ranked list with scoring.
|
|
126
|
+
|
|
127
|
+
**Scoring factors:**
|
|
128
|
+
- Capability match (required)
|
|
129
|
+
- Material availability
|
|
130
|
+
- Part size fit
|
|
131
|
+
- Price competitiveness
|
|
132
|
+
- Lead time
|
|
133
|
+
- Rating/reviews
|
|
134
|
+
- Distance (if user location provided)
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
const results = window.cycleCAD.fabs.findBestFab({
|
|
138
|
+
capability: 'cnc_5axis', // REQUIRED
|
|
139
|
+
material: 'titanium', // optional
|
|
140
|
+
partSize: { x: 400, y: 300, z: 250 }, // optional
|
|
141
|
+
quantity: 5, // optional
|
|
142
|
+
maxPrice: 0.20, // optional € per unit
|
|
143
|
+
maxLeadTime: 10, // optional days
|
|
144
|
+
userLocation: { lat: 48.14, lng: 11.58 } // optional for distance
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Returns: [{ fab, score, distance }, { fab, score, distance }, ...]
|
|
148
|
+
// fab = best match, score = ranking score, distance = km from user
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### `getQuote(fabId, jobData)`
|
|
152
|
+
Get a price quote from a specific fab.
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
const quote = window.cycleCAD.fabs.getQuote('fab_001', {
|
|
156
|
+
capability: 'cnc_5axis',
|
|
157
|
+
partSize: { x: 400, y: 300, z: 250 },
|
|
158
|
+
quantity: 10,
|
|
159
|
+
material: 'aluminum',
|
|
160
|
+
urgency: 'express' // standard | express
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Returns:
|
|
164
|
+
// {
|
|
165
|
+
// fabId: 'fab_001',
|
|
166
|
+
// fabName: 'Lyon Precision',
|
|
167
|
+
// basePrice: 0.16,
|
|
168
|
+
// totalCost: 24.96,
|
|
169
|
+
// currency: '€',
|
|
170
|
+
// leadDays: 3,
|
|
171
|
+
// material: 'aluminum',
|
|
172
|
+
// capability: 'CNC 5-Axis'
|
|
173
|
+
// }
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### Job Management
|
|
179
|
+
|
|
180
|
+
#### `submitJob(jobData)`
|
|
181
|
+
Submit a manufacturing job. Automatically routes to best fab and creates token escrow.
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
const job = window.cycleCAD.fabs.submitJob({
|
|
185
|
+
name: 'Bracket Assembly',
|
|
186
|
+
capability: 'cnc_3axis',
|
|
187
|
+
material: 'steel',
|
|
188
|
+
partSize: { x: 150, y: 100, z: 75 },
|
|
189
|
+
quantity: 10,
|
|
190
|
+
urgency: 'standard', // standard | express
|
|
191
|
+
description: 'Precision bracket',
|
|
192
|
+
userLocation: { lat: 48.2, lng: 16.4 }, // optional for routing
|
|
193
|
+
fabricFile: 'assembly_v2.step' // optional reference
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Job lifecycle: DRAFT → SUBMITTED → ACCEPTED → IN_PROGRESS → QC → SHIPPED → DELIVERED → COMPLETED
|
|
197
|
+
|
|
198
|
+
// Returns job object with cost in tokens and escrow ID
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
#### `getJob(jobId)`
|
|
202
|
+
Get job details.
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
const job = window.cycleCAD.fabs.getJob('job_1');
|
|
206
|
+
console.log(job.status, job.fabName, job.costInTokens);
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
#### `listJobs(filters?)`
|
|
210
|
+
List all jobs with optional filtering.
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
// Get all jobs
|
|
214
|
+
window.cycleCAD.fabs.listJobs();
|
|
215
|
+
|
|
216
|
+
// Filter by status
|
|
217
|
+
window.cycleCAD.fabs.listJobs({ status: 'IN_PROGRESS' });
|
|
218
|
+
|
|
219
|
+
// Filter by fab
|
|
220
|
+
window.cycleCAD.fabs.listJobs({ fabId: 'fab_001' });
|
|
221
|
+
|
|
222
|
+
// Filter by material
|
|
223
|
+
window.cycleCAD.fabs.listJobs({ material: 'aluminum' });
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### `cancelJob(jobId)`
|
|
227
|
+
Cancel a submitted job and release token escrow.
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
const job = window.cycleCAD.fabs.cancelJob('job_1');
|
|
231
|
+
// Only works if job is still in SUBMITTED state
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
#### `rateJob(jobId, rating, review?)`
|
|
235
|
+
Rate a completed job and update fab ratings.
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
window.cycleCAD.fabs.rateJob('job_1', 5, 'Excellent quality! Exactly as specified.');
|
|
239
|
+
|
|
240
|
+
// Rating updates fab's overall rating
|
|
241
|
+
// Fab rating = (oldRating * oldReviewCount + newRating) / (oldReviewCount + 1)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
### Webhook System
|
|
247
|
+
|
|
248
|
+
#### `simulateWebhook(fabId, jobId, event, data?)`
|
|
249
|
+
Simulate a webhook event from a fab (status update). In production, fabs POST to your webhook endpoint.
|
|
250
|
+
|
|
251
|
+
**Valid events:**
|
|
252
|
+
- `job.accepted` → Status: ACCEPTED
|
|
253
|
+
- `job.started` → Status: IN_PROGRESS
|
|
254
|
+
- `job.qc_passed` → Status: QC
|
|
255
|
+
- `job.shipped` → Status: SHIPPED
|
|
256
|
+
- `job.delivered` → Status: DELIVERED
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
// Fab accepts the job
|
|
260
|
+
window.cycleCAD.fabs.simulateWebhook('fab_001', 'job_1', 'job.accepted', {
|
|
261
|
+
acceptedAt: new Date().toISOString(),
|
|
262
|
+
estimatedDelivery: '2026-04-15'
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
// Fab starts manufacturing
|
|
266
|
+
window.cycleCAD.fabs.simulateWebhook('fab_001', 'job_1', 'job.started', {
|
|
267
|
+
toolpath: 'part_001.nc',
|
|
268
|
+
machineId: 'cnc_5'
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Quality check passes
|
|
272
|
+
window.cycleCAD.fabs.simulateWebhook('fab_001', 'job_1', 'job.qc_passed', {
|
|
273
|
+
toleranceCheck: 'PASS',
|
|
274
|
+
surfaceFinish: 'Ra 1.6µm'
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Job ships
|
|
278
|
+
window.cycleCAD.fabs.simulateWebhook('fab_001', 'job_1', 'job.shipped', {
|
|
279
|
+
trackingNumber: 'DHL123456789',
|
|
280
|
+
carrier: 'DHL',
|
|
281
|
+
estimatedDelivery: '2026-04-18'
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// Job delivered
|
|
285
|
+
window.cycleCAD.fabs.simulateWebhook('fab_001', 'job_1', 'job.delivered', {
|
|
286
|
+
signedBy: 'John Doe',
|
|
287
|
+
condition: 'GOOD'
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
#### `getWebhookLog(jobId)`
|
|
292
|
+
Get all webhook events for a job (audit trail).
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
const events = window.cycleCAD.fabs.getWebhookLog('job_1');
|
|
296
|
+
// Returns: [
|
|
297
|
+
// { event: 'job.accepted', timestamp: '2026-03-27T...', data: {...}, fabName: '...' },
|
|
298
|
+
// { event: 'job.started', timestamp: '2026-03-28T...', data: {...}, fabName: '...' },
|
|
299
|
+
// ...
|
|
300
|
+
// ]
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
### UI Panel
|
|
306
|
+
|
|
307
|
+
#### `togglePanel()`
|
|
308
|
+
Show/hide the Connected Fabs UI panel. Panel has 4 tabs:
|
|
309
|
+
1. **Browse Fabs** — Search and filter fab network
|
|
310
|
+
2. **Submit Job** — Create new manufacturing job
|
|
311
|
+
3. **My Jobs** — Track submitted jobs
|
|
312
|
+
4. **Dashboard** — Network stats and job analytics
|
|
313
|
+
|
|
314
|
+
```javascript
|
|
315
|
+
window.cycleCAD.fabs.togglePanel();
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### `switchTab(tabName)`
|
|
319
|
+
Programmatically switch panels.
|
|
320
|
+
|
|
321
|
+
```javascript
|
|
322
|
+
window.cycleCAD.fabs.switchTab('fabs'); // Browse Fabs
|
|
323
|
+
window.cycleCAD.fabs.switchTab('submit'); // Submit Job
|
|
324
|
+
window.cycleCAD.fabs.switchTab('jobs'); // My Jobs
|
|
325
|
+
window.cycleCAD.fabs.switchTab('dashboard'); // Dashboard
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
### Events
|
|
331
|
+
|
|
332
|
+
#### `on(event, listener)`
|
|
333
|
+
Listen for module events.
|
|
334
|
+
|
|
335
|
+
**Events:**
|
|
336
|
+
- `fab-registered` — New fab added to network
|
|
337
|
+
- `fab-updated` — Fab info updated
|
|
338
|
+
- `fab-removed` — Fab removed from network
|
|
339
|
+
- `job-submitted` — New job created
|
|
340
|
+
- `job-status-changed` — Job status updated (webhook event)
|
|
341
|
+
- `job-cancelled` — Job cancelled
|
|
342
|
+
- `job-rated` — Job rated
|
|
343
|
+
|
|
344
|
+
```javascript
|
|
345
|
+
// Listen for new jobs
|
|
346
|
+
window.cycleCAD.fabs.on('job-submitted', (data) => {
|
|
347
|
+
console.log(`Job ${data.jobId} submitted to ${data.fabName}`);
|
|
348
|
+
console.log(`Cost: ${data.costInTokens} tokens`);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// Listen for status changes
|
|
352
|
+
window.cycleCAD.fabs.on('job-status-changed', (data) => {
|
|
353
|
+
console.log(`Job ${data.jobId}: ${data.oldStatus} → ${data.newStatus}`);
|
|
354
|
+
notifyUser(`Job update: ${data.event}`);
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
// Listen for new fabs joining network
|
|
358
|
+
window.cycleCAD.fabs.on('fab-registered', (data) => {
|
|
359
|
+
console.log(`New fab added: ${data.name}`);
|
|
360
|
+
});
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
#### `off(event, listener)`
|
|
364
|
+
Remove an event listener.
|
|
365
|
+
|
|
366
|
+
```javascript
|
|
367
|
+
const handler = (data) => console.log(data);
|
|
368
|
+
window.cycleCAD.fabs.on('job-submitted', handler);
|
|
369
|
+
window.cycleCAD.fabs.off('job-submitted', handler); // Stop listening
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Manufacturing Types
|
|
375
|
+
|
|
376
|
+
Supported manufacturing processes with token costs:
|
|
377
|
+
|
|
378
|
+
| Type | Code | Cost (tokens) | Unit |
|
|
379
|
+
|------|------|---------------|------|
|
|
380
|
+
| 3D Print (FDM) | `3d_print_fdm` | 25 | per job |
|
|
381
|
+
| 3D Print (SLA) | `3d_print_sla` | 35 | per job |
|
|
382
|
+
| 3D Print (SLS) | `3d_print_sls` | 30 | per job |
|
|
383
|
+
| Laser Cut | `laser_cut` | 15 | per job |
|
|
384
|
+
| CNC 3-Axis | `cnc_3axis` | 60 | per job |
|
|
385
|
+
| CNC 5-Axis | `cnc_5axis` | 100 | per job |
|
|
386
|
+
| CNC Lathe | `cnc_lathe` | 40 | per job |
|
|
387
|
+
| Injection Mold | `injection_mold` | 250 | per job |
|
|
388
|
+
| Sheet Metal | `sheet_metal` | 45 | per job |
|
|
389
|
+
| PCB Manufacturing | `pcb_mfg` | 50 | per job |
|
|
390
|
+
| Waterjet Cut | `waterjet_cut` | 50 | per job |
|
|
391
|
+
| Sheet Bending | `bending` | 35 | per job |
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Demo Fabs
|
|
396
|
+
|
|
397
|
+
The module pre-loads 8 real-world demo fab shops:
|
|
398
|
+
|
|
399
|
+
1. **Berlin CNC Works** (DE) — CNC 3/5-axis, laser, 4.7★
|
|
400
|
+
2. **Munich Additive** (DE) — FDM/SLA/SLS 3D print, 4.8★
|
|
401
|
+
3. **Rotterdam Metal** (NL) — CNC, lathe, sheet metal, 4.5★
|
|
402
|
+
4. **Lyon Precision** (FR) — CNC 5-axis, aerospace, 4.9★
|
|
403
|
+
5. **Milano Rapid** (IT) — SLA/SLS, injection mold, 4.6★
|
|
404
|
+
6. **Barcelona Sheet** (ES) — Laser, bending, waterjet, 4.4★
|
|
405
|
+
7. **Prague PCB** (CZ) — PCB manufacturing, 4.3★
|
|
406
|
+
8. **Vienna Mold** (AT) — Injection molding, 4.7★
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Integration with Token Engine
|
|
411
|
+
|
|
412
|
+
The Connected Fabs module integrates with `window.cycleCAD.tokens` for escrow management:
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
// When a job is submitted:
|
|
416
|
+
// 1. Calculate cost in tokens based on manufacturing type
|
|
417
|
+
// 2. Create token escrow via tokens.createEscrow()
|
|
418
|
+
// 3. Store escrowId in job record
|
|
419
|
+
// 4. On job completion, release escrow: tokens.releaseEscrow()
|
|
420
|
+
// 5. On job cancellation, cancel escrow: tokens.cancelEscrow()
|
|
421
|
+
|
|
422
|
+
// Example:
|
|
423
|
+
const escrow = window.cycleCAD.tokens.createEscrow(
|
|
424
|
+
100, // tokens to hold
|
|
425
|
+
'job_1', // jobId
|
|
426
|
+
'fab_001', // fabId
|
|
427
|
+
{ jobName: 'Bracket', manufacturingType: 'cnc_5axis' }
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
// Later, when job completes:
|
|
431
|
+
window.cycleCAD.tokens.releaseEscrow(escrow.id);
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Storage & Persistence
|
|
437
|
+
|
|
438
|
+
All data persists in localStorage:
|
|
439
|
+
|
|
440
|
+
- **`cyclecad_fab_registry`** — Array of fab objects
|
|
441
|
+
- **`cyclecad_fab_jobs`** — Object of { jobId: job }
|
|
442
|
+
- **`cyclecad_job_counter`** — Auto-incrementing job ID counter
|
|
443
|
+
|
|
444
|
+
To reset:
|
|
445
|
+
```javascript
|
|
446
|
+
localStorage.removeItem('cyclecad_fab_registry');
|
|
447
|
+
localStorage.removeItem('cyclecad_fab_jobs');
|
|
448
|
+
localStorage.removeItem('cyclecad_job_counter');
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Example Workflow
|
|
454
|
+
|
|
455
|
+
### 1. User designs a part in cycleCAD
|
|
456
|
+
```javascript
|
|
457
|
+
// User creates a bracket in the 3D viewport
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### 2. User exports as STL and submits job
|
|
461
|
+
```javascript
|
|
462
|
+
const job = window.cycleCAD.fabs.submitJob({
|
|
463
|
+
name: 'Bracket Assembly',
|
|
464
|
+
capability: 'cnc_5axis',
|
|
465
|
+
material: 'aluminum',
|
|
466
|
+
partSize: { x: 200, y: 150, z: 100 },
|
|
467
|
+
quantity: 10,
|
|
468
|
+
urgency: 'standard',
|
|
469
|
+
description: 'High-precision aerospace bracket'
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
console.log(`Job ${job.id} cost: ${job.costInTokens} tokens`);
|
|
473
|
+
console.log(`Routed to: ${job.fabName}`);
|
|
474
|
+
console.log(`Lead time: ${job.quote.leadDays} days`);
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### 3. User tracks job in My Jobs tab
|
|
478
|
+
```javascript
|
|
479
|
+
window.cycleCAD.fabs.switchTab('jobs');
|
|
480
|
+
// Shows job in SUBMITTED state
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### 4. Fab accepts job (webhook event)
|
|
484
|
+
```javascript
|
|
485
|
+
// In real system, fab would POST to webhook
|
|
486
|
+
// For demo, we simulate:
|
|
487
|
+
window.cycleCAD.fabs.simulateWebhook('fab_004', job.id, 'job.accepted', {
|
|
488
|
+
acceptedAt: new Date().toISOString()
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// Job now shows as ACCEPTED
|
|
492
|
+
// Listen for status change:
|
|
493
|
+
window.cycleCAD.fabs.on('job-status-changed', (data) => {
|
|
494
|
+
console.log(`Status: ${data.newStatus}`);
|
|
495
|
+
updateUI();
|
|
496
|
+
});
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### 5. Fab manufactures part (multiple webhooks)
|
|
500
|
+
```javascript
|
|
501
|
+
// job.started
|
|
502
|
+
window.cycleCAD.fabs.simulateWebhook('fab_004', job.id, 'job.started');
|
|
503
|
+
|
|
504
|
+
// job.qc_passed
|
|
505
|
+
window.cycleCAD.fabs.simulateWebhook('fab_004', job.id, 'job.qc_passed', {
|
|
506
|
+
toleranceCheck: 'PASS'
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
// job.shipped
|
|
510
|
+
window.cycleCAD.fabs.simulateWebhook('fab_004', job.id, 'job.shipped', {
|
|
511
|
+
trackingNumber: 'DHL12345'
|
|
512
|
+
});
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
### 6. Job delivered
|
|
516
|
+
```javascript
|
|
517
|
+
window.cycleCAD.fabs.simulateWebhook('fab_004', job.id, 'job.delivered');
|
|
518
|
+
|
|
519
|
+
// User rates the fab
|
|
520
|
+
window.cycleCAD.fabs.rateJob(job.id, 5, 'Perfect quality! Exactly as specified.');
|
|
521
|
+
|
|
522
|
+
// Token escrow is released and fab gets paid
|
|
523
|
+
window.cycleCAD.tokens.releaseEscrow(job.escrowId);
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
## Architecture Notes
|
|
529
|
+
|
|
530
|
+
### Design Principles
|
|
531
|
+
1. **Agent-First** — All operations return structured JSON (no DOM dependencies)
|
|
532
|
+
2. **Token-Aware** — Every job holds tokens in escrow until completion
|
|
533
|
+
3. **Decentralized** — Fabs are just data; no central server required
|
|
534
|
+
4. **Observable** — Full event system for UI synchronization
|
|
535
|
+
5. **Persistent** — All state survives page reload
|
|
536
|
+
|
|
537
|
+
### Scoring Algorithm
|
|
538
|
+
The `findBestFab()` function ranks candidates on:
|
|
539
|
+
- Capability match (required)
|
|
540
|
+
- Material availability (+20 points)
|
|
541
|
+
- Rating (+5 per star)
|
|
542
|
+
- Lead time match (+30 if within maxLeadTime)
|
|
543
|
+
- Price competitiveness (+15 if under maxPrice)
|
|
544
|
+
- Distance penalty (-1 per 100km from user)
|
|
545
|
+
|
|
546
|
+
Higher score = better match.
|
|
547
|
+
|
|
548
|
+
### Job State Machine
|
|
549
|
+
```
|
|
550
|
+
DRAFT ──submit──> SUBMITTED ──webhook: job.accepted──> ACCEPTED
|
|
551
|
+
││
|
|
552
|
+
├──webhook: job.started──> IN_PROGRESS
|
|
553
|
+
├──webhook: job.qc_passed──> QC
|
|
554
|
+
├──webhook: job.shipped──> SHIPPED
|
|
555
|
+
├──webhook: job.delivered──> DELIVERED
|
|
556
|
+
└──complete──> COMPLETED
|
|
557
|
+
|
|
558
|
+
SUBMITTED ──user cancel──> CANCELLED
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## Testing
|
|
564
|
+
|
|
565
|
+
```javascript
|
|
566
|
+
// List all fabs
|
|
567
|
+
console.log(window.cycleCAD.fabs.listFabs());
|
|
568
|
+
|
|
569
|
+
// Submit a test job
|
|
570
|
+
const job = window.cycleCAD.fabs.submitJob({
|
|
571
|
+
name: 'Test Part',
|
|
572
|
+
capability: 'cnc_3axis',
|
|
573
|
+
material: 'aluminum',
|
|
574
|
+
partSize: { x: 100, y: 100, z: 50 },
|
|
575
|
+
quantity: 1,
|
|
576
|
+
urgency: 'standard'
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
// Simulate full lifecycle
|
|
580
|
+
window.cycleCAD.fabs.simulateWebhook(job.fabId, job.id, 'job.accepted');
|
|
581
|
+
window.cycleCAD.fabs.simulateWebhook(job.fabId, job.id, 'job.started');
|
|
582
|
+
window.cycleCAD.fabs.simulateWebhook(job.fabId, job.id, 'job.qc_passed');
|
|
583
|
+
window.cycleCAD.fabs.simulateWebhook(job.fabId, job.id, 'job.shipped');
|
|
584
|
+
window.cycleCAD.fabs.simulateWebhook(job.fabId, job.id, 'job.delivered');
|
|
585
|
+
|
|
586
|
+
// View job details
|
|
587
|
+
console.log(window.cycleCAD.fabs.getJob(job.id));
|
|
588
|
+
|
|
589
|
+
// View webhook log
|
|
590
|
+
console.log(window.cycleCAD.fabs.getWebhookLog(job.id));
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
---
|
|
594
|
+
|
|
595
|
+
## Future Enhancements
|
|
596
|
+
|
|
597
|
+
1. **Real Webhook Integration** — POST to external fab APIs
|
|
598
|
+
2. **Payment Integration** — Stripe/crypto for token redemption
|
|
599
|
+
3. **Capacity Planning** — Fab load balancing and scheduling
|
|
600
|
+
4. **Quality Tracking** — Post-delivery QC metrics
|
|
601
|
+
5. **Vendor Management** — Custom pricing tiers, SLAs
|
|
602
|
+
6. **Analytics Dashboard** — Cost trends, delivery times, fab ratings
|
|
603
|
+
7. **API Gateway** — REST/GraphQL interface for external agents
|
|
604
|
+
8. **Multi-user Collaboration** — Shared job tracking across teams
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
## License & Attribution
|
|
609
|
+
|
|
610
|
+
Part of cycleCAD — Agent-First OS for Manufacturing
|
|
611
|
+
(c) 2026 Sachin Kumar / cycleWASH
|
|
612
|
+
Open Source
|