@enigmax/dashboard 0.1.64 → 0.1.66
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 +75 -1
- package/package.json +1 -1
package/assets/index.html
CHANGED
|
@@ -526,6 +526,7 @@
|
|
|
526
526
|
<a href="#/settings" data-view="settings" class="tab">Settings</a>
|
|
527
527
|
<a href="#/resources" data-view="resources" class="tab">Resources</a>
|
|
528
528
|
<a href="#/recall" data-view="recall" class="tab">Recall</a>
|
|
529
|
+
<a href="#/packs" data-view="packs" class="tab">Packs</a>
|
|
529
530
|
</nav>
|
|
530
531
|
<div class="nav">
|
|
531
532
|
<label class="scope-wrap" title="Scope: global config or a specific project"><span class="scope-lbl">Scope</span><select id="scopeSel" class="scope-sel"><option value="global">Global</option></select></label>
|
|
@@ -803,6 +804,18 @@
|
|
|
803
804
|
<div class="panel"><div class="set-cat-h">Processes <small>by memory</small></div><div id="resProcs"><div class="empty" style="padding:12px 0">Loading...</div></div></div>
|
|
804
805
|
</section>
|
|
805
806
|
|
|
807
|
+
<section id="view-packs" style="display:none">
|
|
808
|
+
<div class="page-head" style="display:flex;align-items:flex-start;gap:16px">
|
|
809
|
+
<div style="flex:1">
|
|
810
|
+
<h1>Packs</h1>
|
|
811
|
+
<p>Optional harness packs you can add on demand. Each runs in its own <strong>isolated agent context</strong>, so its skills and commands never load into your normal coding agent. Launch a pack from a terminal with <code>enigma <pack></code>.</p>
|
|
812
|
+
</div>
|
|
813
|
+
<button id="packsRefresh" type="button" class="iconbtn" title="Refresh" aria-label="Refresh"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M23 4v6h-6"/><path d="M1 20v-6h6"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg></button>
|
|
814
|
+
</div>
|
|
815
|
+
<div id="packsNote" class="set-note"></div>
|
|
816
|
+
<div id="packsBody"><div class="empty" style="padding:12px 0">Loading...</div></div>
|
|
817
|
+
</section>
|
|
818
|
+
|
|
806
819
|
<section id="view-recall" style="display:none">
|
|
807
820
|
<div class="page-head" style="display:flex;align-items:flex-start;gap:16px">
|
|
808
821
|
<div style="flex:1">
|
|
@@ -3696,7 +3709,7 @@ export {
|
|
|
3696
3709
|
|
|
3697
3710
|
// --- hash routing between the subpages ---
|
|
3698
3711
|
// Single source of truth for the subpage ids (savings is the default/fallback).
|
|
3699
|
-
const VIEWS = ["savings", "usage", "accounts", "skills", "settings", "resources", "recall"];
|
|
3712
|
+
const VIEWS = ["savings", "usage", "accounts", "skills", "settings", "resources", "recall", "packs"];
|
|
3700
3713
|
// Views that apply to a single project; the rest are global/machine-level only.
|
|
3701
3714
|
const PROJECT_VIEWS = ["settings", "skills"];
|
|
3702
3715
|
let activeView = "savings";
|
|
@@ -3717,6 +3730,7 @@ export {
|
|
|
3717
3730
|
else if (v === "usage") { loadProviderStatus(); if (!usageAccountsLoaded) { usageAccountsLoaded = true; loadUsageAccounts(); } }
|
|
3718
3731
|
else if (v === "resources") loadResources();
|
|
3719
3732
|
else if (v === "recall") loadRecall();
|
|
3733
|
+
else if (v === "packs") loadPacks();
|
|
3720
3734
|
// The chart was sized while its view may have been hidden; nudge it on return.
|
|
3721
3735
|
else if (v === "savings") { loadSystems(true); if (chart) { try { applyRange(); } catch { /* not ready */ } } }
|
|
3722
3736
|
}
|
|
@@ -3776,6 +3790,65 @@ export {
|
|
|
3776
3790
|
});
|
|
3777
3791
|
}
|
|
3778
3792
|
|
|
3793
|
+
// --- packs subpage (optional isolated harness packs; marketplace) ---
|
|
3794
|
+
function renderPacks(list) {
|
|
3795
|
+
list = list || [];
|
|
3796
|
+
if (!list.length) { $("packsBody").innerHTML = '<div class="empty" style="padding:12px 0">No packs available.</div>'; return; }
|
|
3797
|
+
$("packsBody").innerHTML = list.map((p) => {
|
|
3798
|
+
const tags = (p.tags || []).map((t) => '<span class="tag">' + esc(t) + '</span>').join(" ");
|
|
3799
|
+
const state = p.installed ? '<span class="tag">' + (p.version ? "installed " + esc(p.version) : "installed") + '</span>' : '<span class="tag">not installed</span>';
|
|
3800
|
+
const added = p.enabled ? '<span class="tag" style="color:var(--ok)">added</span>' : "";
|
|
3801
|
+
const actions = p.installed
|
|
3802
|
+
? '<button type="button" class="toggle on" data-pack="launch" data-id="' + esc(p.id) + '">Launch command</button>'
|
|
3803
|
+
+ '<button type="button" class="toggle" data-pack="setup" data-id="' + esc(p.id) + '" title="Register the pack MCP servers (needs Python 3)">Setup MCP</button>'
|
|
3804
|
+
+ '<button type="button" class="toggle" data-pack="update" data-id="' + esc(p.id) + '">Update</button>'
|
|
3805
|
+
+ '<button type="button" class="btn-danger" data-pack="remove" data-id="' + esc(p.id) + '">Remove</button>'
|
|
3806
|
+
: '<button type="button" class="toggle on" data-pack="install" data-id="' + esc(p.id) + '">Install</button>';
|
|
3807
|
+
const opts = '<option value="">follow active (' + esc(p.resolvedAccount || "default") + ')</option>'
|
|
3808
|
+
+ (p.accounts || []).map((a) => '<option value="' + esc(a.name) + '"' + (p.defaultAccount === a.name ? " selected" : "") + '>' + esc(a.name) + (a.label && a.label !== a.name ? " - " + esc(a.label) : "") + "</option>").join("");
|
|
3809
|
+
const accountSel = p.installed
|
|
3810
|
+
? '<label class="set-hint" style="display:flex;align-items:center;gap:8px;margin-top:10px">Account that seeds this pack:'
|
|
3811
|
+
+ '<select data-pack-account data-id="' + esc(p.id) + '">' + opts + "</select></label>"
|
|
3812
|
+
: "";
|
|
3813
|
+
return '<div class="panel"><div class="set-row"><div class="set-meta">'
|
|
3814
|
+
+ '<div class="set-name">' + esc(p.label) + " " + state + " " + added + '</div>'
|
|
3815
|
+
+ '<div class="set-hint">' + esc(p.description) + '</div>'
|
|
3816
|
+
+ '<div class="set-hint" style="margin-top:6px">' + tags + ' <a href="' + esc(p.homepage) + '" target="_blank" rel="noopener">source</a></div>'
|
|
3817
|
+
+ accountSel
|
|
3818
|
+
+ '</div></div><div class="set-ctl" style="display:flex;gap:8px;flex-wrap:wrap;margin-top:8px">' + actions + '</div></div>';
|
|
3819
|
+
}).join("");
|
|
3820
|
+
}
|
|
3821
|
+
async function loadPacks() {
|
|
3822
|
+
$("packsNote").textContent = "";
|
|
3823
|
+
try { renderPacks((await (await fetch("/api/packs", { cache: "no-store" })).json()).packs); }
|
|
3824
|
+
catch { $("packsBody").innerHTML = '<div class="empty" style="padding:12px 0">Packs unavailable.</div>'; }
|
|
3825
|
+
}
|
|
3826
|
+
async function packAction(id, action, value) {
|
|
3827
|
+
const confirmMsg = action === "remove" ? "Remove this pack and its isolated context?" : null;
|
|
3828
|
+
if (confirmMsg && !(await askConfirm("Confirm", confirmMsg, true))) return;
|
|
3829
|
+
setNote("packsNote", action === "install" || action === "update" ? "Working..." : "Saving...");
|
|
3830
|
+
try {
|
|
3831
|
+
const out = await (await fetch("/api/packs", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ id, action, value }) })).json();
|
|
3832
|
+
if (out.packs) renderPacks(out.packs);
|
|
3833
|
+
if (out.command) { try { await navigator.clipboard.writeText(out.command); } catch { /* clipboard blocked */ } }
|
|
3834
|
+
setNote("packsNote", out.note || out.error || (out.ok ? "Done." : "Action failed."), out.ok ? "ok" : "err");
|
|
3835
|
+
} catch { setNote("packsNote", "Could not reach the server.", "err"); }
|
|
3836
|
+
}
|
|
3837
|
+
function wirePacks() {
|
|
3838
|
+
$("packsRefresh").addEventListener("click", loadPacks);
|
|
3839
|
+
$("view-packs").addEventListener("click", (e) => {
|
|
3840
|
+
const b = e.target.closest("button[data-pack]");
|
|
3841
|
+
if (!b) return;
|
|
3842
|
+
packAction(b.dataset.id, b.dataset.pack);
|
|
3843
|
+
});
|
|
3844
|
+
// Pin which account seeds a pack (empty value = follow the active account).
|
|
3845
|
+
$("view-packs").addEventListener("change", (e) => {
|
|
3846
|
+
const sel = e.target.closest("select[data-pack-account]");
|
|
3847
|
+
if (!sel) return;
|
|
3848
|
+
packAction(sel.dataset.id, "set-account", sel.value);
|
|
3849
|
+
});
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3779
3852
|
// --- recall subpage (local session memory; reads your own transcripts) ---
|
|
3780
3853
|
const RECALL_TYPES = ["bugfix", "feature", "refactor", "change", "discovery", "decision", "security"];
|
|
3781
3854
|
let recallProjSig = "";
|
|
@@ -4344,6 +4417,7 @@ export {
|
|
|
4344
4417
|
wireUsage();
|
|
4345
4418
|
wireResources();
|
|
4346
4419
|
wireRecall();
|
|
4420
|
+
wirePacks();
|
|
4347
4421
|
wireScope();
|
|
4348
4422
|
enhanceAll(); // upgrade every static <select> into the shared pretty dropdown
|
|
4349
4423
|
$("cfgExport").addEventListener("click", exportConfig);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enigmax/dashboard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.66",
|
|
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": [
|