@timmeck/brain 1.2.0 → 1.8.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/README.md +225 -50
- package/dist/api/server.d.ts +19 -0
- package/dist/api/server.js +281 -0
- package/dist/api/server.js.map +1 -0
- package/dist/brain.d.ts +3 -0
- package/dist/brain.js +45 -8
- package/dist/brain.js.map +1 -1
- package/dist/cli/commands/dashboard.js +2 -0
- package/dist/cli/commands/dashboard.js.map +1 -1
- package/dist/cli/commands/explain.d.ts +2 -0
- package/dist/cli/commands/explain.js +76 -0
- package/dist/cli/commands/explain.js.map +1 -0
- package/dist/code/analyzer.d.ts +6 -0
- package/dist/code/analyzer.js +35 -0
- package/dist/code/analyzer.js.map +1 -1
- package/dist/code/matcher.d.ts +11 -1
- package/dist/code/matcher.js +49 -0
- package/dist/code/matcher.js.map +1 -1
- package/dist/code/scorer.d.ts +1 -0
- package/dist/code/scorer.js +15 -1
- package/dist/code/scorer.js.map +1 -1
- package/dist/config.js +31 -0
- package/dist/config.js.map +1 -1
- package/dist/dashboard/server.d.ts +15 -0
- package/dist/dashboard/server.js +124 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/db/migrations/007_feedback.d.ts +2 -0
- package/dist/db/migrations/007_feedback.js +12 -0
- package/dist/db/migrations/007_feedback.js.map +1 -0
- package/dist/db/migrations/008_git_integration.d.ts +2 -0
- package/dist/db/migrations/008_git_integration.js +37 -0
- package/dist/db/migrations/008_git_integration.js.map +1 -0
- package/dist/db/migrations/009_embeddings.d.ts +2 -0
- package/dist/db/migrations/009_embeddings.js +7 -0
- package/dist/db/migrations/009_embeddings.js.map +1 -0
- package/dist/db/migrations/index.js +6 -0
- package/dist/db/migrations/index.js.map +1 -1
- package/dist/db/repositories/code-module.repository.d.ts +16 -0
- package/dist/db/repositories/code-module.repository.js +42 -0
- package/dist/db/repositories/code-module.repository.js.map +1 -1
- package/dist/db/repositories/error.repository.d.ts +5 -0
- package/dist/db/repositories/error.repository.js +27 -0
- package/dist/db/repositories/error.repository.js.map +1 -1
- package/dist/db/repositories/insight.repository.d.ts +2 -0
- package/dist/db/repositories/insight.repository.js +13 -0
- package/dist/db/repositories/insight.repository.js.map +1 -1
- package/dist/embeddings/engine.d.ts +42 -0
- package/dist/embeddings/engine.js +166 -0
- package/dist/embeddings/engine.js.map +1 -0
- package/dist/hooks/post-tool-use.js +2 -0
- package/dist/hooks/post-tool-use.js.map +1 -1
- package/dist/hooks/post-write.js +11 -0
- package/dist/hooks/post-write.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/ipc/router.d.ts +2 -0
- package/dist/ipc/router.js +13 -0
- package/dist/ipc/router.js.map +1 -1
- package/dist/learning/confidence-scorer.d.ts +16 -0
- package/dist/learning/confidence-scorer.js +20 -0
- package/dist/learning/confidence-scorer.js.map +1 -1
- package/dist/learning/learning-engine.js +12 -5
- package/dist/learning/learning-engine.js.map +1 -1
- package/dist/matching/error-matcher.d.ts +9 -1
- package/dist/matching/error-matcher.js +50 -5
- package/dist/matching/error-matcher.js.map +1 -1
- package/dist/mcp/http-server.d.ts +14 -0
- package/dist/mcp/http-server.js +117 -0
- package/dist/mcp/http-server.js.map +1 -0
- package/dist/mcp/tools.d.ts +4 -0
- package/dist/mcp/tools.js +41 -14
- package/dist/mcp/tools.js.map +1 -1
- package/dist/services/analytics.service.d.ts +39 -0
- package/dist/services/analytics.service.js +111 -0
- package/dist/services/analytics.service.js.map +1 -1
- package/dist/services/code.service.d.ts +2 -0
- package/dist/services/code.service.js +62 -4
- package/dist/services/code.service.js.map +1 -1
- package/dist/services/error.service.d.ts +17 -1
- package/dist/services/error.service.js +90 -12
- package/dist/services/error.service.js.map +1 -1
- package/dist/services/git.service.d.ts +49 -0
- package/dist/services/git.service.js +112 -0
- package/dist/services/git.service.js.map +1 -0
- package/dist/services/prevention.service.d.ts +7 -0
- package/dist/services/prevention.service.js +38 -0
- package/dist/services/prevention.service.js.map +1 -1
- package/dist/services/research.service.d.ts +1 -0
- package/dist/services/research.service.js +4 -0
- package/dist/services/research.service.js.map +1 -1
- package/dist/services/solution.service.d.ts +10 -0
- package/dist/services/solution.service.js +48 -0
- package/dist/services/solution.service.js.map +1 -1
- package/dist/types/config.types.d.ts +21 -0
- package/dist/types/synapse.types.d.ts +1 -1
- package/package.json +8 -3
- package/src/api/server.ts +321 -0
- package/src/brain.ts +50 -8
- package/src/cli/commands/dashboard.ts +2 -0
- package/src/cli/commands/explain.ts +83 -0
- package/src/code/analyzer.ts +40 -0
- package/src/code/matcher.ts +67 -2
- package/src/code/scorer.ts +13 -1
- package/src/config.ts +24 -0
- package/src/dashboard/server.ts +142 -0
- package/src/db/migrations/007_feedback.ts +13 -0
- package/src/db/migrations/008_git_integration.ts +38 -0
- package/src/db/migrations/009_embeddings.ts +8 -0
- package/src/db/migrations/index.ts +6 -0
- package/src/db/repositories/code-module.repository.ts +53 -0
- package/src/db/repositories/error.repository.ts +40 -0
- package/src/db/repositories/insight.repository.ts +21 -0
- package/src/embeddings/engine.ts +217 -0
- package/src/hooks/post-tool-use.ts +2 -0
- package/src/hooks/post-write.ts +12 -0
- package/src/index.ts +3 -1
- package/src/ipc/router.ts +16 -0
- package/src/learning/confidence-scorer.ts +33 -0
- package/src/learning/learning-engine.ts +13 -5
- package/src/matching/error-matcher.ts +55 -4
- package/src/mcp/http-server.ts +137 -0
- package/src/mcp/tools.ts +52 -14
- package/src/services/analytics.service.ts +136 -0
- package/src/services/code.service.ts +87 -4
- package/src/services/error.service.ts +114 -13
- package/src/services/git.service.ts +132 -0
- package/src/services/prevention.service.ts +40 -0
- package/src/services/research.service.ts +5 -0
- package/src/services/solution.service.ts +58 -0
- package/src/types/config.types.ts +24 -0
- package/src/types/synapse.types.ts +1 -0
package/dist/code/analyzer.js
CHANGED
|
@@ -24,6 +24,7 @@ export function analyzeCode(source, language) {
|
|
|
24
24
|
const isPure = checkPurity(source);
|
|
25
25
|
const typed = parser.hasTypeAnnotations(source);
|
|
26
26
|
const linesOfCode = source.split('\n').filter(l => l.trim().length > 0).length;
|
|
27
|
+
const complexity = computeCyclomaticComplexity(source, language);
|
|
27
28
|
return {
|
|
28
29
|
exports,
|
|
29
30
|
externalDeps: external,
|
|
@@ -31,8 +32,42 @@ export function analyzeCode(source, language) {
|
|
|
31
32
|
isPure,
|
|
32
33
|
hasTypeAnnotations: typed,
|
|
33
34
|
linesOfCode,
|
|
35
|
+
complexity,
|
|
34
36
|
};
|
|
35
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Computes cyclomatic complexity: counts decision points in the code.
|
|
40
|
+
* CC = 1 + number of decision points (if, else if, for, while, case, catch, &&, ||, ?:)
|
|
41
|
+
*/
|
|
42
|
+
export function computeCyclomaticComplexity(source, language) {
|
|
43
|
+
// Remove comments and strings to avoid false positives
|
|
44
|
+
const cleaned = source
|
|
45
|
+
.replace(/\/\/.*$/gm, '') // single-line comments
|
|
46
|
+
.replace(/\/\*[\s\S]*?\*\//g, '') // multi-line comments
|
|
47
|
+
.replace(/#.*$/gm, '') // Python comments
|
|
48
|
+
.replace(/(["'`])(?:(?!\1|\\).|\\.)*\1/g, '""'); // strings
|
|
49
|
+
let complexity = 1; // Base complexity
|
|
50
|
+
// Language-agnostic decision point patterns
|
|
51
|
+
const patterns = [
|
|
52
|
+
/\bif\b/g,
|
|
53
|
+
/\belse\s+if\b/g,
|
|
54
|
+
/\belif\b/g,
|
|
55
|
+
/\bfor\b/g,
|
|
56
|
+
/\bwhile\b/g,
|
|
57
|
+
/\bcase\b/g,
|
|
58
|
+
/\bcatch\b/g,
|
|
59
|
+
/\bexcept\b/g,
|
|
60
|
+
/&&/g,
|
|
61
|
+
/\|\|/g,
|
|
62
|
+
/\?\s*[^:]/g, // ternary operator (not type annotations)
|
|
63
|
+
];
|
|
64
|
+
for (const pattern of patterns) {
|
|
65
|
+
const matches = cleaned.match(pattern);
|
|
66
|
+
if (matches)
|
|
67
|
+
complexity += matches.length;
|
|
68
|
+
}
|
|
69
|
+
return complexity;
|
|
70
|
+
}
|
|
36
71
|
export function checkPurity(source) {
|
|
37
72
|
return !SIDE_EFFECT_PATTERNS.some(p => source.includes(p));
|
|
38
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/code/analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/code/analyzer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,QAAQ,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AAYtD,MAAM,oBAAoB,GAAG;IAC3B,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ;IAC1D,gBAAgB,EAAE,WAAW,EAAE,SAAS;IACxC,SAAS,EAAE,UAAU;CACtB,CAAC;AAEF,SAAS,SAAS,CAAC,QAAgB;IACjC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,YAAY,CAAC;QAClB,KAAK,YAAY;YACf,OAAO,QAAQ,CAAC;QAClB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB;YACE,OAAO,aAAa,CAAC;IACzB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,QAAgB;IAC1D,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9C,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/E,MAAM,UAAU,GAAG,2BAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEjE,OAAO;QACL,OAAO;QACP,YAAY,EAAE,QAAQ;QACtB,YAAY,EAAE,QAAQ;QACtB,MAAM;QACN,kBAAkB,EAAE,KAAK;QACzB,WAAW;QACX,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CAAC,MAAc,EAAE,QAAgB;IAC1E,uDAAuD;IACvD,MAAM,OAAO,GAAG,MAAM;SACnB,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAW,uBAAuB;SAC1D,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAG,sBAAsB;SACzD,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAc,kBAAkB;SACrD,OAAO,CAAC,+BAA+B,EAAE,IAAI,CAAC,CAAC,CAAC,UAAU;IAE7D,IAAI,UAAU,GAAG,CAAC,CAAC,CAAC,kBAAkB;IAEtC,4CAA4C;IAC5C,MAAM,QAAQ,GAAG;QACf,SAAS;QACT,gBAAgB;QAChB,WAAW;QACX,UAAU;QACV,YAAY;QACZ,WAAW;QACX,YAAY;QACZ,aAAa;QACb,KAAK;QACL,OAAO;QACP,YAAY,EAAE,0CAA0C;KACzD,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,OAAO;YAAE,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAC5C,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAqB;IACnD,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAEpC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAC5B,CAAC,CAAC,IAAI;SACH,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,OAAO,CAAC,mBAAmB,EAAE,OAAO,CAAC;SACrC,WAAW,EAAE;SACb,KAAK,CAAC,KAAK,CAAC,CAChB,CAAC;IAEF,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3D,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAC1D,IAAI,KAAK,GAAG,CAAC;YAAE,YAAY,IAAI,KAAK,CAAC;IACvC,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC;IAC9C,OAAO,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,WAAW,CAAC;AAC5D,CAAC"}
|
package/dist/code/matcher.d.ts
CHANGED
|
@@ -2,8 +2,18 @@ import type { CodeModuleRecord } from '../types/code.types.js';
|
|
|
2
2
|
export interface CodeMatchResult {
|
|
3
3
|
moduleId: number;
|
|
4
4
|
score: number;
|
|
5
|
-
matchType: 'exact' | 'structural' | 'semantic';
|
|
5
|
+
matchType: 'exact' | 'structural' | 'semantic' | 'vector';
|
|
6
6
|
}
|
|
7
7
|
export declare function findExactMatches(fingerprint: string, candidates: CodeModuleRecord[]): CodeMatchResult[];
|
|
8
8
|
export declare function findStructuralMatches(source: string, language: string, candidates: CodeModuleRecord[], threshold?: number): CodeMatchResult[];
|
|
9
9
|
export declare function findSemanticMatches(description: string, candidates: CodeModuleRecord[], threshold?: number): CodeMatchResult[];
|
|
10
|
+
/**
|
|
11
|
+
* Find matches using pre-computed vector embeddings.
|
|
12
|
+
* Vector scores are computed externally (by the EmbeddingEngine) and passed in.
|
|
13
|
+
*/
|
|
14
|
+
export declare function findVectorMatches(vectorScores: Map<number, number>, threshold?: number): CodeMatchResult[];
|
|
15
|
+
/**
|
|
16
|
+
* Hybrid search: combine structural + semantic + vector matches,
|
|
17
|
+
* deduplicating and taking the highest score per module.
|
|
18
|
+
*/
|
|
19
|
+
export declare function findHybridMatches(source: string, language: string, description: string, candidates: CodeModuleRecord[], vectorScores?: Map<number, number>): CodeMatchResult[];
|
package/dist/code/matcher.js
CHANGED
|
@@ -34,4 +34,53 @@ export function findSemanticMatches(description, candidates, threshold = 0.5) {
|
|
|
34
34
|
.filter(r => r.score >= threshold)
|
|
35
35
|
.sort((a, b) => b.score - a.score);
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Find matches using pre-computed vector embeddings.
|
|
39
|
+
* Vector scores are computed externally (by the EmbeddingEngine) and passed in.
|
|
40
|
+
*/
|
|
41
|
+
export function findVectorMatches(vectorScores, threshold = 0.5) {
|
|
42
|
+
const results = [];
|
|
43
|
+
for (const [moduleId, score] of vectorScores) {
|
|
44
|
+
if (score >= threshold) {
|
|
45
|
+
results.push({ moduleId, score, matchType: 'vector' });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return results.sort((a, b) => b.score - a.score);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Hybrid search: combine structural + semantic + vector matches,
|
|
52
|
+
* deduplicating and taking the highest score per module.
|
|
53
|
+
*/
|
|
54
|
+
export function findHybridMatches(source, language, description, candidates, vectorScores) {
|
|
55
|
+
const scoreMap = new Map();
|
|
56
|
+
// Structural matches (highest priority)
|
|
57
|
+
for (const match of findStructuralMatches(source, language, candidates, 0.5)) {
|
|
58
|
+
const existing = scoreMap.get(match.moduleId);
|
|
59
|
+
if (!existing || match.score > existing.score) {
|
|
60
|
+
scoreMap.set(match.moduleId, match);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Semantic matches
|
|
64
|
+
for (const match of findSemanticMatches(description, candidates, 0.3)) {
|
|
65
|
+
const existing = scoreMap.get(match.moduleId);
|
|
66
|
+
if (!existing || match.score > existing.score) {
|
|
67
|
+
scoreMap.set(match.moduleId, match);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Vector matches (if available)
|
|
71
|
+
if (vectorScores && vectorScores.size > 0) {
|
|
72
|
+
for (const match of findVectorMatches(vectorScores, 0.4)) {
|
|
73
|
+
const existing = scoreMap.get(match.moduleId);
|
|
74
|
+
if (!existing) {
|
|
75
|
+
scoreMap.set(match.moduleId, match);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// Boost existing matches that also have high vector similarity
|
|
79
|
+
const vectorBoost = match.score * 0.15;
|
|
80
|
+
existing.score = Math.min(1.0, existing.score + vectorBoost);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return [...scoreMap.values()].sort((a, b) => b.score - a.score);
|
|
85
|
+
}
|
|
37
86
|
//# sourceMappingURL=matcher.js.map
|
package/dist/code/matcher.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../src/code/matcher.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"matcher.js","sourceRoot":"","sources":["../../src/code/matcher.ts"],"names":[],"mappings":"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"}
|
package/dist/code/scorer.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export interface CodeUnitForScoring {
|
|
|
5
5
|
exports: ExportInfo[];
|
|
6
6
|
internalDeps: string[];
|
|
7
7
|
hasTypeAnnotations: boolean;
|
|
8
|
+
complexity?: number;
|
|
8
9
|
}
|
|
9
10
|
export declare const MODULE_THRESHOLD = 0.6;
|
|
10
11
|
export declare function computeReusabilityScore(code: CodeUnitForScoring): number;
|
package/dist/code/scorer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const REUSABILITY_SIGNALS = [
|
|
2
2
|
{
|
|
3
3
|
name: 'single_responsibility',
|
|
4
|
-
weight: 0.
|
|
4
|
+
weight: 0.20,
|
|
5
5
|
check: (code) => {
|
|
6
6
|
const count = code.exports.length;
|
|
7
7
|
if (count === 0)
|
|
@@ -85,6 +85,20 @@ const REUSABILITY_SIGNALS = [
|
|
|
85
85
|
return 0.1;
|
|
86
86
|
},
|
|
87
87
|
},
|
|
88
|
+
{
|
|
89
|
+
name: 'low_complexity',
|
|
90
|
+
weight: 0.10,
|
|
91
|
+
check: (code) => {
|
|
92
|
+
const cc = code.complexity ?? 1;
|
|
93
|
+
if (cc <= 5)
|
|
94
|
+
return 1.0;
|
|
95
|
+
if (cc <= 10)
|
|
96
|
+
return 0.7;
|
|
97
|
+
if (cc <= 20)
|
|
98
|
+
return 0.4;
|
|
99
|
+
return 0.1;
|
|
100
|
+
},
|
|
101
|
+
},
|
|
88
102
|
];
|
|
89
103
|
export const MODULE_THRESHOLD = 0.60;
|
|
90
104
|
export function computeReusabilityScore(code) {
|
package/dist/code/scorer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scorer.js","sourceRoot":"","sources":["../../src/code/scorer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scorer.js","sourceRoot":"","sources":["../../src/code/scorer.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -8,6 +8,21 @@ const defaults = {
|
|
|
8
8
|
pipeName: getPipeName(),
|
|
9
9
|
timeout: 5000,
|
|
10
10
|
},
|
|
11
|
+
api: {
|
|
12
|
+
port: 7777,
|
|
13
|
+
enabled: true,
|
|
14
|
+
},
|
|
15
|
+
mcpHttp: {
|
|
16
|
+
port: 7778,
|
|
17
|
+
enabled: true,
|
|
18
|
+
},
|
|
19
|
+
embeddings: {
|
|
20
|
+
enabled: true,
|
|
21
|
+
modelName: 'Xenova/all-MiniLM-L6-v2',
|
|
22
|
+
cacheDir: path.join(getDataDir(), 'models'),
|
|
23
|
+
sweepIntervalMs: 300_000, // 5 minutes
|
|
24
|
+
batchSize: 50,
|
|
25
|
+
},
|
|
11
26
|
learning: {
|
|
12
27
|
intervalMs: 900_000,
|
|
13
28
|
minOccurrences: 3,
|
|
@@ -25,6 +40,8 @@ const defaults = {
|
|
|
25
40
|
fingerprintFields: ['type', 'message', 'file_path'],
|
|
26
41
|
similarityThreshold: 0.8,
|
|
27
42
|
maxResults: 10,
|
|
43
|
+
crossProjectMatching: true,
|
|
44
|
+
crossProjectWeight: 0.7,
|
|
28
45
|
},
|
|
29
46
|
code: {
|
|
30
47
|
supportedLanguages: ['typescript', 'javascript', 'python', 'rust', 'go'],
|
|
@@ -74,6 +91,20 @@ function applyEnvOverrides(config) {
|
|
|
74
91
|
config.log.level = process.env['BRAIN_LOG_LEVEL'];
|
|
75
92
|
if (process.env['BRAIN_PIPE_NAME'])
|
|
76
93
|
config.ipc.pipeName = process.env['BRAIN_PIPE_NAME'];
|
|
94
|
+
if (process.env['BRAIN_API_PORT'])
|
|
95
|
+
config.api.port = Number(process.env['BRAIN_API_PORT']);
|
|
96
|
+
if (process.env['BRAIN_API_ENABLED'])
|
|
97
|
+
config.api.enabled = process.env['BRAIN_API_ENABLED'] !== 'false';
|
|
98
|
+
if (process.env['BRAIN_API_KEY'])
|
|
99
|
+
config.api.apiKey = process.env['BRAIN_API_KEY'];
|
|
100
|
+
if (process.env['BRAIN_MCP_HTTP_PORT'])
|
|
101
|
+
config.mcpHttp.port = Number(process.env['BRAIN_MCP_HTTP_PORT']);
|
|
102
|
+
if (process.env['BRAIN_MCP_HTTP_ENABLED'])
|
|
103
|
+
config.mcpHttp.enabled = process.env['BRAIN_MCP_HTTP_ENABLED'] !== 'false';
|
|
104
|
+
if (process.env['BRAIN_EMBEDDINGS_ENABLED'])
|
|
105
|
+
config.embeddings.enabled = process.env['BRAIN_EMBEDDINGS_ENABLED'] !== 'false';
|
|
106
|
+
if (process.env['BRAIN_EMBEDDINGS_MODEL'])
|
|
107
|
+
config.embeddings.modelName = process.env['BRAIN_EMBEDDINGS_MODEL'];
|
|
77
108
|
}
|
|
78
109
|
function deepMerge(target, source) {
|
|
79
110
|
for (const key of Object.keys(source)) {
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE3D,MAAM,QAAQ,GAAgB;IAC5B,OAAO,EAAE,UAAU,EAAE;IACrB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,UAAU,CAAC;IAC3C,GAAG,EAAE;QACH,QAAQ,EAAE,WAAW,EAAE;QACvB,OAAO,EAAE,IAAI;KACd;IACD,QAAQ,EAAE;QACR,UAAU,EAAE,OAAO;QACnB,cAAc,EAAE,CAAC;QACjB,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,IAAI;QACnB,cAAc,EAAE,IAAI;QACpB,gBAAgB,EAAE,IAAI;QACtB,iBAAiB,EAAE,EAAE;KACtB;IACD,QAAQ,EAAE;QACR,YAAY,EAAE,MAAM,EAAE,QAAQ;QAC9B,YAAY,EAAE,EAAE;KACjB;IACD,QAAQ,EAAE;QACR,iBAAiB,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC;QACnD,mBAAmB,EAAE,GAAG;QACxB,UAAU,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface DashboardServerOptions {
|
|
2
|
+
port: number;
|
|
3
|
+
getDashboardHtml: () => string;
|
|
4
|
+
getStats: () => unknown;
|
|
5
|
+
}
|
|
6
|
+
export declare class DashboardServer {
|
|
7
|
+
private options;
|
|
8
|
+
private server;
|
|
9
|
+
private clients;
|
|
10
|
+
private logger;
|
|
11
|
+
constructor(options: DashboardServerOptions);
|
|
12
|
+
start(): void;
|
|
13
|
+
stop(): void;
|
|
14
|
+
private broadcast;
|
|
15
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import { getEventBus } from '../utils/events.js';
|
|
3
|
+
import { getLogger } from '../utils/logger.js';
|
|
4
|
+
export class DashboardServer {
|
|
5
|
+
options;
|
|
6
|
+
server = null;
|
|
7
|
+
clients = new Set();
|
|
8
|
+
logger = getLogger();
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
}
|
|
12
|
+
start() {
|
|
13
|
+
const { port, getDashboardHtml, getStats } = this.options;
|
|
14
|
+
const bus = getEventBus();
|
|
15
|
+
this.server = http.createServer((req, res) => {
|
|
16
|
+
const url = new URL(req.url ?? '/', `http://localhost:${port}`);
|
|
17
|
+
// CORS
|
|
18
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
19
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
|
|
20
|
+
if (req.method === 'OPTIONS') {
|
|
21
|
+
res.writeHead(204);
|
|
22
|
+
res.end();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (url.pathname === '/events') {
|
|
26
|
+
// SSE endpoint
|
|
27
|
+
res.writeHead(200, {
|
|
28
|
+
'Content-Type': 'text/event-stream',
|
|
29
|
+
'Cache-Control': 'no-cache',
|
|
30
|
+
'Connection': 'keep-alive',
|
|
31
|
+
});
|
|
32
|
+
res.write('data: {"type":"connected"}\n\n');
|
|
33
|
+
this.clients.add(res);
|
|
34
|
+
req.on('close', () => this.clients.delete(res));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (url.pathname === '/api/stats') {
|
|
38
|
+
const stats = getStats();
|
|
39
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
40
|
+
res.end(JSON.stringify(stats));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (url.pathname === '/' || url.pathname === '/dashboard') {
|
|
44
|
+
const html = getDashboardHtml();
|
|
45
|
+
// Inject SSE script into the dashboard
|
|
46
|
+
const sseScript = `
|
|
47
|
+
<script>
|
|
48
|
+
(function(){
|
|
49
|
+
const evtSource = new EventSource('/events');
|
|
50
|
+
evtSource.onmessage = function(e) {
|
|
51
|
+
try {
|
|
52
|
+
const data = JSON.parse(e.data);
|
|
53
|
+
if (data.type === 'stats_update') {
|
|
54
|
+
// Update stat cards
|
|
55
|
+
document.querySelectorAll('.stat-number').forEach(el => {
|
|
56
|
+
const key = el.parentElement?.querySelector('.stat-label')?.textContent?.toLowerCase();
|
|
57
|
+
if (key && data.stats[key] !== undefined) {
|
|
58
|
+
el.textContent = Number(data.stats[key]).toLocaleString();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (data.type === 'event') {
|
|
63
|
+
// Flash the activity dot
|
|
64
|
+
const dot = document.querySelector('.activity-dot');
|
|
65
|
+
if (dot) { dot.style.background = '#ff5577'; setTimeout(() => dot.style.background = '', 500); }
|
|
66
|
+
}
|
|
67
|
+
} catch {}
|
|
68
|
+
};
|
|
69
|
+
evtSource.onerror = function() { setTimeout(() => location.reload(), 5000); };
|
|
70
|
+
})();
|
|
71
|
+
</script>`;
|
|
72
|
+
const liveHtml = html.replace('</body>', sseScript + '</body>');
|
|
73
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
74
|
+
res.end(liveHtml);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
78
|
+
res.end('Not Found');
|
|
79
|
+
});
|
|
80
|
+
// Forward Brain events to SSE clients
|
|
81
|
+
const eventNames = [
|
|
82
|
+
'error:reported', 'error:resolved', 'solution:applied',
|
|
83
|
+
'solution:created', 'module:registered', 'module:updated',
|
|
84
|
+
'synapse:created', 'synapse:strengthened',
|
|
85
|
+
'insight:created', 'rule:learned',
|
|
86
|
+
];
|
|
87
|
+
for (const eventName of eventNames) {
|
|
88
|
+
bus.on(eventName, (data) => {
|
|
89
|
+
this.broadcast({ type: 'event', event: eventName, data });
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// Periodic stats broadcast (every 30s)
|
|
93
|
+
setInterval(() => {
|
|
94
|
+
if (this.clients.size > 0) {
|
|
95
|
+
const stats = getStats();
|
|
96
|
+
this.broadcast({ type: 'stats_update', stats });
|
|
97
|
+
}
|
|
98
|
+
}, 30_000);
|
|
99
|
+
this.server.listen(port, () => {
|
|
100
|
+
this.logger.info(`Dashboard server started on http://localhost:${port}`);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
stop() {
|
|
104
|
+
for (const client of this.clients) {
|
|
105
|
+
client.end();
|
|
106
|
+
}
|
|
107
|
+
this.clients.clear();
|
|
108
|
+
this.server?.close();
|
|
109
|
+
this.server = null;
|
|
110
|
+
this.logger.info('Dashboard server stopped');
|
|
111
|
+
}
|
|
112
|
+
broadcast(data) {
|
|
113
|
+
const msg = `data: ${JSON.stringify(data)}\n\n`;
|
|
114
|
+
for (const client of this.clients) {
|
|
115
|
+
try {
|
|
116
|
+
client.write(msg);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
this.clients.delete(client);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function up(db) {
|
|
2
|
+
db.exec(`
|
|
3
|
+
ALTER TABLE insights ADD COLUMN rating INTEGER DEFAULT NULL;
|
|
4
|
+
ALTER TABLE insights ADD COLUMN rating_comment TEXT DEFAULT NULL;
|
|
5
|
+
ALTER TABLE insights ADD COLUMN rated_at TEXT DEFAULT NULL;
|
|
6
|
+
|
|
7
|
+
ALTER TABLE rules ADD COLUMN rating INTEGER DEFAULT NULL;
|
|
8
|
+
ALTER TABLE rules ADD COLUMN rating_comment TEXT DEFAULT NULL;
|
|
9
|
+
ALTER TABLE rules ADD COLUMN rated_at TEXT DEFAULT NULL;
|
|
10
|
+
`);
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=007_feedback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"007_feedback.js","sourceRoot":"","sources":["../../../src/db/migrations/007_feedback.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,EAAE,CAAC,EAAqB;IACtC,EAAE,CAAC,IAAI,CAAC;;;;;;;;GAQP,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function up(db) {
|
|
2
|
+
db.exec(`
|
|
3
|
+
CREATE TABLE IF NOT EXISTS git_commits (
|
|
4
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
5
|
+
project_id INTEGER NOT NULL,
|
|
6
|
+
commit_hash TEXT NOT NULL,
|
|
7
|
+
message TEXT NOT NULL,
|
|
8
|
+
author TEXT,
|
|
9
|
+
timestamp TEXT NOT NULL,
|
|
10
|
+
files_changed INTEGER NOT NULL DEFAULT 0,
|
|
11
|
+
insertions INTEGER NOT NULL DEFAULT 0,
|
|
12
|
+
deletions INTEGER NOT NULL DEFAULT 0,
|
|
13
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
14
|
+
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
15
|
+
UNIQUE(project_id, commit_hash)
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
CREATE TABLE IF NOT EXISTS error_commits (
|
|
19
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
20
|
+
error_id INTEGER NOT NULL,
|
|
21
|
+
commit_hash TEXT NOT NULL,
|
|
22
|
+
relationship TEXT NOT NULL DEFAULT 'introduced_by',
|
|
23
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
24
|
+
FOREIGN KEY (error_id) REFERENCES errors(id) ON DELETE CASCADE,
|
|
25
|
+
UNIQUE(error_id, commit_hash, relationship)
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
ALTER TABLE errors ADD COLUMN git_diff TEXT DEFAULT NULL;
|
|
29
|
+
ALTER TABLE errors ADD COLUMN git_branch TEXT DEFAULT NULL;
|
|
30
|
+
|
|
31
|
+
CREATE INDEX IF NOT EXISTS idx_git_commits_project ON git_commits(project_id);
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_git_commits_hash ON git_commits(commit_hash);
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_error_commits_error ON error_commits(error_id);
|
|
34
|
+
CREATE INDEX IF NOT EXISTS idx_error_commits_hash ON error_commits(commit_hash);
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=008_git_integration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"008_git_integration.js","sourceRoot":"","sources":["../../../src/db/migrations/008_git_integration.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,EAAE,CAAC,EAAqB;IACtC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCP,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"009_embeddings.js","sourceRoot":"","sources":["../../../src/db/migrations/009_embeddings.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,EAAE,CAAC,EAAqB;IACtC,EAAE,CAAC,IAAI,CAAC;;;GAGP,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -5,6 +5,9 @@ import { up as codeSchema } from './003_code_schema.js';
|
|
|
5
5
|
import { up as synapsesSchema } from './004_synapses_schema.js';
|
|
6
6
|
import { up as ftsIndexes } from './005_fts_indexes.js';
|
|
7
7
|
import { up as synapsesPhase3 } from './006_synapses_phase3.js';
|
|
8
|
+
import { up as feedbackSchema } from './007_feedback.js';
|
|
9
|
+
import { up as gitIntegration } from './008_git_integration.js';
|
|
10
|
+
import { up as embeddings } from './009_embeddings.js';
|
|
8
11
|
const migrations = [
|
|
9
12
|
{ version: 1, name: '001_core_schema', up: coreSchema },
|
|
10
13
|
{ version: 2, name: '002_learning_schema', up: learningSchema },
|
|
@@ -12,6 +15,9 @@ const migrations = [
|
|
|
12
15
|
{ version: 4, name: '004_synapses_schema', up: synapsesSchema },
|
|
13
16
|
{ version: 5, name: '005_fts_indexes', up: ftsIndexes },
|
|
14
17
|
{ version: 6, name: '006_synapses_phase3', up: synapsesPhase3 },
|
|
18
|
+
{ version: 7, name: '007_feedback', up: feedbackSchema },
|
|
19
|
+
{ version: 8, name: '008_git_integration', up: gitIntegration },
|
|
20
|
+
{ version: 9, name: '009_embeddings', up: embeddings },
|
|
15
21
|
];
|
|
16
22
|
function ensureMigrationsTable(db) {
|
|
17
23
|
db.exec(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/db/migrations/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,EAAE,IAAI,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,EAAE,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,EAAE,IAAI,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,EAAE,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,EAAE,IAAI,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,EAAE,IAAI,cAAc,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/db/migrations/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,5 +16,21 @@ export declare class CodeModuleRepository {
|
|
|
16
16
|
search(query: string): CodeModuleRecord[];
|
|
17
17
|
findAll(limit?: number): CodeModuleRecord[];
|
|
18
18
|
countAll(): number;
|
|
19
|
+
upsertSimilarity(moduleAId: number, moduleBId: number, score: number): void;
|
|
20
|
+
findSimilarModules(moduleId: number, limit?: number): Array<{
|
|
21
|
+
module_id: number;
|
|
22
|
+
similarity_score: number;
|
|
23
|
+
name: string;
|
|
24
|
+
file_path: string;
|
|
25
|
+
}>;
|
|
26
|
+
findHighSimilarityPairs(minScore?: number, limit?: number): Array<{
|
|
27
|
+
module_a_id: number;
|
|
28
|
+
module_b_id: number;
|
|
29
|
+
similarity_score: number;
|
|
30
|
+
a_name: string;
|
|
31
|
+
a_path: string;
|
|
32
|
+
b_name: string;
|
|
33
|
+
b_path: string;
|
|
34
|
+
}>;
|
|
19
35
|
}
|
|
20
36
|
export {};
|
|
@@ -19,6 +19,33 @@ export class CodeModuleRepository {
|
|
|
19
19
|
JOIN code_modules_fts fts ON cm.id = fts.rowid
|
|
20
20
|
WHERE code_modules_fts MATCH ?
|
|
21
21
|
ORDER BY rank
|
|
22
|
+
`),
|
|
23
|
+
upsertSimilarity: db.prepare(`
|
|
24
|
+
INSERT INTO module_similarities (module_a_id, module_b_id, similarity_score)
|
|
25
|
+
VALUES (@module_a_id, @module_b_id, @similarity_score)
|
|
26
|
+
ON CONFLICT(module_a_id, module_b_id)
|
|
27
|
+
DO UPDATE SET similarity_score = @similarity_score, computed_at = datetime('now')
|
|
28
|
+
`),
|
|
29
|
+
findSimilarModules: db.prepare(`
|
|
30
|
+
SELECT ms.*, cm.name, cm.file_path, cm.language, cm.reusability_score
|
|
31
|
+
FROM module_similarities ms
|
|
32
|
+
JOIN code_modules cm ON (
|
|
33
|
+
CASE WHEN ms.module_a_id = ? THEN ms.module_b_id ELSE ms.module_a_id END
|
|
34
|
+
) = cm.id
|
|
35
|
+
WHERE ms.module_a_id = ? OR ms.module_b_id = ?
|
|
36
|
+
ORDER BY ms.similarity_score DESC
|
|
37
|
+
LIMIT ?
|
|
38
|
+
`),
|
|
39
|
+
findHighSimilarityPairs: db.prepare(`
|
|
40
|
+
SELECT ms.*,
|
|
41
|
+
a.name as a_name, a.file_path as a_path,
|
|
42
|
+
b.name as b_name, b.file_path as b_path
|
|
43
|
+
FROM module_similarities ms
|
|
44
|
+
JOIN code_modules a ON ms.module_a_id = a.id
|
|
45
|
+
JOIN code_modules b ON ms.module_b_id = b.id
|
|
46
|
+
WHERE ms.similarity_score >= ?
|
|
47
|
+
ORDER BY ms.similarity_score DESC
|
|
48
|
+
LIMIT ?
|
|
22
49
|
`),
|
|
23
50
|
};
|
|
24
51
|
}
|
|
@@ -68,5 +95,20 @@ export class CodeModuleRepository {
|
|
|
68
95
|
countAll() {
|
|
69
96
|
return this.stmts.countAll.get().count;
|
|
70
97
|
}
|
|
98
|
+
upsertSimilarity(moduleAId, moduleBId, score) {
|
|
99
|
+
// Always store with smaller id first for consistency
|
|
100
|
+
const [a, b] = moduleAId < moduleBId ? [moduleAId, moduleBId] : [moduleBId, moduleAId];
|
|
101
|
+
this.stmts.upsertSimilarity.run({
|
|
102
|
+
module_a_id: a,
|
|
103
|
+
module_b_id: b,
|
|
104
|
+
similarity_score: score,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
findSimilarModules(moduleId, limit = 10) {
|
|
108
|
+
return this.stmts.findSimilarModules.all(moduleId, moduleId, moduleId, limit);
|
|
109
|
+
}
|
|
110
|
+
findHighSimilarityPairs(minScore = 0.75, limit = 50) {
|
|
111
|
+
return this.stmts.findHighSimilarityPairs.all(minScore, limit);
|
|
112
|
+
}
|
|
71
113
|
}
|
|
72
114
|
//# sourceMappingURL=code-module.repository.js.map
|