clementine-agent 1.3.0 → 1.3.1
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/dist/cli/dashboard.js +77 -23
- package/package.json +1 -1
package/dist/cli/dashboard.js
CHANGED
|
@@ -11333,7 +11333,7 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
11333
11333
|
<span id="builder-agent-label" style="padding:0;font-size:13px;color:var(--text-secondary);font-weight:500"></span>
|
|
11334
11334
|
<input type="hidden" id="builder-agent" value="">
|
|
11335
11335
|
<span style="flex:1"></span>
|
|
11336
|
-
<button class="btn-sm" onclick="
|
|
11336
|
+
<button class="btn-sm btn-primary" onclick="newFromBuildHeader()" title="Create a new artifact for this tab" style="padding:4px 14px;border-radius:6px;cursor:pointer;font-size:12px">New</button>
|
|
11337
11337
|
<button class="btn-sm" id="builder-test-btn" onclick="testBuilderSkill()" style="background:var(--bg-tertiary);border:1px solid var(--border);color:var(--text-secondary);padding:4px 12px;border-radius:6px;cursor:pointer;font-size:12px;display:none">Test</button>
|
|
11338
11338
|
<button class="btn-sm btn-primary" id="builder-save-btn" onclick="saveBuilderArtifact()" style="padding:4px 16px;font-size:12px;display:none">Save</button>
|
|
11339
11339
|
</div>
|
|
@@ -11402,7 +11402,15 @@ if('serviceWorker' in navigator){navigator.serviceWorker.getRegistrations().then
|
|
|
11402
11402
|
<div onclick="_builderAddNodeOfKind('loop')" class="builder-palette-item" data-kind="loop">loop</div>
|
|
11403
11403
|
</div>
|
|
11404
11404
|
<!-- Slide-out config panel -->
|
|
11405
|
-
<div id="builder-config-panel" style="display:none;position:absolute;right:0;top:0;bottom:0;width:340px;background:var(--bg-secondary);border-left:1px solid var(--border);box-shadow:-4px 0 16px rgba(0,0,0,0.15);z-index:12;
|
|
11405
|
+
<div id="builder-config-panel" style="display:none;position:absolute;right:0;top:0;bottom:0;width:340px;background:var(--bg-secondary);border-left:1px solid var(--border);box-shadow:-4px 0 16px rgba(0,0,0,0.15);z-index:12;flex-direction:column"></div>
|
|
11406
|
+
<!-- Empty-state CTA — visible when no workflow is open on the canvas -->
|
|
11407
|
+
<div id="builder-canvas-empty" style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:14px;color:var(--text-muted);text-align:center;padding:32px;pointer-events:none">
|
|
11408
|
+
<div style="font-size:38px;opacity:0.4">🔗</div>
|
|
11409
|
+
<div style="font-size:14px;font-weight:500;color:var(--text-secondary)">No workflow open</div>
|
|
11410
|
+
<div style="font-size:12px;line-height:1.5;max-width:280px">
|
|
11411
|
+
Pick one from the dropdown above — or click <strong>New</strong> in the header to create one from scratch, or open the <strong>Templates</strong> tab for starter patterns.
|
|
11412
|
+
</div>
|
|
11413
|
+
</div>
|
|
11406
11414
|
<div id="builder-canvas-footer" style="padding:6px 14px;border-top:1px solid var(--border);font-size:11px;color:var(--text-muted);display:flex;gap:14px;align-items:center">
|
|
11407
11415
|
<span id="builder-canvas-status"></span>
|
|
11408
11416
|
<span style="flex:1"></span>
|
|
@@ -14005,6 +14013,9 @@ function switchBuildTab(tab) {
|
|
|
14005
14013
|
var workPane = document.getElementById('build-tab-workflows');
|
|
14006
14014
|
var tplPane = document.getElementById('build-tab-templates');
|
|
14007
14015
|
var headerStrip = document.getElementById('build-header-strip');
|
|
14016
|
+
// Always close any open workflow when changing tabs — switching context
|
|
14017
|
+
// is a clean slate, not a stale node hanging on the canvas.
|
|
14018
|
+
if (typeof closeBuilderCanvas === 'function') closeBuilderCanvas();
|
|
14008
14019
|
if (tab === 'templates') {
|
|
14009
14020
|
if (workPane) workPane.style.display = 'none';
|
|
14010
14021
|
if (tplPane) tplPane.style.display = '';
|
|
@@ -14025,6 +14036,11 @@ function switchBuildTab(tab) {
|
|
|
14025
14036
|
updateBuilderMode();
|
|
14026
14037
|
}
|
|
14027
14038
|
}
|
|
14039
|
+
// Preload Drawflow eagerly so the canvas is responsive when the
|
|
14040
|
+
// user picks a workflow (rather than waiting for the lazy load).
|
|
14041
|
+
if (typeof _ensureDrawflowLoaded === 'function') {
|
|
14042
|
+
_ensureDrawflowLoaded().catch(function() { /* */ });
|
|
14043
|
+
}
|
|
14028
14044
|
// Focus chat input
|
|
14029
14045
|
setTimeout(function() {
|
|
14030
14046
|
var bi = document.getElementById('builder-input');
|
|
@@ -14033,6 +14049,38 @@ function switchBuildTab(tab) {
|
|
|
14033
14049
|
}
|
|
14034
14050
|
}
|
|
14035
14051
|
|
|
14052
|
+
// "New" button in the Build header strip — context-aware: prompts for a
|
|
14053
|
+
// name and creates the right artifact for the active tab. Workflows + Crons
|
|
14054
|
+
// route through the workflow_create surface; Skills falls back to the
|
|
14055
|
+
// existing chat-based Skill Studio reset.
|
|
14056
|
+
async function newFromBuildHeader() {
|
|
14057
|
+
var activeTab = document.querySelector('#build-tabs button.active')?.getAttribute('data-build-tab') || 'workflows';
|
|
14058
|
+
if (activeTab === 'skills') {
|
|
14059
|
+
if (typeof resetBuilder === 'function') resetBuilder();
|
|
14060
|
+
var bi = document.getElementById('builder-input');
|
|
14061
|
+
if (bi) bi.focus();
|
|
14062
|
+
return;
|
|
14063
|
+
}
|
|
14064
|
+
if (activeTab === 'templates') {
|
|
14065
|
+
toast('Pick a template to fork from the cards.', 'info');
|
|
14066
|
+
return;
|
|
14067
|
+
}
|
|
14068
|
+
var noun = activeTab === 'crons' ? 'cron' : 'workflow';
|
|
14069
|
+
var name = prompt('Name your new ' + noun + ':');
|
|
14070
|
+
if (!name || !name.trim()) return;
|
|
14071
|
+
try {
|
|
14072
|
+
var body = { name: name.trim() };
|
|
14073
|
+
if (activeTab === 'crons') body.schedule = '0 9 * * *'; // sensible default; user edits in canvas
|
|
14074
|
+
var r = await apiJson('POST', '/api/builder/workflows', body);
|
|
14075
|
+
if (r && r.error) { toast('Create failed: ' + r.error, 'error'); return; }
|
|
14076
|
+
if (r && r.id) {
|
|
14077
|
+
await refreshBuilderCanvasPicker(activeTab === 'crons' ? 'cron' : 'workflow');
|
|
14078
|
+
await openBuilderWorkflow(r.id);
|
|
14079
|
+
toast('Created ' + noun + ': ' + name, 'success');
|
|
14080
|
+
}
|
|
14081
|
+
} catch (err) { toast('Create error: ' + err, 'error'); }
|
|
14082
|
+
}
|
|
14083
|
+
|
|
14036
14084
|
// ── Build templates: fork a starter pattern into a new workflow ─────
|
|
14037
14085
|
async function forkBuildTemplate(templateId) {
|
|
14038
14086
|
var templates = {
|
|
@@ -18287,6 +18335,9 @@ async function openBuilderWorkflow(id) {
|
|
|
18287
18335
|
function _renderBuilderCanvas(drawflowData) {
|
|
18288
18336
|
var host = document.getElementById('builder-canvas');
|
|
18289
18337
|
if (!host) return;
|
|
18338
|
+
// Hide empty-state CTA — there's a workflow open now.
|
|
18339
|
+
var empty = document.getElementById('builder-canvas-empty');
|
|
18340
|
+
if (empty) empty.style.display = 'none';
|
|
18290
18341
|
// Tear down previous editor
|
|
18291
18342
|
if (_builderCanvasEditor) {
|
|
18292
18343
|
try { _builderCanvasEditor.clear(); } catch (e) { /* ignore */ }
|
|
@@ -18394,35 +18445,30 @@ function _updateBuilderBannerFromValidation(v) {
|
|
|
18394
18445
|
}
|
|
18395
18446
|
|
|
18396
18447
|
function _decorateBuilderNodes(host, wf) {
|
|
18397
|
-
if (!wf) return;
|
|
18448
|
+
if (!wf || !_builderCanvasEditor) return;
|
|
18449
|
+
// Pull each Drawflow node's data via the editor (which preserves the
|
|
18450
|
+
// stepId we set in stepToNodeData on the server side). Earlier code tried
|
|
18451
|
+
// to recover stepId from a df-stepId input, which Drawflow doesn't emit
|
|
18452
|
+
// unless you use templates — so every node decorated with the same step.
|
|
18453
|
+
// Now we look the step up by stepId directly.
|
|
18398
18454
|
var byStepId = {};
|
|
18399
18455
|
for (var i = 0; i < wf.steps.length; i++) byStepId[wf.steps[i].id] = wf.steps[i];
|
|
18400
|
-
|
|
18456
|
+
var allData = _builderCanvasEditor.export();
|
|
18457
|
+
var nodeData = (allData && allData.drawflow && allData.drawflow.Home && allData.drawflow.Home.data) || {};
|
|
18401
18458
|
var nodes = host.querySelectorAll('.drawflow-node');
|
|
18402
18459
|
nodes.forEach(function(nodeEl) {
|
|
18403
18460
|
var contentEl = nodeEl.querySelector('.drawflow_content_node');
|
|
18404
18461
|
if (!contentEl || contentEl.dataset._decorated) return;
|
|
18405
18462
|
contentEl.dataset._decorated = '1';
|
|
18406
|
-
var
|
|
18407
|
-
var
|
|
18408
|
-
|
|
18409
|
-
var
|
|
18410
|
-
var kind =
|
|
18411
|
-
var title = '';
|
|
18412
|
-
var body =
|
|
18413
|
-
var matchedStep = null;
|
|
18414
|
-
for (var j = 0; j < wf.steps.length; j++) {
|
|
18415
|
-
var s = wf.steps[j];
|
|
18416
|
-
if ((s.kind || 'prompt') === kind) { matchedStep = s; break; }
|
|
18417
|
-
}
|
|
18418
|
-
if (!matchedStep) {
|
|
18419
|
-
// Best-effort: use first step
|
|
18420
|
-
matchedStep = wf.steps[0];
|
|
18421
|
-
}
|
|
18422
|
-
title = (matchedStep ? matchedStep.id : '?');
|
|
18423
|
-
body = _summarizeStep(matchedStep, kind);
|
|
18463
|
+
var numericId = (nodeEl.id || '').replace(/^node-/, '');
|
|
18464
|
+
var data = (nodeData[numericId] && nodeData[numericId].data) || {};
|
|
18465
|
+
var stepId = data.stepId || null;
|
|
18466
|
+
var step = stepId ? byStepId[stepId] : null;
|
|
18467
|
+
var kind = (data.kind || (step && step.kind) || 'prompt');
|
|
18468
|
+
var title = step ? step.id : (stepId || '?');
|
|
18469
|
+
var body = _summarizeStep(step || data, kind);
|
|
18424
18470
|
contentEl.innerHTML =
|
|
18425
|
-
'<div style="font-weight:600;font-size:12px;margin-bottom:4px;color:#fff;text-transform:lowercase">' + esc(kind) + '
|
|
18471
|
+
'<div style="font-weight:600;font-size:12px;margin-bottom:4px;color:#fff;text-transform:lowercase">' + esc(kind) + ' · ' + esc(title) + '</div>' +
|
|
18426
18472
|
'<div style="font-size:11px;color:rgba(255,255,255,0.85);line-height:1.35;max-height:80px;overflow:hidden">' + esc(body) + '</div>';
|
|
18427
18473
|
});
|
|
18428
18474
|
}
|
|
@@ -18450,6 +18496,14 @@ function closeBuilderCanvas() {
|
|
|
18450
18496
|
if (idEl) idEl.textContent = '';
|
|
18451
18497
|
var banner = document.getElementById('builder-canvas-banner');
|
|
18452
18498
|
if (banner) banner.style.display = 'none';
|
|
18499
|
+
// Reset picker if it has a stale selection
|
|
18500
|
+
var picker = document.getElementById('builder-canvas-picker');
|
|
18501
|
+
if (picker && picker.value) picker.value = '';
|
|
18502
|
+
// Close config panel if it was open
|
|
18503
|
+
if (typeof _closeNodeConfigPanel === 'function') _closeNodeConfigPanel();
|
|
18504
|
+
// Show empty-state CTA
|
|
18505
|
+
var empty = document.getElementById('builder-canvas-empty');
|
|
18506
|
+
if (empty) empty.style.display = 'flex';
|
|
18453
18507
|
}
|
|
18454
18508
|
|
|
18455
18509
|
async function validateBuilderCanvas() {
|