cyclecad 1.0.2 → 1.0.4
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/app/index.html +36 -14
- package/app/js/ai-copilot.js +21 -12
- package/package.json +1 -1
package/app/index.html
CHANGED
|
@@ -1419,7 +1419,7 @@
|
|
|
1419
1419
|
<span class="splash-logo-cycle">cycle</span><span class="splash-logo-cad">CAD</span>
|
|
1420
1420
|
</div>
|
|
1421
1421
|
<p class="splash-subtitle">Parametric 3D CAD Modeler for the Mechanical Designer</p>
|
|
1422
|
-
<p style="display:inline-block; color:#0066cc; font-size:1rem; margin:12px 0 0 0; letter-spacing:2px; font-family:monospace; font-weight:700; background:rgba(0,102,204,0.08); border:1.5px solid rgba(0,102,204,0.25); border-radius:8px; padding:5px 20px;">v1.0.
|
|
1422
|
+
<p style="display:inline-block; color:#0066cc; font-size:1rem; margin:12px 0 0 0; letter-spacing:2px; font-family:monospace; font-weight:700; background:rgba(0,102,204,0.08); border:1.5px solid rgba(0,102,204,0.25); border-radius:8px; padding:5px 20px;">v1.0.4</p>
|
|
1423
1423
|
</div>
|
|
1424
1424
|
<div class="splash-options">
|
|
1425
1425
|
<button class="splash-button splash-button-primary" id="btn-empty-project" style="grid-column: 1 / -1;">
|
|
@@ -2885,6 +2885,9 @@
|
|
|
2885
2885
|
}
|
|
2886
2886
|
}
|
|
2887
2887
|
|
|
2888
|
+
// Expose globally so Copilot + Agent API + tutorials can create geometry
|
|
2889
|
+
window._executeParsedPrompt = function(prompt) { executeParsedPrompt(prompt); };
|
|
2890
|
+
|
|
2888
2891
|
function executeParsedPrompt(prompt) {
|
|
2889
2892
|
try {
|
|
2890
2893
|
const splash = document.getElementById('welcome-splash');
|
|
@@ -4008,7 +4011,13 @@
|
|
|
4008
4011
|
});
|
|
4009
4012
|
|
|
4010
4013
|
// ========== New Module Toolbar Buttons ==========
|
|
4011
|
-
|
|
4014
|
+
// Map of ES modules that need dynamic import to initialize
|
|
4015
|
+
const _moduleImportMap = {
|
|
4016
|
+
copilot: { path: './js/ai-copilot.js', initFn: 'initCopilot' },
|
|
4017
|
+
materials: { path: './js/material-library.js', initFn: 'initMaterialLibrary' },
|
|
4018
|
+
};
|
|
4019
|
+
|
|
4020
|
+
async function toggleModulePanel(moduleKey, panelId) {
|
|
4012
4021
|
let panel = document.getElementById(panelId);
|
|
4013
4022
|
if (panel) {
|
|
4014
4023
|
panel.style.display = panel.style.display === 'none' ? 'flex' : 'none';
|
|
@@ -4017,7 +4026,7 @@
|
|
|
4017
4026
|
// Create floating panel
|
|
4018
4027
|
panel = document.createElement('div');
|
|
4019
4028
|
panel.id = panelId;
|
|
4020
|
-
panel.style.cssText = 'position:fixed;top:60px;right:320px;width:
|
|
4029
|
+
panel.style.cssText = 'position:fixed;top:60px;right:320px;width:420px;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);';
|
|
4021
4030
|
|
|
4022
4031
|
const header = document.createElement('div');
|
|
4023
4032
|
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;';
|
|
@@ -4049,12 +4058,24 @@
|
|
|
4049
4058
|
const body = document.createElement('div');
|
|
4050
4059
|
body.style.cssText = 'padding:14px;flex:1;min-height:0;overflow-y:auto;font-size:12px;';
|
|
4051
4060
|
|
|
4052
|
-
|
|
4061
|
+
// Try dynamic import for ES modules that export init functions
|
|
4062
|
+
let mod = window.cycleCAD?.[moduleKey];
|
|
4063
|
+
if (!mod && _moduleImportMap[moduleKey]) {
|
|
4064
|
+
try {
|
|
4065
|
+
const m = await import(_moduleImportMap[moduleKey].path);
|
|
4066
|
+
if (m[_moduleImportMap[moduleKey].initFn]) {
|
|
4067
|
+
m[_moduleImportMap[moduleKey].initFn](body);
|
|
4068
|
+
panel.appendChild(body);
|
|
4069
|
+
document.body.appendChild(panel);
|
|
4070
|
+
return;
|
|
4071
|
+
}
|
|
4072
|
+
} catch(e) { console.warn('[Module Import]', moduleKey, e); }
|
|
4073
|
+
mod = window.cycleCAD?.[moduleKey]; // re-check after import
|
|
4074
|
+
}
|
|
4075
|
+
|
|
4053
4076
|
if (mod?.init) {
|
|
4054
|
-
// Use init() which sets innerHTML AND attaches event listeners
|
|
4055
4077
|
mod.init(body);
|
|
4056
4078
|
} else if (mod?.getUI) {
|
|
4057
|
-
// Strip position:fixed and z-index from module HTML — our wrapper handles positioning
|
|
4058
4079
|
let html = mod.getUI();
|
|
4059
4080
|
html = html.replace(/position:\s*fixed;?/gi, 'position:relative;')
|
|
4060
4081
|
.replace(/z-index:\s*\d+;?/gi, '')
|
|
@@ -4063,18 +4084,13 @@
|
|
|
4063
4084
|
.replace(/height:\s*calc\([^)]+\);?/gi, 'height:auto;')
|
|
4064
4085
|
.replace(/width:\s*400px;?/gi, 'width:100%;');
|
|
4065
4086
|
body.innerHTML = html;
|
|
4066
|
-
// Wire up tab switching for modules that use .tab-btn
|
|
4067
4087
|
body.querySelectorAll('.tab-btn').forEach(btn => {
|
|
4068
4088
|
btn.addEventListener('click', () => {
|
|
4069
4089
|
const tab = btn.dataset.tab;
|
|
4070
4090
|
body.querySelectorAll('.tab-btn').forEach(b => {
|
|
4071
|
-
b.style.color = '#888';
|
|
4072
|
-
b.style.borderBottom = 'none';
|
|
4073
|
-
b.classList.remove('active');
|
|
4091
|
+
b.style.color = '#888'; b.style.borderBottom = 'none'; b.classList.remove('active');
|
|
4074
4092
|
});
|
|
4075
|
-
btn.style.color = '#58a6ff';
|
|
4076
|
-
btn.style.borderBottom = '2px solid #58a6ff';
|
|
4077
|
-
btn.classList.add('active');
|
|
4093
|
+
btn.style.color = '#58a6ff'; btn.style.borderBottom = '2px solid #58a6ff'; btn.classList.add('active');
|
|
4078
4094
|
body.querySelectorAll('.tab-content').forEach(c => c.style.display = 'none');
|
|
4079
4095
|
const target = body.querySelector(`.tab-content.${tab}`);
|
|
4080
4096
|
if (target) target.style.display = 'block';
|
|
@@ -4083,6 +4099,12 @@
|
|
|
4083
4099
|
} else if (mod?.getStatus) {
|
|
4084
4100
|
const status = mod.getStatus();
|
|
4085
4101
|
body.innerHTML = `<div style="color:var(--text-secondary);line-height:1.8;">${JSON.stringify(status, null, 2).replace(/\n/g, '<br>')}</div>`;
|
|
4102
|
+
} else if (mod?.analyze || mod?.generate || mod?.search || mod?.execute) {
|
|
4103
|
+
// Module has methods but no UI — build a quick command panel
|
|
4104
|
+
const methods = Object.keys(mod).filter(k => typeof mod[k] === 'function');
|
|
4105
|
+
body.innerHTML = `<div style="margin-bottom:12px;"><input id="_mod_input_${moduleKey}" placeholder="Enter command or query..." style="width:100%;padding:8px 10px;border:1px solid var(--border-color);border-radius:5px;background:var(--bg-primary);color:var(--text-primary);font-size:12px;box-sizing:border-box;"></div>
|
|
4106
|
+
<div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px;">${methods.slice(0,8).map(m => `<button onclick="(async()=>{const r=await window.cycleCAD.${moduleKey}.${m}(document.getElementById('_mod_input_${moduleKey}').value);document.getElementById('_mod_out_${moduleKey}').textContent=JSON.stringify(r,null,2)})()" style="padding:4px 10px;border-radius:4px;border:1px solid var(--border-color);background:var(--bg-tertiary);color:var(--text-primary);cursor:pointer;font-size:11px;">${m}()</button>`).join('')}</div>
|
|
4107
|
+
<pre id="_mod_out_${moduleKey}" style="background:var(--bg-primary);border:1px solid var(--border-color);border-radius:5px;padding:10px;font-size:11px;color:var(--text-secondary);white-space:pre-wrap;max-height:300px;overflow-y:auto;margin:0;">Ready. Click a function above.</pre>`;
|
|
4086
4108
|
} else {
|
|
4087
4109
|
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>`;
|
|
4088
4110
|
}
|
|
@@ -5221,6 +5243,6 @@
|
|
|
5221
5243
|
</div>
|
|
5222
5244
|
</div>
|
|
5223
5245
|
|
|
5224
|
-
<span id="version-badge" style="position:fixed;bottom:42px;left:50%;transform:translateX(-50%);z-index:999;font-size:0.9rem;color:rgba(255,255,255,0.9);letter-spacing:0.1em;white-space:nowrap;padding:6px 16px;user-select:all;pointer-events:auto;font-family:monospace;font-weight:700;background:rgba(0,0,0,0.7);border:1px solid rgba(88,166,255,0.4);border-radius:6px;text-shadow:0 1px 3px rgba(0,0,0,0.5);" title="cycleCAD version">cycleCAD v1.0.
|
|
5246
|
+
<span id="version-badge" style="position:fixed;bottom:42px;left:50%;transform:translateX(-50%);z-index:999;font-size:0.9rem;color:rgba(255,255,255,0.9);letter-spacing:0.1em;white-space:nowrap;padding:6px 16px;user-select:all;pointer-events:auto;font-family:monospace;font-weight:700;background:rgba(0,0,0,0.7);border:1px solid rgba(88,166,255,0.4);border-radius:6px;text-shadow:0 1px 3px rgba(0,0,0,0.5);" title="cycleCAD version">cycleCAD v1.0.4</span>
|
|
5225
5247
|
</body>
|
|
5226
5248
|
</html>
|
package/app/js/ai-copilot.js
CHANGED
|
@@ -938,20 +938,29 @@ export async function executeTextCommand(prompt) {
|
|
|
938
938
|
return { ok: false };
|
|
939
939
|
}
|
|
940
940
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
941
|
+
addMessage('ai', `Got it! ${preview}. Creating now...`);
|
|
942
|
+
|
|
943
|
+
// Execute: try direct geometry creation first (fastest path)
|
|
944
|
+
const results = [];
|
|
945
|
+
for (const cmd of commands) {
|
|
946
|
+
try {
|
|
947
|
+
// Convert Agent API format {method: 'shape.cylinder', params: {}} to executeParsedPrompt format {type: 'cylinder', params: {}}
|
|
948
|
+
if (window._executeParsedPrompt) {
|
|
949
|
+
const method = cmd.method || '';
|
|
950
|
+
const type = method.replace('shape.', '').replace('feature.', '');
|
|
951
|
+
window._executeParsedPrompt({ type, params: cmd.params || {} });
|
|
952
|
+
results.push({ ok: true, method });
|
|
953
|
+
} else if (window.cycleCAD && window.cycleCAD.execute) {
|
|
954
|
+
const result = await window.cycleCAD.execute(cmd);
|
|
955
|
+
results.push(result);
|
|
956
|
+
}
|
|
957
|
+
} catch (e) {
|
|
958
|
+
console.warn('[Copilot] Command failed:', cmd, e);
|
|
959
|
+
results.push({ ok: false, error: e.message });
|
|
947
960
|
}
|
|
948
|
-
|
|
949
|
-
addMessage('ai', `Got it! ${preview}. Creating now...`);
|
|
950
|
-
return { ok: true, results, commands };
|
|
951
|
-
} else {
|
|
952
|
-
addMessage('ai', 'Agent API not available. Try initializing Agent API first.');
|
|
953
|
-
return { ok: false };
|
|
954
961
|
}
|
|
962
|
+
|
|
963
|
+
return { ok: true, results, commands };
|
|
955
964
|
} catch (error) {
|
|
956
965
|
console.error('[Copilot] Execute error:', error);
|
|
957
966
|
addMessage('ai', `Error: ${error.message || 'Something went wrong'}`);
|
package/package.json
CHANGED