@yemi33/minions 0.1.1682 → 0.1.1683
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/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,33 @@ let _skillsTab = 'all';
|
|
|
4
4
|
let _skillsPage = 0;
|
|
5
5
|
const SKILLS_PER_PAGE = 5;
|
|
6
6
|
|
|
7
|
+
// Per-runtime tabs that fold native and plugin skills into one bucket — agents
|
|
8
|
+
// see "skills my Claude/Copilot install can use" rather than discovery-source
|
|
9
|
+
// trivia. Project tabs are added dynamically per configured project.
|
|
10
|
+
const SOURCE_META = {
|
|
11
|
+
'claude-code': { icon: '⚡', label: 'claude', group: 'claude' },
|
|
12
|
+
'plugin': { icon: '🔌', label: 'claude plugin', group: 'claude' },
|
|
13
|
+
'copilot': { icon: '🤖', label: 'copilot', group: 'copilot' },
|
|
14
|
+
'copilot-plugin': { icon: '🔌', label: 'copilot plugin', group: 'copilot' },
|
|
15
|
+
'agent-skill': { icon: '🤝', label: 'agent', group: 'agent' },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function _skillMetaOf(s) {
|
|
19
|
+
if (SOURCE_META[s]) return SOURCE_META[s];
|
|
20
|
+
if (s && s.startsWith('project:')) {
|
|
21
|
+
const name = s.slice('project:'.length);
|
|
22
|
+
return { icon: '📁', label: name, group: name };
|
|
23
|
+
}
|
|
24
|
+
return { icon: '🔧', label: 'unknown', group: 'unknown' };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Inline onclick handlers run in HTML-attr-then-JS context. escHtml alone is
|
|
28
|
+
// unsafe (apostrophes survive into the JS string). JSON.stringify produces a
|
|
29
|
+
// valid JS literal; HTML-escaping that literal is safe in either context.
|
|
30
|
+
function _jsArg(value) {
|
|
31
|
+
return escHtml(JSON.stringify(value == null ? '' : String(value)));
|
|
32
|
+
}
|
|
33
|
+
|
|
7
34
|
function renderSkills(skills) {
|
|
8
35
|
const el = document.getElementById('skills-list');
|
|
9
36
|
const countEl = document.getElementById('skills-count');
|
|
@@ -13,32 +40,21 @@ function renderSkills(skills) {
|
|
|
13
40
|
return;
|
|
14
41
|
}
|
|
15
42
|
|
|
16
|
-
const SOURCE_META = {
|
|
17
|
-
'claude-code': { icon: '⚡', label: 'global', group: 'global' },
|
|
18
|
-
'copilot': { icon: '🤖', label: 'copilot', group: 'copilot' },
|
|
19
|
-
'agent-skill': { icon: '🤝', label: 'agent', group: 'agent' },
|
|
20
|
-
'plugin': { icon: '🔌', label: 'plugin', group: 'plugins' },
|
|
21
|
-
'copilot-plugin': { icon: '🤖', label: 'copilot', group: 'copilot' },
|
|
22
|
-
};
|
|
23
|
-
const metaOf = (s) => {
|
|
24
|
-
if (SOURCE_META[s]) return SOURCE_META[s];
|
|
25
|
-
if (s && s.startsWith('project:')) {
|
|
26
|
-
const name = s.slice('project:'.length);
|
|
27
|
-
return { icon: '📁', label: name, group: name };
|
|
28
|
-
}
|
|
29
|
-
return { icon: '🔧', label: 'global', group: 'global' };
|
|
30
|
-
};
|
|
31
|
-
const sourceIcon = (s) => metaOf(s).icon;
|
|
32
|
-
const sourceLabel = (s) => metaOf(s).label;
|
|
33
|
-
|
|
34
43
|
// Group by source
|
|
35
44
|
const groups = {};
|
|
36
45
|
for (const r of skills) {
|
|
37
|
-
const key =
|
|
46
|
+
const key = _skillMetaOf(r.source).group;
|
|
38
47
|
if (!groups[key]) groups[key] = [];
|
|
39
48
|
groups[key].push(r);
|
|
40
49
|
}
|
|
41
|
-
const groupKeys = Object.keys(groups).sort((a, b) =>
|
|
50
|
+
const groupKeys = Object.keys(groups).sort((a, b) => {
|
|
51
|
+
const order = ['claude', 'copilot', 'agent'];
|
|
52
|
+
const ai = order.indexOf(a), bi = order.indexOf(b);
|
|
53
|
+
if (ai >= 0 && bi >= 0) return ai - bi;
|
|
54
|
+
if (ai >= 0) return -1;
|
|
55
|
+
if (bi >= 0) return 1;
|
|
56
|
+
return a.localeCompare(b);
|
|
57
|
+
});
|
|
42
58
|
|
|
43
59
|
// Tab bar
|
|
44
60
|
const tabs = [{ key: 'all', label: 'All (' + skills.length + ')' }];
|
|
@@ -49,10 +65,18 @@ function renderSkills(skills) {
|
|
|
49
65
|
const active = _skillsTab === t.key;
|
|
50
66
|
html += '<button class="pr-pager-btn" style="font-size:9px;padding:2px 8px;' +
|
|
51
67
|
(active ? 'background:var(--green);color:#fff;border-color:var(--green)' : '') +
|
|
52
|
-
'" onclick="
|
|
68
|
+
'" onclick="_skillsSelectTab(' + _jsArg(t.key) + ')">' + escHtml(t.label) + '</button>';
|
|
53
69
|
}
|
|
54
70
|
html += '</div>';
|
|
55
71
|
|
|
72
|
+
// Note clarifying skill visibility — agents read these on demand, runtime
|
|
73
|
+
// assets (~/.claude/skills, ~/.copilot/skills) are not auto-injected for
|
|
74
|
+
// the OTHER runtime. A Copilot agent only sees Copilot-native + plugin skills.
|
|
75
|
+
html += '<div style="font-size:9px;color:var(--muted);margin-bottom:8px;line-height:1.4">' +
|
|
76
|
+
'Skills are reference docs agents read on demand — they are not injected wholesale into prompts. ' +
|
|
77
|
+
'Each tab reflects what the matching runtime would see; cross-runtime skills are NOT visible to a different runtime.' +
|
|
78
|
+
'</div>';
|
|
79
|
+
|
|
56
80
|
// Filter by tab
|
|
57
81
|
const filtered = _skillsTab === 'all' ? skills : (groups[_skillsTab] || []);
|
|
58
82
|
|
|
@@ -63,10 +87,11 @@ function renderSkills(skills) {
|
|
|
63
87
|
|
|
64
88
|
html += '<div style="display:flex;flex-direction:column;gap:6px">';
|
|
65
89
|
for (const r of page) {
|
|
90
|
+
const meta = _skillMetaOf(r.source);
|
|
66
91
|
const autoTag = r.autoGenerated ? '<span style="font-size:8px;background:rgba(63,185,80,0.15);color:var(--green);padding:1px 4px;border-radius:3px;margin-left:4px">auto</span>' : '';
|
|
67
|
-
html += '<div class="inbox-item" onclick="openSkill(
|
|
68
|
-
'<div class="inbox-name"><span style="color:var(--green);font-weight:600">' +
|
|
69
|
-
'<span style="font-size:9px;color:var(--muted);margin-left:auto">' + escHtml(
|
|
92
|
+
html += '<div class="inbox-item" onclick="openSkill(' + _jsArg(r.file) + ',' + _jsArg(r.source || 'claude-code') + ',' + _jsArg(r.dir || '') + ')" style="border-left-color:var(--green)">' +
|
|
93
|
+
'<div class="inbox-name"><span style="color:var(--green);font-weight:600">' + meta.icon + ' ' + escHtml(r.name) + '</span>' + autoTag +
|
|
94
|
+
'<span style="font-size:9px;color:var(--muted);margin-left:auto">' + escHtml(meta.label) + '</span>' +
|
|
70
95
|
'</div>' +
|
|
71
96
|
(r.description ? '<div class="inbox-preview" style="color:var(--text)">' + escHtml(r.description) + '</div>' : '') +
|
|
72
97
|
'</div>';
|
|
@@ -90,6 +115,12 @@ function renderSkills(skills) {
|
|
|
90
115
|
window._lastSkills = skills;
|
|
91
116
|
}
|
|
92
117
|
|
|
118
|
+
function _skillsSelectTab(key) {
|
|
119
|
+
_skillsTab = key;
|
|
120
|
+
_skillsPage = 0;
|
|
121
|
+
renderSkills(window._lastSkills);
|
|
122
|
+
}
|
|
123
|
+
|
|
93
124
|
function openSkill(file, source, dir) {
|
|
94
125
|
document.getElementById('modal-title').textContent = file;
|
|
95
126
|
document.getElementById('modal-body').innerHTML = '<p style="color:var(--muted)">Loading...</p>';
|
|
@@ -498,7 +498,6 @@ function openWorkItemDetail(id) {
|
|
|
498
498
|
}
|
|
499
499
|
});
|
|
500
500
|
}
|
|
501
|
-
if (arts.skills && arts.skills.length > 0) arts.skills.forEach(function(s) { artPills += '<span onclick="openSkill(\'' + escapeHtml(s) + '\',\'minions\',\'\')" style="' + pillStyle + '">⚙ ' + escapeHtml(s) + '</span> '; });
|
|
502
501
|
if (artPills) html += field('Artifacts', '<div style="display:flex;flex-wrap:wrap;gap:4px">' + artPills + '</div>');
|
|
503
502
|
|
|
504
503
|
if (item._totalCostUsd != null) html += field('Cumulative Cost', '$' + Number(item._totalCostUsd).toFixed(4));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<section>
|
|
2
|
-
<h2>Minions Skills <span class="count" id="skills-count">0</span> <span style="font-size:10px;color:var(--muted);font-weight:400;text-transform:none;letter-spacing:0">
|
|
2
|
+
<h2>Minions Skills <span class="count" id="skills-count">0</span> <span style="font-size:10px;color:var(--muted);font-weight:400;text-transform:none;letter-spacing:0">discovered from runtime native dirs, plugin installs, and configured project repos</span></h2>
|
|
3
3
|
<div id="skills-list"><p class="empty">No skills yet. Agents create these when they discover repeatable workflows.</p></div>
|
|
4
4
|
</section>
|
|
5
5
|
<section>
|
package/engine/lifecycle.js
CHANGED
|
@@ -1703,10 +1703,14 @@ function extractSkillsFromOutput(output, agentId, dispatchItem, config, runtimeN
|
|
|
1703
1703
|
const skillDir = path.join(personalSkillRoot, name.replace(/[^a-z0-9-]/g, '-'));
|
|
1704
1704
|
const skillPath = path.join(skillDir, 'SKILL.md');
|
|
1705
1705
|
if (!fs.existsSync(skillPath)) {
|
|
1706
|
-
// Native skill format: only name + description in frontmatter.
|
|
1706
|
+
// Native skill format: only name + description in frontmatter. The
|
|
1707
|
+
// `Auto-extracted` marker is an HTML comment so the dashboard's
|
|
1708
|
+
// autoGenerated detection picks it up without polluting the body
|
|
1709
|
+
// an agent reads.
|
|
1707
1710
|
const description = m('description') || m('trigger') || `Auto-extracted skill from ${agentName}`;
|
|
1708
1711
|
const body = fmMatch[2] || '';
|
|
1709
|
-
const
|
|
1712
|
+
const marker = `<!-- Auto-extracted by ${agentName} on ${dateStamp()} -->`;
|
|
1713
|
+
const ccContent = `---\nname: ${name}\ndescription: ${description}\n---\n\n${marker}\n\n${body.trim()}\n`;
|
|
1710
1714
|
if (!fs.existsSync(skillDir)) fs.mkdirSync(skillDir, { recursive: true });
|
|
1711
1715
|
shared.safeWrite(skillPath, ccContent);
|
|
1712
1716
|
try { require('./queries').invalidateSkillsCache(); } catch {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1683",
|
|
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"
|