@timmeck/brain 1.9.0 → 2.0.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.
Files changed (214) hide show
  1. package/README.md +19 -0
  2. package/brain.log +1164 -0
  3. package/{src/cli/commands/dashboard.ts → dashboard.html} +688 -807
  4. package/dist/api/server.d.ts +4 -18
  5. package/dist/api/server.js +4 -173
  6. package/dist/api/server.js.map +1 -1
  7. package/dist/brain.d.ts +1 -0
  8. package/dist/brain.js +6 -1
  9. package/dist/brain.js.map +1 -1
  10. package/dist/cli/colors.d.ts +4 -25
  11. package/dist/cli/colors.js +3 -89
  12. package/dist/cli/colors.js.map +1 -1
  13. package/dist/cli/commands/peers.d.ts +2 -0
  14. package/dist/cli/commands/peers.js +38 -0
  15. package/dist/cli/commands/peers.js.map +1 -0
  16. package/dist/db/connection.d.ts +1 -2
  17. package/dist/db/connection.js +1 -18
  18. package/dist/db/connection.js.map +1 -1
  19. package/dist/index.js +3 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/ipc/__tests__/protocol.test.d.ts +1 -0
  22. package/dist/ipc/__tests__/protocol.test.js +117 -0
  23. package/dist/ipc/__tests__/protocol.test.js.map +1 -0
  24. package/dist/ipc/client.d.ts +1 -16
  25. package/dist/ipc/client.js +1 -100
  26. package/dist/ipc/client.js.map +1 -1
  27. package/dist/ipc/protocol.d.ts +1 -8
  28. package/dist/ipc/protocol.js +1 -28
  29. package/dist/ipc/protocol.js.map +1 -1
  30. package/dist/ipc/router.js +8 -0
  31. package/dist/ipc/router.js.map +1 -1
  32. package/dist/ipc/server.d.ts +1 -22
  33. package/dist/ipc/server.js +1 -163
  34. package/dist/ipc/server.js.map +1 -1
  35. package/dist/mcp/http-server.d.ts +1 -7
  36. package/dist/mcp/http-server.js +6 -117
  37. package/dist/mcp/http-server.js.map +1 -1
  38. package/dist/mcp/server.js +5 -61
  39. package/dist/mcp/server.js.map +1 -1
  40. package/dist/signals/__tests__/fingerprint.test.d.ts +1 -0
  41. package/dist/signals/__tests__/fingerprint.test.js +118 -0
  42. package/dist/signals/__tests__/fingerprint.test.js.map +1 -0
  43. package/dist/types/ipc.types.d.ts +1 -11
  44. package/dist/utils/__tests__/hash.test.d.ts +1 -0
  45. package/dist/utils/__tests__/hash.test.js +32 -0
  46. package/dist/utils/__tests__/hash.test.js.map +1 -0
  47. package/dist/utils/__tests__/paths.test.d.ts +1 -0
  48. package/dist/utils/__tests__/paths.test.js +75 -0
  49. package/dist/utils/__tests__/paths.test.js.map +1 -0
  50. package/dist/utils/events.d.ts +4 -8
  51. package/dist/utils/events.js +2 -14
  52. package/dist/utils/events.js.map +1 -1
  53. package/dist/utils/hash.d.ts +1 -1
  54. package/dist/utils/hash.js +1 -4
  55. package/dist/utils/hash.js.map +1 -1
  56. package/dist/utils/logger.d.ts +3 -2
  57. package/dist/utils/logger.js +8 -35
  58. package/dist/utils/logger.js.map +1 -1
  59. package/dist/utils/paths.d.ts +2 -1
  60. package/dist/utils/paths.js +4 -13
  61. package/dist/utils/paths.js.map +1 -1
  62. package/package.json +2 -1
  63. package/BRAIN_PLAN.md +0 -3324
  64. package/reddit_post.md +0 -45
  65. package/src/api/server.ts +0 -395
  66. package/src/brain.ts +0 -313
  67. package/src/cli/colors.ts +0 -116
  68. package/src/cli/commands/config.ts +0 -169
  69. package/src/cli/commands/doctor.ts +0 -124
  70. package/src/cli/commands/explain.ts +0 -83
  71. package/src/cli/commands/export.ts +0 -31
  72. package/src/cli/commands/import.ts +0 -199
  73. package/src/cli/commands/insights.ts +0 -65
  74. package/src/cli/commands/learn.ts +0 -24
  75. package/src/cli/commands/modules.ts +0 -53
  76. package/src/cli/commands/network.ts +0 -67
  77. package/src/cli/commands/projects.ts +0 -42
  78. package/src/cli/commands/query.ts +0 -120
  79. package/src/cli/commands/start.ts +0 -105
  80. package/src/cli/commands/status.ts +0 -75
  81. package/src/cli/commands/stop.ts +0 -34
  82. package/src/cli/ipc-helper.ts +0 -22
  83. package/src/cli/update-check.ts +0 -63
  84. package/src/code/analyzer.ts +0 -117
  85. package/src/code/fingerprint.ts +0 -87
  86. package/src/code/matcher.ts +0 -129
  87. package/src/code/parsers/generic.ts +0 -29
  88. package/src/code/parsers/python.ts +0 -54
  89. package/src/code/parsers/typescript.ts +0 -65
  90. package/src/code/registry.ts +0 -60
  91. package/src/code/scorer.ts +0 -120
  92. package/src/config.ts +0 -135
  93. package/src/dashboard/server.ts +0 -142
  94. package/src/db/connection.ts +0 -22
  95. package/src/db/migrations/001_core_schema.ts +0 -120
  96. package/src/db/migrations/002_learning_schema.ts +0 -38
  97. package/src/db/migrations/003_code_schema.ts +0 -53
  98. package/src/db/migrations/004_synapses_schema.ts +0 -57
  99. package/src/db/migrations/005_fts_indexes.ts +0 -78
  100. package/src/db/migrations/006_synapses_phase3.ts +0 -17
  101. package/src/db/migrations/007_feedback.ts +0 -13
  102. package/src/db/migrations/008_git_integration.ts +0 -38
  103. package/src/db/migrations/009_embeddings.ts +0 -8
  104. package/src/db/migrations/index.ts +0 -70
  105. package/src/db/repositories/antipattern.repository.ts +0 -66
  106. package/src/db/repositories/code-module.repository.ts +0 -142
  107. package/src/db/repositories/error.repository.ts +0 -189
  108. package/src/db/repositories/insight.repository.ts +0 -99
  109. package/src/db/repositories/notification.repository.ts +0 -66
  110. package/src/db/repositories/project.repository.ts +0 -93
  111. package/src/db/repositories/rule.repository.ts +0 -108
  112. package/src/db/repositories/solution.repository.ts +0 -154
  113. package/src/db/repositories/synapse.repository.ts +0 -163
  114. package/src/db/repositories/terminal.repository.ts +0 -101
  115. package/src/embeddings/engine.ts +0 -238
  116. package/src/hooks/post-tool-use.ts +0 -92
  117. package/src/hooks/post-write.ts +0 -129
  118. package/src/index.ts +0 -63
  119. package/src/ipc/client.ts +0 -118
  120. package/src/ipc/protocol.ts +0 -35
  121. package/src/ipc/router.ts +0 -133
  122. package/src/ipc/server.ts +0 -176
  123. package/src/learning/confidence-scorer.ts +0 -80
  124. package/src/learning/decay.ts +0 -46
  125. package/src/learning/learning-engine.ts +0 -170
  126. package/src/learning/pattern-extractor.ts +0 -90
  127. package/src/learning/rule-generator.ts +0 -74
  128. package/src/main.rs:10:5 +0 -0
  129. package/src/matching/error-matcher.ts +0 -166
  130. package/src/matching/fingerprint.ts +0 -34
  131. package/src/matching/similarity.ts +0 -61
  132. package/src/matching/tfidf.ts +0 -74
  133. package/src/matching/tokenizer.ts +0 -41
  134. package/src/mcp/auto-detect.ts +0 -93
  135. package/src/mcp/http-server.ts +0 -140
  136. package/src/mcp/server.ts +0 -73
  137. package/src/mcp/tools.ts +0 -328
  138. package/src/parsing/error-parser.ts +0 -28
  139. package/src/parsing/parsers/compiler.ts +0 -93
  140. package/src/parsing/parsers/generic.ts +0 -28
  141. package/src/parsing/parsers/go.ts +0 -97
  142. package/src/parsing/parsers/node.ts +0 -69
  143. package/src/parsing/parsers/python.ts +0 -62
  144. package/src/parsing/parsers/rust.ts +0 -50
  145. package/src/parsing/parsers/shell.ts +0 -42
  146. package/src/parsing/types.ts +0 -47
  147. package/src/research/gap-analyzer.ts +0 -135
  148. package/src/research/insight-generator.ts +0 -123
  149. package/src/research/research-engine.ts +0 -116
  150. package/src/research/synergy-detector.ts +0 -126
  151. package/src/research/template-extractor.ts +0 -130
  152. package/src/research/trend-analyzer.ts +0 -127
  153. package/src/services/analytics.service.ts +0 -226
  154. package/src/services/code.service.ts +0 -271
  155. package/src/services/error.service.ts +0 -266
  156. package/src/services/git.service.ts +0 -132
  157. package/src/services/notification.service.ts +0 -41
  158. package/src/services/prevention.service.ts +0 -159
  159. package/src/services/research.service.ts +0 -98
  160. package/src/services/solution.service.ts +0 -174
  161. package/src/services/synapse.service.ts +0 -59
  162. package/src/services/terminal.service.ts +0 -81
  163. package/src/synapses/activation.ts +0 -80
  164. package/src/synapses/decay.ts +0 -38
  165. package/src/synapses/hebbian.ts +0 -69
  166. package/src/synapses/pathfinder.ts +0 -81
  167. package/src/synapses/synapse-manager.ts +0 -113
  168. package/src/types/code.types.ts +0 -52
  169. package/src/types/config.types.ts +0 -103
  170. package/src/types/error.types.ts +0 -67
  171. package/src/types/ipc.types.ts +0 -8
  172. package/src/types/mcp.types.ts +0 -53
  173. package/src/types/research.types.ts +0 -28
  174. package/src/types/solution.types.ts +0 -30
  175. package/src/types/synapse.types.ts +0 -50
  176. package/src/utils/events.ts +0 -45
  177. package/src/utils/hash.ts +0 -5
  178. package/src/utils/logger.ts +0 -48
  179. package/src/utils/paths.ts +0 -19
  180. package/tests/e2e/test_code_intelligence.py +0 -1015
  181. package/tests/e2e/test_error_memory.py +0 -451
  182. package/tests/e2e/test_full_integration.py +0 -534
  183. package/tests/fixtures/code-modules/modules.ts +0 -83
  184. package/tests/fixtures/errors/go.ts +0 -9
  185. package/tests/fixtures/errors/node.ts +0 -24
  186. package/tests/fixtures/errors/python.ts +0 -21
  187. package/tests/fixtures/errors/rust.ts +0 -25
  188. package/tests/fixtures/errors/shell.ts +0 -15
  189. package/tests/fixtures/solutions/solutions.ts +0 -27
  190. package/tests/helpers/setup-db.ts +0 -52
  191. package/tests/integration/code-flow.test.ts +0 -86
  192. package/tests/integration/error-flow.test.ts +0 -83
  193. package/tests/integration/ipc-flow.test.ts +0 -166
  194. package/tests/integration/learning-cycle.test.ts +0 -82
  195. package/tests/integration/synapse-flow.test.ts +0 -117
  196. package/tests/unit/code/analyzer.test.ts +0 -58
  197. package/tests/unit/code/fingerprint.test.ts +0 -51
  198. package/tests/unit/code/scorer.test.ts +0 -55
  199. package/tests/unit/learning/confidence-scorer.test.ts +0 -60
  200. package/tests/unit/learning/decay.test.ts +0 -45
  201. package/tests/unit/learning/pattern-extractor.test.ts +0 -50
  202. package/tests/unit/matching/error-matcher.test.ts +0 -69
  203. package/tests/unit/matching/fingerprint.test.ts +0 -47
  204. package/tests/unit/matching/similarity.test.ts +0 -65
  205. package/tests/unit/matching/tfidf.test.ts +0 -71
  206. package/tests/unit/matching/tokenizer.test.ts +0 -83
  207. package/tests/unit/parsing/parsers.test.ts +0 -113
  208. package/tests/unit/research/gap-analyzer.test.ts +0 -45
  209. package/tests/unit/research/trend-analyzer.test.ts +0 -45
  210. package/tests/unit/synapses/activation.test.ts +0 -80
  211. package/tests/unit/synapses/decay.test.ts +0 -27
  212. package/tests/unit/synapses/hebbian.test.ts +0 -96
  213. package/tests/unit/synapses/pathfinder.test.ts +0 -72
  214. package/tsconfig.json +0 -18
