@timmeck/brain 1.0.0 → 1.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 (198) hide show
  1. package/BRAIN_PLAN.md +3324 -3324
  2. package/LICENSE +21 -21
  3. package/README.md +194 -188
  4. package/dist/brain.js +2 -0
  5. package/dist/brain.js.map +1 -1
  6. package/dist/cli/colors.d.ts +50 -0
  7. package/dist/cli/colors.js +106 -0
  8. package/dist/cli/colors.js.map +1 -0
  9. package/dist/cli/commands/config.d.ts +2 -0
  10. package/dist/cli/commands/config.js +165 -0
  11. package/dist/cli/commands/config.js.map +1 -0
  12. package/dist/cli/commands/dashboard.js +222 -8
  13. package/dist/cli/commands/dashboard.js.map +1 -1
  14. package/dist/cli/commands/export.js +3 -0
  15. package/dist/cli/commands/export.js.map +1 -1
  16. package/dist/cli/commands/import.js +24 -15
  17. package/dist/cli/commands/import.js.map +1 -1
  18. package/dist/cli/commands/insights.js +33 -6
  19. package/dist/cli/commands/insights.js.map +1 -1
  20. package/dist/cli/commands/learn.d.ts +2 -0
  21. package/dist/cli/commands/learn.js +22 -0
  22. package/dist/cli/commands/learn.js.map +1 -0
  23. package/dist/cli/commands/modules.js +25 -6
  24. package/dist/cli/commands/modules.js.map +1 -1
  25. package/dist/cli/commands/network.js +15 -9
  26. package/dist/cli/commands/network.js.map +1 -1
  27. package/dist/cli/commands/query.js +92 -25
  28. package/dist/cli/commands/query.js.map +1 -1
  29. package/dist/cli/commands/start.js +5 -4
  30. package/dist/cli/commands/start.js.map +1 -1
  31. package/dist/cli/commands/status.js +19 -16
  32. package/dist/cli/commands/status.js.map +1 -1
  33. package/dist/cli/commands/stop.js +5 -4
  34. package/dist/cli/commands/stop.js.map +1 -1
  35. package/dist/cli/ipc-helper.js +4 -3
  36. package/dist/cli/ipc-helper.js.map +1 -1
  37. package/dist/db/migrations/001_core_schema.js +115 -115
  38. package/dist/db/migrations/002_learning_schema.js +33 -33
  39. package/dist/db/migrations/003_code_schema.js +48 -48
  40. package/dist/db/migrations/004_synapses_schema.js +52 -52
  41. package/dist/db/migrations/005_fts_indexes.js +73 -73
  42. package/dist/db/migrations/index.js +6 -6
  43. package/dist/db/repositories/antipattern.repository.js +3 -3
  44. package/dist/db/repositories/code-module.repository.d.ts +1 -0
  45. package/dist/db/repositories/code-module.repository.js +8 -0
  46. package/dist/db/repositories/code-module.repository.js.map +1 -1
  47. package/dist/db/repositories/error.repository.js +46 -46
  48. package/dist/db/repositories/insight.repository.js +3 -3
  49. package/dist/db/repositories/notification.repository.js +3 -3
  50. package/dist/db/repositories/project.repository.js +21 -21
  51. package/dist/db/repositories/rule.repository.js +24 -24
  52. package/dist/db/repositories/solution.repository.js +50 -50
  53. package/dist/db/repositories/synapse.repository.js +18 -18
  54. package/dist/db/repositories/terminal.repository.js +24 -24
  55. package/dist/index.js +4 -0
  56. package/dist/index.js.map +1 -1
  57. package/dist/ipc/router.d.ts +2 -0
  58. package/dist/ipc/router.js +7 -1
  59. package/dist/ipc/router.js.map +1 -1
  60. package/dist/services/code.service.d.ts +1 -1
  61. package/dist/services/code.service.js +5 -2
  62. package/dist/services/code.service.js.map +1 -1
  63. package/package.json +5 -4
  64. package/src/brain.ts +3 -0
  65. package/src/cli/colors.ts +116 -0
  66. package/src/cli/commands/config.ts +169 -0
  67. package/src/cli/commands/dashboard.ts +231 -8
  68. package/src/cli/commands/export.ts +4 -0
  69. package/src/cli/commands/import.ts +24 -15
  70. package/src/cli/commands/insights.ts +37 -5
  71. package/src/cli/commands/learn.ts +24 -0
  72. package/src/cli/commands/modules.ts +28 -5
  73. package/src/cli/commands/network.ts +15 -9
  74. package/src/cli/commands/query.ts +103 -26
  75. package/src/cli/commands/start.ts +5 -4
  76. package/src/cli/commands/status.ts +19 -16
  77. package/src/cli/commands/stop.ts +5 -4
  78. package/src/cli/ipc-helper.ts +4 -3
  79. package/src/code/analyzer.ts +77 -77
  80. package/src/code/fingerprint.ts +87 -87
  81. package/src/code/matcher.ts +64 -64
  82. package/src/code/parsers/generic.ts +29 -29
  83. package/src/code/parsers/python.ts +54 -54
  84. package/src/code/parsers/typescript.ts +65 -65
  85. package/src/code/registry.ts +60 -60
  86. package/src/code/scorer.ts +108 -108
  87. package/src/config.ts +111 -111
  88. package/src/db/connection.ts +22 -22
  89. package/src/db/migrations/001_core_schema.ts +120 -120
  90. package/src/db/migrations/002_learning_schema.ts +38 -38
  91. package/src/db/migrations/003_code_schema.ts +53 -53
  92. package/src/db/migrations/004_synapses_schema.ts +57 -57
  93. package/src/db/migrations/005_fts_indexes.ts +78 -78
  94. package/src/db/migrations/006_synapses_phase3.ts +17 -17
  95. package/src/db/migrations/index.ts +64 -64
  96. package/src/db/repositories/antipattern.repository.ts +66 -66
  97. package/src/db/repositories/code-module.repository.ts +9 -0
  98. package/src/db/repositories/error.repository.ts +149 -149
  99. package/src/db/repositories/insight.repository.ts +78 -78
  100. package/src/db/repositories/notification.repository.ts +66 -66
  101. package/src/db/repositories/project.repository.ts +93 -93
  102. package/src/db/repositories/rule.repository.ts +108 -108
  103. package/src/db/repositories/solution.repository.ts +154 -154
  104. package/src/db/repositories/synapse.repository.ts +153 -153
  105. package/src/db/repositories/terminal.repository.ts +101 -101
  106. package/src/hooks/post-tool-use.ts +90 -90
  107. package/src/hooks/post-write.ts +117 -117
  108. package/src/index.ts +4 -0
  109. package/src/ipc/client.ts +118 -118
  110. package/src/ipc/protocol.ts +35 -35
  111. package/src/ipc/router.ts +9 -1
  112. package/src/ipc/server.ts +110 -110
  113. package/src/learning/confidence-scorer.ts +47 -47
  114. package/src/learning/decay.ts +46 -46
  115. package/src/learning/learning-engine.ts +162 -162
  116. package/src/learning/pattern-extractor.ts +90 -90
  117. package/src/learning/rule-generator.ts +74 -74
  118. package/src/matching/error-matcher.ts +115 -115
  119. package/src/matching/fingerprint.ts +29 -29
  120. package/src/matching/similarity.ts +61 -61
  121. package/src/matching/tfidf.ts +74 -74
  122. package/src/matching/tokenizer.ts +41 -41
  123. package/src/mcp/auto-detect.ts +93 -93
  124. package/src/mcp/server.ts +73 -73
  125. package/src/mcp/tools.ts +290 -290
  126. package/src/parsing/error-parser.ts +28 -28
  127. package/src/parsing/parsers/compiler.ts +93 -93
  128. package/src/parsing/parsers/generic.ts +28 -28
  129. package/src/parsing/parsers/go.ts +97 -97
  130. package/src/parsing/parsers/node.ts +69 -69
  131. package/src/parsing/parsers/python.ts +62 -62
  132. package/src/parsing/parsers/rust.ts +50 -50
  133. package/src/parsing/parsers/shell.ts +42 -42
  134. package/src/parsing/types.ts +47 -47
  135. package/src/research/gap-analyzer.ts +135 -135
  136. package/src/research/insight-generator.ts +123 -123
  137. package/src/research/research-engine.ts +116 -116
  138. package/src/research/synergy-detector.ts +126 -126
  139. package/src/research/template-extractor.ts +130 -130
  140. package/src/research/trend-analyzer.ts +127 -127
  141. package/src/services/analytics.service.ts +87 -87
  142. package/src/services/code.service.ts +5 -2
  143. package/src/services/error.service.ts +164 -164
  144. package/src/services/notification.service.ts +41 -41
  145. package/src/services/prevention.service.ts +119 -119
  146. package/src/services/research.service.ts +93 -93
  147. package/src/services/solution.service.ts +116 -116
  148. package/src/services/synapse.service.ts +59 -59
  149. package/src/services/terminal.service.ts +81 -81
  150. package/src/synapses/activation.ts +80 -80
  151. package/src/synapses/decay.ts +38 -38
  152. package/src/synapses/hebbian.ts +69 -69
  153. package/src/synapses/pathfinder.ts +81 -81
  154. package/src/synapses/synapse-manager.ts +109 -109
  155. package/src/types/code.types.ts +52 -52
  156. package/src/types/config.types.ts +79 -79
  157. package/src/types/error.types.ts +67 -67
  158. package/src/types/ipc.types.ts +8 -8
  159. package/src/types/mcp.types.ts +53 -53
  160. package/src/types/research.types.ts +28 -28
  161. package/src/types/solution.types.ts +30 -30
  162. package/src/types/synapse.types.ts +49 -49
  163. package/src/utils/events.ts +45 -45
  164. package/src/utils/hash.ts +5 -5
  165. package/src/utils/logger.ts +48 -48
  166. package/src/utils/paths.ts +19 -19
  167. package/tests/fixtures/code-modules/modules.ts +83 -83
  168. package/tests/fixtures/errors/go.ts +9 -9
  169. package/tests/fixtures/errors/node.ts +24 -24
  170. package/tests/fixtures/errors/python.ts +21 -21
  171. package/tests/fixtures/errors/rust.ts +25 -25
  172. package/tests/fixtures/errors/shell.ts +15 -15
  173. package/tests/fixtures/solutions/solutions.ts +27 -27
  174. package/tests/helpers/setup-db.ts +52 -52
  175. package/tests/integration/code-flow.test.ts +86 -86
  176. package/tests/integration/error-flow.test.ts +83 -83
  177. package/tests/integration/ipc-flow.test.ts +166 -166
  178. package/tests/integration/learning-cycle.test.ts +82 -82
  179. package/tests/integration/synapse-flow.test.ts +117 -117
  180. package/tests/unit/code/analyzer.test.ts +58 -58
  181. package/tests/unit/code/fingerprint.test.ts +51 -51
  182. package/tests/unit/code/scorer.test.ts +55 -55
  183. package/tests/unit/learning/confidence-scorer.test.ts +60 -60
  184. package/tests/unit/learning/decay.test.ts +45 -45
  185. package/tests/unit/learning/pattern-extractor.test.ts +50 -50
  186. package/tests/unit/matching/error-matcher.test.ts +69 -69
  187. package/tests/unit/matching/fingerprint.test.ts +47 -47
  188. package/tests/unit/matching/similarity.test.ts +65 -65
  189. package/tests/unit/matching/tfidf.test.ts +71 -71
  190. package/tests/unit/matching/tokenizer.test.ts +83 -83
  191. package/tests/unit/parsing/parsers.test.ts +113 -113
  192. package/tests/unit/research/gap-analyzer.test.ts +45 -45
  193. package/tests/unit/research/trend-analyzer.test.ts +45 -45
  194. package/tests/unit/synapses/activation.test.ts +80 -80
  195. package/tests/unit/synapses/decay.test.ts +27 -27
  196. package/tests/unit/synapses/hebbian.test.ts +96 -96
  197. package/tests/unit/synapses/pathfinder.test.ts +72 -72
  198. package/tsconfig.json +18 -18
