@enigmax/dashboard 0.1.11 → 0.1.13

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.
Files changed (2) hide show
  1. package/assets/index.html +85 -1
  2. package/package.json +1 -1
package/assets/index.html CHANGED
@@ -150,6 +150,22 @@
150
150
  .wval.muted { font-size: 14px; font-weight: 500; color: var(--muted); }
151
151
  .wset { display: flex; gap: 6px; margin-top: 10px; }
152
152
  .wlimit { flex: 1; min-width: 0; background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 7px; padding: 4px 8px; font-size: 12px; }
153
+ /* Fix-path result: per-tool rows with a status dot, badge, reason and resolved path. */
154
+ .fixres { margin-top: 12px; display: none; }
155
+ .fixres.show { display: block; }
156
+ .fixres-head { font-size: 13px; font-weight: 600; margin-bottom: 4px; }
157
+ .fixres-head.ok { color: var(--good); }
158
+ .fixres-head.fixed { color: var(--accent); }
159
+ .fixres-head.bad { color: var(--accent2); }
160
+ .fxrow { display: flex; align-items: flex-start; gap: 10px; padding: 9px 0; border-top: 1px solid var(--surface2); }
161
+ .fxdot { width: 8px; height: 8px; border-radius: 50%; margin-top: 5px; flex: 0 0 auto; }
162
+ .fxdot.ok { background: var(--good); }
163
+ .fxdot.fixed { background: var(--accent); }
164
+ .fxdot.bad { background: var(--accent2); }
165
+ .fxmain { min-width: 0; flex: 1; }
166
+ .fxtitle { font-size: 13px; display: flex; align-items: center; gap: 8px; }
167
+ .fxmsg { color: var(--muted); font-size: 12px; margin-top: 2px; }
168
+ .fxpath { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--muted); margin-top: 3px; word-break: break-all; }
153
169
  .sys-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 0 24px; }
154
170
  .sys-item { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--surface2); font-size: 13px; }
155
171
  .sys-item .k { color: var(--muted); }
@@ -205,12 +221,14 @@
205
221
  <h2>Enigma Systems <small>what's active - configuration, not savings</small></h2>
206
222
  <div class="ctrls">
207
223
  <button id="refreshBtn" type="button" class="toggle">Refresh</button>
224
+ <button id="fixPathBtn" type="button" class="toggle">Fix tool paths</button>
208
225
  <button id="updateBtn" type="button" class="toggle on">Check &amp; update</button>
209
226
  </div>
210
227
  </div>
211
228
  <div class="sub" style="margin-bottom:14px">Only Context Compression and (opt-in) real tool-usage are measured for savings below. The rest is shown as state: enigma can't measure their effect because they run inside the agent, not through enigma - so it reports their configuration honestly instead of inventing a number.</div>
212
229
  <div id="systems" class="sys-grid"><div class="empty" style="padding:16px 0">Loading...</div></div>
213
230
  <div id="updateNote" class="set-note"></div>
231
+ <div id="fixPathResult" class="fixres"></div>
214
232
  </div>
215
233
 
216
234
  <div class="panel">
@@ -1009,7 +1027,17 @@
1009
1027
  + item("Local dashboard", pill(s.dashboard === "off" ? "off" : "lvl", s.dashboard || "off"))
1010
1028
  + item("Permission bypass (security)", boolPill(sec.permissionBypass))
1011
1029
  + item("Commit guard blocks", guard || '<span class="tag">set up with enigma security</span>')
1012
- + item("Skills", skillTags);
1030
+ + item("Skills", skillTags)
1031
+ + item("Tool launch paths", toolPathTags(s.tools));
1032
+ }
1033
+
1034
+ // Per-tool launch-path status: green when launchable, yellow when off PATH, red when missing.
1035
+ function toolPathTags(tools) {
1036
+ if (!tools || !tools.length) return '<span class="tag">unknown</span>';
1037
+ return tools.map((t) => {
1038
+ const cls = t.status === "not installed" ? "warn" : (t.status === "installed, off PATH" ? "ext" : "");
1039
+ return '<span class="tag ' + cls + '">' + esc(t.label) + ": " + esc(t.status) + "</span>";
1040
+ }).join("");
1013
1041
  }
1014
1042
 
