@enigmax/dashboard 0.1.47 → 0.1.49
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/assets/index.html +35 -11
- package/package.json +1 -1
package/assets/index.html
CHANGED
|
@@ -2781,8 +2781,19 @@ export {
|
|
|
2781
2781
|
// Brand icon + text in one inline tag; the icon is omitted when there is none (e.g. content types).
|
|
2782
2782
|
function iconLabel(ic, text) { return '<span class="srctag">' + (ic ? '<span class="aicon">' + ic + '</span>' : '') + esc(text) + '</span>'; }
|
|
2783
2783
|
|
|
2784
|
+
let skillScope = "global"; // "global" | "project" - the same rows render in both
|
|
2784
2785
|
function skillRow(s) {
|
|
2785
2786
|
const ver = s.version ? '<span class="tag">v' + esc(s.version) + "</span>" : "";
|
|
2787
|
+
// Project scope: same row, but the per-app chips toggle deployment INTO this project
|
|
2788
|
+
// (data-pskill, handled by the scope delegate) and the global-only controls are hidden.
|
|
2789
|
+
if (skillScope === "project") {
|
|
2790
|
+
const chips = (s.agentStates || []).map((a) =>
|
|
2791
|
+
'<button type="button" class="achip' + (a.deployed ? " on" : "") + '" data-pskill="' + esc(s.name) + '" data-pagent="' + esc(a.name) + '" data-poff="' + (a.deployed ? 1 : 0) + '" aria-label="' + esc(a.label) + '" title="'
|
|
2792
|
+
+ (a.deployed ? esc(a.label) + " - deployed, click to remove" : esc(a.label) + " - not deployed, click to deploy") + '">' + (agentSvg(a.name) || esc(a.label)) + "</button>").join("");
|
|
2793
|
+
return '<div class="set-row"><div class="set-meta"><div class="set-name">' + esc(s.name) + ver + "</div>"
|
|
2794
|
+
+ '<div class="set-hint">' + esc(s.description || "") + "</div>"
|
|
2795
|
+
+ '<div class="set-agents">' + (chips || '<span class="tag">no agents</span>') + "</div></div></div>";
|
|
2796
|
+
}
|
|
2786
2797
|
// Last-edited date (from skill.json), shown relative via the vendored <relative-time>.
|
|
2787
2798
|
const edited = s.updated ? '<span class="tag" title="Last edited ' + esc(new Date(s.updated).toLocaleString()) + '">edited '
|
|
2788
2799
|
+ rtime(new Date(s.updated).getTime(), 'format="relative"', new Date(s.updated).toLocaleDateString()) + "</span>" : "";
|
|
@@ -2831,11 +2842,19 @@ export {
|
|
|
2831
2842
|
let lastSkills = [];
|
|
2832
2843
|
function renderSkills(skills) {
|
|
2833
2844
|
lastSkills = skills; // kept so the editor can offer per-app save targets
|
|
2834
|
-
const enigma = skills.filter((s) => s.source === "enigma");
|
|
2835
|
-
const ext = skills.filter((s) => s.source === "external");
|
|
2836
2845
|
const section = (title, blurb, list, emptyText) => '<div class="set-cat"><div class="set-cat-h">' + title + "</div>"
|
|
2837
2846
|
+ '<div class="set-cat-b">' + blurb + "</div>"
|
|
2838
2847
|
+ (list.length ? list.map(skillRow).join("") : '<div class="empty" style="padding:16px 0">' + emptyText + "</div>") + "</div>";
|
|
2848
|
+
if (skillScope === "project") {
|
|
2849
|
+
$("skillsBody").innerHTML =
|
|
2850
|
+
'<div class="panel"><div class="set-cat-h">Auto-detect skills by stack</div>'
|
|
2851
|
+
+ '<div class="set-cat-b">Scan this project (packages, config files, gems) and install the matching community skills for its stack - hash-verified and kept separate from the policy skills below.</div>'
|
|
2852
|
+
+ '<div class="ladd"><button type="button" class="toggle on with-icon" data-proj-autoskills><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></svg>Detect & install</button></div></div>'
|
|
2853
|
+
+ section("Policy skills", "Deploy enigma's policy skills into this project, per app. A green chip means the skill is in that app's project folder.", skills, "No skills.");
|
|
2854
|
+
return;
|
|
2855
|
+
}
|
|
2856
|
+
const enigma = skills.filter((s) => s.source === "enigma");
|
|
2857
|
+
const ext = skills.filter((s) => s.source === "external");
|
|
2839
2858
|
$("skillsBody").innerHTML =
|
|
2840
2859
|
section("Enigma skills", "Distributed and kept current by enigma. Disable to remove from your agents; enable to restore.", enigma, "No enigma skills.")
|
|
2841
2860
|
+ section("External skills", "Skills enigma did not author, found in your agents. Remove deletes the skill from every agent that has it.", ext, "No external skills found.");
|
|
@@ -2945,6 +2964,7 @@ export {
|
|
|
2945
2964
|
let skillsLoaded = false;
|
|
2946
2965
|
async function loadSkills() {
|
|
2947
2966
|
if (isProjectScope()) return loadProjectSkills();
|
|
2967
|
+
skillScope = "global";
|
|
2948
2968
|
loadSkillSettings();
|
|
2949
2969
|
try {
|
|
2950
2970
|
const res = await fetch("/api/skills", { cache: "no-store" });
|
|
@@ -3299,7 +3319,7 @@ export {
|
|
|
3299
3319
|
const asSwitch = !c.choices || (c.choices.length === 2 && c.choices.indexOf(c.offChoice) !== -1);
|
|
3300
3320
|
const ctl = !asSwitch
|
|
3301
3321
|
? '<select class="choice" data-proj-cfg="' + esc(c.key) + '">' + c.choices.map((x) => '<option value="' + esc(x) + '"' + (x === c.choice ? " selected" : "") + ">" + esc(prettyChoice(x)) + "</option>").join("") + "</select>"
|
|
3302
|
-
: '<button type="button" class="toggle' + (c.value ? " on" : "") + '" data-proj-cfg-bool="' + esc(c.key) + '" data-on="' + (c.value ? 1 : 0) + '">' + (c.value ? "On" : "Off") + "</button>";
|
|
3322
|
+
: '<button type="button" class="toggle' + (c.value ? " on" : "") + '" data-kind="bool" data-proj-cfg-bool="' + esc(c.key) + '" data-on="' + (c.value ? 1 : 0) + '" title="' + (c.value ? "On" : "Off") + '">' + (c.value ? "On" : "Off") + "</button>";
|
|
3303
3323
|
const reset = c.overridden ? ' <button type="button" class="iconbtn" data-proj-cfg-reset="' + esc(c.key) + '" title="Inherit global">reset</button>' : "";
|
|
3304
3324
|
const badge = c.overridden ? ' <span class="tag">project</span>' : ' <span class="tag">inherited</span>';
|
|
3305
3325
|
return '<div class="set-row"><div class="set-meta"><div class="set-name">' + esc(c.label) + badge + '</div><div class="set-hint">' + esc(c.hint) + "</div></div>"
|
|
@@ -3345,19 +3365,20 @@ export {
|
|
|
3345
3365
|
} catch { setNote("settingsNote", "Could not reach the server.", "err"); }
|
|
3346
3366
|
}
|
|
3347
3367
|
async function loadProjectSkills() {
|
|
3368
|
+
skillScope = "project";
|
|
3348
3369
|
const el = $("skillsBody");
|
|
3349
3370
|
const ss = $("skillSettings"); if (ss) ss.innerHTML = '<div class="set-cat-b" style="padding:0 0 4px">Skill settings are global - switch Scope to Global to change them.</div>';
|
|
3350
3371
|
el.innerHTML = '<div class="empty" style="padding:24px 0">Loading...</div>';
|
|
3351
3372
|
let d; try { d = await fetchProjectDetail(); } catch { el.innerHTML = '<div class="empty" style="padding:24px 0">Project unavailable.</div>'; return; }
|
|
3352
3373
|
if (d.error) { el.innerHTML = '<div class="empty" style="padding:24px 0">' + esc(d.error) + "</div>"; return; }
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3374
|
+
// Build the SAME skill objects renderSkills/skillRow use globally; agentStates carries
|
|
3375
|
+
// this project's per-app deployment so the rows render identically (chips per app).
|
|
3376
|
+
const agents = d.agents || [];
|
|
3377
|
+
const skills = (d.available || []).map((s) => ({
|
|
3378
|
+
name: s.name, description: s.description, source: "enigma",
|
|
3379
|
+
agentStates: agents.map((a) => ({ name: a.name, label: a.label, deployed: (a.deployed || []).indexOf(s.name) !== -1 })),
|
|
3380
|
+
}));
|
|
3381
|
+
renderSkills(skills);
|
|
3361
3382
|
}
|
|
3362
3383
|
async function projAction(payload, confirmMsg) {
|
|
3363
3384
|
if (!isProjectScope()) return;
|
|
@@ -3382,6 +3403,9 @@ export {
|
|
|
3382
3403
|
}
|
|
3383
3404
|
function onProjectControlClick(e) {
|
|
3384
3405
|
if (!isProjectScope()) return;
|
|
3406
|
+
if (e.target.closest("[data-proj-autoskills]")) { projAction({ op: "autoskills" }, "Scan this project and install the matching community skills for its stack?"); return; }
|
|
3407
|
+
const chip = e.target.closest("[data-pskill]"); // per-app deploy chip in the Skills view
|
|
3408
|
+
if (chip) { projAction({ op: "skill", name: chip.dataset.pskill, agent: chip.dataset.pagent, on: chip.dataset.poff !== "1" }); return; }
|
|
3385
3409
|
const sk = e.target.closest("[data-proj-skill]");
|
|
3386
3410
|
if (sk) { projAction({ op: "skill", name: sk.dataset.projSkill, on: sk.dataset.on !== "1" }); return; }
|
|
3387
3411
|
const cb = e.target.closest("[data-proj-cfg-bool]");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enigmax/dashboard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.49",
|
|
4
4
|
"description": "Local browser dashboard UI for enigma: the static page and chart assets enigma serves on its loopback dashboard (savings, real tool usage, in-browser settings). Installed on demand by enigma-cli; not a runtime dependency.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|