devsmind-mcp 2.4.0 β†’ 4.0.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.
Files changed (135) hide show
  1. package/README.md +317 -234
  2. package/dist/cli/activity.d.ts +9 -0
  3. package/dist/cli/activity.js +69 -0
  4. package/dist/cli/activity.js.map +1 -0
  5. package/dist/cli/describe.d.ts +31 -0
  6. package/dist/cli/describe.js +201 -0
  7. package/dist/cli/describe.js.map +1 -0
  8. package/dist/cli/diff.d.ts +14 -0
  9. package/dist/cli/diff.js +161 -0
  10. package/dist/cli/diff.js.map +1 -0
  11. package/dist/cli/embed.d.ts +6 -0
  12. package/dist/cli/embed.js +109 -0
  13. package/dist/cli/embed.js.map +1 -0
  14. package/dist/cli/extract-agent.d.ts +66 -0
  15. package/dist/cli/extract-agent.js +192 -0
  16. package/dist/cli/extract-agent.js.map +1 -0
  17. package/dist/cli/feedback.d.ts +11 -0
  18. package/dist/cli/feedback.js +90 -0
  19. package/dist/cli/feedback.js.map +1 -0
  20. package/dist/cli/index.js +139 -9
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/cli/init.d.ts +30 -0
  23. package/dist/cli/init.js +89 -18
  24. package/dist/cli/init.js.map +1 -1
  25. package/dist/cli/integrations/memory-topics.d.ts +55 -0
  26. package/dist/cli/integrations/memory-topics.js +318 -0
  27. package/dist/cli/integrations/memory-topics.js.map +1 -0
  28. package/dist/cli/integrations/memory.d.ts +17 -6
  29. package/dist/cli/integrations/memory.js +52 -139
  30. package/dist/cli/integrations/memory.js.map +1 -1
  31. package/dist/cli/integrations/prompt.d.ts +8 -0
  32. package/dist/cli/integrations/prompt.js +24 -3
  33. package/dist/cli/integrations/prompt.js.map +1 -1
  34. package/dist/cli/integrations/registry.d.ts +26 -9
  35. package/dist/cli/integrations/registry.js +61 -30
  36. package/dist/cli/integrations/registry.js.map +1 -1
  37. package/dist/cli/llm-client.d.ts +116 -0
  38. package/dist/cli/llm-client.js +322 -0
  39. package/dist/cli/llm-client.js.map +1 -0
  40. package/dist/cli/rule.d.ts +22 -2
  41. package/dist/cli/rule.js +110 -34
  42. package/dist/cli/rule.js.map +1 -1
  43. package/dist/cli/runner.d.ts +21 -0
  44. package/dist/cli/runner.js +94 -276
  45. package/dist/cli/runner.js.map +1 -1
  46. package/dist/cli/sync-progress.d.ts +9 -0
  47. package/dist/cli/sync-progress.js +41 -0
  48. package/dist/cli/sync-progress.js.map +1 -0
  49. package/dist/cli/sync.js +5 -2
  50. package/dist/cli/sync.js.map +1 -1
  51. package/dist/cli/view.js +3 -2
  52. package/dist/cli/view.js.map +1 -1
  53. package/dist/cli/workflow.js +26 -20
  54. package/dist/cli/workflow.js.map +1 -1
  55. package/dist/db/activity-graph.d.ts +55 -0
  56. package/dist/db/activity-graph.js +314 -0
  57. package/dist/db/activity-graph.js.map +1 -0
  58. package/dist/db/activity.d.ts +221 -0
  59. package/dist/db/activity.js +348 -0
  60. package/dist/db/activity.js.map +1 -0
  61. package/dist/db/analyze.js +18 -6
  62. package/dist/db/analyze.js.map +1 -1
  63. package/dist/db/database.d.ts +654 -102
  64. package/dist/db/database.js +1911 -558
  65. package/dist/db/database.js.map +1 -1
  66. package/dist/db/edges.d.ts +24 -0
  67. package/dist/db/edges.js +84 -0
  68. package/dist/db/edges.js.map +1 -1
  69. package/dist/db/embedder.d.ts +39 -0
  70. package/dist/db/embedder.js +0 -0
  71. package/dist/db/embedder.js.map +1 -0
  72. package/dist/db/feedback.d.ts +128 -0
  73. package/dist/db/feedback.js +182 -0
  74. package/dist/db/feedback.js.map +1 -0
  75. package/dist/db/file-diff.d.ts +32 -0
  76. package/dist/db/file-diff.js +110 -0
  77. package/dist/db/file-diff.js.map +1 -0
  78. package/dist/db/grep.d.ts +78 -0
  79. package/dist/db/grep.js +475 -0
  80. package/dist/db/grep.js.map +1 -0
  81. package/dist/db/index-build.d.ts +75 -0
  82. package/dist/db/index-build.js +177 -0
  83. package/dist/db/index-build.js.map +1 -0
  84. package/dist/db/message-revert.d.ts +63 -0
  85. package/dist/db/message-revert.js +258 -0
  86. package/dist/db/message-revert.js.map +1 -0
  87. package/dist/db/revert.d.ts +31 -0
  88. package/dist/db/revert.js +108 -0
  89. package/dist/db/revert.js.map +1 -0
  90. package/dist/db/schema.d.ts +49 -4
  91. package/dist/db/schema.js +125 -73
  92. package/dist/db/schema.js.map +1 -1
  93. package/dist/db/search-index.d.ts +65 -0
  94. package/dist/db/search-index.js +74 -0
  95. package/dist/db/search-index.js.map +1 -0
  96. package/dist/db/staging.d.ts +91 -5
  97. package/dist/db/staging.js +148 -22
  98. package/dist/db/staging.js.map +1 -1
  99. package/dist/mcp/server.d.ts +29 -7
  100. package/dist/mcp/server.js +2637 -878
  101. package/dist/mcp/server.js.map +1 -1
  102. package/dist/mcp/vendor/3d-force-graph.min.js +5 -0
  103. package/dist/mcp/vendor/force-graph.min.js +5 -0
  104. package/dist/mcp/vendor/model/model_int8.onnx +0 -0
  105. package/dist/mcp/vendor/model/vocab.txt +30522 -0
  106. package/dist/mcp/vendor/three.min.js +7 -0
  107. package/dist/mcp/view.css +419 -0
  108. package/dist/mcp/view.html +161 -0
  109. package/dist/mcp/view.js +245 -0
  110. package/dist/mcp/view_chat.js +382 -0
  111. package/dist/mcp/view_graph.js +576 -0
  112. package/dist/mcp/visualizer.d.ts +25 -2
  113. package/dist/mcp/visualizer.js +31 -4
  114. package/dist/mcp/visualizer.js.map +1 -1
  115. package/dist/utils/ast.d.ts +89 -0
  116. package/dist/utils/ast.js +378 -10
  117. package/dist/utils/ast.js.map +1 -1
  118. package/dist/utils/diff.d.ts +44 -0
  119. package/dist/utils/diff.js +78 -0
  120. package/dist/utils/diff.js.map +1 -0
  121. package/dist/utils/edit.d.ts +6 -0
  122. package/dist/utils/edit.js +47 -14
  123. package/dist/utils/edit.js.map +1 -1
  124. package/dist/utils/scanner.d.ts +6 -4
  125. package/dist/utils/scanner.js +18 -8
  126. package/dist/utils/scanner.js.map +1 -1
  127. package/dist/utils/tokenize.d.ts +45 -0
  128. package/dist/utils/tokenize.js +129 -0
  129. package/dist/utils/tokenize.js.map +1 -0
  130. package/dist/utils/version.d.ts +14 -0
  131. package/dist/utils/version.js +61 -0
  132. package/dist/utils/version.js.map +1 -0
  133. package/package.json +18 -5
  134. package/dist/mcp/visualizer_2d.html +0 -635
  135. package/dist/mcp/visualizer_3d.html +0 -613