@@ -1,129 +0,0 @@
1
- import type { CodeModuleRecord } from '../types/code.types.js';
2
- import { fingerprintCode } from './fingerprint.js';
3
- import { tokenize } from '../matching/tokenizer.js';
4
- import { cosineSimilarity } from '../matching/similarity.js';
5
-
6
- export interface CodeMatchResult {
7
- moduleId: number;
8
- score: number;
9
- matchType: 'exact' | 'structural' | 'semantic' | 'vector';
10
- }
11
-
12
- export function findExactMatches(
13
- fingerprint: string,
14
- candidates: CodeModuleRecord[],
15
- ): CodeMatchResult[] {
16
- return candidates
17
- .filter(c => c.fingerprint === fingerprint)
18
- .map(c => ({ moduleId: c.id, score: 1.0, matchType: 'exact' as const }));
19
- }
20
-
21
- export function findStructuralMatches(
22
- source: string,
23
- language: string,
24
- candidates: CodeModuleRecord[],
25
- threshold: number = 0.75,
26
- ): CodeMatchResult[] {
27
- const fp = fingerprintCode(source, language);
28
- const results: CodeMatchResult[] = [];
29
-
30
- for (const candidate of candidates) {
31
- if (candidate.fingerprint === fp) {
32
- results.push({ moduleId: candidate.id, score: 1.0, matchType: 'structural' });
33
- continue;
34
- }
35
-
36
- const tokensA = tokenize(source);
37
- const tokensB = tokenize(candidate.name + ' ' + (candidate.description ?? ''));
38
- const sim = cosineSimilarity(tokensA, tokensB);
39
- if (sim >= threshold) {
40
- results.push({ moduleId: candidate.id, score: sim, matchType: 'structural' });
41
- }
42
- }
43
-
44
- return results.sort((a, b) => b.score - a.score);
45
- }
46
-
47
- export function findSemanticMatches(
48
- description: string,
49
- candidates: CodeModuleRecord[],
50
- threshold: number = 0.5,
51
- ): CodeMatchResult[] {
52
- const queryTokens = tokenize(description);
53
-
54
- return candidates
55
- .map(c => {
56
- const candidateTokens = tokenize(
57
- [c.name, c.description ?? '', c.file_path].join(' ')
58
- );
59
- const score = cosineSimilarity(queryTokens, candidateTokens);
60
- return { moduleId: c.id, score, matchType: 'semantic' as const };
61
- })
62
- .filter(r => r.score >= threshold)
63
- .sort((a, b) => b.score - a.score);
64
- }
65
-
66
- /**
67
- * Find matches using pre-computed vector embeddings.
68
- * Vector scores are computed externally (by the EmbeddingEngine) and passed in.
69
- */
70
- export function findVectorMatches(
71
- vectorScores: Map<number, number>,
72
- threshold: number = 0.5,
73
- ): CodeMatchResult[] {
74
- const results: CodeMatchResult[] = [];
75
-
76
- for (const [moduleId, score] of vectorScores) {
77
- if (score >= threshold) {
78
- results.push({ moduleId, score, matchType: 'vector' });
79
- }
80
- }
81
-
82
- return results.sort((a, b) => b.score - a.score);
83
- }
84
-
85
- /**
86
- * Hybrid search: combine structural + semantic + vector matches,
87
- * deduplicating and taking the highest score per module.
88
- */
89
- export function findHybridMatches(
90
- source: string,
91
- language: string,
92
- description: string,
93
- candidates: CodeModuleRecord[],
94
- vectorScores?: Map<number, number>,
95
- ): CodeMatchResult[] {
96
- const scoreMap = new Map<number, CodeMatchResult>();
97
-
98
- // Structural matches (highest priority)
99
- for (const match of findStructuralMatches(source, language, candidates, 0.5)) {
100
- const existing = scoreMap.get(match.moduleId);
101
- if (!existing || match.score > existing.score) {
102
- scoreMap.set(match.moduleId, match);
103
- }
104
- }
105
-
106
- // Semantic matches
107
- for (const match of findSemanticMatches(description, candidates, 0.3)) {
108
- const existing = scoreMap.get(match.moduleId);
109
- if (!existing || match.score > existing.score) {
110
- scoreMap.set(match.moduleId, match);
111
- }
112
- }
113
-
114
- // Vector matches (if available)
115
- if (vectorScores && vectorScores.size > 0) {
116
- for (const match of findVectorMatches(vectorScores, 0.4)) {
117
- const existing = scoreMap.get(match.moduleId);
118
- if (!existing) {
119
- scoreMap.set(match.moduleId, match);
120
- } else {
121
- // Boost existing matches that also have high vector similarity
122
- const vectorBoost = match.score * 0.15;
123
- existing.score = Math.min(1.0, existing.score + vectorBoost);
124
- }
125
- }
126
- }
127
-
128
- return [...scoreMap.values()].sort((a, b) => b.score - a.score);
129
- }
@@ -1,29 +0,0 @@
1
- import type { ExportInfo } from '../../types/code.types.js';
2
-
3
- const FUNC_RE = /(?:function|func|fn|def|sub)\s+(\w+)/g;
4
- const CLASS_RE = /(?:class|struct|type)\s+(\w+)/g;
5
-
6
- export function extractExports(source: string): ExportInfo[] {
7
- const exports: ExportInfo[] = [];
8
- let match: RegExpExecArray | null;
9
-
10
- const funcRe = new RegExp(FUNC_RE.source, 'g');
11
- while ((match = funcRe.exec(source)) !== null) {
12
- exports.push({ name: match[1]!, type: 'function' });
13
- }
14
-
15
- const classRe = new RegExp(CLASS_RE.source, 'g');
16
- while ((match = classRe.exec(source)) !== null) {
17
- exports.push({ name: match[1]!, type: 'class' });
18
- }
19
-
20
- return exports;
21
- }
22
-
23
- export function extractImports(_source: string): { external: string[]; internal: string[] } {
24
- return { external: [], internal: [] };
25
- }
26
-
27
- export function hasTypeAnnotations(_source: string): boolean {
28
- return false;
29
- }
@@ -1,54 +0,0 @@
1
- import type { ExportInfo } from '../../types/code.types.js';
2
-
3
- const FUNC_DEF_RE = /^def\s+(\w+)\s*\(/gm;
4
- const CLASS_DEF_RE = /^class\s+(\w+)/gm;
5
- const IMPORT_RE = /^(?:from\s+(\S+)\s+)?import\s+(.+)/gm;
6
- const TOP_LEVEL_ASSIGN_RE = /^([A-Z_][A-Z_\d]*)\s*=/gm;
7
-
8
- export function extractExports(source: string): ExportInfo[] {
9
- const exports: ExportInfo[] = [];
10
- let match: RegExpExecArray | null;
11
-
12
- const funcRe = new RegExp(FUNC_DEF_RE.source, 'gm');
13
- while ((match = funcRe.exec(source)) !== null) {
14
- if (!match[1]!.startsWith('_')) {
15
- exports.push({ name: match[1]!, type: 'function' });
16
- }
17
- }
18
-
19
- const classRe = new RegExp(CLASS_DEF_RE.source, 'gm');
20
- while ((match = classRe.exec(source)) !== null) {
21
- if (!match[1]!.startsWith('_')) {
22
- exports.push({ name: match[1]!, type: 'class' });
23
- }
24
- }
25
-
26
- const constRe = new RegExp(TOP_LEVEL_ASSIGN_RE.source, 'gm');
27
- while ((match = constRe.exec(source)) !== null) {
28
- exports.push({ name: match[1]!, type: 'constant' });
29
- }
30
-
31
- return exports;
32
- }
33
-
34
- export function extractImports(source: string): { external: string[]; internal: string[] } {
35
- const external: string[] = [];
36
- const internal: string[] = [];
37
- let match: RegExpExecArray | null;
38
-
39
- const importRe = new RegExp(IMPORT_RE.source, 'gm');
40
- while ((match = importRe.exec(source)) !== null) {
41
- const module = match[1] ?? match[2]!.trim().split(/\s*,\s*/)[0]!;
42
- if (module.startsWith('.')) {
43
- internal.push(module);
44
- } else {
45
- external.push(module);
46
- }
47
- }
48
-
49
- return { external, internal };
50
- }
51
-
52
- export function hasTypeAnnotations(source: string): boolean {
53
- return /:\s*\w+/.test(source) && /->/.test(source);
54
- }
@@ -1,65 +0,0 @@
1
- import type { ExportInfo } from '../../types/code.types.js';
2
-
3
- const NAMED_EXPORT_RE = /export\s+(?:async\s+)?(?:function|const|let|var|class|interface|type|enum)\s+(\w+)/g;
4
- const DEFAULT_EXPORT_RE = /export\s+default\s+(?:(?:async\s+)?(?:function|class)\s+)?(\w+)?/g;
5
- const IMPORT_RE = /import\s+(?:(?:type\s+)?(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)(?:\s*,\s*(?:\{[^}]*\}|\*\s+as\s+\w+|\w+))*\s+from\s+)?['"]([^'"]+)['"]/g;
6
-
7
- export function extractExports(source: string): ExportInfo[] {
8
- const exports: ExportInfo[] = [];
9
- let match: RegExpExecArray | null;
10
-
11
- const namedRe = new RegExp(NAMED_EXPORT_RE.source, 'g');
12
- while ((match = namedRe.exec(source)) !== null) {
13
- const line = source.substring(
14
- source.lastIndexOf('\n', match.index) + 1,
15
- source.indexOf('\n', match.index),
16
- );
17
- exports.push({
18
- name: match[1]!,
19
- type: detectExportType(line),
20
- });
21
- }
22
-
23
- const defaultRe = new RegExp(DEFAULT_EXPORT_RE.source, 'g');
24
- while ((match = defaultRe.exec(source)) !== null) {
25
- exports.push({
26
- name: match[1] ?? 'default',
27
- type: 'function',
28
- });
29
- }
30
-
31
- return exports;
32
- }
33
-
34
- export function extractImports(source: string): { external: string[]; internal: string[] } {
35
- const external: string[] = [];
36
- const internal: string[] = [];
37
- let match: RegExpExecArray | null;
38
-
39
- const importRe = new RegExp(IMPORT_RE.source, 'g');
40
- while ((match = importRe.exec(source)) !== null) {
41
- const specifier = match[1]!;
42
- if (specifier.startsWith('.') || specifier.startsWith('/')) {
43
- internal.push(specifier);
44
- } else {
45
- external.push(specifier);
46
- }
47
- }
48
-
49
- return { external, internal };
50
- }
51
-
52
- export function hasTypeAnnotations(source: string): boolean {
53
- return /:\s*\w+[\[\]<>|&]*\s*[=;,)\n{]/.test(source) ||
54
- /interface\s+\w+/.test(source) ||
55
- /type\s+\w+\s*=/.test(source);
56
- }
57
-
58
- function detectExportType(line: string): ExportInfo['type'] {
59
- if (/\bfunction\b/.test(line)) return 'function';
60
- if (/\bclass\b/.test(line)) return 'class';
61
- if (/\binterface\b/.test(line)) return 'interface';
62
- if (/\btype\b/.test(line)) return 'type';
63
- if (/\bconst\b/.test(line)) return 'constant';
64
- return 'variable';
65
- }
@@ -1,60 +0,0 @@
1
- import type { ExportInfo } from '../types/code.types.js';
2
- import { analyzeCode, measureCohesion } from './analyzer.js';
3
-
4
- export type ModuleType = 'file' | 'class' | 'function';
5
-
6
- export function detectGranularity(
7
- source: string,
8
- language: string,
9
- ): ModuleType {
10
- const { exports } = analyzeCode(source, language);
11
-
12
- const hasDefault = exports.some(e => e.name === 'default');
13
- if (hasDefault && exports.length <= 3) return 'file';
14
-
15
- const classes = exports.filter(e => e.type === 'class');
16
- if (classes.length === 1 && exports.length <= 3) return 'class';
17
-
18
- if (exports.length > 3) {
19
- const cohesion = measureCohesion(exports);
20
- if (cohesion < 0.5) return 'function';
21
- }
22
-
23
- return 'file';
24
- }
25
-
26
- export interface ModuleRegistration {
27
- name: string;
28
- filePath: string;
29
- language: string;
30
- source: string;
31
- description?: string;
32
- projectId: number;
33
- }
34
-
35
- export interface RegisteredModule {
36
- name: string;
37
- moduleType: ModuleType;
38
- exports: ExportInfo[];
39
- externalDeps: string[];
40
- internalDeps: string[];
41
- isPure: boolean;
42
- hasTypeAnnotations: boolean;
43
- linesOfCode: number;
44
- }
45
-
46
- export function prepareModule(reg: ModuleRegistration): RegisteredModule {
47
- const analysis = analyzeCode(reg.source, reg.language);
48
- const moduleType = detectGranularity(reg.source, reg.language);
49
-
50
- return {
51
- name: reg.name,
52
- moduleType,
53
- exports: analysis.exports,
54
- externalDeps: analysis.externalDeps,
55
- internalDeps: analysis.internalDeps,
56
- isPure: analysis.isPure,
57
- hasTypeAnnotations: analysis.hasTypeAnnotations,
58
- linesOfCode: analysis.linesOfCode,
59
- };
60
- }
@@ -1,120 +0,0 @@
1
- import type { ExportInfo } from '../types/code.types.js';
2
-
3
- export interface CodeUnitForScoring {
4
- source: string;
5
- filePath: string;
6
- exports: ExportInfo[];
7
- internalDeps: string[];
8
- hasTypeAnnotations: boolean;
9
- complexity?: number;
10
- }
11
-
12
- interface ReusabilitySignal {
13
- name: string;
14
- weight: number;
15
- check: (code: CodeUnitForScoring) => number;
16
- }
17
-
18
- const REUSABILITY_SIGNALS: ReusabilitySignal[] = [
19
- {
20
- name: 'single_responsibility',
21
- weight: 0.20,
22
- check: (code) => {
23
- const count = code.exports.length;
24
- if (count === 0) return 0;
25
- if (count <= 3) return 1.0;
26
- if (count <= 6) return 0.6;
27
- return 0.3;
28
- },
29
- },
30
- {
31
- name: 'pure_function',
32
- weight: 0.20,
33
- check: (code) => {
34
- const sideEffects = [
35
- 'fs.', 'process.', 'console.', 'fetch(',
36
- 'XMLHttpRequest', 'document.', 'window.',
37
- 'global.', 'require(',
38
- ];
39
- const found = sideEffects.filter(se => code.source.includes(se));
40
- return found.length === 0 ? 1.0 : Math.max(0, 1 - found.length * 0.3);
41
- },
42
- },
43
- {
44
- name: 'clear_interface',
45
- weight: 0.20,
46
- check: (code) => {
47
- let score = 0.5;
48
- if (code.hasTypeAnnotations) score += 0.3;
49
- if (!code.source.includes(': any')) score += 0.2;
50
- return Math.min(1.0, score);
51
- },
52
- },
53
- {
54
- name: 'cohesion',
55
- weight: 0.15,
56
- check: (code) => {
57
- const internalImports = code.internalDeps.length;
58
- const exportCount = code.exports.length;
59
- if (exportCount === 0) return 0;
60
- const ratio = internalImports / exportCount;
61
- if (ratio === 0) return 1.0;
62
- if (ratio < 0.5) return 0.8;
63
- if (ratio < 1.0) return 0.5;
64
- return 0.2;
65
- },
66
- },
67
- {
68
- name: 'generic_utility',
69
- weight: 0.10,
70
- check: (code) => {
71
- const utilPaths = ['utils/', 'helpers/', 'lib/', 'shared/', 'common/'];
72
- const isUtilPath = utilPaths.some(p => code.filePath.includes(p));
73
- const hasGenerics = /<[A-Z]\w*>/.test(code.source);
74
- let score = 0;
75
- if (isUtilPath) score += 0.6;
76
- if (hasGenerics) score += 0.4;
77
- return Math.min(1.0, score || 0.2);
78
- },
79
- },
80
- {
81
- name: 'documentation',
82
- weight: 0.10,
83
- check: (code) => {
84
- const hasJsdoc = /\/\*\*[\s\S]*?\*\//.test(code.source);
85
- const hasDocstring = /"""[\s\S]*?"""/.test(code.source) || /'''[\s\S]*?'''/.test(code.source);
86
- const hasInlineComments = (code.source.match(/\/\/ /g) ?? []).length >= 2;
87
- if (hasJsdoc || hasDocstring) return 1.0;
88
- if (hasInlineComments) return 0.5;
89
- return 0.1;
90
- },
91
- },
92
- {
93
- name: 'low_complexity',
94
- weight: 0.10,
95
- check: (code) => {
96
- const cc = code.complexity ?? 1;
97
- if (cc <= 5) return 1.0;
98
- if (cc <= 10) return 0.7;
99
- if (cc <= 20) return 0.4;
100
- return 0.1;
101
- },
102
- },
103
- ];
104
-
105
- export const MODULE_THRESHOLD = 0.60;
106
-
107
- export function computeReusabilityScore(code: CodeUnitForScoring): number {
108
- let totalScore = 0;
109
- for (const signal of REUSABILITY_SIGNALS) {
110
- totalScore += signal.check(code) * signal.weight;
111
- }
112
- return Math.min(1.0, totalScore);
113
- }
114
-
115
- export function getSignalBreakdown(code: CodeUnitForScoring): Array<{ name: string; score: number; weighted: number }> {
116
- return REUSABILITY_SIGNALS.map(signal => {
117
- const score = signal.check(code);
118
- return { name: signal.name, score, weighted: score * signal.weight };
119
- });
120
- }
package/src/config.ts DELETED
@@ -1,135 +0,0 @@
1
- import path from 'node:path';
2
- import fs from 'node:fs';
3
- import type { BrainConfig } from './types/config.types.js';
4
- import { getDataDir, getPipeName } from './utils/paths.js';
5
-
6
- const defaults: BrainConfig = {
7
- dataDir: getDataDir(),
8
- dbPath: path.join(getDataDir(), 'brain.db'),
9
- ipc: {
10
- pipeName: getPipeName(),
11
- timeout: 5000,
12
- },
13
- api: {
14
- port: 7777,
15
- enabled: true,
16
- },
17
- mcpHttp: {
18
- port: 7778,
19
- enabled: true,
20
- },
21
- embeddings: {
22
- enabled: true,
23
- modelName: 'Xenova/all-MiniLM-L6-v2',
24
- cacheDir: path.join(getDataDir(), 'models'),
25
- sweepIntervalMs: 300_000, // 5 minutes
26
- batchSize: 50,
27
- },
28
- learning: {
29
- intervalMs: 900_000,
30
- minOccurrences: 3,
31
- minSuccessRate: 0.70,
32
- minConfidence: 0.60,
33
- pruneThreshold: 0.20,
34
- maxRejectionRate: 0.50,
35
- decayHalfLifeDays: 30,
36
- },
37
- terminal: {
38
- staleTimeout: 300000, // 5 min
39
- maxConnected: 50,
40
- },
41
- matching: {
42
- fingerprintFields: ['type', 'message', 'file_path'],
43
- similarityThreshold: 0.8,
44
- maxResults: 10,
45
- crossProjectMatching: true,
46
- crossProjectWeight: 0.7,
47
- },
48
- code: {
49
- supportedLanguages: ['typescript', 'javascript', 'python', 'rust', 'go'],
50
- maxModuleSize: 50000,
51
- similarityThreshold: 0.75,
52
- },
53
- synapses: {
54
- initialWeight: 0.1,
55
- learningRate: 0.15,
56
- decayHalfLifeDays: 45,
57
- pruneThreshold: 0.05,
58
- decayAfterDays: 14,
59
- maxDepth: 3,
60
- minActivationWeight: 0.2,
61
- },
62
- research: {
63
- intervalMs: 3_600_000,
64
- initialDelayMs: 300_000,
65
- minDataPoints: 10,
66
- trendWindowDays: 7,
67
- gapMinOccurrences: 5,
68
- synergyMinWeight: 0.5,
69
- templateMinAdaptations: 3,
70
- insightExpiryDays: 30,
71
- },
72
- log: {
73
- level: 'info',
74
- file: path.join(getDataDir(), 'brain.log'),
75
- maxSize: 10 * 1024 * 1024,
76
- maxFiles: 3,
77
- },
78
- retention: {
79
- errorDays: 90,
80
- solutionDays: 365,
81
- insightDays: 30,
82
- },
83
- };
84
-
85
- function applyEnvOverrides(config: BrainConfig): void {
86
- if (process.env['BRAIN_DATA_DIR']) {
87
- config.dataDir = process.env['BRAIN_DATA_DIR'];
88
- config.dbPath = path.join(config.dataDir, 'brain.db');
89
- config.log.file = path.join(config.dataDir, 'brain.log');
90
- }
91
- if (process.env['BRAIN_DB_PATH']) config.dbPath = process.env['BRAIN_DB_PATH'];
92
- if (process.env['BRAIN_LOG_LEVEL']) config.log.level = process.env['BRAIN_LOG_LEVEL'];
93
- if (process.env['BRAIN_PIPE_NAME']) config.ipc.pipeName = process.env['BRAIN_PIPE_NAME'];
94
- if (process.env['BRAIN_API_PORT']) config.api.port = Number(process.env['BRAIN_API_PORT']);
95
- if (process.env['BRAIN_API_ENABLED']) config.api.enabled = process.env['BRAIN_API_ENABLED'] !== 'false';
96
- if (process.env['BRAIN_API_KEY']) config.api.apiKey = process.env['BRAIN_API_KEY'];
97
- if (process.env['BRAIN_MCP_HTTP_PORT']) config.mcpHttp.port = Number(process.env['BRAIN_MCP_HTTP_PORT']);
98
- if (process.env['BRAIN_MCP_HTTP_ENABLED']) config.mcpHttp.enabled = process.env['BRAIN_MCP_HTTP_ENABLED'] !== 'false';
99
- if (process.env['BRAIN_EMBEDDINGS_ENABLED']) config.embeddings.enabled = process.env['BRAIN_EMBEDDINGS_ENABLED'] !== 'false';
100
- if (process.env['BRAIN_EMBEDDINGS_MODEL']) config.embeddings.modelName = process.env['BRAIN_EMBEDDINGS_MODEL'];
101
- }
102
-
103
- function deepMerge(target: Record<string, unknown>, source: Record<string, unknown>): void {
104
- for (const key of Object.keys(source)) {
105
- const val = source[key];
106
- if (val && typeof val === 'object' && !Array.isArray(val) && target[key] && typeof target[key] === 'object') {
107
- deepMerge(target[key] as Record<string, unknown>, val as Record<string, unknown>);
108
- } else if (val !== undefined) {
109
- target[key] = val;
110
- }
111
- }
112
- }
113
-
114
- export function loadConfig(configPath?: string): BrainConfig {
115
- const config = structuredClone(defaults);
116
-
117
- if (configPath) {
118
- const filePath = path.resolve(configPath);
119
- if (fs.existsSync(filePath)) {
120
- const raw = fs.readFileSync(filePath, 'utf-8');
121
- const fileConfig = JSON.parse(raw) as Partial<BrainConfig>;
122
- deepMerge(config as unknown as Record<string, unknown>, fileConfig as unknown as Record<string, unknown>);
123
- }
124
- } else {
125
- const defaultConfigPath = path.join(getDataDir(), 'config.json');
126
- if (fs.existsSync(defaultConfigPath)) {
127
- const raw = fs.readFileSync(defaultConfigPath, 'utf-8');
128
- const fileConfig = JSON.parse(raw) as Partial<BrainConfig>;
129
- deepMerge(config as unknown as Record<string, unknown>, fileConfig as unknown as Record<string, unknown>);
130
- }
131
- }
132
-
133
- applyEnvOverrides(config);
134
- return config;
135
- }