@timmeck/brain 1.8.0 → 1.8.2

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 (177) hide show
  1. package/BRAIN_PLAN.md +3324 -3324
  2. package/LICENSE +21 -21
  3. package/dist/api/server.d.ts +4 -0
  4. package/dist/api/server.js +73 -0
  5. package/dist/api/server.js.map +1 -1
  6. package/dist/brain.js +2 -1
  7. package/dist/brain.js.map +1 -1
  8. package/dist/cli/commands/dashboard.js +606 -572
  9. package/dist/cli/commands/dashboard.js.map +1 -1
  10. package/dist/dashboard/server.js +25 -25
  11. package/dist/db/migrations/001_core_schema.js +115 -115
  12. package/dist/db/migrations/002_learning_schema.js +33 -33
  13. package/dist/db/migrations/003_code_schema.js +48 -48
  14. package/dist/db/migrations/004_synapses_schema.js +52 -52
  15. package/dist/db/migrations/005_fts_indexes.js +73 -73
  16. package/dist/db/migrations/007_feedback.js +8 -8
  17. package/dist/db/migrations/008_git_integration.js +33 -33
  18. package/dist/db/migrations/009_embeddings.js +3 -3
  19. package/dist/db/repositories/antipattern.repository.js +3 -3
  20. package/dist/db/repositories/code-module.repository.js +32 -32
  21. package/dist/db/repositories/notification.repository.js +3 -3
  22. package/dist/db/repositories/project.repository.js +21 -21
  23. package/dist/db/repositories/rule.repository.js +24 -24
  24. package/dist/db/repositories/solution.repository.js +50 -50
  25. package/dist/db/repositories/synapse.repository.js +18 -18
  26. package/dist/db/repositories/terminal.repository.js +24 -24
  27. package/dist/embeddings/engine.d.ts +2 -2
  28. package/dist/embeddings/engine.js +17 -4
  29. package/dist/embeddings/engine.js.map +1 -1
  30. package/dist/index.js +1 -1
  31. package/dist/ipc/server.d.ts +8 -0
  32. package/dist/ipc/server.js +67 -1
  33. package/dist/ipc/server.js.map +1 -1
  34. package/dist/matching/error-matcher.js +5 -5
  35. package/dist/matching/fingerprint.js +6 -1
  36. package/dist/matching/fingerprint.js.map +1 -1
  37. package/dist/mcp/http-server.js +8 -2
  38. package/dist/mcp/http-server.js.map +1 -1
  39. package/dist/services/code.service.d.ts +3 -0
  40. package/dist/services/code.service.js +33 -4
  41. package/dist/services/code.service.js.map +1 -1
  42. package/dist/services/error.service.js +4 -3
  43. package/dist/services/error.service.js.map +1 -1
  44. package/dist/services/git.service.js +14 -14
  45. package/package.json +49 -49
  46. package/src/api/server.ts +395 -321
  47. package/src/brain.ts +266 -265
  48. package/src/cli/colors.ts +116 -116
  49. package/src/cli/commands/config.ts +169 -169
  50. package/src/cli/commands/dashboard.ts +755 -720
  51. package/src/cli/commands/doctor.ts +118 -118
  52. package/src/cli/commands/explain.ts +83 -83
  53. package/src/cli/commands/export.ts +31 -31
  54. package/src/cli/commands/import.ts +199 -199
  55. package/src/cli/commands/insights.ts +65 -65
  56. package/src/cli/commands/learn.ts +24 -24
  57. package/src/cli/commands/modules.ts +53 -53
  58. package/src/cli/commands/network.ts +67 -67
  59. package/src/cli/commands/projects.ts +42 -42
  60. package/src/cli/commands/query.ts +120 -120
  61. package/src/cli/commands/start.ts +62 -62
  62. package/src/cli/commands/status.ts +75 -75
  63. package/src/cli/commands/stop.ts +34 -34
  64. package/src/cli/ipc-helper.ts +22 -22
  65. package/src/cli/update-check.ts +63 -63
  66. package/src/code/fingerprint.ts +87 -87
  67. package/src/code/parsers/generic.ts +29 -29
  68. package/src/code/parsers/python.ts +54 -54
  69. package/src/code/parsers/typescript.ts +65 -65
  70. package/src/code/registry.ts +60 -60
  71. package/src/dashboard/server.ts +142 -142
  72. package/src/db/connection.ts +22 -22
  73. package/src/db/migrations/001_core_schema.ts +120 -120
  74. package/src/db/migrations/002_learning_schema.ts +38 -38
  75. package/src/db/migrations/003_code_schema.ts +53 -53
  76. package/src/db/migrations/004_synapses_schema.ts +57 -57
  77. package/src/db/migrations/005_fts_indexes.ts +78 -78
  78. package/src/db/migrations/006_synapses_phase3.ts +17 -17
  79. package/src/db/migrations/007_feedback.ts +13 -13
  80. package/src/db/migrations/008_git_integration.ts +38 -38
  81. package/src/db/migrations/009_embeddings.ts +8 -8
  82. package/src/db/repositories/antipattern.repository.ts +66 -66
  83. package/src/db/repositories/code-module.repository.ts +142 -142
  84. package/src/db/repositories/notification.repository.ts +66 -66
  85. package/src/db/repositories/project.repository.ts +93 -93
  86. package/src/db/repositories/rule.repository.ts +108 -108
  87. package/src/db/repositories/solution.repository.ts +154 -154
  88. package/src/db/repositories/synapse.repository.ts +153 -153
  89. package/src/db/repositories/terminal.repository.ts +101 -101
  90. package/src/embeddings/engine.ts +238 -217
  91. package/src/index.ts +63 -63
  92. package/src/ipc/client.ts +118 -118
  93. package/src/ipc/protocol.ts +35 -35
  94. package/src/ipc/router.ts +133 -133
  95. package/src/ipc/server.ts +176 -110
  96. package/src/learning/decay.ts +46 -46
  97. package/src/learning/pattern-extractor.ts +90 -90
  98. package/src/learning/rule-generator.ts +74 -74
  99. package/src/matching/error-matcher.ts +5 -5
  100. package/src/matching/fingerprint.ts +34 -29
  101. package/src/matching/similarity.ts +61 -61
  102. package/src/matching/tfidf.ts +74 -74
  103. package/src/matching/tokenizer.ts +41 -41
  104. package/src/mcp/auto-detect.ts +93 -93
  105. package/src/mcp/http-server.ts +140 -137
  106. package/src/mcp/server.ts +73 -73
  107. package/src/parsing/error-parser.ts +28 -28
  108. package/src/parsing/parsers/compiler.ts +93 -93
  109. package/src/parsing/parsers/generic.ts +28 -28
  110. package/src/parsing/parsers/go.ts +97 -97
  111. package/src/parsing/parsers/node.ts +69 -69
  112. package/src/parsing/parsers/python.ts +62 -62
  113. package/src/parsing/parsers/rust.ts +50 -50
  114. package/src/parsing/parsers/shell.ts +42 -42
  115. package/src/parsing/types.ts +47 -47
  116. package/src/research/gap-analyzer.ts +135 -135
  117. package/src/research/insight-generator.ts +123 -123
  118. package/src/research/research-engine.ts +116 -116
  119. package/src/research/synergy-detector.ts +126 -126
  120. package/src/research/template-extractor.ts +130 -130
  121. package/src/research/trend-analyzer.ts +127 -127
  122. package/src/services/code.service.ts +271 -238
  123. package/src/services/error.service.ts +4 -3
  124. package/src/services/git.service.ts +132 -132
  125. package/src/services/notification.service.ts +41 -41
  126. package/src/services/synapse.service.ts +59 -59
  127. package/src/services/terminal.service.ts +81 -81
  128. package/src/synapses/activation.ts +80 -80
  129. package/src/synapses/decay.ts +38 -38
  130. package/src/synapses/hebbian.ts +69 -69
  131. package/src/synapses/pathfinder.ts +81 -81
  132. package/src/synapses/synapse-manager.ts +109 -109
  133. package/src/types/code.types.ts +52 -52
  134. package/src/types/error.types.ts +67 -67
  135. package/src/types/ipc.types.ts +8 -8
  136. package/src/types/mcp.types.ts +53 -53
  137. package/src/types/research.types.ts +28 -28
  138. package/src/types/solution.types.ts +30 -30
  139. package/src/utils/events.ts +45 -45
  140. package/src/utils/hash.ts +5 -5
  141. package/src/utils/logger.ts +48 -48
  142. package/src/utils/paths.ts +19 -19
  143. package/tests/e2e/test_code_intelligence.py +1015 -0
  144. package/tests/e2e/test_error_memory.py +451 -0
  145. package/tests/e2e/test_full_integration.py +534 -0
  146. package/tests/fixtures/code-modules/modules.ts +83 -83
  147. package/tests/fixtures/errors/go.ts +9 -9
  148. package/tests/fixtures/errors/node.ts +24 -24
  149. package/tests/fixtures/errors/python.ts +21 -21
  150. package/tests/fixtures/errors/rust.ts +25 -25
  151. package/tests/fixtures/errors/shell.ts +15 -15
  152. package/tests/fixtures/solutions/solutions.ts +27 -27
  153. package/tests/helpers/setup-db.ts +52 -52
  154. package/tests/integration/code-flow.test.ts +86 -86
  155. package/tests/integration/error-flow.test.ts +83 -83
  156. package/tests/integration/ipc-flow.test.ts +166 -166
  157. package/tests/integration/learning-cycle.test.ts +82 -82
  158. package/tests/integration/synapse-flow.test.ts +117 -117
  159. package/tests/unit/code/analyzer.test.ts +58 -58
  160. package/tests/unit/code/fingerprint.test.ts +51 -51
  161. package/tests/unit/code/scorer.test.ts +55 -55
  162. package/tests/unit/learning/confidence-scorer.test.ts +60 -60
  163. package/tests/unit/learning/decay.test.ts +45 -45
  164. package/tests/unit/learning/pattern-extractor.test.ts +50 -50
  165. package/tests/unit/matching/error-matcher.test.ts +69 -69
  166. package/tests/unit/matching/fingerprint.test.ts +47 -47
  167. package/tests/unit/matching/similarity.test.ts +65 -65
  168. package/tests/unit/matching/tfidf.test.ts +71 -71
  169. package/tests/unit/matching/tokenizer.test.ts +83 -83
  170. package/tests/unit/parsing/parsers.test.ts +113 -113
  171. package/tests/unit/research/gap-analyzer.test.ts +45 -45
  172. package/tests/unit/research/trend-analyzer.test.ts +45 -45
  173. package/tests/unit/synapses/activation.test.ts +80 -80
  174. package/tests/unit/synapses/decay.test.ts +27 -27
  175. package/tests/unit/synapses/hebbian.test.ts +96 -96
  176. package/tests/unit/synapses/pathfinder.test.ts +72 -72
  177. package/tsconfig.json +18 -18
