crg-dev-kit 2.0.7 → 2.2.1
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/CLAUDE.md +78 -48
- package/lib/actions.js +3 -5
- package/package.json +1 -1
- package/server.js +214 -35
package/assets/CLAUDE.md
CHANGED
|
@@ -1,48 +1,78 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
###
|
|
44
|
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
|
|
1
|
+
# ${PROJECT_NAME}
|
|
2
|
+
|
|
3
|
+
## MANDATORY: Use CRG Tools First
|
|
4
|
+
|
|
5
|
+
**CRITICAL: You MUST use code-review-graph (CRG) tools for ALL code exploration. Never use Read/Glob/Grep directly.**
|
|
6
|
+
|
|
7
|
+
### Required Workflow
|
|
8
|
+
|
|
9
|
+
1. **Every file read** → Use `get_review_context` or `query_graph` first
|
|
10
|
+
2. **Code review** → Use `detect_changes`
|
|
11
|
+
3. **Finding tests** → Use `query_graph pattern="tests_for"`
|
|
12
|
+
4. **Understanding code** → Use `query_graph pattern="callees_of"` or `callers_of"`
|
|
13
|
+
5. **Impact analysis** → Use `get_impact_radius`
|
|
14
|
+
|
|
15
|
+
### Why This Matters
|
|
16
|
+
|
|
17
|
+
- **CRG**: 6.8x fewer tokens on file reads
|
|
18
|
+
- **token-optimizer**: 95% compression on tool outputs
|
|
19
|
+
- **mem0**: Persistent memory across sessions
|
|
20
|
+
- **Combined**: Up to 49x token reduction + memory that persists
|
|
21
|
+
|
|
22
|
+
### When You MUST Use CRG
|
|
23
|
+
|
|
24
|
+
| Task | CRG Tool |
|
|
25
|
+
|------|----------|
|
|
26
|
+
| Read any file | `get_review_context` |
|
|
27
|
+
| Find function usages | `query_graph` with callers_of |
|
|
28
|
+
| Find tests for code | `query_graph pattern="tests_for"` |
|
|
29
|
+
| Understand imports | `query_graph pattern="imports_of"` |
|
|
30
|
+
| Review changes | `detect_changes` |
|
|
31
|
+
| See impact radius | `get_impact_radius` |
|
|
32
|
+
| Search code | `semantic_search_nodes` |
|
|
33
|
+
|
|
34
|
+
### Memory: Log Your Decisions
|
|
35
|
+
|
|
36
|
+
After completing a significant task, log the decision:
|
|
37
|
+
```
|
|
38
|
+
mem0.add("Added auth middleware. Why: Need rate limiting. Files: auth.js, rate.js. Context: 3 endpoints.")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This builds persistent memory for future sessions.
|
|
42
|
+
|
|
43
|
+
### Fallback Only If
|
|
44
|
+
|
|
45
|
+
- CRG returns insufficient info
|
|
46
|
+
- File not in graph yet
|
|
47
|
+
- Need very recent changes not yet in graph
|
|
48
|
+
|
|
49
|
+
### Available Tools
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
CRG (code-review-graph):
|
|
53
|
+
detect_changes - Risk-scored change review
|
|
54
|
+
get_review_context - Token-efficient snippets
|
|
55
|
+
get_impact_radius - Blast radius analysis
|
|
56
|
+
query_graph - Callers, callees, tests, imports
|
|
57
|
+
semantic_search - Find by meaning
|
|
58
|
+
build_or_update_graph - Refresh graph
|
|
59
|
+
list_graph_stats - Check graph health
|
|
60
|
+
|
|
61
|
+
Memory (mem0):
|
|
62
|
+
mem0.add - Store decision/context
|
|
63
|
+
mem0.search - Retrieve past context
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Quick Commands
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Build graph when new code is added
|
|
70
|
+
code-review-graph build
|
|
71
|
+
|
|
72
|
+
# Check graph stats
|
|
73
|
+
code-review-graph list_graph_stats
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
*This file auto-generated by crg-dev-kit.*
|
package/lib/actions.js
CHANGED
|
@@ -53,6 +53,9 @@ function install(targetDir, trackROI = true) {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// Don't update global CLAUDE.md - preserve user's custom rules
|
|
57
|
+
// The project CLAUDE.md already has all CRG instructions
|
|
58
|
+
|
|
56
59
|
if (trackROI) {
|
|
57
60
|
roi.setInstallDate(targetDir);
|
|
58
61
|
}
|
|
@@ -99,11 +102,9 @@ function uninstall(targetDir) {
|
|
|
99
102
|
function healthCheck(targetDir) {
|
|
100
103
|
const results = [];
|
|
101
104
|
|
|
102
|
-
// Check graph DB
|
|
103
105
|
const dbPath = path.join(targetDir, '.code-review-graph', 'graph.db');
|
|
104
106
|
results.push({ check: 'Graph DB exists', pass: fs.existsSync(dbPath) });
|
|
105
107
|
|
|
106
|
-
// Check setup files
|
|
107
108
|
results.push({ check: 'setup-crg.sh present', pass: fs.existsSync(path.join(targetDir, 'setup-crg.sh')) });
|
|
108
109
|
results.push({ check: 'CLAUDE.md present', pass: fs.existsSync(path.join(targetDir, 'CLAUDE.md')) });
|
|
109
110
|
|
|
@@ -111,11 +112,8 @@ function healthCheck(targetDir) {
|
|
|
111
112
|
execFile('code-review-graph', ['--version'], (err, stdout) => {
|
|
112
113
|
results.push({ check: 'code-review-graph CLI', pass: !err, version: err ? null : (stdout || '').trim() });
|
|
113
114
|
|
|
114
|
-
// Try getting graph stats
|
|
115
115
|
if (fs.existsSync(dbPath)) {
|
|
116
116
|
try {
|
|
117
|
-
const sqlite3 = require('child_process');
|
|
118
|
-
// Use python to read SQLite since we can't require sqlite3
|
|
119
117
|
const cmd = `python3 -c "import sqlite3,json;db=sqlite3.connect('${dbPath}');r=dict(nodes=db.execute('SELECT COUNT(*) FROM nodes').fetchone()[0],edges=db.execute('SELECT COUNT(*) FROM edges').fetchone()[0]);print(json.dumps(r))"`;
|
|
120
118
|
execFile('bash', ['-c', cmd], (err2, stdout2) => {
|
|
121
119
|
if (!err2 && stdout2) {
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const http = require('http');
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
|
-
const { execFile } = require('child_process');
|
|
4
|
+
const { execFile, exec } = require('child_process');
|
|
5
5
|
const analytics = require('./lib/analytics');
|
|
6
6
|
const roi = require('./lib/roi');
|
|
7
7
|
const actions = require('./lib/actions');
|
|
@@ -171,6 +171,14 @@ section{max-width:clamp(320px,90vw,780px);margin:0 auto;padding:0 clamp(16px,4vw
|
|
|
171
171
|
.dl-size{font-family:var(--m);font-size:11px;color:var(--t4);flex-shrink:0}
|
|
172
172
|
.dl-btn{background:var(--a);color:#fff;padding:6px 14px;border-radius:5px;font-size:12px;font-weight:700;flex-shrink:0;transition:background .15s}
|
|
173
173
|
.dl-card:hover .dl-btn{background:#c2410c}
|
|
174
|
+
.install-options{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:16px;margin-bottom:24px}
|
|
175
|
+
.install-card{background:var(--s);border:1px solid var(--b);border-radius:8px;padding:20px;display:flex;flex-direction:column}
|
|
176
|
+
.install-card:hover{border-color:var(--a)}
|
|
177
|
+
.install-header{display:flex;gap:12px;align-items:flex-start;margin-bottom:12px}
|
|
178
|
+
.install-icon{font-size:24px;line-height:1}
|
|
179
|
+
.install-title{font-weight:700;font-size:15px}
|
|
180
|
+
.install-desc{font-size:12px;color:var(--t3);margin-top:2px}
|
|
181
|
+
.install-card .btn{margin-top:auto}
|
|
174
182
|
.rc{background:var(--s);border:1px solid var(--b);border-radius:8px;padding:clamp(16px,3vw,32px)}
|
|
175
183
|
.rc h1{font-size:22px;font-weight:700;margin-bottom:16px;letter-spacing:-0.02em}
|
|
176
184
|
.rc h2{font-size:17px;font-weight:700;margin:24px 0 8px}
|
|
@@ -236,6 +244,9 @@ footer a{color:var(--a);text-decoration:none;font-weight:600}
|
|
|
236
244
|
.tool-name{font-family:var(--m);font-size:11px;color:var(--a);font-weight:600}
|
|
237
245
|
.tool-label{font-size:14px;font-weight:600;color:var(--t)}
|
|
238
246
|
.tool-desc{font-size:12px;color:var(--t3);line-height:1.4}
|
|
247
|
+
.btn-tool{background:var(--a);color:#fff;border:none;border-radius:4px;padding:4px 12px;font-size:11px;font-weight:600;cursor:pointer;margin-top:8px;width:100%}
|
|
248
|
+
.btn-tool:hover{background:#c2410c}
|
|
249
|
+
.btn-tool:disabled{opacity:.5;cursor:not-allowed}
|
|
239
250
|
.btn{background:var(--a);color:#fff;padding:10px 20px;border:none;border-radius:6px;font-weight:700;font-size:13px;cursor:pointer;font-family:inherit;transition:background .15s}
|
|
240
251
|
.btn:hover{background:#c2410c}
|
|
241
252
|
.btn:focus-visible{outline:2px solid var(--a);outline-offset:2px}
|
|
@@ -245,7 +256,7 @@ footer a{color:var(--a);text-decoration:none;font-weight:600}
|
|
|
245
256
|
.btn-secondary{background:var(--bg);color:var(--t2);border:1px solid var(--b)}
|
|
246
257
|
.check-pass{color:#16a34a}
|
|
247
258
|
.check-fail{color:#dc2626}
|
|
248
|
-
.check-item{display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--b)}
|
|
259
|
+
.check-item{display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--b);color:var(--t)}
|
|
249
260
|
.check-item:last-child{border-bottom:none}
|
|
250
261
|
.result-box{background:var(--s);border:1px solid var(--b);border-radius:8px;padding:20px;margin-top:16px}
|
|
251
262
|
.result-success{border-color:#16a34a;background:#f0fdf4}
|
|
@@ -261,9 +272,18 @@ footer a{color:var(--a);text-decoration:none;font-weight:600}
|
|
|
261
272
|
@media(prefers-color-scheme:dark){
|
|
262
273
|
:root{--bg:#1c1917;--s:#292524;--b:#44403c;--t:#fafaf9;--t2:#d6d3d1;--t3:#a8a29e;--t4:#78716c;--al:#292524;--ab:#44403c}
|
|
263
274
|
.dl-card:hover,.roi-card,.stat-card,.tool-card,.project-table table,.roi-compare{background:var(--s)}
|
|
275
|
+
.result-box{background:var(--s)}
|
|
276
|
+
.result-success{background:#16653420;border-color:#22c55e}
|
|
277
|
+
.result-error{background:#991b1b20;border-color:#ef4444}
|
|
278
|
+
.check-pass{color:#22c55e}
|
|
279
|
+
.check-fail{color:#ef4444}
|
|
264
280
|
}
|
|
265
281
|
@media(prefers-color-scheme:light){
|
|
266
282
|
:root{--bg:#fafaf9;--s:#fff;--b:#e7e5e4;--t:#1c1917;--t2:#57534e;--t3:#78716c;--t4:#a8a29e;--al:#fff7ed;--ab:#fed7aa}
|
|
283
|
+
.result-success{background:#f0fdf4;border-color:#16a34a}
|
|
284
|
+
.result-error{background:#fef2f2;border-color:#dc2626}
|
|
285
|
+
.check-pass{color:#16a34a}
|
|
286
|
+
.check-fail{color:#dc2626}
|
|
267
287
|
}
|
|
268
288
|
@media(max-width:768px){
|
|
269
289
|
.analytics-grid,.roi-grid{grid-template-columns:repeat(2,1fr)}
|
|
@@ -348,31 +368,97 @@ function tabDashboard(cwd) {
|
|
|
348
368
|
function tabInstall(cwd) {
|
|
349
369
|
return `
|
|
350
370
|
<section>
|
|
351
|
-
<div class="st">Install
|
|
352
|
-
<p style="color:var(--t2);font-size:14px;margin-bottom:
|
|
353
|
-
<div
|
|
354
|
-
<
|
|
355
|
-
|
|
371
|
+
<div class="st">Quick Install — Maximum Token Savings</div>
|
|
372
|
+
<p style="color:var(--t2);font-size:14px;margin-bottom:20px">Install both CRG + token-optimizer-mcp for 95%+ token reduction.</p>
|
|
373
|
+
<div class="install-options">
|
|
374
|
+
<div class="install-card">
|
|
375
|
+
<div class="install-header">
|
|
376
|
+
<span class="install-icon">⚡</span>
|
|
377
|
+
<div>
|
|
378
|
+
<div class="install-title">Full Stack (Recommended)</div>
|
|
379
|
+
<div class="install-desc">CRG + token-optimizer + mem0 — 95%+ token savings + persistent memory</div>
|
|
380
|
+
</div>
|
|
381
|
+
</div>
|
|
382
|
+
<button class="btn" style="width:100%;margin-top:12px"
|
|
383
|
+
hx-post="/api/install-fullstack"
|
|
384
|
+
hx-target="#install-result"
|
|
385
|
+
hx-swap="innerHTML">
|
|
386
|
+
Install Full Stack
|
|
387
|
+
</button>
|
|
388
|
+
</div>
|
|
389
|
+
|
|
390
|
+
<div class="install-card">
|
|
391
|
+
<div class="install-header">
|
|
392
|
+
<span class="install-icon">📊</span>
|
|
393
|
+
<div>
|
|
394
|
+
<div class="install-title">CRG Only</div>
|
|
395
|
+
<div class="install-desc">Knowledge graph — reads less, understands more</div>
|
|
396
|
+
</div>
|
|
397
|
+
</div>
|
|
398
|
+
<button class="btn btn-secondary" style="width:100%;margin-top:12px"
|
|
399
|
+
hx-post="/api/install"
|
|
400
|
+
hx-target="#install-result"
|
|
401
|
+
hx-swap="innerHTML"
|
|
402
|
+
hx-include="#install-dir">
|
|
403
|
+
Install CRG Only
|
|
404
|
+
</button>
|
|
405
|
+
</div>
|
|
406
|
+
|
|
407
|
+
<div class="install-card">
|
|
408
|
+
<div class="install-header">
|
|
409
|
+
<span class="install-icon">🎯</span>
|
|
410
|
+
<div>
|
|
411
|
+
<div class="install-title">token-optimizer Only</div>
|
|
412
|
+
<div class="install-desc">Smart caching + compression for tool outputs</div>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
<button class="btn btn-secondary" style="width:100%;margin-top:12px"
|
|
416
|
+
hx-post="/api/install-optimizer"
|
|
417
|
+
hx-target="#install-result"
|
|
418
|
+
hx-swap="innerHTML">
|
|
419
|
+
Install token-optimizer
|
|
420
|
+
</button>
|
|
421
|
+
</div>
|
|
422
|
+
|
|
423
|
+
<div class="install-card">
|
|
424
|
+
<div class="install-header">
|
|
425
|
+
<span class="install-icon">🧠</span>
|
|
426
|
+
<div>
|
|
427
|
+
<div class="install-title">mem0 Only</div>
|
|
428
|
+
<div class="install-desc">Persistent memory layer for sessions</div>
|
|
429
|
+
</div>
|
|
430
|
+
</div>
|
|
431
|
+
<button class="btn btn-secondary" style="width:100%;margin-top:12px"
|
|
432
|
+
hx-post="/api/install-mem0"
|
|
433
|
+
hx-target="#install-result"
|
|
434
|
+
hx-swap="innerHTML">
|
|
435
|
+
Install mem0
|
|
436
|
+
</button>
|
|
437
|
+
</div>
|
|
356
438
|
</div>
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
hx-swap="innerHTML"
|
|
362
|
-
hx-include="#install-dir"
|
|
363
|
-
hx-indicator="#install-spinner">
|
|
364
|
-
Install Files <span id="install-spinner" class="htmx-indicator"><span class="spinner"></span></span>
|
|
365
|
-
</button>
|
|
366
|
-
<button class="btn btn-danger"
|
|
367
|
-
hx-post="/api/uninstall"
|
|
368
|
-
hx-target="#install-result"
|
|
369
|
-
hx-swap="innerHTML"
|
|
370
|
-
hx-include="#install-dir"
|
|
371
|
-
hx-indicator="#uninstall-spinner">
|
|
372
|
-
Uninstall <span id="uninstall-spinner" class="htmx-indicator"><span class="spinner"></span></span>
|
|
373
|
-
</button>
|
|
439
|
+
|
|
440
|
+
<div style="margin-top:24px">
|
|
441
|
+
<label for="install-dir" style="font-size:12px;font-weight:600;color:var(--t3);display:block;margin-bottom:6px">Target Directory (for CRG files)</label>
|
|
442
|
+
<input class="input" id="install-dir" name="targetDir" value="${esc(cwd)}" />
|
|
374
443
|
</div>
|
|
444
|
+
|
|
375
445
|
<div id="install-result"></div>
|
|
446
|
+
|
|
447
|
+
<div class="st" style="margin-top:32px">Why Full Stack?</div>
|
|
448
|
+
<div class="roi-grid" style="grid-template-columns:repeat(3,1fr)">
|
|
449
|
+
<div class="roi-card">
|
|
450
|
+
<div class="roi-value" style="color:#16a34a">6.8x</div>
|
|
451
|
+
<div class="roi-label">CRG Reduction</div>
|
|
452
|
+
</div>
|
|
453
|
+
<div class="roi-card">
|
|
454
|
+
<div class="roi-value" style="color:#16a34a">95%</div>
|
|
455
|
+
<div class="roi-label">token-optimizer</div>
|
|
456
|
+
</div>
|
|
457
|
+
<div class="roi-card">
|
|
458
|
+
<div class="roi-value" style="color:#16a34a">🧠</div>
|
|
459
|
+
<div class="roi-label">mem0 Memory</div>
|
|
460
|
+
</div>
|
|
461
|
+
</div>
|
|
376
462
|
</section>`;
|
|
377
463
|
}
|
|
378
464
|
|
|
@@ -549,17 +635,31 @@ function tabAnalytics(cwd) {
|
|
|
549
635
|
return `<section>${roiHtml}${tokenHtml}</section>`;
|
|
550
636
|
}
|
|
551
637
|
|
|
552
|
-
function tabTools() {
|
|
638
|
+
function tabTools(cwd) {
|
|
553
639
|
const toolCards = CRG_TOOLS.map(t => `
|
|
554
|
-
<div class="tool-card"
|
|
640
|
+
<div class="tool-card">
|
|
555
641
|
<span class="tool-name">${t.name}</span>
|
|
556
642
|
<span class="tool-label">${t.label}</span>
|
|
557
643
|
<span class="tool-desc">${t.desc}</span>
|
|
644
|
+
<button class="btn-tool" onclick="runTool('${t.name}')">Run</button>
|
|
558
645
|
</div>`).join('');
|
|
559
646
|
return `<section>
|
|
560
|
-
<div class="st">
|
|
561
|
-
<p style="font-size:14px;color:var(--t3);margin-bottom:16px">
|
|
647
|
+
<div class="st">CRG Tools</div>
|
|
648
|
+
<p style="font-size:14px;color:var(--t3);margin-bottom:16px">Run tools directly from here. Click Run to execute.</p>
|
|
562
649
|
<div class="tools-grid">${toolCards}</div>
|
|
650
|
+
<div id="tool-result" style="margin-top:16px"></div>
|
|
651
|
+
|
|
652
|
+
<div class="st" style="margin-top:32px">Graph Actions</div>
|
|
653
|
+
<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:16px">
|
|
654
|
+
<button class="btn" hx-post="/api/graph/update" hx-target="#graph-result" hx-swap="innerHTML">
|
|
655
|
+
↻ Rebuild Graph
|
|
656
|
+
</button>
|
|
657
|
+
<button class="btn btn-secondary" hx-get="/api/graph/stats" hx-target="#graph-stats" hx-swap="innerHTML">
|
|
658
|
+
View Stats
|
|
659
|
+
</button>
|
|
660
|
+
</div>
|
|
661
|
+
<div id="graph-result"></div>
|
|
662
|
+
<div id="graph-stats" class="result-box" style="display:none"></div>
|
|
563
663
|
</section>`;
|
|
564
664
|
}
|
|
565
665
|
|
|
@@ -685,7 +785,7 @@ function start(port, noOpen) {
|
|
|
685
785
|
|
|
686
786
|
} else if (url.pathname === '/tab/tools') {
|
|
687
787
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
688
|
-
res.end(tabTools());
|
|
788
|
+
res.end(tabTools(cwd));
|
|
689
789
|
|
|
690
790
|
} else if (url.pathname === '/tab/downloads') {
|
|
691
791
|
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
@@ -709,6 +809,60 @@ function start(port, noOpen) {
|
|
|
709
809
|
}
|
|
710
810
|
});
|
|
711
811
|
|
|
812
|
+
} else if (url.pathname === '/api/install-optimizer' && req.method === 'POST') {
|
|
813
|
+
exec('npm install -g token-optimizer-mcp', (err, stdout, stderr) => {
|
|
814
|
+
if (err) {
|
|
815
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
816
|
+
res.end(`<div class="result-box result-error"><p>Failed to install: ${esc(stderr || err.message)}</p></div>`);
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
820
|
+
res.end(`<div class="result-box result-success"><p>✓ token-optimizer-mcp installed globally</p><p style="font-size:13px;color:var(--t3);margin-top:8px">Add to your Claude Code config to activate.</p></div>`);
|
|
821
|
+
});
|
|
822
|
+
|
|
823
|
+
} else if (url.pathname === '/api/install-mem0' && req.method === 'POST') {
|
|
824
|
+
exec('pip install mem0ai 2>&1', (err, stdout, stderr) => {
|
|
825
|
+
if (err) {
|
|
826
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
827
|
+
res.end(`<div class="result-box result-error"><p>Failed to install mem0: ${esc(stderr || err.message)}</p></div>`);
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
831
|
+
res.end(`<div class="result-box result-success"><p>✓ mem0 installed</p><p style="font-size:13px;color:var(--t3);margin-top:8px">Persistent memory layer ready.</p></div>`);
|
|
832
|
+
});
|
|
833
|
+
|
|
834
|
+
} else if (url.pathname === '/api/install-fullstack' && req.method === 'POST') {
|
|
835
|
+
readBody(req, res, (data) => {
|
|
836
|
+
const targetDir = data.targetDir || cwd;
|
|
837
|
+
let output = '';
|
|
838
|
+
|
|
839
|
+
try {
|
|
840
|
+
const crgResult = actions.install(targetDir);
|
|
841
|
+
output += `<div class="check-item"><span class="check-pass">✓</span> CRG installed (${crgResult.copied} files)</div>`;
|
|
842
|
+
} catch (err) {
|
|
843
|
+
output += `<div class="check-item"><span class="check-fail">✗</span> CRG: ${esc(err.message)}</div>`;
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
exec('npm install -g token-optimizer-mcp', (err, stdout, stderr) => {
|
|
847
|
+
if (err) {
|
|
848
|
+
output += `<div class="check-item"><span class="check-fail">✗</span> token-optimizer: ${esc(stderr || err.message)}</div>`;
|
|
849
|
+
} else {
|
|
850
|
+
output += `<div class="check-item"><span class="check-pass">✓</span> token-optimizer installed</div>`;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
exec('pip install mem0ai 2>&1', (err2, stdout2, stderr2) => {
|
|
854
|
+
if (err2) {
|
|
855
|
+
output += `<div class="check-item"><span class="check-fail">✗</span> mem0: ${esc(stderr2 || err2.message)}</div>`;
|
|
856
|
+
} else {
|
|
857
|
+
output += `<div class="check-item"><span class="check-pass">✓</span> mem0 (memory layer) installed</div>`;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
861
|
+
res.end(`<div class="result-box result-success">${output}<p style="margin-top:16px;font-size:13px;color:var(--t3)">⚡ All 3 tools installed! See docs for configuration.</p></div>`);
|
|
862
|
+
});
|
|
863
|
+
});
|
|
864
|
+
});
|
|
865
|
+
|
|
712
866
|
} else if (url.pathname === '/api/uninstall' && req.method === 'POST') {
|
|
713
867
|
readBody(req, res, (data) => {
|
|
714
868
|
const targetDir = data.targetDir || cwd;
|
|
@@ -744,18 +898,43 @@ function start(port, noOpen) {
|
|
|
744
898
|
|
|
745
899
|
} else if (url.pathname === '/api/report') {
|
|
746
900
|
const report = analytics.generateReport();
|
|
747
|
-
|
|
748
|
-
res.
|
|
901
|
+
const html = mdToHtml(report);
|
|
902
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
903
|
+
res.end(`<div class="rc">${html}</div>`);
|
|
749
904
|
|
|
750
905
|
} else if (url.pathname === '/api/roi-report') {
|
|
751
906
|
const report = roi.generateROIReport(cwd);
|
|
752
|
-
|
|
753
|
-
res.
|
|
907
|
+
const html = mdToHtml(report);
|
|
908
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
909
|
+
res.end(`<div class="rc">${html}</div>`);
|
|
910
|
+
|
|
911
|
+
} else if (url.pathname === '/api/graph/update' && req.method === 'POST') {
|
|
912
|
+
exec('code-review-graph build', { cwd: cwd }, (err, stdout, stderr) => {
|
|
913
|
+
if (err) {
|
|
914
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
915
|
+
res.end(`<div class="result-box result-error"><p>Build failed: ${esc(stderr || err.message)}</p></div>`);
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
919
|
+
res.end(`<div class="result-box result-success"><p>✓ Graph updated successfully</p><p style="font-size:12px;color:var(--t3)">${esc(stdout)}</p></div>`);
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
} else if (url.pathname === '/api/graph/stats') {
|
|
923
|
+
exec('code-review-graph list_graph_stats', { cwd: cwd }, (err, stdout, stderr) => {
|
|
924
|
+
if (err) {
|
|
925
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
926
|
+
res.end(`<p style="color:var(--t3)">Graph stats unavailable</p>`);
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
930
|
+
res.end(`<pre style="font-family:var(--m);font-size:12px;background:var(--bg);padding:12px;border-radius:6px">${esc(stdout)}</pre>`);
|
|
931
|
+
});
|
|
754
932
|
|
|
755
933
|
} else if (url.pathname === '/api/daily-breakdown') {
|
|
756
934
|
const breakdown = roi.generateDailyBreakdown();
|
|
757
|
-
|
|
758
|
-
res.
|
|
935
|
+
const html = mdToHtml(breakdown);
|
|
936
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
937
|
+
res.end(`<div class="rc">${html}</div>`);
|
|
759
938
|
|
|
760
939
|
} else if (url.pathname === '/api/session' && req.method === 'POST') {
|
|
761
940
|
readBody(req, res, (data) => {
|