@enigmax/dashboard 0.1.70 → 0.1.71

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 +38 -25
  2. package/package.json +1 -1
package/assets/index.html CHANGED
@@ -878,12 +878,17 @@
878
878
  <div class="page-head" style="display:flex;align-items:flex-start;gap:16px">
879
879
  <div style="flex:1">
880
880
  <h1>Code graph</h1>
881
- <p>Structural memory of your codebase - a knowledge graph of symbols, call chains, and routes. Enabling it registers the code-intelligence server in your agents so they can query the graph over MCP. Complements <a href="#/recall">Recall</a> (session memory).</p>
881
+ <p>Structural memory of your codebase - a native knowledge graph of the symbols each file defines, the modules it imports and cross-file references. Enabling it exposes enigma's code-graph tools to your agents over MCP. Complements <a href="#/recall">Recall</a> (session memory).</p>
882
882
  </div>
883
- <button id="cgToggle" type="button" class="toggle" role="switch" aria-checked="false" aria-label="Codebase memory">off</button>
883
+ <button id="cgToggle" type="button" class="toggle" data-kind="bool" role="switch" aria-checked="false" aria-label="Code graph">Off</button>
884
884
  <button id="cgRefresh" 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>
885
885
  </div>
886
886
  <div id="cgNote" class="set-note"></div>
887
+ <div class="panel">
888
+ <div class="set-cat-h">Index a project</div>
889
+ <div class="set-hint" style="padding:4px 0">Build the graph for a codebase. Leave the path empty to index enigma's own working directory.</div>
890
+ <div class="ladd" style="gap:8px;flex-wrap:wrap"><input id="cgRoot" class="linput" placeholder="absolute project path (optional)" style="flex:1;min-width:240px"><button id="cgIndex" type="button" class="toggle on">Index</button></div>
891
+ </div>
887
892
  <div id="cgBody"><div class="empty" style="padding:12px 0">Loading...</div></div>
888
893
  </section>
889
894
 
@@ -3873,9 +3878,9 @@ export {
3873
3878
  });
3874
3879
  }
3875
3880
 
3876
- // --- code graph subpage (structural code memory) ---
3881
+ // --- code graph subpage (native structural code memory) ---
3877
3882
  let cgProject = null;