@@ -0,0 +1,419 @@
1
+ /* DevsMind view β€” hand-written, no CDN, no build step. Dark theme only (matches the old pages). */
2
+
3
+ :root {
4
+ --bg: #0b0f19;
5
+ --panel: #111827;
6
+ --panel-2: #161e2e;
7
+ --border: #1f2937;
8
+ --text: #e2e8f0;
9
+ --text-dim: #94a3b8;
10
+ --text-faint: #64748b;
11
+ --accent: #38bdf8;
12
+ --accent-dim: #0ea5e9;
13
+ --green: #34d399;
14
+ --green-bg: rgba(52, 211, 153, 0.12);
15
+ --red: #f87171;
16
+ --red-bg: rgba(248, 113, 113, 0.12);
17
+ --purple: #a78bfa;
18
+ --radius: 8px;
19
+ }
20
+
21
+ * { box-sizing: border-box; }
22
+
23
+ body {
24
+ margin: 0;
25
+ background: var(--bg);
26
+ color: var(--text);
27
+ font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
28
+ font-size: 14px;
29
+ height: 100vh;
30
+ overflow: hidden;
31
+ display: flex;
32
+ flex-direction: column;
33
+ }
34
+
35
+ code, .mono { font-family: "Consolas", "Menlo", "Courier New", monospace; }
36
+
37
+ button {
38
+ font-family: inherit;
39
+ cursor: pointer;
40
+ }
41
+
42
+ ::-webkit-scrollbar { width: 10px; height: 10px; }
43
+ ::-webkit-scrollbar-track { background: transparent; }
44
+ ::-webkit-scrollbar-thumb { background: #2a3548; border-radius: 6px; }
45
+ ::-webkit-scrollbar-thumb:hover { background: #37455c; }
46
+
47
+ /* ── Topbar ─────────────────────────────────────────────────────── */
48
+
49
+ .topbar {
50
+ display: flex;
51
+ align-items: center;
52
+ gap: 20px;
53
+ padding: 10px 16px;
54
+ background: var(--panel);
55
+ border-bottom: 1px solid var(--border);
56
+ flex-shrink: 0;
57
+ }
58
+ .brand { display: flex; align-items: center; gap: 8px; }
59
+ .brand-mark { color: var(--accent); font-size: 18px; }
60
+ .brand-name { font-weight: 600; letter-spacing: 0.02em; }
61
+ .brand-sub { color: var(--text-faint); font-size: 12px; }
62
+
63
+ .tabs { display: flex; gap: 4px; }
64
+ .tab {
65
+ background: transparent;
66
+ border: 1px solid transparent;
67
+ color: var(--text-dim);
68
+ padding: 6px 14px;
69
+ border-radius: var(--radius);
70
+ font-size: 13px;
71
+ }
72
+ .tab:hover { color: var(--text); background: var(--panel-2); }
73
+ .tab.active { color: var(--bg); background: var(--accent); font-weight: 600; }
74
+
75
+ .topbar-actions { margin-left: auto; display: flex; gap: 8px; }
76
+ .btn-icon {
77
+ background: var(--panel-2);
78
+ border: 1px solid var(--border);
79
+ color: var(--text-dim);
80
+ border-radius: var(--radius);
81
+ padding: 6px 10px;
82
+ font-size: 14px;
83
+ }
84
+ .btn-icon:hover { color: var(--text); border-color: var(--accent-dim); }
85
+ .btn-icon.small { padding: 4px 8px; font-size: 12px; }
86
+
87
+ .btn {
88
+ background: var(--panel-2);
89
+ border: 1px solid var(--border);
90
+ color: var(--text);
91
+ border-radius: var(--radius);
92
+ padding: 6px 12px;
93
+ font-size: 13px;
94
+ }
95
+ .btn:hover { border-color: var(--accent-dim); color: var(--accent); }
96
+ .btn.primary { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
97
+ .btn.danger:hover { border-color: var(--red); color: var(--red); }
98
+ .btn.small { padding: 3px 9px; font-size: 11px; }
99
+
100
+ /* ── Layout ─────────────────────────────────────────────────────── */
101
+
102
+ #app { flex: 1; min-height: 0; position: relative; }
103
+ .section { display: flex; height: 100%; }
104
+ .section.hidden { display: none; }
105
+ .hidden { display: none !important; }
106
+
107
+ .sidebar {
108
+ width: 300px;
109
+ flex-shrink: 0;
110
+ background: var(--panel);
111
+ border-right: 1px solid var(--border);
112
+ display: flex;
113
+ flex-direction: column;
114
+ overflow: hidden;
115
+ position: relative;
116
+ }
117
+ .sidebar-head {
118
+ display: flex;
119
+ align-items: center;
120
+ justify-content: space-between;
121
+ padding: 12px 14px;
122
+ font-size: 12px;
123
+ text-transform: uppercase;
124
+ letter-spacing: 0.06em;
125
+ color: var(--text-faint);
126
+ border-bottom: 1px solid var(--border);
127
+ }
128
+
129
+ .search-input {
130
+ margin: 8px 12px 0;
131
+ padding: 6px 10px;
132
+ background: var(--panel-2);
133
+ border: 1px solid var(--border);
134
+ border-radius: var(--radius);
135
+ color: var(--text);
136
+ font-size: 13px;
137
+ }
138
+ .search-input:focus { outline: none; border-color: var(--accent-dim); }
139
+
140
+ .main-pane {
141
+ flex: 1;
142
+ min-width: 0;
143
+ display: flex;
144
+ flex-direction: column;
145
+ overflow: hidden;
146
+ position: relative;
147
+ }
148
+
149
+ .empty-hint { padding: 16px; color: var(--text-faint); font-size: 13px; }
150
+ .empty-state, .graph-empty {
151
+ flex: 1;
152
+ display: flex;
153
+ align-items: center;
154
+ justify-content: center;
155
+ color: var(--text-faint);
156
+ text-align: center;
157
+ padding: 40px;
158
+ }
159
+ .empty-state p, .graph-empty p { max-width: 420px; line-height: 1.6; }
160
+
161
+ /* ── Floating filter panel ─────────────────────────────────────── */
162
+
163
+ .filter-panel {
164
+ position: absolute;
165
+ top: 46px;
166
+ left: 12px;
167
+ right: 12px;
168
+ z-index: 20;
169
+ background: var(--panel-2);
170
+ border: 1px solid var(--border);
171
+ border-radius: var(--radius);
172
+ padding: 12px;
173
+ box-shadow: 0 8px 24px rgba(0,0,0,0.4);
174
+ }
175
+ .filter-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; }
176
+ .filter-row select {
177
+ background: var(--panel);
178
+ color: var(--text);
179
+ border: 1px solid var(--border);
180
+ border-radius: 6px;
181
+ padding: 4px 8px;
182
+ }
183
+ .filter-group { margin-bottom: 10px; }
184
+ .filter-group:last-child { margin-bottom: 0; }
185
+ .filter-group-title { font-size: 11px; text-transform: uppercase; color: var(--text-faint); margin-bottom: 6px; letter-spacing: 0.05em; }
186
+ .filter-group-title-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
187
+ .filter-group-title-row .filter-group-title { margin-bottom: 0; }
188
+ .filter-group-actions { display: flex; gap: 8px; }
189
+ .link-btn {
190
+ background: transparent; border: none; color: var(--accent); font-size: 11px;
191
+ padding: 0; text-decoration: underline; text-underline-offset: 2px;
192
+ }
193
+ .link-btn:hover { color: var(--accent-dim); }
194
+ .filter-checks { display: flex; flex-wrap: wrap; gap: 6px; max-height: 140px; overflow-y: auto; }
195
+ .filter-checks label {
196
+ display: flex; align-items: center; gap: 5px;
197
+ background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
198
+ padding: 3px 9px; font-size: 12px; color: var(--text-dim);
199
+ }
200
+ .filter-checks input { accent-color: var(--accent); }
201
+
202
+ .date-range-row { display: flex; align-items: center; gap: 6px; }
203
+ .date-range-row input[type="date"] {
204
+ flex: 1; min-width: 0;
205
+ background: var(--panel); color: var(--text); border: 1px solid var(--border);
206
+ border-radius: 6px; padding: 5px 6px; font-size: 12px; color-scheme: dark;
207
+ }
208
+ .date-range-row span { color: var(--text-faint); font-size: 11px; }
209
+ .filter-quick-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
210
+ .chip-btn {
211
+ background: var(--panel); border: 1px solid var(--border); color: var(--text-dim);
212
+ border-radius: 12px; padding: 3px 10px; font-size: 11px;
213
+ }
214
+ .chip-btn:hover { border-color: var(--accent-dim); color: var(--accent); }
215
+ .chip-btn.active { background: rgba(56,189,248,0.15); border-color: var(--accent-dim); color: var(--accent); }
216
+
217
+ /* ── Chat: session list ─────────────────────────────────────────── */
218
+
219
+ .session-list { flex: 1; overflow-y: auto; padding: 6px; }
220
+ .session-item {
221
+ padding: 10px 10px;
222
+ border-radius: var(--radius);
223
+ cursor: pointer;
224
+ margin-bottom: 2px;
225
+ border: 1px solid transparent;
226
+ }
227
+ .session-item:hover { background: var(--panel-2); }
228
+ .session-item.active { background: var(--panel-2); border-color: var(--accent-dim); }
229
+ .session-item-label { font-size: 13px; color: var(--text); margin-bottom: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
230
+ .session-item-meta { font-size: 11px; color: var(--text-faint); }
231
+
232
+ /* ── Chat: transcript ───────────────────────────────────────────── */
233
+
234
+ .transcript { flex: 1; overflow-y: auto; padding: 20px 24px; max-width: 900px; margin: 0 auto; width: 100%; }
235
+ .msg-pair { margin-bottom: 22px; }
236
+ .msg-pair.reverted { opacity: 0.5; }
237
+ .msg-pair.partial { opacity: 0.8; }
238
+ .bubble { max-width: 78%; padding: 10px 14px; border-radius: 14px; font-size: 13.5px; line-height: 1.55; }
239
+ .bubble-user { background: var(--panel-2); border: 1px solid var(--border); margin-left: auto; border-bottom-right-radius: 4px; }
240
+ .bubble-ai { background: rgba(56, 189, 248, 0.08); border: 1px solid rgba(56, 189, 248, 0.25); margin-right: auto; margin-top: 8px; border-bottom-left-radius: 4px; cursor: pointer; }
241
+ .bubble-meta { font-size: 11px; color: var(--text-faint); margin-top: 4px; display: flex; gap: 10px; align-items: center; }
242
+ .bubble-user + .bubble-meta { text-align: right; }
243
+ .msg-actions { display: flex; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
244
+ .msg-actions .btn { font-size: 11px; padding: 3px 9px; }
245
+
246
+ .file-diff-block { margin-top: 12px; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
247
+ .file-diff-head {
248
+ display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap;
249
+ padding: 6px 10px; background: var(--panel-2); font-size: 12px; color: var(--text-dim);
250
+ }
251
+ .file-diff-head .path { font-family: monospace; }
252
+ .file-diff-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
253
+ .file-diff-meta { color: var(--text-faint); font-size: 11px; margin-right: auto; }
254
+ .drift-note { font-size: 11px; color: #fbbf24; padding: 6px 10px; background: rgba(251,191,36,0.08); }
255
+
256
+ .file-collapse-toggle { cursor: pointer; user-select: none; }
257
+ .file-collapse-toggle:hover { background: #1b2436; }
258
+ .collapse-chevron { display: inline-block; color: var(--text-faint); transition: transform 0.12s ease; flex: 0 0 auto; }
259
+ .file-collapse-toggle.expanded .collapse-chevron { transform: rotate(90deg); }
260
+ .file-diff-body { border-top: 1px solid var(--border); }
261
+
262
+ .single-edits-list { border-top: 1px solid var(--border); }
263
+ .single-edit-row { padding: 8px 10px; border-bottom: 1px solid var(--border); }
264
+ .single-edit-row:last-child { border-bottom: none; }
265
+ .single-edit-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 11px; margin-bottom: 4px; }
266
+ .single-edit-meta .mono { color: var(--text-dim); }
267
+
268
+ .diff-lines { font-family: "Consolas", "Menlo", monospace; font-size: 12px; line-height: 1.5; overflow-x: auto; }
269
+ .diff-line { display: flex; white-space: pre; }
270
+ .diff-line.add { background: var(--green-bg); color: var(--green); }
271
+ .diff-line.del { background: var(--red-bg); color: var(--red); }
272
+ .diff-line.ctx { color: var(--text-dim); }
273
+ .line-no {
274
+ flex: 0 0 38px; text-align: right; padding-right: 6px; user-select: none;
275
+ color: var(--text-faint); opacity: 0.7; border-right: 1px solid transparent;
276
+ }
277
+ .line-no.new { border-right: 1px solid var(--border); padding-right: 6px; margin-right: 6px; }
278
+ .diff-line.add .line-no, .diff-line.del .line-no, .diff-line.ctx .line-no { color: var(--text-faint); }
279
+ .line-marker { flex: 0 0 12px; text-align: center; font-weight: 700; }
280
+ .line-text { flex: 1; }
281
+
282
+ /* ── Diff block: shared toggle + side-by-side layout ─────────────── */
283
+
284
+ .diff-sxs { font-family: "Consolas", "Menlo", monospace; font-size: 12px; line-height: 1.5; overflow-x: auto; }
285
+ .diff-sxs-row { display: flex; }
286
+ .diff-sxs-cell { flex: 1 1 50%; min-width: 0; display: flex; white-space: pre; border-right: 1px solid var(--border); }
287
+ .diff-sxs-cell:last-child { border-right: none; }
288
+ .diff-sxs-cell.add { background: var(--green-bg); color: var(--green); }
289
+ .diff-sxs-cell.del { background: var(--red-bg); color: var(--red); }
290
+ .diff-sxs-cell.ctx { color: var(--text-dim); }
291
+ .diff-sxs-cell.blank { background: rgba(255,255,255,0.03); }
292
+ .diff-sxs-cell .line-no { flex: 0 0 38px; opacity: 0.7; }
293
+ .diff-sxs-cell .line-text { flex: 1; }
294
+
295
+ .combined-file-diff { border-top: 1px solid var(--border); }
296
+
297
+ /* ── Graph: accordion sidebar ───────────────────────────────────── */
298
+
299
+ .accordion { flex: 1; overflow-y: auto; padding: 6px 4px 20px; }
300
+ .repo-group summary, .type-group summary {
301
+ cursor: pointer;
302
+ list-style: none;
303
+ padding: 8px 10px;
304
+ font-size: 13px;
305
+ display: flex;
306
+ align-items: center;
307
+ gap: 6px;
308
+ }
309
+ .repo-group summary::-webkit-details-marker,
310
+ .type-group summary::-webkit-details-marker { display: none; }
311
+ .repo-group > summary { font-weight: 600; color: var(--text); }
312
+ .repo-group > summary .count { color: var(--text-faint); font-weight: 400; margin-left: auto; font-size: 11px; }
313
+ .type-group { margin-left: 10px; border-left: 1px solid var(--border); }
314
+ .type-group > summary { color: var(--accent); font-size: 12px; padding-left: 12px; }
315
+ .type-group > summary .count { color: var(--text-faint); margin-left: auto; font-size: 11px; }
316
+ .node-item {
317
+ padding: 5px 10px 5px 26px;
318
+ font-size: 12.5px;
319
+ color: var(--text-dim);
320
+ cursor: pointer;
321
+ border-radius: 4px;
322
+ overflow: hidden;
323
+ text-overflow: ellipsis;
324
+ white-space: nowrap;
325
+ }
326
+ .node-item:hover { background: var(--panel-2); color: var(--text); }
327
+ .node-item.selected { background: rgba(56,189,248,0.12); color: var(--accent); }
328
+ .node-item.filtered-out { display: none; }
329
+ .type-group.filtered-out, .repo-group.filtered-out { display: none; }
330
+
331
+ /* ── Graph: main pane ───────────────────────────────────────────── */
332
+
333
+ .graph-toolbar {
334
+ display: flex;
335
+ align-items: center;
336
+ gap: 10px;
337
+ padding: 8px 14px;
338
+ border-bottom: 1px solid var(--border);
339
+ }
340
+ .toolbar-spacer { flex: 1; }
341
+ .stat-pill { font-size: 12px; color: var(--text-faint); }
342
+
343
+ .ego-legend {
344
+ display: flex; gap: 16px; padding: 8px 14px;
345
+ font-size: 12px; color: var(--text-dim); border-bottom: 1px solid var(--border);
346
+ }
347
+ .legend-item { display: flex; align-items: center; gap: 6px; }
348
+ .dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
349
+ .dot-center { background: #f43f5e; }
350
+ .dot-uses { background: #38bdf8; }
351
+ .dot-usedby { background: #a78bfa; }
352
+
353
+ .graph-canvas { flex: 1; position: relative; }
354
+
355
+ /* ── Graph: details pane ────────────────────────────────────────── */
356
+
357
+ .details-pane {
358
+ width: 360px;
359
+ flex-shrink: 0;
360
+ background: var(--panel);
361
+ border-left: 1px solid var(--border);
362
+ overflow-y: auto;
363
+ padding: 14px;
364
+ position: relative;
365
+ }
366
+ .close-details { position: absolute; top: 10px; right: 10px; }
367
+ .detail-type-badge {
368
+ display: inline-block; padding: 2px 8px; border-radius: 10px;
369
+ font-size: 11px; font-weight: 600; margin-bottom: 8px;
370
+ }
371
+ .detail-name { font-size: 16px; font-weight: 600; margin-bottom: 2px; }
372
+ .detail-id { font-family: monospace; font-size: 11px; color: var(--text-faint); word-break: break-all; margin-bottom: 10px; }
373
+ .detail-field { margin-bottom: 10px; }
374
+ .detail-field-label { font-size: 11px; text-transform: uppercase; color: var(--text-faint); letter-spacing: 0.05em; margin-bottom: 4px; }
375
+ .detail-field-value { font-size: 12.5px; color: var(--text-dim); font-family: monospace; word-break: break-all; }
376
+ .conn-link {
377
+ display: block; width: 100%; text-align: left;
378
+ background: var(--panel-2); border: 1px solid var(--border); color: var(--text-dim);
379
+ padding: 5px 8px; margin-bottom: 4px; border-radius: 6px; font-size: 12px;
380
+ }
381
+ .conn-link:hover { border-color: var(--accent-dim); color: var(--accent); }
382
+ .history-entry { border-top: 1px solid var(--border); padding-top: 10px; margin-top: 10px; font-size: 12px; }
383
+ .history-entry .when { color: var(--text-faint); }
384
+ .history-entry .dev-badge { color: var(--purple); }
385
+
386
+ /* ── Whole-graph overlay ─────────────────────────────────────────── */
387
+
388
+ .whole-graph-overlay {
389
+ position: fixed; inset: 0; z-index: 50;
390
+ background: var(--bg);
391
+ display: flex; flex-direction: column;
392
+ }
393
+ .whole-graph-toolbar {
394
+ display: flex; align-items: center; justify-content: space-between;
395
+ padding: 10px 16px; border-bottom: 1px solid var(--border);
396
+ font-size: 13px; color: var(--text-dim);
397
+ }
398
+ #whole-graph-canvas { flex: 1; position: relative; }
399
+
400
+ /* ── Full-file view: half-page side panel ────────────────────────── */
401
+
402
+ .full-file-backdrop {
403
+ position: fixed; inset: 0; z-index: 69;
404
+ background: rgba(0,0,0,0.35);
405
+ }
406
+ .full-file-panel {
407
+ position: fixed; top: 0; right: 0; bottom: 0; z-index: 70;
408
+ width: 50vw; min-width: 420px;
409
+ background: var(--panel); border-left: 1px solid var(--border);
410
+ box-shadow: -12px 0 32px rgba(0,0,0,0.45);
411
+ display: flex; flex-direction: column;
412
+ }
413
+ .full-file-header {
414
+ display: flex; align-items: center; justify-content: space-between;
415
+ padding: 12px 16px; border-bottom: 1px solid var(--border);
416
+ flex-shrink: 0;
417
+ }
418
+ .full-file-header .path { font-family: monospace; font-size: 12.5px; color: var(--text-dim); word-break: break-all; }
419
+ .full-file-body { flex: 1; overflow-y: auto; }
@@ -0,0 +1,161 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>DevsMind β€” View</title>
7
+ <!--DEVSMIND_TOKEN-->
8
+ <link rel="stylesheet" href="/app/view.css">
9
+ </head>
10
+ <body>
11
+ <header class="topbar">
12
+ <div class="brand">
13
+ <span class="brand-mark">β—†</span>
14
+ <span class="brand-name">DevsMind</span>
15
+ <span class="brand-sub" id="project-name-label"></span>
16
+ </div>
17
+ <nav class="tabs" role="tablist">
18
+ <button class="tab active" id="tab-chat" role="tab" aria-selected="true">πŸ’¬ Chat</button>
19
+ <button class="tab" id="tab-graph" role="tab" aria-selected="false">πŸ•ΈοΈ Graph</button>
20
+ </nav>
21
+ <div class="topbar-actions">
22
+ <button class="btn-icon" id="btn-diff-mode" title="Switch every diff on the page between unified and side-by-side">⇄ Side by side</button>
23
+ <button class="btn-icon" id="btn-reload" title="Reload">πŸ”„</button>
24
+ </div>
25
+ </header>
26
+
27
+ <main id="app">
28
+ <!-- ───────────────────────── Chat section ───────────────────────── -->
29
+ <section id="section-chat" class="section">
30
+ <aside class="sidebar" id="chat-sidebar">
31
+ <div class="sidebar-head">
32
+ <span>Sessions</span>
33
+ <button class="btn-icon small" id="chat-filter-toggle" title="Filter by date">☰</button>
34
+ </div>
35
+ <div class="filter-panel hidden" id="chat-filter-panel">
36
+ <div class="filter-group">
37
+ <div class="filter-group-title">Date range</div>
38
+ <div class="date-range-row">
39
+ <input type="date" id="chat-date-from">
40
+ <span>to</span>
41
+ <input type="date" id="chat-date-to">
42
+ </div>
43
+ <div class="filter-quick-row">
44
+ <button class="chip-btn" data-chat-quick="today">Today</button>
45
+ <button class="chip-btn" data-chat-quick="7d">7 days</button>
46
+ <button class="chip-btn" data-chat-quick="30d">30 days</button>
47
+ <button class="chip-btn" data-chat-quick="clear">All time</button>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ <div class="session-list" id="session-list">
52
+ <div class="empty-hint">Loading…</div>
53
+ </div>
54
+ </aside>
55
+ <div class="main-pane" id="chat-main">
56
+ <div class="empty-state" id="chat-empty">
57
+ <p>Select a session to see its history β€” every <code>commit_changes</code> call as a message, with the diff of what changed.</p>
58
+ </div>
59
+ <div class="transcript hidden" id="transcript"></div>
60
+ </div>
61
+ </section>
62
+
63
+ <!-- ───────────────────────── Graph section ───────────────────────── -->
64
+ <section id="section-graph" class="section hidden">
65
+ <aside class="sidebar" id="graph-sidebar">
66
+ <div class="sidebar-head">
67
+ <span>Nodes</span>
68
+ <button class="btn-icon small" id="graph-filter-toggle" title="Filter by type / developer / date">☰</button>
69
+ </div>
70
+ <input type="text" id="node-search" class="search-input" placeholder="Search nodes…">
71
+ <div class="filter-panel hidden" id="graph-filter-panel">
72
+ <div class="filter-group">
73
+ <div class="filter-group-title-row">
74
+ <span class="filter-group-title">Type</span>
75
+ <span class="filter-group-actions">
76
+ <button class="link-btn" data-select-all="type-filters">All</button>
77
+ <button class="link-btn" data-select-none="type-filters">None</button>
78
+ </span>
79
+ </div>
80
+ <div id="type-filters" class="filter-checks"></div>
81
+ </div>
82
+ <div class="filter-group">
83
+ <div class="filter-group-title-row">
84
+ <span class="filter-group-title">Developer</span>
85
+ <span class="filter-group-actions">
86
+ <button class="link-btn" data-select-all="dev-filters">All</button>
87
+ <button class="link-btn" data-select-none="dev-filters">None</button>
88
+ </span>
89
+ </div>
90
+ <div id="dev-filters" class="filter-checks"></div>
91
+ </div>
92
+ <div class="filter-group">
93
+ <div class="filter-group-title">Date range</div>
94
+ <div class="date-range-row">
95
+ <input type="date" id="graph-date-from">
96
+ <span>to</span>
97
+ <input type="date" id="graph-date-to">
98
+ </div>
99
+ <div class="filter-quick-row">
100
+ <button class="chip-btn" data-graph-quick="1d">Last day</button>
101
+ <button class="chip-btn" data-graph-quick="7d">7 days</button>
102
+ <button class="chip-btn" data-graph-quick="30d">30 days</button>
103
+ <button class="chip-btn" data-graph-quick="clear">All time</button>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ <div class="accordion" id="node-accordion">
108
+ <div class="empty-hint">Loading…</div>
109
+ </div>
110
+ </aside>
111
+ <div class="main-pane" id="graph-main">
112
+ <div class="graph-toolbar">
113
+ <div class="stat-pill" id="graph-stats">β€” nodes</div>
114
+ <div class="toolbar-spacer"></div>
115
+ <button class="btn" id="btn-toggle-3d">🌌 3D</button>
116
+ <button class="btn" id="btn-whole-graph">πŸ—ΊοΈ See whole graph (2D)</button>
117
+ </div>
118
+ <div class="graph-empty" id="graph-empty">
119
+ <p>Click a node in the sidebar to see it, and only what it connects to β€” not the whole graph.</p>
120
+ </div>
121
+ <div class="ego-legend hidden" id="ego-legend">
122
+ <span class="legend-item"><span class="dot dot-center"></span> Selected</span>
123
+ <span class="legend-item"><span class="dot dot-uses"></span> Uses (calls out β†’)</span>
124
+ <span class="legend-item"><span class="dot dot-usedby"></span> Used by (← called by)</span>
125
+ </div>
126
+ <div class="graph-canvas hidden" id="graph-canvas"></div>
127
+ </div>
128
+ <aside class="details-pane hidden" id="details-pane">
129
+ <button class="btn-icon close-details" id="details-close">βœ•</button>
130
+ <div id="details-content"></div>
131
+ </aside>
132
+ </section>
133
+ </main>
134
+
135
+ <div class="whole-graph-overlay hidden" id="whole-graph-overlay">
136
+ <div class="whole-graph-toolbar">
137
+ <span>Whole graph (2D) β€” filtered set</span>
138
+ <button class="btn" id="btn-close-whole-graph">βœ• Close</button>
139
+ </div>
140
+ <div class="graph-canvas" id="whole-graph-canvas"></div>
141
+ </div>
142
+
143
+ <!-- Full-file view: a half-page side panel, not an inline swap β€” "changes only" stays the
144
+ default inline view; this is where the complete reconstructed file lives when asked for. -->
145
+ <div class="full-file-backdrop hidden" id="full-file-backdrop"></div>
146
+ <div class="full-file-panel hidden" id="full-file-panel">
147
+ <div class="full-file-header">
148
+ <span class="path" id="full-file-path"></span>
149
+ <button class="btn-icon" id="full-file-close" title="Close">βœ•</button>
150
+ </div>
151
+ <div class="full-file-body" id="full-file-body"></div>
152
+ </div>
153
+
154
+ <script src="/vendor/three.min.js"></script>
155
+ <script src="/vendor/force-graph.min.js"></script>
156
+ <script src="/vendor/3d-force-graph.min.js"></script>
157
+ <script src="/app/view.js"></script>
158
+ <script src="/app/view_chat.js"></script>
159
+ <script src="/app/view_graph.js"></script>
160
+ </body>
161
+ </html>