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,262 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { mkdirSync, existsSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
|
|
5
|
+
export function initializeDatabase(dbPath: string): Database.Database {
|
|
6
|
+
// Ensure directory exists
|
|
7
|
+
const dir = dirname(dbPath);
|
|
8
|
+
if (!existsSync(dir)) {
|
|
9
|
+
mkdirSync(dir, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const db = new Database(dbPath);
|
|
13
|
+
|
|
14
|
+
// Enable WAL mode for better concurrent access
|
|
15
|
+
db.pragma('journal_mode = WAL');
|
|
16
|
+
|
|
17
|
+
// Create tables
|
|
18
|
+
db.exec(`
|
|
19
|
+
-- Files table: stores file metadata
|
|
20
|
+
CREATE TABLE IF NOT EXISTS files (
|
|
21
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
22
|
+
path TEXT UNIQUE NOT NULL,
|
|
23
|
+
content_hash TEXT NOT NULL,
|
|
24
|
+
preview TEXT,
|
|
25
|
+
language TEXT,
|
|
26
|
+
size_bytes INTEGER,
|
|
27
|
+
line_count INTEGER,
|
|
28
|
+
last_modified INTEGER,
|
|
29
|
+
indexed_at INTEGER DEFAULT (unixepoch())
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
-- Embeddings table: stores file embeddings as binary blobs
|
|
33
|
+
CREATE TABLE IF NOT EXISTS embeddings (
|
|
34
|
+
file_id INTEGER PRIMARY KEY REFERENCES files(id) ON DELETE CASCADE,
|
|
35
|
+
embedding BLOB NOT NULL,
|
|
36
|
+
dimension INTEGER NOT NULL
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
-- Dependencies table: tracks file relationships
|
|
40
|
+
CREATE TABLE IF NOT EXISTS dependencies (
|
|
41
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
42
|
+
source_file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
|
|
43
|
+
target_file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
|
|
44
|
+
relationship TEXT NOT NULL,
|
|
45
|
+
UNIQUE(source_file_id, target_file_id, relationship)
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
-- Decisions table: stores architectural decisions
|
|
49
|
+
CREATE TABLE IF NOT EXISTS decisions (
|
|
50
|
+
id TEXT PRIMARY KEY,
|
|
51
|
+
title TEXT NOT NULL,
|
|
52
|
+
description TEXT NOT NULL,
|
|
53
|
+
files TEXT,
|
|
54
|
+
tags TEXT,
|
|
55
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
56
|
+
embedding BLOB,
|
|
57
|
+
-- Phase 4: Team features
|
|
58
|
+
author TEXT,
|
|
59
|
+
status TEXT DEFAULT 'accepted',
|
|
60
|
+
superseded_by TEXT
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
-- Sessions table: tracks session history
|
|
64
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
65
|
+
id TEXT PRIMARY KEY,
|
|
66
|
+
start_time INTEGER NOT NULL,
|
|
67
|
+
end_time INTEGER,
|
|
68
|
+
files_viewed TEXT,
|
|
69
|
+
summary TEXT
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
-- Project summary table
|
|
73
|
+
CREATE TABLE IF NOT EXISTS project_summary (
|
|
74
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
75
|
+
name TEXT,
|
|
76
|
+
description TEXT,
|
|
77
|
+
languages TEXT,
|
|
78
|
+
key_directories TEXT,
|
|
79
|
+
architecture_notes TEXT,
|
|
80
|
+
updated_at INTEGER DEFAULT (unixepoch())
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
-- Phase 2: Symbols table - stores code symbols (functions, classes, etc.)
|
|
84
|
+
CREATE TABLE IF NOT EXISTS symbols (
|
|
85
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
86
|
+
file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
87
|
+
kind TEXT NOT NULL,
|
|
88
|
+
name TEXT NOT NULL,
|
|
89
|
+
signature TEXT,
|
|
90
|
+
docstring TEXT,
|
|
91
|
+
line_start INTEGER NOT NULL,
|
|
92
|
+
line_end INTEGER NOT NULL,
|
|
93
|
+
exported INTEGER NOT NULL DEFAULT 0
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
-- Phase 2: Imports table - tracks what each file imports
|
|
97
|
+
CREATE TABLE IF NOT EXISTS imports (
|
|
98
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
99
|
+
file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
100
|
+
imported_from TEXT NOT NULL,
|
|
101
|
+
imported_symbols TEXT NOT NULL,
|
|
102
|
+
is_default INTEGER NOT NULL DEFAULT 0,
|
|
103
|
+
is_namespace INTEGER NOT NULL DEFAULT 0,
|
|
104
|
+
line_number INTEGER NOT NULL
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
-- Phase 2: Exports table - tracks what each file exports
|
|
108
|
+
CREATE TABLE IF NOT EXISTS exports (
|
|
109
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
110
|
+
file_id INTEGER NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
|
111
|
+
exported_name TEXT NOT NULL,
|
|
112
|
+
local_name TEXT,
|
|
113
|
+
is_default INTEGER NOT NULL DEFAULT 0,
|
|
114
|
+
line_number INTEGER NOT NULL
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
-- Create indexes for common queries
|
|
118
|
+
CREATE INDEX IF NOT EXISTS idx_files_path ON files(path);
|
|
119
|
+
CREATE INDEX IF NOT EXISTS idx_files_language ON files(language);
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_files_last_modified ON files(last_modified);
|
|
121
|
+
CREATE INDEX IF NOT EXISTS idx_dependencies_source ON dependencies(source_file_id);
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_dependencies_target ON dependencies(target_file_id);
|
|
123
|
+
CREATE INDEX IF NOT EXISTS idx_decisions_created_at ON decisions(created_at);
|
|
124
|
+
|
|
125
|
+
-- Phase 2: Symbol indexes
|
|
126
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_file_id ON symbols(file_id);
|
|
127
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols(name);
|
|
128
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_kind ON symbols(kind);
|
|
129
|
+
CREATE INDEX IF NOT EXISTS idx_imports_file_id ON imports(file_id);
|
|
130
|
+
CREATE INDEX IF NOT EXISTS idx_imports_from ON imports(imported_from);
|
|
131
|
+
CREATE INDEX IF NOT EXISTS idx_exports_file_id ON exports(file_id);
|
|
132
|
+
CREATE INDEX IF NOT EXISTS idx_exports_name ON exports(exported_name);
|
|
133
|
+
|
|
134
|
+
-- Phase 3: Usage tracking for learning
|
|
135
|
+
CREATE TABLE IF NOT EXISTS usage_events (
|
|
136
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
137
|
+
event_type TEXT NOT NULL,
|
|
138
|
+
file_path TEXT,
|
|
139
|
+
query TEXT,
|
|
140
|
+
context_used INTEGER DEFAULT 0,
|
|
141
|
+
timestamp INTEGER DEFAULT (unixepoch())
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
-- Phase 3: File access frequency for personalized ranking
|
|
145
|
+
CREATE TABLE IF NOT EXISTS file_access (
|
|
146
|
+
file_id INTEGER PRIMARY KEY REFERENCES files(id) ON DELETE CASCADE,
|
|
147
|
+
access_count INTEGER DEFAULT 0,
|
|
148
|
+
last_accessed INTEGER DEFAULT (unixepoch()),
|
|
149
|
+
relevance_score REAL DEFAULT 0.5
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
-- Phase 3: Query patterns for prediction
|
|
153
|
+
CREATE TABLE IF NOT EXISTS query_patterns (
|
|
154
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
155
|
+
query_hash TEXT UNIQUE NOT NULL,
|
|
156
|
+
query_text TEXT NOT NULL,
|
|
157
|
+
result_files TEXT,
|
|
158
|
+
hit_count INTEGER DEFAULT 1,
|
|
159
|
+
avg_usefulness REAL DEFAULT 0.5,
|
|
160
|
+
last_used INTEGER DEFAULT (unixepoch())
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
-- Phase 3: File summaries for compression
|
|
164
|
+
CREATE TABLE IF NOT EXISTS file_summaries (
|
|
165
|
+
file_id INTEGER PRIMARY KEY REFERENCES files(id) ON DELETE CASCADE,
|
|
166
|
+
summary TEXT NOT NULL,
|
|
167
|
+
summary_tokens INTEGER,
|
|
168
|
+
generated_at INTEGER DEFAULT (unixepoch())
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
-- Phase 3: Indexes for usage tracking
|
|
172
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_timestamp ON usage_events(timestamp);
|
|
173
|
+
CREATE INDEX IF NOT EXISTS idx_usage_events_file ON usage_events(file_path);
|
|
174
|
+
CREATE INDEX IF NOT EXISTS idx_file_access_count ON file_access(access_count DESC);
|
|
175
|
+
CREATE INDEX IF NOT EXISTS idx_query_patterns_hash ON query_patterns(query_hash);
|
|
176
|
+
|
|
177
|
+
-- Phase 6: Living Documentation tables
|
|
178
|
+
CREATE TABLE IF NOT EXISTS documentation (
|
|
179
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
180
|
+
file_id INTEGER REFERENCES files(id) ON DELETE CASCADE,
|
|
181
|
+
doc_type TEXT NOT NULL,
|
|
182
|
+
content TEXT NOT NULL,
|
|
183
|
+
generated_at INTEGER DEFAULT (unixepoch()),
|
|
184
|
+
UNIQUE(file_id, doc_type)
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
CREATE TABLE IF NOT EXISTS activity_log (
|
|
188
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
189
|
+
timestamp INTEGER DEFAULT (unixepoch()),
|
|
190
|
+
activity_type TEXT NOT NULL,
|
|
191
|
+
description TEXT,
|
|
192
|
+
file_path TEXT,
|
|
193
|
+
metadata TEXT,
|
|
194
|
+
commit_hash TEXT
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
CREATE INDEX IF NOT EXISTS idx_activity_timestamp ON activity_log(timestamp);
|
|
198
|
+
CREATE INDEX IF NOT EXISTS idx_activity_type ON activity_log(activity_type);
|
|
199
|
+
CREATE INDEX IF NOT EXISTS idx_documentation_file ON documentation(file_id);
|
|
200
|
+
|
|
201
|
+
-- Phase 7: Context Rot Prevention tables
|
|
202
|
+
CREATE TABLE IF NOT EXISTS critical_context (
|
|
203
|
+
id TEXT PRIMARY KEY,
|
|
204
|
+
type TEXT NOT NULL,
|
|
205
|
+
content TEXT NOT NULL,
|
|
206
|
+
reason TEXT,
|
|
207
|
+
source TEXT,
|
|
208
|
+
never_compress INTEGER DEFAULT 1,
|
|
209
|
+
created_at INTEGER DEFAULT (unixepoch())
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
CREATE TABLE IF NOT EXISTS context_health_history (
|
|
213
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
214
|
+
timestamp INTEGER DEFAULT (unixepoch()),
|
|
215
|
+
tokens_used INTEGER,
|
|
216
|
+
tokens_limit INTEGER,
|
|
217
|
+
utilization_percent REAL,
|
|
218
|
+
drift_score REAL,
|
|
219
|
+
relevance_score REAL,
|
|
220
|
+
health TEXT,
|
|
221
|
+
compaction_triggered INTEGER DEFAULT 0
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
CREATE INDEX IF NOT EXISTS idx_critical_context_type ON critical_context(type);
|
|
225
|
+
CREATE INDEX IF NOT EXISTS idx_critical_context_created ON critical_context(created_at);
|
|
226
|
+
CREATE INDEX IF NOT EXISTS idx_context_health_timestamp ON context_health_history(timestamp);
|
|
227
|
+
|
|
228
|
+
-- Phase 11: Test-Aware Suggestions tables
|
|
229
|
+
CREATE TABLE IF NOT EXISTS test_index (
|
|
230
|
+
id TEXT PRIMARY KEY,
|
|
231
|
+
file_path TEXT NOT NULL,
|
|
232
|
+
test_name TEXT NOT NULL,
|
|
233
|
+
describes TEXT,
|
|
234
|
+
covers_files TEXT, -- JSON array
|
|
235
|
+
covers_functions TEXT, -- JSON array
|
|
236
|
+
assertions TEXT, -- JSON array
|
|
237
|
+
line_start INTEGER,
|
|
238
|
+
line_end INTEGER,
|
|
239
|
+
last_status TEXT,
|
|
240
|
+
last_run INTEGER,
|
|
241
|
+
indexed_at INTEGER DEFAULT (unixepoch()),
|
|
242
|
+
UNIQUE(file_path, test_name)
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
CREATE TABLE IF NOT EXISTS test_config (
|
|
246
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
247
|
+
framework TEXT NOT NULL,
|
|
248
|
+
test_patterns TEXT, -- JSON array of glob patterns
|
|
249
|
+
last_indexed INTEGER
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
CREATE INDEX IF NOT EXISTS idx_test_index_file ON test_index(file_path);
|
|
253
|
+
CREATE INDEX IF NOT EXISTS idx_test_index_name ON test_index(test_name);
|
|
254
|
+
CREATE INDEX IF NOT EXISTS idx_test_covers_files ON test_index(covers_files);
|
|
255
|
+
`);
|
|
256
|
+
|
|
257
|
+
return db;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export function closeDatabase(db: Database.Database): void {
|
|
261
|
+
db.close();
|
|
262
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
|
|
2
|
+
import { dirname, join } from 'path';
|
|
3
|
+
import type { Tier1Context, Decision, ActiveFile, ContextSnippet, Session } from '../types/index.js';
|
|
4
|
+
|
|
5
|
+
const MAX_RECENT_DECISIONS = 20;
|
|
6
|
+
const MAX_IMMEDIATE_CONTEXT = 10;
|
|
7
|
+
const MAX_FILES_VIEWED = 50;
|
|
8
|
+
|
|
9
|
+
export class Tier1Storage {
|
|
10
|
+
private filePath: string;
|
|
11
|
+
private context: Tier1Context;
|
|
12
|
+
|
|
13
|
+
constructor(dataDir: string) {
|
|
14
|
+
this.filePath = join(dataDir, 'tier1.json');
|
|
15
|
+
this.context = this.load();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private getDefaultContext(): Tier1Context {
|
|
19
|
+
return {
|
|
20
|
+
activeFile: null,
|
|
21
|
+
recentDecisions: [],
|
|
22
|
+
session: {
|
|
23
|
+
startTime: new Date(),
|
|
24
|
+
filesViewed: [],
|
|
25
|
+
currentGoal: undefined
|
|
26
|
+
},
|
|
27
|
+
immediateContext: []
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
load(): Tier1Context {
|
|
32
|
+
try {
|
|
33
|
+
if (existsSync(this.filePath)) {
|
|
34
|
+
const data = JSON.parse(readFileSync(this.filePath, 'utf-8'));
|
|
35
|
+
// Parse dates
|
|
36
|
+
if (data.session?.startTime) {
|
|
37
|
+
data.session.startTime = new Date(data.session.startTime);
|
|
38
|
+
}
|
|
39
|
+
if (data.recentDecisions) {
|
|
40
|
+
data.recentDecisions = data.recentDecisions.map((d: Decision) => ({
|
|
41
|
+
...d,
|
|
42
|
+
createdAt: new Date(d.createdAt)
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
if (data.immediateContext) {
|
|
46
|
+
data.immediateContext = data.immediateContext.map((c: ContextSnippet) => ({
|
|
47
|
+
...c,
|
|
48
|
+
timestamp: new Date(c.timestamp)
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
return data;
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error('Error loading tier1 context:', error);
|
|
55
|
+
}
|
|
56
|
+
return this.getDefaultContext();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
save(): void {
|
|
60
|
+
try {
|
|
61
|
+
const dir = dirname(this.filePath);
|
|
62
|
+
if (!existsSync(dir)) {
|
|
63
|
+
mkdirSync(dir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
writeFileSync(this.filePath, JSON.stringify(this.context, null, 2));
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error('Error saving tier1 context:', error);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getContext(): Tier1Context {
|
|
72
|
+
return this.context;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
setActiveFile(file: ActiveFile | null): void {
|
|
76
|
+
this.context.activeFile = file;
|
|
77
|
+
|
|
78
|
+
if (file && !this.context.session.filesViewed.includes(file.path)) {
|
|
79
|
+
this.context.session.filesViewed.unshift(file.path);
|
|
80
|
+
// Limit files viewed list
|
|
81
|
+
if (this.context.session.filesViewed.length > MAX_FILES_VIEWED) {
|
|
82
|
+
this.context.session.filesViewed = this.context.session.filesViewed.slice(0, MAX_FILES_VIEWED);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.save();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
addDecision(decision: Decision): void {
|
|
90
|
+
// Remove existing decision with same ID if present
|
|
91
|
+
this.context.recentDecisions = this.context.recentDecisions.filter(d => d.id !== decision.id);
|
|
92
|
+
|
|
93
|
+
// Add new decision at the beginning
|
|
94
|
+
this.context.recentDecisions.unshift(decision);
|
|
95
|
+
|
|
96
|
+
// Limit recent decisions
|
|
97
|
+
if (this.context.recentDecisions.length > MAX_RECENT_DECISIONS) {
|
|
98
|
+
this.context.recentDecisions = this.context.recentDecisions.slice(0, MAX_RECENT_DECISIONS);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.save();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
getRecentDecisions(limit: number = 10): Decision[] {
|
|
105
|
+
return this.context.recentDecisions.slice(0, limit);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
addImmediateContext(snippet: ContextSnippet): void {
|
|
109
|
+
this.context.immediateContext.unshift(snippet);
|
|
110
|
+
|
|
111
|
+
if (this.context.immediateContext.length > MAX_IMMEDIATE_CONTEXT) {
|
|
112
|
+
this.context.immediateContext = this.context.immediateContext.slice(0, MAX_IMMEDIATE_CONTEXT);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
this.save();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
setCurrentGoal(goal: string | undefined): void {
|
|
119
|
+
this.context.session.currentGoal = goal;
|
|
120
|
+
this.save();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
startNewSession(): void {
|
|
124
|
+
this.context = this.getDefaultContext();
|
|
125
|
+
this.save();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
getSession(): Session {
|
|
129
|
+
return this.context.session;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
getFilesViewed(): string[] {
|
|
133
|
+
return this.context.session.filesViewed;
|
|
134
|
+
}
|
|
135
|
+
}
|