neuronlayer 0.1.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/CONTRIBUTING.md +127 -0
- package/LICENSE +21 -0
- package/README.md +305 -0
- package/dist/index.js +38016 -0
- package/esbuild.config.js +26 -0
- package/package.json +63 -0
- package/src/cli/commands.ts +382 -0
- package/src/core/adr-exporter.ts +253 -0
- package/src/core/architecture/architecture-enforcement.ts +228 -0
- package/src/core/architecture/duplicate-detector.ts +288 -0
- package/src/core/architecture/index.ts +6 -0
- package/src/core/architecture/pattern-learner.ts +306 -0
- package/src/core/architecture/pattern-library.ts +403 -0
- package/src/core/architecture/pattern-validator.ts +324 -0
- package/src/core/change-intelligence/bug-correlator.ts +444 -0
- package/src/core/change-intelligence/change-intelligence.ts +221 -0
- package/src/core/change-intelligence/change-tracker.ts +334 -0
- package/src/core/change-intelligence/fix-suggester.ts +340 -0
- package/src/core/change-intelligence/index.ts +5 -0
- package/src/core/code-verifier.ts +843 -0
- package/src/core/confidence/confidence-scorer.ts +251 -0
- package/src/core/confidence/conflict-checker.ts +289 -0
- package/src/core/confidence/index.ts +5 -0
- package/src/core/confidence/source-tracker.ts +263 -0
- package/src/core/confidence/warning-detector.ts +241 -0
- package/src/core/context-rot/compaction.ts +284 -0
- package/src/core/context-rot/context-health.ts +243 -0
- package/src/core/context-rot/context-rot-prevention.ts +213 -0
- package/src/core/context-rot/critical-context.ts +221 -0
- package/src/core/context-rot/drift-detector.ts +255 -0
- package/src/core/context-rot/index.ts +7 -0
- package/src/core/context.ts +263 -0
- package/src/core/decision-extractor.ts +339 -0
- package/src/core/decisions.ts +69 -0
- package/src/core/deja-vu.ts +421 -0
- package/src/core/engine.ts +1455 -0
- package/src/core/feature-context.ts +726 -0
- package/src/core/ghost-mode.ts +412 -0
- package/src/core/learning.ts +485 -0
- package/src/core/living-docs/activity-tracker.ts +296 -0
- package/src/core/living-docs/architecture-generator.ts +428 -0
- package/src/core/living-docs/changelog-generator.ts +348 -0
- package/src/core/living-docs/component-generator.ts +230 -0
- package/src/core/living-docs/doc-engine.ts +110 -0
- package/src/core/living-docs/doc-validator.ts +282 -0
- package/src/core/living-docs/index.ts +8 -0
- package/src/core/project-manager.ts +297 -0
- package/src/core/summarizer.ts +267 -0
- package/src/core/test-awareness/change-validator.ts +499 -0
- package/src/core/test-awareness/index.ts +5 -0
- package/src/index.ts +49 -0
- package/src/indexing/ast.ts +563 -0
- package/src/indexing/embeddings.ts +85 -0
- package/src/indexing/indexer.ts +245 -0
- package/src/indexing/watcher.ts +78 -0
- package/src/server/gateways/aggregator.ts +374 -0
- package/src/server/gateways/index.ts +473 -0
- package/src/server/gateways/memory-ghost.ts +343 -0
- package/src/server/gateways/memory-query.ts +452 -0
- package/src/server/gateways/memory-record.ts +346 -0
- package/src/server/gateways/memory-review.ts +410 -0
- package/src/server/gateways/memory-status.ts +517 -0
- package/src/server/gateways/memory-verify.ts +392 -0
- package/src/server/gateways/router.ts +434 -0
- package/src/server/gateways/types.ts +610 -0
- package/src/server/mcp.ts +154 -0
- package/src/server/resources.ts +85 -0
- package/src/server/tools.ts +2261 -0
- package/src/storage/database.ts +262 -0
- package/src/storage/tier1.ts +135 -0
- package/src/storage/tier2.ts +764 -0
- package/src/storage/tier3.ts +123 -0
- package/src/types/documentation.ts +619 -0
- package/src/types/index.ts +222 -0
- package/src/utils/config.ts +193 -0
- package/src/utils/files.ts +117 -0
- package/src/utils/time.ts +37 -0
- package/src/utils/tokens.ts +52 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Status Gateway
|
|
3
|
+
*
|
|
4
|
+
* Routes to: get_project_summary, what_happened, what_changed, get_architecture,
|
|
5
|
+
* get_changelog, validate_docs, get_context_health, list_patterns,
|
|
6
|
+
* get_architecture_stats, find_undocumented, get_critical_context, get_learning_stats
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { MemoryLayerEngine } from '../../core/engine.js';
|
|
10
|
+
import type { MemoryStatusInput, MemoryStatusResponse, MemoryStatusAction } from './types.js';
|
|
11
|
+
import { detectStatusAction, getStatusGathers } from './router.js';
|
|
12
|
+
import { aggregateStatusResults } from './aggregator.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Handle a memory_status gateway call
|
|
16
|
+
*/
|
|
17
|
+
export async function handleMemoryStatus(
|
|
18
|
+
engine: MemoryLayerEngine,
|
|
19
|
+
input: MemoryStatusInput
|
|
20
|
+
): Promise<MemoryStatusResponse> {
|
|
21
|
+
const action = detectStatusAction(input);
|
|
22
|
+
const sourcesUsed: string[] = [];
|
|
23
|
+
|
|
24
|
+
// Handle specific actions
|
|
25
|
+
switch (action) {
|
|
26
|
+
case 'summary':
|
|
27
|
+
return handleProjectSummary(engine, input, sourcesUsed);
|
|
28
|
+
|
|
29
|
+
case 'happened':
|
|
30
|
+
return handleWhatHappened(engine, input, sourcesUsed);
|
|
31
|
+
|
|
32
|
+
case 'changed':
|
|
33
|
+
return handleWhatChanged(engine, input, sourcesUsed);
|
|
34
|
+
|
|
35
|
+
case 'architecture':
|
|
36
|
+
return handleArchitecture(engine, input, sourcesUsed);
|
|
37
|
+
|
|
38
|
+
case 'changelog':
|
|
39
|
+
return handleChangelog(engine, input, sourcesUsed);
|
|
40
|
+
|
|
41
|
+
case 'health':
|
|
42
|
+
return handleContextHealth(engine, input, sourcesUsed);
|
|
43
|
+
|
|
44
|
+
case 'patterns':
|
|
45
|
+
return handlePatterns(engine, input, sourcesUsed);
|
|
46
|
+
|
|
47
|
+
case 'stats':
|
|
48
|
+
return handleArchitectureStats(engine, input, sourcesUsed);
|
|
49
|
+
|
|
50
|
+
case 'undocumented':
|
|
51
|
+
return handleUndocumented(engine, input, sourcesUsed);
|
|
52
|
+
|
|
53
|
+
case 'critical':
|
|
54
|
+
return handleCriticalContext(engine, input, sourcesUsed);
|
|
55
|
+
|
|
56
|
+
case 'learning':
|
|
57
|
+
return handleLearningStats(engine, input, sourcesUsed);
|
|
58
|
+
|
|
59
|
+
default:
|
|
60
|
+
// Default to project summary
|
|
61
|
+
return handleProjectSummary(engine, input, sourcesUsed);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get project summary
|
|
67
|
+
* Enhanced with proactive context resurrection for "Welcome back!" experience
|
|
68
|
+
*/
|
|
69
|
+
async function handleProjectSummary(
|
|
70
|
+
engine: MemoryLayerEngine,
|
|
71
|
+
input: MemoryStatusInput,
|
|
72
|
+
sourcesUsed: string[]
|
|
73
|
+
): Promise<MemoryStatusResponse> {
|
|
74
|
+
sourcesUsed.push('get_project_summary');
|
|
75
|
+
|
|
76
|
+
const summary = engine.getProjectSummary();
|
|
77
|
+
|
|
78
|
+
// Get engine status for visibility
|
|
79
|
+
const engineStatus = engine.getEngineStatus();
|
|
80
|
+
|
|
81
|
+
// Also get learning stats for a fuller picture
|
|
82
|
+
sourcesUsed.push('get_learning_stats');
|
|
83
|
+
const learningStats = engine.getLearningStats();
|
|
84
|
+
|
|
85
|
+
// Get resurrection data for proactive "Welcome back!" messaging
|
|
86
|
+
sourcesUsed.push('resurrect_context');
|
|
87
|
+
const resurrection = engine.resurrectContext();
|
|
88
|
+
|
|
89
|
+
const response: MemoryStatusResponse = {
|
|
90
|
+
sources_used: sourcesUsed,
|
|
91
|
+
engine: {
|
|
92
|
+
status: engineStatus.status,
|
|
93
|
+
ready: engineStatus.ready,
|
|
94
|
+
indexing: engineStatus.indexing,
|
|
95
|
+
},
|
|
96
|
+
project: {
|
|
97
|
+
name: summary.name,
|
|
98
|
+
description: summary.description,
|
|
99
|
+
languages: summary.languages,
|
|
100
|
+
total_files: summary.totalFiles,
|
|
101
|
+
total_lines: summary.totalLines,
|
|
102
|
+
key_directories: summary.keyDirectories,
|
|
103
|
+
recent_decisions: summary.recentDecisions.map(d => ({
|
|
104
|
+
id: d.id,
|
|
105
|
+
title: d.title,
|
|
106
|
+
created_at: d.createdAt.toISOString(),
|
|
107
|
+
})),
|
|
108
|
+
},
|
|
109
|
+
learning: {
|
|
110
|
+
total_queries: learningStats.usageStats.totalQueries,
|
|
111
|
+
total_file_views: learningStats.usageStats.totalFileViews,
|
|
112
|
+
top_files: learningStats.usageStats.topFiles.slice(0, 5),
|
|
113
|
+
cache_size: learningStats.hotCacheStats.size,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Add resurrection data if there's meaningful context to resume
|
|
118
|
+
if (resurrection.activeFiles.length > 0 || resurrection.lastQueries.length > 0) {
|
|
119
|
+
(response as MemoryStatusResponse & { welcome_back?: unknown }).welcome_back = {
|
|
120
|
+
summary: resurrection.summary,
|
|
121
|
+
active_files: resurrection.activeFiles.slice(0, 5),
|
|
122
|
+
last_queries: resurrection.lastQueries.slice(0, 3),
|
|
123
|
+
possible_blocker: resurrection.possibleBlocker,
|
|
124
|
+
suggested_actions: resurrection.suggestedActions,
|
|
125
|
+
time_since_last_active: resurrection.timeSinceLastActive,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return response;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* What happened - activity summary
|
|
134
|
+
*/
|
|
135
|
+
async function handleWhatHappened(
|
|
136
|
+
engine: MemoryLayerEngine,
|
|
137
|
+
input: MemoryStatusInput,
|
|
138
|
+
sourcesUsed: string[]
|
|
139
|
+
): Promise<MemoryStatusResponse> {
|
|
140
|
+
sourcesUsed.push('what_happened');
|
|
141
|
+
|
|
142
|
+
const since = input.since || 'this week';
|
|
143
|
+
const result = await engine.whatHappened(since, input.file);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
sources_used: sourcesUsed,
|
|
147
|
+
activity: {
|
|
148
|
+
time_range: {
|
|
149
|
+
since: result.timeRange.since.toISOString(),
|
|
150
|
+
until: result.timeRange.until.toISOString(),
|
|
151
|
+
},
|
|
152
|
+
summary: result.summary,
|
|
153
|
+
changes_count: result.changes.length,
|
|
154
|
+
decisions_count: result.decisions.length,
|
|
155
|
+
files_affected: result.filesAffected.slice(0, 20),
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* What changed - file changes
|
|
162
|
+
*/
|
|
163
|
+
async function handleWhatChanged(
|
|
164
|
+
engine: MemoryLayerEngine,
|
|
165
|
+
input: MemoryStatusInput,
|
|
166
|
+
sourcesUsed: string[]
|
|
167
|
+
): Promise<MemoryStatusResponse> {
|
|
168
|
+
sourcesUsed.push('what_changed');
|
|
169
|
+
|
|
170
|
+
const since = input.since || 'this week';
|
|
171
|
+
const result = engine.whatChanged({
|
|
172
|
+
since,
|
|
173
|
+
file: input.file,
|
|
174
|
+
author: input.author,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
sources_used: sourcesUsed,
|
|
179
|
+
changes: {
|
|
180
|
+
period: result.period,
|
|
181
|
+
total_files: result.totalFiles,
|
|
182
|
+
total_lines_added: result.totalLinesAdded,
|
|
183
|
+
total_lines_removed: result.totalLinesRemoved,
|
|
184
|
+
by_author: result.byAuthor,
|
|
185
|
+
recent: result.changes.slice(0, 20).map(c => ({
|
|
186
|
+
file: c.file,
|
|
187
|
+
type: c.type,
|
|
188
|
+
lines_added: c.linesAdded,
|
|
189
|
+
lines_removed: c.linesRemoved,
|
|
190
|
+
author: c.author,
|
|
191
|
+
timestamp: c.timestamp.toISOString(),
|
|
192
|
+
})),
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Architecture overview
|
|
199
|
+
*/
|
|
200
|
+
async function handleArchitecture(
|
|
201
|
+
engine: MemoryLayerEngine,
|
|
202
|
+
input: MemoryStatusInput,
|
|
203
|
+
sourcesUsed: string[]
|
|
204
|
+
): Promise<MemoryStatusResponse> {
|
|
205
|
+
sourcesUsed.push('get_architecture');
|
|
206
|
+
|
|
207
|
+
const arch = await engine.getArchitecture();
|
|
208
|
+
|
|
209
|
+
// Also get stats
|
|
210
|
+
sourcesUsed.push('get_architecture_stats');
|
|
211
|
+
const stats = engine.getArchitectureStats();
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
sources_used: sourcesUsed,
|
|
215
|
+
architecture: {
|
|
216
|
+
name: arch.name,
|
|
217
|
+
description: arch.description,
|
|
218
|
+
diagram: arch.diagram,
|
|
219
|
+
layers: arch.layers.map(l => ({
|
|
220
|
+
name: l.name,
|
|
221
|
+
directory: l.directory,
|
|
222
|
+
files_count: l.files.length,
|
|
223
|
+
purpose: l.purpose,
|
|
224
|
+
})),
|
|
225
|
+
data_flow: arch.dataFlow,
|
|
226
|
+
key_components: arch.keyComponents.map(c => ({
|
|
227
|
+
name: c.name,
|
|
228
|
+
file: c.file,
|
|
229
|
+
purpose: c.purpose,
|
|
230
|
+
})),
|
|
231
|
+
},
|
|
232
|
+
stats: {
|
|
233
|
+
patterns_total: stats.patterns.total,
|
|
234
|
+
functions_total: stats.functions.total,
|
|
235
|
+
functions_exported: stats.functions.exported,
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Changelog
|
|
242
|
+
*/
|
|
243
|
+
async function handleChangelog(
|
|
244
|
+
engine: MemoryLayerEngine,
|
|
245
|
+
input: MemoryStatusInput,
|
|
246
|
+
sourcesUsed: string[]
|
|
247
|
+
): Promise<MemoryStatusResponse> {
|
|
248
|
+
sourcesUsed.push('get_changelog');
|
|
249
|
+
|
|
250
|
+
const changelogs = await engine.getChangelog({
|
|
251
|
+
since: input.since,
|
|
252
|
+
groupBy: input.group_by,
|
|
253
|
+
includeDecisions: input.include_decisions,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
sources_used: sourcesUsed,
|
|
258
|
+
changelog: changelogs.map(day => ({
|
|
259
|
+
date: day.date.toISOString().split('T')[0] || day.date.toISOString(),
|
|
260
|
+
summary: day.summary,
|
|
261
|
+
features: day.features.length,
|
|
262
|
+
fixes: day.fixes.length,
|
|
263
|
+
refactors: day.refactors.length,
|
|
264
|
+
})),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Context health
|
|
270
|
+
*/
|
|
271
|
+
async function handleContextHealth(
|
|
272
|
+
engine: MemoryLayerEngine,
|
|
273
|
+
input: MemoryStatusInput,
|
|
274
|
+
sourcesUsed: string[]
|
|
275
|
+
): Promise<MemoryStatusResponse> {
|
|
276
|
+
sourcesUsed.push('get_context_health');
|
|
277
|
+
|
|
278
|
+
const health = engine.getContextHealth();
|
|
279
|
+
const drift = engine.detectDrift();
|
|
280
|
+
|
|
281
|
+
// Also get critical context
|
|
282
|
+
sourcesUsed.push('get_critical_context');
|
|
283
|
+
const criticalItems = engine.getCriticalContext();
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
sources_used: sourcesUsed,
|
|
287
|
+
health: {
|
|
288
|
+
health: health.health,
|
|
289
|
+
tokens_used: health.tokensUsed,
|
|
290
|
+
tokens_limit: health.tokensLimit,
|
|
291
|
+
utilization: `${health.utilizationPercent}%`,
|
|
292
|
+
drift_detected: health.driftDetected,
|
|
293
|
+
compaction_needed: health.compactionNeeded,
|
|
294
|
+
suggestions: health.suggestions,
|
|
295
|
+
},
|
|
296
|
+
critical: {
|
|
297
|
+
total: criticalItems.length,
|
|
298
|
+
by_type: {
|
|
299
|
+
decision: criticalItems.filter(i => i.type === 'decision').length,
|
|
300
|
+
requirement: criticalItems.filter(i => i.type === 'requirement').length,
|
|
301
|
+
instruction: criticalItems.filter(i => i.type === 'instruction').length,
|
|
302
|
+
custom: criticalItems.filter(i => i.type === 'custom').length,
|
|
303
|
+
},
|
|
304
|
+
items: criticalItems.slice(0, 10).map(item => ({
|
|
305
|
+
id: item.id,
|
|
306
|
+
type: item.type,
|
|
307
|
+
content: item.content.slice(0, 100),
|
|
308
|
+
reason: item.reason,
|
|
309
|
+
})),
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Pattern list
|
|
316
|
+
*/
|
|
317
|
+
async function handlePatterns(
|
|
318
|
+
engine: MemoryLayerEngine,
|
|
319
|
+
input: MemoryStatusInput,
|
|
320
|
+
sourcesUsed: string[]
|
|
321
|
+
): Promise<MemoryStatusResponse> {
|
|
322
|
+
sourcesUsed.push('list_patterns');
|
|
323
|
+
|
|
324
|
+
const patterns = engine.listPatterns(input.category);
|
|
325
|
+
|
|
326
|
+
// Group by category
|
|
327
|
+
const byCategory: Record<string, number> = {};
|
|
328
|
+
for (const pattern of patterns) {
|
|
329
|
+
byCategory[pattern.category] = (byCategory[pattern.category] || 0) + 1;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
sources_used: sourcesUsed,
|
|
334
|
+
patterns: {
|
|
335
|
+
total: patterns.length,
|
|
336
|
+
by_category: byCategory,
|
|
337
|
+
patterns: patterns.slice(0, 20).map(p => ({
|
|
338
|
+
id: p.id,
|
|
339
|
+
name: p.name,
|
|
340
|
+
category: p.category,
|
|
341
|
+
usage_count: p.usageCount,
|
|
342
|
+
})),
|
|
343
|
+
},
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Architecture stats
|
|
349
|
+
*/
|
|
350
|
+
async function handleArchitectureStats(
|
|
351
|
+
engine: MemoryLayerEngine,
|
|
352
|
+
input: MemoryStatusInput,
|
|
353
|
+
sourcesUsed: string[]
|
|
354
|
+
): Promise<MemoryStatusResponse> {
|
|
355
|
+
sourcesUsed.push('get_architecture_stats');
|
|
356
|
+
|
|
357
|
+
const stats = engine.getArchitectureStats();
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
sources_used: sourcesUsed,
|
|
361
|
+
stats: {
|
|
362
|
+
patterns_total: stats.patterns.total,
|
|
363
|
+
functions_total: stats.functions.total,
|
|
364
|
+
functions_exported: stats.functions.exported,
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Find undocumented code
|
|
371
|
+
*/
|
|
372
|
+
async function handleUndocumented(
|
|
373
|
+
engine: MemoryLayerEngine,
|
|
374
|
+
input: MemoryStatusInput,
|
|
375
|
+
sourcesUsed: string[]
|
|
376
|
+
): Promise<MemoryStatusResponse> {
|
|
377
|
+
sourcesUsed.push('find_undocumented');
|
|
378
|
+
|
|
379
|
+
const items = await engine.findUndocumented({});
|
|
380
|
+
|
|
381
|
+
// Group by importance
|
|
382
|
+
const byImportance: Record<string, number> = {
|
|
383
|
+
high: 0,
|
|
384
|
+
medium: 0,
|
|
385
|
+
low: 0,
|
|
386
|
+
};
|
|
387
|
+
for (const item of items) {
|
|
388
|
+
byImportance[item.importance] = (byImportance[item.importance] || 0) + 1;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Also validate docs
|
|
392
|
+
sourcesUsed.push('validate_docs');
|
|
393
|
+
const docsResult = await engine.validateDocs();
|
|
394
|
+
|
|
395
|
+
return {
|
|
396
|
+
sources_used: sourcesUsed,
|
|
397
|
+
undocumented: {
|
|
398
|
+
total: items.length,
|
|
399
|
+
by_importance: byImportance,
|
|
400
|
+
items: items.slice(0, 30).map(i => ({
|
|
401
|
+
file: i.file,
|
|
402
|
+
symbol: i.symbol,
|
|
403
|
+
type: i.type,
|
|
404
|
+
importance: i.importance,
|
|
405
|
+
})),
|
|
406
|
+
},
|
|
407
|
+
docs: {
|
|
408
|
+
is_valid: docsResult.isValid,
|
|
409
|
+
score: docsResult.score,
|
|
410
|
+
outdated_count: docsResult.outdatedDocs.length,
|
|
411
|
+
undocumented_count: docsResult.undocumentedCode.length,
|
|
412
|
+
suggestions: docsResult.suggestions.slice(0, 5).map(s => ({
|
|
413
|
+
file: s.file,
|
|
414
|
+
suggestion: s.suggestion,
|
|
415
|
+
priority: s.priority,
|
|
416
|
+
})),
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Critical context items
|
|
423
|
+
*/
|
|
424
|
+
async function handleCriticalContext(
|
|
425
|
+
engine: MemoryLayerEngine,
|
|
426
|
+
input: MemoryStatusInput,
|
|
427
|
+
sourcesUsed: string[]
|
|
428
|
+
): Promise<MemoryStatusResponse> {
|
|
429
|
+
sourcesUsed.push('get_critical_context');
|
|
430
|
+
|
|
431
|
+
const items = engine.getCriticalContext();
|
|
432
|
+
|
|
433
|
+
// Group by type
|
|
434
|
+
const byType: Record<string, number> = {
|
|
435
|
+
decision: 0,
|
|
436
|
+
requirement: 0,
|
|
437
|
+
instruction: 0,
|
|
438
|
+
custom: 0,
|
|
439
|
+
};
|
|
440
|
+
for (const item of items) {
|
|
441
|
+
byType[item.type] = (byType[item.type] || 0) + 1;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return {
|
|
445
|
+
sources_used: sourcesUsed,
|
|
446
|
+
critical: {
|
|
447
|
+
total: items.length,
|
|
448
|
+
by_type: byType,
|
|
449
|
+
items: items.map(item => ({
|
|
450
|
+
id: item.id,
|
|
451
|
+
type: item.type,
|
|
452
|
+
content: item.content,
|
|
453
|
+
reason: item.reason,
|
|
454
|
+
})),
|
|
455
|
+
},
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Learning stats - enhanced with context resurrection for seamless session continuity
|
|
461
|
+
*/
|
|
462
|
+
async function handleLearningStats(
|
|
463
|
+
engine: MemoryLayerEngine,
|
|
464
|
+
input: MemoryStatusInput,
|
|
465
|
+
sourcesUsed: string[]
|
|
466
|
+
): Promise<MemoryStatusResponse> {
|
|
467
|
+
sourcesUsed.push('get_learning_stats', 'resurrect_context');
|
|
468
|
+
|
|
469
|
+
const stats = engine.getLearningStats();
|
|
470
|
+
|
|
471
|
+
// Get context resurrection for session continuity
|
|
472
|
+
const resurrection = engine.resurrectContext();
|
|
473
|
+
const resurrectableContexts = engine.getResurrectableContexts();
|
|
474
|
+
|
|
475
|
+
// Get déjà vu stats
|
|
476
|
+
const dejaVuStats = engine.getDejaVuStats();
|
|
477
|
+
|
|
478
|
+
const response: MemoryStatusResponse = {
|
|
479
|
+
sources_used: sourcesUsed,
|
|
480
|
+
learning: {
|
|
481
|
+
total_queries: stats.usageStats.totalQueries,
|
|
482
|
+
total_file_views: stats.usageStats.totalFileViews,
|
|
483
|
+
top_files: stats.usageStats.topFiles,
|
|
484
|
+
cache_size: stats.hotCacheStats.size,
|
|
485
|
+
},
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// Add resurrection data for "Welcome back!" experience
|
|
489
|
+
(response as MemoryStatusResponse & { resurrection?: unknown }).resurrection = {
|
|
490
|
+
summary: resurrection.summary,
|
|
491
|
+
active_files: resurrection.activeFiles,
|
|
492
|
+
last_queries: resurrection.lastQueries,
|
|
493
|
+
possible_blocker: resurrection.possibleBlocker,
|
|
494
|
+
suggested_actions: resurrection.suggestedActions,
|
|
495
|
+
time_since_last_active: resurrection.timeSinceLastActive,
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
// Add resurrectable contexts
|
|
499
|
+
if (resurrectableContexts.length > 0) {
|
|
500
|
+
(response as MemoryStatusResponse & { resurrectable_contexts?: unknown }).resurrectable_contexts =
|
|
501
|
+
resurrectableContexts.map(c => ({
|
|
502
|
+
id: c.id,
|
|
503
|
+
name: c.name,
|
|
504
|
+
last_active: c.lastActive.toISOString(),
|
|
505
|
+
summary: c.summary,
|
|
506
|
+
}));
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Add déjà vu stats
|
|
510
|
+
(response as MemoryStatusResponse & { deja_vu_stats?: unknown }).deja_vu_stats = {
|
|
511
|
+
total_queries: dejaVuStats.totalQueries,
|
|
512
|
+
useful_queries: dejaVuStats.usefulQueries,
|
|
513
|
+
avg_usefulness: Math.round(dejaVuStats.avgUsefulness * 100) / 100,
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
return response;
|
|
517
|
+
}
|