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
package/app/index.html CHANGED
@@ -1276,6 +1276,17 @@
1276
1276
  }
1277
1277
 
1278
1278
  </style>
1279
+
1280
+ <!-- Token Engine — Initialize early so window.cycleCAD.tokens is available -->
1281
+ <script src="./js/token-engine.js"></script>
1282
+ <!-- New Architecture Modules -->
1283
+ <script src="./js/material-library.js"></script>
1284
+ <script src="./js/dfm-analyzer.js"></script>
1285
+ <script src="./js/cam-pipeline.js"></script>
1286
+ <script src="./js/connected-fabs.js"></script>
1287
+ <script src="./js/ai-copilot.js"></script>
1288
+ <script src="./js/collaboration.js"></script>
1289
+ <script src="./js/collaboration-ui.js"></script>
1279
1290
  </head>
1280
1291
  <body>
1281
1292
  <div id="app">
@@ -1444,6 +1455,42 @@
1444
1455
  </button>
1445
1456
  </div>
1446
1457
 
1458
+ <!-- Token Balance Indicator -->
1459
+ <div class="toolbar-group">
1460
+ <button class="toolbar-button" id="btn-token-balance" title="View Token Balance & Billing" style="background: linear-gradient(135deg, rgba(88,166,255,0.1), rgba(63,185,80,0.1)); border: 1px solid rgba(88,166,255,0.3);" onclick="document.querySelector('[data-tab=tokens]')?.click()">
1461
+ <span class="toolbar-icon">💰</span>
1462
+ <span class="toolbar-label" id="token-balance-label">1K Tokens</span>
1463
+ </button>
1464
+ </div>
1465
+
1466
+ <!-- AI & Analysis -->
1467
+ <div class="toolbar-group">
1468
+ <button class="toolbar-button" id="btn-ai-copilot" title="AI Copilot — Text-to-CAD, Voice Commands" style="background:rgba(139,92,246,0.1);border:1px solid rgba(139,92,246,0.3);">
1469
+ <span class="toolbar-icon">✨</span>
1470
+ <span class="toolbar-label">Copilot</span>
1471
+ </button>
1472
+ <button class="toolbar-button" id="btn-dfm" title="DFM Analyzer — Manufacturability Check" style="background:rgba(248,113,113,0.1);border:1px solid rgba(248,113,113,0.3);">
1473
+ <span class="toolbar-icon">🏭</span>
1474
+ <span class="toolbar-label">DFM</span>
1475
+ </button>
1476
+ <button class="toolbar-button" id="btn-materials" title="Material Library — 40+ PBR Materials" style="background:rgba(34,211,238,0.1);border:1px solid rgba(34,211,238,0.3);">
1477
+ <span class="toolbar-icon">🎨</span>
1478
+ <span class="toolbar-label">Materials</span>
1479
+ </button>
1480
+ <button class="toolbar-button" id="btn-cam" title="CAM Pipeline — Slicer, Toolpath, G-code" style="background:rgba(251,191,36,0.1);border:1px solid rgba(251,191,36,0.3);">
1481
+ <span class="toolbar-icon">⚙</span>
1482
+ <span class="toolbar-label">CAM</span>
1483
+ </button>
1484
+ <button class="toolbar-button" id="btn-fabs" title="Connected Fabs — Send to Fabrication" style="background:rgba(74,222,128,0.1);border:1px solid rgba(74,222,128,0.3);">
1485
+ <span class="toolbar-icon">🏗</span>
1486
+ <span class="toolbar-label">Fabs</span>
1487
+ </button>
1488
+ <button class="toolbar-button" id="btn-collab" title="Collaboration — Multi-User Sessions" style="background:rgba(96,165,250,0.1);border:1px solid rgba(96,165,250,0.3);">
1489
+ <span class="toolbar-icon">👥</span>
1490
+ <span class="toolbar-label">Collab</span>
1491
+ </button>
1492
+ </div>
1493
+
1447
1494
  <!-- Agent API Panel -->
1448
1495
  <div class="toolbar-group">
1449
1496
  <button class="toolbar-button" id="btn-agent-panel" title="Agent Command Panel (Test API)">
@@ -1551,6 +1598,7 @@
1551
1598
  <button class="properties-tab active" data-tab="properties">Properties</button>
