activo 0.4.3 → 0.5.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 (166) hide show
  1. package/README.md +203 -1
  2. package/data/2026-03-04_20-54.json +181 -0
  3. package/data/2026-03-04_20-56.json +181 -0
  4. package/data/apex-rulesets/egov.yaml +469 -0
  5. package/data/apex-rulesets/modernize.yaml +687 -0
  6. package/data/apex-rulesets/quality.yaml +1677 -0
  7. package/data/apex-rulesets/rule-schema.yaml +587 -0
  8. package/data/apex-rulesets/secure.yaml +1688 -0
  9. package/data/apex-rulesets/spring.yaml +455 -0
  10. package/data/apex-rulesets/sql-format.yaml +99 -0
  11. package/data/apex-rulesets/sql-oracle.yaml +281 -0
  12. package/data/apex-rulesets/sql.yaml +1660 -0
  13. package/dist/cli/headless.d.ts.map +1 -1
  14. package/dist/cli/headless.js +32 -10
  15. package/dist/cli/headless.js.map +1 -1
  16. package/dist/cli/index.js +31 -3
  17. package/dist/cli/index.js.map +1 -1
  18. package/dist/core/agent.d.ts +3 -3
  19. package/dist/core/agent.d.ts.map +1 -1
  20. package/dist/core/agent.js +255 -17
  21. package/dist/core/agent.js.map +1 -1
  22. package/dist/core/commands.d.ts +2 -1
  23. package/dist/core/commands.d.ts.map +1 -1
  24. package/dist/core/commands.js +61 -9
  25. package/dist/core/commands.js.map +1 -1
  26. package/dist/core/config.d.ts +14 -0
  27. package/dist/core/config.d.ts.map +1 -1
  28. package/dist/core/config.js +41 -4
  29. package/dist/core/config.js.map +1 -1
  30. package/dist/core/conversation.d.ts +2 -2
  31. package/dist/core/conversation.d.ts.map +1 -1
  32. package/dist/core/conversation.js.map +1 -1
  33. package/dist/core/intentRouter.d.ts +43 -0
  34. package/dist/core/intentRouter.d.ts.map +1 -0
  35. package/dist/core/intentRouter.js +804 -0
  36. package/dist/core/intentRouter.js.map +1 -0
  37. package/dist/core/llm/anthropic.d.ts +24 -0
  38. package/dist/core/llm/anthropic.d.ts.map +1 -0
  39. package/dist/core/llm/anthropic.js +226 -0
  40. package/dist/core/llm/anthropic.js.map +1 -0
  41. package/dist/core/llm/ollama.d.ts +5 -14
  42. package/dist/core/llm/ollama.d.ts.map +1 -1
  43. package/dist/core/llm/ollama.js +3 -0
  44. package/dist/core/llm/ollama.js.map +1 -1
  45. package/dist/core/llm/types.d.ts +22 -0
  46. package/dist/core/llm/types.d.ts.map +1 -0
  47. package/dist/core/llm/types.js +2 -0
  48. package/dist/core/llm/types.js.map +1 -0
  49. package/dist/core/mcp/client.d.ts +6 -0
  50. package/dist/core/mcp/client.d.ts.map +1 -1
  51. package/dist/core/mcp/client.js +16 -0
  52. package/dist/core/mcp/client.js.map +1 -1
  53. package/dist/core/mcp/init.d.ts +12 -0
  54. package/dist/core/mcp/init.d.ts.map +1 -0
  55. package/dist/core/mcp/init.js +55 -0
  56. package/dist/core/mcp/init.js.map +1 -0
  57. package/dist/core/mcp/logger.d.ts +14 -0
  58. package/dist/core/mcp/logger.d.ts.map +1 -0
  59. package/dist/core/mcp/logger.js +50 -0
  60. package/dist/core/mcp/logger.js.map +1 -0
  61. package/dist/core/tools/analyzeAll.d.ts.map +1 -1
  62. package/dist/core/tools/analyzeAll.js +16 -28
  63. package/dist/core/tools/analyzeAll.js.map +1 -1
  64. package/dist/core/tools/analyzePatterns.d.ts +3 -0
  65. package/dist/core/tools/analyzePatterns.d.ts.map +1 -0
  66. package/dist/core/tools/analyzePatterns.js +293 -0
  67. package/dist/core/tools/analyzePatterns.js.map +1 -0
  68. package/dist/core/tools/apexPaths.d.ts +14 -0
  69. package/dist/core/tools/apexPaths.d.ts.map +1 -0
  70. package/dist/core/tools/apexPaths.js +54 -0
  71. package/dist/core/tools/apexPaths.js.map +1 -0
  72. package/dist/core/tools/apexUtils.d.ts +36 -0
  73. package/dist/core/tools/apexUtils.d.ts.map +1 -0
  74. package/dist/core/tools/apexUtils.js +83 -0
  75. package/dist/core/tools/apexUtils.js.map +1 -0
  76. package/dist/core/tools/explainIssue.d.ts +3 -0
  77. package/dist/core/tools/explainIssue.d.ts.map +1 -0
  78. package/dist/core/tools/explainIssue.js +181 -0
  79. package/dist/core/tools/explainIssue.js.map +1 -0
  80. package/dist/core/tools/fixGen.d.ts +3 -0
  81. package/dist/core/tools/fixGen.d.ts.map +1 -0
  82. package/dist/core/tools/fixGen.js +338 -0
  83. package/dist/core/tools/fixGen.js.map +1 -0
  84. package/dist/core/tools/generateImprovements.d.ts +21 -0
  85. package/dist/core/tools/generateImprovements.d.ts.map +1 -0
  86. package/dist/core/tools/generateImprovements.js +602 -0
  87. package/dist/core/tools/generateImprovements.js.map +1 -0
  88. package/dist/core/tools/generateReport.d.ts +3 -0
  89. package/dist/core/tools/generateReport.d.ts.map +1 -0
  90. package/dist/core/tools/generateReport.js +315 -0
  91. package/dist/core/tools/generateReport.js.map +1 -0
  92. package/dist/core/tools/index.d.ts +7 -0
  93. package/dist/core/tools/index.d.ts.map +1 -1
  94. package/dist/core/tools/index.js +62 -23
  95. package/dist/core/tools/index.js.map +1 -1
  96. package/dist/core/tools/javaAst.d.ts.map +1 -1
  97. package/dist/core/tools/javaAst.js +191 -0
  98. package/dist/core/tools/javaAst.js.map +1 -1
  99. package/dist/core/tools/recommendProfile.d.ts +3 -0
  100. package/dist/core/tools/recommendProfile.d.ts.map +1 -0
  101. package/dist/core/tools/recommendProfile.js +334 -0
  102. package/dist/core/tools/recommendProfile.js.map +1 -0
  103. package/dist/core/tools/ruleGen.d.ts +3 -0
  104. package/dist/core/tools/ruleGen.d.ts.map +1 -0
  105. package/dist/core/tools/ruleGen.js +1103 -0
  106. package/dist/core/tools/ruleGen.js.map +1 -0
  107. package/dist/core/tools/standards.d.ts.map +1 -1
  108. package/dist/core/tools/standards.js +7 -3
  109. package/dist/core/tools/standards.js.map +1 -1
  110. package/dist/ui/App.d.ts.map +1 -1
  111. package/dist/ui/App.js +86 -35
  112. package/dist/ui/App.js.map +1 -1
  113. package/dist/ui/components/InputBox.d.ts +1 -3
  114. package/dist/ui/components/InputBox.d.ts.map +1 -1
  115. package/dist/ui/components/InputBox.js +146 -5
  116. package/dist/ui/components/InputBox.js.map +1 -1
  117. package/dist/ui/components/MessageList.d.ts +3 -1
  118. package/dist/ui/components/MessageList.d.ts.map +1 -1
  119. package/dist/ui/components/MessageList.js +13 -7
  120. package/dist/ui/components/MessageList.js.map +1 -1
  121. package/dist/ui/components/StatusBar.d.ts +1 -1
  122. package/dist/ui/components/StatusBar.d.ts.map +1 -1
  123. package/dist/ui/components/StatusBar.js +3 -2
  124. package/dist/ui/components/StatusBar.js.map +1 -1
  125. package/dist/ui/components/ToolStatus.d.ts +3 -1
  126. package/dist/ui/components/ToolStatus.d.ts.map +1 -1
  127. package/dist/ui/components/ToolStatus.js +19 -4
  128. package/dist/ui/components/ToolStatus.js.map +1 -1
  129. package/package.json +7 -1
  130. package/demo.gif +0 -0
  131. package/demo.tape +0 -53
  132. package/screenshot.png +0 -0
  133. package/src/cli/banner.ts +0 -38
  134. package/src/cli/headless.ts +0 -63
  135. package/src/cli/index.ts +0 -57
  136. package/src/core/agent.ts +0 -237
  137. package/src/core/commands.ts +0 -118
  138. package/src/core/config.ts +0 -98
  139. package/src/core/conversation.ts +0 -235
  140. package/src/core/llm/ollama.ts +0 -351
  141. package/src/core/mcp/client.ts +0 -143
  142. package/src/core/tools/analyzeAll.ts +0 -494
  143. package/src/core/tools/ast.ts +0 -826
  144. package/src/core/tools/builtIn.ts +0 -221
  145. package/src/core/tools/cache.ts +0 -570
  146. package/src/core/tools/cssAnalysis.ts +0 -324
  147. package/src/core/tools/dependencyAnalysis.ts +0 -363
  148. package/src/core/tools/embeddings.ts +0 -746
  149. package/src/core/tools/frontendAst.ts +0 -802
  150. package/src/core/tools/htmlAnalysis.ts +0 -466
  151. package/src/core/tools/index.ts +0 -160
  152. package/src/core/tools/javaAst.ts +0 -812
  153. package/src/core/tools/memory.ts +0 -655
  154. package/src/core/tools/mybatisAnalysis.ts +0 -322
  155. package/src/core/tools/openapiAnalysis.ts +0 -431
  156. package/src/core/tools/pythonAnalysis.ts +0 -477
  157. package/src/core/tools/sqlAnalysis.ts +0 -298
  158. package/src/core/tools/standards.test.ts +0 -186
  159. package/src/core/tools/standards.ts +0 -889
  160. package/src/core/tools/types.ts +0 -38
  161. package/src/ui/App.tsx +0 -334
  162. package/src/ui/components/InputBox.tsx +0 -37
  163. package/src/ui/components/MessageList.tsx +0 -80
  164. package/src/ui/components/StatusBar.tsx +0 -36
  165. package/src/ui/components/ToolStatus.tsx +0 -38
  166. package/tsconfig.json +0 -21