@@ -1,93 +1,93 @@
1
- import type { ErrorParser, ParsedError, StackFrame } from '../types.js';
2
- import path from 'node:path';
3
-
4
- const GCC_RE = /^(.+?):(\d+):(\d+): (error|warning|fatal error): (.+)/m;
5
- const JAVAC_RE = /^(.+\.java):(\d+): error: (.+)/m;
6
- const GENERIC_COMPILER_RE = /^(.+?):(\d+)(?::(\d+))?: (?:error|fatal): (.+)/m;
7
-
8
- export const compilerParser: ErrorParser = {
9
- name: 'compiler',
10
- priority: 7,
11
-
12
- canParse(input: string): boolean {
13
- return (
14
- GCC_RE.test(input) ||
15
- JAVAC_RE.test(input) ||
16
- /compilation failed|fatal error:/.test(input)
17
- );
18
- },
19
-
20
- parse(input: string): ParsedError | null {
21
- let gccMatch = GCC_RE.exec(input);
22
- if (gccMatch) {
23
- const filePath = gccMatch[1]!;
24
- const frame: StackFrame = {
25
- function_name: null,
26
- file_path: filePath,
27
- line_number: parseInt(gccMatch[2]!, 10),
28
- column_number: parseInt(gccMatch[3]!, 10),
29
- normalized: `<compiler>@${path.basename(filePath)}`,
30
- };
31
- return {
32
- errorType: gccMatch[4] === 'warning' ? 'CompilerWarning' : 'CompilerError',
33
- message: gccMatch[5]!,
34
- stackTrace: input,
35
- frames: [frame],
36
- sourceFile: filePath,
37
- sourceLine: frame.line_number,
38
- language: detectLanguage(filePath),
39
- };
40
- }
41
-
42
- const javacMatch = JAVAC_RE.exec(input);
43
- if (javacMatch) {
44
- const filePath = javacMatch[1]!;
45
- return {
46
- errorType: 'CompilerError',
47
- message: javacMatch[3]!,
48
- stackTrace: input,
49
- frames: [{
50
- function_name: null,
51
- file_path: filePath,
52
- line_number: parseInt(javacMatch[2]!, 10),
53
- column_number: null,
54
- normalized: `<compiler>@${path.basename(filePath)}`,
55
- }],
56
- sourceFile: filePath,
57
- sourceLine: parseInt(javacMatch[2]!, 10),
58
- language: 'java',
59
- };
60
- }
61
-
62
- const genericMatch = GENERIC_COMPILER_RE.exec(input);
63
- if (genericMatch) {
64
- const filePath = genericMatch[1]!;
65
- return {
66
- errorType: 'CompilerError',
67
- message: genericMatch[4]!,
68
- stackTrace: input,
69
- frames: [{
70
- function_name: null,
71
- file_path: filePath,
72
- line_number: parseInt(genericMatch[2]!, 10),
73
- column_number: genericMatch[3] ? parseInt(genericMatch[3], 10) : null,
74
- normalized: `<compiler>@${path.basename(filePath)}`,
75
- }],
76
- sourceFile: filePath,
77
- sourceLine: parseInt(genericMatch[2]!, 10),
78
- language: detectLanguage(filePath),
79
- };
80
- }
81
-
82
- return null;
83
- },
84
- };
85
-
86
- function detectLanguage(filePath: string): string {
87
- const ext = path.extname(filePath).toLowerCase();
88
- const map: Record<string, string> = {
89
- '.c': 'c', '.h': 'c', '.cpp': 'cpp', '.cc': 'cpp', '.cxx': 'cpp',
90
- '.java': 'java', '.rs': 'rust', '.go': 'go', '.swift': 'swift',
91
- };
92
- return map[ext] ?? 'unknown';
93
- }
1
+ import type { ErrorParser, ParsedError, StackFrame } from '../types.js';
2
+ import path from 'node:path';
3
+
4
+ const GCC_RE = /^(.+?):(\d+):(\d+): (error|warning|fatal error): (.+)/m;
5
+ const JAVAC_RE = /^(.+\.java):(\d+): error: (.+)/m;
6
+ const GENERIC_COMPILER_RE = /^(.+?):(\d+)(?::(\d+))?: (?:error|fatal): (.+)/m;
7
+
8
+ export const compilerParser: ErrorParser = {
9
+ name: 'compiler',
10
+ priority: 7,
11
+
12
+ canParse(input: string): boolean {
13
+ return (
14
+ GCC_RE.test(input) ||
15
+ JAVAC_RE.test(input) ||
16
+ /compilation failed|fatal error:/.test(input)
17
+ );
18
+ },
19
+
20
+ parse(input: string): ParsedError | null {
21
+ let gccMatch = GCC_RE.exec(input);
22
+ if (gccMatch) {
23
+ const filePath = gccMatch[1]!;
24
+ const frame: StackFrame = {
25
+ function_name: null,
26
+ file_path: filePath,
27
+ line_number: parseInt(gccMatch[2]!, 10),
28
+ column_number: parseInt(gccMatch[3]!, 10),
29
+ normalized: `<compiler>@${path.basename(filePath)}`,
30
+ };
31
+ return {
32
+ errorType: gccMatch[4] === 'warning' ? 'CompilerWarning' : 'CompilerError',
33
+ message: gccMatch[5]!,
34
+ stackTrace: input,
35
+ frames: [frame],
36
+ sourceFile: filePath,
37
+ sourceLine: frame.line_number,
38
+ language: detectLanguage(filePath),
39
+ };
40
+ }
41
+
42
+ const javacMatch = JAVAC_RE.exec(input);
43
+ if (javacMatch) {
44
+ const filePath = javacMatch[1]!;
45
+ return {
46
+ errorType: 'CompilerError',
47
+ message: javacMatch[3]!,
48
+ stackTrace: input,
49
+ frames: [{
50
+ function_name: null,
51
+ file_path: filePath,
52
+ line_number: parseInt(javacMatch[2]!, 10),
53
+ column_number: null,
54
+ normalized: `<compiler>@${path.basename(filePath)}`,
55
+ }],
56
+ sourceFile: filePath,
57
+ sourceLine: parseInt(javacMatch[2]!, 10),
58
+ language: 'java',
59
+ };
60
+ }
61
+
62
+ const genericMatch = GENERIC_COMPILER_RE.exec(input);
63
+ if (genericMatch) {
64
+ const filePath = genericMatch[1]!;
65
+ return {
66
+ errorType: 'CompilerError',
67
+ message: genericMatch[4]!,
68
+ stackTrace: input,
69
+ frames: [{
70
+ function_name: null,
71
+ file_path: filePath,
72
+ line_number: parseInt(genericMatch[2]!, 10),
73
+ column_number: genericMatch[3] ? parseInt(genericMatch[3], 10) : null,
74
+ normalized: `<compiler>@${path.basename(filePath)}`,
75
+ }],
76
+ sourceFile: filePath,
77
+ sourceLine: parseInt(genericMatch[2]!, 10),
78
+ language: detectLanguage(filePath),
79
+ };
80
+ }
81
+
82
+ return null;
83
+ },
84
+ };
85
+
86
+ function detectLanguage(filePath: string): string {
87
+ const ext = path.extname(filePath).toLowerCase();
88
+ const map: Record<string, string> = {
89
+ '.c': 'c', '.h': 'c', '.cpp': 'cpp', '.cc': 'cpp', '.cxx': 'cpp',
90
+ '.java': 'java', '.rs': 'rust', '.go': 'go', '.swift': 'swift',
91
+ };
92
+ return map[ext] ?? 'unknown';
93
+ }
@@ -1,28 +1,28 @@
1
- import type { ErrorParser, ParsedError } from '../types.js';
2
-
3
- const ERROR_LINE_RE = /(?:error|Error|ERROR)[\s:]+(.+)/;
4
-
5
- export const genericParser: ErrorParser = {
6
- name: 'generic',
7
- priority: 0,
8
-
9
- canParse(_input: string): boolean {
10
- return true;
11
- },
12
-
13
- parse(input: string): ParsedError | null {
14
- const match = ERROR_LINE_RE.exec(input);
15
- const firstLine = input.trim().split('\n')[0] ?? input;
16
- const message = match ? match[1]! : firstLine;
17
-
18
- return {
19
- errorType: 'UnknownError',
20
- message: message.trim(),
21
- stackTrace: null,
22
- frames: [],
23
- sourceFile: null,
24
- sourceLine: null,
25
- language: null,
26
- };
27
- },
28
- };
1
+ import type { ErrorParser, ParsedError } from '../types.js';
2
+
3
+ const ERROR_LINE_RE = /(?:error|Error|ERROR)[\s:]+(.+)/;
4
+
5
+ export const genericParser: ErrorParser = {
6
+ name: 'generic',
7
+ priority: 0,
8
+
9
+ canParse(_input: string): boolean {
10
+ return true;
11
+ },
12
+
13
+ parse(input: string): ParsedError | null {
14
+ const match = ERROR_LINE_RE.exec(input);
15
+ const firstLine = input.trim().split('\n')[0] ?? input;
16
+ const message = match ? match[1]! : firstLine;
17
+
18
+ return {
19
+ errorType: 'UnknownError',
20
+ message: message.trim(),
21
+ stackTrace: null,
22
+ frames: [],
23
+ sourceFile: null,
24
+ sourceLine: null,
25
+ language: null,
26
+ };
27
+ },
28
+ };
@@ -1,97 +1,97 @@
1
- import type { ErrorParser, ParsedError, StackFrame } from '../types.js';
2
- import path from 'node:path';
3
-
4
- const GO_FILE_ERROR_RE = /^\.?\/?(.+\.go):(\d+):(\d+): (.+)/m;
5
- const GO_PANIC_RE = /^panic: (.+)/m;
6
- const GO_GOROUTINE_RE = /^goroutine \d+ \[.+\]:/m;
7
- const GO_STACK_RE = /^\t(.+\.go):(\d+)/gm;
8
- const GO_FUNC_RE = /^(.+)\(.*\)$/gm;
9
-
10
- export const goParser: ErrorParser = {
11
- name: 'go',
12
- priority: 10,
13
-
14
- canParse(input: string): boolean {
15
- return (
16
- GO_FILE_ERROR_RE.test(input) ||
17
- GO_PANIC_RE.test(input) ||
18
- /^fatal error:/.test(input)
19
- );
20
- },
21
-
22
- parse(input: string): ParsedError | null {
23
- const panicMatch = GO_PANIC_RE.exec(input);
24
- if (panicMatch) {
25
- return parsePanic(input, panicMatch[1]!);
26
- }
27
-
28
- const fileMatch = GO_FILE_ERROR_RE.exec(input);
29
- if (fileMatch) {
30
- return {
31
- errorType: 'CompilerError',
32
- message: fileMatch[4]!,
33
- stackTrace: input,
34
- frames: [{
35
- function_name: null,
36
- file_path: fileMatch[1]!,
37
- line_number: parseInt(fileMatch[2]!, 10),
38
- column_number: parseInt(fileMatch[3]!, 10),
39
- normalized: `<compiler>@${path.basename(fileMatch[1]!)}`,
40
- }],
41
- sourceFile: fileMatch[1]!,
42
- sourceLine: parseInt(fileMatch[2]!, 10),
43
- language: 'go',
44
- };
45
- }
46
-
47
- const fatalMatch = /^fatal error: (.+)/m.exec(input);
48
- if (fatalMatch) {
49
- return {
50
- errorType: 'FatalError',
51
- message: fatalMatch[1]!,
52
- stackTrace: input,
53
- frames: [],
54
- sourceFile: null,
55
- sourceLine: null,
56
- language: 'go',
57
- };
58
- }
59
-
60
- return null;
61
- },
62
- };
63
-
64
- function parsePanic(input: string, message: string): ParsedError {
65
- const frames: StackFrame[] = [];
66
- const lines = input.split('\n');
67
- let i = 0;
68
-
69
- while (i < lines.length) {
70
- if (lines[i]!.startsWith('\t')) {
71
- const stackMatch = /^\t(.+\.go):(\d+)/.exec(lines[i]!);
72
- if (stackMatch) {
73
- const funcLine = i > 0 ? lines[i - 1]!.trim() : null;
74
- const funcName = funcLine?.replace(/\(.*\)$/, '') ?? null;
75
- frames.push({
76
- function_name: funcName,
77
- file_path: stackMatch[1]!,
78
- line_number: parseInt(stackMatch[2]!, 10),
79
- column_number: null,
80
- normalized: `${funcName || '<anon>'}@${path.basename(stackMatch[1]!)}`,
81
- });
82
- }
83
- }
84
- i++;
85
- }
86
-
87
- const topFrame = frames[0];
88
- return {
89
- errorType: 'PanicError',
90
- message,
91
- stackTrace: input,
92
- frames,
93
- sourceFile: topFrame?.file_path ?? null,
94
- sourceLine: topFrame?.line_number ?? null,
95
- language: 'go',
96
- };
97
- }
1
+ import type { ErrorParser, ParsedError, StackFrame } from '../types.js';
2
+ import path from 'node:path';
3
+
4
+ const GO_FILE_ERROR_RE = /^\.?\/?(.+\.go):(\d+):(\d+): (.+)/m;
5
+ const GO_PANIC_RE = /^panic: (.+)/m;
6
+ const GO_GOROUTINE_RE = /^goroutine \d+ \[.+\]:/m;
7
+ const GO_STACK_RE = /^\t(.+\.go):(\d+)/gm;
8
+ const GO_FUNC_RE = /^(.+)\(.*\)$/gm;
9
+
10
+ export const goParser: ErrorParser = {
11
+ name: 'go',
12
+ priority: 10,
13
+
14
+ canParse(input: string): boolean {
15
+ return (
16
+ GO_FILE_ERROR_RE.test(input) ||
17
+ GO_PANIC_RE.test(input) ||
18
+ /^fatal error:/.test(input)
19
+ );
20
+ },
21
+
22
+ parse(input: string): ParsedError | null {
23
+ const panicMatch = GO_PANIC_RE.exec(input);
24
+ if (panicMatch) {
25
+ return parsePanic(input, panicMatch[1]!);
26
+ }
27
+
28
+ const fileMatch = GO_FILE_ERROR_RE.exec(input);
29
+ if (fileMatch) {
30
+ return {
31
+ errorType: 'CompilerError',
32
+ message: fileMatch[4]!,
33
+ stackTrace: input,
34
+ frames: [{
35
+ function_name: null,
36
+ file_path: fileMatch[1]!,
37
+ line_number: parseInt(fileMatch[2]!, 10),
38
+ column_number: parseInt(fileMatch[3]!, 10),
39
+ normalized: `<compiler>@${path.basename(fileMatch[1]!)}`,
40
+ }],
41
+ sourceFile: fileMatch[1]!,
42
+ sourceLine: parseInt(fileMatch[2]!, 10),
43
+ language: 'go',
44
+ };
45
+ }
46
+
47
+ const fatalMatch = /^fatal error: (.+)/m.exec(input);
48
+ if (fatalMatch) {
49
+ return {
50
+ errorType: 'FatalError',
51
+ message: fatalMatch[1]!,
52
+ stackTrace: input,
53
+ frames: [],
54
+ sourceFile: null,
55
+ sourceLine: null,
56
+ language: 'go',
57
+ };
58
+ }
59
+
60
+ return null;
61
+ },
62
+ };
63
+
64
+ function parsePanic(input: string, message: string): ParsedError {
65
+ const frames: StackFrame[] = [];
66
+ const lines = input.split('\n');
67
+ let i = 0;
68
+
69
+ while (i < lines.length) {
70
+ if (lines[i]!.startsWith('\t')) {
71
+ const stackMatch = /^\t(.+\.go):(\d+)/.exec(lines[i]!);
72
+ if (stackMatch) {
73
+ const funcLine = i > 0 ? lines[i - 1]!.trim() : null;
74
+ const funcName = funcLine?.replace(/\(.*\)$/, '') ?? null;
75
+ frames.push({
76
+ function_name: funcName,
77
+ file_path: stackMatch[1]!,
78
+ line_number: parseInt(stackMatch[2]!, 10),
79
+ column_number: null,
80
+ normalized: `${funcName || '<anon>'}@${path.basename(stackMatch[1]!)}`,
81
+ });
82
+ }
83
+ }
84
+ i++;
85
+ }
86
+
87
+ const topFrame = frames[0];
88
+ return {
89
+ errorType: 'PanicError',
90
+ message,
91
+ stackTrace: input,
92
+ frames,
93
+ sourceFile: topFrame?.file_path ?? null,
94
+ sourceLine: topFrame?.line_number ?? null,
95
+ language: 'go',
96
+ };
97
+ }
@@ -1,69 +1,69 @@
1
- import type { ErrorParser, ParsedError, StackFrame } from '../types.js';
2
- import path from 'node:path';
3
-
4
- const V8_STACK_RE = /at (?:(.+?) )?\((.+?):(\d+):(\d+)\)/;
5
- const V8_STACK_BARE_RE = /at (.+?):(\d+):(\d+)/;
6
- const ERROR_TYPE_RE = /^(\w+(?:Error|Exception|Warning)?): (.+)$/m;
7
-
8
- function parseFrames(input: string): StackFrame[] {
9
- const frames: StackFrame[] = [];
10
- for (const line of input.split('\n')) {
11
- const trimmed = line.trim();
12
- let match = V8_STACK_RE.exec(trimmed);
13
- if (match) {
14
- frames.push({
15
- function_name: match[1] || null,
16
- file_path: match[2]!,
17
- line_number: parseInt(match[3]!, 10),
18
- column_number: parseInt(match[4]!, 10),
19
- normalized: `${match[1] || '<anon>'}@${path.basename(match[2]!)}`,
20
- });
21
- continue;
22
- }
23
- match = V8_STACK_BARE_RE.exec(trimmed);
24
- if (match) {
25
- frames.push({
26
- function_name: null,
27
- file_path: match[1]!,
28
- line_number: parseInt(match[2]!, 10),
29
- column_number: parseInt(match[3]!, 10),
30
- normalized: `<anon>@${path.basename(match[1]!)}`,
31
- });
32
- }
33
- }
34
- return frames;
35
- }
36
-
37
- export const nodeParser: ErrorParser = {
38
- name: 'node',
39
- priority: 10,
40
-
41
- canParse(input: string): boolean {
42
- return (
43
- /at .+ \(.+:\d+:\d+\)/.test(input) ||
44
- /at .+:\d+:\d+/.test(input) ||
45
- /^\w*Error:/.test(input) ||
46
- /^\w*TypeError:/.test(input)
47
- );
48
- },
49
-
50
- parse(input: string): ParsedError | null {
51
- const typeMatch = ERROR_TYPE_RE.exec(input);
52
- if (!typeMatch) return null;
53
-
54
- const errorType = typeMatch[1]!;
55
- const message = typeMatch[2]!;
56
- const frames = parseFrames(input);
57
- const topFrame = frames[0];
58
-
59
- return {
60
- errorType,
61
- message,
62
- stackTrace: input,
63
- frames,
64
- sourceFile: topFrame?.file_path ?? null,
65
- sourceLine: topFrame?.line_number ?? null,
66
- language: 'javascript',
67
- };
68
- },
69
- };
1
+ import type { ErrorParser, ParsedError, StackFrame } from '../types.js';
2
+ import path from 'node:path';
3
+
4
+ const V8_STACK_RE = /at (?:(.+?) )?\((.+?):(\d+):(\d+)\)/;
5
+ const V8_STACK_BARE_RE = /at (.+?):(\d+):(\d+)/;
6
+ const ERROR_TYPE_RE = /^(\w+(?:Error|Exception|Warning)?): (.+)$/m;
7
+
8
+ function parseFrames(input: string): StackFrame[] {
9
+ const frames: StackFrame[] = [];
10
+ for (const line of input.split('\n')) {
11
+ const trimmed = line.trim();
12
+ let match = V8_STACK_RE.exec(trimmed);
13
+ if (match) {
14
+ frames.push({
15
+ function_name: match[1] || null,
16
+ file_path: match[2]!,
17
+ line_number: parseInt(match[3]!, 10),
18
+ column_number: parseInt(match[4]!, 10),
19
+ normalized: `${match[1] || '<anon>'}@${path.basename(match[2]!)}`,
20
+ });
21
+ continue;
22
+ }
23
+ match = V8_STACK_BARE_RE.exec(trimmed);
24
+ if (match) {
25
+ frames.push({
26
+ function_name: null,
27
+ file_path: match[1]!,
28
+ line_number: parseInt(match[2]!, 10),
29
+ column_number: parseInt(match[3]!, 10),
30
+ normalized: `<anon>@${path.basename(match[1]!)}`,
31
+ });
32
+ }
33
+ }
34
+ return frames;
35
+ }
36
+
37
+ export const nodeParser: ErrorParser = {
38
+ name: 'node',
39
+ priority: 10,
40
+
41
+ canParse(input: string): boolean {
42
+ return (
43
+ /at .+ \(.+:\d+:\d+\)/.test(input) ||
44
+ /at .+:\d+:\d+/.test(input) ||
45
+ /^\w*Error:/.test(input) ||
46
+ /^\w*TypeError:/.test(input)
47
+ );
48
+ },
49
+
50
+ parse(input: string): ParsedError | null {
51
+ const typeMatch = ERROR_TYPE_RE.exec(input);
52
+ if (!typeMatch) return null;
53
+
54
+ const errorType = typeMatch[1]!;
55
+ const message = typeMatch[2]!;
56
+ const frames = parseFrames(input);
57
+ const topFrame = frames[0];
58
+
59
+ return {
60
+ errorType,
61
+ message,
62
+ stackTrace: input,
63
+ frames,
64
+ sourceFile: topFrame?.file_path ?? null,
65
+ sourceLine: topFrame?.line_number ?? null,
66
+ language: 'javascript',
67
+ };
68
+ },
69
+ };