1552
1599
  <button class="properties-tab" data-tab="chat">Chat</button>
1553
1600
  <button class="properties-tab" data-tab="guide">Guide</button>
1601
+ <button class="properties-tab" data-tab="tokens" style="margin-left: auto; background: linear-gradient(135deg, rgba(88,166,255,0.1), rgba(63,185,80,0.1)); border: 1px solid rgba(88,166,255,0.3);" title="Token Balance & Billing">💰 Tokens</button>
1554
1602
  </div>
1555
1603
 
1556
1604
  <!-- Properties Content -->
@@ -1564,6 +1612,7 @@
1564
1612
  <div id="tab-guide" style="display: none;">
1565
1613
  <!-- Rebuild guide populated by JavaScript -->
1566
1614
  </div>
1615
+ <!-- Tokens tab will be populated by token-dashboard.js -->
1567
1616
  </div>
1568
1617
  </div>
1569
1618
  </div>
@@ -1656,6 +1705,7 @@
1656
1705
  import Assembly from './js/assembly.js';
1657
1706
  import { exportSketchToDXF, exportProjectionToDXF, exportMultiViewDXF, export3DDXF, downloadDXF } from './js/dxf-export.js';
1658
1707
  import { initAgentAPI } from './js/agent-api.js';
1708
+ import { initTokenDashboard } from './js/token-dashboard.js';
1659
1709
 
1660
1710
  // ========== Application State ==========
1661
1711
  const APP = {
@@ -1713,6 +1763,38 @@
1713
1763
  );
1714
1764
  }
1715
1765
 
1766
+ // 4b. Initialize Token Dashboard
1767
+ const tokenTab = document.getElementById('tab-tokens');
1768
+ if (tokenTab) {
1769
+ const tokenDashboard = initTokenDashboard();
1770
+ tokenTab.innerHTML = tokenDashboard.html;
1771
+ tokenTab.style.display = 'none';
1772
+ tokenTab.style.overflowY = 'auto';
1773
+ // Initialize the dashboard events
1774
+ tokenDashboard.init();
1775
+
1776
+ // Update toolbar balance indicator
1777
+ function updateTokenBalanceLabel() {
1778
+ const balance = window.cycleCAD?.tokens?.getBalance?.() || 0;
1779
+ const label = document.getElementById('token-balance-label');
1780
+ if (label) {
1781
+ if (balance >= 1000) {
1782
+ label.textContent = Math.floor(balance / 1000) + 'K Tokens';
1783
+ } else {
1784
+ label.textContent = balance + ' Tokens';
1785
+ }
1786
+ }
1787
+ }
1788
+ updateTokenBalanceLabel();
1789
+
1790
+ // Update label when tokens change
1791
+ if (window.cycleCAD?.tokens?.on) {
1792
+ window.cycleCAD.tokens.on('token-spent', updateTokenBalanceLabel);
1793
+ window.cycleCAD.tokens.on('token-added', updateTokenBalanceLabel);
1794
+ window.cycleCAD.tokens.on('month-reset', updateTokenBalanceLabel);
1795
+ }
1796
+ }
1797
+
1716
1798
  // 5. Wire up toolbar buttons
1717
1799
  setupToolbar();
1718
1800
 
@@ -1889,7 +1971,33 @@
1889
1971
  console.log('[Agent API] Usage: window.cycleCAD.execute({ method: "meta.ping" })');
1890
1972
  console.log('[Agent API] Schema: window.cycleCAD.getSchema()');
1891
1973
 
