@timmeck/brain 1.8.1 → 1.8.3

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 (164) hide show
  1. package/BRAIN_PLAN.md +3324 -3324
  2. package/LICENSE +21 -21
  3. package/dist/cli/commands/dashboard.js +595 -595
  4. package/dist/cli/commands/doctor.js +6 -1
  5. package/dist/cli/commands/doctor.js.map +1 -1
  6. package/dist/dashboard/server.js +25 -25
  7. package/dist/db/migrations/001_core_schema.js +115 -115
  8. package/dist/db/migrations/002_learning_schema.js +33 -33
  9. package/dist/db/migrations/003_code_schema.js +48 -48
  10. package/dist/db/migrations/004_synapses_schema.js +52 -52
  11. package/dist/db/migrations/005_fts_indexes.js +73 -73
  12. package/dist/db/migrations/007_feedback.js +8 -8
  13. package/dist/db/migrations/008_git_integration.js +33 -33
  14. package/dist/db/migrations/009_embeddings.js +3 -3
  15. package/dist/db/repositories/antipattern.repository.js +3 -3
  16. package/dist/db/repositories/code-module.repository.js +32 -32
  17. package/dist/db/repositories/notification.repository.js +3 -3
  18. package/dist/db/repositories/project.repository.js +21 -21
  19. package/dist/db/repositories/rule.repository.js +24 -24
  20. package/dist/db/repositories/solution.repository.js +50 -50
  21. package/dist/db/repositories/synapse.repository.js +18 -18
  22. package/dist/db/repositories/terminal.repository.js +24 -24
  23. package/dist/ipc/server.d.ts +8 -0
  24. package/dist/ipc/server.js +67 -1
  25. package/dist/ipc/server.js.map +1 -1
  26. package/dist/matching/error-matcher.js +5 -5
  27. package/dist/matching/fingerprint.js +6 -1
  28. package/dist/matching/fingerprint.js.map +1 -1
  29. package/dist/services/error.service.js +4 -3
  30. package/dist/services/error.service.js.map +1 -1
  31. package/dist/services/git.service.js +14 -14
  32. package/package.json +49 -49
  33. package/src/api/server.ts +395 -395
  34. package/src/brain.ts +266 -266
  35. package/src/cli/colors.ts +116 -116
  36. package/src/cli/commands/config.ts +169 -169
  37. package/src/cli/commands/dashboard.ts +755 -755
  38. package/src/cli/commands/doctor.ts +124 -118
  39. package/src/cli/commands/explain.ts +83 -83
  40. package/src/cli/commands/export.ts +31 -31
  41. package/src/cli/commands/import.ts +199 -199
  42. package/src/cli/commands/insights.ts +65 -65
  43. package/src/cli/commands/learn.ts +24 -24
  44. package/src/cli/commands/modules.ts +53 -53
  45. package/src/cli/commands/network.ts +67 -67
  46. package/src/cli/commands/projects.ts +42 -42
  47. package/src/cli/commands/query.ts +120 -120
  48. package/src/cli/commands/start.ts +62 -62
  49. package/src/cli/commands/status.ts +75 -75
  50. package/src/cli/commands/stop.ts +34 -34
  51. package/src/cli/ipc-helper.ts +22 -22
  52. package/src/cli/update-check.ts +63 -63
  53. package/src/code/fingerprint.ts +87 -87
  54. package/src/code/parsers/generic.ts +29 -29
  55. package/src/code/parsers/python.ts +54 -54
  56. package/src/code/parsers/typescript.ts +65 -65
  57. package/src/code/registry.ts +60 -60
  58. package/src/dashboard/server.ts +142 -142
  59. package/src/db/connection.ts +22 -22
  60. package/src/db/migrations/001_core_schema.ts +120 -120
  61. package/src/db/migrations/002_learning_schema.ts +38 -38
  62. package/src/db/migrations/003_code_schema.ts +53 -53
  63. package/src/db/migrations/004_synapses_schema.ts +57 -57
  64. package/src/db/migrations/005_fts_indexes.ts +78 -78
  65. package/src/db/migrations/006_synapses_phase3.ts +17 -17
  66. package/src/db/migrations/007_feedback.ts +13 -13
  67. package/src/db/migrations/008_git_integration.ts +38 -38
  68. package/src/db/migrations/009_embeddings.ts +8 -8
  69. package/src/db/repositories/antipattern.repository.ts +66 -66
  70. package/src/db/repositories/code-module.repository.ts +142 -142
  71. package/src/db/repositories/notification.repository.ts +66 -66
  72. package/src/db/repositories/project.repository.ts +93 -93
  73. package/src/db/repositories/rule.repository.ts +108 -108
  74. package/src/db/repositories/solution.repository.ts +154 -154
  75. package/src/db/repositories/synapse.repository.ts +153 -153
  76. package/src/db/repositories/terminal.repository.ts +101 -101
  77. package/src/embeddings/engine.ts +238 -238
  78. package/src/index.ts +63 -63
  79. package/src/ipc/client.ts +118 -118
  80. package/src/ipc/protocol.ts +35 -35
  81. package/src/ipc/router.ts +133 -133
  82. package/src/ipc/server.ts +176 -110
  83. package/src/learning/decay.ts +46 -46
  84. package/src/learning/pattern-extractor.ts +90 -90
  85. package/src/learning/rule-generator.ts +74 -74
  86. package/src/matching/error-matcher.ts +5 -5
  87. package/src/matching/fingerprint.ts +34 -29
  88. package/src/matching/similarity.ts +61 -61
  89. package/src/matching/tfidf.ts +74 -74
  90. package/src/matching/tokenizer.ts +41 -41
  91. package/src/mcp/auto-detect.ts +93 -93
  92. package/src/mcp/http-server.ts +140 -140
  93. package/src/mcp/server.ts +73 -73
  94. package/src/parsing/error-parser.ts +28 -28
  95. package/src/parsing/parsers/compiler.ts +93 -93
  96. package/src/parsing/parsers/generic.ts +28 -28
  97. package/src/parsing/parsers/go.ts +97 -97
  98. package/src/parsing/parsers/node.ts +69 -69
  99. package/src/parsing/parsers/python.ts +62 -62
  100. package/src/parsing/parsers/rust.ts +50 -50
  101. package/src/parsing/parsers/shell.ts +42 -42
  102. package/src/parsing/types.ts +47 -47
  103. package/src/research/gap-analyzer.ts +135 -135
  104. package/src/research/insight-generator.ts +123 -123
  105. package/src/research/research-engine.ts +116 -116
  106. package/src/research/synergy-detector.ts +126 -126
  107. package/src/research/template-extractor.ts +130 -130
  108. package/src/research/trend-analyzer.ts +127 -127
  109. package/src/services/code.service.ts +271 -271
  110. package/src/services/error.service.ts +4 -3
  111. package/src/services/git.service.ts +132 -132
  112. package/src/services/notification.service.ts +41 -41
  113. package/src/services/synapse.service.ts +59 -59
  114. package/src/services/terminal.service.ts +81 -81
  115. package/src/synapses/activation.ts +80 -80
  116. package/src/synapses/decay.ts +38 -38
  117. package/src/synapses/hebbian.ts +69 -69
  118. package/src/synapses/pathfinder.ts +81 -81
  119. package/src/synapses/synapse-manager.ts +109 -109
  120. package/src/types/code.types.ts +52 -52
  121. package/src/types/error.types.ts +67 -67
  122. package/src/types/ipc.types.ts +8 -8
  123. package/src/types/mcp.types.ts +53 -53
  124. package/src/types/research.types.ts +28 -28
  125. package/src/types/solution.types.ts +30 -30
  126. package/src/utils/events.ts +45 -45
  127. package/src/utils/hash.ts +5 -5
  128. package/src/utils/logger.ts +48 -48
  129. package/src/utils/paths.ts +19 -19
  130. package/tests/e2e/test_code_intelligence.py +1015 -0
  131. package/tests/e2e/test_error_memory.py +451 -0
  132. package/tests/e2e/test_full_integration.py +534 -0
  133. package/tests/fixtures/code-modules/modules.ts +83 -83
  134. package/tests/fixtures/errors/go.ts +9 -9
  135. package/tests/fixtures/errors/node.ts +24 -24
  136. package/tests/fixtures/errors/python.ts +21 -21
  137. package/tests/fixtures/errors/rust.ts +25 -25
  138. package/tests/fixtures/errors/shell.ts +15 -15
  139. package/tests/fixtures/solutions/solutions.ts +27 -27
  140. package/tests/helpers/setup-db.ts +52 -52
  141. package/tests/integration/code-flow.test.ts +86 -86
  142. package/tests/integration/error-flow.test.ts +83 -83
  143. package/tests/integration/ipc-flow.test.ts +166 -166
  144. package/tests/integration/learning-cycle.test.ts +82 -82
  145. package/tests/integration/synapse-flow.test.ts +117 -117
  146. package/tests/unit/code/analyzer.test.ts +58 -58
  147. package/tests/unit/code/fingerprint.test.ts +51 -51
  148. package/tests/unit/code/scorer.test.ts +55 -55
  149. package/tests/unit/learning/confidence-scorer.test.ts +60 -60
  150. package/tests/unit/learning/decay.test.ts +45 -45
  151. package/tests/unit/learning/pattern-extractor.test.ts +50 -50
  152. package/tests/unit/matching/error-matcher.test.ts +69 -69
  153. package/tests/unit/matching/fingerprint.test.ts +47 -47
  154. package/tests/unit/matching/similarity.test.ts +65 -65
  155. package/tests/unit/matching/tfidf.test.ts +71 -71
  156. package/tests/unit/matching/tokenizer.test.ts +83 -83
  157. package/tests/unit/parsing/parsers.test.ts +113 -113
  158. package/tests/unit/research/gap-analyzer.test.ts +45 -45
  159. package/tests/unit/research/trend-analyzer.test.ts +45 -45
  160. package/tests/unit/synapses/activation.test.ts +80 -80
  161. package/tests/unit/synapses/decay.test.ts +27 -27
  162. package/tests/unit/synapses/hebbian.test.ts +96 -96
  163. package/tests/unit/synapses/pathfinder.test.ts +72 -72
  164. 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
+ };