@yemi33/minions 0.1.2194 → 0.1.2195
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/dashboard/js/command-center.js +2 -0
- package/dashboard/js/fre.js +125 -1
- package/dashboard/js/refresh.js +6 -0
- package/package.json +1 -1
|
@@ -476,6 +476,8 @@ function ccAbort() {
|
|
|
476
476
|
|
|
477
477
|
function toggleCommandCenter() {
|
|
478
478
|
_ccOpen = !_ccOpen;
|
|
479
|
+
// Opening CC means the operator found it — retire the first-use coachmark.
|
|
480
|
+
if (_ccOpen && typeof dismissCcHint === 'function') dismissCcHint();
|
|
479
481
|
var drawer = document.getElementById('cc-drawer');
|
|
480
482
|
var overlay = document.getElementById('cc-overlay');
|
|
481
483
|
if (_ccOpen) ccApplySavedWidth();
|
package/dashboard/js/fre.js
CHANGED
|
@@ -188,4 +188,128 @@ function renderFre(statusOrProjects) {
|
|
|
188
188
|
'</div>';
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
// ── Command Center first-use coachmark ──────────────────────────────────────
|
|
192
|
+
// A small popup anchored under the Command Center header button, shown to
|
|
193
|
+
// brand-new operators who have never used CC. Teaches the primary entry point:
|
|
194
|
+
// "prompt the Command Center to ask it to dispatch work." Self-contained and
|
|
195
|
+
// idempotent — safe to call renderCcHint() every refresh tick.
|
|
196
|
+
//
|
|
197
|
+
// Trigger: NOT dismissed AND the operator has never sent a CC message (no
|
|
198
|
+
// 'cc-tabs' entry carries any messages). Auto-suppressed while the CC drawer
|
|
199
|
+
// is open. Dismissed permanently when the user opens CC (see
|
|
200
|
+
// toggleCommandCenter in command-center.js) or clicks "Got it".
|
|
201
|
+
|
|
202
|
+
const CC_HINT_DISMISS_KEY = 'minions_cc_hint_dismissed';
|
|
203
|
+
const CC_HINT_MOUNT_ID = 'cc-hint-coachmark';
|
|
204
|
+
|
|
205
|
+
function _ccHintIsDismissed() {
|
|
206
|
+
try { return localStorage.getItem(CC_HINT_DISMISS_KEY) === '1'; } catch { return false; }
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// "Brand new" = the operator has never sent a Command Center message. Reads the
|
|
210
|
+
// same 'cc-tabs' localStorage key command-center.js persists; any tab carrying
|
|
211
|
+
// at least one message means CC has been used and the hint has served its
|
|
212
|
+
// purpose. Absent/empty/parse-error all read as new (fail toward showing).
|
|
213
|
+
function _ccHintUserIsNew() {
|
|
214
|
+
try {
|
|
215
|
+
const raw = localStorage.getItem('cc-tabs');
|
|
216
|
+
if (!raw) return true;
|
|
217
|
+
const tabs = JSON.parse(raw);
|
|
218
|
+
if (!Array.isArray(tabs) || tabs.length === 0) return true;
|
|
219
|
+
return !tabs.some(function(t) { return t && Array.isArray(t.messages) && t.messages.length > 0; });
|
|
220
|
+
} catch { return true; }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function _ccHintRemove() {
|
|
224
|
+
const mount = document.getElementById(CC_HINT_MOUNT_ID);
|
|
225
|
+
if (mount && mount.parentNode) mount.parentNode.removeChild(mount);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function dismissCcHint() {
|
|
229
|
+
try { localStorage.setItem(CC_HINT_DISMISS_KEY, '1'); } catch { /* expected */ }
|
|
230
|
+
_ccHintRemove();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Reset helper (exposed for tests / debugging only). Not wired to UI.
|
|
234
|
+
function _ccHintReset() {
|
|
235
|
+
try { localStorage.removeItem(CC_HINT_DISMISS_KEY); } catch { /* expected */ }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Open the Command Center from the coachmark CTA, then dismiss the hint.
|
|
239
|
+
function openCcFromHint() {
|
|
240
|
+
dismissCcHint();
|
|
241
|
+
if (typeof toggleCommandCenter === 'function' && !window._ccOpen) {
|
|
242
|
+
try { toggleCommandCenter(); } catch { /* drawer not mounted yet */ }
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Re-anchor the coachmark under the CC button. Called on render and on resize.
|
|
247
|
+
function _ccHintPosition() {
|
|
248
|
+
const mount = document.getElementById(CC_HINT_MOUNT_ID);
|
|
249
|
+
const btn = document.getElementById('cc-toggle-btn');
|
|
250
|
+
if (!mount || !btn) return;
|
|
251
|
+
const rect = btn.getBoundingClientRect();
|
|
252
|
+
mount.style.top = (rect.bottom + 10) + 'px';
|
|
253
|
+
// Right-align the card to the button's right edge.
|
|
254
|
+
mount.style.right = Math.max(8, window.innerWidth - rect.right) + 'px';
|
|
255
|
+
// Point the caret at the button's horizontal centre.
|
|
256
|
+
const arrow = document.getElementById('cc-hint-arrow');
|
|
257
|
+
if (arrow) arrow.style.right = Math.max(12, (rect.width / 2) - 6) + 'px';
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
let _ccHintResizeBound = false;
|
|
261
|
+
|
|
262
|
+
// Render the coachmark into document.body. Idempotent — bails out (and removes
|
|
263
|
+
// any stale mount) when dismissed, when CC has been used, when the header
|
|
264
|
+
// button isn't mounted yet, or while the drawer is open.
|
|
265
|
+
function renderCcHint() {
|
|
266
|
+
if (_ccHintIsDismissed() || !_ccHintUserIsNew()) {
|
|
267
|
+
_ccHintRemove();
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const btn = document.getElementById('cc-toggle-btn');
|
|
271
|
+
if (!btn) return; // header not assembled yet
|
|
272
|
+
const drawer = document.getElementById('cc-drawer');
|
|
273
|
+
if (drawer && drawer.style.display === 'flex') {
|
|
274
|
+
// User already found CC — don't hover the hint over the open drawer.
|
|
275
|
+
_ccHintRemove();
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
let mount = document.getElementById(CC_HINT_MOUNT_ID);
|
|
280
|
+
if (!mount) {
|
|
281
|
+
mount = document.createElement('div');
|
|
282
|
+
mount.id = CC_HINT_MOUNT_ID;
|
|
283
|
+
mount.style.cssText = [
|
|
284
|
+
'position:fixed',
|
|
285
|
+
'z-index:330',
|
|
286
|
+
'width:260px',
|
|
287
|
+
'padding:14px 16px',
|
|
288
|
+
'background:var(--surface)',
|
|
289
|
+
'border:1px solid var(--blue)',
|
|
290
|
+
'border-radius:var(--radius-lg)',
|
|
291
|
+
'box-shadow:var(--shadow-md)',
|
|
292
|
+
'color:var(--text)',
|
|
293
|
+
'font-size:var(--text-md)',
|
|
294
|
+
'line-height:1.5',
|
|
295
|
+
].join(';');
|
|
296
|
+
document.body.appendChild(mount);
|
|
297
|
+
// eslint-disable-next-line no-unsanitized/property -- reason: static string literal — no user-controlled data is interpolated
|
|
298
|
+
mount.innerHTML =
|
|
299
|
+
'<div id="cc-hint-arrow" style="position:absolute;top:-7px;width:12px;height:12px;background:var(--surface);border-left:1px solid var(--blue);border-top:1px solid var(--blue);transform:rotate(45deg)"></div>' +
|
|
300
|
+
'<div style="font-weight:700;color:var(--blue);margin-bottom:4px">👋 Start here</div>' +
|
|
301
|
+
'<div style="color:var(--text)">Prompt your <strong>Command Center</strong> here to ask it to dispatch work.</div>' +
|
|
302
|
+
'<div style="display:flex;gap:8px;margin-top:12px">' +
|
|
303
|
+
'<button onclick="openCcFromHint()" class="btn-primary-solid" style="padding:5px 12px;font-size:var(--text-sm)">Open Command Center</button>' +
|
|
304
|
+
'<button onclick="dismissCcHint()" style="padding:5px 12px;font-size:var(--text-sm);background:transparent;color:var(--muted);border:1px solid var(--border);border-radius:var(--radius-sm);cursor:pointer">Got it</button>' +
|
|
305
|
+
'</div>';
|
|
306
|
+
}
|
|
307
|
+
_ccHintPosition();
|
|
308
|
+
if (!_ccHintResizeBound) {
|
|
309
|
+
_ccHintResizeBound = true;
|
|
310
|
+
window.addEventListener('resize', _ccHintPosition);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
window.MinionsFre = { renderFre, dismissFre, openSettingsToDefaultCli, _freReset, FRE_DISMISS_KEY,
|
|
315
|
+
renderCcHint, dismissCcHint, openCcFromHint, _ccHintReset, _ccHintUserIsNew, CC_HINT_DISMISS_KEY };
|
package/dashboard/js/refresh.js
CHANGED
|
@@ -612,6 +612,12 @@ function _processStatusUpdate(data, opts) {
|
|
|
612
612
|
if (typeof renderFre === 'function') {
|
|
613
613
|
_safeRender('fre', function() { renderFre(data); });
|
|
614
614
|
}
|
|
615
|
+
// Command Center first-use coachmark — anchored under the CC header button
|
|
616
|
+
// for brand-new operators who have never sent a CC message. Idempotent +
|
|
617
|
+
// cheap; self-suppresses once CC is used or dismissed.
|
|
618
|
+
if (typeof renderCcHint === 'function') {
|
|
619
|
+
_safeRender('ccHint', function() { renderCcHint(); });
|
|
620
|
+
}
|
|
615
621
|
// Notes file (notes.md) is now sourced from /state/notes.md. Same shape
|
|
616
622
|
// as the legacy /api/status notes slice ({ content, updatedAt }); the
|
|
617
623
|
// ETag mtime is parsed out of the response header for updatedAt.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2195",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|