1892
- console.log('cycleCAD initialized successfully');
1974
+ // Initialize new architecture modules
1975
+ if (window.cycleCAD?.materials?.init) {
1976
+ window.cycleCAD.materials.init();
1977
+ console.log('[Materials] Library initialized — ' + (window.cycleCAD.materials.getAll?.()?.length || '40+') + ' materials');
1978
+ }
1979
+ if (window.cycleCAD?.dfm?.init) {
1980
+ window.cycleCAD.dfm.init();
1981
+ console.log('[DFM] Analyzer initialized — 8 manufacturing processes');
1982
+ }
1983
+ if (window.cycleCAD?.cam?.init) {
1984
+ window.cycleCAD.cam.init();
1985
+ console.log('[CAM] Pipeline initialized — slicer, toolpath, G-code');
1986
+ }
1987
+ if (window.cycleCAD?.fabs?.init) {
1988
+ window.cycleCAD.fabs.init();
1989
+ console.log('[Fabs] Connected fabrication network initialized');
1990
+ }
1991
+ if (window.cycleCAD?.copilot?.init) {
1992
+ window.cycleCAD.copilot.init();
1993
+ console.log('[AI Copilot] Initialized — text-to-CAD, voice commands');
1994
+ }
1995
+ if (window.cycleCAD?.collab?.init) {
1996
+ window.cycleCAD.collab.init();
1997
+ console.log('[Collaboration] Session management initialized');
1998
+ }
1999
+
2000
+ console.log('cycleCAD initialized successfully — all modules loaded');
1893
2001
  updateStatus('Ready');
1894
2002
 
1895
2003
  } catch (error) {
@@ -2302,6 +2410,14 @@
2302
2410
  document.getElementById('tab-properties').style.display = target === 'properties' ? 'block' : 'none';
2303
2411
  document.getElementById('tab-chat').style.display = target === 'chat' ? 'flex' : 'none';
2304
2412
  document.getElementById('tab-guide').style.display = target === 'guide' ? 'block' : 'none';
2413
+ const tokenTab = document.getElementById('tab-tokens');
2414
+ if (tokenTab) {
2415
+ tokenTab.style.display = target === 'tokens' ? 'block' : 'none';
2416
+ if (target === 'tokens') {
2417
+ // Update token dashboard when switching to it
2418
+ window.cycleCAD?.tokens?.on?.('panel-opened', () => {});
2419
+ }
2420
+ }
2305
2421
  });
2306
2422
  });
2307
2423
  }
@@ -2702,7 +2818,7 @@
2702
2818
  init();
2703
2819
  }
2704
2820
 
2705
- window.cycleCAD = { version: '1.0.0', APP, init };
2821
+ window.cycleCAD = Object.assign(window.cycleCAD || {}, { version: '1.0.0', APP, init });
2706
2822
 
2707
2823
  // ========== Hard Reset (with browser detection) ==========
2708
2824
  const hardResetBtn = document.getElementById('btn-hard-reset');
@@ -3119,6 +3235,55 @@
3119
3235
  }
3120
3236
  });
3121
3237
 
