mr-sliy 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/.env.example +145 -0
  2. package/database/schema.sql +187 -0
  3. package/package.json +74 -0
  4. package/scripts/download-tree-sitter.js +171 -0
  5. package/scripts/postinstall.js +134 -0
  6. package/src/agent/agent.js +563 -0
  7. package/src/agent.js +87 -0
  8. package/src/cli/index.js +1643 -0
  9. package/src/config/index.js +232 -0
  10. package/src/engine/dualModeEngine.js +486 -0
  11. package/src/index.js +165 -0
  12. package/src/middlewares/errorHandler.js +166 -0
  13. package/src/middlewares/index.js +23 -0
  14. package/src/routes/aiRoutes.js +117 -0
  15. package/src/routes/configRoutes.js +31 -0
  16. package/src/routes/index.js +75 -0
  17. package/src/routes/issueRoutes.js +195 -0
  18. package/src/routes/projectRoutes.js +46 -0
  19. package/src/routes/reportRoutes.js +40 -0
  20. package/src/routes/scanRoutes.js +245 -0
  21. package/src/routes/userRoutes.js +47 -0
  22. package/src/services/ast/parser.js +503 -0
  23. package/src/services/detection/detector.js +934 -0
  24. package/src/services/llm/providers.js +1107 -0
  25. package/src/services/rag/agent.js +375 -0
  26. package/src/services/vector/knowledgeBase.js +863 -0
  27. package/src/skills/Skill.js +38 -0
  28. package/src/skills/code-analysis/index.js +272 -0
  29. package/src/skills/code-detection/index.js +166 -0
  30. package/src/skills/code-detection/rules/console-log.js +45 -0
  31. package/src/skills/code-detection/rules/deep-nesting.js +76 -0
  32. package/src/skills/code-detection/rules/duplicate-code.js +57 -0
  33. package/src/skills/code-detection/rules/high-complexity.js +109 -0
  34. package/src/skills/code-detection/rules/index.js +59 -0
  35. package/src/skills/code-detection/rules/long-functions.js +54 -0
  36. package/src/skills/code-detection/rules/magic-numbers.js +48 -0
  37. package/src/skills/code-detection/rules/missing-comment.js +64 -0
  38. package/src/skills/code-detection/rules/null-check.js +71 -0
  39. package/src/skills/code-detection/rules/unnecessary-else.js +46 -0
  40. package/src/skills/code-detection/rules/unused-functions.js +57 -0
  41. package/src/skills/code-detection/rules/unused-imports.js +57 -0
  42. package/src/skills/code-detection/rules/unused-variables.js +54 -0
  43. package/src/skills/code-optimization/index.js +319 -0
  44. package/src/skills/index.js +152 -0
  45. package/src/utils/crypto.js +212 -0
  46. package/src/utils/database.js +125 -0
  47. package/src/utils/helpers.js +226 -0
  48. package/src/utils/logger.js +202 -0
  49. package/src/utils/mysql.js +198 -0
  50. package/src/utils/response.js +124 -0
