shieldcortex 2.1.1 → 2.1.3

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 (87) hide show
  1. package/README.md +1 -1
  2. package/dist/defence/firewall/encoding-detector.js +1 -1
  3. package/dist/defence/firewall/encoding-detector.js.map +1 -1
  4. package/dist/defence/firewall/index.js +22 -0
  5. package/dist/defence/firewall/index.js.map +1 -1
  6. package/dist/defence/firewall/instruction-detector.d.ts.map +1 -1
  7. package/dist/defence/firewall/instruction-detector.js +26 -0
  8. package/dist/defence/firewall/instruction-detector.js.map +1 -1
  9. package/dist/defence/pipeline.d.ts.map +1 -1
  10. package/dist/defence/pipeline.js +8 -0
  11. package/dist/defence/pipeline.js.map +1 -1
  12. package/hooks/clawdbot/cortex-memory/HOOK.md +2 -2
  13. package/package.json +13 -9
  14. package/dashboard/components.json +0 -22
  15. package/dashboard/eslint.config.mjs +0 -42
  16. package/dashboard/next.config.ts +0 -7
  17. package/dashboard/package-lock.json +0 -8053
  18. package/dashboard/package.json +0 -44
  19. package/dashboard/postcss.config.mjs +0 -7
  20. package/dashboard/public/file.svg +0 -1
  21. package/dashboard/public/globe.svg +0 -1
  22. package/dashboard/public/next.svg +0 -1
  23. package/dashboard/public/vercel.svg +0 -1
  24. package/dashboard/public/window.svg +0 -1
  25. package/dashboard/scripts/ensure-api.mjs +0 -76
  26. package/dashboard/src/app/error.tsx +0 -49
  27. package/dashboard/src/app/favicon.ico +0 -0
  28. package/dashboard/src/app/globals.css +0 -130
  29. package/dashboard/src/app/layout.tsx +0 -35
  30. package/dashboard/src/app/page.tsx +0 -364
  31. package/dashboard/src/components/Providers.tsx +0 -27
  32. package/dashboard/src/components/brain/ActivityPulseSystem.tsx +0 -229
  33. package/dashboard/src/components/brain/BrainMesh.tsx +0 -133
  34. package/dashboard/src/components/brain/BrainRegions.tsx +0 -254
  35. package/dashboard/src/components/brain/BrainScene.tsx +0 -255
  36. package/dashboard/src/components/brain/CategoryLabels.tsx +0 -103
  37. package/dashboard/src/components/brain/CoreSphere.tsx +0 -215
  38. package/dashboard/src/components/brain/DataFlowParticles.tsx +0 -123
  39. package/dashboard/src/components/brain/DataStreamRings.tsx +0 -161
  40. package/dashboard/src/components/brain/ElectronFlow.tsx +0 -323
  41. package/dashboard/src/components/brain/HolographicGrid.tsx +0 -235
  42. package/dashboard/src/components/brain/MemoryLinks.tsx +0 -271
  43. package/dashboard/src/components/brain/MemoryNode.tsx +0 -245
  44. package/dashboard/src/components/brain/NeuralPathways.tsx +0 -441
  45. package/dashboard/src/components/brain/SynapseNodes.tsx +0 -312
  46. package/dashboard/src/components/brain/TimelineControls.tsx +0 -205
  47. package/dashboard/src/components/chip/ChipScene.tsx +0 -497
  48. package/dashboard/src/components/chip/ChipSubstrate.tsx +0 -238
  49. package/dashboard/src/components/chip/CortexCore.tsx +0 -210
  50. package/dashboard/src/components/chip/DataBus.tsx +0 -416
  51. package/dashboard/src/components/chip/MemoryCell.tsx +0 -225
  52. package/dashboard/src/components/chip/MemoryGrid.tsx +0 -328
  53. package/dashboard/src/components/chip/QuantumCell.tsx +0 -316
  54. package/dashboard/src/components/chip/SectionLabel.tsx +0 -113
  55. package/dashboard/src/components/chip/index.ts +0 -14
  56. package/dashboard/src/components/controls/ControlPanel.tsx +0 -106
  57. package/dashboard/src/components/controls/VersionPanel.tsx +0 -185
  58. package/dashboard/src/components/dashboard/StatsPanel.tsx +0 -164
  59. package/dashboard/src/components/debug/ActivityLog.tsx +0 -250
  60. package/dashboard/src/components/debug/DebugPanel.tsx +0 -101
  61. package/dashboard/src/components/debug/QueryTester.tsx +0 -192
  62. package/dashboard/src/components/debug/RelationshipGraph.tsx +0 -403
  63. package/dashboard/src/components/debug/SqlConsole.tsx +0 -319
  64. package/dashboard/src/components/graph/KnowledgeGraph.tsx +0 -230
  65. package/dashboard/src/components/graph/OntologyGraph.tsx +0 -631
  66. package/dashboard/src/components/insights/ActivityHeatmap.tsx +0 -131
  67. package/dashboard/src/components/insights/InsightsView.tsx +0 -46
  68. package/dashboard/src/components/insights/KnowledgeMapPanel.tsx +0 -80
  69. package/dashboard/src/components/insights/QualityPanel.tsx +0 -116
  70. package/dashboard/src/components/memories/MemoriesView.tsx +0 -150
  71. package/dashboard/src/components/memories/MemoryCard.tsx +0 -103
  72. package/dashboard/src/components/memory/MemoryDetail.tsx +0 -325
  73. package/dashboard/src/components/nav/NavRail.tsx +0 -54
  74. package/dashboard/src/components/ui/button.tsx +0 -62
  75. package/dashboard/src/components/ui/card.tsx +0 -92
  76. package/dashboard/src/components/ui/input.tsx +0 -21
  77. package/dashboard/src/hooks/useDebouncedValue.ts +0 -24
  78. package/dashboard/src/hooks/useMemories.ts +0 -458
  79. package/dashboard/src/hooks/useSuggestions.ts +0 -46
  80. package/dashboard/src/lib/category-colors.ts +0 -84
  81. package/dashboard/src/lib/position-algorithm.ts +0 -177
  82. package/dashboard/src/lib/simplex-noise.ts +0 -217
  83. package/dashboard/src/lib/store.ts +0 -88
  84. package/dashboard/src/lib/utils.ts +0 -6
  85. package/dashboard/src/lib/websocket.ts +0 -249
  86. package/dashboard/src/types/memory.ts +0 -73
  87. package/dashboard/tsconfig.json +0 -34
