gencode-ai 0.2.0 → 0.3.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/dist/agent/agent.d.ts +9 -2
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +37 -8
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/types.d.ts +5 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/cli/components/App.d.ts.map +1 -1
- package/dist/cli/components/App.js +15 -9
- package/dist/cli/components/App.js.map +1 -1
- package/dist/cli/components/Messages.js +1 -1
- package/dist/cli/components/Messages.js.map +1 -1
- package/dist/cli/components/ModelSelector.d.ts +4 -3
- package/dist/cli/components/ModelSelector.d.ts.map +1 -1
- package/dist/cli/components/ModelSelector.js +54 -37
- package/dist/cli/components/ModelSelector.js.map +1 -1
- package/dist/cli/components/ProviderManager.d.ts +2 -2
- package/dist/cli/components/ProviderManager.d.ts.map +1 -1
- package/dist/cli/components/ProviderManager.js +137 -156
- package/dist/cli/components/ProviderManager.js.map +1 -1
- package/dist/cli/index.js +30 -13
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/levels.d.ts +5 -5
- package/dist/config/levels.d.ts.map +1 -1
- package/dist/config/levels.js +20 -20
- package/dist/config/levels.js.map +1 -1
- package/dist/config/merger.js +1 -1
- package/dist/config/merger.js.map +1 -1
- package/dist/config/providers-config.d.ts +8 -5
- package/dist/config/providers-config.d.ts.map +1 -1
- package/dist/config/providers-config.js +19 -22
- package/dist/config/providers-config.js.map +1 -1
- package/dist/config/test-utils.d.ts +2 -2
- package/dist/config/test-utils.d.ts.map +1 -1
- package/dist/config/test-utils.js +4 -4
- package/dist/config/test-utils.js.map +1 -1
- package/dist/config/types.d.ts +23 -17
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +14 -14
- package/dist/config/types.js.map +1 -1
- package/dist/memory/memory-manager.d.ts +25 -12
- package/dist/memory/memory-manager.d.ts.map +1 -1
- package/dist/memory/memory-manager.js +241 -112
- package/dist/memory/memory-manager.js.map +1 -1
- package/dist/memory/test-utils.d.ts +1 -1
- package/dist/memory/test-utils.d.ts.map +1 -1
- package/dist/memory/test-utils.js +3 -3
- package/dist/memory/test-utils.js.map +1 -1
- package/dist/memory/types.d.ts +20 -10
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +13 -13
- package/dist/memory/types.js.map +1 -1
- package/dist/migration/migrate.d.ts +24 -0
- package/dist/migration/migrate.d.ts.map +1 -0
- package/dist/migration/migrate.js +164 -0
- package/dist/migration/migrate.js.map +1 -0
- package/dist/permissions/persistence.d.ts +2 -2
- package/dist/permissions/persistence.js +4 -4
- package/dist/permissions/persistence.js.map +1 -1
- package/dist/planning/plan-file.d.ts +1 -1
- package/dist/planning/plan-file.js +2 -2
- package/dist/planning/plan-file.js.map +1 -1
- package/dist/prompts/index.d.ts +5 -4
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +11 -8
- package/dist/prompts/index.js.map +1 -1
- package/dist/providers/anthropic.d.ts +2 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +7 -0
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/gemini.d.ts +2 -1
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +7 -0
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/index.d.ts +20 -10
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +48 -24
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai.d.ts +2 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +7 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/registry.d.ts +48 -34
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +72 -88
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/store.d.ts +43 -17
- package/dist/providers/store.d.ts.map +1 -1
- package/dist/providers/store.js +112 -19
- package/dist/providers/store.js.map +1 -1
- package/dist/providers/types.d.ts +23 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/providers/vertex-ai.d.ts +15 -7
- package/dist/providers/vertex-ai.d.ts.map +1 -1
- package/dist/providers/vertex-ai.js +46 -13
- package/dist/providers/vertex-ai.js.map +1 -1
- package/dist/session/types.js +1 -1
- package/dist/session/types.js.map +1 -1
- package/docs/config-system-comparison.md +50 -50
- package/docs/cost-tracking-comparison.md +2 -2
- package/docs/memory-system.md +124 -31
- package/docs/permissions.md +2 -2
- package/docs/proposals/0006-memory-system.md +4 -4
- package/docs/proposals/0008-checkpointing.md +109 -2
- package/docs/proposals/0011-custom-commands.md +2 -1
- package/docs/proposals/0021-skills-system.md +2 -1
- package/docs/proposals/0023-permission-enhancements.md +2 -2
- package/docs/proposals/0033-enterprise-deployment.md +1 -1
- package/docs/proposals/0041-configuration-system.md +17 -19
- package/docs/proposals/0042-prompt-optimization.md +17 -9
- package/docs/proposals/README.md +5 -5
- package/docs/providers.md +94 -9
- package/package.json +3 -2
- package/scripts/migrate.ts +449 -0
- package/src/agent/agent.ts +51 -9
- package/src/agent/types.ts +5 -1
- package/src/cli/components/App.tsx +17 -8
- package/src/cli/components/Messages.tsx +1 -1
- package/src/cli/components/ModelSelector.tsx +62 -43
- package/src/cli/components/ProviderManager.tsx +278 -323
- package/src/cli/index.tsx +36 -17
- package/src/config/index.ts +5 -3
- package/src/config/levels.test.ts +22 -22
- package/src/config/levels.ts +22 -22
- package/src/config/loader.test.ts +14 -14
- package/src/config/manager.test.ts +19 -19
- package/src/config/merger.test.ts +23 -23
- package/src/config/merger.ts +1 -1
- package/src/config/providers-config.ts +23 -21
- package/src/config/test-utils.ts +6 -6
- package/src/config/types.ts +30 -20
- package/src/memory/memory-manager.test.ts +242 -24
- package/src/memory/memory-manager.ts +270 -141
- package/src/memory/test-utils.ts +4 -4
- package/src/memory/types.ts +28 -17
- package/src/permissions/persistence.ts +4 -4
- package/src/planning/plan-file.ts +2 -2
- package/src/prompts/index.ts +13 -9
- package/src/providers/anthropic.ts +9 -0
- package/src/providers/gemini.ts +9 -0
- package/src/providers/index.ts +76 -33
- package/src/providers/openai.ts +9 -0
- package/src/providers/registry.ts +116 -111
- package/src/providers/store.ts +130 -28
- package/src/providers/types.ts +33 -1
- package/src/providers/vertex-ai.ts +49 -13
- package/src/session/types.ts +1 -1
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
* Memory Manager - Core memory system implementation
|
|
3
3
|
*
|
|
4
4
|
* Implements Claude Code compatible memory loading with merge semantics:
|
|
5
|
-
* At each level, both .
|
|
6
|
-
* Content from .
|
|
5
|
+
* At each level, both .gen and .claude directories are loaded.
|
|
6
|
+
* Content from .gen appears later in the context (higher priority for LLM).
|
|
7
7
|
*
|
|
8
8
|
* Loading order within each level:
|
|
9
9
|
* 1. .claude files first (lower priority - LLM sees earlier)
|
|
10
|
-
* 2. .
|
|
10
|
+
* 2. .gen files second (higher priority - LLM sees later)
|
|
11
11
|
*
|
|
12
12
|
* Level loading order:
|
|
13
13
|
* 1. Enterprise (system-wide managed, enforced)
|
|
14
|
-
* 2. User (~/.
|
|
14
|
+
* 2. User (~/.gen/ + ~/.claude/)
|
|
15
15
|
* 3. User Rules
|
|
16
|
-
* 4. Extra (
|
|
16
|
+
* 4. Extra (GEN_CONFIG)
|
|
17
17
|
* 5. Project (recursive upward search)
|
|
18
18
|
* 6. Project Rules
|
|
19
19
|
* 7. Local (*.local.md files)
|
|
@@ -25,7 +25,7 @@ import { glob } from 'glob';
|
|
|
25
25
|
import { ImportResolver } from './import-resolver.js';
|
|
26
26
|
import { parseRuleFrontmatter, activateRules } from './rules-parser.js';
|
|
27
27
|
import { DEFAULT_MEMORY_CONFIG } from './types.js';
|
|
28
|
-
import { getManagedPaths,
|
|
28
|
+
import { getManagedPaths, GEN_CONFIG_ENV } from '../config/types.js';
|
|
29
29
|
export class MemoryManager {
|
|
30
30
|
config;
|
|
31
31
|
importResolver;
|
|
@@ -39,18 +39,19 @@ export class MemoryManager {
|
|
|
39
39
|
* Load all memory files for the given working directory
|
|
40
40
|
*/
|
|
41
41
|
async load(options) {
|
|
42
|
-
const { cwd, currentFile } = options;
|
|
42
|
+
const { cwd, currentFile, strategy = 'fallback' } = options;
|
|
43
43
|
const files = [];
|
|
44
44
|
const rules = [];
|
|
45
45
|
const errors = [];
|
|
46
46
|
const sources = [];
|
|
47
|
+
const skippedFiles = [];
|
|
47
48
|
let totalSize = 0;
|
|
48
49
|
this.importResolver.reset();
|
|
49
50
|
const projectRoot = await this.findProjectRoot(cwd);
|
|
50
51
|
this.importResolver.setProjectRoot(projectRoot);
|
|
51
52
|
// 1. Load enterprise memory (system-wide, enforced)
|
|
52
|
-
const
|
|
53
|
-
for (const file of
|
|
53
|
+
const enterpriseResult = await this.loadEnterpriseMemory(strategy);
|
|
54
|
+
for (const file of enterpriseResult.files) {
|
|
54
55
|
files.push(file);
|
|
55
56
|
totalSize += file.content.length;
|
|
56
57
|
sources.push({
|
|
@@ -61,8 +62,10 @@ export class MemoryManager {
|
|
|
61
62
|
size: file.content.length,
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
skippedFiles.push(...enterpriseResult.skipped);
|
|
66
|
+
// 2. Load user-level memory (both claude and gen)
|
|
67
|
+
const userResult = await this.loadUserMemory(strategy);
|
|
68
|
+
const userFiles = userResult.files;
|
|
66
69
|
for (const file of userFiles) {
|
|
67
70
|
if (totalSize + file.content.length <= this.config.maxTotalSize) {
|
|
68
71
|
files.push(file);
|
|
@@ -79,7 +82,8 @@ export class MemoryManager {
|
|
|
79
82
|
errors.push(`Skipped ${file.path}: would exceed max total size`);
|
|
80
83
|
}
|
|
81
84
|
}
|
|
82
|
-
|
|
85
|
+
skippedFiles.push(...userResult.skipped);
|
|
86
|
+
// 3. Load user-level rules (both claude and gen)
|
|
83
87
|
const userRules = await this.loadUserRules();
|
|
84
88
|
for (const rule of userRules) {
|
|
85
89
|
rules.push(rule);
|
|
@@ -92,7 +96,8 @@ export class MemoryManager {
|
|
|
92
96
|
});
|
|
93
97
|
}
|
|
94
98
|
// 4. Load extra config dirs memory
|
|
95
|
-
const
|
|
99
|
+
const extraResult = await this.loadExtraMemory(strategy);
|
|
100
|
+
const extraFiles = extraResult.files;
|
|
96
101
|
for (const file of extraFiles) {
|
|
97
102
|
if (totalSize + file.content.length <= this.config.maxTotalSize) {
|
|
98
103
|
files.push(file);
|
|
@@ -109,8 +114,10 @@ export class MemoryManager {
|
|
|
109
114
|
errors.push(`Skipped ${file.path}: would exceed max total size`);
|
|
110
115
|
}
|
|
111
116
|
}
|
|
112
|
-
|
|
113
|
-
|
|
117
|
+
skippedFiles.push(...extraResult.skipped);
|
|
118
|
+
// 5. Load project-level memory (both claude and gen, recursive upward)
|
|
119
|
+
const projectResult = await this.loadProjectMemory(cwd, projectRoot, strategy);
|
|
120
|
+
const projectFiles = projectResult.files;
|
|
114
121
|
for (const file of projectFiles) {
|
|
115
122
|
if (totalSize + file.content.length <= this.config.maxTotalSize) {
|
|
116
123
|
files.push(file);
|
|
@@ -127,7 +134,8 @@ export class MemoryManager {
|
|
|
127
134
|
errors.push(`Skipped ${file.path}: would exceed max total size`);
|
|
128
135
|
}
|
|
129
136
|
}
|
|
130
|
-
|
|
137
|
+
skippedFiles.push(...projectResult.skipped);
|
|
138
|
+
// 6. Load project-level rules (both claude and gen)
|
|
131
139
|
const projectRules = await this.loadProjectRules(projectRoot);
|
|
132
140
|
for (const rule of projectRules) {
|
|
133
141
|
rules.push(rule);
|
|
@@ -139,8 +147,9 @@ export class MemoryManager {
|
|
|
139
147
|
size: rule.content.length,
|
|
140
148
|
});
|
|
141
149
|
}
|
|
142
|
-
// 7. Load local memory (both claude and
|
|
143
|
-
const
|
|
150
|
+
// 7. Load local memory (both claude and gen)
|
|
151
|
+
const localResult = await this.loadLocalMemory(projectRoot, strategy);
|
|
152
|
+
const localFiles = localResult.files;
|
|
144
153
|
for (const file of localFiles) {
|
|
145
154
|
if (totalSize + file.content.length <= this.config.maxTotalSize) {
|
|
146
155
|
files.push(file);
|
|
@@ -157,6 +166,7 @@ export class MemoryManager {
|
|
|
157
166
|
errors.push(`Skipped ${file.path}: would exceed max total size`);
|
|
158
167
|
}
|
|
159
168
|
}
|
|
169
|
+
skippedFiles.push(...localResult.skipped);
|
|
160
170
|
// Activate rules based on current file
|
|
161
171
|
const activatedRules = activateRules(rules, currentFile);
|
|
162
172
|
// Build combined context
|
|
@@ -168,6 +178,7 @@ export class MemoryManager {
|
|
|
168
178
|
context,
|
|
169
179
|
errors,
|
|
170
180
|
sources,
|
|
181
|
+
skippedFiles,
|
|
171
182
|
};
|
|
172
183
|
return this.loadedMemory;
|
|
173
184
|
}
|
|
@@ -216,47 +227,112 @@ export class MemoryManager {
|
|
|
216
227
|
'project-rules': 'project rules',
|
|
217
228
|
local: 'local personal notes',
|
|
218
229
|
};
|
|
219
|
-
const namespaceLabel = namespace === '
|
|
230
|
+
const namespaceLabel = namespace === 'gen' ? 'gen' : namespace === 'claude' ? 'claude' : 'extra';
|
|
220
231
|
return `${levelLabels[level]} - ${namespaceLabel}`;
|
|
221
232
|
}
|
|
222
233
|
/**
|
|
223
|
-
*
|
|
234
|
+
* Apply merge strategy to decide which files to load
|
|
235
|
+
* Returns the files to load and the files to skip
|
|
224
236
|
*/
|
|
225
|
-
async
|
|
237
|
+
async applyMergeStrategy(claudeFilePath, genFilePath, level, strategy) {
|
|
226
238
|
const files = [];
|
|
239
|
+
const skipped = [];
|
|
240
|
+
switch (strategy) {
|
|
241
|
+
case 'fallback': {
|
|
242
|
+
// Try gen first, fallback to claude
|
|
243
|
+
const genFile = await this.loadFile(genFilePath, level, 'gen');
|
|
244
|
+
if (genFile) {
|
|
245
|
+
files.push(genFile);
|
|
246
|
+
// Only skip claude file if it exists
|
|
247
|
+
const claudeExists = await this.fileExists(claudeFilePath);
|
|
248
|
+
if (claudeExists) {
|
|
249
|
+
skipped.push(claudeFilePath);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
const claudeFile = await this.loadFile(claudeFilePath, level, 'claude');
|
|
254
|
+
if (claudeFile) {
|
|
255
|
+
files.push(claudeFile);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
case 'both': {
|
|
261
|
+
// Load both (claude first for lower priority)
|
|
262
|
+
const claudeFile = await this.loadFile(claudeFilePath, level, 'claude');
|
|
263
|
+
if (claudeFile)
|
|
264
|
+
files.push(claudeFile);
|
|
265
|
+
const genFile = await this.loadFile(genFilePath, level, 'gen');
|
|
266
|
+
if (genFile)
|
|
267
|
+
files.push(genFile);
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
case 'gen-only': {
|
|
271
|
+
// Only load gen
|
|
272
|
+
const genFile = await this.loadFile(genFilePath, level, 'gen');
|
|
273
|
+
if (genFile) {
|
|
274
|
+
files.push(genFile);
|
|
275
|
+
}
|
|
276
|
+
// Only mark as skipped if claude file exists
|
|
277
|
+
const claudeExists = await this.fileExists(claudeFilePath);
|
|
278
|
+
if (claudeExists) {
|
|
279
|
+
skipped.push(claudeFilePath);
|
|
280
|
+
}
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
case 'claude-only': {
|
|
284
|
+
// Only load claude
|
|
285
|
+
const claudeFile = await this.loadFile(claudeFilePath, level, 'claude');
|
|
286
|
+
if (claudeFile) {
|
|
287
|
+
files.push(claudeFile);
|
|
288
|
+
}
|
|
289
|
+
// Only mark as skipped if gen file exists
|
|
290
|
+
const genExists = await this.fileExists(genFilePath);
|
|
291
|
+
if (genExists) {
|
|
292
|
+
skipped.push(genFilePath);
|
|
293
|
+
}
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return { files, skipped };
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Check if a file exists
|
|
301
|
+
*/
|
|
302
|
+
async fileExists(filePath) {
|
|
303
|
+
try {
|
|
304
|
+
await fs.stat(filePath);
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Load enterprise-level memory files
|
|
313
|
+
*/
|
|
314
|
+
async loadEnterpriseMemory(strategy) {
|
|
227
315
|
const managedPaths = getManagedPaths();
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (gencodeFile) {
|
|
237
|
-
gencodeFile.enforced = true;
|
|
238
|
-
files.push(gencodeFile);
|
|
239
|
-
}
|
|
240
|
-
return files;
|
|
316
|
+
const claudePath = path.join(managedPaths.claude, this.config.claudeFilename);
|
|
317
|
+
const genPath = path.join(managedPaths.gen, this.config.genFilename);
|
|
318
|
+
const result = await this.applyMergeStrategy(claudePath, genPath, 'enterprise', strategy);
|
|
319
|
+
// Mark all enterprise files as enforced
|
|
320
|
+
for (const file of result.files) {
|
|
321
|
+
file.enforced = true;
|
|
322
|
+
}
|
|
323
|
+
return result;
|
|
241
324
|
}
|
|
242
325
|
/**
|
|
243
|
-
* Load user-level memory files (both claude and
|
|
326
|
+
* Load user-level memory files (both claude and gen)
|
|
244
327
|
*/
|
|
245
|
-
async loadUserMemory() {
|
|
328
|
+
async loadUserMemory(strategy) {
|
|
246
329
|
const home = os.homedir();
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (claudeFile)
|
|
251
|
-
files.push(claudeFile);
|
|
252
|
-
// Load GenCode second (higher priority)
|
|
253
|
-
const gencodeFile = await this.loadFile(path.join(home, this.config.gencodeDir, this.config.gencodeFilename), 'user', 'gencode');
|
|
254
|
-
if (gencodeFile)
|
|
255
|
-
files.push(gencodeFile);
|
|
256
|
-
return files;
|
|
330
|
+
const claudePath = path.join(home, this.config.claudeDir, this.config.claudeFilename);
|
|
331
|
+
const genPath = path.join(home, this.config.genDir, this.config.genFilename);
|
|
332
|
+
return await this.applyMergeStrategy(claudePath, genPath, 'user', strategy);
|
|
257
333
|
}
|
|
258
334
|
/**
|
|
259
|
-
* Load user-level rules (both claude and
|
|
335
|
+
* Load user-level rules (both claude and gen)
|
|
260
336
|
*/
|
|
261
337
|
async loadUserRules() {
|
|
262
338
|
const home = os.homedir();
|
|
@@ -266,34 +342,32 @@ export class MemoryManager {
|
|
|
266
342
|
const claudeRules = await this.loadRulesFromDir(claudeRulesDir, 'user-rules', 'claude');
|
|
267
343
|
rules.push(...claudeRules);
|
|
268
344
|
// Load GenCode rules second (higher priority)
|
|
269
|
-
const
|
|
270
|
-
const
|
|
271
|
-
rules.push(...
|
|
345
|
+
const genRulesDir = path.join(home, this.config.genDir, this.config.rulesDir);
|
|
346
|
+
const genRules = await this.loadRulesFromDir(genRulesDir, 'user-rules', 'gen');
|
|
347
|
+
rules.push(...genRules);
|
|
272
348
|
return rules;
|
|
273
349
|
}
|
|
274
350
|
/**
|
|
275
351
|
* Load extra config dirs memory
|
|
276
352
|
*/
|
|
277
|
-
async loadExtraMemory() {
|
|
353
|
+
async loadExtraMemory(strategy) {
|
|
278
354
|
const extraDirs = this.parseExtraConfigDirs();
|
|
279
355
|
const files = [];
|
|
356
|
+
const skipped = [];
|
|
280
357
|
for (const dir of extraDirs) {
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
files.push(gencodeFile);
|
|
289
|
-
}
|
|
290
|
-
return files;
|
|
358
|
+
const claudePath = path.join(dir, this.config.claudeFilename);
|
|
359
|
+
const genPath = path.join(dir, this.config.genFilename);
|
|
360
|
+
const result = await this.applyMergeStrategy(claudePath, genPath, 'extra', strategy);
|
|
361
|
+
files.push(...result.files);
|
|
362
|
+
skipped.push(...result.skipped);
|
|
363
|
+
}
|
|
364
|
+
return { files, skipped };
|
|
291
365
|
}
|
|
292
366
|
/**
|
|
293
|
-
* Parse
|
|
367
|
+
* Parse GEN_CONFIG environment variable
|
|
294
368
|
*/
|
|
295
369
|
parseExtraConfigDirs() {
|
|
296
|
-
const value = process.env[
|
|
370
|
+
const value = process.env[GEN_CONFIG_ENV];
|
|
297
371
|
if (!value)
|
|
298
372
|
return [];
|
|
299
373
|
return value
|
|
@@ -303,38 +377,45 @@ export class MemoryManager {
|
|
|
303
377
|
.map((dir) => dir.replace(/^~/, os.homedir()));
|
|
304
378
|
}
|
|
305
379
|
/**
|
|
306
|
-
* Load project-level memory files (both claude and
|
|
380
|
+
* Load project-level memory files (both claude and gen)
|
|
307
381
|
*/
|
|
308
|
-
async loadProjectMemory(cwd, projectRoot) {
|
|
309
|
-
|
|
310
|
-
// Load from project root - Claude files first
|
|
382
|
+
async loadProjectMemory(cwd, projectRoot, strategy) {
|
|
383
|
+
// Find first existing claude file
|
|
311
384
|
const claudeCandidates = [
|
|
312
385
|
path.join(projectRoot, this.config.claudeFilename),
|
|
313
386
|
path.join(projectRoot, this.config.claudeDir, this.config.claudeFilename),
|
|
314
387
|
];
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
388
|
+
let claudePath = claudeCandidates[0]; // Default for skipped tracking
|
|
389
|
+
for (const candidate of claudeCandidates) {
|
|
390
|
+
try {
|
|
391
|
+
await fs.stat(candidate);
|
|
392
|
+
claudePath = candidate;
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
continue;
|
|
320
397
|
}
|
|
321
398
|
}
|
|
322
|
-
//
|
|
323
|
-
const
|
|
324
|
-
path.join(projectRoot, this.config.
|
|
325
|
-
path.join(projectRoot, this.config.
|
|
399
|
+
// Find first existing gen file
|
|
400
|
+
const genCandidates = [
|
|
401
|
+
path.join(projectRoot, this.config.genFilename),
|
|
402
|
+
path.join(projectRoot, this.config.genDir, this.config.genFilename),
|
|
326
403
|
];
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
404
|
+
let genPath = genCandidates[0]; // Default for skipped tracking
|
|
405
|
+
for (const candidate of genCandidates) {
|
|
406
|
+
try {
|
|
407
|
+
await fs.stat(candidate);
|
|
408
|
+
genPath = candidate;
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
continue;
|
|
332
413
|
}
|
|
333
414
|
}
|
|
334
|
-
return
|
|
415
|
+
return await this.applyMergeStrategy(claudePath, genPath, 'project', strategy);
|
|
335
416
|
}
|
|
336
417
|
/**
|
|
337
|
-
* Load project-level rules (both claude and
|
|
418
|
+
* Load project-level rules (both claude and gen)
|
|
338
419
|
*/
|
|
339
420
|
async loadProjectRules(projectRoot) {
|
|
340
421
|
const rules = [];
|
|
@@ -343,41 +424,48 @@ export class MemoryManager {
|
|
|
343
424
|
const claudeRules = await this.loadRulesFromDir(claudeRulesDir, 'project-rules', 'claude');
|
|
344
425
|
rules.push(...claudeRules);
|
|
345
426
|
// Load GenCode rules second (higher priority)
|
|
346
|
-
const
|
|
347
|
-
const
|
|
348
|
-
rules.push(...
|
|
427
|
+
const genRulesDir = path.join(projectRoot, this.config.genDir, this.config.rulesDir);
|
|
428
|
+
const genRules = await this.loadRulesFromDir(genRulesDir, 'project-rules', 'gen');
|
|
429
|
+
rules.push(...genRules);
|
|
349
430
|
return rules;
|
|
350
431
|
}
|
|
351
432
|
/**
|
|
352
|
-
* Load local memory files (both claude and
|
|
433
|
+
* Load local memory files (both claude and gen)
|
|
353
434
|
*/
|
|
354
|
-
async loadLocalMemory(projectRoot) {
|
|
355
|
-
|
|
356
|
-
// Load Claude local files first
|
|
435
|
+
async loadLocalMemory(projectRoot, strategy) {
|
|
436
|
+
// Find first existing claude local file
|
|
357
437
|
const claudeCandidates = [
|
|
358
438
|
path.join(projectRoot, this.config.claudeLocalFilename),
|
|
359
439
|
path.join(projectRoot, this.config.claudeDir, this.config.claudeLocalFilename),
|
|
360
440
|
];
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
441
|
+
let claudePath = claudeCandidates[0];
|
|
442
|
+
for (const candidate of claudeCandidates) {
|
|
443
|
+
try {
|
|
444
|
+
await fs.stat(candidate);
|
|
445
|
+
claudePath = candidate;
|
|
365
446
|
break;
|
|
366
447
|
}
|
|
448
|
+
catch {
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
367
451
|
}
|
|
368
|
-
//
|
|
369
|
-
const
|
|
370
|
-
path.join(projectRoot, this.config.
|
|
371
|
-
path.join(projectRoot, this.config.
|
|
452
|
+
// Find first existing gen local file
|
|
453
|
+
const genCandidates = [
|
|
454
|
+
path.join(projectRoot, this.config.genLocalFilename),
|
|
455
|
+
path.join(projectRoot, this.config.genDir, this.config.genLocalFilename),
|
|
372
456
|
];
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
457
|
+
let genPath = genCandidates[0];
|
|
458
|
+
for (const candidate of genCandidates) {
|
|
459
|
+
try {
|
|
460
|
+
await fs.stat(candidate);
|
|
461
|
+
genPath = candidate;
|
|
377
462
|
break;
|
|
378
463
|
}
|
|
464
|
+
catch {
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
379
467
|
}
|
|
380
|
-
return
|
|
468
|
+
return await this.applyMergeStrategy(claudePath, genPath, 'local', strategy);
|
|
381
469
|
}
|
|
382
470
|
/**
|
|
383
471
|
* Load rules from a directory
|
|
@@ -464,13 +552,13 @@ export class MemoryManager {
|
|
|
464
552
|
let filePath;
|
|
465
553
|
const home = os.homedir();
|
|
466
554
|
if (level === 'user') {
|
|
467
|
-
const dir = path.join(home, this.config.
|
|
555
|
+
const dir = path.join(home, this.config.genDir);
|
|
468
556
|
await fs.mkdir(dir, { recursive: true });
|
|
469
|
-
filePath = path.join(dir, this.config.
|
|
557
|
+
filePath = path.join(dir, this.config.genFilename);
|
|
470
558
|
}
|
|
471
559
|
else {
|
|
472
560
|
const projectRoot = await this.findProjectRoot(cwd);
|
|
473
|
-
filePath = path.join(projectRoot, this.config.
|
|
561
|
+
filePath = path.join(projectRoot, this.config.genFilename);
|
|
474
562
|
}
|
|
475
563
|
// Read existing content
|
|
476
564
|
let existing = '';
|
|
@@ -479,7 +567,7 @@ export class MemoryManager {
|
|
|
479
567
|
}
|
|
480
568
|
catch {
|
|
481
569
|
// File doesn't exist, create with header
|
|
482
|
-
existing = `# ${this.config.
|
|
570
|
+
existing = `# ${this.config.genFilename.replace('.md', '')}\n\nThis file provides guidance when working with code in this repository.\n\n`;
|
|
483
571
|
}
|
|
484
572
|
// Append new content
|
|
485
573
|
const newContent = `${existing.trimEnd()}\n\n${content}\n`;
|
|
@@ -517,7 +605,7 @@ export class MemoryManager {
|
|
|
517
605
|
* Get the path where /init would create a file
|
|
518
606
|
*/
|
|
519
607
|
getInitFilePath(cwd) {
|
|
520
|
-
return path.join(cwd, this.config.
|
|
608
|
+
return path.join(cwd, this.config.genFilename);
|
|
521
609
|
}
|
|
522
610
|
/**
|
|
523
611
|
* Check if project memory already exists
|
|
@@ -525,8 +613,8 @@ export class MemoryManager {
|
|
|
525
613
|
async hasProjectMemory(cwd) {
|
|
526
614
|
const projectRoot = await this.findProjectRoot(cwd);
|
|
527
615
|
const candidates = [
|
|
528
|
-
path.join(projectRoot, this.config.
|
|
529
|
-
path.join(projectRoot, this.config.
|
|
616
|
+
path.join(projectRoot, this.config.genFilename),
|
|
617
|
+
path.join(projectRoot, this.config.genDir, this.config.genFilename),
|
|
530
618
|
path.join(projectRoot, this.config.claudeFilename),
|
|
531
619
|
path.join(projectRoot, this.config.claudeDir, this.config.claudeFilename),
|
|
532
620
|
];
|
|
@@ -547,8 +635,8 @@ export class MemoryManager {
|
|
|
547
635
|
async getExistingProjectMemoryPath(cwd) {
|
|
548
636
|
const projectRoot = await this.findProjectRoot(cwd);
|
|
549
637
|
const candidates = [
|
|
550
|
-
path.join(projectRoot, this.config.
|
|
551
|
-
path.join(projectRoot, this.config.
|
|
638
|
+
path.join(projectRoot, this.config.genFilename),
|
|
639
|
+
path.join(projectRoot, this.config.genDir, this.config.genFilename),
|
|
552
640
|
path.join(projectRoot, this.config.claudeFilename),
|
|
553
641
|
path.join(projectRoot, this.config.claudeDir, this.config.claudeFilename),
|
|
554
642
|
];
|
|
@@ -583,5 +671,46 @@ export class MemoryManager {
|
|
|
583
671
|
}
|
|
584
672
|
return lines.join('\n');
|
|
585
673
|
}
|
|
674
|
+
/**
|
|
675
|
+
* Get verbose loading summary with strategy info
|
|
676
|
+
*/
|
|
677
|
+
getVerboseSummary(strategy) {
|
|
678
|
+
if (!this.loadedMemory)
|
|
679
|
+
return 'Memory not loaded';
|
|
680
|
+
const lines = [];
|
|
681
|
+
const kbLoaded = (this.loadedMemory.totalSize / 1024).toFixed(1);
|
|
682
|
+
lines.push(`[Memory] Strategy: ${strategy}`);
|
|
683
|
+
// Group sources by level
|
|
684
|
+
const byLevel = new Map();
|
|
685
|
+
for (const source of this.loadedMemory.sources) {
|
|
686
|
+
const key = source.level;
|
|
687
|
+
if (!byLevel.has(key)) {
|
|
688
|
+
byLevel.set(key, []);
|
|
689
|
+
}
|
|
690
|
+
byLevel.get(key).push(source);
|
|
691
|
+
}
|
|
692
|
+
// Show what was loaded per level
|
|
693
|
+
for (const [level, sources] of byLevel) {
|
|
694
|
+
for (const source of sources) {
|
|
695
|
+
const sizeKb = (source.size / 1024).toFixed(1);
|
|
696
|
+
const marker = source.level === 'enterprise' ? ' [enforced]' : '';
|
|
697
|
+
lines.push(`[Memory] ${level}: ${source.path} (${sizeKb} KB)${marker}`);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
// Show what was skipped
|
|
701
|
+
if (this.loadedMemory.skippedFiles.length > 0) {
|
|
702
|
+
for (const skipped of this.loadedMemory.skippedFiles) {
|
|
703
|
+
lines.push(`[Memory] Skipped: ${skipped}`);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
lines.push(`[Memory] Total: ${kbLoaded} KB (${this.loadedMemory.files.length} files loaded, ${this.loadedMemory.skippedFiles.length} skipped)`);
|
|
707
|
+
if (this.loadedMemory.errors.length > 0) {
|
|
708
|
+
lines.push('[Memory] Errors:');
|
|
709
|
+
for (const error of this.loadedMemory.errors) {
|
|
710
|
+
lines.push(` - ${error}`);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return lines.join('\n');
|
|
714
|
+
}
|
|
586
715
|
}
|
|
587
716
|
//# sourceMappingURL=memory-manager.js.map
|