3238
+ // ========== New Module Toolbar Buttons ==========
3239
+ function toggleModulePanel(moduleKey, panelId) {
3240
+ let panel = document.getElementById(panelId);
3241
+ if (panel) {
3242
+ panel.style.display = panel.style.display === 'none' ? 'flex' : 'none';
3243
+ return;
3244
+ }
3245
+ // Create floating panel
3246
+ panel = document.createElement('div');
3247
+ panel.id = panelId;
3248
+ panel.style.cssText = 'position:fixed;top:60px;right:320px;width:400px;max-height:80vh;overflow-y:auto;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:8px;z-index:500;display:flex;flex-direction:column;box-shadow:var(--shadow-lg);';
3249
+
3250
+ const header = document.createElement('div');
3251
+ header.style.cssText = 'display:flex;justify-content:space-between;align-items:center;padding:10px 14px;border-bottom:1px solid var(--border-color);background:var(--bg-tertiary);border-radius:8px 8px 0 0;cursor:move;';
3252
+
3253
+ const titles = {
3254
+ 'copilot-panel': '✨ AI Copilot',
3255
+ 'dfm-panel': '🏭 DFM Analyzer',
3256
+ 'materials-panel': '🎨 Material Library',
3257
+ 'cam-panel': '⚙ CAM Pipeline',
3258
+ 'fabs-panel': '🏗 Connected Fabs',
3259
+ 'collab-panel': '👥 Collaboration'
3260
+ };
3261
+ header.innerHTML = `<span style="font-weight:600;font-size:13px;">${titles[panelId] || moduleKey}</span><button onclick="document.getElementById('${panelId}').style.display='none'" style="background:none;border:none;color:var(--text-secondary);cursor:pointer;font-size:16px;">✕</button>`;
3262
+ panel.appendChild(header);
3263
+
3264
+ const body = document.createElement('div');
3265
+ body.style.cssText = 'padding:14px;flex:1;min-height:0;overflow-y:auto;font-size:12px;';
3266
+
3267
+ const mod = window.cycleCAD?.[moduleKey];
3268
+ if (mod?.getUI) {
3269
+ body.innerHTML = mod.getUI();
3270
+ } else if (mod?.getStatus) {
3271
+ const status = mod.getStatus();
3272
+ body.innerHTML = `<div style="color:var(--text-secondary);line-height:1.8;">${JSON.stringify(status, null, 2).replace(/\n/g, '<br>')}</div>`;
3273
+ } else {
3274
+ body.innerHTML = `<div style="color:var(--accent-green);padding:12px;text-align:center;"><p style="font-weight:600;margin-bottom:8px;">Module Loaded</p><p style="color:var(--text-secondary);">Access via console:<br><code style="background:var(--bg-tertiary);padding:2px 6px;border-radius:3px;">window.cycleCAD.${moduleKey}</code></p></div>`;
3275
+ }
3276
+ panel.appendChild(body);
3277
+ document.body.appendChild(panel);
3278
+ }
3279
+
3280
+ document.getElementById('btn-ai-copilot')?.addEventListener('click', () => toggleModulePanel('copilot', 'copilot-panel'));
3281
+ document.getElementById('btn-dfm')?.addEventListener('click', () => toggleModulePanel('dfm', 'dfm-panel'));
3282
+ document.getElementById('btn-materials')?.addEventListener('click', () => toggleModulePanel('materials', 'materials-panel'));
3283
+ document.getElementById('btn-cam')?.addEventListener('click', () => toggleModulePanel('cam', 'cam-panel'));
3284
+ document.getElementById('btn-fabs')?.addEventListener('click', () => toggleModulePanel('fabs', 'fabs-panel'));
3285
+ document.getElementById('btn-collab')?.addEventListener('click', () => toggleModulePanel('collab', 'collab-panel'));
3286
+
3122
3287
  </script>
3123
3288
 
3124
3289
  <!-- Operation Dialogs -->
@@ -3468,6 +3633,6 @@
3468
3633
  </div>
3469
3634
  </div>
3470
3635
 
3471
- <span id="version-badge" style="position:fixed;bottom:10px;left:50%;transform:translateX(-50%);z-index:70;font-size:0.85rem;color:rgba(255,255,255,0.7);letter-spacing:0.1em;white-space:nowrap;padding:5px 14px;user-select:all;pointer-events:auto;font-family:monospace;font-weight:600;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.15);border-radius:6px;text-shadow:0 1px 3px rgba(0,0,0,0.5);" title="cycleCAD version">cycleCAD v0.2.0</span>
3636
+ <span id="version-badge" style="position:fixed;bottom:10px;left:50%;transform:translateX(-50%);z-index:70;font-size:0.85rem;color:rgba(255,255,255,0.7);letter-spacing:0.1em;white-space:nowrap;padding:5px 14px;user-select:all;pointer-events:auto;font-family:monospace;font-weight:600;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.15);border-radius:6px;text-shadow:0 1px 3px rgba(0,0,0,0.5);" title="cycleCAD version">cycleCAD v0.2.2</span>
3472
3637
  </body>
3473
3638
  </html>