@@ -0,0 +1,198 @@
1
+ /**
2
+ * MySQL数据库连接模块
3
+ * 用于云端知识库同步
4
+ * 可选配置,未启用时不影响本地SQLite
5
+ */
6
+
7
+ const mysql = require('mysql2/promise');
8
+ const { config } = require('../config');
9
+ const { logger } = require('./logger');
10
+
11
+ let pool = null;
12
+
13
+ /**
14
+ * 获取MySQL连接池
15
+ */
16
+ function getPool() {
17
+ if (!config.mysql.enabled) {
18
+ return null;
19
+ }
20
+
21
+ if (!pool) {
22
+ try {
23
+ pool = mysql.createPool({
24
+ host: config.mysql.host,
25
+ port: config.mysql.port,
26
+ user: config.mysql.user,
27
+ password: config.mysql.password,
28
+ database: config.mysql.database,
29
+ connectionLimit: config.mysql.connectionLimit,
30
+ waitForConnections: true,
31
+ queueLimit: 0,
32
+ charset: 'utf8mb4'
33
+ });
34
+
35
+ logger.info('MySQL连接池创建成功');
36
+ } catch (error) {
37
+ logger.warn(`MySQL连接池创建失败: ${error.message}`);
38
+ pool = null;
39
+ }
40
+ }
41
+
42
+ return pool;
43
+ }
44
+
45
+ /**
46
+ * 测试MySQL连接
47
+ */
48
+ async function testConnection() {
49
+ const pool = getPool();
50
+ if (!pool) {
51
+ return { success: false, message: 'MySQL未启用' };
52
+ }
53
+
54
+ try {
55
+ const connection = await pool.getConnection();
56
+ await connection.ping();
57
+ connection.release();
58
+ return { success: true, message: 'MySQL连接成功' };
59
+ } catch (error) {
60
+ return { success: false, message: error.message };
61
+ }
62
+ }
63
+
64
+ /**
65
+ * 执行查询
66
+ */
67
+ async function query(sql, params = []) {
68
+ const pool = getPool();
69
+ if (!pool) {
70
+ throw new Error('MySQL未启用');
71
+ }
72
+
73
+ try {
74
+ const [rows] = await pool.execute(sql, params);
75
+ return rows;
76
+ } catch (error) {
77
+ logger.debug(`MySQL查询失败: ${error.message}`);
78
+ throw error;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * 执行插入/更新/删除
84
+ */
85
+ async function execute(sql, params = []) {
86
+ const pool = getPool();
87
+ if (!pool) {
88
+ throw new Error('MySQL未启用');
89
+ }
90
+
91
+ try {
92
+ const [result] = await pool.execute(sql, params);
93
+ return {
94
+ success: true,
95
+ affectedRows: result.affectedRows,
96
+ insertId: result.insertId
97
+ };
98
+ } catch (error) {
99
+ logger.debug(`MySQL执行失败: ${error.message}`);
100
+ throw error;
101
+ }
102
+ }
103
+
104
+ /**
105
+ * 初始化MySQL数据库表
106
+ */
107
+ async function initDatabase() {
108
+ const pool = getPool();
109
+ if (!pool) {
110
+ return false;
111
+ }
112
+
113
+ try {
114
+ // 创建知识条目表
115
+ await query(`
116
+ CREATE TABLE IF NOT EXISTS knowledge_entries (
117
+ id VARCHAR(36) PRIMARY KEY,
118
+ title VARCHAR(255) NOT NULL,
119
+ category VARCHAR(50) NOT NULL,
120
+ content TEXT NOT NULL,
121
+ tags TEXT,
122
+ language VARCHAR(20) DEFAULT 'general',
123
+ source VARCHAR(50) DEFAULT 'default',
124
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
125
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
126
+ INDEX idx_category (category),
127
+ INDEX idx_language (language)
128
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
129
+ `);
130
+
131
+ // 创建优化案例表
132
+ await query(`
133
+ CREATE TABLE IF NOT EXISTS optimization_cases (
134
+ id VARCHAR(36) PRIMARY KEY,
135
+ title VARCHAR(255) NOT NULL,
136
+ category VARCHAR(50) NOT NULL,
137
+ before_code TEXT,
138
+ after_code TEXT,
139
+ description TEXT,
140
+ language VARCHAR(20) DEFAULT 'javascript',
141
+ complexity VARCHAR(20) DEFAULT 'medium',
142
+ tags TEXT,
143
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
144
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
145
+ INDEX idx_category (category),
146
+ INDEX idx_language (language)
147
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
148
+ `);
149
+
150
+ // 创建同步元数据表
151
+ await query(`
152
+ CREATE TABLE IF NOT EXISTS sync_metadata (
153
+ id INT PRIMARY KEY AUTO_INCREMENT,
154
+ table_name VARCHAR(50) NOT NULL,
155
+ last_sync_at TIMESTAMP NULL,
156
+ record_count INT DEFAULT 0,
157
+ machine_id VARCHAR(32),
158
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
159
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
160
+ UNIQUE KEY uk_table_machine (table_name, machine_id)
161
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
162
+ `);
163
+
164
+ logger.info('MySQL数据库表初始化完成');
165
+ return true;
166
+ } catch (error) {
167
+ logger.warn(`MySQL数据库表初始化失败: ${error.message}`);
168
+ return false;
169
+ }
170
+ }
171
+
172
+ /**
173
+ * 关闭连接池
174
+ */
175
+ async function closePool() {
176
+ if (pool) {
177
+ await pool.end();
178
+ pool = null;
179
+ logger.info('MySQL连接池已关闭');
180
+ }
181
+ }
182
+
183
+ /**
184
+ * 检查MySQL是否可用
185
+ */
186
+ function isEnabled() {
187
+ return config.mysql.enabled && getPool() !== null;
188
+ }
189
+
190
+ module.exports = {
191
+ getPool,
192
+ testConnection,
193
+ query,
194
+ execute,
195
+ initDatabase,
196
+ closePool,
197
+ isEnabled
198
+ };
@@ -0,0 +1,124 @@
1
+ /**
2
+ * API响应工具模块
3
+ * 统一API响应格式
4
+ */
5
+
6
+ /**
7
+ * 成功响应
8
+ */
9
+ function success(data = null, message = '操作成功', code = 200) {
10
+ return {
11
+ success: true,
12
+ code,
13
+ message,
14
+ data,
15
+ timestamp: new Date().toISOString()
16
+ };
17
+ }
18
+
19
+ /**
20
+ * 错误响应
21
+ */
22
+ function error(message = '操作失败', code = 500, errors = null) {
23
+ return {
24
+ success: false,
25
+ code,
26
+ message,
27
+ errors,
28
+ timestamp: new Date().toISOString()
29
+ };
30
+ }
31
+
32
+ /**
33
+ * 分页响应
34
+ */
35
+ function paginate(data, total, page, pageSize) {
36
+ return {
37
+ success: true,
38
+ code: 200,
39
+ message: '查询成功',
40
+ data: {
41
+ list: data,
42
+ pagination: {
43
+ total,
44
+ page: parseInt(page),
45
+ pageSize: parseInt(pageSize),
46
+ totalPages: Math.ceil(total / parseInt(pageSize))
47
+ }
48
+ },
49
+ timestamp: new Date().toISOString()
50
+ };
51
+ }
52
+
53
+ /**
54
+ * 参数验证错误响应
55
+ */
56
+ function validationError(errors) {
57
+ return {
58
+ success: false,
59
+ code: 400,
60
+ message: '参数验证失败',
61
+ errors,
62
+ timestamp: new Date().toISOString()
63
+ };
64
+ }
65
+
66
+ /**
67
+ * 未授权响应
68
+ */
69
+ function unauthorized(message = '未授权访问') {
70
+ return {
71
+ success: false,
72
+ code: 401,
73
+ message,
74
+ timestamp: new Date().toISOString()
75
+ };
76
+ }
77
+
78
+ /**
79
+ * 禁止访问响应
80
+ */
81
+ function forbidden(message = '禁止访问') {
82
+ return {
83
+ success: false,
84
+ code: 403,
85
+ message,
86
+ timestamp: new Date().toISOString()
87
+ };
88
+ }
89
+
90
+ /**
91
+ * 资源未找到响应
92
+ */
93
+ function notFound(message = '资源未找到') {
94
+ return {
95
+ success: false,
96
+ code: 404,
97
+ message,
98
+ timestamp: new Date().toISOString()
99
+ };
100
+ }
101
+
102
+ /**
103
+ * 服务端错误响应
104
+ */
105
+ function serverError(message = '服务器内部错误', errors = null) {
106
+ return {
107
+ success: false,
108
+ code: 500,
109
+ message,
110
+ errors,
111
+ timestamp: new Date().toISOString()
112
+ };
113
+ }
114
+
115
+ module.exports = {
116
+ success,
117
+ error,
118
+ paginate,
119
+ validationError,
120
+ unauthorized,
121
+ forbidden,
122
+ notFound,
123
+ serverError
124
+ };