@yemi33/minions 0.1.2255 → 0.1.2256
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/slim/js/projects.js +48 -35
- package/dashboard/slim/styles.css +41 -14
- package/package.json +1 -1
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
// Project context picker: populated from /api/status (which already returns
|
|
2
|
-
// the configured project list). One-or-more projects: a
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// add one. No auto-default: we never silently fall back to projects[0] /
|
|
2
|
+
// the configured project list). One-or-more projects: a row of selectable pill
|
|
3
|
+
// buttons, single-select, none active until the user explicitly picks one and
|
|
4
|
+
// can always be toggled back off to a "Select project" state. Zero-project: a
|
|
5
|
+
// hint to add one. No auto-default: we never silently fall back to projects[0] /
|
|
7
6
|
// last-used / constellation, so project-scoped CC actions can't land in the
|
|
8
7
|
// wrong project (W-mqayzsj3). Selection persists per-browser in localStorage
|
|
9
8
|
// and is included in every /api/command-center/stream call.
|
|
@@ -26,29 +25,33 @@
|
|
|
26
25
|
empty.textContent = 'No projects linked yet.';
|
|
27
26
|
return empty;
|
|
28
27
|
}
|
|
29
|
-
// Strip variant: project
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
sel.appendChild(placeholder);
|
|
28
|
+
// Strip variant: project pills. One selectable pill per project, single-select.
|
|
29
|
+
// No auto-default: when nothing is explicitly chosen, no pill is active and the
|
|
30
|
+
// indicator stays in the "Select project" state, so the picker never silently
|
|
31
|
+
// falls back to projects[0] (W-mqayzsj3) and the user can always toggle their
|
|
32
|
+
// choice back off. Returns a container of pill buttons built as real DOM nodes
|
|
33
|
+
// (no innerHTML — SEC-03 ratchet, see test/unit.test.js DYNAMIC_INNERHTML_BASELINE);
|
|
34
|
+
// the caller attaches a click listener via event delegation.
|
|
35
|
+
function makeContextPills(projects, selected, displayByName) {
|
|
36
|
+
var group = document.createElement('span');
|
|
37
|
+
group.id = 'chat-context-pills';
|
|
38
|
+
group.className = 'context-pills';
|
|
39
|
+
group.setAttribute('role', 'radiogroup');
|
|
40
|
+
group.setAttribute('aria-label', 'Working in project');
|
|
43
41
|
for (var i = 0; i < projects.length; i++) {
|
|
44
42
|
var p = projects[i];
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
var pill = document.createElement('button');
|
|
44
|
+
pill.type = 'button';
|
|
45
|
+
pill.className = 'context-pill';
|
|
46
|
+
pill.dataset.project = p;
|
|
47
|
+
pill.textContent = (displayByName && displayByName[p]) || p;
|
|
48
|
+
pill.setAttribute('role', 'radio');
|
|
49
|
+
var isActive = p === selected;
|
|
50
|
+
pill.classList.toggle('active', isActive);
|
|
51
|
+
pill.setAttribute('aria-checked', isActive ? 'true' : 'false');
|
|
52
|
+
group.appendChild(pill);
|
|
50
53
|
}
|
|
51
|
-
return
|
|
54
|
+
return group;
|
|
52
55
|
}
|
|
53
56
|
async function loadProjectsAndRenderContext(opts) {
|
|
54
57
|
var stripEl = document.getElementById('chat-context-strip');
|
|
@@ -77,23 +80,33 @@
|
|
|
77
80
|
try { localStorage.removeItem(SLIM_PROJECT_KEY); } catch (_e) {}
|
|
78
81
|
}
|
|
79
82
|
// No auto-default: when nothing is explicitly selected, currentProject
|
|
80
|
-
// stays null and
|
|
81
|
-
//
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
var
|
|
83
|
+
// stays null and no pill is active (the "Select project" state). We
|
|
84
|
+
// deliberately do NOT fall back to projects[0] here (W-mqayzsj3) so CC
|
|
85
|
+
// turns and project-scoped actions don't silently target the wrong
|
|
86
|
+
// project.
|
|
87
|
+
var pills = makeContextPills(projects, currentProject, displayByName);
|
|
85
88
|
stripEl.style.display = '';
|
|
86
|
-
controlsEl.replaceChildren(
|
|
87
|
-
|
|
88
|
-
var
|
|
89
|
-
if (
|
|
89
|
+
controlsEl.replaceChildren(pills, makeContextAddBtn());
|
|
90
|
+
pills.addEventListener('click', function(ev) {
|
|
91
|
+
var pill = ev.target.closest('.context-pill');
|
|
92
|
+
if (!pill || !pills.contains(pill)) return;
|
|
93
|
+
var val = pill.dataset.project || '';
|
|
94
|
+
if (val && val !== currentProject) {
|
|
95
|
+
// Select this project.
|
|
90
96
|
currentProject = val;
|
|
91
97
|
try { localStorage.setItem(SLIM_PROJECT_KEY, currentProject); } catch (_e) {}
|
|
92
98
|
} else {
|
|
93
|
-
//
|
|
99
|
+
// Re-clicking the active pill toggles back to "Select project" —
|
|
100
|
+
// drop the persisted choice so nothing is selected.
|
|
94
101
|
currentProject = null;
|
|
95
102
|
try { localStorage.removeItem(SLIM_PROJECT_KEY); } catch (_e) {}
|
|
96
103
|
}
|
|
104
|
+
var nodes = pills.querySelectorAll('.context-pill');
|
|
105
|
+
for (var j = 0; j < nodes.length; j++) {
|
|
106
|
+
var active = nodes[j].dataset.project === currentProject;
|
|
107
|
+
nodes[j].classList.toggle('active', active);
|
|
108
|
+
nodes[j].setAttribute('aria-checked', active ? 'true' : 'false');
|
|
109
|
+
}
|
|
97
110
|
});
|
|
98
111
|
}
|
|
99
112
|
var addBtn = document.getElementById('chat-context-add');
|
|
@@ -496,27 +496,54 @@
|
|
|
496
496
|
font-weight: 700;
|
|
497
497
|
font-size: var(--text-base);
|
|
498
498
|
}
|
|
499
|
-
|
|
499
|
+
/* Pills + "+ Add" lay out in a single row next to the "Working in" label
|
|
500
|
+
(W-mqsdptzy / PR #366). #chat-context-controls is a plain <span>, so
|
|
501
|
+
without an explicit flex the display:flex .context-pills (a block-level
|
|
502
|
+
flex container) pushed the "+ Add" sibling onto its own line below. */
|
|
503
|
+
.chat-context-strip #chat-context-controls {
|
|
504
|
+
display: flex;
|
|
505
|
+
align-items: center;
|
|
506
|
+
gap: var(--space-2);
|
|
507
|
+
flex-wrap: wrap;
|
|
508
|
+
min-width: 0;
|
|
509
|
+
}
|
|
510
|
+
.chat-context-strip .context-pills {
|
|
511
|
+
display: flex;
|
|
512
|
+
align-items: center;
|
|
513
|
+
gap: var(--space-2);
|
|
514
|
+
flex-wrap: wrap;
|
|
515
|
+
}
|
|
516
|
+
/* Project pills: outlined by default, filled/highlighted when active.
|
|
517
|
+
Single-select — exactly one (or zero) carries .active at a time. */
|
|
518
|
+
.chat-context-strip .context-pill {
|
|
500
519
|
background: var(--bg);
|
|
501
520
|
color: var(--text);
|
|
502
521
|
border: 1px solid var(--border);
|
|
503
|
-
border-radius:
|
|
504
|
-
padding: 4px
|
|
522
|
+
border-radius: 999px;
|
|
523
|
+
padding: 4px 12px;
|
|
505
524
|
font-family: inherit;
|
|
506
525
|
font-size: var(--text-base);
|
|
526
|
+
line-height: 1;
|
|
507
527
|
cursor: pointer;
|
|
528
|
+
transition: background 0.12s, border-color 0.12s, color 0.12s;
|
|
529
|
+
}
|
|
530
|
+
.chat-context-strip .context-pill:hover {
|
|
531
|
+
border-color: var(--blue);
|
|
532
|
+
background: var(--surface2);
|
|
533
|
+
}
|
|
534
|
+
.chat-context-strip .context-pill:focus-visible {
|
|
535
|
+
outline: none;
|
|
536
|
+
border-color: var(--blue);
|
|
537
|
+
}
|
|
538
|
+
.chat-context-strip .context-pill.active {
|
|
539
|
+
background: var(--blue);
|
|
540
|
+
border-color: var(--blue);
|
|
541
|
+
color: #fff;
|
|
542
|
+
font-weight: 600;
|
|
543
|
+
}
|
|
544
|
+
.chat-context-strip .context-pill.active:hover {
|
|
545
|
+
background: var(--blue);
|
|
508
546
|
}
|
|
509
|
-
.chat-context-strip select:focus { outline: none; border-color: var(--blue); }
|
|
510
|
-
/* Italicize the "Select project" placeholder option AND the closed select
|
|
511
|
-
widget while the placeholder is the active value. `:has()` is needed
|
|
512
|
-
because native <select> rendering ignores child <option> styles for the
|
|
513
|
-
displayed (closed) text — we have to style the <select> itself. The
|
|
514
|
-
explicit `option { font-style: normal }` reset stops real project names
|
|
515
|
-
from inheriting the parent select's italic when the dropdown is opened
|
|
516
|
-
while the placeholder is still selected. */
|
|
517
|
-
.chat-context-strip select option { font-style: normal; color: var(--text); }
|
|
518
|
-
.chat-context-strip select option[value=""] { font-style: italic; color: var(--muted); }
|
|
519
|
-
.chat-context-strip select:has(option[value=""]:checked) { font-style: italic; color: var(--muted); }
|
|
520
547
|
.chat-context-strip .context-static {
|
|
521
548
|
color: var(--text);
|
|
522
549
|
font-weight: 500;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2256",
|
|
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"
|