@@ -0,0 +1,391 @@
1
+ # $CYCLE Token Engine Integration Guide
2
+
3
+ ## Overview
4
+
5
+ The `$CYCLE` Token Engine is a per-operation billing system for cycleCAD, inspired by the Claude API token model. Every CAD operation costs tokens, and tokens can be purchased, earned, or generated through cache hits.
6
+
7
+ ## Files Created
8
+
9
+ 1. **token-engine.js** (~750 lines)
10
+ - Core billing engine with balance management
11
+ - Double-entry ledger (debit buyer, credit creator + platform)
12
+ - Per-operation pricing (2-100 tokens per operation)
13
+ - Tier system (FREE/PRO/ENTERPRISE)
14
+ - Cache discounts (10% repeat access within 24h)
15
+ - Batch discounts (25% for 10+, 50% for 100+)
16
+ - Escrow system for manufacturing jobs
17
+ - Token purchase flow (Stripe placeholder)
18
+ - Event system for real-time updates
19
+ - All data persisted to localStorage
20
+
21
+ 2. **token-dashboard.js** (~600 lines)
22
+ - Rich UI dashboard for balance, transactions, usage analytics
23
+ - 4 dialog systems: estimate price, purchase tokens, upgrade tier, view history
24
+ - Real-time balance indicator in toolbar
25
+ - Recent activity list
26
+ - Top operations breakdown
27
+ - Tier information cards
28
+
29
+ 3. **index.html** (Modified)
30
+ - Added token-engine.js `<script>` tag in head
31
+ - Added import for token-dashboard.js in main script
32
+ - Added "💰 Tokens" tab to properties panel
33
+ - Added token balance indicator button to toolbar
34
+ - Wired tab switching and balance updates
35
+
36
+ ## API Usage
37
+
38
+ ### Balance Management
39
+
40
+ ```javascript
41
+ // Get current balance
42
+ const balance = window.cycleCAD.tokens.getBalance();
43
+
44
+ // Get detailed info
45
+ const info = window.cycleCAD.tokens.getBalanceInfo();
46
+ // Returns: { balance, tier, monthlyAllowance, usedThisMonth, remainingThisMonth, tierColor, creatorRoyalty }
47
+
48
+ // Add tokens (for purchases/earnings)
49
+ window.cycleCAD.tokens.addTokens(1000, 'stripe_purchase', { purchaseId: '...' });
50
+
51
+ // Spend tokens for operations
52
+ try {
53
+ window.cycleCAD.tokens.spendTokens(10, 'model.export.step', { fileSize: 2.5 });
54
+ } catch (err) {
55
+ console.error('Insufficient tokens:', err.message);
56
+ }
57
+ ```
58
+
59
+ ### Operation Pricing
60
+
61
+ ```javascript
62
+ // Get price for an operation (includes cache & batch discounts)
63
+ const price = window.cycleCAD.tokens.getPriceForOperation('model.export.step', {});
64
+
65
+ // Estimate cost with optional batch size
66
+ const estimate = window.cycleCAD.tokens.estimateOperation('model.export.step', {
67
+ batchSize: 10 // 25% discount applied
68
+ });
69
+ // Returns: { operation, basePrice, batchSize, batchDiscount, finalPrice, cached }
70
+
71
+ // Charge for operation (returns actual price paid including discounts)
72
+ const charge = window.cycleCAD.tokens.chargeForOperation('model.export.step', {}, {
73
+ fileSize: 2.5
74
+ });
75
+ // Returns: { price, discount }
76
+ ```
77
+
78
+ ### Transaction History
79
+
80
+ ```javascript
81
+ // Get transaction history with optional filters
82
+ const history = window.cycleCAD.tokens.getTransactionHistory({
83
+ type: 'debit', // 'debit' or 'credit'
84
+ operation: 'model.export.step',
85
+ after: '2026-03-25T00:00:00Z',
86
+ minAmount: 5,
87
+ limit: 50
88
+ });
89
+
90
+ // Get usage by operation (this month)
91
+ const usage = window.cycleCAD.tokens.getUsageByOperation();
92
+ // Returns: { 'model.export.stl': { count: 5, totalTokens: 10 }, ... }
93
+
94
+ // Get cost breakdown
95
+ const breakdown = window.cycleCAD.tokens.getCostBreakdown();
96
+ // Returns: [ { operation, count, totalTokens, averagePerOp, costInEuros }, ... ]
97
+
98
+ // Get monthly usage
99
+ const used = window.cycleCAD.tokens.getMonthlyUsage();
100
+ ```
101
+
102
+ ### Escrow System (for Manufacturing)
103
+
104
+ ```javascript
105
+ // Create escrow for a fab job
106
+ const escrow = window.cycleCAD.tokens.createEscrow(500, 'job_123', 'fab_456', {
107
+ service: 'CNC milling',
108
+ estimatedCost: 50
109
+ });
110
+ // Returns: { escrowId, amount, status: 'held' }
111
+
112
+ // Release tokens to fab when job is delivered
113
+ window.cycleCAD.tokens.releaseEscrow('escrow_1');
114
+
115
+ // Cancel escrow and refund tokens
116
+ window.cycleCAD.tokens.cancelEscrow('escrow_1');
117
+
118
+ // Check escrow status
119
+ const status = window.cycleCAD.tokens.getEscrowStatus('escrow_1');
120
+ ```
121
+
122
+ ### Tier Management
123
+
124
+ ```javascript
125
+ // Set user tier
126
+ window.cycleCAD.tokens.setTier('PRO'); // 'FREE', 'PRO', or 'ENTERPRISE'
127
+
128
+ // Get tier info
129
+ const tier = window.cycleCAD.tokens.getTier();
130
+ // Returns: { tier, tokensPerMonth, creatorRoyalty, color, balance, monthlyTokens }
131
+ ```
132
+
133
+ ### Token Purchases
134
+
135
+ ```javascript
136
+ // Initiate token purchase (opens Stripe checkout in real app)
137
+ const session = window.cycleCAD.tokens.purchaseTokens(1000, 'stripe');
138
+ // Returns: { id, type, tokens, euros, method, status, stripeCheckoutUrl, metadata }
139
+
140
+ // Crypto purchase
141
+ const cryptoSession = window.cycleCAD.tokens.purchaseWithCrypto(10, 'USDC');
142
+
143
+ // Complete purchase after payment confirmation
144
+ window.cycleCAD.tokens.completePurchase('purchase_123', 1000);
145
+ ```
146
+
147
+ ### Events
148
+
149
+ ```javascript
150
+ // Subscribe to token events
151
+ window.cycleCAD.tokens.on('token-spent', (data) => {
152
+ console.log('Spent', data.amount, 'tokens on', data.operation);
153
+ });
154
+
155
+ window.cycleCAD.tokens.on('token-added', (data) => {
156
+ console.log('Added', data.amount, 'tokens from', data.source);
157
+ });
158
+
159
+ window.cycleCAD.tokens.on('month-reset', (data) => {
160
+ console.log('Monthly allowance reset:', data.balance, 'tokens');
161
+ });
162
+
163
+ window.cycleCAD.tokens.on('tier-changed', (data) => {
164
+ console.log('Upgraded from', data.oldTier, 'to', data.newTier);
165
+ });
166
+
167
+ window.cycleCAD.tokens.on('escrow-created', (data) => {
168
+ console.log('Escrow created:', data.escrowId);
169
+ });
170
+
171
+ // Unsubscribe
172
+ window.cycleCAD.tokens.off('token-spent', listener);
173
+ ```
174
+
175
+ ### Debug & Export
176
+
177
+ ```javascript
178
+ // Export token data as JSON
179
+ const data = window.cycleCAD.tokens.exportDataAsJSON();
180
+
181
+ // Clear all token data (requires confirmation)
182
+ window.cycleCAD.tokens.clearAllData();
183
+ ```
184
+
185
+ ## Operation Pricing Table
186
+
187
+ All prices in tokens (100 tokens = €1):
188
+
189
+ ### Model Operations
190
+ - Export as STL: 2 tokens
191
+ - Export as STEP: 10 tokens
192
+ - Export as glTF: 3 tokens
193
+ - Export as OBJ: 2 tokens
194
+ - Export as JSON: 1 token
195
+ - Export as DXF: 5 tokens
196
+ - Download mesh (read-only): 50 tokens
197
+ - Download parametric: 200 tokens
198
+ - Download with full IP: 1,000 tokens
199
+
200
+ ### AI Operations
201
+ - Part identifier: 5 tokens
202
+ - Design review: 15 tokens
203
+ - Material suggestion: 3 tokens
204
+ - Fastener suggestion: 4 tokens
205
+ - Generative design: 50 tokens
206
+
207
+ ### CAM Operations
208
+ - Slice for 3D print: 20 tokens
209
+ - CNC toolpath: 75 tokens
210
+ - Laser path: 30 tokens
211
+ - Foam cutting: 25 tokens
212
+
213
+ ### Manufacturing
214
+ - Submit fab job (escrow): 100 tokens
215
+ - Request quote: 10 tokens
216
+ - List vendors: 5 tokens
217
+
218
+ ### Analysis
219
+ - Thermal analysis: 20 tokens
220
+ - Stress analysis: 30 tokens
221
+ - Clearance check: 15 tokens
222
+ - Weight estimation: 2 tokens
223
+ - Cost analysis: 5 tokens
224
+
225
+ ### Marketplace & Collaboration
226
+ - Publish design: 0 tokens (free)
227
+ - List design: 0 tokens (free)
228
+ - Download design: 25 tokens
229
+ - Share link: 0 tokens (free)
230
+ - Comments: 0 tokens (free)
231
+ - Collaboration workspace: 50 tokens/month
232
+
233
+ ## Tier System
234
+
235
+ ### FREE Tier
236
+ - 1,000 tokens/month
237
+ - 70% creator royalty
238
+ - Basic exports
239
+ - Community support
240
+
241
+ ### PRO Tier (€49/month)
242
+ - 10,000 tokens/month
243
+ - 80% creator royalty
244
+ - STEP import/export
245
+ - AI design review
246
+ - Priority support
247
+
248
+ ### ENTERPRISE Tier (€299/month)
249
+ - 100,000 tokens/month
250
+ - 90% creator royalty
251
+ - Unlimited STEP
252
+ - Advanced analytics
253
+ - SLA & support
254
+ - Custom integrations
255
+
256
+ ## Discounts
257
+
258
+ ### Cache Discount
259
+ - First access: full price
260
+ - Repeat access within 24h: 10% of original price
261
+ - Cached operations tracked in localStorage
262
+
263
+ ### Batch Discount
264
+ - Single operation: full price
265
+ - Batch of 10+ operations: 25% discount
266
+ - Batch of 100+ operations: 50% discount
267
+
268
+ ## Double-Entry Ledger
269
+
270
+ Every transaction creates entries for:
271
+ 1. **Debit**: Charged to the user
272
+ 2. **Credit**: Split between creator (70-90%) and platform (10-30%)
273
+
274
+ For example, exporting a STEP file (10 tokens):
275
+ - User debited 10 tokens
276
+ - Creator credited 8 tokens (80% on PRO tier)
277
+ - Platform credited 2 tokens (20% fee)
278
+
279
+ ## localStorage Keys
280
+
281
+ - `cyclecad_token_balance` — current token balance
282
+ - `cyclecad_token_ledger` — transaction history (JSON array)
283
+ - `cyclecad_token_cache` — cached operations (JSON object)
284
+ - `cyclecad_token_escrow` — active escrows (JSON object)
285
+ - `cyclecad_user_tier` — current tier ('FREE', 'PRO', 'ENTERPRISE')
286
+ - `cyclecad_month_start` — month start date for allowance reset
287
+
288
+ ## Integration Checklist
289
+
290
+ - [x] token-engine.js created and initialized in head
291
+ - [x] token-dashboard.js created and imported
292
+ - [x] Token tab added to properties panel (right side)
293
+ - [x] Token balance button added to toolbar
294
+ - [x] Token balance indicator updates in real-time
295
+ - [x] All UI dialogs created (estimate, purchase, upgrade, history)
296
+ - [x] Event system wired to dashboard updates
297
+ - [x] localStorage persistence implemented
298
+ - [x] Monthly allowance reset logic
299
+ - [x] Cache discount system
300
+
301
+ ## Next Steps (Optional Enhancements)
302
+
303
+ 1. **Stripe Integration**: Connect purchaseTokens() to real Stripe checkout
304
+ 2. **Crypto Payments**: Implement purchaseWithCrypto() with Polygon/USDC
305
+ 3. **Creator Dashboard**: Show royalty earnings and payout history
306
+ 4. **Cost Estimation**: Show cost before operations (prompt before spending)
307
+ 5. **Cost Breakdown**: Pie chart showing token spend by operation type
308
+ 6. **Invoice Export**: Generate PDF invoices for purchases
309
+ 7. **Team Billing**: Support shared team tokens pool
310
+ 8. **Usage Alerts**: Notify when approaching monthly limit
311
+ 9. **Subscription Management**: Add cancel/pause subscription flows
312
+ 10. **Analytics Dashboard**: Historical usage trends and projections
313
+
314
+ ## Testing
315
+
316
+ To test the token engine in browser console:
317
+
318
+ ```javascript
319
+ // Check balance
320
+ console.log(window.cycleCAD.tokens.getBalance());
321
+
322
+ // Spend tokens
323
+ window.cycleCAD.tokens.spendTokens(5, 'test.operation', { test: true });
324
+
325
+ // View history
326
+ console.log(window.cycleCAD.tokens.getTransactionHistory({ limit: 10 }));
327
+
328
+ // Upgrade tier
329
+ window.cycleCAD.tokens.setTier('PRO');
330
+
331
+ // View tier info
332
+ console.log(window.cycleCAD.tokens.getTier());
333
+ ```
334
+
335
+ ## Architecture
336
+
337
+ ```
338
+ ┌─────────────────────────────────────────────────────────────┐
339
+ │ cycleCAD Browser App │
340
+ ├─────────────────────────────────────────────────────────────┤
341
+ │ │
342
+ │ ┌────────────────────────────────────────────────────────┐ │
343
+ │ │ Agent API / User Actions │ │
344
+ │ │ (trigger operations) │ │
345
+ │ └─────────────────┬──────────────────────────────────────┘ │
346
+ │ │ │
347
+ │ ┌────────────────▼───────────────────────────────────────┐ │
348
+ │ │ Token Engine (token-engine.js) │ │
349
+ │ │ - Balance tracking │ │
350
+ │ │ - Operation pricing │ │
351
+ │ │ - Ledger management │ │
352
+ │ │ - Tier system │ │
353
+ │ │ - Event emissions │ │
354
+ │ └─────────────────┬──────────────────────────────────────┘ │
355
+ │ │ │
356
+ │ ┌────────────────▼───────────────────────────────────────┐ │
357
+ │ │ Token Dashboard UI (token-dashboard.js) │ │
358
+ │ │ - Balance card │ │
359
+ │ │ - Transaction list │ │
360
+ │ │ - Usage analytics │ │
361
+ │ │ - Purchase dialogs │ │
362
+ │ │ - Tier upgrade flows │ │
363
+ │ └────────────────────────────────────────────────────────┘ │
364
+ │ │ │
365
+ │ ┌────────────────▼───────────────────────────────────────┐ │
366
+ │ │ localStorage (Persistence) │ │
367
+ │ │ - cyclecad_token_balance │ │
368
+ │ │ - cyclecad_token_ledger │ │
369
+ │ │ - cyclecad_token_cache │ │
370
+ │ │ - cyclecad_token_escrow │ │
371
+ │ │ - cyclecad_user_tier │ │
372
+ │ └────────────────────────────────────────────────────────┘ │
373
+ │ │
374
+ └─────────────────────────────────────────────────────────────┘
375
+ ```
376
+
377
+ ## Files Modified
378
+
379
+ 1. `/app/index.html`
380
+ - Added `<script src="./js/token-engine.js"></script>` in head
381
+ - Added `import { initTokenDashboard } from './js/token-dashboard.js';`
382
+ - Added "💰 Tokens" tab button to properties panel
383
+ - Added token balance indicator button to toolbar
384
+ - Added token dashboard initialization and event wiring
385
+ - Updated tab switching logic to include tokens tab
386
+
387
+ ## Questions?
388
+
389
+ For API questions, inspect `window.cycleCAD.tokens` directly or check the source in token-engine.js.
390
+
391
+ The token system is **opt-in**: if you don't call the API, tokens aren't spent. Only operations that explicitly call `chargeForOperation()` will incur costs.
@@ -70,8 +70,8 @@ export function initAgentAPI({ viewport, sketch, operations, advancedOps, export
70
70
  eventListeners = {};
71
71
  console.log(`[Agent API] Initialized. Session: ${sessionId}`);
72
72
 
73
- // Expose globally for external agent access
74
- window.cycleCAD = {
73
+ // Expose globally for external agent access (merge, don't overwrite — other modules already registered)
74
+ window.cycleCAD = Object.assign(window.cycleCAD || {}, {
75
75
  execute,
76
76
  executeMany,
77
77
  executeBatch,
@@ -85,7 +85,7 @@ export function initAgentAPI({ viewport, sketch, operations, advancedOps, export
85
85
  canUndo,
86
86
  canRedo,
87
87
  _debug: { viewport, sketch, operations, advancedOps, exportModule, appState, tree, assembly }
88
- };
88
+ });
89
89
 
90
90
  return { sessionId };
91
91
  }