cyclecad 0.1.9 ā 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_API_IMPLEMENTATION_SUMMARY.md +399 -0
- package/AGENT_API_MANIFEST.md +343 -0
- package/AGENT_API_QUICKSTART.md +316 -0
- package/AGENT_API_WIRING.md +495 -0
- package/CLAUDE.md +120 -8
- package/DELIVERABLES.txt +471 -0
- package/app/agent-demo.html +1990 -1294
- package/app/agent-test.html +486 -0
- package/app/index.html +236 -5
- package/app/js/agent-api.js +953 -98
- package/app/js/viewer-mode.js +899 -0
- package/architecture.html +372 -0
- package/docs/EXPLODEVIEW-FEATURE-MAPPING.md +602 -0
- package/docs/README-VIEWER-MODE-MERGE.md +364 -0
- package/docs/VIEWER-MODE-IMPLEMENTATION-GUIDE.md +412 -0
- package/docs/explodeview-merge-plan.md +476 -0
- package/docs/opencascade-integration.md +1102 -0
- package/linkedin-post.md +24 -0
- package/package.json +1 -1
package/app/index.html
CHANGED
|
@@ -1444,6 +1444,22 @@
|
|
|
1444
1444
|
</button>
|
|
1445
1445
|
</div>
|
|
1446
1446
|
|
|
1447
|
+
<!-- Agent API Panel -->
|
|
1448
|
+
<div class="toolbar-group">
|
|
1449
|
+
<button class="toolbar-button" id="btn-agent-panel" title="Agent Command Panel (Test API)">
|
|
1450
|
+
<span class="toolbar-icon">š¤</span>
|
|
1451
|
+
<span class="toolbar-label">Agent</span>
|
|
1452
|
+
</button>
|
|
1453
|
+
</div>
|
|
1454
|
+
|
|
1455
|
+
<!-- Hard Reset -->
|
|
1456
|
+
<div class="toolbar-group">
|
|
1457
|
+
<button class="toolbar-button" id="btn-hard-reset" title="Clear cache and reload" style="color:#f55;">
|
|
1458
|
+
<span class="toolbar-icon">š</span>
|
|
1459
|
+
<span class="toolbar-label">Reset</span>
|
|
1460
|
+
</button>
|
|
1461
|
+
</div>
|
|
1462
|
+
|
|
1447
1463
|
<!-- Edit Operations -->
|
|
1448
1464
|
<div class="toolbar-group">
|
|
1449
1465
|
<button class="toolbar-button" id="btn-undo" title="Undo (Ctrl+Z)">
|
|
@@ -1589,6 +1605,36 @@
|
|
|
1589
1605
|
<!-- Context Menu -->
|
|
1590
1606
|
<div id="context-menu"></div>
|
|
1591
1607
|
|
|
1608
|
+
<!-- Agent Command Panel -->
|
|
1609
|
+
<div id="agent-panel" style="display:none;position:fixed;bottom:40px;right:20px;width:450px;max-height:600px;background:var(--bg-secondary);border:1px solid var(--border-color);border-radius:6px;box-shadow:var(--shadow-lg);z-index:1000;flex-direction:column;gap:0;">
|
|
1610
|
+
<div style="padding:12px 16px;border-bottom:1px solid var(--border-color);display:flex;justify-content:space-between;align-items:center;user-select:none;">
|
|
1611
|
+
<strong style="font-size:13px;">Agent Command Panel</strong>
|
|
1612
|
+
<button onclick="document.getElementById('agent-panel').style.display='none'" style="background:transparent;border:none;color:var(--text-secondary);cursor:pointer;font-size:16px;padding:0;width:20px;height:20px;">ā</button>
|
|
1613
|
+
</div>
|
|
1614
|
+
|
|
1615
|
+
<div style="flex:1;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:8px;min-height:0;">
|
|
1616
|
+
<div id="agent-log" style="flex:1;display:flex;flex-direction:column;gap:6px;font-family:monospace;font-size:11px;color:var(--text-secondary);overflow-y:auto;min-height:100px;max-height:400px;">
|
|
1617
|
+
<div style="color:var(--accent-green);">[Ready to accept commands]</div>
|
|
1618
|
+
</div>
|
|
1619
|
+
</div>
|
|
1620
|
+
|
|
1621
|
+
<div style="padding:12px;border-top:1px solid var(--border-color);display:flex;flex-direction:column;gap:8px;">
|
|
1622
|
+
<!-- Command input -->
|
|
1623
|
+
<input type="text" id="agent-command-input" placeholder="{ method: "sketch.start", params: { plane: "XY" } }" style="width:100%;padding:8px 10px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:4px;color:var(--text-primary);font-family:monospace;font-size:11px;box-sizing:border-box;">
|
|
1624
|
+
|
|
1625
|
+
<!-- Quick command buttons -->
|
|
1626
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:6px;font-size:11px;">
|
|
1627
|
+
<button onclick="agentPanel.executeQuickCommand('ping')" style="padding:6px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:3px;color:var(--accent-blue);cursor:pointer;">Test (Ping)</button>
|
|
1628
|
+
<button onclick="agentPanel.executeQuickCommand('schema')" style="padding:6px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:3px;color:var(--accent-blue);cursor:pointer;">Schema</button>
|
|
1629
|
+
<button onclick="agentPanel.executeQuickCommand('newsketch')" style="padding:6px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:3px;color:var(--accent-green);cursor:pointer;">New Sketch</button>
|
|
1630
|
+
<button onclick="agentPanel.executeQuickCommand('features')" style="padding:6px;background:var(--bg-tertiary);border:1px solid var(--border-color);border-radius:3px;color:var(--accent-green);cursor:pointer;">List Features</button>
|
|
1631
|
+
</div>
|
|
1632
|
+
|
|
1633
|
+
<!-- Execute button -->
|
|
1634
|
+
<button onclick="agentPanel.executeCommand()" style="width:100%;padding:8px;background:var(--accent-blue);color:#fff;border:none;border-radius:4px;cursor:pointer;font-weight:bold;font-size:12px;">Execute Command</button>
|
|
1635
|
+
</div>
|
|
1636
|
+
</div>
|
|
1637
|
+
|
|
1592
1638
|
<!-- Module Loader -->
|
|
1593
1639
|
<script type="module">
|
|
1594
1640
|
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js';
|
|
@@ -1778,11 +1824,65 @@
|
|
|
1778
1824
|
// Initialize Agent API ā the primary interface
|
|
1779
1825
|
const agentImports = await import('./js/agent-api.js');
|
|
1780
1826
|
const agentSession = initAgentAPI({
|
|
1781
|
-
viewport: {
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1827
|
+
viewport: {
|
|
1828
|
+
getCamera,
|
|
1829
|
+
getControls,
|
|
1830
|
+
getScene,
|
|
1831
|
+
setView,
|
|
1832
|
+
fitToObject,
|
|
1833
|
+
addToScene,
|
|
1834
|
+
removeFromScene,
|
|
1835
|
+
toggleGrid: vpToggleGrid,
|
|
1836
|
+
toggleWireframe: (e) => console.log('wireframe:', e),
|
|
1837
|
+
toggleAxisLines: () => {},
|
|
1838
|
+
getRenderer: () => null
|
|
1839
|
+
},
|
|
1840
|
+
sketch: {
|
|
1841
|
+
startSketch,
|
|
1842
|
+
endSketch,
|
|
1843
|
+
setTool,
|
|
1844
|
+
getEntities,
|
|
1845
|
+
clearSketch
|
|
1846
|
+
},
|
|
1847
|
+
operations: {
|
|
1848
|
+
extrudeProfile,
|
|
1849
|
+
createPrimitive,
|
|
1850
|
+
rebuildFeature,
|
|
1851
|
+
createMaterial,
|
|
1852
|
+
fillet: (mesh, edges, radius) => console.log('fillet:', mesh, edges, radius),
|
|
1853
|
+
chamfer: (mesh, edges, dist) => console.log('chamfer:', mesh, edges, dist),
|
|
1854
|
+
booleanUnion: (a, b) => { console.log('union:', a, b); return a; },
|
|
1855
|
+
booleanCut: (a, b) => { console.log('cut:', a, b); return a; },
|
|
1856
|
+
booleanIntersect: (a, b) => { console.log('intersect:', a, b); return a; },
|
|
1857
|
+
createShell: (mesh, thickness) => console.log('shell:', mesh, thickness),
|
|
1858
|
+
createPattern: (mesh, type, count, spacing) => { console.log('pattern:', mesh, type, count, spacing); return []; },
|
|
1859
|
+
getMaterialPresets: () => ({
|
|
1860
|
+
steel: { color: 0x7799bb, name: 'Steel' },
|
|
1861
|
+
aluminum: { color: 0xccccdd, name: 'Aluminum' },
|
|
1862
|
+
plastic: { color: 0x2c3e50, name: 'Plastic' },
|
|
1863
|
+
brass: { color: 0xcd7f32, name: 'Brass' },
|
|
1864
|
+
titanium: { color: 0x878786, name: 'Titanium' },
|
|
1865
|
+
nylon: { color: 0xf5f5dc, name: 'Nylon' }
|
|
1866
|
+
})
|
|
1867
|
+
},
|
|
1868
|
+
advancedOps: {
|
|
1869
|
+
createSweep,
|
|
1870
|
+
createLoft,
|
|
1871
|
+
createBend,
|
|
1872
|
+
createFlange,
|
|
1873
|
+
createTab,
|
|
1874
|
+
createSlot,
|
|
1875
|
+
unfoldSheetMetal,
|
|
1876
|
+
createSpring,
|
|
1877
|
+
createThread
|
|
1878
|
+
},
|
|
1879
|
+
exportModule: {
|
|
1880
|
+
exportSTL,
|
|
1881
|
+
exportOBJ,
|
|
1882
|
+
exportJSON,
|
|
1883
|
+
exportSTLBinary: exportSTL,
|
|
1884
|
+
exportGLTF: exportOBJ
|
|
1885
|
+
},
|
|
1786
1886
|
appState: APP
|
|
1787
1887
|
});
|
|
1788
1888
|
console.log(`[Agent API] Ready. Session: ${agentSession.sessionId}`);
|
|
@@ -2604,6 +2704,70 @@
|
|
|
2604
2704
|
|
|
2605
2705
|
window.cycleCAD = { version: '1.0.0', APP, init };
|
|
2606
2706
|
|
|
2707
|
+
// ========== Hard Reset (with browser detection) ==========
|
|
2708
|
+
const hardResetBtn = document.getElementById('btn-hard-reset');
|
|
2709
|
+
if (hardResetBtn) {
|
|
2710
|
+
function detectBrowserCC() {
|
|
2711
|
+
const ua = navigator.userAgent;
|
|
2712
|
+
if (/Edg\//i.test(ua)) return 'Edge';
|
|
2713
|
+
if (/Chrome\//i.test(ua) && !/Edg\//i.test(ua)) return 'Chrome';
|
|
2714
|
+
if (/Safari\//i.test(ua) && !/Chrome\//i.test(ua)) return 'Safari';
|
|
2715
|
+
if (/Firefox\//i.test(ua)) return 'Firefox';
|
|
2716
|
+
return 'Unknown';
|
|
2717
|
+
}
|
|
2718
|
+
hardResetBtn.addEventListener('click', async () => {
|
|
2719
|
+
const browser = detectBrowserCC();
|
|
2720
|
+
const msg = `Clear ALL cached data and reload?\n\nDetected browser: ${browser}\n\nThis will clear:\n⢠Service Workers\n⢠Cache API storage\n⢠IndexedDB databases\n⢠OPFS storage\n⢠localStorage & sessionStorage`;
|
|
2721
|
+
if (!confirm(msg)) return;
|
|
2722
|
+
const log = [];
|
|
2723
|
+
// 1. Unregister service workers
|
|
2724
|
+
try {
|
|
2725
|
+
if ('serviceWorker' in navigator) {
|
|
2726
|
+
const regs = await navigator.serviceWorker.getRegistrations();
|
|
2727
|
+
for (const r of regs) await r.unregister();
|
|
2728
|
+
log.push('SW: ' + regs.length);
|
|
2729
|
+
}
|
|
2730
|
+
} catch(e) {}
|
|
2731
|
+
// 2. Cache API
|
|
2732
|
+
try {
|
|
2733
|
+
if ('caches' in window) {
|
|
2734
|
+
const names = await caches.keys();
|
|
2735
|
+
for (const n of names) await caches.delete(n);
|
|
2736
|
+
log.push('Caches: ' + names.length);
|
|
2737
|
+
}
|
|
2738
|
+
} catch(e) {}
|
|
2739
|
+
// 3. IndexedDB ā clear all
|
|
2740
|
+
try {
|
|
2741
|
+
if (indexedDB.databases) {
|
|
2742
|
+
const allDBs = await indexedDB.databases();
|
|
2743
|
+
for (const db of allDBs) { if (db.name) indexedDB.deleteDatabase(db.name); }
|
|
2744
|
+
log.push('IDB: ' + allDBs.length);
|
|
2745
|
+
}
|
|
2746
|
+
} catch(e) {}
|
|
2747
|
+
// 4. OPFS
|
|
2748
|
+
try {
|
|
2749
|
+
if (navigator.storage && navigator.storage.getDirectory) {
|
|
2750
|
+
const root = await navigator.storage.getDirectory();
|
|
2751
|
+
for await (const [name] of root.entries()) {
|
|
2752
|
+
try { await root.removeEntry(name, { recursive: true }); } catch(e) {}
|
|
2753
|
+
}
|
|
2754
|
+
log.push('OPFS: cleared');
|
|
2755
|
+
}
|
|
2756
|
+
} catch(e) {}
|
|
2757
|
+
// 5. Storage
|
|
2758
|
+
try { localStorage.clear(); } catch(e) {}
|
|
2759
|
+
try { sessionStorage.clear(); } catch(e) {}
|
|
2760
|
+
log.push('Storage: cleared');
|
|
2761
|
+
console.log('[Hard Reset]', browser, log.join(' | '));
|
|
2762
|
+
// 6. Browser-specific reload
|
|
2763
|
+
if (browser === 'Safari') {
|
|
2764
|
+
window.location.href = window.location.pathname + '?cachebust=' + Date.now();
|
|
2765
|
+
} else {
|
|
2766
|
+
setTimeout(() => { window.location.reload(true); }, 300);
|
|
2767
|
+
}
|
|
2768
|
+
});
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2607
2771
|
// ========== Operation Dialog Management ==========
|
|
2608
2772
|
let currentDialogId = null;
|
|
2609
2773
|
|
|
@@ -2889,6 +3053,72 @@
|
|
|
2889
3053
|
}
|
|
2890
3054
|
});
|
|
2891
3055
|
|
|
3056
|
+
// ========== Agent Command Panel ==========
|
|
3057
|
+
const agentPanel = {
|
|
3058
|
+
executeCommand() {
|
|
3059
|
+
const input = document.getElementById('agent-command-input');
|
|
3060
|
+
const cmd = input.value.trim();
|
|
3061
|
+
if (!cmd) return;
|
|
3062
|
+
|
|
3063
|
+
this.log(`> ${cmd}`, 'input');
|
|
3064
|
+
try {
|
|
3065
|
+
const parsed = JSON.parse(cmd);
|
|
3066
|
+
if (!window.cycleCAD || !window.cycleCAD.execute) {
|
|
3067
|
+
this.log('ā Agent API not initialized', 'error');
|
|
3068
|
+
return;
|
|
3069
|
+
}
|
|
3070
|
+
const result = window.cycleCAD.execute(parsed);
|
|
3071
|
+
this.log(`ā ${JSON.stringify(result, null, 2)}`, 'output');
|
|
3072
|
+
input.value = '';
|
|
3073
|
+
} catch (e) {
|
|
3074
|
+
this.log(`ā ${e.message}`, 'error');
|
|
3075
|
+
}
|
|
3076
|
+
},
|
|
3077
|
+
|
|
3078
|
+
executeQuickCommand(cmd) {
|
|
3079
|
+
const input = document.getElementById('agent-command-input');
|
|
3080
|
+
const commands = {
|
|
3081
|
+
'ping': { method: 'meta.ping', params: {} },
|
|
3082
|
+
'schema': { method: 'meta.schema', params: {} },
|
|
3083
|
+
'newsketch': { method: 'sketch.start', params: { plane: 'XY' } },
|
|
3084
|
+
'features': { method: 'query.features', params: {} },
|
|
3085
|
+
};
|
|
3086
|
+
const cmdObj = commands[cmd];
|
|
3087
|
+
if (cmdObj) {
|
|
3088
|
+
input.value = JSON.stringify(cmdObj);
|
|
3089
|
+
setTimeout(() => this.executeCommand(), 0);
|
|
3090
|
+
}
|
|
3091
|
+
},
|
|
3092
|
+
|
|
3093
|
+
log(msg, type = 'info') {
|
|
3094
|
+
const logEl = document.getElementById('agent-log');
|
|
3095
|
+
const div = document.createElement('div');
|
|
3096
|
+
if (type === 'input') div.style.color = 'var(--accent-blue)';
|
|
3097
|
+
if (type === 'output') div.style.color = 'var(--accent-green)';
|
|
3098
|
+
if (type === 'error') div.style.color = 'var(--accent-red)';
|
|
3099
|
+
div.textContent = msg;
|
|
3100
|
+
logEl.appendChild(div);
|
|
3101
|
+
logEl.scrollTop = logEl.scrollHeight;
|
|
3102
|
+
},
|
|
3103
|
+
};
|
|
3104
|
+
|
|
3105
|
+
// Wire Agent Panel button
|
|
3106
|
+
const agentPanelBtn = document.getElementById('btn-agent-panel');
|
|
3107
|
+
if (agentPanelBtn) {
|
|
3108
|
+
agentPanelBtn.addEventListener('click', () => {
|
|
3109
|
+
const panel = document.getElementById('agent-panel');
|
|
3110
|
+
panel.style.display = panel.style.display === 'none' ? 'flex' : 'none';
|
|
3111
|
+
});
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3114
|
+
// Wire Enter key in command input
|
|
3115
|
+
document.getElementById('agent-command-input')?.addEventListener('keydown', (e) => {
|
|
3116
|
+
if (e.key === 'Enter') {
|
|
3117
|
+
e.preventDefault();
|
|
3118
|
+
agentPanel.executeCommand();
|
|
3119
|
+
}
|
|
3120
|
+
});
|
|
3121
|
+
|
|
2892
3122
|
</script>
|
|
2893
3123
|
|
|
2894
3124
|
<!-- Operation Dialogs -->
|
|
@@ -3238,5 +3468,6 @@
|
|
|
3238
3468
|
</div>
|
|
3239
3469
|
</div>
|
|
3240
3470
|
|
|
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>
|
|
3241
3472
|
</body>
|
|
3242
3473
|
</html>
|