@@ -1,322 +0,0 @@
1
- import { Tool, ToolResult } from "./types.js";
2
- import * as fs from "fs";
3
- import * as path from "path";
4
-
5
- interface MybatisStatement {
6
- id: string;
7
- type: "select" | "insert" | "update" | "delete" | "sql";
8
- parameterType?: string;
9
- resultType?: string;
10
- resultMap?: string;
11
- sql: string;
12
- line: number;
13
- issues: string[];
14
- dynamicElements: string[];
15
- }
16
-
17
- interface MybatisMapper {
18
- file: string;
19
- namespace: string;
20
- statements: MybatisStatement[];
21
- resultMaps: string[];
22
- sqlFragments: string[];
23
- issues: string[];
24
- }
25
-
26
- interface MybatisAnalysisResult {
27
- file: string;
28
- isMyBatis: boolean;
29
- mapper?: MybatisMapper;
30
- summary: {
31
- statements: number;
32
- withIssues: number;
33
- injectionRisks: number;
34
- dynamicSqlCount: number;
35
- };
36
- }
37
-
38
- // MyBatis XML 파싱 및 분석
39
- function analyzeMyBatisXml(filePath: string): MybatisAnalysisResult {
40
- const content = fs.readFileSync(filePath, "utf-8");
41
- const lines = content.split("\n");
42
-
43
- // MyBatis XML 여부 확인
44
- const isMyBatis =
45
- content.includes("mybatis") ||
46
- content.includes("ibatis") ||
47
- content.includes('PUBLIC "-//mybatis.org') ||
48
- content.includes('PUBLIC "-//ibatis.org') ||
49
- /<mapper\s+namespace=/i.test(content);
50
-
51
- if (!isMyBatis) {
52
- return {
53
- file: filePath,
54
- isMyBatis: false,
55
- summary: { statements: 0, withIssues: 0, injectionRisks: 0, dynamicSqlCount: 0 },
56
- };
57
- }
58
-
59
- const statements: MybatisStatement[] = [];
60
- const resultMaps: string[] = [];
61
- const sqlFragments: string[] = [];
62
- const mapperIssues: string[] = [];
63
-
64
- // namespace 추출
65
- const namespaceMatch = content.match(/<mapper\s+namespace=["']([^"']+)["']/);
66
- const namespace = namespaceMatch ? namespaceMatch[1] : "unknown";
67
-
68
- // resultMap 추출
69
- const resultMapRegex = /<resultMap\s+[^>]*id=["']([^"']+)["'][^>]*>/g;
70
- let match;
71
- while ((match = resultMapRegex.exec(content)) !== null) {
72
- resultMaps.push(match[1]);
73
- }
74
-
75
- // sql fragment 추출
76
- const sqlFragmentRegex = /<sql\s+[^>]*id=["']([^"']+)["'][^>]*>/g;
77
- while ((match = sqlFragmentRegex.exec(content)) !== null) {
78
- sqlFragments.push(match[1]);
79
- }
80
-
81
- // statement 추출 함수
82
- const extractStatements = (type: "select" | "insert" | "update" | "delete") => {
83
- const regex = new RegExp(
84
- `<${type}\\s+([^>]*)>([\\s\\S]*?)</${type}>`,
85
- "gi"
86
- );
87
-
88
- while ((match = regex.exec(content)) !== null) {
89
- const attrs = match[1];
90
- const sqlContent = match[2];
91
-
92
- // 속성 파싱
93
- const idMatch = attrs.match(/id=["']([^"']+)["']/);
94
- const paramMatch = attrs.match(/parameterType=["']([^"']+)["']/);
95
- const resultTypeMatch = attrs.match(/resultType=["']([^"']+)["']/);
96
- const resultMapMatch = attrs.match(/resultMap=["']([^"']+)["']/);
97
-
98
- const id = idMatch ? idMatch[1] : "unknown";
99
- const issues: string[] = [];
100
- const dynamicElements: string[] = [];
101
-
102
- // ${} 사용 검사 (SQL Injection 위험)
103
- const dollarBraceMatches = sqlContent.match(/\$\{[^}]+\}/g) || [];
104
- if (dollarBraceMatches.length > 0) {
105
- issues.push(`SQL Injection 위험: ${dollarBraceMatches.join(", ")} 사용`);
106
- }
107
-
108
- // 동적 SQL 요소 추출
109
- const dynamicTags = ["if", "choose", "when", "otherwise", "where", "set", "foreach", "trim", "bind"];
110
- dynamicTags.forEach((tag) => {
111
- const tagRegex = new RegExp(`<${tag}[\\s>]`, "gi");
112
- const count = (sqlContent.match(tagRegex) || []).length;
113
- if (count > 0) {
114
- dynamicElements.push(`${tag}(${count})`);
115
- }
116
- });
117
-
118
- // SELECT * 검사
119
- if (/SELECT\s+\*\s+FROM/i.test(sqlContent)) {
120
- issues.push("SELECT * 사용");
121
- }
122
-
123
- // WHERE 없는 UPDATE/DELETE
124
- if ((type === "update" || type === "delete") && !/<where>|WHERE/i.test(sqlContent)) {
125
- issues.push("WHERE 절 없음 - 전체 테이블 영향 위험");
126
- }
127
-
128
- // 복잡한 동적 SQL
129
- if (dynamicElements.length >= 5) {
130
- issues.push(`복잡한 동적 SQL (${dynamicElements.length}개 요소)`);
131
- }
132
-
133
- // 중첩 foreach
134
- const foreachCount = (sqlContent.match(/<foreach/gi) || []).length;
135
- if (foreachCount >= 2) {
136
- issues.push(`중첩 foreach ${foreachCount}개 - 성능 검토 필요`);
137
- }
138
-
139
- // LIKE '%${...}%' 패턴
140
- if (/LIKE\s+['"]?%?\$\{/i.test(sqlContent)) {
141
- issues.push("LIKE + ${} 패턴 - SQL Injection 및 인덱스 문제");
142
- }
143
-
144
- // ORDER BY ${} 패턴
145
- if (/ORDER\s+BY\s+\$\{/i.test(sqlContent)) {
146
- issues.push("ORDER BY ${} - SQL Injection 위험");
147
- }
148
-
149
- // 라인 번호 찾기
150
- const statementIndex = content.indexOf(match[0]);
151
- let lineNum = 1;
152
- for (let i = 0; i < statementIndex; i++) {
153
- if (content[i] === "\n") lineNum++;
154
- }
155
-
156
- // SQL 정리
157
- const cleanSql = sqlContent
158
- .replace(/<[^>]+>/g, " ") // XML 태그 제거
159
- .replace(/\s+/g, " ")
160
- .trim();
161
-
162
- statements.push({
163
- id,
164
- type,
165
- parameterType: paramMatch ? paramMatch[1] : undefined,
166
- resultType: resultTypeMatch ? resultTypeMatch[1] : undefined,
167
- resultMap: resultMapMatch ? resultMapMatch[1] : undefined,
168
- sql: cleanSql,
169
- line: lineNum,
170
- issues,
171
- dynamicElements,
172
- });
173
- }
174
- };
175
-
176
- // 각 statement 타입 처리
177
- extractStatements("select");
178
- extractStatements("insert");
179
- extractStatements("update");
180
- extractStatements("delete");
181
-
182
- // mapper 레벨 이슈 검사
183
- if (!namespaceMatch) {
184
- mapperIssues.push("namespace 미정의");
185
- }
186
-
187
- // 미사용 resultMap 검사 (간단한 체크)
188
- resultMaps.forEach((rm) => {
189
- const usageCount = (content.match(new RegExp(`resultMap=["']${rm}["']`, "g")) || []).length;
190
- if (usageCount <= 1) {
191
- // 정의만 있고 사용 없음
192
- mapperIssues.push(`미사용 가능성: resultMap '${rm}'`);
193
- }
194
- });
195
-
196
- // 통계
197
- const injectionRisks = statements.filter((s) =>
198
- s.issues.some((i) => i.includes("Injection"))
199
- ).length;
200
- const dynamicSqlCount = statements.filter((s) => s.dynamicElements.length > 0).length;
201
-
202
- return {
203
- file: filePath,
204
- isMyBatis: true,
205
- mapper: {
206
- file: filePath,
207
- namespace,
208
- statements,
209
- resultMaps,
210
- sqlFragments,
211
- issues: mapperIssues,
212
- },
213
- summary: {
214
- statements: statements.length,
215
- withIssues: statements.filter((s) => s.issues.length > 0).length,
216
- injectionRisks,
217
- dynamicSqlCount,
218
- },
219
- };
220
- }
221
-
222
- // 도구 정의
223
- export const mybatisTools: Tool[] = [
224
- {
225
- name: "mybatis_check",
226
- description:
227
- "MyBatis XML 매퍼 파일을 분석합니다. ${} SQL Injection 위험, 동적 SQL 복잡도, SELECT *, resultMap 사용 등을 검사합니다. DTD/namespace로 MyBatis 파일을 자동 감지합니다.",
228
- parameters: {
229
- type: "object",
230
- properties: {
231
- path: {
232
- type: "string",
233
- description: "분석할 XML 파일 또는 디렉토리 경로",
234
- },
235
- recursive: {
236
- type: "boolean",
237
- description: "디렉토리인 경우 하위 폴더 포함 여부 (기본: true)",
238
- },
239
- },
240
- required: ["path"],
241
- },
242
- handler: async (args: Record<string, unknown>): Promise<ToolResult> => {
243
- const targetPath = args.path as string;
244
- const recursive = args.recursive !== false;
245
-
246
- if (!fs.existsSync(targetPath)) {
247
- return {
248
- success: false,
249
- content: "",
250
- error: `경로를 찾을 수 없습니다: ${targetPath}`,
251
- };
252
- }
253
-
254
- const results: MybatisAnalysisResult[] = [];
255
- const stats = fs.statSync(targetPath);
256
-
257
- if (stats.isFile()) {
258
- if (targetPath.endsWith(".xml")) {
259
- const result = analyzeMyBatisXml(targetPath);
260
- if (result.isMyBatis) {
261
- results.push(result);
262
- }
263
- }
264
- } else if (stats.isDirectory()) {
265
- const walkDir = (dir: string) => {
266
- const files = fs.readdirSync(dir);
267
- for (const file of files) {
268
- const filePath = path.join(dir, file);
269
- const fileStat = fs.statSync(filePath);
270
- if (fileStat.isDirectory() && recursive) {
271
- if (!file.startsWith(".") && file !== "node_modules" && file !== "target" && file !== "build") {
272
- walkDir(filePath);
273
- }
274
- } else if (file.endsWith(".xml")) {
275
- const result = analyzeMyBatisXml(filePath);
276
- if (result.isMyBatis) {
277
- results.push(result);
278
- }
279
- }
280
- }
281
- };
282
- walkDir(targetPath);
283
- }
284
-
285
- // 전체 통계
286
- const totalStatements = results.reduce((sum, r) => sum + r.summary.statements, 0);
287
- const totalWithIssues = results.reduce((sum, r) => sum + r.summary.withIssues, 0);
288
- const totalInjectionRisks = results.reduce((sum, r) => sum + r.summary.injectionRisks, 0);
289
- const totalDynamicSql = results.reduce((sum, r) => sum + r.summary.dynamicSqlCount, 0);
290
-
291
- const output = {
292
- analyzedMappers: results.length,
293
- totalStatements,
294
- statementsWithIssues: totalWithIssues,
295
- injectionRisks: totalInjectionRisks,
296
- dynamicSqlStatements: totalDynamicSql,
297
- mappers: results.map((r) => ({
298
- file: r.file,
299
- namespace: r.mapper?.namespace,
300
- resultMaps: r.mapper?.resultMaps,
301
- sqlFragments: r.mapper?.sqlFragments,
302
- mapperIssues: r.mapper?.issues,
303
- statements: r.mapper?.statements.map((s) => ({
304
- id: s.id,
305
- type: s.type,
306
- line: s.line,
307
- parameterType: s.parameterType,
308
- resultType: s.resultType || s.resultMap,
309
- dynamicElements: s.dynamicElements,
310
- issues: s.issues,
311
- sql: s.sql.length > 150 ? s.sql.substring(0, 150) + "..." : s.sql,
312
- })),
313
- })),
314
- };
315
-
316
- return {
317
- success: true,
318
- content: JSON.stringify(output, null, 2),
319
- };
320
- },
321
- },
322
- ];