claude-memory-layer 1.0.12 → 1.0.13
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/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
6
|
+
|
|
7
|
+
cd "${ROOT_DIR}"
|
|
8
|
+
|
|
9
|
+
if [[ ! -f package.json ]]; then
|
|
10
|
+
echo "Error: package.json not found in ${ROOT_DIR}" >&2
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
old_version="$(node -p "require('./package.json').version")"
|
|
15
|
+
npm version patch --no-git-tag-version >/dev/null
|
|
16
|
+
new_version="$(node -p "require('./package.json').version")"
|
|
17
|
+
|
|
18
|
+
echo "Version bumped: ${old_version} -> ${new_version}"
|
|
@@ -126,19 +126,31 @@ export class SessionHistoryImporter {
|
|
|
126
126
|
|
|
127
127
|
// Find project directory
|
|
128
128
|
onProgress?.({ phase: 'scan', message: 'Scanning for session files...' });
|
|
129
|
-
const
|
|
130
|
-
if (
|
|
129
|
+
const projectDirs = await this.findProjectDirs(projectPath);
|
|
130
|
+
if (projectDirs.length === 0) {
|
|
131
131
|
result.errors.push(`Project directory not found for: ${projectPath}`);
|
|
132
132
|
return result;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
// Find all session files
|
|
136
|
-
const
|
|
135
|
+
// Find all session files across matched directories
|
|
136
|
+
const allSessionFiles: string[] = [];
|
|
137
|
+
for (const dir of projectDirs) {
|
|
138
|
+
const files = await this.findSessionFiles(dir);
|
|
139
|
+
allSessionFiles.push(...files);
|
|
140
|
+
}
|
|
141
|
+
const sessionFiles = [...new Set(allSessionFiles)];
|
|
137
142
|
result.totalSessions = sessionFiles.length;
|
|
138
|
-
onProgress?.({
|
|
143
|
+
onProgress?.({
|
|
144
|
+
phase: 'scan',
|
|
145
|
+
message: `Found ${sessionFiles.length} sessions in ${projectDirs.length} matched project folder(s)`
|
|
146
|
+
});
|
|
139
147
|
|
|
140
148
|
if (options.verbose) {
|
|
141
|
-
console.log(`
|
|
149
|
+
console.log(`Matched project folders:`);
|
|
150
|
+
for (const dir of projectDirs) {
|
|
151
|
+
console.log(` - ${dir}`);
|
|
152
|
+
}
|
|
153
|
+
console.log(`Found ${sessionFiles.length} session files across matched folders`);
|
|
142
154
|
}
|
|
143
155
|
|
|
144
156
|
// Import each session
|
|
@@ -401,33 +413,52 @@ export class SessionHistoryImporter {
|
|
|
401
413
|
}
|
|
402
414
|
|
|
403
415
|
/**
|
|
404
|
-
* Find project
|
|
416
|
+
* Find project directories from project path.
|
|
417
|
+
* Supports wrappers (e.g. happy) that append extra path segments in folder names.
|
|
405
418
|
*/
|
|
406
|
-
private async
|
|
419
|
+
private async findProjectDirs(projectPath: string): Promise<string[]> {
|
|
407
420
|
const projectsDir = path.join(this.claudeDir, 'projects');
|
|
408
421
|
if (!fs.existsSync(projectsDir)) {
|
|
409
|
-
return
|
|
422
|
+
return [];
|
|
410
423
|
}
|
|
411
424
|
|
|
412
|
-
// Claude uses a hash of the project path as directory name
|
|
413
|
-
// Try to find matching directory by checking all projects
|
|
414
425
|
const projectDirs = fs.readdirSync(projectsDir)
|
|
415
426
|
.map(name => path.join(projectsDir, name))
|
|
416
427
|
.filter(p => fs.statSync(p).isDirectory());
|
|
417
428
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
const
|
|
429
|
+
const normalizedPath = projectPath.replace(/\/+/g, '/').replace(/\/$/, '');
|
|
430
|
+
const normalizedDashed = normalizedPath.replace(/\//g, '-').replace(/^-/, '');
|
|
431
|
+
const baseName = path.basename(normalizedPath);
|
|
421
432
|
|
|
422
|
-
|
|
433
|
+
const scored = projectDirs.map((dir) => {
|
|
423
434
|
const dirName = path.basename(dir);
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
435
|
+
let score = 0;
|
|
436
|
+
|
|
437
|
+
// strong matches
|
|
438
|
+
if (dirName.includes(normalizedDashed)) score += 100;
|
|
439
|
+
if (normalizedDashed.includes(dirName)) score += 80;
|
|
440
|
+
|
|
441
|
+
// basename signal (handles wrappers adding extra suffix)
|
|
442
|
+
if (baseName && dirName.includes(baseName)) score += 30;
|
|
443
|
+
|
|
444
|
+
// token overlap signal
|
|
445
|
+
const pathTokens = normalizedDashed.split('-').filter(Boolean);
|
|
446
|
+
const tokenHits = pathTokens.filter(t => t.length >= 3 && dirName.includes(t)).length;
|
|
447
|
+
score += Math.min(tokenHits, 20);
|
|
428
448
|
|
|
429
|
-
|
|
430
|
-
|
|
449
|
+
return { dir, score, dirName };
|
|
450
|
+
}).filter(x => x.score > 0)
|
|
451
|
+
.sort((a, b) => b.score - a.score);
|
|
452
|
+
|
|
453
|
+
if (scored.length === 0) return [];
|
|
454
|
+
|
|
455
|
+
// Keep close matches (same family) to include wrapper-generated variants
|
|
456
|
+
const top = scored[0].score;
|
|
457
|
+
const threshold = Math.max(30, top - 25);
|
|
458
|
+
|
|
459
|
+
return scored
|
|
460
|
+
.filter(x => x.score >= threshold)
|
|
461
|
+
.map(x => x.dir);
|
|
431
462
|
}
|
|
432
463
|
|
|
433
464
|
/**
|
|
@@ -489,10 +520,7 @@ export class SessionHistoryImporter {
|
|
|
489
520
|
let projectDirs: string[] = [];
|
|
490
521
|
|
|
491
522
|
if (projectPath) {
|
|
492
|
-
|
|
493
|
-
if (projectDir) {
|
|
494
|
-
projectDirs = [projectDir];
|
|
495
|
-
}
|
|
523
|
+
projectDirs = await this.findProjectDirs(projectPath);
|
|
496
524
|
} else {
|
|
497
525
|
const projectsDir = path.join(this.claudeDir, 'projects');
|
|
498
526
|
if (fs.existsSync(projectsDir)) {
|