clawvault 1.11.2 → 2.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.
- package/README.md +135 -1
- package/bin/clawvault.js +51 -1252
- package/bin/command-registration.test.js +148 -0
- package/bin/command-runtime.js +42 -0
- package/bin/command-runtime.test.js +102 -0
- package/bin/help-contract.test.js +23 -0
- package/bin/register-core-commands.js +139 -0
- package/bin/register-maintenance-commands.js +137 -0
- package/bin/register-query-commands.js +225 -0
- package/bin/register-resilience-commands.js +147 -0
- package/bin/register-session-lifecycle-commands.js +204 -0
- package/bin/register-template-commands.js +72 -0
- package/bin/register-vault-operations-commands.js +295 -0
- package/bin/test-helpers/cli-command-fixtures.js +94 -0
- package/dashboard/lib/graph-diff.js +3 -1
- package/dashboard/lib/graph-diff.test.js +19 -0
- package/dashboard/lib/vault-parser.js +330 -26
- package/dashboard/lib/vault-parser.test.js +191 -11
- package/dashboard/public/app.js +22 -9
- package/dist/chunk-MXSSG3QU.js +42 -0
- package/dist/chunk-O5V7SD5C.js +398 -0
- package/dist/chunk-PAYUH64O.js +284 -0
- package/dist/{chunk-3HFB7EMU.js → chunk-QFBKWDYR.js} +12 -0
- package/dist/{chunk-UBRYOIII.js → chunk-TBVI4N53.js} +210 -21
- package/dist/chunk-TXO34J3O.js +56 -0
- package/dist/commands/compat.d.ts +28 -0
- package/dist/commands/compat.js +10 -0
- package/dist/commands/context.d.ts +2 -33
- package/dist/commands/context.js +3 -2
- package/dist/commands/doctor.js +61 -3
- package/dist/commands/entities.d.ts +1 -0
- package/dist/commands/entities.js +4 -4
- package/dist/commands/graph.d.ts +21 -0
- package/dist/commands/graph.js +10 -0
- package/dist/commands/link.d.ts +1 -0
- package/dist/commands/link.js +14 -5
- package/dist/commands/sleep.js +7 -6
- package/dist/commands/status.d.ts +6 -0
- package/dist/commands/status.js +63 -3
- package/dist/commands/wake.js +5 -4
- package/dist/context-COo8oq1k.d.ts +45 -0
- package/dist/index.d.ts +63 -2
- package/dist/index.js +53 -15
- package/dist/lib/config.d.ts +6 -1
- package/dist/lib/config.js +7 -3
- package/hooks/clawvault/HOOK.md +6 -1
- package/hooks/clawvault/handler.js +44 -3
- package/hooks/clawvault/handler.test.js +161 -0
- package/package.json +34 -2
- package/dashboard/public/graph.js +0 -376
- package/dashboard/public/style.css +0 -154
- package/dist/chunk-4KDZZW4X.js +0 -13
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
const CATEGORY_COLORS = {
|
|
2
|
-
decisions: '#f26430',
|
|
3
|
-
lessons: '#4ecdc4',
|
|
4
|
-
people: '#ff6b6b',
|
|
5
|
-
projects: '#95e1d3',
|
|
6
|
-
commitments: '#f9d56e',
|
|
7
|
-
research: '#a8e6cf',
|
|
8
|
-
inbox: '#888888',
|
|
9
|
-
root: '#666666',
|
|
10
|
-
default: '#aaaaaa'
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const HIGHLIGHT_NODE_COLOR = '#ffffff';
|
|
14
|
-
const HIGHLIGHT_LINK_COLOR = '#f3f4f6';
|
|
15
|
-
const DIMMED_NODE_COLOR = '#324055';
|
|
16
|
-
const DIMMED_LINK_COLOR = 'rgba(130, 145, 170, 0.2)';
|
|
17
|
-
|
|
18
|
-
const state = {
|
|
19
|
-
searchTerm: '',
|
|
20
|
-
category: 'all',
|
|
21
|
-
nodes: [],
|
|
22
|
-
links: [],
|
|
23
|
-
stats: null,
|
|
24
|
-
nodeById: new Map(),
|
|
25
|
-
neighborsByNodeId: new Map(),
|
|
26
|
-
linksByNodeId: new Map(),
|
|
27
|
-
hoveredNode: null,
|
|
28
|
-
selectedNode: null,
|
|
29
|
-
highlightedNodeIds: new Set(),
|
|
30
|
-
highlightedLinks: new Set()
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const graphElement = document.querySelector('#graph');
|
|
34
|
-
const detailsElement = document.querySelector('#node-details');
|
|
35
|
-
const statsElement = document.querySelector('#stats');
|
|
36
|
-
const searchElement = document.querySelector('#search');
|
|
37
|
-
const categoryFilterElement = document.querySelector('#category-filter');
|
|
38
|
-
const refreshButtonElement = document.querySelector('#refresh');
|
|
39
|
-
|
|
40
|
-
if (typeof window.ForceGraph !== 'function') {
|
|
41
|
-
statsElement.textContent = 'ForceGraph failed to load.';
|
|
42
|
-
throw new Error('force-graph library unavailable');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const graph = window
|
|
46
|
-
.ForceGraph()(graphElement)
|
|
47
|
-
.backgroundColor('#0c1117')
|
|
48
|
-
.nodeId('id')
|
|
49
|
-
.linkSource('source')
|
|
50
|
-
.linkTarget('target')
|
|
51
|
-
.nodeRelSize(5)
|
|
52
|
-
.nodeVal((node) => 1 + Math.sqrt((node.degree ?? 0) + 1))
|
|
53
|
-
.nodeLabel((node) => `${node.title}\n${node.id}`)
|
|
54
|
-
.nodeColor((node) => getNodeColor(node))
|
|
55
|
-
.linkColor((link) => getLinkColor(link))
|
|
56
|
-
.linkWidth((link) => (state.highlightedLinks.has(link) ? 2.6 : 1))
|
|
57
|
-
.linkDirectionalParticles((link) => (state.highlightedLinks.has(link) ? 2 : 0))
|
|
58
|
-
.linkDirectionalParticleWidth(2)
|
|
59
|
-
.cooldownTicks(120)
|
|
60
|
-
.onNodeHover((node) => {
|
|
61
|
-
state.hoveredNode = node ?? null;
|
|
62
|
-
syncHighlights();
|
|
63
|
-
})
|
|
64
|
-
.onNodeClick((node) => {
|
|
65
|
-
state.selectedNode = node;
|
|
66
|
-
syncHighlights();
|
|
67
|
-
renderDetails(node);
|
|
68
|
-
})
|
|
69
|
-
.onBackgroundClick(() => {
|
|
70
|
-
state.selectedNode = null;
|
|
71
|
-
syncHighlights();
|
|
72
|
-
renderEmptyDetails();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
resizeGraphToContainer();
|
|
76
|
-
|
|
77
|
-
window.addEventListener('resize', () => {
|
|
78
|
-
resizeGraphToContainer();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
function resizeGraphToContainer() {
|
|
82
|
-
graph.width(graphElement.clientWidth);
|
|
83
|
-
graph.height(graphElement.clientHeight);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
searchElement.addEventListener('input', (event) => {
|
|
87
|
-
state.searchTerm = String(event.target.value ?? '').trim().toLowerCase();
|
|
88
|
-
applyFilters();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
categoryFilterElement.addEventListener('change', (event) => {
|
|
92
|
-
state.category = String(event.target.value ?? 'all');
|
|
93
|
-
applyFilters();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
refreshButtonElement.addEventListener('click', async () => {
|
|
97
|
-
await loadGraphData({ refresh: true });
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
detailsElement.addEventListener('click', (event) => {
|
|
101
|
-
const target = event.target;
|
|
102
|
-
if (!(target instanceof HTMLElement)) {
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const linkedNodeId = target.dataset.nodeId;
|
|
107
|
-
if (!linkedNodeId) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
event.preventDefault();
|
|
112
|
-
const linkedNode = state.nodeById.get(linkedNodeId);
|
|
113
|
-
if (!linkedNode) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
state.selectedNode = linkedNode;
|
|
118
|
-
syncHighlights();
|
|
119
|
-
renderDetails(linkedNode);
|
|
120
|
-
graph.centerAt(linkedNode.x ?? 0, linkedNode.y ?? 0, 450);
|
|
121
|
-
graph.zoom(4, 350);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
await loadGraphData();
|
|
125
|
-
|
|
126
|
-
async function loadGraphData({ refresh = false } = {}) {
|
|
127
|
-
statsElement.textContent = 'Loading graph...';
|
|
128
|
-
refreshButtonElement.disabled = true;
|
|
129
|
-
try {
|
|
130
|
-
const response = await fetch(refresh ? '/api/graph?refresh=1' : '/api/graph');
|
|
131
|
-
if (!response.ok) {
|
|
132
|
-
throw new Error(`HTTP ${response.status}`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const payload = await response.json();
|
|
136
|
-
const nodes = payload.nodes ?? [];
|
|
137
|
-
const links = (payload.edges ?? []).map((edge) => ({
|
|
138
|
-
source: edge.source,
|
|
139
|
-
target: edge.target
|
|
140
|
-
}));
|
|
141
|
-
|
|
142
|
-
hydrateState(nodes, links, payload.stats ?? null);
|
|
143
|
-
populateCategoryFilter();
|
|
144
|
-
applyFilters();
|
|
145
|
-
renderEmptyDetails();
|
|
146
|
-
updateStats();
|
|
147
|
-
graph.zoomToFit(600, 80);
|
|
148
|
-
} catch (error) {
|
|
149
|
-
statsElement.textContent = `Failed to load graph: ${error instanceof Error ? error.message : String(error)}`;
|
|
150
|
-
} finally {
|
|
151
|
-
refreshButtonElement.disabled = false;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function hydrateState(nodes, links, stats) {
|
|
156
|
-
state.nodes = nodes;
|
|
157
|
-
state.links = links;
|
|
158
|
-
state.stats = stats;
|
|
159
|
-
state.nodeById = new Map(nodes.map((node) => [node.id, node]));
|
|
160
|
-
state.neighborsByNodeId = new Map();
|
|
161
|
-
state.linksByNodeId = new Map();
|
|
162
|
-
state.hoveredNode = null;
|
|
163
|
-
state.selectedNode = null;
|
|
164
|
-
|
|
165
|
-
for (const node of nodes) {
|
|
166
|
-
state.neighborsByNodeId.set(node.id, new Set());
|
|
167
|
-
state.linksByNodeId.set(node.id, new Set());
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
for (const link of links) {
|
|
171
|
-
const sourceId = getNodeId(link.source);
|
|
172
|
-
const targetId = getNodeId(link.target);
|
|
173
|
-
if (!sourceId || !targetId) {
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
state.neighborsByNodeId.get(sourceId)?.add(targetId);
|
|
177
|
-
state.neighborsByNodeId.get(targetId)?.add(sourceId);
|
|
178
|
-
state.linksByNodeId.get(sourceId)?.add(link);
|
|
179
|
-
state.linksByNodeId.get(targetId)?.add(link);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
graph.graphData({ nodes: state.nodes, links: state.links });
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function applyFilters() {
|
|
186
|
-
graph.nodeVisibility((node) => isNodeVisible(node));
|
|
187
|
-
graph.linkVisibility((link) => {
|
|
188
|
-
const sourceNode = getNodeFromLinkEnd(link.source);
|
|
189
|
-
const targetNode = getNodeFromLinkEnd(link.target);
|
|
190
|
-
return Boolean(sourceNode && targetNode && isNodeVisible(sourceNode) && isNodeVisible(targetNode));
|
|
191
|
-
});
|
|
192
|
-
syncHighlights();
|
|
193
|
-
graph.refresh();
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function syncHighlights() {
|
|
197
|
-
state.highlightedNodeIds.clear();
|
|
198
|
-
state.highlightedLinks.clear();
|
|
199
|
-
|
|
200
|
-
const focusNode = state.selectedNode ?? state.hoveredNode;
|
|
201
|
-
if (!focusNode) {
|
|
202
|
-
graph.refresh();
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const focusNodeId = focusNode.id;
|
|
207
|
-
state.highlightedNodeIds.add(focusNodeId);
|
|
208
|
-
|
|
209
|
-
for (const neighborId of state.neighborsByNodeId.get(focusNodeId) ?? []) {
|
|
210
|
-
state.highlightedNodeIds.add(neighborId);
|
|
211
|
-
}
|
|
212
|
-
for (const link of state.linksByNodeId.get(focusNodeId) ?? []) {
|
|
213
|
-
state.highlightedLinks.add(link);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
graph.refresh();
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function renderEmptyDetails() {
|
|
220
|
-
detailsElement.innerHTML = '<p>Select a node to inspect details and connections.</p>';
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
function renderDetails(node) {
|
|
224
|
-
const neighbors = Array.from(state.neighborsByNodeId.get(node.id) ?? [])
|
|
225
|
-
.map((id) => state.nodeById.get(id))
|
|
226
|
-
.filter(Boolean)
|
|
227
|
-
.sort((a, b) => a.title.localeCompare(b.title));
|
|
228
|
-
|
|
229
|
-
const tags = Array.isArray(node.tags) && node.tags.length > 0 ? node.tags.join(', ') : 'none';
|
|
230
|
-
const category = node.category || 'default';
|
|
231
|
-
const degree = Number(node.degree ?? neighbors.length);
|
|
232
|
-
const pathValue = node.path ?? '(unresolved link target)';
|
|
233
|
-
|
|
234
|
-
const connectionItems = neighbors.length
|
|
235
|
-
? neighbors
|
|
236
|
-
.map((neighbor) => {
|
|
237
|
-
const color = colorForCategory(neighbor.category);
|
|
238
|
-
return `<li><a href="#" class="connection-link" data-node-id="${escapeHtml(neighbor.id)}" style="color:${color}">${escapeHtml(neighbor.title)}</a></li>`;
|
|
239
|
-
})
|
|
240
|
-
.join('')
|
|
241
|
-
: '<li>No direct connections</li>';
|
|
242
|
-
|
|
243
|
-
detailsElement.innerHTML = `
|
|
244
|
-
<div class="meta-label">Title</div>
|
|
245
|
-
<p class="meta-value">${escapeHtml(node.title)}</p>
|
|
246
|
-
<div class="meta-label">ID</div>
|
|
247
|
-
<p class="meta-value">${escapeHtml(node.id)}</p>
|
|
248
|
-
<div class="meta-label">Category</div>
|
|
249
|
-
<p class="meta-value">${escapeHtml(category)}</p>
|
|
250
|
-
<div class="meta-label">Tags</div>
|
|
251
|
-
<p class="meta-value">${escapeHtml(tags)}</p>
|
|
252
|
-
<div class="meta-label">Degree</div>
|
|
253
|
-
<p class="meta-value">${degree}</p>
|
|
254
|
-
<div class="meta-label">Path</div>
|
|
255
|
-
<p class="meta-value">${escapeHtml(pathValue)}</p>
|
|
256
|
-
<div class="meta-label">Connections (${neighbors.length})</div>
|
|
257
|
-
<ul class="connection-list">${connectionItems}</ul>
|
|
258
|
-
`;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function updateStats() {
|
|
262
|
-
const nodeCount = state.stats?.nodeCount ?? state.nodes.length;
|
|
263
|
-
const edgeCount = state.stats?.edgeCount ?? state.links.length;
|
|
264
|
-
const fileCount = state.stats?.fileCount ?? state.nodes.length;
|
|
265
|
-
statsElement.textContent = `${nodeCount} nodes • ${edgeCount} links • ${fileCount} files`;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
function populateCategoryFilter() {
|
|
269
|
-
const currentValue = state.category;
|
|
270
|
-
const categories = new Set(['all']);
|
|
271
|
-
for (const node of state.nodes) {
|
|
272
|
-
categories.add(node.category || 'default');
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const options = Array.from(categories).sort((a, b) => {
|
|
276
|
-
if (a === 'all') return -1;
|
|
277
|
-
if (b === 'all') return 1;
|
|
278
|
-
return a.localeCompare(b);
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
categoryFilterElement.innerHTML = options
|
|
282
|
-
.map((value) => `<option value="${escapeHtml(value)}">${escapeHtml(value === 'all' ? 'All categories' : value)}</option>`)
|
|
283
|
-
.join('');
|
|
284
|
-
|
|
285
|
-
if (options.includes(currentValue)) {
|
|
286
|
-
categoryFilterElement.value = currentValue;
|
|
287
|
-
state.category = currentValue;
|
|
288
|
-
} else {
|
|
289
|
-
categoryFilterElement.value = 'all';
|
|
290
|
-
state.category = 'all';
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function getNodeColor(node) {
|
|
295
|
-
const nodeId = node.id;
|
|
296
|
-
if (!isNodeVisible(node)) {
|
|
297
|
-
return DIMMED_NODE_COLOR;
|
|
298
|
-
}
|
|
299
|
-
if (state.highlightedNodeIds.has(nodeId)) {
|
|
300
|
-
return HIGHLIGHT_NODE_COLOR;
|
|
301
|
-
}
|
|
302
|
-
if ((state.selectedNode || state.hoveredNode) && !state.highlightedNodeIds.has(nodeId)) {
|
|
303
|
-
return DIMMED_NODE_COLOR;
|
|
304
|
-
}
|
|
305
|
-
return colorForCategory(node.category);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
function getLinkColor(link) {
|
|
309
|
-
if (state.highlightedLinks.has(link)) {
|
|
310
|
-
return HIGHLIGHT_LINK_COLOR;
|
|
311
|
-
}
|
|
312
|
-
const sourceNode = getNodeFromLinkEnd(link.source);
|
|
313
|
-
const targetNode = getNodeFromLinkEnd(link.target);
|
|
314
|
-
if (!sourceNode || !targetNode || !isNodeVisible(sourceNode) || !isNodeVisible(targetNode)) {
|
|
315
|
-
return 'rgba(0, 0, 0, 0)';
|
|
316
|
-
}
|
|
317
|
-
if (state.selectedNode || state.hoveredNode) {
|
|
318
|
-
return DIMMED_LINK_COLOR;
|
|
319
|
-
}
|
|
320
|
-
return 'rgba(157, 176, 198, 0.36)';
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function isNodeVisible(node) {
|
|
324
|
-
const matchesCategory = state.category === 'all' || (node.category || 'default') === state.category;
|
|
325
|
-
if (!matchesCategory) {
|
|
326
|
-
return false;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (!state.searchTerm) {
|
|
330
|
-
return true;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
const haystack = [
|
|
334
|
-
node.id,
|
|
335
|
-
node.title,
|
|
336
|
-
Array.isArray(node.tags) ? node.tags.join(' ') : '',
|
|
337
|
-
node.category
|
|
338
|
-
]
|
|
339
|
-
.join(' ')
|
|
340
|
-
.toLowerCase();
|
|
341
|
-
|
|
342
|
-
return haystack.includes(state.searchTerm);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function getNodeFromLinkEnd(linkEnd) {
|
|
346
|
-
if (!linkEnd) {
|
|
347
|
-
return null;
|
|
348
|
-
}
|
|
349
|
-
if (typeof linkEnd === 'object') {
|
|
350
|
-
return linkEnd;
|
|
351
|
-
}
|
|
352
|
-
return state.nodeById.get(linkEnd) ?? null;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function getNodeId(linkEnd) {
|
|
356
|
-
if (!linkEnd) {
|
|
357
|
-
return '';
|
|
358
|
-
}
|
|
359
|
-
if (typeof linkEnd === 'object') {
|
|
360
|
-
return linkEnd.id || '';
|
|
361
|
-
}
|
|
362
|
-
return String(linkEnd);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function colorForCategory(category) {
|
|
366
|
-
return CATEGORY_COLORS[category] ?? CATEGORY_COLORS.default;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function escapeHtml(value) {
|
|
370
|
-
return String(value)
|
|
371
|
-
.replaceAll('&', '&')
|
|
372
|
-
.replaceAll('<', '<')
|
|
373
|
-
.replaceAll('>', '>')
|
|
374
|
-
.replaceAll('"', '"')
|
|
375
|
-
.replaceAll("'", ''');
|
|
376
|
-
}
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
:root {
|
|
2
|
-
color-scheme: dark;
|
|
3
|
-
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
4
|
-
--bg: #0c1117;
|
|
5
|
-
--panel: #121a24;
|
|
6
|
-
--panel-border: #1e2936;
|
|
7
|
-
--text: #d8e3f0;
|
|
8
|
-
--muted: #8fa1b7;
|
|
9
|
-
--accent: #4ecdc4;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
* {
|
|
13
|
-
box-sizing: border-box;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
html,
|
|
17
|
-
body {
|
|
18
|
-
margin: 0;
|
|
19
|
-
width: 100%;
|
|
20
|
-
height: 100%;
|
|
21
|
-
background: var(--bg);
|
|
22
|
-
color: var(--text);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
body {
|
|
26
|
-
display: flex;
|
|
27
|
-
flex-direction: column;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.toolbar {
|
|
31
|
-
border-bottom: 1px solid var(--panel-border);
|
|
32
|
-
background: #0f1520;
|
|
33
|
-
display: flex;
|
|
34
|
-
align-items: center;
|
|
35
|
-
justify-content: space-between;
|
|
36
|
-
gap: 1rem;
|
|
37
|
-
padding: 0.75rem 1rem;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.toolbar h1 {
|
|
41
|
-
margin: 0;
|
|
42
|
-
font-size: 1.1rem;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
.toolbar p {
|
|
46
|
-
margin: 0.2rem 0 0;
|
|
47
|
-
color: var(--muted);
|
|
48
|
-
font-size: 0.85rem;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.toolbar-controls {
|
|
52
|
-
display: flex;
|
|
53
|
-
gap: 0.5rem;
|
|
54
|
-
flex-wrap: wrap;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
input,
|
|
58
|
-
select,
|
|
59
|
-
button {
|
|
60
|
-
border: 1px solid var(--panel-border);
|
|
61
|
-
background: var(--panel);
|
|
62
|
-
color: var(--text);
|
|
63
|
-
border-radius: 8px;
|
|
64
|
-
padding: 0.5rem 0.65rem;
|
|
65
|
-
font-size: 0.9rem;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
input {
|
|
69
|
-
min-width: 220px;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
button {
|
|
73
|
-
cursor: pointer;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
button:hover {
|
|
77
|
-
border-color: var(--accent);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.layout {
|
|
81
|
-
display: grid;
|
|
82
|
-
grid-template-columns: 1fr 300px;
|
|
83
|
-
min-height: 0;
|
|
84
|
-
flex: 1;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
#graph {
|
|
88
|
-
min-height: 0;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.details-panel {
|
|
92
|
-
border-left: 1px solid var(--panel-border);
|
|
93
|
-
padding: 1rem;
|
|
94
|
-
background: #0f1520;
|
|
95
|
-
overflow-y: auto;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.details-panel h2 {
|
|
99
|
-
margin-top: 0;
|
|
100
|
-
font-size: 1rem;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
.meta-label {
|
|
104
|
-
color: var(--muted);
|
|
105
|
-
font-size: 0.82rem;
|
|
106
|
-
margin-bottom: 0.15rem;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.meta-value {
|
|
110
|
-
margin: 0 0 0.8rem;
|
|
111
|
-
font-size: 0.92rem;
|
|
112
|
-
word-break: break-word;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.connection-list {
|
|
116
|
-
list-style: none;
|
|
117
|
-
margin: 0;
|
|
118
|
-
padding: 0;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.connection-list li {
|
|
122
|
-
border-bottom: 1px solid var(--panel-border);
|
|
123
|
-
padding: 0.35rem 0;
|
|
124
|
-
font-size: 0.9rem;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.connection-list li:last-child {
|
|
128
|
-
border-bottom: none;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.connection-link {
|
|
132
|
-
color: #9bc3ff;
|
|
133
|
-
text-decoration: none;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.connection-link:hover {
|
|
137
|
-
text-decoration: underline;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
@media (max-width: 980px) {
|
|
141
|
-
.layout {
|
|
142
|
-
grid-template-columns: 1fr;
|
|
143
|
-
grid-template-rows: 1fr auto;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
#graph {
|
|
147
|
-
height: 65vh;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
.details-panel {
|
|
151
|
-
border-left: none;
|
|
152
|
-
border-top: 1px solid var(--panel-border);
|
|
153
|
-
}
|
|
154
|
-
}
|
package/dist/chunk-4KDZZW4X.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// src/lib/config.ts
|
|
2
|
-
import * as path from "path";
|
|
3
|
-
function getVaultPath() {
|
|
4
|
-
const vaultPath = process.env.CLAWVAULT_PATH;
|
|
5
|
-
if (!vaultPath) {
|
|
6
|
-
throw new Error("CLAWVAULT_PATH environment variable not set");
|
|
7
|
-
}
|
|
8
|
-
return path.resolve(vaultPath);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export {
|
|
12
|
-
getVaultPath
|
|
13
|
-
};
|