@timmeck/brain 1.9.0 → 2.1.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 (253) hide show
  1. package/README.md +33 -0
  2. package/brain.log +3876 -0
  3. package/{src/cli/commands/dashboard.ts → dashboard.html} +694 -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 +2 -0
  8. package/dist/brain.js +15 -4
  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/dashboard.js +21 -2
  14. package/dist/cli/commands/dashboard.js.map +1 -1
  15. package/dist/cli/commands/peers.d.ts +2 -0
  16. package/dist/cli/commands/peers.js +38 -0
  17. package/dist/cli/commands/peers.js.map +1 -0
  18. package/dist/cli/commands/status.js +0 -1
  19. package/dist/cli/commands/status.js.map +1 -1
  20. package/dist/config.js +2 -29
  21. package/dist/config.js.map +1 -1
  22. package/dist/db/connection.d.ts +1 -2
  23. package/dist/db/connection.js +1 -18
  24. package/dist/db/connection.js.map +1 -1
  25. package/dist/index.js +3 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/ipc/__tests__/protocol.test.d.ts +1 -0
  28. package/dist/ipc/__tests__/protocol.test.js +117 -0
  29. package/dist/ipc/__tests__/protocol.test.js.map +1 -0
  30. package/dist/ipc/client.d.ts +1 -16
  31. package/dist/ipc/client.js +1 -100
  32. package/dist/ipc/client.js.map +1 -1
  33. package/dist/ipc/protocol.d.ts +1 -8
  34. package/dist/ipc/protocol.js +1 -28
  35. package/dist/ipc/protocol.js.map +1 -1
  36. package/dist/ipc/router.d.ts +2 -0
  37. package/dist/ipc/router.js +30 -0
  38. package/dist/ipc/router.js.map +1 -1
  39. package/dist/ipc/server.d.ts +1 -22
  40. package/dist/ipc/server.js +1 -163
  41. package/dist/ipc/server.js.map +1 -1
  42. package/dist/learning/confidence-scorer.d.ts +2 -5
  43. package/dist/learning/confidence-scorer.js +4 -19
  44. package/dist/learning/confidence-scorer.js.map +1 -1
  45. package/dist/learning/decay.js +2 -3
  46. package/dist/learning/decay.js.map +1 -1
  47. package/dist/learning/learning-engine.d.ts +2 -5
  48. package/dist/learning/learning-engine.js +3 -15
  49. package/dist/learning/learning-engine.js.map +1 -1
  50. package/dist/mcp/http-server.d.ts +1 -7
  51. package/dist/mcp/http-server.js +6 -117
  52. package/dist/mcp/http-server.js.map +1 -1
  53. package/dist/mcp/server.js +5 -61
  54. package/dist/mcp/server.js.map +1 -1
  55. package/dist/mcp/tools.js +36 -0
  56. package/dist/mcp/tools.js.map +1 -1
  57. package/dist/parsing/parsers/compiler.js +1 -1
  58. package/dist/parsing/parsers/compiler.js.map +1 -1
  59. package/dist/research/research-engine.d.ts +2 -6
  60. package/dist/research/research-engine.js +3 -23
  61. package/dist/research/research-engine.js.map +1 -1
  62. package/dist/services/synapse.service.d.ts +3 -3
  63. package/dist/signals/__tests__/fingerprint.test.d.ts +1 -0
  64. package/dist/signals/__tests__/fingerprint.test.js +118 -0
  65. package/dist/signals/__tests__/fingerprint.test.js.map +1 -0
  66. package/dist/synapses/activation.d.ts +3 -13
  67. package/dist/synapses/activation.js +2 -49
  68. package/dist/synapses/activation.js.map +1 -1
  69. package/dist/synapses/decay.d.ts +2 -11
  70. package/dist/synapses/decay.js +2 -26
  71. package/dist/synapses/decay.js.map +1 -1
  72. package/dist/synapses/hebbian.d.ts +2 -13
  73. package/dist/synapses/hebbian.js +2 -35
  74. package/dist/synapses/hebbian.js.map +1 -1
  75. package/dist/synapses/pathfinder.d.ts +2 -14
  76. package/dist/synapses/pathfinder.js +2 -49
  77. package/dist/synapses/pathfinder.js.map +1 -1
  78. package/dist/synapses/synapse-manager.d.ts +7 -23
  79. package/dist/synapses/synapse-manager.js +6 -63
  80. package/dist/synapses/synapse-manager.js.map +1 -1
  81. package/dist/types/ipc.types.d.ts +1 -11
  82. package/dist/utils/__tests__/hash.test.d.ts +1 -0
  83. package/dist/utils/__tests__/hash.test.js +32 -0
  84. package/dist/utils/__tests__/hash.test.js.map +1 -0
  85. package/dist/utils/__tests__/paths.test.d.ts +1 -0
  86. package/dist/utils/__tests__/paths.test.js +75 -0
  87. package/dist/utils/__tests__/paths.test.js.map +1 -0
  88. package/dist/utils/events.d.ts +4 -8
  89. package/dist/utils/events.js +2 -14
  90. package/dist/utils/events.js.map +1 -1
  91. package/dist/utils/hash.d.ts +1 -1
  92. package/dist/utils/hash.js +1 -4
  93. package/dist/utils/hash.js.map +1 -1
  94. package/dist/utils/logger.d.ts +3 -2
  95. package/dist/utils/logger.js +8 -35
  96. package/dist/utils/logger.js.map +1 -1
  97. package/dist/utils/paths.d.ts +2 -1
  98. package/dist/utils/paths.js +4 -13
  99. package/dist/utils/paths.js.map +1 -1
  100. package/eslint.config.js +14 -0
  101. package/package.json +56 -49
  102. package/BRAIN_PLAN.md +0 -3324
  103. package/reddit_post.md +0 -45
  104. package/src/api/server.ts +0 -395
  105. package/src/brain.ts +0 -313
  106. package/src/cli/colors.ts +0 -116
  107. package/src/cli/commands/config.ts +0 -169
  108. package/src/cli/commands/doctor.ts +0 -124
  109. package/src/cli/commands/explain.ts +0 -83
  110. package/src/cli/commands/export.ts +0 -31
  111. package/src/cli/commands/import.ts +0 -199
  112. package/src/cli/commands/insights.ts +0 -65
  113. package/src/cli/commands/learn.ts +0 -24
  114. package/src/cli/commands/modules.ts +0 -53
  115. package/src/cli/commands/network.ts +0 -67
  116. package/src/cli/commands/projects.ts +0 -42
  117. package/src/cli/commands/query.ts +0 -120
  118. package/src/cli/commands/start.ts +0 -105
  119. package/src/cli/commands/status.ts +0 -75
  120. package/src/cli/commands/stop.ts +0 -34
  121. package/src/cli/ipc-helper.ts +0 -22
  122. package/src/cli/update-check.ts +0 -63
  123. package/src/code/analyzer.ts +0 -117
  124. package/src/code/fingerprint.ts +0 -87
  125. package/src/code/matcher.ts +0 -129
  126. package/src/code/parsers/generic.ts +0 -29
  127. package/src/code/parsers/python.ts +0 -54
  128. package/src/code/parsers/typescript.ts +0 -65
  129. package/src/code/registry.ts +0 -60
  130. package/src/code/scorer.ts +0 -120
  131. package/src/config.ts +0 -135
  132. package/src/dashboard/server.ts +0 -142
  133. package/src/db/connection.ts +0 -22
  134. package/src/db/migrations/001_core_schema.ts +0 -120
  135. package/src/db/migrations/002_learning_schema.ts +0 -38
  136. package/src/db/migrations/003_code_schema.ts +0 -53
  137. package/src/db/migrations/004_synapses_schema.ts +0 -57
  138. package/src/db/migrations/005_fts_indexes.ts +0 -78
  139. package/src/db/migrations/006_synapses_phase3.ts +0 -17
  140. package/src/db/migrations/007_feedback.ts +0 -13
  141. package/src/db/migrations/008_git_integration.ts +0 -38
  142. package/src/db/migrations/009_embeddings.ts +0 -8
  143. package/src/db/migrations/index.ts +0 -70
  144. package/src/db/repositories/antipattern.repository.ts +0 -66
  145. package/src/db/repositories/code-module.repository.ts +0 -142
  146. package/src/db/repositories/error.repository.ts +0 -189
  147. package/src/db/repositories/insight.repository.ts +0 -99
  148. package/src/db/repositories/notification.repository.ts +0 -66
  149. package/src/db/repositories/project.repository.ts +0 -93
  150. package/src/db/repositories/rule.repository.ts +0 -108
  151. package/src/db/repositories/solution.repository.ts +0 -154
  152. package/src/db/repositories/synapse.repository.ts +0 -163
  153. package/src/db/repositories/terminal.repository.ts +0 -101
  154. package/src/embeddings/engine.ts +0 -238
  155. package/src/hooks/post-tool-use.ts +0 -92
  156. package/src/hooks/post-write.ts +0 -129
  157. package/src/index.ts +0 -63
  158. package/src/ipc/client.ts +0 -118
  159. package/src/ipc/protocol.ts +0 -35
  160. package/src/ipc/router.ts +0 -133
  161. package/src/ipc/server.ts +0 -176
  162. package/src/learning/confidence-scorer.ts +0 -80
  163. package/src/learning/decay.ts +0 -46
  164. package/src/learning/learning-engine.ts +0 -170
  165. package/src/learning/pattern-extractor.ts +0 -90
  166. package/src/learning/rule-generator.ts +0 -74
  167. package/src/main.rs:10:5 +0 -0
  168. package/src/matching/error-matcher.ts +0 -166
  169. package/src/matching/fingerprint.ts +0 -34
  170. package/src/matching/similarity.ts +0 -61
  171. package/src/matching/tfidf.ts +0 -74
  172. package/src/matching/tokenizer.ts +0 -41
  173. package/src/mcp/auto-detect.ts +0 -93
  174. package/src/mcp/http-server.ts +0 -140
  175. package/src/mcp/server.ts +0 -73
  176. package/src/mcp/tools.ts +0 -328
  177. package/src/parsing/error-parser.ts +0 -28
  178. package/src/parsing/parsers/compiler.ts +0 -93
  179. package/src/parsing/parsers/generic.ts +0 -28
  180. package/src/parsing/parsers/go.ts +0 -97
  181. package/src/parsing/parsers/node.ts +0 -69
  182. package/src/parsing/parsers/python.ts +0 -62
  183. package/src/parsing/parsers/rust.ts +0 -50
  184. package/src/parsing/parsers/shell.ts +0 -42
  185. package/src/parsing/types.ts +0 -47
  186. package/src/research/gap-analyzer.ts +0 -135
  187. package/src/research/insight-generator.ts +0 -123
  188. package/src/research/research-engine.ts +0 -116
  189. package/src/research/synergy-detector.ts +0 -126
  190. package/src/research/template-extractor.ts +0 -130
  191. package/src/research/trend-analyzer.ts +0 -127
  192. package/src/services/analytics.service.ts +0 -226
  193. package/src/services/code.service.ts +0 -271
  194. package/src/services/error.service.ts +0 -266
  195. package/src/services/git.service.ts +0 -132
  196. package/src/services/notification.service.ts +0 -41
  197. package/src/services/prevention.service.ts +0 -159
  198. package/src/services/research.service.ts +0 -98
  199. package/src/services/solution.service.ts +0 -174
  200. package/src/services/synapse.service.ts +0 -59
  201. package/src/services/terminal.service.ts +0 -81
  202. package/src/synapses/activation.ts +0 -80
  203. package/src/synapses/decay.ts +0 -38
  204. package/src/synapses/hebbian.ts +0 -69
  205. package/src/synapses/pathfinder.ts +0 -81
  206. package/src/synapses/synapse-manager.ts +0 -113
  207. package/src/types/code.types.ts +0 -52
  208. package/src/types/config.types.ts +0 -103
  209. package/src/types/error.types.ts +0 -67
  210. package/src/types/ipc.types.ts +0 -8
  211. package/src/types/mcp.types.ts +0 -53
  212. package/src/types/research.types.ts +0 -28
  213. package/src/types/solution.types.ts +0 -30
  214. package/src/types/synapse.types.ts +0 -50
  215. package/src/utils/events.ts +0 -45
  216. package/src/utils/hash.ts +0 -5
  217. package/src/utils/logger.ts +0 -48
  218. package/src/utils/paths.ts +0 -19
  219. package/tests/e2e/test_code_intelligence.py +0 -1015
  220. package/tests/e2e/test_error_memory.py +0 -451
  221. package/tests/e2e/test_full_integration.py +0 -534
  222. package/tests/fixtures/code-modules/modules.ts +0 -83
  223. package/tests/fixtures/errors/go.ts +0 -9
  224. package/tests/fixtures/errors/node.ts +0 -24
  225. package/tests/fixtures/errors/python.ts +0 -21
  226. package/tests/fixtures/errors/rust.ts +0 -25
  227. package/tests/fixtures/errors/shell.ts +0 -15
  228. package/tests/fixtures/solutions/solutions.ts +0 -27
  229. package/tests/helpers/setup-db.ts +0 -52
  230. package/tests/integration/code-flow.test.ts +0 -86
  231. package/tests/integration/error-flow.test.ts +0 -83
  232. package/tests/integration/ipc-flow.test.ts +0 -166
  233. package/tests/integration/learning-cycle.test.ts +0 -82
  234. package/tests/integration/synapse-flow.test.ts +0 -117
  235. package/tests/unit/code/analyzer.test.ts +0 -58
  236. package/tests/unit/code/fingerprint.test.ts +0 -51
  237. package/tests/unit/code/scorer.test.ts +0 -55
  238. package/tests/unit/learning/confidence-scorer.test.ts +0 -60
  239. package/tests/unit/learning/decay.test.ts +0 -45
  240. package/tests/unit/learning/pattern-extractor.test.ts +0 -50
  241. package/tests/unit/matching/error-matcher.test.ts +0 -69
  242. package/tests/unit/matching/fingerprint.test.ts +0 -47
  243. package/tests/unit/matching/similarity.test.ts +0 -65
  244. package/tests/unit/matching/tfidf.test.ts +0 -71
  245. package/tests/unit/matching/tokenizer.test.ts +0 -83
  246. package/tests/unit/parsing/parsers.test.ts +0 -113
  247. package/tests/unit/research/gap-analyzer.test.ts +0 -45
  248. package/tests/unit/research/trend-analyzer.test.ts +0 -45
  249. package/tests/unit/synapses/activation.test.ts +0 -80
  250. package/tests/unit/synapses/decay.test.ts +0 -27
  251. package/tests/unit/synapses/hebbian.test.ts +0 -96
  252. package/tests/unit/synapses/pathfinder.test.ts +0 -72
  253. 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
- }