couchloop-eq-mcp 1.0.3 → 1.0.5
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/README.md +24 -11
- package/dist/clients/shrinkChatClient.js +1 -1
- package/dist/clients/shrinkChatClient.js.map +1 -1
- package/dist/developer/analyzers/bloat-detector.d.ts +89 -0
- package/dist/developer/analyzers/bloat-detector.d.ts.map +1 -0
- package/dist/developer/analyzers/bloat-detector.js +483 -0
- package/dist/developer/analyzers/bloat-detector.js.map +1 -0
- package/dist/developer/backup/auto-backup.d.ts +96 -0
- package/dist/developer/backup/auto-backup.d.ts.map +1 -0
- package/dist/developer/backup/auto-backup.js +346 -0
- package/dist/developer/backup/auto-backup.js.map +1 -0
- package/dist/developer/blockers/package-blocker.d.ts +33 -0
- package/dist/developer/blockers/package-blocker.d.ts.map +1 -0
- package/dist/developer/blockers/package-blocker.js +224 -0
- package/dist/developer/blockers/package-blocker.js.map +1 -0
- package/dist/developer/evaluators/ai-error-preventer.d.ts +54 -0
- package/dist/developer/evaluators/ai-error-preventer.d.ts.map +1 -0
- package/dist/developer/evaluators/ai-error-preventer.js +270 -0
- package/dist/developer/evaluators/ai-error-preventer.js.map +1 -0
- package/dist/developer/evaluators/build-context-detector.d.ts +44 -0
- package/dist/developer/evaluators/build-context-detector.d.ts.map +1 -0
- package/dist/developer/evaluators/build-context-detector.js +258 -0
- package/dist/developer/evaluators/build-context-detector.js.map +1 -0
- package/dist/developer/evaluators/package-evaluator.d.ts +37 -0
- package/dist/developer/evaluators/package-evaluator.d.ts.map +1 -0
- package/dist/developer/evaluators/package-evaluator.js +278 -0
- package/dist/developer/evaluators/package-evaluator.js.map +1 -0
- package/dist/developer/guards/file-guardian.d.ts +79 -0
- package/dist/developer/guards/file-guardian.d.ts.map +1 -0
- package/dist/developer/guards/file-guardian.js +309 -0
- package/dist/developer/guards/file-guardian.js.map +1 -0
- package/dist/developer/managers/context-manager.d.ts +61 -0
- package/dist/developer/managers/context-manager.d.ts.map +1 -0
- package/dist/developer/managers/context-manager.js +302 -0
- package/dist/developer/managers/context-manager.js.map +1 -0
- package/dist/developer/metrics/complexity-calculator.d.ts +52 -0
- package/dist/developer/metrics/complexity-calculator.d.ts.map +1 -0
- package/dist/developer/metrics/complexity-calculator.js +259 -0
- package/dist/developer/metrics/complexity-calculator.js.map +1 -0
- package/dist/developer/reports/review-summary.d.ts +49 -0
- package/dist/developer/reports/review-summary.d.ts.map +1 -0
- package/dist/developer/reports/review-summary.js +249 -0
- package/dist/developer/reports/review-summary.js.map +1 -0
- package/dist/developer/scanners/review-assistant.d.ts +41 -0
- package/dist/developer/scanners/review-assistant.d.ts.map +1 -0
- package/dist/developer/scanners/review-assistant.js +374 -0
- package/dist/developer/scanners/review-assistant.js.map +1 -0
- package/dist/developer/scanners/secret-scanner.d.ts +66 -0
- package/dist/developer/scanners/secret-scanner.d.ts.map +1 -0
- package/dist/developer/scanners/secret-scanner.js +287 -0
- package/dist/developer/scanners/secret-scanner.js.map +1 -0
- package/dist/developer/scanners/sql-injection-detector.d.ts +54 -0
- package/dist/developer/scanners/sql-injection-detector.d.ts.map +1 -0
- package/dist/developer/scanners/sql-injection-detector.js +174 -0
- package/dist/developer/scanners/sql-injection-detector.js.map +1 -0
- package/dist/developer/scanners/xss-detector.d.ts +60 -0
- package/dist/developer/scanners/xss-detector.d.ts.map +1 -0
- package/dist/developer/scanners/xss-detector.js +229 -0
- package/dist/developer/scanners/xss-detector.js.map +1 -0
- package/dist/developer/types/ai-errors.d.ts +34 -0
- package/dist/developer/types/ai-errors.d.ts.map +1 -0
- package/dist/developer/types/ai-errors.js +271 -0
- package/dist/developer/types/ai-errors.js.map +1 -0
- package/dist/developer/types/package.d.ts +32 -0
- package/dist/developer/types/package.d.ts.map +1 -0
- package/dist/developer/types/package.js +5 -0
- package/dist/developer/types/package.js.map +1 -0
- package/dist/developer/updaters/dependency-updater.d.ts +102 -0
- package/dist/developer/updaters/dependency-updater.d.ts.map +1 -0
- package/dist/developer/updaters/dependency-updater.js +472 -0
- package/dist/developer/updaters/dependency-updater.js.map +1 -0
- package/dist/developer/validators/cargo.d.ts +14 -0
- package/dist/developer/validators/cargo.d.ts.map +1 -0
- package/dist/developer/validators/cargo.js +132 -0
- package/dist/developer/validators/cargo.js.map +1 -0
- package/dist/developer/validators/gem.d.ts +14 -0
- package/dist/developer/validators/gem.d.ts.map +1 -0
- package/dist/developer/validators/gem.js +85 -0
- package/dist/developer/validators/gem.js.map +1 -0
- package/dist/developer/validators/go.d.ts +14 -0
- package/dist/developer/validators/go.d.ts.map +1 -0
- package/dist/developer/validators/go.js +138 -0
- package/dist/developer/validators/go.js.map +1 -0
- package/dist/developer/validators/maven.d.ts +14 -0
- package/dist/developer/validators/maven.d.ts.map +1 -0
- package/dist/developer/validators/maven.js +99 -0
- package/dist/developer/validators/maven.js.map +1 -0
- package/dist/developer/validators/npm.d.ts +14 -0
- package/dist/developer/validators/npm.d.ts.map +1 -0
- package/dist/developer/validators/npm.js +96 -0
- package/dist/developer/validators/npm.js.map +1 -0
- package/dist/developer/validators/nuget.d.ts +15 -0
- package/dist/developer/validators/nuget.d.ts.map +1 -0
- package/dist/developer/validators/nuget.js +107 -0
- package/dist/developer/validators/nuget.js.map +1 -0
- package/dist/developer/validators/pypi.d.ts +14 -0
- package/dist/developer/validators/pypi.d.ts.map +1 -0
- package/dist/developer/validators/pypi.js +118 -0
- package/dist/developer/validators/pypi.js.map +1 -0
- package/dist/developer/validators/registry-manager.d.ts +37 -0
- package/dist/developer/validators/registry-manager.d.ts.map +1 -0
- package/dist/developer/validators/registry-manager.js +89 -0
- package/dist/developer/validators/registry-manager.js.map +1 -0
- package/dist/developer/validators/version-checker.d.ts +145 -0
- package/dist/developer/validators/version-checker.d.ts.map +1 -0
- package/dist/developer/validators/version-checker.js +529 -0
- package/dist/developer/validators/version-checker.js.map +1 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/middleware/auth.d.ts +7 -9
- package/dist/server/middleware/auth.d.ts.map +1 -1
- package/dist/server/middleware/auth.js.map +1 -1
- package/dist/tools/check-versions.d.ts +100 -0
- package/dist/tools/check-versions.d.ts.map +1 -0
- package/dist/tools/check-versions.js +328 -0
- package/dist/tools/check-versions.js.map +1 -0
- package/dist/tools/detect-code-smell.d.ts +9 -0
- package/dist/tools/detect-code-smell.d.ts.map +1 -0
- package/dist/tools/detect-code-smell.js +231 -0
- package/dist/tools/detect-code-smell.js.map +1 -0
- package/dist/tools/index.d.ts +471 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +178 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/journey.js +1 -1
- package/dist/tools/journey.js.map +1 -1
- package/dist/tools/pre-review-code.d.ts +71 -0
- package/dist/tools/pre-review-code.d.ts.map +1 -0
- package/dist/tools/pre-review-code.js +159 -0
- package/dist/tools/pre-review-code.js.map +1 -0
- package/dist/tools/preserve-context.d.ts +27 -0
- package/dist/tools/preserve-context.d.ts.map +1 -0
- package/dist/tools/preserve-context.js +98 -0
- package/dist/tools/preserve-context.js.map +1 -0
- package/dist/tools/protect-files.d.ts +224 -0
- package/dist/tools/protect-files.d.ts.map +1 -0
- package/dist/tools/protect-files.js +286 -0
- package/dist/tools/protect-files.js.map +1 -0
- package/dist/tools/scan-security.d.ts +38 -0
- package/dist/tools/scan-security.d.ts.map +1 -0
- package/dist/tools/scan-security.js +237 -0
- package/dist/tools/scan-security.js.map +1 -0
- package/dist/tools/validate_packages.d.ts +8 -0
- package/dist/tools/validate_packages.d.ts.map +1 -0
- package/dist/tools/validate_packages.js +159 -0
- package/dist/tools/validate_packages.js.map +1 -0
- package/dist/types/auth.d.ts +18 -18
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js +91 -36
- package/dist/types/auth.js.map +1 -1
- package/dist/types/context.d.ts +46 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +17 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/file-protection.d.ts +50 -0
- package/dist/types/file-protection.d.ts.map +1 -0
- package/dist/types/file-protection.js +9 -0
- package/dist/types/file-protection.js.map +1 -0
- package/dist/utils/errorHandler.d.ts.map +1 -1
- package/dist/utils/errorHandler.js +2 -1
- package/dist/utils/errorHandler.js.map +1 -1
- package/package.json +23 -2
- package/dist/db/migrate.d.ts +0 -4
- package/dist/db/migrate.d.ts.map +0 -1
- package/dist/db/migrate.js +0 -34
- package/dist/db/migrate.js.map +0 -1
- package/dist/db/migrations/schema.d.ts +0 -1074
- package/dist/db/migrations/schema.d.ts.map +0 -1
- package/dist/db/migrations/schema.js +0 -160
- package/dist/db/migrations/schema.js.map +0 -1
- package/dist/db/schema.d.ts +0 -1576
- package/dist/db/schema.d.ts.map +0 -1
- package/dist/db/schema.js +0 -204
- package/dist/db/schema.js.map +0 -1
- package/dist/db/seed.d.ts +0 -4
- package/dist/db/seed.d.ts.map +0 -1
- package/dist/db/seed.js +0 -57
- package/dist/db/seed.js.map +0 -1
- package/dist/db/seedOAuth.d.ts +0 -4
- package/dist/db/seedOAuth.d.ts.map +0 -1
- package/dist/db/seedOAuth.js +0 -76
- package/dist/db/seedOAuth.js.map +0 -1
- package/dist/governance/config.d.ts +0 -66
- package/dist/governance/config.d.ts.map +0 -1
- package/dist/governance/config.js +0 -238
- package/dist/governance/config.js.map +0 -1
- package/dist/governance/detectors/hallucination.d.ts +0 -61
- package/dist/governance/detectors/hallucination.d.ts.map +0 -1
- package/dist/governance/detectors/hallucination.js +0 -338
- package/dist/governance/detectors/hallucination.js.map +0 -1
- package/dist/governance/detectors/inconsistency.d.ts +0 -99
- package/dist/governance/detectors/inconsistency.d.ts.map +0 -1
- package/dist/governance/detectors/inconsistency.js +0 -548
- package/dist/governance/detectors/inconsistency.js.map +0 -1
- package/dist/governance/detectors/toneDrift.d.ts +0 -63
- package/dist/governance/detectors/toneDrift.d.ts.map +0 -1
- package/dist/governance/detectors/toneDrift.js +0 -421
- package/dist/governance/detectors/toneDrift.js.map +0 -1
- package/dist/governance/detectors/unsafeReasoning.d.ts +0 -54
- package/dist/governance/detectors/unsafeReasoning.d.ts.map +0 -1
- package/dist/governance/detectors/unsafeReasoning.js +0 -473
- package/dist/governance/detectors/unsafeReasoning.js.map +0 -1
- package/dist/governance/evaluationEngine.d.ts +0 -112
- package/dist/governance/evaluationEngine.d.ts.map +0 -1
- package/dist/governance/evaluationEngine.js +0 -265
- package/dist/governance/evaluationEngine.js.map +0 -1
- package/dist/governance/intervention.d.ts +0 -81
- package/dist/governance/intervention.d.ts.map +0 -1
- package/dist/governance/intervention.js +0 -405
- package/dist/governance/intervention.js.map +0 -1
- package/dist/server/oauth/anomalyDetection.d.ts +0 -146
- package/dist/server/oauth/anomalyDetection.d.ts.map +0 -1
- package/dist/server/oauth/anomalyDetection.js +0 -405
- package/dist/server/oauth/anomalyDetection.js.map +0 -1
- package/dist/server/oauth/authServer.d.ts +0 -61
- package/dist/server/oauth/authServer.d.ts.map +0 -1
- package/dist/server/oauth/authServer.js +0 -283
- package/dist/server/oauth/authServer.js.map +0 -1
- package/dist/server/oauth/dpop.d.ts +0 -135
- package/dist/server/oauth/dpop.d.ts.map +0 -1
- package/dist/server/oauth/dpop.js +0 -338
- package/dist/server/oauth/dpop.js.map +0 -1
- package/dist/server/oauth/gdpr/consent.d.ts +0 -173
- package/dist/server/oauth/gdpr/consent.d.ts.map +0 -1
- package/dist/server/oauth/gdpr/consent.js +0 -388
- package/dist/server/oauth/gdpr/consent.js.map +0 -1
- package/dist/server/oauth/gdpr/dataPortability.d.ts +0 -214
- package/dist/server/oauth/gdpr/dataPortability.d.ts.map +0 -1
- package/dist/server/oauth/gdpr/dataPortability.js +0 -486
- package/dist/server/oauth/gdpr/dataPortability.js.map +0 -1
- package/dist/server/oauth/gdpr/index.d.ts +0 -103
- package/dist/server/oauth/gdpr/index.d.ts.map +0 -1
- package/dist/server/oauth/gdpr/index.js +0 -273
- package/dist/server/oauth/gdpr/index.js.map +0 -1
- package/dist/server/oauth/gdpr/rightToErasure.d.ts +0 -184
- package/dist/server/oauth/gdpr/rightToErasure.d.ts.map +0 -1
- package/dist/server/oauth/gdpr/rightToErasure.js +0 -527
- package/dist/server/oauth/gdpr/rightToErasure.js.map +0 -1
- package/dist/server/oauth/monitoring/securityMonitor.d.ts +0 -218
- package/dist/server/oauth/monitoring/securityMonitor.d.ts.map +0 -1
- package/dist/server/oauth/monitoring/securityMonitor.js +0 -615
- package/dist/server/oauth/monitoring/securityMonitor.js.map +0 -1
- package/dist/server/oauth/pkce.d.ts +0 -61
- package/dist/server/oauth/pkce.d.ts.map +0 -1
- package/dist/server/oauth/pkce.js +0 -157
- package/dist/server/oauth/pkce.js.map +0 -1
- package/dist/server/oauth/providers/base.d.ts +0 -147
- package/dist/server/oauth/providers/base.d.ts.map +0 -1
- package/dist/server/oauth/providers/base.js +0 -312
- package/dist/server/oauth/providers/base.js.map +0 -1
- package/dist/server/oauth/providers/github.d.ts +0 -55
- package/dist/server/oauth/providers/github.d.ts.map +0 -1
- package/dist/server/oauth/providers/github.js +0 -225
- package/dist/server/oauth/providers/github.js.map +0 -1
- package/dist/server/oauth/providers/google.d.ts +0 -49
- package/dist/server/oauth/providers/google.d.ts.map +0 -1
- package/dist/server/oauth/providers/google.js +0 -153
- package/dist/server/oauth/providers/google.js.map +0 -1
- package/dist/server/oauth/providers/index.d.ts +0 -9
- package/dist/server/oauth/providers/index.d.ts.map +0 -1
- package/dist/server/oauth/providers/index.js +0 -24
- package/dist/server/oauth/providers/index.js.map +0 -1
- package/dist/server/oauth/refreshTokenRotation.d.ts +0 -114
- package/dist/server/oauth/refreshTokenRotation.d.ts.map +0 -1
- package/dist/server/oauth/refreshTokenRotation.js +0 -344
- package/dist/server/oauth/refreshTokenRotation.js.map +0 -1
- package/dist/server/oauth/security.d.ts +0 -101
- package/dist/server/oauth/security.d.ts.map +0 -1
- package/dist/server/oauth/security.js +0 -268
- package/dist/server/oauth/security.js.map +0 -1
- package/dist/server/oauth/tokenEncryption.d.ts +0 -80
- package/dist/server/oauth/tokenEncryption.d.ts.map +0 -1
- package/dist/server/oauth/tokenEncryption.js +0 -218
- package/dist/server/oauth/tokenEncryption.js.map +0 -1
- package/dist/tools/sendMessage-complex-backup.d.ts +0 -6
- package/dist/tools/sendMessage-complex-backup.d.ts.map +0 -1
- package/dist/tools/sendMessage-complex-backup.js +0 -545
- package/dist/tools/sendMessage-complex-backup.js.map +0 -1
- package/dist/tools/sendMessage-revised.d.ts +0 -11
- package/dist/tools/sendMessage-revised.d.ts.map +0 -1
- package/dist/tools/sendMessage-revised.js +0 -429
- package/dist/tools/sendMessage-revised.js.map +0 -1
- package/dist/tools/sendMessage-truly-simple.d.ts +0 -8
- package/dist/tools/sendMessage-truly-simple.d.ts.map +0 -1
- package/dist/tools/sendMessage-truly-simple.js +0 -299
- package/dist/tools/sendMessage-truly-simple.js.map +0 -1
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { logger } from '../../utils/logger.js';
|
|
3
|
+
/**
|
|
4
|
+
* File Guardian - Detects and prevents destructive file operations
|
|
5
|
+
* Protects against accidental deletion, overwriting, and data loss
|
|
6
|
+
*/
|
|
7
|
+
// Patterns that ALWAYS require confirmation before modification/deletion
|
|
8
|
+
const PROTECTED_PATTERNS = [
|
|
9
|
+
'.env*',
|
|
10
|
+
'*.key',
|
|
11
|
+
'*.pem',
|
|
12
|
+
'*.secret',
|
|
13
|
+
'*.credentials',
|
|
14
|
+
'database.sqlite',
|
|
15
|
+
'production.json',
|
|
16
|
+
'secrets.json',
|
|
17
|
+
'config.json',
|
|
18
|
+
'package.json',
|
|
19
|
+
'package-lock.json',
|
|
20
|
+
'yarn.lock',
|
|
21
|
+
];
|
|
22
|
+
// Paths that should NEVER be deleted (code freeze)
|
|
23
|
+
const FORBIDDEN_PATHS = [
|
|
24
|
+
'.git',
|
|
25
|
+
'.gitignore',
|
|
26
|
+
'node_modules',
|
|
27
|
+
'dist',
|
|
28
|
+
'build',
|
|
29
|
+
'.next',
|
|
30
|
+
'.env.production',
|
|
31
|
+
'.env.staging',
|
|
32
|
+
'Dockerfile',
|
|
33
|
+
'.dockerignore',
|
|
34
|
+
];
|
|
35
|
+
// System/critical files
|
|
36
|
+
const CRITICAL_SYSTEM_FILES = [
|
|
37
|
+
'.env',
|
|
38
|
+
'.env.local',
|
|
39
|
+
'.env.production',
|
|
40
|
+
'.env.staging',
|
|
41
|
+
'package.json',
|
|
42
|
+
'tsconfig.json',
|
|
43
|
+
'eslint.config.js',
|
|
44
|
+
'vitest.config.ts',
|
|
45
|
+
'drizzle.config.ts',
|
|
46
|
+
];
|
|
47
|
+
// Dangerous operations that require explicit confirmation
|
|
48
|
+
const DANGEROUS_OPERATIONS = ['rm -rf', 'rm -f', 'delete', 'unlink', 'truncate'];
|
|
49
|
+
export class FileGuardian {
|
|
50
|
+
codeFreezeMode = false;
|
|
51
|
+
operationLog = [];
|
|
52
|
+
constructor() {
|
|
53
|
+
this.codeFreezeMode = process.env.CODE_FREEZE_MODE === 'true';
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Enable code freeze mode - all file operations require approval
|
|
57
|
+
*/
|
|
58
|
+
enableCodeFreezeMode() {
|
|
59
|
+
this.codeFreezeMode = true;
|
|
60
|
+
logger.info('Code freeze mode ENABLED - all file operations require approval');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Disable code freeze mode
|
|
64
|
+
*/
|
|
65
|
+
disableCodeFreezeMode() {
|
|
66
|
+
this.codeFreezeMode = false;
|
|
67
|
+
logger.info('Code freeze mode disabled');
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check if a file path matches a protected pattern
|
|
71
|
+
*/
|
|
72
|
+
matchesProtectedPattern(filePath) {
|
|
73
|
+
const fileName = path.basename(filePath);
|
|
74
|
+
return PROTECTED_PATTERNS.some(pattern => {
|
|
75
|
+
const globPattern = pattern.replace(/\*/g, '.*');
|
|
76
|
+
const regex = new RegExp(`^${globPattern}$`);
|
|
77
|
+
return regex.test(fileName);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Check if a path is forbidden (should never be deleted)
|
|
82
|
+
*/
|
|
83
|
+
isForbiddenPath(filePath) {
|
|
84
|
+
const normalized = path.normalize(filePath);
|
|
85
|
+
return FORBIDDEN_PATHS.some(forbidden => {
|
|
86
|
+
return normalized.includes(forbidden) || path.basename(normalized) === forbidden;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if this is a critical system file
|
|
91
|
+
*/
|
|
92
|
+
isCriticalSystemFile(filePath) {
|
|
93
|
+
const fileName = path.basename(filePath);
|
|
94
|
+
return CRITICAL_SYSTEM_FILES.includes(fileName);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if operation is dangerous
|
|
98
|
+
*/
|
|
99
|
+
isDangerousOperation(operation) {
|
|
100
|
+
return DANGEROUS_OPERATIONS.some(op => operation.toLowerCase().includes(op));
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Validate file deletion operation
|
|
104
|
+
*/
|
|
105
|
+
validateDelete(filePath, _force = false) {
|
|
106
|
+
const violations = [];
|
|
107
|
+
// Check if path is forbidden
|
|
108
|
+
if (this.isForbiddenPath(filePath)) {
|
|
109
|
+
violations.push({
|
|
110
|
+
type: 'forbidden_path',
|
|
111
|
+
path: filePath,
|
|
112
|
+
message: `Path '${filePath}' is protected and cannot be deleted. This directory/file is critical to system operation.`,
|
|
113
|
+
severity: 'critical',
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// Check for critical system files
|
|
117
|
+
if (this.isCriticalSystemFile(filePath)) {
|
|
118
|
+
violations.push({
|
|
119
|
+
type: 'system_file',
|
|
120
|
+
path: filePath,
|
|
121
|
+
message: `System file '${filePath}' requires special approval before deletion.`,
|
|
122
|
+
severity: 'high',
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
// Check protected patterns
|
|
126
|
+
if (this.matchesProtectedPattern(filePath)) {
|
|
127
|
+
violations.push({
|
|
128
|
+
type: 'protected_pattern',
|
|
129
|
+
path: filePath,
|
|
130
|
+
message: `File '${filePath}' matches protected pattern. Credentials/configs must not be deleted.`,
|
|
131
|
+
severity: 'critical',
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
// Code freeze mode check
|
|
135
|
+
if (this.codeFreezeMode) {
|
|
136
|
+
violations.push({
|
|
137
|
+
type: 'dangerous_operation',
|
|
138
|
+
path: filePath,
|
|
139
|
+
message: `Code freeze mode is ENABLED. All delete operations require explicit approval. Cannot proceed.`,
|
|
140
|
+
severity: 'critical',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return violations;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Validate file overwrite operation
|
|
147
|
+
*/
|
|
148
|
+
validateOverwrite(filePath, _force = false) {
|
|
149
|
+
const violations = [];
|
|
150
|
+
// Check for critical system files
|
|
151
|
+
if (this.isCriticalSystemFile(filePath)) {
|
|
152
|
+
violations.push({
|
|
153
|
+
type: 'system_file',
|
|
154
|
+
path: filePath,
|
|
155
|
+
message: `System file '${filePath}' cannot be overwritten without backup and approval.`,
|
|
156
|
+
severity: 'high',
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
// Check protected patterns
|
|
160
|
+
if (this.matchesProtectedPattern(filePath)) {
|
|
161
|
+
violations.push({
|
|
162
|
+
type: 'protected_pattern',
|
|
163
|
+
path: filePath,
|
|
164
|
+
message: `File '${filePath}' is protected. Overwriting credentials/configs is dangerous.`,
|
|
165
|
+
severity: 'critical',
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
// Code freeze mode check
|
|
169
|
+
if (this.codeFreezeMode) {
|
|
170
|
+
violations.push({
|
|
171
|
+
type: 'dangerous_operation',
|
|
172
|
+
path: filePath,
|
|
173
|
+
message: `Code freeze mode is ENABLED. All file modifications require explicit approval.`,
|
|
174
|
+
severity: 'critical',
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return violations;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Validate file move operation
|
|
181
|
+
*/
|
|
182
|
+
validateMove(sourcePath, targetPath, _force = false) {
|
|
183
|
+
const violations = [];
|
|
184
|
+
// Check if source is forbidden
|
|
185
|
+
if (this.isForbiddenPath(sourcePath)) {
|
|
186
|
+
violations.push({
|
|
187
|
+
type: 'forbidden_path',
|
|
188
|
+
path: sourcePath,
|
|
189
|
+
message: `Cannot move protected path '${sourcePath}'`,
|
|
190
|
+
severity: 'critical',
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
// Check if source is critical
|
|
194
|
+
if (this.isCriticalSystemFile(sourcePath)) {
|
|
195
|
+
violations.push({
|
|
196
|
+
type: 'system_file',
|
|
197
|
+
path: sourcePath,
|
|
198
|
+
message: `Cannot move critical system file '${sourcePath}' without backup.`,
|
|
199
|
+
severity: 'high',
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
// Warn if target path suggests unsafe operation
|
|
203
|
+
if (this.isForbiddenPath(targetPath)) {
|
|
204
|
+
violations.push({
|
|
205
|
+
type: 'dangerous_operation',
|
|
206
|
+
path: targetPath,
|
|
207
|
+
message: `Moving to protected location '${targetPath}' may cause issues.`,
|
|
208
|
+
severity: 'high',
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
// Code freeze mode check
|
|
212
|
+
if (this.codeFreezeMode) {
|
|
213
|
+
violations.push({
|
|
214
|
+
type: 'dangerous_operation',
|
|
215
|
+
path: sourcePath,
|
|
216
|
+
message: `Code freeze mode is ENABLED. All file operations require explicit approval.`,
|
|
217
|
+
severity: 'critical',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return violations;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Perform comprehensive file operation validation
|
|
224
|
+
*/
|
|
225
|
+
validateOperation(operation, filePath, targetPath, force = false) {
|
|
226
|
+
let violations = [];
|
|
227
|
+
switch (operation) {
|
|
228
|
+
case 'delete':
|
|
229
|
+
violations = this.validateDelete(filePath, force);
|
|
230
|
+
break;
|
|
231
|
+
case 'overwrite':
|
|
232
|
+
violations = this.validateOverwrite(filePath, force);
|
|
233
|
+
break;
|
|
234
|
+
case 'move':
|
|
235
|
+
violations = this.validateMove(filePath, targetPath || '', force);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
// Determine severity from violations
|
|
239
|
+
let maxSeverity = 'none';
|
|
240
|
+
for (const violation of violations) {
|
|
241
|
+
if (violation.severity === 'critical') {
|
|
242
|
+
maxSeverity = 'critical';
|
|
243
|
+
}
|
|
244
|
+
else if (violation.severity === 'high' && maxSeverity !== 'critical') {
|
|
245
|
+
maxSeverity = 'high';
|
|
246
|
+
}
|
|
247
|
+
else if (violation.severity === 'medium' && maxSeverity === 'none') {
|
|
248
|
+
maxSeverity = 'medium';
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
allowed: violations.length === 0,
|
|
253
|
+
violations,
|
|
254
|
+
requiresApproval: violations.length > 0,
|
|
255
|
+
severity: maxSeverity,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Log a file operation
|
|
260
|
+
*/
|
|
261
|
+
logOperation(operation) {
|
|
262
|
+
this.operationLog.push({
|
|
263
|
+
...operation,
|
|
264
|
+
timestamp: new Date(),
|
|
265
|
+
});
|
|
266
|
+
logger.info(`File operation logged: ${operation.operation} on ${operation.path} - Status: ${operation.status}`);
|
|
267
|
+
// Keep only last 100 operations
|
|
268
|
+
if (this.operationLog.length > 100) {
|
|
269
|
+
this.operationLog = this.operationLog.slice(-100);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Get operation history
|
|
274
|
+
*/
|
|
275
|
+
getOperationHistory(limit = 50) {
|
|
276
|
+
return this.operationLog.slice(-limit);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Get protected paths configuration
|
|
280
|
+
*/
|
|
281
|
+
getProtectionConfig() {
|
|
282
|
+
return {
|
|
283
|
+
protectedPatterns: PROTECTED_PATTERNS,
|
|
284
|
+
forbiddenPaths: FORBIDDEN_PATHS,
|
|
285
|
+
criticalSystemFiles: CRITICAL_SYSTEM_FILES,
|
|
286
|
+
codeFreezeMode: this.codeFreezeMode,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Generate protection report
|
|
291
|
+
*/
|
|
292
|
+
getProtectionReport() {
|
|
293
|
+
const recentViolations = [];
|
|
294
|
+
// Extract violations from recent operations
|
|
295
|
+
for (const _op of this.operationLog.slice(-20)) {
|
|
296
|
+
// This would need to store violations in FileOperation
|
|
297
|
+
// For now, return empty
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
codeFreezeEnabled: this.codeFreezeMode,
|
|
301
|
+
totalOperationsLogged: this.operationLog.length,
|
|
302
|
+
recentViolations,
|
|
303
|
+
protectedItemsCount: PROTECTED_PATTERNS.length + FORBIDDEN_PATHS.length,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Export singleton instance
|
|
308
|
+
export const fileGuardian = new FileGuardian();
|
|
309
|
+
//# sourceMappingURL=file-guardian.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-guardian.js","sourceRoot":"","sources":["../../../src/developer/guards/file-guardian.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ContextEntry, ContextCategoryType, PreserveContextResponse } from '../../types/context.js';
|
|
2
|
+
interface ContextStore {
|
|
3
|
+
version: string;
|
|
4
|
+
entries: ContextEntry[];
|
|
5
|
+
metadata: {
|
|
6
|
+
created_at: string;
|
|
7
|
+
last_updated: string;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export declare class ContextManager {
|
|
11
|
+
private store;
|
|
12
|
+
private isInitialized;
|
|
13
|
+
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Initialize the context store from disk
|
|
16
|
+
*/
|
|
17
|
+
initialize(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Store a context entry
|
|
20
|
+
*/
|
|
21
|
+
storeEntry(category: ContextCategoryType, content: string): Promise<PreserveContextResponse>;
|
|
22
|
+
/**
|
|
23
|
+
* Retrieve context entries by category or search term
|
|
24
|
+
*/
|
|
25
|
+
retrieve(category?: ContextCategoryType, searchTerm?: string): Promise<PreserveContextResponse>;
|
|
26
|
+
/**
|
|
27
|
+
* Check context window status and provide warnings if needed
|
|
28
|
+
*/
|
|
29
|
+
check(includeMetadata?: boolean): Promise<PreserveContextResponse>;
|
|
30
|
+
/**
|
|
31
|
+
* Get metadata about the context store
|
|
32
|
+
*/
|
|
33
|
+
private getMetadata;
|
|
34
|
+
/**
|
|
35
|
+
* Clear old or unused context entries (cleanup)
|
|
36
|
+
*/
|
|
37
|
+
cleanup(daysOld?: number): Promise<PreserveContextResponse>;
|
|
38
|
+
/**
|
|
39
|
+
* Export all context for backup
|
|
40
|
+
*/
|
|
41
|
+
export(): Promise<ContextStore>;
|
|
42
|
+
/**
|
|
43
|
+
* Import context from backup
|
|
44
|
+
*/
|
|
45
|
+
import(store: ContextStore): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Create default context store
|
|
48
|
+
*/
|
|
49
|
+
private createDefaultStore;
|
|
50
|
+
/**
|
|
51
|
+
* Save store to disk
|
|
52
|
+
*/
|
|
53
|
+
private save;
|
|
54
|
+
/**
|
|
55
|
+
* Ensure manager is initialized
|
|
56
|
+
*/
|
|
57
|
+
private ensureInitialized;
|
|
58
|
+
}
|
|
59
|
+
export declare function getContextManager(): Promise<ContextManager>;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=context-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-manager.d.ts","sourceRoot":"","sources":["../../../src/developer/managers/context-manager.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,YAAY,EACZ,mBAAmB,EAEnB,uBAAuB,EACxB,MAAM,wBAAwB,CAAC;AAMhC,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,aAAa,CAAS;;IAa9B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA0BjC;;OAEG;IACG,UAAU,CACd,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,uBAAuB,CAAC;IA+BnC;;OAEG;IACG,QAAQ,CACZ,QAAQ,CAAC,EAAE,mBAAmB,EAC9B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,uBAAuB,CAAC;IAmDnC;;OAEG;IACG,KAAK,CAAC,eAAe,GAAE,OAAe,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAmC/E;;OAEG;IACH,OAAO,CAAC,WAAW;IA6BnB;;OAEG;IACG,OAAO,CAAC,OAAO,GAAE,MAAW,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA8BrE;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC;IAKrC;;OAEG;IACG,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAYhD;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAsC1B;;OAEG;IACH,OAAO,CAAC,IAAI;IAaZ;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAO1B;AAKD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAMjE"}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { nanoid } from 'nanoid';
|
|
4
|
+
import { logger } from '../../utils/logger.js';
|
|
5
|
+
const CONTEXT_STORE_PATH = path.join(process.cwd(), 'src', 'db', 'context-store.json');
|
|
6
|
+
const MAX_CONTEXT_WINDOW_TOKENS = 200000; // Approximate token limit
|
|
7
|
+
const AVG_CHARS_PER_TOKEN = 4; // Average characters per token
|
|
8
|
+
export class ContextManager {
|
|
9
|
+
store;
|
|
10
|
+
isInitialized = false;
|
|
11
|
+
constructor() {
|
|
12
|
+
this.store = {
|
|
13
|
+
version: '1.0.0',
|
|
14
|
+
entries: [],
|
|
15
|
+
metadata: {
|
|
16
|
+
created_at: new Date().toISOString(),
|
|
17
|
+
last_updated: new Date().toISOString(),
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Initialize the context store from disk
|
|
23
|
+
*/
|
|
24
|
+
async initialize() {
|
|
25
|
+
try {
|
|
26
|
+
// Create parent directory if it doesn't exist
|
|
27
|
+
const dir = path.dirname(CONTEXT_STORE_PATH);
|
|
28
|
+
if (!fs.existsSync(dir)) {
|
|
29
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
// Load existing store or create new one
|
|
32
|
+
if (fs.existsSync(CONTEXT_STORE_PATH)) {
|
|
33
|
+
const data = fs.readFileSync(CONTEXT_STORE_PATH, 'utf-8');
|
|
34
|
+
this.store = JSON.parse(data);
|
|
35
|
+
logger.info(`Loaded context store with ${this.store.entries.length} entries`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
this.createDefaultStore();
|
|
39
|
+
this.save();
|
|
40
|
+
logger.info('Created new context store');
|
|
41
|
+
}
|
|
42
|
+
this.isInitialized = true;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
logger.error('Failed to initialize context manager:', error);
|
|
46
|
+
throw new Error(`Context manager initialization failed: ${error}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Store a context entry
|
|
51
|
+
*/
|
|
52
|
+
async storeEntry(category, content) {
|
|
53
|
+
this.ensureInitialized();
|
|
54
|
+
try {
|
|
55
|
+
const entry = {
|
|
56
|
+
id: nanoid(),
|
|
57
|
+
category,
|
|
58
|
+
content,
|
|
59
|
+
timestamp: new Date(),
|
|
60
|
+
usage_count: 0,
|
|
61
|
+
last_retrieved: null,
|
|
62
|
+
};
|
|
63
|
+
this.store.entries.push(entry);
|
|
64
|
+
this.store.metadata.last_updated = new Date().toISOString();
|
|
65
|
+
this.save();
|
|
66
|
+
logger.info(`Stored context entry: ${entry.id} in category: ${category}`);
|
|
67
|
+
return {
|
|
68
|
+
success: true,
|
|
69
|
+
action: 'store',
|
|
70
|
+
message: `Successfully stored context in "${category}" category`,
|
|
71
|
+
data: [entry],
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
logger.error('Error storing context:', error);
|
|
76
|
+
throw new Error(`Failed to store context: ${error}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Retrieve context entries by category or search term
|
|
81
|
+
*/
|
|
82
|
+
async retrieve(category, searchTerm) {
|
|
83
|
+
this.ensureInitialized();
|
|
84
|
+
try {
|
|
85
|
+
let results = this.store.entries;
|
|
86
|
+
// Filter by category if provided
|
|
87
|
+
if (category) {
|
|
88
|
+
results = results.filter((e) => e.category === category);
|
|
89
|
+
}
|
|
90
|
+
// Filter by search term if provided
|
|
91
|
+
if (searchTerm) {
|
|
92
|
+
const term = searchTerm.toLowerCase();
|
|
93
|
+
results = results.filter((e) => e.content.toLowerCase().includes(term));
|
|
94
|
+
}
|
|
95
|
+
// Update usage count and last retrieved timestamp
|
|
96
|
+
results.forEach((entry) => {
|
|
97
|
+
entry.usage_count += 1;
|
|
98
|
+
entry.last_retrieved = new Date();
|
|
99
|
+
});
|
|
100
|
+
this.store.metadata.last_updated = new Date().toISOString();
|
|
101
|
+
this.save();
|
|
102
|
+
if (results.length === 0) {
|
|
103
|
+
return {
|
|
104
|
+
success: true,
|
|
105
|
+
action: 'retrieve',
|
|
106
|
+
message: `No context found${category ? ` in category "${category}"` : ''}${searchTerm ? ` matching "${searchTerm}"` : ''}`,
|
|
107
|
+
data: null,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
logger.info(`Retrieved ${results.length} context entries`);
|
|
111
|
+
return {
|
|
112
|
+
success: true,
|
|
113
|
+
action: 'retrieve',
|
|
114
|
+
message: `Retrieved ${results.length} context entries`,
|
|
115
|
+
data: results,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
logger.error('Error retrieving context:', error);
|
|
120
|
+
throw new Error(`Failed to retrieve context: ${error}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Check context window status and provide warnings if needed
|
|
125
|
+
*/
|
|
126
|
+
async check(includeMetadata = false) {
|
|
127
|
+
this.ensureInitialized();
|
|
128
|
+
try {
|
|
129
|
+
const metadata = this.getMetadata();
|
|
130
|
+
let warning;
|
|
131
|
+
if (metadata.context_window_usage_percent > 80) {
|
|
132
|
+
warning = `Context window is ${metadata.context_window_usage_percent.toFixed(1)}% full. Consider archiving or cleaning up old context entries.`;
|
|
133
|
+
}
|
|
134
|
+
else if (metadata.context_window_usage_percent > 60) {
|
|
135
|
+
warning = `Context window is ${metadata.context_window_usage_percent.toFixed(1)}% full. You may want to monitor usage.`;
|
|
136
|
+
}
|
|
137
|
+
const response = {
|
|
138
|
+
success: true,
|
|
139
|
+
action: 'check',
|
|
140
|
+
message: `Context store contains ${metadata.total_entries} entries`,
|
|
141
|
+
warning,
|
|
142
|
+
};
|
|
143
|
+
if (includeMetadata) {
|
|
144
|
+
response.data = metadata;
|
|
145
|
+
}
|
|
146
|
+
return response;
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
logger.error('Error checking context:', error);
|
|
150
|
+
throw new Error(`Failed to check context: ${error}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Get metadata about the context store
|
|
155
|
+
*/
|
|
156
|
+
getMetadata() {
|
|
157
|
+
const entriesByCategory = {
|
|
158
|
+
architecture: 0,
|
|
159
|
+
requirements: 0,
|
|
160
|
+
constraints: 0,
|
|
161
|
+
decisions: 0,
|
|
162
|
+
'technical-patterns': 0,
|
|
163
|
+
'project-metadata': 0,
|
|
164
|
+
};
|
|
165
|
+
let totalBytes = 0;
|
|
166
|
+
this.store.entries.forEach((entry) => {
|
|
167
|
+
entriesByCategory[entry.category]++;
|
|
168
|
+
totalBytes += entry.content.length;
|
|
169
|
+
});
|
|
170
|
+
const estimatedTokens = totalBytes / AVG_CHARS_PER_TOKEN;
|
|
171
|
+
const usagePercent = (estimatedTokens / MAX_CONTEXT_WINDOW_TOKENS) * 100;
|
|
172
|
+
return {
|
|
173
|
+
total_entries: this.store.entries.length,
|
|
174
|
+
entries_by_category: entriesByCategory,
|
|
175
|
+
total_stored_bytes: totalBytes,
|
|
176
|
+
last_updated: new Date(this.store.metadata.last_updated),
|
|
177
|
+
context_window_usage_percent: Math.min(usagePercent, 100),
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Clear old or unused context entries (cleanup)
|
|
182
|
+
*/
|
|
183
|
+
async cleanup(daysOld = 30) {
|
|
184
|
+
this.ensureInitialized();
|
|
185
|
+
try {
|
|
186
|
+
const cutoffDate = new Date();
|
|
187
|
+
cutoffDate.setDate(cutoffDate.getDate() - daysOld);
|
|
188
|
+
const beforeCount = this.store.entries.length;
|
|
189
|
+
this.store.entries = this.store.entries.filter((entry) => {
|
|
190
|
+
const entryDate = new Date(entry.timestamp);
|
|
191
|
+
return entryDate > cutoffDate;
|
|
192
|
+
});
|
|
193
|
+
const removedCount = beforeCount - this.store.entries.length;
|
|
194
|
+
this.store.metadata.last_updated = new Date().toISOString();
|
|
195
|
+
this.save();
|
|
196
|
+
logger.info(`Cleaned up ${removedCount} context entries older than ${daysOld} days`);
|
|
197
|
+
return {
|
|
198
|
+
success: true,
|
|
199
|
+
action: 'retrieve',
|
|
200
|
+
message: `Removed ${removedCount} entries older than ${daysOld} days`,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
logger.error('Error cleaning context:', error);
|
|
205
|
+
throw new Error(`Failed to cleanup context: ${error}`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Export all context for backup
|
|
210
|
+
*/
|
|
211
|
+
async export() {
|
|
212
|
+
this.ensureInitialized();
|
|
213
|
+
return JSON.parse(JSON.stringify(this.store));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Import context from backup
|
|
217
|
+
*/
|
|
218
|
+
async import(store) {
|
|
219
|
+
try {
|
|
220
|
+
this.store = store;
|
|
221
|
+
this.store.metadata.last_updated = new Date().toISOString();
|
|
222
|
+
this.save();
|
|
223
|
+
logger.info('Imported context store');
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
logger.error('Error importing context:', error);
|
|
227
|
+
throw new Error(`Failed to import context: ${error}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Create default context store
|
|
232
|
+
*/
|
|
233
|
+
createDefaultStore() {
|
|
234
|
+
this.store = {
|
|
235
|
+
version: '1.0.0',
|
|
236
|
+
entries: [
|
|
237
|
+
{
|
|
238
|
+
id: nanoid(),
|
|
239
|
+
category: 'project-metadata',
|
|
240
|
+
content: 'CouchLoop MCP Server - Model Context Protocol server for stateful conversation management',
|
|
241
|
+
timestamp: new Date(),
|
|
242
|
+
usage_count: 0,
|
|
243
|
+
last_retrieved: null,
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
id: nanoid(),
|
|
247
|
+
category: 'architecture',
|
|
248
|
+
content: 'CouchLoop uses PostgreSQL via Supabase with Drizzle ORM. MCP protocol via stdio for communication. Session/journey/checkpoint management.',
|
|
249
|
+
timestamp: new Date(),
|
|
250
|
+
usage_count: 0,
|
|
251
|
+
last_retrieved: null,
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: nanoid(),
|
|
255
|
+
category: 'requirements',
|
|
256
|
+
content: 'Must support multi-turn conversations, session persistence across interruptions, guided journeys, crisis detection via shrink-chat integration',
|
|
257
|
+
timestamp: new Date(),
|
|
258
|
+
usage_count: 0,
|
|
259
|
+
last_retrieved: null,
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
metadata: {
|
|
263
|
+
created_at: new Date().toISOString(),
|
|
264
|
+
last_updated: new Date().toISOString(),
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Save store to disk
|
|
270
|
+
*/
|
|
271
|
+
save() {
|
|
272
|
+
try {
|
|
273
|
+
const dir = path.dirname(CONTEXT_STORE_PATH);
|
|
274
|
+
if (!fs.existsSync(dir)) {
|
|
275
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
276
|
+
}
|
|
277
|
+
fs.writeFileSync(CONTEXT_STORE_PATH, JSON.stringify(this.store, null, 2), 'utf-8');
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
logger.error('Failed to save context store:', error);
|
|
281
|
+
throw new Error(`Failed to persist context: ${error}`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Ensure manager is initialized
|
|
286
|
+
*/
|
|
287
|
+
ensureInitialized() {
|
|
288
|
+
if (!this.isInitialized) {
|
|
289
|
+
throw new Error('ContextManager not initialized. Call initialize() before using other methods.');
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// Singleton instance
|
|
294
|
+
let instance = null;
|
|
295
|
+
export async function getContextManager() {
|
|
296
|
+
if (!instance) {
|
|
297
|
+
instance = new ContextManager();
|
|
298
|
+
await instance.initialize();
|
|
299
|
+
}
|
|
300
|
+
return instance;
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=context-manager.js.map
|