@@ -1,142 +1,142 @@
1
- import http from 'node:http';
2
- import { getEventBus } from '../utils/events.js';
3
- import { getLogger } from '../utils/logger.js';
4
-
5
- export interface DashboardServerOptions {
6
- port: number;
7
- getDashboardHtml: () => string;
8
- getStats: () => unknown;
9
- }
10
-
11
- export class DashboardServer {
12
- private server: http.Server | null = null;
13
- private clients: Set<http.ServerResponse> = new Set();
14
- private logger = getLogger();
15
-
16
- constructor(private options: DashboardServerOptions) {}
17
-
18
- start(): void {
19
- const { port, getDashboardHtml, getStats } = this.options;
20
- const bus = getEventBus();
21
-
22
- this.server = http.createServer((req, res) => {
23
- const url = new URL(req.url ?? '/', `http://localhost:${port}`);
24
-
25
- // CORS
26
- res.setHeader('Access-Control-Allow-Origin', '*');
27
- res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
28
-
29
- if (req.method === 'OPTIONS') {
30
- res.writeHead(204);
31
- res.end();
32
- return;
33
- }
34
-
35
- if (url.pathname === '/events') {
36
- // SSE endpoint
37
- res.writeHead(200, {
38
- 'Content-Type': 'text/event-stream',
39
- 'Cache-Control': 'no-cache',
40
- 'Connection': 'keep-alive',
41
- });
42
- res.write('data: {"type":"connected"}\n\n');
43
-
44
- this.clients.add(res);
45
- req.on('close', () => this.clients.delete(res));
46
- return;
47
- }
48
-
49
- if (url.pathname === '/api/stats') {
50
- const stats = getStats();
51
- res.writeHead(200, { 'Content-Type': 'application/json' });
52
- res.end(JSON.stringify(stats));
53
- return;
54
- }
55
-
56
- if (url.pathname === '/' || url.pathname === '/dashboard') {
57
- const html = getDashboardHtml();
58
- // Inject SSE script into the dashboard
59
- const sseScript = `
60
- <script>
61
- (function(){
62
- const evtSource = new EventSource('/events');
63
- evtSource.onmessage = function(e) {
64
- try {
65
- const data = JSON.parse(e.data);
66
- if (data.type === 'stats_update') {
67
- // Update stat cards
68
- document.querySelectorAll('.stat-number').forEach(el => {
69
- const key = el.parentElement?.querySelector('.stat-label')?.textContent?.toLowerCase();
70
- if (key && data.stats[key] !== undefined) {
71
- el.textContent = Number(data.stats[key]).toLocaleString();
72
- }
73
- });
74
- }
75
- if (data.type === 'event') {
76
- // Flash the activity dot
77
- const dot = document.querySelector('.activity-dot');
78
- if (dot) { dot.style.background = '#ff5577'; setTimeout(() => dot.style.background = '', 500); }
79
- }
80
- } catch {}
81
- };
82
- evtSource.onerror = function() { setTimeout(() => location.reload(), 5000); };
83
- })();
84
- </script>`;
85
- const liveHtml = html.replace('</body>', sseScript + '</body>');
86
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
87
- res.end(liveHtml);
88
- return;
89
- }
90
-
91
- res.writeHead(404, { 'Content-Type': 'text/plain' });
92
- res.end('Not Found');
93
- });
94
-
95
- // Forward Brain events to SSE clients
96
- const eventNames = [
97
- 'error:reported', 'error:resolved', 'solution:applied',
98
- 'solution:created', 'module:registered', 'module:updated',
99
- 'synapse:created', 'synapse:strengthened',
100
- 'insight:created', 'rule:learned',
101
- ] as const;
102
-
103
- for (const eventName of eventNames) {
104
- bus.on(eventName, (data: unknown) => {
105
- this.broadcast({ type: 'event', event: eventName, data });
106
- });
107
- }
108
-
109
- // Periodic stats broadcast (every 30s)
110
- setInterval(() => {
111
- if (this.clients.size > 0) {
112
- const stats = getStats();
113
- this.broadcast({ type: 'stats_update', stats });
114
- }
115
- }, 30_000);
116
-
117
- this.server.listen(port, () => {
118
- this.logger.info(`Dashboard server started on http://localhost:${port}`);
119
- });
120
- }
121
-
122
- stop(): void {
123
- for (const client of this.clients) {
124
- client.end();
125
- }
126
- this.clients.clear();
127
- this.server?.close();
128
- this.server = null;
129
- this.logger.info('Dashboard server stopped');
130
- }
131
-
132
- private broadcast(data: unknown): void {
133
- const msg = `data: ${JSON.stringify(data)}\n\n`;
134
- for (const client of this.clients) {
135
- try {
136
- client.write(msg);
137
- } catch {
138
- this.clients.delete(client);
139
- }
140
- }
141
- }
142
- }
1
+ import http from 'node:http';
2
+ import { getEventBus } from '../utils/events.js';
3
+ import { getLogger } from '../utils/logger.js';
4
+
5
+ export interface DashboardServerOptions {
6
+ port: number;
7
+ getDashboardHtml: () => string;
8
+ getStats: () => unknown;
9
+ }
10
+
11
+ export class DashboardServer {
12
+ private server: http.Server | null = null;
13
+ private clients: Set<http.ServerResponse> = new Set();
14
+ private logger = getLogger();
15
+
16
+ constructor(private options: DashboardServerOptions) {}
17
+
18
+ start(): void {
19
+ const { port, getDashboardHtml, getStats } = this.options;
20
+ const bus = getEventBus();
21
+
22
+ this.server = http.createServer((req, res) => {
23
+ const url = new URL(req.url ?? '/', `http://localhost:${port}`);
24
+
25
+ // CORS
26
+ res.setHeader('Access-Control-Allow-Origin', '*');
27
+ res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
28
+
29
+ if (req.method === 'OPTIONS') {
30
+ res.writeHead(204);
31
+ res.end();
32
+ return;
33
+ }
34
+
35
+ if (url.pathname === '/events') {
36
+ // SSE endpoint
37
+ res.writeHead(200, {
38
+ 'Content-Type': 'text/event-stream',
39
+ 'Cache-Control': 'no-cache',
40
+ 'Connection': 'keep-alive',
41
+ });
42
+ res.write('data: {"type":"connected"}\n\n');
43
+
44
+ this.clients.add(res);
45
+ req.on('close', () => this.clients.delete(res));
46
+ return;
47
+ }
48
+
49
+ if (url.pathname === '/api/stats') {
50
+ const stats = getStats();
51
+ res.writeHead(200, { 'Content-Type': 'application/json' });
52
+ res.end(JSON.stringify(stats));
53
+ return;
54
+ }
55
+
56
+ if (url.pathname === '/' || url.pathname === '/dashboard') {
57
+ const html = getDashboardHtml();
58
+ // Inject SSE script into the dashboard
59
+ const sseScript = `
60
+ <script>
61
+ (function(){
62
+ const evtSource = new EventSource('/events');
63
+ evtSource.onmessage = function(e) {
64
+ try {
65
+ const data = JSON.parse(e.data);
66
+ if (data.type === 'stats_update') {
67
+ // Update stat cards
68
+ document.querySelectorAll('.stat-number').forEach(el => {
69
+ const key = el.parentElement?.querySelector('.stat-label')?.textContent?.toLowerCase();
70
+ if (key && data.stats[key] !== undefined) {
71
+ el.textContent = Number(data.stats[key]).toLocaleString();
72
+ }
73
+ });
74
+ }
75
+ if (data.type === 'event') {
76
+ // Flash the activity dot
77
+ const dot = document.querySelector('.activity-dot');
78
+ if (dot) { dot.style.background = '#ff5577'; setTimeout(() => dot.style.background = '', 500); }
79
+ }
80
+ } catch {}
81
+ };
82
+ evtSource.onerror = function() { setTimeout(() => location.reload(), 5000); };
83
+ })();
84
+ </script>`;
85
+ const liveHtml = html.replace('</body>', sseScript + '</body>');
86
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
87
+ res.end(liveHtml);
88
+ return;
89
+ }
90
+
91
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
92
+ res.end('Not Found');
93
+ });
94
+
95
+ // Forward Brain events to SSE clients
96
+ const eventNames = [
97
+ 'error:reported', 'error:resolved', 'solution:applied',
98
+ 'solution:created', 'module:registered', 'module:updated',
99
+ 'synapse:created', 'synapse:strengthened',
100
+ 'insight:created', 'rule:learned',
101
+ ] as const;
102
+
103
+ for (const eventName of eventNames) {
104
+ bus.on(eventName, (data: unknown) => {
105
+ this.broadcast({ type: 'event', event: eventName, data });
106
+ });
107
+ }
108
+
109
+ // Periodic stats broadcast (every 30s)
110
+ setInterval(() => {
111
+ if (this.clients.size > 0) {
112
+ const stats = getStats();
113
+ this.broadcast({ type: 'stats_update', stats });
114
+ }
115
+ }, 30_000);
116
+
117
+ this.server.listen(port, () => {
118
+ this.logger.info(`Dashboard server started on http://localhost:${port}`);
119
+ });
120
+ }
121
+
122
+ stop(): void {
123
+ for (const client of this.clients) {
124
+ client.end();
125
+ }
126
+ this.clients.clear();
127
+ this.server?.close();
128
+ this.server = null;
129
+ this.logger.info('Dashboard server stopped');
130
+ }
131
+
132
+ private broadcast(data: unknown): void {
133
+ const msg = `data: ${JSON.stringify(data)}\n\n`;
134
+ for (const client of this.clients) {
135
+ try {
136
+ client.write(msg);
137
+ } catch {
138
+ this.clients.delete(client);
139
+ }
140
+ }
141
+ }
142
+ }
@@ -1,22 +1,22 @@
1
- import Database from 'better-sqlite3';
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import { getLogger } from '../utils/logger.js';
5
-
6
- export function createConnection(dbPath: string): Database.Database {
7
- const logger = getLogger();
8
- const dir = path.dirname(dbPath);
9
- if (!fs.existsSync(dir)) {
10
- fs.mkdirSync(dir, { recursive: true });
11
- }
12
-
13
- logger.info(`Opening database at ${dbPath}`);
14
- const db = new Database(dbPath);
15
-
16
- db.pragma('journal_mode = WAL');
17
- db.pragma('synchronous = NORMAL');
18
- db.pragma('cache_size = 10000');
19
- db.pragma('foreign_keys = ON');
20
-
21
- return db;
22
- }
1
+ import Database from 'better-sqlite3';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { getLogger } from '../utils/logger.js';
5
+
6
+ export function createConnection(dbPath: string): Database.Database {
7
+ const logger = getLogger();
8
+ const dir = path.dirname(dbPath);
9
+ if (!fs.existsSync(dir)) {
10
+ fs.mkdirSync(dir, { recursive: true });
11
+ }
12
+
13
+ logger.info(`Opening database at ${dbPath}`);
14
+ const db = new Database(dbPath);
15
+
16
+ db.pragma('journal_mode = WAL');
17
+ db.pragma('synchronous = NORMAL');
18
+ db.pragma('cache_size = 10000');
19
+ db.pragma('foreign_keys = ON');
20
+
21
+ return db;
22
+ }
@@ -1,120 +1,120 @@
1
- import type Database from 'better-sqlite3';
2
-
3
- export function up(db: Database.Database): void {
4
- db.exec(`
5
- CREATE TABLE IF NOT EXISTS projects (
6
- id INTEGER PRIMARY KEY AUTOINCREMENT,
7
- name TEXT NOT NULL UNIQUE,
8
- path TEXT,
9
- language TEXT,
10
- framework TEXT,
11
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
12
- updated_at TEXT NOT NULL DEFAULT (datetime('now'))
13
- );
14
-
15
- CREATE TABLE IF NOT EXISTS terminals (
16
- id INTEGER PRIMARY KEY AUTOINCREMENT,
17
- uuid TEXT NOT NULL UNIQUE,
18
- project_id INTEGER,
19
- pid INTEGER,
20
- shell TEXT,
21
- cwd TEXT,
22
- connected_at TEXT NOT NULL DEFAULT (datetime('now')),
23
- last_seen TEXT NOT NULL DEFAULT (datetime('now')),
24
- disconnected_at TEXT,
25
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL
26
- );
27
-
28
- CREATE TABLE IF NOT EXISTS errors (
29
- id INTEGER PRIMARY KEY AUTOINCREMENT,
30
- project_id INTEGER NOT NULL,
31
- terminal_id INTEGER,
32
- fingerprint TEXT NOT NULL,
33
- type TEXT NOT NULL,
34
- message TEXT NOT NULL,
35
- raw_output TEXT NOT NULL,
36
- context TEXT,
37
- file_path TEXT,
38
- line_number INTEGER,
39
- column_number INTEGER,
40
- occurrence_count INTEGER NOT NULL DEFAULT 1,
41
- first_seen TEXT NOT NULL DEFAULT (datetime('now')),
42
- last_seen TEXT NOT NULL DEFAULT (datetime('now')),
43
- resolved INTEGER NOT NULL DEFAULT 0,
44
- resolved_at TEXT,
45
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
46
- FOREIGN KEY (terminal_id) REFERENCES terminals(id) ON DELETE SET NULL
47
- );
48
-
49
- CREATE TABLE IF NOT EXISTS stack_frames (
50
- id INTEGER PRIMARY KEY AUTOINCREMENT,
51
- error_id INTEGER NOT NULL,
52
- frame_index INTEGER NOT NULL,
53
- file TEXT NOT NULL,
54
- line INTEGER NOT NULL,
55
- "column" INTEGER,
56
- function_name TEXT,
57
- source TEXT,
58
- FOREIGN KEY (error_id) REFERENCES errors(id) ON DELETE CASCADE
59
- );
60
-
61
- CREATE TABLE IF NOT EXISTS solutions (
62
- id INTEGER PRIMARY KEY AUTOINCREMENT,
63
- description TEXT NOT NULL,
64
- commands TEXT,
65
- code_change TEXT,
66
- source TEXT NOT NULL DEFAULT 'manual',
67
- confidence REAL NOT NULL DEFAULT 0.5,
68
- success_count INTEGER NOT NULL DEFAULT 0,
69
- fail_count INTEGER NOT NULL DEFAULT 0,
70
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
71
- updated_at TEXT NOT NULL DEFAULT (datetime('now'))
72
- );
73
-
74
- CREATE TABLE IF NOT EXISTS error_solutions (
75
- id INTEGER PRIMARY KEY AUTOINCREMENT,
76
- error_id INTEGER NOT NULL,
77
- solution_id INTEGER NOT NULL,
78
- applied_at TEXT,
79
- success INTEGER,
80
- FOREIGN KEY (error_id) REFERENCES errors(id) ON DELETE CASCADE,
81
- FOREIGN KEY (solution_id) REFERENCES solutions(id) ON DELETE CASCADE,
82
- UNIQUE(error_id, solution_id)
83
- );
84
-
85
- CREATE TABLE IF NOT EXISTS solution_attempts (
86
- id INTEGER PRIMARY KEY AUTOINCREMENT,
87
- error_solution_id INTEGER NOT NULL,
88
- terminal_id INTEGER,
89
- attempted_at TEXT NOT NULL DEFAULT (datetime('now')),
90
- success INTEGER NOT NULL DEFAULT 0,
91
- output TEXT,
92
- duration_ms INTEGER,
93
- FOREIGN KEY (error_solution_id) REFERENCES error_solutions(id) ON DELETE CASCADE,
94
- FOREIGN KEY (terminal_id) REFERENCES terminals(id) ON DELETE SET NULL
95
- );
96
-
97
- CREATE TABLE IF NOT EXISTS error_chains (
98
- id INTEGER PRIMARY KEY AUTOINCREMENT,
99
- parent_error_id INTEGER NOT NULL,
100
- child_error_id INTEGER NOT NULL,
101
- relationship TEXT NOT NULL DEFAULT 'causes',
102
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
103
- FOREIGN KEY (parent_error_id) REFERENCES errors(id) ON DELETE CASCADE,
104
- FOREIGN KEY (child_error_id) REFERENCES errors(id) ON DELETE CASCADE,
105
- UNIQUE(parent_error_id, child_error_id)
106
- );
107
-
108
- CREATE INDEX IF NOT EXISTS idx_errors_fingerprint ON errors(fingerprint);
109
- CREATE INDEX IF NOT EXISTS idx_errors_project ON errors(project_id);
110
- CREATE INDEX IF NOT EXISTS idx_errors_type ON errors(type);
111
- CREATE INDEX IF NOT EXISTS idx_errors_resolved ON errors(resolved);
112
- CREATE INDEX IF NOT EXISTS idx_errors_last_seen ON errors(last_seen);
113
- CREATE INDEX IF NOT EXISTS idx_stack_frames_error ON stack_frames(error_id);
114
- CREATE INDEX IF NOT EXISTS idx_error_solutions_error ON error_solutions(error_id);
115
- CREATE INDEX IF NOT EXISTS idx_error_solutions_solution ON error_solutions(solution_id);
116
- CREATE INDEX IF NOT EXISTS idx_solution_attempts_es ON solution_attempts(error_solution_id);
117
- CREATE INDEX IF NOT EXISTS idx_terminals_uuid ON terminals(uuid);
118
- CREATE INDEX IF NOT EXISTS idx_terminals_project ON terminals(project_id);
119
- `);
120
- }
1
+ import type Database from 'better-sqlite3';
2
+
3
+ export function up(db: Database.Database): void {
4
+ db.exec(`
5
+ CREATE TABLE IF NOT EXISTS projects (
6
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
7
+ name TEXT NOT NULL UNIQUE,
8
+ path TEXT,
9
+ language TEXT,
10
+ framework TEXT,
11
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
12
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
13
+ );
14
+
15
+ CREATE TABLE IF NOT EXISTS terminals (
16
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
17
+ uuid TEXT NOT NULL UNIQUE,
18
+ project_id INTEGER,
19
+ pid INTEGER,
20
+ shell TEXT,
21
+ cwd TEXT,
22
+ connected_at TEXT NOT NULL DEFAULT (datetime('now')),
23
+ last_seen TEXT NOT NULL DEFAULT (datetime('now')),
24
+ disconnected_at TEXT,
25
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL
26
+ );
27
+
28
+ CREATE TABLE IF NOT EXISTS errors (
29
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
30
+ project_id INTEGER NOT NULL,
31
+ terminal_id INTEGER,
32
+ fingerprint TEXT NOT NULL,
33
+ type TEXT NOT NULL,
34
+ message TEXT NOT NULL,
35
+ raw_output TEXT NOT NULL,
36
+ context TEXT,
37
+ file_path TEXT,
38
+ line_number INTEGER,
39
+ column_number INTEGER,
40
+ occurrence_count INTEGER NOT NULL DEFAULT 1,
41
+ first_seen TEXT NOT NULL DEFAULT (datetime('now')),
42
+ last_seen TEXT NOT NULL DEFAULT (datetime('now')),
43
+ resolved INTEGER NOT NULL DEFAULT 0,
44
+ resolved_at TEXT,
45
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
46
+ FOREIGN KEY (terminal_id) REFERENCES terminals(id) ON DELETE SET NULL
47
+ );
48
+
49
+ CREATE TABLE IF NOT EXISTS stack_frames (
50
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
51
+ error_id INTEGER NOT NULL,
52
+ frame_index INTEGER NOT NULL,
53
+ file TEXT NOT NULL,
54
+ line INTEGER NOT NULL,
55
+ "column" INTEGER,
56
+ function_name TEXT,
57
+ source TEXT,
58
+ FOREIGN KEY (error_id) REFERENCES errors(id) ON DELETE CASCADE
59
+ );
60
+
61
+ CREATE TABLE IF NOT EXISTS solutions (
62
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
63
+ description TEXT NOT NULL,
64
+ commands TEXT,
65
+ code_change TEXT,
66
+ source TEXT NOT NULL DEFAULT 'manual',
67
+ confidence REAL NOT NULL DEFAULT 0.5,
68
+ success_count INTEGER NOT NULL DEFAULT 0,
69
+ fail_count INTEGER NOT NULL DEFAULT 0,
70
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
71
+ updated_at TEXT NOT NULL DEFAULT (datetime('now'))
72
+ );
73
+
74
+ CREATE TABLE IF NOT EXISTS error_solutions (
75
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
76
+ error_id INTEGER NOT NULL,
77
+ solution_id INTEGER NOT NULL,
78
+ applied_at TEXT,
79
+ success INTEGER,
80
+ FOREIGN KEY (error_id) REFERENCES errors(id) ON DELETE CASCADE,
81
+ FOREIGN KEY (solution_id) REFERENCES solutions(id) ON DELETE CASCADE,
82
+ UNIQUE(error_id, solution_id)
83
+ );
84
+
85
+ CREATE TABLE IF NOT EXISTS solution_attempts (
86
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
87
+ error_solution_id INTEGER NOT NULL,
88
+ terminal_id INTEGER,
89
+ attempted_at TEXT NOT NULL DEFAULT (datetime('now')),
90
+ success INTEGER NOT NULL DEFAULT 0,
91
+ output TEXT,
92
+ duration_ms INTEGER,
93
+ FOREIGN KEY (error_solution_id) REFERENCES error_solutions(id) ON DELETE CASCADE,
94
+ FOREIGN KEY (terminal_id) REFERENCES terminals(id) ON DELETE SET NULL
95
+ );
96
+
97
+ CREATE TABLE IF NOT EXISTS error_chains (
98
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
99
+ parent_error_id INTEGER NOT NULL,
100
+ child_error_id INTEGER NOT NULL,
101
+ relationship TEXT NOT NULL DEFAULT 'causes',
102
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
103
+ FOREIGN KEY (parent_error_id) REFERENCES errors(id) ON DELETE CASCADE,
104
+ FOREIGN KEY (child_error_id) REFERENCES errors(id) ON DELETE CASCADE,
105
+ UNIQUE(parent_error_id, child_error_id)
106
+ );
107
+
108
+ CREATE INDEX IF NOT EXISTS idx_errors_fingerprint ON errors(fingerprint);
109
+ CREATE INDEX IF NOT EXISTS idx_errors_project ON errors(project_id);
110
+ CREATE INDEX IF NOT EXISTS idx_errors_type ON errors(type);
111
+ CREATE INDEX IF NOT EXISTS idx_errors_resolved ON errors(resolved);
112
+ CREATE INDEX IF NOT EXISTS idx_errors_last_seen ON errors(last_seen);
113
+ CREATE INDEX IF NOT EXISTS idx_stack_frames_error ON stack_frames(error_id);
114
+ CREATE INDEX IF NOT EXISTS idx_error_solutions_error ON error_solutions(error_id);
115
+ CREATE INDEX IF NOT EXISTS idx_error_solutions_solution ON error_solutions(solution_id);
116
+ CREATE INDEX IF NOT EXISTS idx_solution_attempts_es ON solution_attempts(error_solution_id);
117
+ CREATE INDEX IF NOT EXISTS idx_terminals_uuid ON terminals(uuid);
118
+ CREATE INDEX IF NOT EXISTS idx_terminals_project ON terminals(project_id);
119
+ `);
120
+ }
@@ -1,38 +1,38 @@
1
- import type Database from 'better-sqlite3';
2
-
3
- export function up(db: Database.Database): void {
4
- db.exec(`
5
- CREATE TABLE IF NOT EXISTS rules (
6
- id INTEGER PRIMARY KEY AUTOINCREMENT,
7
- pattern TEXT NOT NULL,
8
- action TEXT NOT NULL,
9
- description TEXT,
10
- confidence REAL NOT NULL DEFAULT 0.5,
11
- occurrences INTEGER NOT NULL DEFAULT 0,
12
- active INTEGER NOT NULL DEFAULT 1,
13
- project_id INTEGER,
14
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
15
- updated_at TEXT NOT NULL DEFAULT (datetime('now')),
16
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL
17
- );
18
-
19
- CREATE TABLE IF NOT EXISTS antipatterns (
20
- id INTEGER PRIMARY KEY AUTOINCREMENT,
21
- pattern TEXT NOT NULL,
22
- description TEXT NOT NULL,
23
- severity TEXT NOT NULL DEFAULT 'warning',
24
- suggestion TEXT,
25
- occurrences INTEGER NOT NULL DEFAULT 0,
26
- project_id INTEGER,
27
- global INTEGER NOT NULL DEFAULT 0,
28
- created_at TEXT NOT NULL DEFAULT (datetime('now')),
29
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL
30
- );
31
-
32
- CREATE INDEX IF NOT EXISTS idx_rules_pattern ON rules(pattern);
33
- CREATE INDEX IF NOT EXISTS idx_rules_active ON rules(active);
34
- CREATE INDEX IF NOT EXISTS idx_rules_project ON rules(project_id);
35
- CREATE INDEX IF NOT EXISTS idx_antipatterns_project ON antipatterns(project_id);
36
- CREATE INDEX IF NOT EXISTS idx_antipatterns_global ON antipatterns(global);
37
- `);
38
- }
1
+ import type Database from 'better-sqlite3';
2
+
3
+ export function up(db: Database.Database): void {
4
+ db.exec(`
5
+ CREATE TABLE IF NOT EXISTS rules (
6
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
7
+ pattern TEXT NOT NULL,
8
+ action TEXT NOT NULL,
9
+ description TEXT,
10
+ confidence REAL NOT NULL DEFAULT 0.5,
11
+ occurrences INTEGER NOT NULL DEFAULT 0,
12
+ active INTEGER NOT NULL DEFAULT 1,
13
+ project_id INTEGER,
14
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
15
+ updated_at TEXT NOT NULL DEFAULT (datetime('now')),
16
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL
17
+ );
18
+
19
+ CREATE TABLE IF NOT EXISTS antipatterns (
20
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
21
+ pattern TEXT NOT NULL,
22
+ description TEXT NOT NULL,
23
+ severity TEXT NOT NULL DEFAULT 'warning',
24
+ suggestion TEXT,
25
+ occurrences INTEGER NOT NULL DEFAULT 0,
26
+ project_id INTEGER,
27
+ global INTEGER NOT NULL DEFAULT 0,
28
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
29
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL
30
+ );
31
+
32
+ CREATE INDEX IF NOT EXISTS idx_rules_pattern ON rules(pattern);
33
+ CREATE INDEX IF NOT EXISTS idx_rules_active ON rules(active);
34
+ CREATE INDEX IF NOT EXISTS idx_rules_project ON rules(project_id);
35
+ CREATE INDEX IF NOT EXISTS idx_antipatterns_project ON antipatterns(project_id);
36
+ CREATE INDEX IF NOT EXISTS idx_antipatterns_global ON antipatterns(global);
37
+ `);
38
+ }