@@ -1,250 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * Activity Log Component
5
- *
6
- * Real-time event stream showing memory operations.
7
- * Uses WebSocket for live updates.
8
- */
9
-
10
- import { useState, useEffect, useRef } from 'react';
11
- import { useMemoryWebSocket, MemoryEventType } from '@/lib/websocket';
12
-
13
- interface LogEntry {
14
- id: number;
15
- timestamp: Date;
16
- type: MemoryEventType;
17
- message: string;
18
- details?: Record<string, unknown>;
19
- }
20
-
21
- const EVENT_COLORS: Record<MemoryEventType, string> = {
22
- memory_created: 'text-green-400',
23
- memory_accessed: 'text-blue-400',
24
- memory_updated: 'text-yellow-400',
25
- memory_deleted: 'text-red-400',
26
- consolidation_complete: 'text-purple-400',
27
- decay_tick: 'text-slate-500',
28
- initial_state: 'text-slate-400',
29
- worker_light_tick: 'text-slate-500',
30
- worker_medium_tick: 'text-slate-500',
31
- link_discovered: 'text-cyan-400',
32
- predictive_consolidation: 'text-purple-400',
33
- update_started: 'text-blue-400',
34
- update_complete: 'text-green-400',
35
- update_failed: 'text-red-400',
36
- server_restarting: 'text-orange-400',
37
- };
38
-
39
- const EVENT_ICONS: Record<MemoryEventType, string> = {
40
- memory_created: '+',
41
- memory_accessed: '👁',
42
- memory_updated: '✏',
43
- memory_deleted: '✕',
44
- consolidation_complete: '🔄',
45
- decay_tick: '⏱',
46
- initial_state: '📋',
47
- worker_light_tick: '⚡',
48
- worker_medium_tick: '🔋',
49
- link_discovered: '🔗',
50
- predictive_consolidation: '🔮',
51
- update_started: '⬆',
52
- update_complete: '✓',
53
- update_failed: '✗',
54
- server_restarting: '🔄',
55
- };
56
-
57
- export function ActivityLog() {
58
- const [logs, setLogs] = useState<LogEntry[]>([]);
59
- const [autoScroll, setAutoScroll] = useState(true);
60
- const [filters, setFilters] = useState<Record<MemoryEventType, boolean>>({
61
- memory_created: true,
62
- memory_accessed: true,
63
- memory_updated: true,
64
- memory_deleted: true,
65
- consolidation_complete: true,
66
- decay_tick: false, // Off by default (noisy)
67
- initial_state: false,
68
- worker_light_tick: false,
69
- worker_medium_tick: false,
70
- link_discovered: true,
71
- predictive_consolidation: true,
72
- update_started: true,
73
- update_complete: true,
74
- update_failed: true,
75
- server_restarting: true,
76
- });
77
-
78
- const logContainerRef = useRef<HTMLDivElement>(null);
79
- const nextIdRef = useRef(1);
80
-
81
- // Connect to WebSocket
82
- const { lastEvent, isConnected } = useMemoryWebSocket();
83
-
84
- // Process incoming events
85
- useEffect(() => {
86
- if (!lastEvent) return;
87
-
88
- const entry: LogEntry = {
89
- id: nextIdRef.current++,
90
- timestamp: new Date(lastEvent.timestamp),
91
- type: lastEvent.type,
92
- message: formatEventMessage(lastEvent),
93
- details: lastEvent.data as Record<string, unknown>,
94
- };
95
-
96
- setLogs((prev) => {
97
- const updated = [...prev, entry];
98
- // Keep only last 500 entries
99
- return updated.slice(-500);
100
- });
101
- }, [lastEvent]);
102
-
103
- // Auto-scroll to bottom
104
- useEffect(() => {
105
- if (autoScroll && logContainerRef.current) {
106
- logContainerRef.current.scrollTop = logContainerRef.current.scrollHeight;
107
- }
108
- }, [logs, autoScroll]);
109
-
110
- const filteredLogs = logs.filter((log) => filters[log.type]);
111
-
112
- const toggleFilter = (type: MemoryEventType) => {
113
- setFilters((prev) => ({ ...prev, [type]: !prev[type] }));
114
- };
115
-
116
- const clearLogs = () => {
117
- setLogs([]);
118
- };
119
-
120
- const exportLogs = () => {
121
- const json = JSON.stringify(filteredLogs, null, 2);
122
- const blob = new Blob([json], { type: 'application/json' });
123
- const url = URL.createObjectURL(blob);
124
- const a = document.createElement('a');
125
- a.href = url;
126
- a.download = `cortex-activity-${new Date().toISOString().split('T')[0]}.json`;
127
- a.click();
128
- URL.revokeObjectURL(url);
129
- };
130
-
131
- return (
132
- <div className="h-full flex flex-col">
133
- {/* Controls */}
134
- <div className="p-3 border-b border-slate-700 flex items-center gap-3 flex-wrap">
135
- {/* Connection Status */}
136
- <div className="flex items-center gap-2 text-xs">
137
- <span
138
- className={`w-2 h-2 rounded-full ${isConnected ? 'bg-green-500' : 'bg-red-500'}`}
139
- />
140
- <span className="text-slate-400">
141
- {isConnected ? 'Connected' : 'Disconnected'}
142
- </span>
143
- </div>
144
-
145
- <div className="w-px h-4 bg-slate-700" />
146
-
147
- {/* Filters */}
148
- <div className="flex items-center gap-1 flex-wrap">
149
- {(Object.keys(filters) as MemoryEventType[]).map((type) => (
150
- <button
151
- key={type}
152
- onClick={() => toggleFilter(type)}
153
- className={`px-2 py-0.5 text-xs rounded transition-colors ${
154
- filters[type]
155
- ? `${EVENT_COLORS[type]} bg-slate-700`
156
- : 'text-slate-600 bg-slate-800'
157
- }`}
158
- >
159
- {type.replace(/_/g, ' ').replace('memory ', '')}
160
- </button>
161
- ))}
162
- </div>
163
-
164
- <div className="flex-1" />
165
-
166
- {/* Actions */}
167
- <label className="flex items-center gap-1 text-xs text-slate-400 cursor-pointer">
168
- <input
169
- type="checkbox"
170
- checked={autoScroll}
171
- onChange={(e) => setAutoScroll(e.target.checked)}
172
- className="rounded border-slate-600 bg-slate-800"
173
- />
174
- Auto-scroll
175
- </label>
176
-
177
- <button
178
- onClick={exportLogs}
179
- className="text-xs text-slate-400 hover:text-white"
180
- >
181
- Export
182
- </button>
183
-
184
- <button
185
- onClick={clearLogs}
186
- className="text-xs text-red-400 hover:text-red-300"
187
- >
188
- Clear
189
- </button>
190
- </div>
191
-
192
- {/* Log Entries */}
193
- <div
194
- ref={logContainerRef}
195
- className="flex-1 overflow-auto p-3 font-mono text-xs"
196
- >
197
- {filteredLogs.length === 0 ? (
198
- <div className="text-slate-500 text-center py-8">
199
- {isConnected ? 'Waiting for events...' : 'Not connected to server'}
200
- </div>
201
- ) : (
202
- <div className="space-y-1">
203
- {filteredLogs.map((log) => (
204
- <div key={log.id} className="flex gap-2 hover:bg-slate-800/50 px-1 rounded">
205
- <span className="text-slate-500 shrink-0">
206
- {log.timestamp.toLocaleTimeString()}
207
- </span>
208
- <span className={`shrink-0 w-4 ${EVENT_COLORS[log.type]}`}>
209
- {EVENT_ICONS[log.type]}
210
- </span>
211
- <span className={EVENT_COLORS[log.type]}>{log.message}</span>
212
- </div>
213
- ))}
214
- </div>
215
- )}
216
- </div>
217
- </div>
218
- );
219
- }
220
-
221
- function formatEventMessage(event: { type: MemoryEventType; data?: unknown }): string {
222
- const data = event.data as Record<string, unknown> | undefined;
223
-
224
- switch (event.type) {
225
- case 'memory_created':
226
- return `Created: "${data?.title || 'Unknown'}" (${data?.type || 'unknown'})`;
227
- case 'memory_accessed':
228
- return `Accessed: "${data?.title || 'Unknown'}" → salience ${((data?.newSalience as number) * 100).toFixed(0)}%`;
229
- case 'memory_updated':
230
- return `Updated: "${data?.title || 'Unknown'}"`;
231
- case 'memory_deleted':
232
- return `Deleted: "${data?.title || 'Unknown'}" (ID: ${data?.memoryId})`;
233
- case 'consolidation_complete':
234
- return `Consolidation: ${data?.consolidated || 0} promoted, ${data?.decayed || 0} decayed, ${data?.deleted || 0} deleted`;
235
- case 'decay_tick':
236
- return `Decay tick: ${(data?.updates as unknown[])?.length || 0} memories updated`;
237
- case 'initial_state':
238
- return 'Connected - received initial state';
239
- case 'worker_light_tick':
240
- return 'Worker light tick completed';
241
- case 'worker_medium_tick':
242
- return 'Worker medium tick completed';
243
- case 'link_discovered':
244
- return `Link discovered: ${data?.sourceTitle || '?'} → ${data?.targetTitle || '?'}`;
245
- case 'predictive_consolidation':
246
- return `Predictive consolidation: ${data?.promoted || 0} promoted`;
247
- default:
248
- return `Event: ${event.type}`;
249
- }
250
- }
@@ -1,101 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * Debug Panel Component
5
- *
6
- * Collapsible bottom panel with tabbed interface for debug tools:
7
- * - Memory Detail (enhanced)
8
- * - Query Tester
9
- * - Activity Log
10
- * - Relationship Graph
11
- * - SQL Console
12
- */
13
-
14
- import { useState } from 'react';
15
- import { QueryTester } from './QueryTester';
16
- import { ActivityLog } from './ActivityLog';
17
- import { RelationshipGraph } from './RelationshipGraph';
18
- import { SqlConsole } from './SqlConsole';
19
-
20
- type TabId = 'detail' | 'query' | 'activity' | 'graph' | 'sql';
21
-
22
- interface Tab {
23
- id: TabId;
24
- label: string;
25
- icon: string;
26
- }
27
-
28
- const TABS: Tab[] = [
29
- { id: 'query', label: 'Query', icon: '🔍' },
30
- { id: 'activity', label: 'Activity', icon: '📋' },
31
- { id: 'graph', label: 'Graph', icon: '🕸' },
32
- { id: 'sql', label: 'SQL', icon: '💾' },
33
- ];
34
-
35
- interface DebugPanelProps {
36
- onCollapse?: () => void;
37
- }
38
-
39
- export function DebugPanel({ onCollapse }: DebugPanelProps) {
40
- const [activeTab, setActiveTab] = useState<TabId>('query');
41
- const [isCollapsed, setIsCollapsed] = useState(false);
42
-
43
- const handleCollapse = () => {
44
- setIsCollapsed(!isCollapsed);
45
- onCollapse?.();
46
- };
47
-
48
- if (isCollapsed) {
49
- return (
50
- <div className="h-10 border-t border-slate-700 bg-slate-900/80 flex items-center px-4">
51
- <button
52
- onClick={handleCollapse}
53
- className="flex items-center gap-2 text-sm text-slate-400 hover:text-white"
54
- >
55
- <span>▲</span>
56
- <span>Debug Panel</span>
57
- </button>
58
- </div>
59
- );
60
- }
61
-
62
- return (
63
- <div className="h-96 border-t border-slate-700 bg-slate-900/80 flex flex-col">
64
- {/* Tab Bar */}
65
- <div className="flex items-center border-b border-slate-700 px-2">
66
- {TABS.map((tab) => (
67
- <button
68
- key={tab.id}
69
- onClick={() => setActiveTab(tab.id)}
70
- className={`px-4 py-2 text-sm flex items-center gap-1.5 border-b-2 transition-colors ${
71
- activeTab === tab.id
72
- ? 'text-white border-blue-500'
73
- : 'text-slate-400 border-transparent hover:text-white hover:border-slate-600'
74
- }`}
75
- >
76
- <span>{tab.icon}</span>
77
- <span>{tab.label}</span>
78
- </button>
79
- ))}
80
-
81
- <div className="flex-1" />
82
-
83
- <button
84
- onClick={handleCollapse}
85
- className="p-2 text-slate-400 hover:text-white"
86
- title="Collapse panel"
87
- >
88
-
89
- </button>
90
- </div>
91
-
92
- {/* Tab Content */}
93
- <div className="flex-1 overflow-hidden min-h-0">
94
- {activeTab === 'query' && <QueryTester />}
95
- {activeTab === 'activity' && <ActivityLog />}
96
- {activeTab === 'graph' && <RelationshipGraph />}
97
- {activeTab === 'sql' && <SqlConsole />}
98
- </div>
99
- </div>
100
- );
101
- }
@@ -1,192 +0,0 @@
1
- 'use client';
2
-
3
- /**
4
- * Query Tester Component
5
- *
6
- * Allows testing search queries against the memory system
7
- * with detailed score breakdowns and explanations.
8
- */
9
-
10
- import { useState } from 'react';
11
- import { Button } from '@/components/ui/button';
12
- import { Input } from '@/components/ui/input';
13
- import { Memory } from '@/types/memory';
14
-
15
- const API_BASE = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
16
-
17
- interface SearchResult {
18
- memory: Memory & { decayedScore: number };
19
- relevanceScore: number;
20
- }
21
-
22
- type SearchMode = 'hybrid' | 'fts' | 'vector';
23
-
24
- export function QueryTester() {
25
- const [query, setQuery] = useState('');
26
- const [mode, setMode] = useState<SearchMode>('hybrid');
27
- const [results, setResults] = useState<SearchResult[]>([]);
28
- const [isSearching, setIsSearching] = useState(false);
29
- const [error, setError] = useState<string | null>(null);
30
-
31
- const handleSearch = async () => {
32
- if (!query.trim()) return;
33
-
34
- setIsSearching(true);
35
- setError(null);
36
-
37
- try {
38
- const params = new URLSearchParams({
39
- query: query.trim(),
40
- mode: 'search',
41
- limit: '20',
42
- });
43
-
44
- const response = await fetch(`${API_BASE}/api/memories?${params}`);
45
- if (!response.ok) {
46
- throw new Error(`Search failed: ${response.statusText}`);
47
- }
48
-
49
- const data = await response.json();
50
- // Transform API response to include relevance score
51
- const resultsWithScore: SearchResult[] = data.memories.map((m: Memory & { decayedScore: number }) => ({
52
- memory: m,
53
- relevanceScore: m.decayedScore, // Using decayedScore as proxy for relevance
54
- }));
55
-
56
- setResults(resultsWithScore);
57
- } catch (err) {
58
- setError((err as Error).message);
59
- setResults([]);
60
- } finally {
61
- setIsSearching(false);
62
- }
63
- };
64
-
65
- const handleKeyDown = (e: React.KeyboardEvent) => {
66
- if (e.key === 'Enter') {
67
- handleSearch();
68
- }
69
- };
70
-
71
- return (
72
- <div className="h-full flex flex-col">
73
- {/* Search Controls */}
74
- <div className="p-3 border-b border-slate-700 flex gap-2 items-center">
75
- <Input
76
- type="text"
77
- placeholder="Enter search query..."
78
- value={query}
79
- onChange={(e) => setQuery(e.target.value)}
80
- onKeyDown={handleKeyDown}
81
- className="flex-1 bg-slate-800 border-slate-600 text-white"
82
- />
83
-
84
- {/* Mode Toggle */}
85
- <div className="flex gap-1 bg-slate-800 rounded-lg p-1">
86
- {(['hybrid', 'fts', 'vector'] as SearchMode[]).map((m) => (
87
- <button
88
- key={m}
89
- onClick={() => setMode(m)}
90
- className={`px-2 py-1 text-xs rounded transition-colors ${
91
- mode === m
92
- ? 'bg-blue-600 text-white'
93
- : 'text-slate-400 hover:text-white'
94
- }`}
95
- >
96
- {m.toUpperCase()}
97
- </button>
98
- ))}
99
- </div>
100
-
101
- <Button
102
- onClick={handleSearch}
103
- disabled={isSearching || !query.trim()}
104
- size="sm"
105
- className="bg-blue-600 hover:bg-blue-700"
106
- >
107
- {isSearching ? 'Searching...' : 'Search'}
108
- </Button>
109
- </div>
110
-
111
- {/* Results */}
112
- <div className="flex-1 overflow-auto p-3">
113
- {error && (
114
- <div className="p-3 rounded-lg bg-red-500/20 border border-red-500/50 text-red-300 text-sm mb-3">
115
- {error}
116
- </div>
117
- )}
118
-
119
- {results.length === 0 && !error && (
120
- <div className="text-slate-500 text-sm text-center py-8">
121
- {query ? 'No results found' : 'Enter a query to search memories'}
122
- </div>
123
- )}
124
-
125
- {results.length > 0 && (
126
- <div className="space-y-2">
127
- <div className="text-xs text-slate-400 mb-2">
128
- Found {results.length} results
129
- </div>
130
-
131
- <table className="w-full text-sm">
132
- <thead>
133
- <tr className="text-left text-slate-400 border-b border-slate-700">
134
- <th className="pb-2 pr-4">Title</th>
135
- <th className="pb-2 pr-4 w-20">Score</th>
136
- <th className="pb-2 pr-4 w-24">Type</th>
137
- <th className="pb-2 w-24">Category</th>
138
- </tr>
139
- </thead>
140
- <tbody>
141
- {results.map((result, index) => (
142
- <tr
143
- key={result.memory.id}
144
- className="border-b border-slate-800 hover:bg-slate-800/50"
145
- >
146
- <td className="py-2 pr-4">
147
- <div className="flex items-center gap-2">
148
- <span className="text-slate-500 text-xs w-5">
149
- {index + 1}.
150
- </span>
151
- <span className="text-white truncate max-w-[300px]">
152
- {result.memory.title}
153
- </span>
154
- </div>
155
- </td>
156
- <td className="py-2 pr-4">
157
- <div className="flex items-center gap-1">
158
- <div
159
- className="h-1.5 rounded-full bg-gradient-to-r from-blue-600 to-purple-600"
160
- style={{ width: `${result.relevanceScore * 100}%`, maxWidth: '60px' }}
161
- />
162
- <span className="text-xs text-slate-400">
163
- {(result.relevanceScore * 100).toFixed(0)}%
164
- </span>
165
- </div>
166
- </td>
167
- <td className="py-2 pr-4">
168
- <span className={`text-xs px-1.5 py-0.5 rounded ${
169
- result.memory.type === 'long_term'
170
- ? 'bg-purple-600/30 text-purple-300'
171
- : result.memory.type === 'short_term'
172
- ? 'bg-blue-600/30 text-blue-300'
173
- : 'bg-green-600/30 text-green-300'
174
- }`}>
175
- {result.memory.type.replace('_', '-')}
176
- </span>
177
- </td>
178
- <td className="py-2">
179
- <span className="text-xs text-slate-400">
180
- {result.memory.category}
181
- </span>
182
- </td>
183
- </tr>
184
- ))}
185
- </tbody>
186
- </table>
187
- </div>
188
- )}
189
- </div>
190
- </div>
191
- );
192
- }