@monoes/monomindcli 1.6.8 → 1.7.0
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/.claude/commands/monomind-createtask.md +73 -111
- package/.claude/commands/monomind-do.md +227 -115
- package/.claude/commands/monomind-idea.md +46 -109
- package/.claude/commands/monomind-improve.md +352 -0
- package/.claude/helpers/graphify-freshen.cjs +12 -97
- package/.claude/helpers/hook-handler.cjs +16 -0
- package/.claude/helpers/statusline.cjs +89 -65
- package/.claude/skills/monomind-task-engine/SKILL.md +358 -0
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +72 -10
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +152 -24
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/shared-instructions-generator.d.ts +38 -0
- package/dist/src/init/shared-instructions-generator.d.ts.map +1 -0
- package/dist/src/init/shared-instructions-generator.js +571 -0
- package/dist/src/init/shared-instructions-generator.js.map +1 -0
- package/dist/src/init/types.d.ts +1 -1
- package/dist/src/init/types.d.ts.map +1 -1
- package/dist/src/mcp-tools/graphify-tools.d.ts +4 -4
- package/dist/src/mcp-tools/graphify-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/graphify-tools.js +84 -60
- package/dist/src/mcp-tools/graphify-tools.js.map +1 -1
- package/dist/src/ui/dashboard.html +219 -45
- package/dist/src/ui/server.mjs +201 -16
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1457,18 +1457,12 @@
|
|
|
1457
1457
|
width: 200px; flex-shrink: 0; border-right: 1px solid var(--border);
|
|
1458
1458
|
padding: 16px 14px; overflow-y: auto; background: rgba(0,0,0,0.12);
|
|
1459
1459
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
}
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
display: flex; align-items: center; gap: 14px; flex-shrink: 0;
|
|
1467
|
-
font-size: 9px; color: var(--muted); letter-spacing: 0.07em;
|
|
1468
|
-
}
|
|
1469
|
-
#po-knowledge-canvas-controls label { display: flex; align-items: center; gap: 4px; cursor: pointer; }
|
|
1470
|
-
#po-kg2-canvas { flex: 1; width: 100%; display: block; }
|
|
1471
|
-
#po-knowledge-main { flex: 1; min-width: 240px; overflow-y: auto; padding: 16px 20px; }
|
|
1460
|
+
|
|
1461
|
+
.gf-tool-tab { background: none; border: 1px solid transparent; color: var(--muted); font-family: 'Azeret Mono', monospace; font-size: 8px; letter-spacing: 0.1em; padding: 3px 10px; cursor: pointer; border-radius: 2px; transition: all 0.15s; }
|
|
1462
|
+
.gf-tool-tab:hover { color: var(--text); background: rgba(255,255,255,0.04); }
|
|
1463
|
+
.gf-tool-tab.active { color: var(--teal); border-color: rgba(0,229,200,0.3); background: rgba(0,229,200,0.06); }
|
|
1464
|
+
.gf-view { display: none; }
|
|
1465
|
+
.gf-view.active { display: flex; }
|
|
1472
1466
|
|
|
1473
1467
|
/* Sidebar stat blocks */
|
|
1474
1468
|
.kg-stat-group { margin-bottom: 18px; }
|
|
@@ -1550,7 +1544,7 @@
|
|
|
1550
1544
|
<button class="po-tab" onclick="switchPalaceTab('routing')">ROUTING</button>
|
|
1551
1545
|
<button class="po-tab" onclick="switchPalaceTab('swarm')">SWARM</button>
|
|
1552
1546
|
<button class="po-tab" onclick="switchPalaceTab('graph')">AGENT GRAPH</button>
|
|
1553
|
-
<button class="po-tab" onclick="switchPalaceTab('knowledge')">
|
|
1547
|
+
<button class="po-tab" onclick="switchPalaceTab('knowledge')">GRAPHIFY</button>
|
|
1554
1548
|
</div>
|
|
1555
1549
|
<div id="po-stats"></div>
|
|
1556
1550
|
</div>
|
|
@@ -1686,15 +1680,71 @@
|
|
|
1686
1680
|
<div id="po-knowledge-sidebar">
|
|
1687
1681
|
<div id="po-knowledge-stats"><div style="color:var(--muted);font-size:10px;">Loading…</div></div>
|
|
1688
1682
|
</div>
|
|
1689
|
-
<div id="po-knowledge-
|
|
1690
|
-
<div id="po-
|
|
1691
|
-
<
|
|
1692
|
-
<
|
|
1683
|
+
<div id="po-knowledge-main-area" style="flex:1;display:flex;flex-direction:column;min-width:0;overflow:hidden;">
|
|
1684
|
+
<div id="po-graphify-toolbar" style="display:flex;align-items:center;gap:8px;padding:6px 14px;border-bottom:1px solid var(--border);flex-shrink:0;">
|
|
1685
|
+
<button class="gf-tool-tab active" data-gftab="graph" onclick="switchGraphifyView('graph')">GRAPH</button>
|
|
1686
|
+
<button class="gf-tool-tab" data-gftab="query" onclick="switchGraphifyView('query')">QUERY</button>
|
|
1687
|
+
<button class="gf-tool-tab" data-gftab="explain" onclick="switchGraphifyView('explain')">EXPLAIN</button>
|
|
1688
|
+
<button class="gf-tool-tab" data-gftab="path" onclick="switchGraphifyView('path')">PATH</button>
|
|
1689
|
+
<button class="gf-tool-tab" data-gftab="benchmark" onclick="switchGraphifyView('benchmark')">BENCHMARK</button>
|
|
1690
|
+
<button class="gf-tool-tab" data-gftab="report" onclick="switchGraphifyView('report')">REPORT</button>
|
|
1691
|
+
<span style="flex:1;"></span>
|
|
1692
|
+
<span id="gf-watch-indicator" style="font-size:8px;letter-spacing:0.06em;"></span>
|
|
1693
|
+
<button id="gf-watch-btn" class="kg-action-btn" style="width:auto;padding:3px 10px;margin:0;" onclick="toggleGraphifyWatch()">WATCH</button>
|
|
1694
|
+
</div>
|
|
1695
|
+
|
|
1696
|
+
<!-- GRAPH sub-view (embedded graphify interactive HTML) -->
|
|
1697
|
+
<div id="gf-view-graph" class="gf-view active" style="flex:1;display:flex;flex-direction:column;">
|
|
1698
|
+
<iframe id="gf-graph-iframe" style="flex:1;width:100%;border:none;background:#0f0f1a;"></iframe>
|
|
1699
|
+
</div>
|
|
1700
|
+
|
|
1701
|
+
<!-- QUERY sub-view -->
|
|
1702
|
+
<div id="gf-view-query" class="gf-view" style="flex:1;overflow-y:auto;padding:16px 20px;">
|
|
1703
|
+
<div style="display:flex;gap:8px;align-items:center;margin-bottom:12px;">
|
|
1704
|
+
<input id="gf-query-input" type="text" placeholder="Ask about the codebase…" style="flex:1;background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:3px;padding:7px 10px;color:var(--text);font-family:'Azeret Mono',monospace;font-size:11px;outline:none;" onkeydown="if(event.key==='Enter')runGraphifyQuery()">
|
|
1705
|
+
<select id="gf-query-mode" style="background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:3px;padding:5px 8px;color:var(--text);font-family:'Azeret Mono',monospace;font-size:9px;">
|
|
1706
|
+
<option value="dfs">DFS</option>
|
|
1707
|
+
<option value="bfs">BFS</option>
|
|
1708
|
+
</select>
|
|
1709
|
+
<input id="gf-query-budget" type="number" value="2000" min="100" max="50000" step="500" style="width:70px;background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:3px;padding:5px 6px;color:var(--text);font-family:'Azeret Mono',monospace;font-size:9px;" title="Token budget">
|
|
1710
|
+
<button class="kg-action-btn" style="width:auto;padding:5px 14px;margin:0;" onclick="runGraphifyQuery()">ASK</button>
|
|
1711
|
+
</div>
|
|
1712
|
+
<div id="gf-query-result" style="font-size:10px;color:var(--dim);line-height:1.7;white-space:pre-wrap;word-break:break-word;"></div>
|
|
1713
|
+
</div>
|
|
1714
|
+
|
|
1715
|
+
<!-- EXPLAIN sub-view -->
|
|
1716
|
+
<div id="gf-view-explain" class="gf-view" style="flex:1;overflow-y:auto;padding:16px 20px;">
|
|
1717
|
+
<div style="display:flex;gap:8px;align-items:center;margin-bottom:12px;">
|
|
1718
|
+
<input id="gf-explain-input" type="text" placeholder="Node name (e.g. UserService, auth.ts)…" style="flex:1;background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:3px;padding:7px 10px;color:var(--text);font-family:'Azeret Mono',monospace;font-size:11px;outline:none;" onkeydown="if(event.key==='Enter')runGraphifyExplain()">
|
|
1719
|
+
<button class="kg-action-btn" style="width:auto;padding:5px 14px;margin:0;" onclick="runGraphifyExplain()">EXPLAIN</button>
|
|
1720
|
+
</div>
|
|
1721
|
+
<div id="gf-explain-result" style="font-size:10px;color:var(--dim);line-height:1.7;white-space:pre-wrap;word-break:break-word;"></div>
|
|
1722
|
+
</div>
|
|
1723
|
+
|
|
1724
|
+
<!-- PATH sub-view -->
|
|
1725
|
+
<div id="gf-view-path" class="gf-view" style="flex:1;overflow-y:auto;padding:16px 20px;">
|
|
1726
|
+
<div style="display:flex;gap:8px;align-items:center;margin-bottom:12px;">
|
|
1727
|
+
<input id="gf-path-from" type="text" placeholder="From node…" style="flex:1;background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:3px;padding:7px 10px;color:var(--text);font-family:'Azeret Mono',monospace;font-size:11px;outline:none;">
|
|
1728
|
+
<span style="color:var(--muted);font-size:10px;">→</span>
|
|
1729
|
+
<input id="gf-path-to" type="text" placeholder="To node…" style="flex:1;background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:3px;padding:7px 10px;color:var(--text);font-family:'Azeret Mono',monospace;font-size:11px;outline:none;" onkeydown="if(event.key==='Enter')runGraphifyPath()">
|
|
1730
|
+
<button class="kg-action-btn" style="width:auto;padding:5px 14px;margin:0;" onclick="runGraphifyPath()">FIND PATH</button>
|
|
1731
|
+
</div>
|
|
1732
|
+
<div id="gf-path-result" style="font-size:10px;color:var(--dim);line-height:1.7;white-space:pre-wrap;word-break:break-word;"></div>
|
|
1733
|
+
</div>
|
|
1734
|
+
|
|
1735
|
+
<!-- BENCHMARK sub-view -->
|
|
1736
|
+
<div id="gf-view-benchmark" class="gf-view" style="flex:1;overflow-y:auto;padding:16px 20px;">
|
|
1737
|
+
<div style="display:flex;gap:8px;align-items:center;margin-bottom:12px;">
|
|
1738
|
+
<button class="kg-action-btn" style="width:auto;padding:5px 14px;margin:0;" onclick="runGraphifyBenchmark()">RUN BENCHMARK</button>
|
|
1739
|
+
<span id="gf-bench-status" style="font-size:9px;color:var(--muted);"></span>
|
|
1740
|
+
</div>
|
|
1741
|
+
<div id="gf-benchmark-result" style="font-size:10px;color:var(--dim);line-height:1.7;white-space:pre-wrap;word-break:break-word;"></div>
|
|
1742
|
+
</div>
|
|
1743
|
+
|
|
1744
|
+
<!-- REPORT sub-view -->
|
|
1745
|
+
<div id="gf-view-report" class="gf-view" style="flex:1;overflow-y:auto;padding:16px 20px;">
|
|
1746
|
+
<div id="po-knowledge-body"><div style="color:var(--muted);font-size:10px;padding:16px;">Loading…</div></div>
|
|
1693
1747
|
</div>
|
|
1694
|
-
<canvas id="po-kg2-canvas"></canvas>
|
|
1695
|
-
</div>
|
|
1696
|
-
<div id="po-knowledge-main">
|
|
1697
|
-
<div id="po-knowledge-body"><div style="color:var(--muted);font-size:10px;padding:16px;">Loading…</div></div>
|
|
1698
1748
|
</div>
|
|
1699
1749
|
</div>
|
|
1700
1750
|
</div>
|
|
@@ -3530,7 +3580,7 @@ window.switchPalaceTab = function(tab) {
|
|
|
3530
3580
|
const paneIds = { drawers: 'po-drawers-tab', sessions: 'po-sessions-tab', chunks: 'po-chunks-tab', routing: 'po-routing-tab', swarm: 'po-swarm-tab', graph: 'po-graph-tab', knowledge: 'po-knowledge-tab' };
|
|
3531
3581
|
const pane = document.getElementById(paneIds[tab]);
|
|
3532
3582
|
if (pane) pane.classList.add('active');
|
|
3533
|
-
if (tab !== 'knowledge') kgCodeGraph.stop();
|
|
3583
|
+
if (tab !== 'knowledge' && typeof kgCodeGraph !== 'undefined' && kgCodeGraph.stop) kgCodeGraph.stop();
|
|
3534
3584
|
if (palaceData) renderPalaceTab(tab);
|
|
3535
3585
|
};
|
|
3536
3586
|
|
|
@@ -3628,7 +3678,7 @@ function renderPalaceTab(tab) {
|
|
|
3628
3678
|
else if (tab === 'routing') renderHooks(appData || {});
|
|
3629
3679
|
else if (tab === 'swarm') renderPalaceSwarm();
|
|
3630
3680
|
else if (tab === 'graph') { renderAgentGraph(palaceData.graph || { nodes: [], edges: [] }); }
|
|
3631
|
-
else if (tab === 'knowledge') { renderPalaceKnowledge();
|
|
3681
|
+
else if (tab === 'knowledge') { renderPalaceKnowledge(); loadGraphifyIframe(); refreshWatchStatus(); }
|
|
3632
3682
|
}
|
|
3633
3683
|
|
|
3634
3684
|
let _allChunks = [];
|
|
@@ -4312,28 +4362,15 @@ async function renderPalaceKnowledge() {
|
|
|
4312
4362
|
}
|
|
4313
4363
|
}
|
|
4314
4364
|
|
|
4315
|
-
let
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
if (
|
|
4319
|
-
if (_codeGraphLoaded && !force) return;
|
|
4320
|
-
_codeGraphPending = true;
|
|
4365
|
+
let _graphifyIframeLoaded = false;
|
|
4366
|
+
function loadGraphifyIframe(force) {
|
|
4367
|
+
const iframe = document.getElementById('gf-graph-iframe');
|
|
4368
|
+
if (!iframe) return;
|
|
4321
4369
|
const dir = selectedProjectDir || '';
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
} catch { gd = null; }
|
|
4327
|
-
_codeGraphPending = false;
|
|
4328
|
-
if ((selectedProjectDir || '') !== dir) return;
|
|
4329
|
-
if (palaceCurrentTab !== 'knowledge') return;
|
|
4330
|
-
const info = document.getElementById('po-kg2-info');
|
|
4331
|
-
if (!gd || !gd.nodes || !gd.nodes.length) {
|
|
4332
|
-
if (info) info.textContent = gd && gd.tooLarge ? 'Graph too large to display' : 'No graph data';
|
|
4333
|
-
return;
|
|
4334
|
-
}
|
|
4335
|
-
kgCodeGraph.init();
|
|
4336
|
-
kgCodeGraph.render(gd, () => { _codeGraphLoaded = true; });
|
|
4370
|
+
const src = `/api/graphify-html${dir ? '?dir=' + encodeURIComponent(dir) : ''}`;
|
|
4371
|
+
if (!force && _graphifyIframeLoaded && iframe.src && iframe.src.includes('/api/graphify-html')) return;
|
|
4372
|
+
iframe.src = src;
|
|
4373
|
+
_graphifyIframeLoaded = true;
|
|
4337
4374
|
}
|
|
4338
4375
|
|
|
4339
4376
|
window.triggerPalaceGraphBuild = async function() {
|
|
@@ -4350,7 +4387,7 @@ window.triggerPalaceGraphBuild = async function() {
|
|
|
4350
4387
|
try {
|
|
4351
4388
|
const r = await fetch(`/api/graphify-report${dir ? '?dir=' + encodeURIComponent(dir) : ''}`);
|
|
4352
4389
|
const d = await r.json();
|
|
4353
|
-
if (d.stats || d.exists) { clearInterval(poll); renderPalaceKnowledge();
|
|
4390
|
+
if (d.stats || d.exists) { clearInterval(poll); renderPalaceKnowledge(); _graphifyIframeLoaded = false; loadGraphifyIframe(true); }
|
|
4354
4391
|
else if (attempts >= 36) { clearInterval(poll); if (bodyEl) bodyEl.innerHTML = '<div style="color:var(--amber);font-size:10px;">Build timed out — check server logs.</div>'; }
|
|
4355
4392
|
} catch {}
|
|
4356
4393
|
}, 5000);
|
|
@@ -4360,6 +4397,143 @@ window.triggerPalaceGraphBuild = async function() {
|
|
|
4360
4397
|
}
|
|
4361
4398
|
};
|
|
4362
4399
|
|
|
4400
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
4401
|
+
// GRAPHIFY INTERACTIVE VIEWS
|
|
4402
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
4403
|
+
let _currentGraphifyView = 'graph';
|
|
4404
|
+
|
|
4405
|
+
window.switchGraphifyView = function(view) {
|
|
4406
|
+
_currentGraphifyView = view;
|
|
4407
|
+
document.querySelectorAll('.gf-tool-tab').forEach(b => {
|
|
4408
|
+
b.classList.toggle('active', b.getAttribute('data-gftab') === view);
|
|
4409
|
+
});
|
|
4410
|
+
document.querySelectorAll('.gf-view').forEach(v => v.classList.remove('active'));
|
|
4411
|
+
const pane = document.getElementById('gf-view-' + view);
|
|
4412
|
+
if (pane) pane.classList.add('active');
|
|
4413
|
+
if (view === 'graph') { loadGraphifyIframe(); }
|
|
4414
|
+
if (view === 'report') { renderPalaceKnowledge(); }
|
|
4415
|
+
};
|
|
4416
|
+
|
|
4417
|
+
window.runGraphifyQuery = async function() {
|
|
4418
|
+
const input = document.getElementById('gf-query-input');
|
|
4419
|
+
const mode = document.getElementById('gf-query-mode');
|
|
4420
|
+
const budget = document.getElementById('gf-query-budget');
|
|
4421
|
+
const result = document.getElementById('gf-query-result');
|
|
4422
|
+
const q = (input && input.value || '').trim();
|
|
4423
|
+
if (!q) { if (result) result.textContent = 'Type a question first.'; return; }
|
|
4424
|
+
if (result) result.innerHTML = '<span style="color:var(--teal);">Querying…</span>';
|
|
4425
|
+
const dir = selectedProjectDir || '';
|
|
4426
|
+
try {
|
|
4427
|
+
const params = new URLSearchParams({ q, mode: mode.value, budget: budget.value });
|
|
4428
|
+
if (dir) params.set('dir', dir);
|
|
4429
|
+
const r = await fetch('/api/graphify-query?' + params);
|
|
4430
|
+
const d = await r.json();
|
|
4431
|
+
if (d.error) { result.innerHTML = `<span style="color:var(--red);">${escHtml(d.error)}</span>`; return; }
|
|
4432
|
+
result.innerHTML = `<div class="kg-card kg-card-wide" style="margin-bottom:10px;">
|
|
4433
|
+
<div class="kg-card-title"><span class="kg-card-title-icon">🔍</span>QUERY RESULT</div>
|
|
4434
|
+
<div class="kg-card-body">${escHtml(d.output || d.result || JSON.stringify(d, null, 2))}</div>
|
|
4435
|
+
</div>`;
|
|
4436
|
+
} catch (e) { result.innerHTML = `<span style="color:var(--red);">${escHtml(e.message)}</span>`; }
|
|
4437
|
+
};
|
|
4438
|
+
|
|
4439
|
+
window.runGraphifyExplain = async function() {
|
|
4440
|
+
const input = document.getElementById('gf-explain-input');
|
|
4441
|
+
const result = document.getElementById('gf-explain-result');
|
|
4442
|
+
const node = (input && input.value || '').trim();
|
|
4443
|
+
if (!node) { if (result) result.textContent = 'Enter a node name first.'; return; }
|
|
4444
|
+
if (result) result.innerHTML = '<span style="color:var(--teal);">Explaining…</span>';
|
|
4445
|
+
const dir = selectedProjectDir || '';
|
|
4446
|
+
try {
|
|
4447
|
+
const params = new URLSearchParams({ node });
|
|
4448
|
+
if (dir) params.set('dir', dir);
|
|
4449
|
+
const r = await fetch('/api/graphify-explain?' + params);
|
|
4450
|
+
const d = await r.json();
|
|
4451
|
+
if (d.error) { result.innerHTML = `<span style="color:var(--red);">${escHtml(d.error)}</span>`; return; }
|
|
4452
|
+
result.innerHTML = `<div class="kg-card kg-card-wide" style="margin-bottom:10px;">
|
|
4453
|
+
<div class="kg-card-title"><span class="kg-card-title-icon">📖</span>EXPLAIN: ${escHtml(node.toUpperCase())}</div>
|
|
4454
|
+
<div class="kg-card-body">${escHtml(d.output || d.result || JSON.stringify(d, null, 2))}</div>
|
|
4455
|
+
</div>`;
|
|
4456
|
+
} catch (e) { result.innerHTML = `<span style="color:var(--red);">${escHtml(e.message)}</span>`; }
|
|
4457
|
+
};
|
|
4458
|
+
|
|
4459
|
+
window.runGraphifyPath = async function() {
|
|
4460
|
+
const fromEl = document.getElementById('gf-path-from');
|
|
4461
|
+
const toEl = document.getElementById('gf-path-to');
|
|
4462
|
+
const result = document.getElementById('gf-path-result');
|
|
4463
|
+
const from = (fromEl && fromEl.value || '').trim();
|
|
4464
|
+
const to = (toEl && toEl.value || '').trim();
|
|
4465
|
+
if (!from || !to) { if (result) result.textContent = 'Enter both source and target nodes.'; return; }
|
|
4466
|
+
if (result) result.innerHTML = '<span style="color:var(--teal);">Finding shortest path…</span>';
|
|
4467
|
+
const dir = selectedProjectDir || '';
|
|
4468
|
+
try {
|
|
4469
|
+
const params = new URLSearchParams({ from, to });
|
|
4470
|
+
if (dir) params.set('dir', dir);
|
|
4471
|
+
const r = await fetch('/api/graphify-path?' + params);
|
|
4472
|
+
const d = await r.json();
|
|
4473
|
+
if (d.error) { result.innerHTML = `<span style="color:var(--red);">${escHtml(d.error)}</span>`; return; }
|
|
4474
|
+
result.innerHTML = `<div class="kg-card kg-card-wide" style="margin-bottom:10px;">
|
|
4475
|
+
<div class="kg-card-title"><span class="kg-card-title-icon">🛤</span>PATH: ${escHtml(from)} → ${escHtml(to)}</div>
|
|
4476
|
+
<div class="kg-card-body">${escHtml(d.output || d.result || JSON.stringify(d, null, 2))}</div>
|
|
4477
|
+
</div>`;
|
|
4478
|
+
} catch (e) { result.innerHTML = `<span style="color:var(--red);">${escHtml(e.message)}</span>`; }
|
|
4479
|
+
};
|
|
4480
|
+
|
|
4481
|
+
window.runGraphifyBenchmark = async function() {
|
|
4482
|
+
const result = document.getElementById('gf-benchmark-result');
|
|
4483
|
+
const status = document.getElementById('gf-bench-status');
|
|
4484
|
+
if (result) result.innerHTML = '<span style="color:var(--teal);">Running benchmark…</span>';
|
|
4485
|
+
if (status) status.textContent = 'Running…';
|
|
4486
|
+
const dir = selectedProjectDir || '';
|
|
4487
|
+
try {
|
|
4488
|
+
const params = dir ? '?dir=' + encodeURIComponent(dir) : '';
|
|
4489
|
+
const r = await fetch('/api/graphify-benchmark' + params);
|
|
4490
|
+
const d = await r.json();
|
|
4491
|
+
if (status) status.textContent = '';
|
|
4492
|
+
if (d.error) { result.innerHTML = `<span style="color:var(--red);">${escHtml(d.error)}</span>`; return; }
|
|
4493
|
+
result.innerHTML = `<div class="kg-card kg-card-wide">
|
|
4494
|
+
<div class="kg-card-title"><span class="kg-card-title-icon">⚡</span>BENCHMARK RESULTS</div>
|
|
4495
|
+
<div class="kg-card-body">${escHtml(d.output || d.result || JSON.stringify(d, null, 2))}</div>
|
|
4496
|
+
</div>`;
|
|
4497
|
+
} catch (e) { if (status) status.textContent = ''; result.innerHTML = `<span style="color:var(--red);">${escHtml(e.message)}</span>`; }
|
|
4498
|
+
};
|
|
4499
|
+
|
|
4500
|
+
window.toggleGraphifyWatch = async function() {
|
|
4501
|
+
const btn = document.getElementById('gf-watch-btn');
|
|
4502
|
+
const indicator = document.getElementById('gf-watch-indicator');
|
|
4503
|
+
const dir = selectedProjectDir || '';
|
|
4504
|
+
const params = dir ? '?dir=' + encodeURIComponent(dir) : '';
|
|
4505
|
+
try {
|
|
4506
|
+
const r = await fetch('/api/graphify-watch-toggle' + params, { method: 'POST' });
|
|
4507
|
+
const d = await r.json();
|
|
4508
|
+
updateWatchIndicator(d);
|
|
4509
|
+
} catch (e) {
|
|
4510
|
+
if (indicator) indicator.innerHTML = `<span style="color:var(--red);">Error</span>`;
|
|
4511
|
+
}
|
|
4512
|
+
};
|
|
4513
|
+
|
|
4514
|
+
async function refreshWatchStatus() {
|
|
4515
|
+
const dir = selectedProjectDir || '';
|
|
4516
|
+
const params = dir ? '?dir=' + encodeURIComponent(dir) : '';
|
|
4517
|
+
try {
|
|
4518
|
+
const r = await fetch('/api/graphify-watch-status' + params);
|
|
4519
|
+
const d = await r.json();
|
|
4520
|
+
updateWatchIndicator(d);
|
|
4521
|
+
} catch {}
|
|
4522
|
+
}
|
|
4523
|
+
|
|
4524
|
+
function updateWatchIndicator(d) {
|
|
4525
|
+
const indicator = document.getElementById('gf-watch-indicator');
|
|
4526
|
+
const btn = document.getElementById('gf-watch-btn');
|
|
4527
|
+
if (!indicator) return;
|
|
4528
|
+
if (d.running) {
|
|
4529
|
+
indicator.innerHTML = '<span style="color:var(--green);">● WATCHING</span>';
|
|
4530
|
+
if (btn) btn.textContent = 'STOP';
|
|
4531
|
+
} else {
|
|
4532
|
+
indicator.innerHTML = '<span style="color:var(--muted);">○ IDLE</span>';
|
|
4533
|
+
if (btn) btn.textContent = 'WATCH';
|
|
4534
|
+
}
|
|
4535
|
+
}
|
|
4536
|
+
|
|
4363
4537
|
let _palaceSelectedSession = null;
|
|
4364
4538
|
|
|
4365
4539
|
function renderPalaceSessions() {
|
package/dist/src/ui/server.mjs
CHANGED
|
@@ -594,6 +594,23 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
|
|
|
594
594
|
return;
|
|
595
595
|
}
|
|
596
596
|
|
|
597
|
+
// ------------------------------------------------------- GET /api/graphify-html
|
|
598
|
+
if (req.method === 'GET' && url === '/api/graphify-html') {
|
|
599
|
+
try {
|
|
600
|
+
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
601
|
+
const dir = qs.get('dir') || projectDir;
|
|
602
|
+
const d = path.resolve(dir || process.cwd());
|
|
603
|
+
const htmlPath = path.join(d, '.monomind', 'graph', 'graph.html');
|
|
604
|
+
const html = fs.readFileSync(htmlPath, 'utf-8');
|
|
605
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Access-Control-Allow-Origin': '*', 'Cache-Control': 'no-cache' });
|
|
606
|
+
res.end(html);
|
|
607
|
+
} catch (err) {
|
|
608
|
+
res.writeHead(404, { 'Content-Type': 'text/html' });
|
|
609
|
+
res.end('<html><body style="background:#0f0f1a;color:#888;font-family:monospace;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;"><div style="text-align:center;"><h3 style="color:#4E79A7;">No Graph Built Yet</h3><p>Run <code style="color:#00E5C8;">graphify update .</code> or click BUILD in the sidebar.</p></div></body></html>');
|
|
610
|
+
}
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
|
|
597
614
|
// ------------------------------------------------------- GET /api/graphify-report
|
|
598
615
|
if (req.method === 'GET' && url === '/api/graphify-report') {
|
|
599
616
|
try {
|
|
@@ -693,25 +710,193 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
|
|
|
693
710
|
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
694
711
|
const dir = qs.get('dir') || projectDir;
|
|
695
712
|
const d = path.resolve(dir || process.cwd());
|
|
696
|
-
const outputDir = path.join(d, '.monomind', 'graph');
|
|
697
713
|
|
|
698
|
-
// Start build in background, respond immediately so UI can show progress state
|
|
699
714
|
res.writeHead(202, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
700
|
-
res.end(JSON.stringify({ status: 'building', dir: d
|
|
715
|
+
res.end(JSON.stringify({ status: 'building', dir: d }));
|
|
701
716
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
717
|
+
// Build via graphify CLI in background
|
|
718
|
+
const { spawn: sp } = await import('child_process');
|
|
719
|
+
const child = sp('graphify', ['update', d], { stdio: 'ignore', detached: true, cwd: d });
|
|
720
|
+
child.unref();
|
|
721
|
+
console.log(`[graph] build started for ${d} via graphify update`);
|
|
722
|
+
} catch (err) {
|
|
723
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
724
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
725
|
+
}
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// -------------------------------------------------- GET /api/graphify-query
|
|
730
|
+
if (req.method === 'GET' && url === '/api/graphify-query') {
|
|
731
|
+
try {
|
|
732
|
+
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
733
|
+
const dir = qs.get('dir') || projectDir;
|
|
734
|
+
const q = qs.get('q') || '';
|
|
735
|
+
const mode = qs.get('mode') === 'dfs' ? '--dfs' : '';
|
|
736
|
+
const budget = qs.get('budget') || '2000';
|
|
737
|
+
const d = path.resolve(dir || process.cwd());
|
|
738
|
+
const graphPath = path.join(d, '.monomind', 'graph', 'graph.json');
|
|
739
|
+
const legacyPath = path.join(d, 'graphify-out', 'graph.json');
|
|
740
|
+
const gp = fs.existsSync(graphPath) ? graphPath : (fs.existsSync(legacyPath) ? legacyPath : null);
|
|
741
|
+
|
|
742
|
+
if (!q) {
|
|
743
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
744
|
+
res.end(JSON.stringify({ error: 'Missing ?q= parameter' }));
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
const { execSync: ex } = await import('child_process');
|
|
749
|
+
const args = ['query', JSON.stringify(q), '--budget', budget];
|
|
750
|
+
if (mode) args.push(mode);
|
|
751
|
+
if (gp) args.push('--graph', gp);
|
|
752
|
+
const out = ex(`graphify ${args.join(' ')}`, { encoding: 'utf8', cwd: d, timeout: 30000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
753
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
754
|
+
res.end(JSON.stringify({ success: true, query: q, result: out }));
|
|
755
|
+
} catch (err) {
|
|
756
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
757
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
758
|
+
}
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// -------------------------------------------------- GET /api/graphify-explain
|
|
763
|
+
if (req.method === 'GET' && url === '/api/graphify-explain') {
|
|
764
|
+
try {
|
|
765
|
+
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
766
|
+
const dir = qs.get('dir') || projectDir;
|
|
767
|
+
const node = qs.get('node') || '';
|
|
768
|
+
const d = path.resolve(dir || process.cwd());
|
|
769
|
+
const graphPath = path.join(d, '.monomind', 'graph', 'graph.json');
|
|
770
|
+
const legacyPath = path.join(d, 'graphify-out', 'graph.json');
|
|
771
|
+
const gp = fs.existsSync(graphPath) ? graphPath : (fs.existsSync(legacyPath) ? legacyPath : null);
|
|
772
|
+
|
|
773
|
+
if (!node) {
|
|
774
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
775
|
+
res.end(JSON.stringify({ error: 'Missing ?node= parameter' }));
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
const { execSync: ex } = await import('child_process');
|
|
780
|
+
const args = ['explain', JSON.stringify(node)];
|
|
781
|
+
if (gp) args.push('--graph', gp);
|
|
782
|
+
const out = ex(`graphify ${args.join(' ')}`, { encoding: 'utf8', cwd: d, timeout: 15000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
783
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
784
|
+
res.end(JSON.stringify({ success: true, node, explanation: out }));
|
|
785
|
+
} catch (err) {
|
|
786
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
787
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
788
|
+
}
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// -------------------------------------------------- GET /api/graphify-path
|
|
793
|
+
if (req.method === 'GET' && url === '/api/graphify-path') {
|
|
794
|
+
try {
|
|
795
|
+
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
796
|
+
const dir = qs.get('dir') || projectDir;
|
|
797
|
+
const from = qs.get('from') || '';
|
|
798
|
+
const to = qs.get('to') || '';
|
|
799
|
+
const d = path.resolve(dir || process.cwd());
|
|
800
|
+
const graphPath = path.join(d, '.monomind', 'graph', 'graph.json');
|
|
801
|
+
const legacyPath = path.join(d, 'graphify-out', 'graph.json');
|
|
802
|
+
const gp = fs.existsSync(graphPath) ? graphPath : (fs.existsSync(legacyPath) ? legacyPath : null);
|
|
803
|
+
|
|
804
|
+
if (!from || !to) {
|
|
805
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
806
|
+
res.end(JSON.stringify({ error: 'Missing ?from= and ?to= parameters' }));
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
const { execSync: ex } = await import('child_process');
|
|
811
|
+
const args = ['path', JSON.stringify(from), JSON.stringify(to)];
|
|
812
|
+
if (gp) args.push('--graph', gp);
|
|
813
|
+
const out = ex(`graphify ${args.join(' ')}`, { encoding: 'utf8', cwd: d, timeout: 15000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
814
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
815
|
+
res.end(JSON.stringify({ success: true, from, to, path: out }));
|
|
816
|
+
} catch (err) {
|
|
817
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
818
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
819
|
+
}
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
// -------------------------------------------------- GET /api/graphify-watch-status
|
|
824
|
+
if (req.method === 'GET' && url === '/api/graphify-watch-status') {
|
|
825
|
+
try {
|
|
826
|
+
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
827
|
+
const dir = qs.get('dir') || projectDir;
|
|
828
|
+
const d = path.resolve(dir || process.cwd());
|
|
829
|
+
const pidPath = path.join(d, '.monomind', 'graph', 'watch.pid');
|
|
830
|
+
let running = false, pid = null;
|
|
831
|
+
try {
|
|
832
|
+
pid = parseInt(fs.readFileSync(pidPath, 'utf-8').trim(), 10);
|
|
833
|
+
process.kill(pid, 0);
|
|
834
|
+
running = true;
|
|
835
|
+
} catch {}
|
|
836
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
837
|
+
res.end(JSON.stringify({ running, pid }));
|
|
838
|
+
} catch (err) {
|
|
839
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
840
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
841
|
+
}
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// -------------------------------------------------- POST /api/graphify-watch-toggle
|
|
846
|
+
if (req.method === 'POST' && url === '/api/graphify-watch-toggle') {
|
|
847
|
+
try {
|
|
848
|
+
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
849
|
+
const dir = qs.get('dir') || projectDir;
|
|
850
|
+
const d = path.resolve(dir || process.cwd());
|
|
851
|
+
const pidPath = path.join(d, '.monomind', 'graph', 'watch.pid');
|
|
852
|
+
let wasRunning = false;
|
|
853
|
+
try {
|
|
854
|
+
const pid = parseInt(fs.readFileSync(pidPath, 'utf-8').trim(), 10);
|
|
855
|
+
process.kill(pid, 0);
|
|
856
|
+
wasRunning = true;
|
|
857
|
+
process.kill(pid, 'SIGTERM');
|
|
858
|
+
try { fs.unlinkSync(pidPath); } catch {}
|
|
859
|
+
} catch {}
|
|
860
|
+
|
|
861
|
+
if (wasRunning) {
|
|
862
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
863
|
+
res.end(JSON.stringify({ running: false, action: 'stopped' }));
|
|
864
|
+
} else {
|
|
865
|
+
const { spawn: sp } = await import('child_process');
|
|
866
|
+
const child = sp('graphify', ['watch', d], { stdio: 'ignore', detached: true, cwd: d });
|
|
867
|
+
child.unref();
|
|
868
|
+
try { fs.mkdirSync(path.join(d, '.monomind', 'graph'), { recursive: true }); } catch {}
|
|
869
|
+
try { fs.writeFileSync(pidPath, String(child.pid)); } catch {}
|
|
870
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
871
|
+
res.end(JSON.stringify({ running: true, pid: child.pid, action: 'started' }));
|
|
872
|
+
}
|
|
873
|
+
} catch (err) {
|
|
874
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
875
|
+
res.end(JSON.stringify({ error: err.message }));
|
|
876
|
+
}
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
// -------------------------------------------------- GET /api/graphify-benchmark
|
|
881
|
+
if (req.method === 'GET' && url === '/api/graphify-benchmark') {
|
|
882
|
+
try {
|
|
883
|
+
const qs = new URL(req.url, 'http://localhost').searchParams;
|
|
884
|
+
const dir = qs.get('dir') || projectDir;
|
|
885
|
+
const d = path.resolve(dir || process.cwd());
|
|
886
|
+
const graphPath = path.join(d, '.monomind', 'graph', 'graph.json');
|
|
887
|
+
const legacyPath = path.join(d, 'graphify-out', 'graph.json');
|
|
888
|
+
const gp = fs.existsSync(graphPath) ? graphPath : (fs.existsSync(legacyPath) ? legacyPath : null);
|
|
889
|
+
|
|
890
|
+
if (!gp) {
|
|
891
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
892
|
+
res.end(JSON.stringify({ available: false }));
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
const { execSync: ex } = await import('child_process');
|
|
897
|
+
const out = ex(`graphify benchmark ${gp}`, { encoding: 'utf8', cwd: d, timeout: 30000, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
898
|
+
res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
|
|
899
|
+
res.end(JSON.stringify({ available: true, result: out }));
|
|
715
900
|
} catch (err) {
|
|
716
901
|
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
717
902
|
res.end(JSON.stringify({ error: err.message }));
|