1015
1043
  async function runUpdate() {
@@ -1025,6 +1053,61 @@
1025
1053
  } catch { $("updateNote").textContent = "Could not reach the server to update."; }
1026
1054
  }
1027
1055
 
1056
+ // Detect & repair every tool's launch path; the server persists any off-PATH
1057
+ // binary so `enigma <tool>` works, and returns the refreshed status.
1058
+ async function runFixPath() {
1059
+ const btn = $("fixPathBtn");
1060
+ $("fixPathResult").className = "fixres";
1061
+ $("updateNote").textContent = "Detecting tool paths...";
1062
+ if (btn) { btn.disabled = true; }
1063
+ try {
1064
+ const res = await fetch("/api/fix-path", { method: "POST", headers: { "Content-Type": "application/json" }, body: "{}" });
1065
+ const out = await res.json();
1066
+ $("updateNote").textContent = "";
1067
+ renderFixPath(out);
1068
+ loadSystems(true);
1069
+ } catch {
1070
+ $("updateNote").textContent = "";
1071
+ $("fixPathResult").className = "fixres show";
1072
+ $("fixPathResult").innerHTML = '<div class="fixres-head bad">Could not reach the server to fix tool paths.</div>';
1073
+ } finally { if (btn) { btn.disabled = false; } }
1074
+ }
1075
+
1076
+ // Short, non-redundant reason per tool (the resolved path is shown separately below).
1077
+ function fixReason(r) {
1078
+ if (!r.installed) return "Not installed. Install it, then run fix-path again.";
1079
+ if (r.changed) return "Found off PATH and saved - 'enigma " + esc(r.command) + "' now launches it.";
1080
+ return "Launchable - '" + esc(r.command) + "' works.";
1081
+ }
1082
+
1083
+ // Render the fix-path outcome as one row per tool: status dot + badge + reason + path.
1084
+ function renderFixPath(out) {
1085
+ const box = $("fixPathResult");
1086
+ const results = out.results || [];
1087
+ box.className = "fixres show";
1088
+ if (!results.length) {
1089
+ box.innerHTML = '<div class="fxmsg">' + esc((out.lines || []).join(" ") || (out.ok ? "Tool paths OK." : "Could not fix tools.")) + "</div>";
1090
+ return;
1091
+ }
1092
+ const fixedN = results.filter((r) => r.changed).length;
1093
+ const badN = results.filter((r) => !r.ok).length;
1094
+ let head, hc;
1095
+ if (badN) { head = badN + " of " + results.length + " tools need attention"; hc = "bad"; }
1096
+ else if (fixedN) { head = "Repaired " + fixedN + " of " + results.length + " tools - all launchable now"; hc = "fixed"; }
1097
+ else { head = "All " + results.length + " tools launchable"; hc = "ok"; }
1098
+ const rows = results.map((r) => {
1099
+ const cls = !r.ok ? "bad" : (r.changed ? "fixed" : "ok");
1100
+ const badge = !r.ok ? '<span class="pill off">not found</span>'
1101
+ : (r.changed ? '<span class="pill lvl">fixed</span>' : '<span class="pill on">ok</span>');
1102
+ return '<div class="fxrow"><span class="fxdot ' + cls + '"></span><div class="fxmain">'
1103
+ + '<div class="fxtitle">' + esc(r.label) + " " + badge + "</div>"
1104
+ + '<div class="fxmsg">' + fixReason(r) + "</div>"
1105
+ + (r.path ? '<div class="fxpath">' + esc(r.path) + "</div>" : "")
1106
+ + "</div></div>";
1107
+ }).join("");
1108
+ box.innerHTML = '<div class="fixres-head ' + hc + '">' + esc(head) + "</div>" + rows;
1109
+ }
1110
+
1028
1111
  async function loadSystems(force) {
1029
1112
  if (!live && !force) return;
1030
1113
  try {
@@ -1283,6 +1366,7 @@
1283
1366
  $("cfgExport").addEventListener("click", exportConfig);
1284
1367
  $("cfgImport").addEventListener("click", importConfig);
1285
1368
  $("updateBtn").addEventListener("click", runUpdate);
1369
+ $("fixPathBtn").addEventListener("click", runFixPath);
1286
1370
  $("refreshBtn").addEventListener("click", () => refreshAll(true));
1287
1371
  window.addEventListener("hashchange", route);
1288
1372
  route();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enigmax/dashboard",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
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": [