frontend-guardian-core 2.9.0 → 3.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.
package/bin/fg-core.js CHANGED
@@ -44,6 +44,11 @@ import {
44
44
  scanWorkspace,
45
45
  formatWorkspaceReport,
46
46
  formatWorkspaceJson,
47
+ AIFixSuggester,
48
+ detectAIConfig,
49
+ compareHistoryReports,
50
+ formatHistoryCompare,
51
+ formatHistoryCompareJson,
47
52
  } from "../dist/index.js";
48
53
  import pc from "picocolors";
49
54
  import { runWatchMode } from "./watch-mode.js";
@@ -76,7 +81,7 @@ const MODULE_RULES = {
76
81
 
77
82
  function showHelp() {
78
83
  console.log(`
79
- Frontend Guardian Core v2.9.0
84
+ Frontend Guardian Core v3.1.0
80
85
 
81
86
  Usage:
82
87
  fg-core <project-dir> [options]
@@ -118,11 +123,14 @@ Options:
118
123
  --history 查看历史扫描记录
119
124
  --history-module <m> 历史记录按模块过滤(配合 --history)
120
125
  --history-limit <n> 历史记录显示条数限制(默认 20)
126
+ --history-compare [c] [p] 对比历史报告:不指定则对比最近两次;指定一个则与该报告对比最近一次;指定两个则对比指定报告
121
127
  --generate-dashboard 生成团队趋势看板 HTML 页面
122
128
  --monorepo 启用 Monorepo 模式:自动检测 workspace 并扫描所有子包
123
129
  --workspace <name> 仅扫描指定 workspace 包(可多次使用,配合 --monorepo)
124
130
  --skip-package <name> 跳过指定 workspace 包(可多次使用,配合 --monorepo)
125
131
  --no-cross-deps 禁用跨包依赖分析(配合 --monorepo)
132
+ --ai-fix 启用 AI 修复建议(需配置 FG_AI_API_KEY 环境变量)
133
+ --ai-model <model> 指定 AI 模型(如 gpt-4o-mini / claude-3-5-sonnet,配合 --ai-fix)
126
134
  --help, -h 显示帮助
127
135
 
128
136
  Examples:
@@ -181,11 +189,15 @@ async function main() {
181
189
  history: false,
182
190
  historyModule: undefined,
183
191
  historyLimit: 20,
192
+ historyCompare: false,
193
+ historyCompareArgs: [],
184
194
  generateDashboard: false,
185
195
  monorepo: false,
186
196
  workspace: [],
187
197
  skipPackage: [],
188
198
  crossDeps: true,
199
+ aiFix: false,
200
+ aiModel: undefined,
189
201
  };
190
202
 
191
203
  for (let i = 0; i < args.length; i++) {
@@ -301,6 +313,13 @@ async function main() {
301
313
  case "--history-limit":
302
314
  options.historyLimit = parseInt(args[++i], 10) || 20;
303
315
  break;
316
+ case "--history-compare":
317
+ options.historyCompare = true;
318
+ // 收集后续非 -- 开头的参数作为对比报告引用
319
+ while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
320
+ options.historyCompareArgs.push(args[++i]);
321
+ }
322
+ break;
304
323
  case "--generate-dashboard":
305
324
  options.generateDashboard = true;
306
325
  break;
@@ -316,6 +335,12 @@ async function main() {
316
335
  case "--no-cross-deps":
317
336
  options.crossDeps = false;
318
337
  break;
338
+ case "--ai-fix":
339
+ options.aiFix = true;
340
+ break;
341
+ case "--ai-model":
342
+ options.aiModel = args[++i];
343
+ break;
319
344
  case "--help":
320
345
  case "-h":
321
346
  showHelp();
@@ -409,6 +434,28 @@ async function main() {
409
434
  process.exit(0);
410
435
  }
411
436
 
437
+ // v3.1.0: 历史报告对比
438
+ if (options.historyCompare) {
439
+ const [currentRef, previousRef] = options.historyCompareArgs;
440
+ const result = compareHistoryReports({
441
+ projectDir: options.projectDir,
442
+ current: currentRef,
443
+ previous: previousRef,
444
+ });
445
+
446
+ if (!result) {
447
+ console.log(pc.yellow("⚠️ 暂无历史报告可供对比。请先运行 --save-report 生成历史数据。"));
448
+ process.exit(1);
449
+ }
450
+
451
+ if (options.json) {
452
+ console.log(JSON.stringify(formatHistoryCompareJson(result), null, 2));
453
+ } else {
454
+ console.log(formatHistoryCompare(result));
455
+ }
456
+ process.exit(0);
457
+ }
458
+
412
459
  // v2.8.0: 生成趋势看板
413
460
  if (options.generateDashboard) {
414
461
  const hr = new HistoryReport(options.projectDir);
@@ -965,6 +1012,45 @@ async function runAllModules(options, cacheInstance) {
965
1012
  }
966
1013
  }
967
1014
 
1015
+ // v3.0.0: AI 修复建议
1016
+ if (options.aiFix) {
1017
+ const aiConfig = detectAIConfig();
1018
+ if (aiConfig) {
1019
+ if (options.aiModel) {
1020
+ aiConfig.model = options.aiModel;
1021
+ }
1022
+ console.log(pc.cyan("🤖 正在生成 AI 修复建议..."));
1023
+ const suggester = new AIFixSuggester(aiConfig);
1024
+ const allIssues = collectAllIssues(allResults, externalResults);
1025
+ // 只给没有自动修复的 issue 生成 AI 建议
1026
+ const issuesWithoutFix = allIssues.filter((i) => !i.fix);
1027
+ if (issuesWithoutFix.length > 0) {
1028
+ const suggestions = await suggester.suggestFixes(issuesWithoutFix.slice(0, 5), options.projectDir);
1029
+ if (suggestions.length > 0) {
1030
+ console.log(pc.cyan(` ✅ 生成 ${suggestions.length} 个 AI 修复建议`));
1031
+ for (const s of suggestions) {
1032
+ const confidenceIcon = s.confidence === "high" ? pc.green("●") : s.confidence === "medium" ? pc.yellow("●") : pc.red("●");
1033
+ console.log(pc.cyan(`\n 📄 ${s.issue.file}:${s.issue.line}`));
1034
+ console.log(pc.yellow(` [${s.issue.ruleId}] ${s.issue.title}`));
1035
+ console.log(pc.gray(` AI 置信度: ${confidenceIcon} ${s.confidence}`));
1036
+ if (s.explanation) {
1037
+ console.log(pc.gray(` 说明: ${s.explanation}`));
1038
+ }
1039
+ console.log(pc.gray(` 模型: ${s.model}`));
1040
+ }
1041
+ } else {
1042
+ console.log(pc.gray(" 未生成 AI 修复建议"));
1043
+ }
1044
+ } else {
1045
+ console.log(pc.gray(" 所有问题都有自动修复,无需 AI 建议"));
1046
+ }
1047
+ console.log("");
1048
+ } else {
1049
+ console.log(pc.yellow(" ⚠️ 未检测到 AI 配置。请设置 FG_AI_API_KEY 或 OPENAI_API_KEY 环境变量。"));
1050
+ console.log("");
1051
+ }
1052
+ }
1053
+
968
1054
  // v2.8.0: 保存完整扫描报告
969
1055
  if (options.saveReport) {
970
1056
  const hr = new HistoryReport(options.projectDir);
@@ -1306,6 +1392,44 @@ async function runSingleModule(options, cacheInstance) {
1306
1392
  }
1307
1393
  }
1308
1394
 
1395
+ // v3.0.0: AI 修复建议
1396
+ if (options.aiFix) {
1397
+ const aiConfig = detectAIConfig();
1398
+ if (aiConfig) {
1399
+ if (options.aiModel) {
1400
+ aiConfig.model = options.aiModel;
1401
+ }
1402
+ console.log(pc.cyan("\n🤖 正在生成 AI 修复建议..."));
1403
+ const suggester = new AIFixSuggester(aiConfig);
1404
+ const allIssues = [...issues.critical, ...issues.warning, ...issues.suggestion];
1405
+ const issuesWithoutFix = allIssues.filter((i) => !i.fix);
1406
+ if (issuesWithoutFix.length > 0) {
1407
+ const suggestions = await suggester.suggestFixes(issuesWithoutFix.slice(0, 5), options.projectDir);
1408
+ if (suggestions.length > 0) {
1409
+ console.log(pc.cyan(` ✅ 生成 ${suggestions.length} 个 AI 修复建议`));
1410
+ for (const s of suggestions) {
1411
+ const confidenceIcon = s.confidence === "high" ? pc.green("●") : s.confidence === "medium" ? pc.yellow("●") : pc.red("●");
1412
+ console.log(pc.cyan(`\n 📄 ${s.issue.file}:${s.issue.line}`));
1413
+ console.log(pc.yellow(` [${s.issue.ruleId}] ${s.issue.title}`));
1414
+ console.log(pc.gray(` AI 置信度: ${confidenceIcon} ${s.confidence}`));
1415
+ if (s.explanation) {
1416
+ console.log(pc.gray(` 说明: ${s.explanation}`));
1417
+ }
1418
+ console.log(pc.gray(` 模型: ${s.model}`));
1419
+ }
1420
+ } else {
1421
+ console.log(pc.gray(" 未生成 AI 修复建议"));
1422
+ }
1423
+ } else {
1424
+ console.log(pc.gray(" 所有问题都有自动修复,无需 AI 建议"));
1425
+ }
1426
+ console.log("");
1427
+ } else {
1428
+ console.log(pc.yellow(" ⚠️ 未检测到 AI 配置。请设置 FG_AI_API_KEY 或 OPENAI_API_KEY 环境变量。"));
1429
+ console.log("");
1430
+ }
1431
+ }
1432
+
1309
1433
  console.log(
1310
1434
  pc.gray(
1311
1435
  `⏱️ 耗时: ${result.duration}ms | 扫描 ${result.filesScanned} 个文件 | ${result.filesWithIssues} 个文件有问题`
package/dist/index.d.ts CHANGED
@@ -23,6 +23,10 @@ export { detectMonorepo, analyzeCrossPackageDeps } from "./utils/monorepo.js";
23
23
  export type { MonorepoInfo, WorkspacePackage, CrossPackageIssue, MonorepoTool } from "./utils/monorepo.js";
24
24
  export { scanWorkspace, formatWorkspaceReport, formatWorkspaceJson } from "./utils/workspace-scanner.js";
25
25
  export type { WorkspaceScanResult, PackageScanResult, WorkspaceSummary, WorkspaceScanOptions } from "./utils/workspace-scanner.js";
26
+ export { AIFixSuggester, detectAIConfig, generateAIFixSuggestions } from "./utils/ai-fix-suggester.js";
27
+ export type { AIConfig, AIProvider, AIFixSuggestion } from "./utils/ai-fix-suggester.js";
28
+ export { compareHistoryReports, formatHistoryCompare, formatHistoryCompareJson } from "./utils/history-compare.js";
29
+ export type { HistoryCompareResult, HistoryCompareOptions, ComparedIssue, IssueStatus, ReportRef } from "./utils/history-compare.js";
26
30
  export { uploadReport, detectUploadConfig } from "./utils/report-uploader.js";
27
31
  export type { UploadConfig, UploadResult } from "./utils/report-uploader.js";
28
32
  export { runFixBot, detectFixBotConfig } from "./utils/fix-bot.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACnE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnE,YAAY,EACR,IAAI,EACJ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,KAAK,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,WAAW,EACX,SAAS,EACT,GAAG,EACH,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,YAAY,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnG,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC7E,YAAY,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAGzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,YAAY,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACzG,YAAY,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGnI,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAC9E,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG7E,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGrE,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC1I,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGvF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACnE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAGzD,OAAO,EACH,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,eAAe,GAClB,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EACH,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,EACd,iBAAiB,GACpB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EACH,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,kBAAkB,GACrB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG3F,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,GACtB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEhF,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -4,8 +4,8 @@
4
4
  * 导出所有公共 API
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.detectPublisherConfig = exports.GitLabMRPublisher = exports.GitHubPRPublisher = exports.isGuardianComment = exports.COMMENT_MARKER = exports.generatePRCommentSummary = exports.generatePRComment = exports.writeJobSummary = exports.isGitHubActions = exports.formatAllAnnotations = exports.formatIssuesAnnotations = exports.formatIssueAnnotation = exports.formatSarif = exports.generateSarif = exports.toBaselineIssue = exports.saveBaseline = exports.loadBaseline = exports.generateBaseline = exports.compareWithBaseline = exports.BaselineManager = exports.detectFixBotConfig = exports.runFixBot = exports.detectUploadConfig = exports.uploadReport = exports.formatWorkspaceJson = exports.formatWorkspaceReport = exports.scanWorkspace = exports.analyzeCrossPackageDeps = exports.detectMonorepo = exports.generateDashboard = exports.HistoryReport = exports.detectCIProvider = exports.generateCIConfig = exports.detectHusky = exports.hasGitHook = exports.uninstallGitHooks = exports.installGitHooks = exports.generateDefaultConfig = exports.initConfig = exports.loadConfig = exports.detectProjectMeta = exports.walkAST = exports.hasImport = exports.getImports = exports.parseAST = exports.createRegistry = exports.RuleRegistry = exports.SmartCache = exports.createEngine = exports.RuleEngine = void 0;
8
- exports.getJSXTagName = exports.getFileExt = exports.svelteRules = exports.platformRules = exports.hooksRules = exports.componentRules = exports.crossFileRules = exports.namingRules = exports.securityRules = exports.a11yRules = exports.performanceRules = exports.i18nRules = exports.runAllExternalTools = exports.stylelintIntegration = exports.typescriptIntegration = exports.eslintIntegration = exports.allExternalTools = exports.autoPublishComment = exports.createPublisher = void 0;
7
+ exports.generatePRComment = exports.writeJobSummary = exports.isGitHubActions = exports.formatAllAnnotations = exports.formatIssuesAnnotations = exports.formatIssueAnnotation = exports.formatSarif = exports.generateSarif = exports.toBaselineIssue = exports.saveBaseline = exports.loadBaseline = exports.generateBaseline = exports.compareWithBaseline = exports.BaselineManager = exports.detectFixBotConfig = exports.runFixBot = exports.detectUploadConfig = exports.uploadReport = exports.formatHistoryCompareJson = exports.formatHistoryCompare = exports.compareHistoryReports = exports.generateAIFixSuggestions = exports.detectAIConfig = exports.AIFixSuggester = exports.formatWorkspaceJson = exports.formatWorkspaceReport = exports.scanWorkspace = exports.analyzeCrossPackageDeps = exports.detectMonorepo = exports.generateDashboard = exports.HistoryReport = exports.detectCIProvider = exports.generateCIConfig = exports.detectHusky = exports.hasGitHook = exports.uninstallGitHooks = exports.installGitHooks = exports.generateDefaultConfig = exports.initConfig = exports.loadConfig = exports.detectProjectMeta = exports.walkAST = exports.hasImport = exports.getImports = exports.parseAST = exports.createRegistry = exports.RuleRegistry = exports.SmartCache = exports.createEngine = exports.RuleEngine = void 0;
8
+ exports.getJSXTagName = exports.getFileExt = exports.svelteRules = exports.platformRules = exports.hooksRules = exports.componentRules = exports.crossFileRules = exports.namingRules = exports.securityRules = exports.a11yRules = exports.performanceRules = exports.i18nRules = exports.runAllExternalTools = exports.stylelintIntegration = exports.typescriptIntegration = exports.eslintIntegration = exports.allExternalTools = exports.autoPublishComment = exports.createPublisher = exports.detectPublisherConfig = exports.GitLabMRPublisher = exports.GitHubPRPublisher = exports.isGuardianComment = exports.COMMENT_MARKER = exports.generatePRCommentSummary = void 0;
9
9
  var rule_engine_js_1 = require("./engine/rule-engine.js");
10
10
  Object.defineProperty(exports, "RuleEngine", { enumerable: true, get: function () { return rule_engine_js_1.RuleEngine; } });
11
11
  Object.defineProperty(exports, "createEngine", { enumerable: true, get: function () { return rule_engine_js_1.createEngine; } });
@@ -47,6 +47,16 @@ var workspace_scanner_js_1 = require("./utils/workspace-scanner.js");
47
47
  Object.defineProperty(exports, "scanWorkspace", { enumerable: true, get: function () { return workspace_scanner_js_1.scanWorkspace; } });
48
48
  Object.defineProperty(exports, "formatWorkspaceReport", { enumerable: true, get: function () { return workspace_scanner_js_1.formatWorkspaceReport; } });
49
49
  Object.defineProperty(exports, "formatWorkspaceJson", { enumerable: true, get: function () { return workspace_scanner_js_1.formatWorkspaceJson; } });
50
+ // v3.0.0: AI 修复建议
51
+ var ai_fix_suggester_js_1 = require("./utils/ai-fix-suggester.js");
52
+ Object.defineProperty(exports, "AIFixSuggester", { enumerable: true, get: function () { return ai_fix_suggester_js_1.AIFixSuggester; } });
53
+ Object.defineProperty(exports, "detectAIConfig", { enumerable: true, get: function () { return ai_fix_suggester_js_1.detectAIConfig; } });
54
+ Object.defineProperty(exports, "generateAIFixSuggestions", { enumerable: true, get: function () { return ai_fix_suggester_js_1.generateAIFixSuggestions; } });
55
+ // v3.1.0: 历史报告对比
56
+ var history_compare_js_1 = require("./utils/history-compare.js");
57
+ Object.defineProperty(exports, "compareHistoryReports", { enumerable: true, get: function () { return history_compare_js_1.compareHistoryReports; } });
58
+ Object.defineProperty(exports, "formatHistoryCompare", { enumerable: true, get: function () { return history_compare_js_1.formatHistoryCompare; } });
59
+ Object.defineProperty(exports, "formatHistoryCompareJson", { enumerable: true, get: function () { return history_compare_js_1.formatHistoryCompareJson; } });
50
60
  // v2.5.0: 报告上传
51
61
  var report_uploader_js_1 = require("./utils/report-uploader.js");
52
62
  Object.defineProperty(exports, "uploadReport", { enumerable: true, get: function () { return report_uploader_js_1.uploadReport; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;AAEH,0DAAmE;AAA1D,4GAAA,UAAU,OAAA;AAAE,8GAAA,YAAY,OAAA;AAEjC,8CAA+C;AAAtC,sGAAA,UAAU,OAAA;AAEnB,mDAAmE;AAA1D,2GAAA,YAAY,OAAA;AAAE,6GAAA,cAAc,OAAA;AAsBrC,uDAAiF;AAAxE,yGAAA,QAAQ,OAAA;AAAE,2GAAA,UAAU,OAAA;AAAE,0GAAA,SAAS,OAAA;AAAE,wGAAA,OAAO,OAAA;AACjD,mEAAgE;AAAvD,wHAAA,iBAAiB,OAAA;AAC1B,6DAAsD;AAA7C,8GAAA,UAAU,OAAA;AACnB,yDAA2E;AAAlE,4GAAA,UAAU,OAAA;AAAE,uHAAA,qBAAqB,OAAA;AAC1C,qDAAmG;AAA1F,+GAAA,eAAe,OAAA;AAAE,iHAAA,iBAAiB,OAAA;AAAE,0GAAA,UAAU,OAAA;AAAE,2GAAA,WAAW,OAAA;AACpE,2DAA6E;AAApE,mHAAA,gBAAgB,OAAA;AAAE,mHAAA,gBAAgB,OAAA;AAE3C,+DAA0D;AAAjD,kHAAA,aAAa,OAAA;AAGtB,eAAe;AACf,qDAAyD;AAAhD,iHAAA,iBAAiB,OAAA;AAG1B,yBAAyB;AACzB,mDAA8E;AAArE,6GAAA,cAAc,OAAA;AAAE,sHAAA,uBAAuB,OAAA;AAEhD,qEAAyG;AAAhG,qHAAA,aAAa,OAAA;AAAE,6HAAA,qBAAqB,OAAA;AAAE,2HAAA,mBAAmB,OAAA;AAGlE,eAAe;AACf,iEAA8E;AAArE,kHAAA,YAAY,OAAA;AAAE,wHAAA,kBAAkB,OAAA;AAGzC,mBAAmB;AACnB,iDAAmE;AAA1D,uGAAA,SAAS,OAAA;AAAE,gHAAA,kBAAkB,OAAA;AAGtC,4BAA4B;AAC5B,mDAA0I;AAAjI,8GAAA,eAAe,OAAA;AAAE,kHAAA,mBAAmB,OAAA;AAAE,+GAAA,gBAAgB,OAAA;AAAE,2GAAA,YAAY,OAAA;AAAE,2GAAA,YAAY,OAAA;AAAE,8GAAA,eAAe,OAAA;AAG5G,0BAA0B;AAC1B,kDAAmE;AAA1D,yGAAA,aAAa,OAAA;AAAE,uGAAA,WAAW,OAAA;AAGnC,0CAA0C;AAC1C,0EAM2C;AALvC,6HAAA,qBAAqB,OAAA;AACrB,+HAAA,uBAAuB,OAAA;AACvB,4HAAA,oBAAoB,OAAA;AACpB,uHAAA,eAAe,OAAA;AACf,uHAAA,eAAe,OAAA;AAGnB,qBAAqB;AACrB,4DAKoC;AAJhC,kHAAA,iBAAiB,OAAA;AACjB,yHAAA,wBAAwB,OAAA;AACxB,+GAAA,cAAc,OAAA;AACd,kHAAA,iBAAiB,OAAA;AAIrB,2DAMiC;AAL7B,oHAAA,iBAAiB,OAAA;AACjB,oHAAA,iBAAiB,OAAA;AACjB,wHAAA,qBAAqB,OAAA;AACrB,kHAAA,eAAe,OAAA;AACf,qHAAA,kBAAkB,OAAA;AAItB,kBAAkB;AAClB,oDAMiC;AAL7B,4GAAA,gBAAgB,OAAA;AAChB,6GAAA,iBAAiB,OAAA;AACjB,iHAAA,qBAAqB,OAAA;AACrB,gHAAA,oBAAoB,OAAA;AACpB,+GAAA,mBAAmB,OAAA;AAIvB,8DAAuD;AAA9C,4GAAA,SAAS,OAAA;AAElB,4EAAqE;AAA5D,0HAAA,gBAAgB,OAAA;AACzB,8DAAuD;AAA9C,4GAAA,SAAS,OAAA;AAClB,sEAA+D;AAAtD,oHAAA,aAAa,OAAA;AACtB,kEAA2D;AAAlD,gHAAA,WAAW,OAAA;AACpB,0EAAkE;AAAzD,uHAAA,cAAc,OAAA;AACvB,wEAAiE;AAAxD,sHAAA,cAAc,OAAA;AACvB,gEAAyD;AAAhD,8GAAA,UAAU,OAAA;AACnB,sEAA+D;AAAtD,oHAAA,aAAa,OAAA;AACtB,kEAA2D;AAAlD,gHAAA,WAAW,OAAA;AACpB,+CAA8D;AAArD,uGAAA,UAAU,OAAA;AAAE,0GAAA,aAAa,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * AI Fix Suggester — LLM 驱动的 Issue 修复建议
3
+ *
4
+ * v3.0.0 功能:
5
+ * 1. 为无自动修复的 Issue 生成 AI 修复建议
6
+ * 2. 为低置信度修复提供替代方案
7
+ * 3. 支持 OpenAI / Claude API
8
+ * 4. 建议缓存避免重复调用
9
+ */
10
+ import type { Issue, Fix, FixConfidence } from "../types.js";
11
+ /** AI 提供商 */
12
+ export type AIProvider = "openai" | "claude" | "auto";
13
+ /** AI 修复建议结果 */
14
+ export interface AIFixSuggestion {
15
+ /** 原始 Issue */
16
+ issue: Issue;
17
+ /** AI 生成的修复 */
18
+ fix: Fix;
19
+ /** AI 修复的置信度 */
20
+ confidence: FixConfidence;
21
+ /** AI 对修复的解释 */
22
+ explanation?: string;
23
+ /** 使用的模型 */
24
+ model?: string;
25
+ }
26
+ /** AI 配置 */
27
+ export interface AIConfig {
28
+ /** 提供商 */
29
+ provider: AIProvider;
30
+ /** API Key */
31
+ apiKey: string;
32
+ /** 模型名称 */
33
+ model: string;
34
+ /** API 基础 URL(可选,用于自定义端点) */
35
+ baseUrl?: string;
36
+ /** 最大 token 数 */
37
+ maxTokens?: number;
38
+ /** 温度 */
39
+ temperature?: number;
40
+ /** 是否启用缓存 */
41
+ cacheEnabled?: boolean;
42
+ /** 缓存目录 */
43
+ cacheDir?: string;
44
+ }
45
+ /** 从环境变量检测 AI 配置 */
46
+ export declare function detectAIConfig(): AIConfig | null;
47
+ /**
48
+ * AI 修复建议器
49
+ */
50
+ export declare class AIFixSuggester {
51
+ private config;
52
+ private cacheDir?;
53
+ constructor(config: AIConfig);
54
+ /**
55
+ * 为单个 Issue 生成 AI 修复建议
56
+ */
57
+ suggestFix(issue: Issue, projectDir: string): Promise<AIFixSuggestion | null>;
58
+ /**
59
+ * 批量生成 AI 修复建议
60
+ */
61
+ suggestFixes(issues: Issue[], projectDir: string): Promise<AIFixSuggestion[]>;
62
+ /** 构建给 LLM 的 prompt */
63
+ private buildPrompt;
64
+ /** 调用 LLM API */
65
+ private callLLM;
66
+ /** 调用 Claude API */
67
+ private callClaude;
68
+ /** 调用 OpenAI API */
69
+ private callOpenAI;
70
+ /** 解析 LLM 响应 */
71
+ private parseResponse;
72
+ /** 读取源代码文件 */
73
+ private readSource;
74
+ /** 生成缓存 key */
75
+ private getCacheKey;
76
+ /** 读取缓存 */
77
+ private readCache;
78
+ /** 写入缓存 */
79
+ private writeCache;
80
+ }
81
+ /**
82
+ * 为 Issue 列表生成 AI 修复建议的便捷函数
83
+ */
84
+ export declare function generateAIFixSuggestions(issues: Issue[], projectDir: string, config?: Partial<AIConfig>): Promise<AIFixSuggestion[]>;
85
+ //# sourceMappingURL=ai-fix-suggester.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-fix-suggester.d.ts","sourceRoot":"","sources":["../../src/utils/ai-fix-suggester.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE5D,aAAa;AACb,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEtD,gBAAgB;AAChB,MAAM,WAAW,eAAe;IAC5B,eAAe;IACf,KAAK,EAAE,KAAK,CAAC;IACb,eAAe;IACf,GAAG,EAAE,GAAG,CAAC;IACT,gBAAgB;IAChB,UAAU,EAAE,aAAa,CAAC;IAC1B,gBAAgB;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,YAAY;AACZ,MAAM,WAAW,QAAQ;IACrB,UAAU;IACV,QAAQ,EAAE,UAAU,CAAC;IACrB,cAAc;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS;IACT,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,oBAAoB;AACpB,wBAAgB,cAAc,IAAI,QAAQ,GAAG,IAAI,CAiChD;AAED;;GAEG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,QAAQ,CAAC,CAAS;gBAEd,MAAM,EAAE,QAAQ;IAO5B;;OAEG;IACG,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAmCnF;;OAEG;IACG,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAanF,uBAAuB;IACvB,OAAO,CAAC,WAAW;IAgCnB,iBAAiB;YACH,OAAO;IAOrB,oBAAoB;YACN,UAAU;IAyBxB,oBAAoB;YACN,UAAU;IAwBxB,gBAAgB;IAChB,OAAO,CAAC,aAAa;IAiCrB,cAAc;IACd,OAAO,CAAC,UAAU;IAqBlB,eAAe;IACf,OAAO,CAAC,WAAW;IAQnB,WAAW;IACX,OAAO,CAAC,SAAS;IAYjB,WAAW;IACX,OAAO,CAAC,UAAU;CAYrB;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAC1C,MAAM,EAAE,KAAK,EAAE,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,GAC3B,OAAO,CAAC,eAAe,EAAE,CAAC,CAa5B"}
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+ /**
3
+ * AI Fix Suggester — LLM 驱动的 Issue 修复建议
4
+ *
5
+ * v3.0.0 功能:
6
+ * 1. 为无自动修复的 Issue 生成 AI 修复建议
7
+ * 2. 为低置信度修复提供替代方案
8
+ * 3. 支持 OpenAI / Claude API
9
+ * 4. 建议缓存避免重复调用
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.AIFixSuggester = void 0;
13
+ exports.detectAIConfig = detectAIConfig;
14
+ exports.generateAIFixSuggestions = generateAIFixSuggestions;
15
+ const node_fs_1 = require("node:fs");
16
+ const node_path_1 = require("node:path");
17
+ const node_crypto_1 = require("node:crypto");
18
+ /** 从环境变量检测 AI 配置 */
19
+ function detectAIConfig() {
20
+ const provider = process.env.FG_AI_PROVIDER || "auto";
21
+ const apiKey = process.env.FG_AI_API_KEY || process.env.OPENAI_API_KEY || process.env.ANTHROPIC_API_KEY || "";
22
+ if (!apiKey) {
23
+ return null;
24
+ }
25
+ // 自动推断提供商
26
+ let detectedProvider = provider;
27
+ if (provider === "auto") {
28
+ if (process.env.ANTHROPIC_API_KEY) {
29
+ detectedProvider = "claude";
30
+ }
31
+ else if (process.env.OPENAI_API_KEY || process.env.FG_AI_API_KEY) {
32
+ detectedProvider = "openai";
33
+ }
34
+ }
35
+ // 默认模型
36
+ const defaultModel = detectedProvider === "claude"
37
+ ? "claude-3-5-sonnet-20241022"
38
+ : "gpt-4o-mini";
39
+ return {
40
+ provider: detectedProvider,
41
+ apiKey,
42
+ model: process.env.FG_AI_MODEL || defaultModel,
43
+ baseUrl: process.env.FG_AI_BASE_URL,
44
+ maxTokens: parseInt(process.env.FG_AI_MAX_TOKENS || "2048", 10),
45
+ temperature: parseFloat(process.env.FG_AI_TEMPERATURE || "0.2"),
46
+ cacheEnabled: process.env.FG_AI_CACHE !== "false",
47
+ cacheDir: process.env.FG_AI_CACHE_DIR,
48
+ };
49
+ }
50
+ /**
51
+ * AI 修复建议器
52
+ */
53
+ class AIFixSuggester {
54
+ config;
55
+ cacheDir;
56
+ constructor(config) {
57
+ this.config = config;
58
+ if (config.cacheEnabled !== false) {
59
+ this.cacheDir = config.cacheDir || (0, node_path_1.join)(process.cwd(), ".frontend-guardian", "ai-cache");
60
+ }
61
+ }
62
+ /**
63
+ * 为单个 Issue 生成 AI 修复建议
64
+ */
65
+ async suggestFix(issue, projectDir) {
66
+ const cacheKey = this.getCacheKey(issue);
67
+ // 尝试从缓存读取
68
+ if (this.cacheDir) {
69
+ const cached = this.readCache(cacheKey);
70
+ if (cached) {
71
+ return { ...cached, issue };
72
+ }
73
+ }
74
+ // 读取源代码
75
+ const source = this.readSource(issue.file, projectDir, issue.line);
76
+ if (!source) {
77
+ return null;
78
+ }
79
+ // 构建 prompt
80
+ const prompt = this.buildPrompt(issue, source);
81
+ try {
82
+ const response = await this.callLLM(prompt);
83
+ const suggestion = this.parseResponse(response, issue);
84
+ if (suggestion && this.cacheDir) {
85
+ this.writeCache(cacheKey, suggestion);
86
+ }
87
+ return suggestion;
88
+ }
89
+ catch (err) {
90
+ // 静默失败,返回 null
91
+ return null;
92
+ }
93
+ }
94
+ /**
95
+ * 批量生成 AI 修复建议
96
+ */
97
+ async suggestFixes(issues, projectDir) {
98
+ const results = [];
99
+ for (const issue of issues) {
100
+ const suggestion = await this.suggestFix(issue, projectDir);
101
+ if (suggestion) {
102
+ results.push(suggestion);
103
+ }
104
+ }
105
+ return results;
106
+ }
107
+ /** 构建给 LLM 的 prompt */
108
+ buildPrompt(issue, source) {
109
+ return `You are an expert frontend code reviewer. Given the following code issue, provide a precise fix.
110
+
111
+ Issue Details:
112
+ - Rule: ${issue.ruleId}
113
+ - Title: ${issue.title}
114
+ - Description: ${issue.description}
115
+ - File: ${issue.file}
116
+ - Line: ${issue.line}, Column: ${issue.column}
117
+ - Severity: ${issue.severity}
118
+
119
+ Source Code (around the issue):
120
+ \`\`\`
121
+ ${source}
122
+ \`\`\`
123
+
124
+ Please provide:
125
+ 1. The fixed code snippet (only the corrected version, no explanations)
126
+ 2. A brief explanation of the fix
127
+ 3. Your confidence in this fix: high / medium / low
128
+
129
+ Format your response as:
130
+ FIX:
131
+ <corrected code snippet>
132
+
133
+ EXPLANATION:
134
+ <brief explanation>
135
+
136
+ CONFIDENCE:
137
+ <high|medium|low>`;
138
+ }
139
+ /** 调用 LLM API */
140
+ async callLLM(prompt) {
141
+ if (this.config.provider === "claude") {
142
+ return this.callClaude(prompt);
143
+ }
144
+ return this.callOpenAI(prompt);
145
+ }
146
+ /** 调用 Claude API */
147
+ async callClaude(prompt) {
148
+ const url = this.config.baseUrl || "https://api.anthropic.com/v1/messages";
149
+ const response = await fetch(url, {
150
+ method: "POST",
151
+ headers: {
152
+ "Content-Type": "application/json",
153
+ "x-api-key": this.config.apiKey,
154
+ "anthropic-version": "2023-06-01",
155
+ },
156
+ body: JSON.stringify({
157
+ model: this.config.model,
158
+ max_tokens: this.config.maxTokens || 2048,
159
+ temperature: this.config.temperature || 0.2,
160
+ messages: [{ role: "user", content: prompt }],
161
+ }),
162
+ });
163
+ if (!response.ok) {
164
+ throw new Error(`Claude API error: ${response.status} ${response.statusText}`);
165
+ }
166
+ const data = await response.json();
167
+ return data.content[0]?.text || "";
168
+ }
169
+ /** 调用 OpenAI API */
170
+ async callOpenAI(prompt) {
171
+ const url = this.config.baseUrl || "https://api.openai.com/v1/chat/completions";
172
+ const response = await fetch(url, {
173
+ method: "POST",
174
+ headers: {
175
+ "Content-Type": "application/json",
176
+ Authorization: `Bearer ${this.config.apiKey}`,
177
+ },
178
+ body: JSON.stringify({
179
+ model: this.config.model,
180
+ max_tokens: this.config.maxTokens || 2048,
181
+ temperature: this.config.temperature || 0.2,
182
+ messages: [{ role: "user", content: prompt }],
183
+ }),
184
+ });
185
+ if (!response.ok) {
186
+ throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);
187
+ }
188
+ const data = await response.json();
189
+ return data.choices[0]?.message?.content || "";
190
+ }
191
+ /** 解析 LLM 响应 */
192
+ parseResponse(response, issue) {
193
+ const fixMatch = response.match(/FIX:\s*\n?([\s\S]*?)(?=\n?EXPLANATION:|\n?CONFIDENCE:|$)/);
194
+ const explanationMatch = response.match(/EXPLANATION:\s*\n?([\s\S]*?)(?=\n?CONFIDENCE:|$)/);
195
+ const confidenceMatch = response.match(/CONFIDENCE:\s*(high|medium|low)/i);
196
+ if (!fixMatch) {
197
+ return null;
198
+ }
199
+ const fixedCode = fixMatch[1].trim();
200
+ const explanation = explanationMatch ? explanationMatch[1].trim() : undefined;
201
+ const confidenceStr = confidenceMatch ? confidenceMatch[1].toLowerCase() : "medium";
202
+ const confidence = ["high", "medium", "low"].includes(confidenceStr) ? confidenceStr : "medium";
203
+ // 构建 Fix 对象
204
+ // 简单实现:替换整行代码
205
+ const fix = {
206
+ text: fixedCode,
207
+ start: { line: issue.line, column: issue.column },
208
+ end: { line: issue.endLine || issue.line, column: issue.endColumn || issue.column + 1 },
209
+ confidence,
210
+ description: explanation,
211
+ };
212
+ return {
213
+ issue,
214
+ fix,
215
+ confidence,
216
+ explanation,
217
+ model: this.config.model,
218
+ };
219
+ }
220
+ /** 读取源代码文件 */
221
+ readSource(filePath, projectDir, issueLine) {
222
+ const fullPath = (0, node_path_1.resolve)(projectDir, filePath);
223
+ if (!(0, node_fs_1.existsSync)(fullPath)) {
224
+ return null;
225
+ }
226
+ try {
227
+ const content = (0, node_fs_1.readFileSync)(fullPath, "utf-8");
228
+ const lines = content.split("\n");
229
+ // 提取 issue 周围的代码(前后 5 行)
230
+ const startLine = Math.max(0, issueLine - 6);
231
+ const endLine = Math.min(lines.length, issueLine + 5);
232
+ const contextLines = lines.slice(startLine, endLine);
233
+ // 添加行号
234
+ return contextLines.map((line, idx) => `${startLine + idx + 1}: ${line}`).join("\n");
235
+ }
236
+ catch {
237
+ return null;
238
+ }
239
+ }
240
+ /** 生成缓存 key */
241
+ getCacheKey(issue) {
242
+ const hash = (0, node_crypto_1.createHash)("sha256")
243
+ .update(`${issue.file}|${issue.ruleId}|${issue.line}|${issue.column}|${issue.title}`)
244
+ .digest("hex")
245
+ .slice(0, 16);
246
+ return hash;
247
+ }
248
+ /** 读取缓存 */
249
+ readCache(key) {
250
+ if (!this.cacheDir)
251
+ return null;
252
+ try {
253
+ const cachePath = (0, node_path_1.join)(this.cacheDir, `${key}.json`);
254
+ if (!(0, node_fs_1.existsSync)(cachePath))
255
+ return null;
256
+ const raw = (0, node_fs_1.readFileSync)(cachePath, "utf-8");
257
+ return JSON.parse(raw);
258
+ }
259
+ catch {
260
+ return null;
261
+ }
262
+ }
263
+ /** 写入缓存 */
264
+ writeCache(key, suggestion) {
265
+ if (!this.cacheDir)
266
+ return;
267
+ try {
268
+ if (!(0, node_fs_1.existsSync)(this.cacheDir)) {
269
+ (0, node_fs_1.mkdirSync)(this.cacheDir, { recursive: true });
270
+ }
271
+ const cachePath = (0, node_path_1.join)(this.cacheDir, `${key}.json`);
272
+ (0, node_fs_1.writeFileSync)(cachePath, JSON.stringify(suggestion, null, 2), "utf-8");
273
+ }
274
+ catch {
275
+ // 忽略缓存写入失败
276
+ }
277
+ }
278
+ }
279
+ exports.AIFixSuggester = AIFixSuggester;
280
+ /**
281
+ * 为 Issue 列表生成 AI 修复建议的便捷函数
282
+ */
283
+ async function generateAIFixSuggestions(issues, projectDir, config) {
284
+ const detected = detectAIConfig();
285
+ if (!detected) {
286
+ return [];
287
+ }
288
+ const mergedConfig = {
289
+ ...detected,
290
+ ...config,
291
+ };
292
+ const suggester = new AIFixSuggester(mergedConfig);
293
+ return suggester.suggestFixes(issues, projectDir);
294
+ }
295
+ //# sourceMappingURL=ai-fix-suggester.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-fix-suggester.js","sourceRoot":"","sources":["../../src/utils/ai-fix-suggester.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * History Report Compare — 历史报告对比
3
+ *
4
+ * 功能:
5
+ * 1. 对比两次扫描报告,输出新增/已修复/持续存在的问题明细
6
+ * 2. 支持按文件+规则+行号精确匹配 issue
7
+ * 3. 检测 severity 变化的问题
8
+ * 4. 终端友好输出 + JSON 结构化输出
9
+ */
10
+ import type { Issue, Severity } from "../types.js";
11
+ export type IssueStatus = "new" | "fixed" | "persistent" | "changed";
12
+ export interface ComparedIssue {
13
+ issue: Issue;
14
+ status: IssueStatus;
15
+ previousSeverity?: Severity;
16
+ previousIssue?: Issue;
17
+ }
18
+ export interface ReportRef {
19
+ filename: string;
20
+ timestamp: number;
21
+ module: string;
22
+ git?: {
23
+ commit?: string;
24
+ branch?: string;
25
+ };
26
+ }
27
+ export interface HistoryCompareResult {
28
+ currentReport: ReportRef;
29
+ previousReport: ReportRef;
30
+ summary: {
31
+ new: number;
32
+ fixed: number;
33
+ persistent: number;
34
+ changed: number;
35
+ totalCurrent: number;
36
+ totalPrevious: number;
37
+ };
38
+ newIssues: ComparedIssue[];
39
+ fixedIssues: ComparedIssue[];
40
+ persistentIssues: ComparedIssue[];
41
+ changedIssues: ComparedIssue[];
42
+ }
43
+ export interface HistoryCompareOptions {
44
+ projectDir: string;
45
+ current?: string;
46
+ previous?: string;
47
+ }
48
+ /**
49
+ * 对比两次历史报告
50
+ */
51
+ export declare function compareHistoryReports(options: HistoryCompareOptions): HistoryCompareResult | null;
52
+ /**
53
+ * 终端友好的对比报告输出
54
+ */
55
+ export declare function formatHistoryCompare(result: HistoryCompareResult): string;
56
+ /**
57
+ * JSON 格式的对比结果
58
+ */
59
+ export declare function formatHistoryCompareJson(result: HistoryCompareResult): object;
60
+ //# sourceMappingURL=history-compare.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-compare.d.ts","sourceRoot":"","sources":["../../src/utils/history-compare.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,OAAO,GAAG,YAAY,GAAG,SAAS,CAAC;AAErE,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,gBAAgB,CAAC,EAAE,QAAQ,CAAC;IAC5B,aAAa,CAAC,EAAE,KAAK,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,MAAM,WAAW,oBAAoB;IACjC,aAAa,EAAE,SAAS,CAAC;IACzB,cAAc,EAAE,SAAS,CAAC;IAC1B,OAAO,EAAE;QACL,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;KACzB,CAAC;IACF,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,WAAW,EAAE,aAAa,EAAE,CAAC;IAC7B,gBAAgB,EAAE,aAAa,EAAE,CAAC;IAClC,aAAa,EAAE,aAAa,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAuDD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,GAAG,IAAI,CA+FjG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAgEzE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAuB7E"}
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ /**
3
+ * History Report Compare — 历史报告对比
4
+ *
5
+ * 功能:
6
+ * 1. 对比两次扫描报告,输出新增/已修复/持续存在的问题明细
7
+ * 2. 支持按文件+规则+行号精确匹配 issue
8
+ * 3. 检测 severity 变化的问题
9
+ * 4. 终端友好输出 + JSON 结构化输出
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.compareHistoryReports = compareHistoryReports;
13
+ exports.formatHistoryCompare = formatHistoryCompare;
14
+ exports.formatHistoryCompareJson = formatHistoryCompareJson;
15
+ const node_fs_1 = require("node:fs");
16
+ const node_path_1 = require("node:path");
17
+ /** Issue 签名:用于跨报告精确匹配 */
18
+ function issueSignature(issue) {
19
+ return `${issue.file}|${issue.ruleId}|${issue.line}`;
20
+ }
21
+ /** 从 history 目录加载报告 */
22
+ function loadReport(projectDir, filename) {
23
+ const reportsDir = (0, node_path_1.resolve)(projectDir, ".frontend-guardian", "history");
24
+ try {
25
+ const raw = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(reportsDir, filename), "utf-8");
26
+ return JSON.parse(raw);
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ /** 列出所有报告文件(按时间倒序) */
33
+ function listReportFiles(projectDir) {
34
+ const reportsDir = (0, node_path_1.resolve)(projectDir, ".frontend-guardian", "history");
35
+ try {
36
+ if (!(0, node_fs_1.existsSync)(reportsDir))
37
+ return [];
38
+ return (0, node_fs_1.readdirSync)(reportsDir)
39
+ .filter((f) => f.endsWith(".json"))
40
+ .sort()
41
+ .reverse();
42
+ }
43
+ catch {
44
+ return [];
45
+ }
46
+ }
47
+ /** 查找报告文件(支持 "latest" 和模糊匹配) */
48
+ function resolveReportFile(projectDir, ref, exclude) {
49
+ const files = listReportFiles(projectDir);
50
+ if (files.length === 0)
51
+ return null;
52
+ if (!ref || ref === "latest") {
53
+ if (exclude) {
54
+ return files.find((f) => f !== exclude) ?? null;
55
+ }
56
+ return files[0];
57
+ }
58
+ // 精确匹配
59
+ if (files.includes(ref))
60
+ return ref;
61
+ // 前缀匹配(如 "20250601" 匹配 "20250601-120000.json")
62
+ const matches = files.filter((f) => f.startsWith(ref));
63
+ if (matches.length === 1)
64
+ return matches[0];
65
+ if (matches.length > 1)
66
+ return matches[0]; // 取最新的
67
+ return null;
68
+ }
69
+ /**
70
+ * 对比两次历史报告
71
+ */
72
+ function compareHistoryReports(options) {
73
+ const files = listReportFiles(options.projectDir);
74
+ if (files.length === 0)
75
+ return null;
76
+ const currentFile = resolveReportFile(options.projectDir, options.current);
77
+ if (!currentFile)
78
+ return null;
79
+ const previousFile = resolveReportFile(options.projectDir, options.previous, currentFile);
80
+ if (!previousFile)
81
+ return null;
82
+ const current = loadReport(options.projectDir, currentFile);
83
+ const previous = loadReport(options.projectDir, previousFile);
84
+ if (!current || !previous)
85
+ return null;
86
+ const currentIssues = current.issues;
87
+ const previousIssues = previous.issues;
88
+ const currMap = new Map();
89
+ const prevMap = new Map();
90
+ for (const issue of currentIssues) {
91
+ currMap.set(issueSignature(issue), issue);
92
+ }
93
+ for (const issue of previousIssues) {
94
+ prevMap.set(issueSignature(issue), issue);
95
+ }
96
+ const newIssues = [];
97
+ const fixedIssues = [];
98
+ const persistentIssues = [];
99
+ const changedIssues = [];
100
+ // 当前报告中存在、previous 中不存在 → 新增
101
+ for (const [sig, issue] of currMap) {
102
+ if (!prevMap.has(sig)) {
103
+ newIssues.push({ issue, status: "new" });
104
+ }
105
+ else {
106
+ const prevIssue = prevMap.get(sig);
107
+ if (prevIssue.severity !== issue.severity) {
108
+ changedIssues.push({
109
+ issue,
110
+ status: "changed",
111
+ previousSeverity: prevIssue.severity,
112
+ previousIssue: prevIssue,
113
+ });
114
+ }
115
+ else {
116
+ persistentIssues.push({ issue, status: "persistent" });
117
+ }
118
+ }
119
+ }
120
+ // previous 中存在、当前不存在 → 已修复
121
+ for (const [sig, issue] of prevMap) {
122
+ if (!currMap.has(sig)) {
123
+ fixedIssues.push({ issue, status: "fixed" });
124
+ }
125
+ }
126
+ // 按 severity 排序
127
+ const severityOrder = { critical: 0, warning: 1, suggestion: 2 };
128
+ const sortBySeverity = (a, b) => severityOrder[a.issue.severity] - severityOrder[b.issue.severity];
129
+ newIssues.sort(sortBySeverity);
130
+ fixedIssues.sort(sortBySeverity);
131
+ persistentIssues.sort(sortBySeverity);
132
+ changedIssues.sort(sortBySeverity);
133
+ return {
134
+ currentReport: {
135
+ filename: currentFile,
136
+ timestamp: current.timestamp,
137
+ module: current.module,
138
+ git: current.git,
139
+ },
140
+ previousReport: {
141
+ filename: previousFile,
142
+ timestamp: previous.timestamp,
143
+ module: previous.module,
144
+ git: previous.git,
145
+ },
146
+ summary: {
147
+ new: newIssues.length,
148
+ fixed: fixedIssues.length,
149
+ persistent: persistentIssues.length,
150
+ changed: changedIssues.length,
151
+ totalCurrent: currentIssues.length,
152
+ totalPrevious: previousIssues.length,
153
+ },
154
+ newIssues,
155
+ fixedIssues,
156
+ persistentIssues,
157
+ changedIssues,
158
+ };
159
+ }
160
+ /**
161
+ * 终端友好的对比报告输出
162
+ */
163
+ function formatHistoryCompare(result) {
164
+ const lines = [];
165
+ const formatDate = (ts) => new Date(ts).toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
166
+ lines.push(`📊 历史报告对比`);
167
+ lines.push(` 当前: ${result.currentReport.filename} (${formatDate(result.currentReport.timestamp)}) [${result.currentReport.module}]`);
168
+ lines.push(` 对比: ${result.previousReport.filename} (${formatDate(result.previousReport.timestamp)}) [${result.previousReport.module}]`);
169
+ lines.push("");
170
+ // 摘要
171
+ const { summary } = result;
172
+ lines.push(`📈 变化摘要`);
173
+ lines.push(` 当前报告: ${summary.totalCurrent} 个问题`);
174
+ lines.push(` 对比报告: ${summary.totalPrevious} 个问题`);
175
+ lines.push(` 新增: ${summary.new} | 已修复: ${summary.fixed} | 持续存在: ${summary.persistent} | 级别变化: ${summary.changed}`);
176
+ lines.push("");
177
+ // 新增问题
178
+ if (result.newIssues.length > 0) {
179
+ lines.push(`🆕 新增问题 (${result.newIssues.length})`);
180
+ for (const ci of result.newIssues) {
181
+ const sev = ci.issue.severity === "critical" ? "🔴" : ci.issue.severity === "warning" ? "🟡" : "💡";
182
+ lines.push(` ${sev} [${ci.issue.ruleId}] ${ci.issue.title}`);
183
+ lines.push(` 📄 ${ci.issue.file}:${ci.issue.line}`);
184
+ }
185
+ lines.push("");
186
+ }
187
+ // 已修复问题
188
+ if (result.fixedIssues.length > 0) {
189
+ lines.push(`✅ 已修复问题 (${result.fixedIssues.length})`);
190
+ for (const ci of result.fixedIssues) {
191
+ const sev = ci.issue.severity === "critical" ? "🔴" : ci.issue.severity === "warning" ? "🟡" : "💡";
192
+ lines.push(` ${sev} [${ci.issue.ruleId}] ${ci.issue.title}`);
193
+ lines.push(` 📄 ${ci.issue.file}:${ci.issue.line}`);
194
+ }
195
+ lines.push("");
196
+ }
197
+ // 级别变化
198
+ if (result.changedIssues.length > 0) {
199
+ lines.push(`🔄 严重级别变化 (${result.changedIssues.length})`);
200
+ for (const ci of result.changedIssues) {
201
+ lines.push(` [${ci.issue.ruleId}] ${ci.issue.title}`);
202
+ lines.push(` 📄 ${ci.issue.file}:${ci.issue.line}`);
203
+ lines.push(` ${ci.previousSeverity} → ${ci.issue.severity}`);
204
+ }
205
+ lines.push("");
206
+ }
207
+ // 持续存在
208
+ if (result.persistentIssues.length > 0) {
209
+ lines.push(`⏳ 持续存在的问题 (${result.persistentIssues.length})`);
210
+ const bySeverity = { critical: 0, warning: 0, suggestion: 0 };
211
+ for (const ci of result.persistentIssues) {
212
+ bySeverity[ci.issue.severity]++;
213
+ }
214
+ lines.push(` 🔴 Critical: ${bySeverity.critical} | 🟡 Warning: ${bySeverity.warning} | 💡 Suggestion: ${bySeverity.suggestion}`);
215
+ lines.push("");
216
+ }
217
+ return lines.join("\n");
218
+ }
219
+ /**
220
+ * JSON 格式的对比结果
221
+ */
222
+ function formatHistoryCompareJson(result) {
223
+ return {
224
+ currentReport: result.currentReport,
225
+ previousReport: result.previousReport,
226
+ summary: result.summary,
227
+ newIssues: result.newIssues.map((ci) => ({
228
+ ...ci.issue,
229
+ status: ci.status,
230
+ })),
231
+ fixedIssues: result.fixedIssues.map((ci) => ({
232
+ ...ci.issue,
233
+ status: ci.status,
234
+ })),
235
+ changedIssues: result.changedIssues.map((ci) => ({
236
+ ...ci.issue,
237
+ status: ci.status,
238
+ previousSeverity: ci.previousSeverity,
239
+ })),
240
+ persistentIssues: result.persistentIssues.map((ci) => ({
241
+ ...ci.issue,
242
+ status: ci.status,
243
+ })),
244
+ };
245
+ }
246
+ //# sourceMappingURL=history-compare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-compare.js","sourceRoot":"","sources":["../../src/utils/history-compare.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontend-guardian-core",
3
- "version": "2.9.0",
3
+ "version": "3.1.0",
4
4
  "description": "Core analysis engine for frontend-guardian — AST-based scanning and auto-fixing",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",