3878
- // A single architecture/schema field, rendered defensively (shape varies by tool version).
3883
+ // Render one architecture/schema field defensively (arrays -> chips, objects -> count).
3879
3884
  function cgItem(x) {
3880
3885
  if (x && typeof x === "object") return String(x.name || x.label || x.path || x.id || JSON.stringify(x)).slice(0, 60);
3881
3886
  return String(x);
@@ -3883,10 +3888,14 @@ export {
3883
3888
  function cgVal(v) {
3884
3889
  if (Array.isArray(v)) {
3885
3890
  if (!v.length) return '<span class="tag">none</span>';
3886
- return v.slice(0, 12).map((x) => '<span class="tag">' + esc(cgItem(x)) + "</span>").join(" ")
3887
- + (v.length > 12 ? ' <span class="set-hint">+' + (v.length - 12) + " more</span>" : "");
3891
+ return v.slice(0, 16).map((x) => '<span class="tag">' + esc(cgItem(x)) + "</span>").join(" ")
3892
+ + (v.length > 16 ? ' <span class="set-hint">+' + (v.length - 16) + " more</span>" : "");
3893
+ }
3894
+ if (v && typeof v === "object") {
3895
+ const ents = Object.entries(v);
3896
+ if (!ents.length) return '<span class="tag">none</span>';
3897
+ return ents.slice(0, 16).map(([k, n]) => '<span class="tag">' + esc(k) + " " + esc(String(n)) + "</span>").join(" ");
3888
3898
  }
3889
- if (v && typeof v === "object") return '<span class="set-hint">' + esc(Object.keys(v).length + " field(s)") + "</span>";
3890
3899
  return esc(String(v));
3891
3900
  }
3892
3901
  function cgSection(title, obj) {
@@ -3900,23 +3909,17 @@ export {
3900
3909
  view = view || {};
3901
3910
  const on = !!view.enabled;
3902
3911
  const t = $("cgToggle");
3903
- t.classList.toggle("on", on); t.setAttribute("aria-checked", on ? "true" : "false"); t.textContent = on ? "on" : "off";
3904
- if (!view.available) {
3905
- $("cgBody").innerHTML = '<div class="panel"><div class="set-cat-h">Not installed</div>'
3906
- + '<div class="set-hint" style="padding:6px 0">The code-intelligence engine is not available yet. When enabled, your agent fetches it automatically on first use (needs <code>npx</code> on PATH). Then tell your agent "Index this project".</div></div>';
3907
- return;
3908
- }
3912
+ t.classList.toggle("on", on); t.setAttribute("aria-checked", on ? "true" : "false"); t.textContent = on ? "On" : "Off";
3909
3913
  const projects = view.projects || [];
3910
3914
  const projHtml = projects.length
3911
3915
  ? projects.map((p) => {
3912
- const name = p.name || p.root || "";
3913
- const sel = name === view.selected;
3914
- return '<div class="set-row"><div class="set-meta"><div class="set-name">' + esc(name)
3916
+ const sel = p.name === view.selected;
3917
+ return '<div class="set-row"><div class="set-meta"><div class="set-name">' + esc(p.name)
3915
3918
  + (sel ? ' <span class="tag" style="color:var(--ok)">viewing</span>' : "")
3916
- + '</div><div class="set-hint">' + esc(p.root || "") + '</div></div>'
3917
- + '<div class="set-ctl"><button type="button" class="toggle' + (sel ? " on" : "") + '" data-cg-project="' + esc(name) + '">View</button></div></div>';
3919
+ + '</div><div class="set-hint">' + esc((p.files || 0) + " files · " + (p.symbols || 0) + " symbols · " + (p.root || "")) + '</div></div>'
3920
+ + '<div class="set-ctl"><button type="button" class="toggle' + (sel ? " on" : "") + '" data-cg-project="' + esc(p.name) + '">View</button></div></div>';
3918
3921
  }).join("")
3919
- : '<div class="empty" style="padding:12px 0">No projects indexed yet. In your agent, say "Index this project".</div>';
3922
+ : '<div class="empty" style="padding:12px 0">No projects indexed yet. Use "Index a project" above.</div>';
3920
3923
  let html = '<div class="panel"><div class="set-cat-h">Indexed projects <small>' + projects.length + "</small></div>" + projHtml + "</div>";
3921
3924
  if (view.architecture) html += cgSection("Architecture" + (view.selected ? " - " + view.selected : ""), view.architecture);
3922
3925
  if (view.schema) html += cgSection("Graph schema", view.schema);
@@ -3929,18 +3932,28 @@ export {
3929
3932
  renderCodeGraph(await (await fetch("/api/codegraph" + q, { cache: "no-store" })).json());
3930
3933
  } catch { $("cgBody").innerHTML = '<div class="empty" style="padding:12px 0">Code graph unavailable.</div>'; }
3931
3934
  }
3932
- async function cgToggleAction() {
3933
- const turnOn = $("cgToggle").getAttribute("aria-checked") !== "true";
3934
- setNote("cgNote", "Saving...");
3935
+ async function cgPost(payload, working) {
3936
+ setNote("cgNote", working);
3935
3937
  try {
3936
- const out = await (await fetch("/api/codegraph", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ op: "toggle", on: turnOn, project: cgProject || undefined }) })).json();
3938
+ const out = await (await fetch("/api/codegraph", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) })).json();
3937
3939
  if (out.view) renderCodeGraph(out.view);
3938
- setNote("cgNote", out.ok ? (turnOn ? "Codebase memory enabled - registered in your agents (restart them to load it)." : "Codebase memory disabled.") : (out.error || "Action failed."), out.ok ? "ok" : "err");
3939
- } catch { setNote("cgNote", "Could not reach the server.", "err"); }
3940
+ return out;
3941
+ } catch { setNote("cgNote", "Could not reach the server.", "err"); return null; }
3942
+ }
3943
+ async function cgToggleAction() {
3944
+ const turnOn = $("cgToggle").getAttribute("aria-checked") !== "true";
3945
+ const out = await cgPost({ op: "toggle", on: turnOn, project: cgProject || undefined }, "Saving...");
3946
+ if (out) setNote("cgNote", out.ok ? (turnOn ? "Code graph enabled - tools exposed to your agents (restart them to load it)." : "Code graph disabled.") : (out.error || "Action failed."), out.ok ? "ok" : "err");
3947
+ }
3948
+ async function cgIndexAction() {
3949
+ const root = $("cgRoot").value.trim();
3950
+ const out = await cgPost({ op: "index", root: root || undefined }, "Indexing...");
3951
+ if (out) { if (out.view && out.view.selected) cgProject = out.view.selected; setNote("cgNote", out.ok ? "Indexed." : (out.error || "Indexing failed."), out.ok ? "ok" : "err"); }
3940
3952
  }
3941
3953
  function wireCodeGraph() {
3942
3954
  $("cgRefresh").addEventListener("click", loadCodeGraph);
3943
3955
  $("cgToggle").addEventListener("click", cgToggleAction);
3956
+ $("cgIndex").addEventListener("click", cgIndexAction);
3944
3957
  $("view-codegraph").addEventListener("click", (e) => {
3945
3958
  const b = e.target.closest("button[data-cg-project]");
3946
3959
  if (!b) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@enigmax/dashboard",
3
- "version": "0.1.70",
3
+ "version": "0.1.71",
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": [