@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.
- package/assets/index.html +38 -25
- 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
|
|
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="
|
|
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
|
-
//
|
|
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,
|
|
3887
|
-
+ (v.length >
|
|
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 ? "
|
|
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
|
|
3913
|
-
|
|
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.
|
|
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
|
|
3933
|
-
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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": [
|