@wuyanbin/ai-code-review-cli-remote 1.0.2 → 1.0.4

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 (48) hide show
  1. package/dist/client.d.ts +1 -0
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +11 -3
  4. package/dist/client.js.map +1 -1
  5. package/dist/config.d.ts +11 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +147 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/constants.d.ts +3 -3
  10. package/dist/constants.d.ts.map +1 -1
  11. package/dist/constants.js +4 -4
  12. package/dist/constants.js.map +1 -1
  13. package/dist/diff.d.ts +6 -0
  14. package/dist/diff.d.ts.map +1 -0
  15. package/dist/diff.js +127 -0
  16. package/dist/diff.js.map +1 -0
  17. package/dist/formatters.d.ts +4 -0
  18. package/dist/formatters.d.ts.map +1 -0
  19. package/dist/formatters.js +30 -0
  20. package/dist/formatters.js.map +1 -0
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +16 -75
  24. package/dist/index.js.map +1 -1
  25. package/dist/model.d.ts +5 -0
  26. package/dist/model.d.ts.map +1 -0
  27. package/dist/model.js +80 -0
  28. package/dist/model.js.map +1 -0
  29. package/dist/report.d.ts +9 -0
  30. package/dist/report.d.ts.map +1 -0
  31. package/dist/report.js +30 -0
  32. package/dist/report.js.map +1 -0
  33. package/dist/reviewer.d.ts +3 -0
  34. package/dist/reviewer.d.ts.map +1 -0
  35. package/dist/reviewer.js +77 -0
  36. package/dist/reviewer.js.map +1 -0
  37. package/dist/runner.d.ts +5 -0
  38. package/dist/runner.d.ts.map +1 -0
  39. package/dist/runner.js +97 -0
  40. package/dist/runner.js.map +1 -0
  41. package/dist/summarizer.d.ts +3 -0
  42. package/dist/summarizer.d.ts.map +1 -0
  43. package/dist/summarizer.js +75 -0
  44. package/dist/summarizer.js.map +1 -0
  45. package/dist/types.d.ts +48 -12
  46. package/dist/types.d.ts.map +1 -1
  47. package/package.json +3 -3
  48. package/bin/ai-code-review-remote.js +0 -11
package/dist/client.d.ts CHANGED
@@ -14,4 +14,5 @@ export interface AnalyzeResult {
14
14
  error?: string;
15
15
  }
16
16
  export declare function analyzeWithCi(diff: string, ci: CiContext): Promise<AnalyzeResult>;
17
+ export declare function resolvePlatformUrlForTest(env?: NodeJS.ProcessEnv): string;
17
18
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAkBD,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,SAAS,GACZ,OAAO,CAAC,aAAa,CAAC,CA0CxB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAsBD,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,SAAS,GACZ,OAAO,CAAC,aAAa,CAAC,CA0CxB;AAED,wBAAgB,yBAAyB,CACvC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAER"}
package/dist/client.js CHANGED
@@ -1,9 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.analyzeWithCi = analyzeWithCi;
4
+ exports.resolvePlatformUrlForTest = resolvePlatformUrlForTest;
4
5
  const constants_1 = require("./constants");
5
- function getPlatformUrl() {
6
- return (process.env[constants_1.ENV_PLATFORM_URL]?.replace(/\/+$/, "") || constants_1.DEFAULT_PLATFORM_URL);
6
+ function getPlatformUrlFromEnv(env = process.env) {
7
+ const platformUrl = env[constants_1.ENV_PLATFORM_URL]?.replace(/\/+$/, "");
8
+ if (!platformUrl) {
9
+ throw new Error(`${constants_1.ENV_PLATFORM_URL} 未设置。请在 GitLab CI 变量中配置平台地址。`);
10
+ }
11
+ return platformUrl;
7
12
  }
8
13
  function getProjectToken() {
9
14
  const token = process.env[constants_1.ENV_PROJECT_TOKEN];
@@ -14,7 +19,7 @@ function getProjectToken() {
14
19
  }
15
20
  async function analyzeWithCi(diff, ci) {
16
21
  const token = getProjectToken();
17
- const url = `${getPlatformUrl()}${constants_1.API_REVIEW_PATH}`;
22
+ const url = `${getPlatformUrlFromEnv()}${constants_1.API_REVIEW_PATH}`;
18
23
  console.error(`[remote] POST ${url} (mrIid=${ci.mrIid})`);
19
24
  const controller = new AbortController();
20
25
  const timeout = setTimeout(() => controller.abort(), constants_1.REQUEST_TIMEOUT_MS);
@@ -51,4 +56,7 @@ async function analyzeWithCi(diff, ci) {
51
56
  clearTimeout(timeout);
52
57
  }
53
58
  }
59
+ function resolvePlatformUrlForTest(env = process.env) {
60
+ return getPlatformUrlFromEnv(env);
61
+ }
54
62
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;AAyCA,sCA6CC;AAtFD,2CAMqB;AAmBrB,SAAS,cAAc;IACrB,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,4BAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,gCAAoB,CAC3E,CAAC;AACJ,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,6BAAiB,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,GAAG,6BAAiB,oCAAoC,CACzD,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAEM,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,EAAa;IAEb,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,GAAG,cAAc,EAAE,GAAG,2BAAe,EAAE,CAAC;IACpD,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,WAAW,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,8BAAkB,CAAC,CAAC;IAEzE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,EAAE;aACjC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YAClC,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,IAAmB,CAAC;QACxB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CACb,UAAU,8BAAkB,GAAG,IAAI,UAAU,4BAAgB,cAAc,CAC5E,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;AA4CA,sCA6CC;AAED,8DAIC;AA/FD,2CAKqB;AAmBrB,SAAS,qBAAqB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACjE,MAAM,WAAW,GAAG,GAAG,CAAC,4BAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/D,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,GAAG,4BAAgB,8BAA8B,CAClD,CAAC;IACJ,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,eAAe;IACtB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,6BAAiB,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,GAAG,6BAAiB,oCAAoC,CACzD,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAEM,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,EAAa;IAEb,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,GAAG,qBAAqB,EAAE,GAAG,2BAAe,EAAE,CAAC;IAC3D,OAAO,CAAC,KAAK,CAAC,iBAAiB,GAAG,WAAW,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,8BAAkB,CAAC,CAAC;IAEzE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC5B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,EAAE;aACjC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;YAClC,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,IAAI,IAAmB,CAAC;QACxB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAmB,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CACb,UAAU,8BAAkB,GAAG,IAAI,UAAU,4BAAgB,cAAc,CAC5E,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,OAAO,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,SAAgB,yBAAyB,CACvC,MAAyB,OAAO,CAAC,GAAG;IAEpC,OAAO,qBAAqB,CAAC,GAAG,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { CodeReviewConfig } from "./types";
2
+ type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
3
+ export interface LoadReviewConfigOptions {
4
+ cwd?: string;
5
+ env?: NodeJS.ProcessEnv;
6
+ fetchImpl?: FetchLike;
7
+ }
8
+ export declare function loadReviewConfig(options?: LoadReviewConfigOptions): Promise<CodeReviewConfig>;
9
+ export declare function sanitizeConfigForLog(config: CodeReviewConfig): CodeReviewConfig;
10
+ export {};
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,SAAS,CAAC;AAE1D,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE1E,MAAM,WAAW,uBAAuB;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAoJD,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CAY3B;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAM/E"}
package/dist/config.js ADDED
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadReviewConfig = loadReviewConfig;
4
+ exports.sanitizeConfigForLog = sanitizeConfigForLog;
5
+ const node_fs_1 = require("node:fs");
6
+ const promises_1 = require("node:fs/promises");
7
+ const node_path_1 = require("node:path");
8
+ const node_module_1 = require("node:module");
9
+ const constants_1 = require("./constants");
10
+ const LOCAL_CONFIG_FILES = [
11
+ ".aicr.config.js",
12
+ "aicr.config.js",
13
+ ".aicr.config.cjs",
14
+ "aicr.config.cjs",
15
+ ];
16
+ const requireConfig = (0, node_module_1.createRequire)(__filename);
17
+ function normalizePlatformUrl(env) {
18
+ const raw = env[constants_1.ENV_PLATFORM_URL]?.replace(/\/+$/, "");
19
+ return raw || null;
20
+ }
21
+ function asStringArray(value) {
22
+ return Array.isArray(value)
23
+ ? value.filter((item) => typeof item === "string")
24
+ : [];
25
+ }
26
+ function normalizeSeverity(value) {
27
+ return value === "info" || value === "warning" || value === "error"
28
+ ? value
29
+ : "warning";
30
+ }
31
+ function normalizeMaxComments(value) {
32
+ return typeof value === "number" && Number.isFinite(value) && value > 0
33
+ ? Math.floor(value)
34
+ : 100;
35
+ }
36
+ function normalizeConfig(raw, source, env) {
37
+ return {
38
+ source,
39
+ ai: {
40
+ name: raw.ai?.name,
41
+ provider: raw.ai?.provider,
42
+ model: raw.ai?.model || "deepseek-chat",
43
+ endpoint: raw.ai?.endpoint || "https://api.deepseek.com/chat/completions",
44
+ apiKey: env.MODEL_API_KEY || raw.ai?.apiKey || "",
45
+ },
46
+ rules: {
47
+ custom: asStringArray(raw.rules?.custom),
48
+ },
49
+ review: {
50
+ severity: normalizeSeverity(raw.review?.severity),
51
+ ignore: asStringArray(raw.review?.ignore),
52
+ maxComments: normalizeMaxComments(raw.review?.maxComments),
53
+ },
54
+ summary: {
55
+ enabled: raw.summary?.enabled ?? true,
56
+ },
57
+ gitlab: raw.gitlab?.token ? { token: raw.gitlab.token } : undefined,
58
+ };
59
+ }
60
+ async function loadDevhubConfig(env, fetchImpl) {
61
+ const platformUrl = normalizePlatformUrl(env);
62
+ const token = env[constants_1.ENV_PROJECT_TOKEN];
63
+ if (!platformUrl || !token)
64
+ return null;
65
+ const url = `${platformUrl}${constants_1.API_CONFIG_PATH}`;
66
+ try {
67
+ console.error("[config] fetching Devhub config");
68
+ const resp = await fetchImpl(url, {
69
+ method: "GET",
70
+ headers: { Authorization: `Bearer ${token}` },
71
+ });
72
+ if (!resp.ok) {
73
+ console.error(`[config] Devhub 配置获取失败 status=${resp.status}`);
74
+ return null;
75
+ }
76
+ const raw = (await resp.json());
77
+ const config = normalizeConfig(raw, "devhub", {});
78
+ if (!config.ai.apiKey || !config.ai.endpoint) {
79
+ console.error("[config] Devhub 配置缺少模型密钥或 endpoint,回退本地配置");
80
+ return null;
81
+ }
82
+ return config;
83
+ }
84
+ catch (error) {
85
+ console.error("[config] Devhub 配置获取异常,回退本地配置:", error instanceof Error ? error.message : String(error));
86
+ return null;
87
+ }
88
+ }
89
+ async function loadCachedConfig(env) {
90
+ const cachePath = env.AICR_CONFIG_CACHE;
91
+ if (!cachePath || !(0, node_fs_1.existsSync)(cachePath))
92
+ return null;
93
+ try {
94
+ const raw = JSON.parse(await (0, promises_1.readFile)(cachePath, "utf8"));
95
+ if (raw.source === "devhub" && raw.ai?.apiKey && raw.ai?.endpoint) {
96
+ console.error("[config] Loaded config from Devhub cache");
97
+ return raw;
98
+ }
99
+ }
100
+ catch (error) {
101
+ console.error("[config] Devhub 配置缓存读取失败:", error instanceof Error ? error.message : String(error));
102
+ }
103
+ return null;
104
+ }
105
+ async function writeCachedConfig(env, config) {
106
+ const cachePath = env.AICR_CONFIG_CACHE;
107
+ if (!cachePath || config.source !== "devhub")
108
+ return;
109
+ await (0, promises_1.writeFile)(cachePath, JSON.stringify(config), { mode: 0o600 });
110
+ console.error("[config] Devhub config cached");
111
+ }
112
+ async function loadLocalConfig(cwd, env) {
113
+ for (const filename of LOCAL_CONFIG_FILES) {
114
+ const file = (0, node_path_1.resolve)(cwd, filename);
115
+ if (!(0, node_fs_1.existsSync)(file))
116
+ continue;
117
+ delete requireConfig.cache[requireConfig.resolve(file)];
118
+ const imported = requireConfig(file);
119
+ const raw = imported.default ?? imported;
120
+ console.error(`[config] Loaded local config from: ${file}`);
121
+ return normalizeConfig(raw, "local", env);
122
+ }
123
+ console.error("[config] No local config file found, using defaults.");
124
+ return normalizeConfig({}, "local", env);
125
+ }
126
+ async function loadReviewConfig(options = {}) {
127
+ const env = options.env ?? process.env;
128
+ const fetchImpl = options.fetchImpl ?? fetch;
129
+ const cached = await loadCachedConfig(env);
130
+ if (cached)
131
+ return cached;
132
+ const devhubConfig = await loadDevhubConfig(env, fetchImpl);
133
+ if (devhubConfig) {
134
+ await writeCachedConfig(env, devhubConfig);
135
+ console.error("[config] Loaded config from Devhub");
136
+ return devhubConfig;
137
+ }
138
+ return loadLocalConfig(options.cwd ?? process.cwd(), env);
139
+ }
140
+ function sanitizeConfigForLog(config) {
141
+ return {
142
+ ...config,
143
+ ai: { ...config.ai, apiKey: config.ai.apiKey ? "***" : "" },
144
+ gitlab: config.gitlab?.token ? { token: "***" } : config.gitlab,
145
+ };
146
+ }
147
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;AAiKA,4CAcC;AAED,oDAMC;AAvLD,qCAAqC;AACrC,+CAAuD;AACvD,yCAAoC;AACpC,6CAA4C;AAC5C,2CAAmF;AAWnF,MAAM,kBAAkB,GAAG;IACzB,iBAAiB;IACjB,gBAAgB;IAChB,kBAAkB;IAClB,iBAAiB;CAClB,CAAC;AACF,MAAM,aAAa,GAAG,IAAA,2BAAa,EAAC,UAAU,CAAC,CAAC;AAEhD,SAAS,oBAAoB,CAAC,GAAsB;IAClD,MAAM,GAAG,GAAG,GAAG,CAAC,4BAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,GAAG,IAAI,IAAI,CAAC;AACrB,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC;QAClE,CAAC,CAAC,EAAE,CAAC;AACT,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACvC,OAAO,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,OAAO;QACjE,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QACrE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;QACnB,CAAC,CAAC,GAAG,CAAC;AACV,CAAC;AAED,SAAS,eAAe,CACtB,GAA8B,EAC9B,MAA0B,EAC1B,GAAsB;IAEtB,OAAO;QACL,MAAM;QACN,EAAE,EAAE;YACF,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI;YAClB,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,QAAQ;YAC1B,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,IAAI,eAAe;YACvC,QAAQ,EACN,GAAG,CAAC,EAAE,EAAE,QAAQ,IAAI,2CAA2C;YACjE,MAAM,EAAE,GAAG,CAAC,aAAa,IAAI,GAAG,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE;SAClD;QACD,KAAK,EAAE;YACL,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC;SACzC;QACD,MAAM,EAAE;YACN,QAAQ,EAAE,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC;YACjD,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;YACzC,WAAW,EAAE,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC;SAC3D;QACD,OAAO,EAAE;YACP,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,IAAI;SACtC;QACD,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS;KACpE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,GAAsB,EACtB,SAAoB;IAEpB,MAAM,WAAW,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,6BAAiB,CAAC,CAAC;IACrC,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,GAAG,GAAG,GAAG,WAAW,GAAG,2BAAe,EAAE,CAAC;IAC/C,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;SAC9C,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,iCAAiC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAA8B,CAAC;QAC7D,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;YAC7C,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC3D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,gCAAgC,EAChC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,GAAsB;IAEtB,MAAM,SAAS,GAAG,GAAG,CAAC,iBAAiB,CAAC;IACxC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAA,oBAAU,EAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,IAAA,mBAAQ,EAAC,SAAS,EAAE,MAAM,CAAC,CAAqB,CAAC;QAC9E,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC;YAClE,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;YAC1D,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,2BAA2B,EAC3B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,GAAsB,EACtB,MAAwB;IAExB,MAAM,SAAS,GAAG,GAAG,CAAC,iBAAiB,CAAC;IACxC,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO;IACrD,MAAM,IAAA,oBAAS,EAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,eAAe,CAC5B,GAAW,EACX,GAAsB;IAEtB,KAAK,MAAM,QAAQ,IAAI,kBAAkB,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,IAAA,mBAAO,EAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,IAAA,oBAAU,EAAC,IAAI,CAAC;YAAE,SAAS;QAChC,OAAO,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAEN,CAAC;QAC9B,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC;QACzC,OAAO,CAAC,KAAK,CAAC,sCAAsC,IAAI,EAAE,CAAC,CAAC;QAC5D,OAAO,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC;IACtE,OAAO,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC;AAEM,KAAK,UAAU,gBAAgB,CACpC,UAAmC,EAAE;IAErC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACvC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC5D,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,iBAAiB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACpD,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,eAAe,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;AAC5D,CAAC;AAED,SAAgB,oBAAoB,CAAC,MAAwB;IAC3D,OAAO;QACL,GAAG,MAAM;QACT,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM;KAChE,CAAC;AACJ,CAAC"}
@@ -1,8 +1,8 @@
1
1
  export declare const TOOL_NAME = "ai-code-review";
2
- export declare const CLI_NAME = "ai-code-review-cli-remote";
3
- export declare const DEFAULT_PLATFORM_URL = "http://43.138.0.254:3001";
4
2
  export declare const REQUEST_TIMEOUT_MS = 120000;
5
3
  export declare const ENV_PLATFORM_URL = "AICR_PLATFORM_URL";
6
4
  export declare const ENV_PROJECT_TOKEN = "AICR_PROJECT_TOKEN";
7
- export declare const API_REVIEW_PATH = "/api/review/analyze";
5
+ export declare const API_REVIEW_PATH = "/api/modules/code-review/analyze";
6
+ export declare const API_CONFIG_PATH = "/api/modules/code-review/ci/config";
7
+ export declare const API_RUNS_PATH = "/api/modules/code-review/ci/runs";
8
8
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAC1C,eAAO,MAAM,QAAQ,8BAA8B,CAAC;AAEpD,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAC/D,eAAO,MAAM,kBAAkB,SAAU,CAAC;AAE1C,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AACpD,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,eAAO,MAAM,eAAe,wBAAwB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAC1C,eAAO,MAAM,kBAAkB,SAAU,CAAC;AAE1C,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AACpD,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,eAAO,MAAM,eAAe,qCAAqC,CAAC;AAClE,eAAO,MAAM,eAAe,uCAAuC,CAAC;AACpE,eAAO,MAAM,aAAa,qCAAqC,CAAC"}
package/dist/constants.js CHANGED
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.API_REVIEW_PATH = exports.ENV_PROJECT_TOKEN = exports.ENV_PLATFORM_URL = exports.REQUEST_TIMEOUT_MS = exports.DEFAULT_PLATFORM_URL = exports.CLI_NAME = exports.TOOL_NAME = void 0;
3
+ exports.API_RUNS_PATH = exports.API_CONFIG_PATH = exports.API_REVIEW_PATH = exports.ENV_PROJECT_TOKEN = exports.ENV_PLATFORM_URL = exports.REQUEST_TIMEOUT_MS = exports.TOOL_NAME = void 0;
4
4
  exports.TOOL_NAME = "ai-code-review";
5
- exports.CLI_NAME = "ai-code-review-cli-remote";
6
- exports.DEFAULT_PLATFORM_URL = "http://43.138.0.254:3001";
7
5
  exports.REQUEST_TIMEOUT_MS = 120000;
8
6
  exports.ENV_PLATFORM_URL = "AICR_PLATFORM_URL";
9
7
  exports.ENV_PROJECT_TOKEN = "AICR_PROJECT_TOKEN";
10
- exports.API_REVIEW_PATH = "/api/review/analyze";
8
+ exports.API_REVIEW_PATH = "/api/modules/code-review/analyze";
9
+ exports.API_CONFIG_PATH = "/api/modules/code-review/ci/config";
10
+ exports.API_RUNS_PATH = "/api/modules/code-review/ci/runs";
11
11
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,SAAS,GAAG,gBAAgB,CAAC;AAC7B,QAAA,QAAQ,GAAG,2BAA2B,CAAC;AAEvC,QAAA,oBAAoB,GAAG,0BAA0B,CAAC;AAClD,QAAA,kBAAkB,GAAG,MAAO,CAAC;AAE7B,QAAA,gBAAgB,GAAG,mBAAmB,CAAC;AACvC,QAAA,iBAAiB,GAAG,oBAAoB,CAAC;AAEzC,QAAA,eAAe,GAAG,qBAAqB,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,SAAS,GAAG,gBAAgB,CAAC;AAC7B,QAAA,kBAAkB,GAAG,MAAO,CAAC;AAE7B,QAAA,gBAAgB,GAAG,mBAAmB,CAAC;AACvC,QAAA,iBAAiB,GAAG,oBAAoB,CAAC;AAEzC,QAAA,eAAe,GAAG,kCAAkC,CAAC;AACrD,QAAA,eAAe,GAAG,oCAAoC,CAAC;AACvD,QAAA,aAAa,GAAG,kCAAkC,CAAC"}
package/dist/diff.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { AIComment } from "./types";
2
+ export declare function globToRegExp(pattern: string): RegExp;
3
+ export declare function filterDiffByIgnore(diff: string, ignorePatterns?: string[]): string;
4
+ export declare function buildAddedLinesIndexText(diff: string, maxLines?: number): string;
5
+ export declare function alignCommentsToDiffAddedLines(diff: string, comments: AIComment[]): AIComment[];
6
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBpD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAmBlF;AA4DD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAO,GAAG,MAAM,CAU9E;AAED,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,SAAS,EAAE,GACpB,SAAS,EAAE,CAqBb"}
package/dist/diff.js ADDED
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.globToRegExp = globToRegExp;
4
+ exports.filterDiffByIgnore = filterDiffByIgnore;
5
+ exports.buildAddedLinesIndexText = buildAddedLinesIndexText;
6
+ exports.alignCommentsToDiffAddedLines = alignCommentsToDiffAddedLines;
7
+ function globToRegExp(pattern) {
8
+ if (pattern.endsWith("/**")) {
9
+ const prefix = pattern.slice(0, -3).replace(/[.+?^${}()|[\]\\]/g, "\\$&");
10
+ return new RegExp(`^${prefix}/.*$`);
11
+ }
12
+ if (pattern.startsWith("**/")) {
13
+ const rest = pattern
14
+ .slice(3)
15
+ .replace(/[.+?^${}()|[\]\\]/g, "\\$&")
16
+ .replace(/\*/g, "[^/]*");
17
+ return new RegExp(`^(?:.*/)?${rest}$`);
18
+ }
19
+ const escaped = pattern
20
+ .replace(/[.+?^${}()|[\]\\]/g, "\\$&")
21
+ .replace(/\*/g, "[^/]*");
22
+ return new RegExp(`^${escaped}$`);
23
+ }
24
+ function filterDiffByIgnore(diff, ignorePatterns) {
25
+ if (!ignorePatterns?.length || !diff.trim())
26
+ return diff;
27
+ const lines = diff.split("\n");
28
+ const kept = [];
29
+ let ignoreCurrent = false;
30
+ for (const line of lines) {
31
+ if (line.startsWith("diff --git ")) {
32
+ ignoreCurrent = false;
33
+ const match = /^diff --git a\/(.+?) b\/(.+)$/.exec(line);
34
+ if (match) {
35
+ ignoreCurrent = ignorePatterns.some((pattern) => globToRegExp(pattern).test(match[2]));
36
+ }
37
+ }
38
+ if (!ignoreCurrent)
39
+ kept.push(line);
40
+ }
41
+ return kept.join("\n");
42
+ }
43
+ function normalizePath(path) {
44
+ return path.trim().replace(/^[ab]\//, "").replace(/^\.\//, "");
45
+ }
46
+ function collectAddedLines(diff) {
47
+ const files = new Map();
48
+ let currentFile = null;
49
+ let inHunk = false;
50
+ let newLine = 0;
51
+ let oldLine = 0;
52
+ for (const raw of diff.split("\n")) {
53
+ if (raw.startsWith("diff --git ")) {
54
+ inHunk = false;
55
+ currentFile = null;
56
+ const match = /^diff --git a\/(.+?) b\/(.+)$/.exec(raw);
57
+ if (match) {
58
+ currentFile = normalizePath(match[2]);
59
+ files.set(currentFile, files.get(currentFile) ?? []);
60
+ }
61
+ continue;
62
+ }
63
+ if (raw.startsWith("+++ b/")) {
64
+ currentFile = normalizePath(raw.slice("+++ b/".length));
65
+ files.set(currentFile, files.get(currentFile) ?? []);
66
+ continue;
67
+ }
68
+ if (raw.startsWith("@@")) {
69
+ const match = /^@@\s+\-(\d+)(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s+@@/.exec(raw);
70
+ inHunk = !!match;
71
+ oldLine = Number(match?.[1] ?? 0);
72
+ newLine = Number(match?.[2] ?? 0);
73
+ continue;
74
+ }
75
+ if (!inHunk || !currentFile)
76
+ continue;
77
+ if (raw.startsWith("+") && !raw.startsWith("+++")) {
78
+ files.get(currentFile)?.push({
79
+ file: currentFile,
80
+ line: newLine,
81
+ content: raw.slice(1),
82
+ });
83
+ newLine += 1;
84
+ }
85
+ else if (raw.startsWith("-") && !raw.startsWith("---")) {
86
+ oldLine += 1;
87
+ }
88
+ else if (raw.startsWith(" ")) {
89
+ oldLine += 1;
90
+ newLine += 1;
91
+ }
92
+ }
93
+ return files;
94
+ }
95
+ function buildAddedLinesIndexText(diff, maxLines = 5000) {
96
+ const rows = [];
97
+ for (const [file, lines] of collectAddedLines(diff)) {
98
+ for (const item of lines) {
99
+ if (rows.length >= maxLines)
100
+ break;
101
+ rows.push(`[${file}:${item.line}] ${item.content}`);
102
+ }
103
+ if (rows.length >= maxLines)
104
+ break;
105
+ }
106
+ return rows.length ? rows.join("\n") : "(diff 中未检测到可评论的新增行)";
107
+ }
108
+ function alignCommentsToDiffAddedLines(diff, comments) {
109
+ const added = collectAddedLines(diff);
110
+ return comments.flatMap((comment) => {
111
+ const file = normalizePath(comment.file);
112
+ const candidates = added.get(file);
113
+ if (!candidates?.length)
114
+ return [];
115
+ const exact = candidates.find((item) => item.line === comment.line);
116
+ const byCode = typeof comment.code === "string"
117
+ ? candidates.find((item) => item.content.trim() === comment.code?.trim())
118
+ : undefined;
119
+ const chosen = exact ??
120
+ byCode ??
121
+ candidates.reduce((best, item) => Math.abs(item.line - comment.line) < Math.abs(best.line - comment.line)
122
+ ? item
123
+ : best);
124
+ return [{ ...comment, file, line: chosen.line }];
125
+ });
126
+ }
127
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":";;AAEA,oCAgBC;AAED,gDAmBC;AA4DD,4DAUC;AAED,sEAwBC;AArID,SAAgB,YAAY,CAAC,OAAe;IAC1C,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QAC1E,OAAO,IAAI,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,OAAO;aACjB,KAAK,CAAC,CAAC,CAAC;aACR,OAAO,CAAC,oBAAoB,EAAE,MAAM,CAAC;aACrC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3B,OAAO,IAAI,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,OAAO,GAAG,OAAO;SACpB,OAAO,CAAC,oBAAoB,EAAE,MAAM,CAAC;SACrC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3B,OAAO,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;AACpC,CAAC;AAED,SAAgB,kBAAkB,CAAC,IAAY,EAAE,cAAyB;IACxE,IAAI,CAAC,cAAc,EAAE,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,OAAO,IAAI,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,aAAa,GAAG,KAAK,CAAC;IAE1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACnC,aAAa,GAAG,KAAK,CAAC;YACtB,MAAM,KAAK,GAAG,+BAA+B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzD,IAAI,KAAK,EAAE,CAAC;gBACV,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAC9C,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CACrC,CAAC;YACJ,CAAC;QACH,CAAC;QACD,IAAI,CAAC,aAAa;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAQD,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC7C,IAAI,WAAW,GAAkB,IAAI,CAAC;IACtC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAClC,MAAM,GAAG,KAAK,CAAC;YACf,WAAW,GAAG,IAAI,CAAC;YACnB,MAAM,KAAK,GAAG,+BAA+B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACxD,IAAI,KAAK,EAAE,CAAC;gBACV,WAAW,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBACtC,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;YACxD,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;YACrD,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,gDAAgD,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzE,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC;YACjB,OAAO,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAClC,OAAO,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAClC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW;YAAE,SAAS;QACtC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC;gBAC3B,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;aACtB,CAAC,CAAC;YACH,OAAO,IAAI,CAAC,CAAC;QACf,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC,CAAC;QACf,CAAC;aAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,CAAC;YACb,OAAO,IAAI,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,wBAAwB,CAAC,IAAY,EAAE,QAAQ,GAAG,IAAI;IACpE,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;gBAAE,MAAM;YACnC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,IAAI,QAAQ;YAAE,MAAM;IACrC,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC;AAC/D,CAAC;AAED,SAAgB,6BAA6B,CAC3C,IAAY,EACZ,QAAqB;IAErB,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,UAAU,EAAE,MAAM;YAAE,OAAO,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACpE,MAAM,MAAM,GACV,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ;YAC9B,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;YACzE,CAAC,CAAC,SAAS,CAAC;QAChB,MAAM,MAAM,GACV,KAAK;YACL,MAAM;YACN,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;gBACrE,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,IAAI,CACT,CAAC;QACJ,OAAO,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { AIComment, RdjsonOutput } from "./types";
2
+ export declare function buildEmptyRdjson(): RdjsonOutput;
3
+ export declare function buildRdjson(comments: AIComment[]): RdjsonOutput;
4
+ //# sourceMappingURL=formatters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAY,MAAM,SAAS,CAAC;AAQjE,wBAAgB,gBAAgB,IAAI,YAAY,CAE/C;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,YAAY,CAgB/D"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildEmptyRdjson = buildEmptyRdjson;
4
+ exports.buildRdjson = buildRdjson;
5
+ function toRdjsonSeverity(severity) {
6
+ if (severity === "error")
7
+ return "ERROR";
8
+ if (severity === "info")
9
+ return "INFO";
10
+ return "WARNING";
11
+ }
12
+ function buildEmptyRdjson() {
13
+ return { source: { name: "ai_code_review" }, diagnostics: [] };
14
+ }
15
+ function buildRdjson(comments) {
16
+ return {
17
+ source: { name: "ai_code_review" },
18
+ diagnostics: comments
19
+ .filter((comment) => comment.file && comment.line)
20
+ .map((comment) => ({
21
+ message: `${comment.message || "AI Code Review 提示"}${comment.suggestion ? `\n建议:${comment.suggestion}` : ""}`,
22
+ location: {
23
+ path: comment.file,
24
+ range: { start: { line: Number(comment.line) || 1, column: 1 } },
25
+ },
26
+ severity: toRdjsonSeverity(comment.severity),
27
+ })),
28
+ };
29
+ }
30
+ //# sourceMappingURL=formatters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatters.js","sourceRoot":"","sources":["../src/formatters.ts"],"names":[],"mappings":";;AAQA,4CAEC;AAED,kCAgBC;AA1BD,SAAS,gBAAgB,CAAC,QAAkB;IAC1C,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IACzC,IAAI,QAAQ,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IACvC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AACjE,CAAC;AAED,SAAgB,WAAW,CAAC,QAAqB;IAC/C,OAAO;QACL,MAAM,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;QAClC,WAAW,EAAE,QAAQ;aAClB,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;aACjD,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACjB,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,IAAI,mBAAmB,GAChD,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EACtD,EAAE;YACF,QAAQ,EAAE;gBACR,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE;aACjE;YACD,QAAQ,EAAE,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC;SAC7C,CAAC,CAAC;KACN,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export declare const reviewMain: () => Promise<void>;
2
- export declare const summaryMain: () => Promise<void>;
1
+ #!/usr/bin/env node
2
+ export {};
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoFA,eAAO,MAAM,UAAU,QAAa,OAAO,CAAC,IAAI,CAE/C,CAAC;AAEF,eAAO,MAAM,WAAW,QAAa,OAAO,CAAC,IAAI,CAEhD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js CHANGED
@@ -1,82 +1,23 @@
1
+ #!/usr/bin/env node
1
2
  "use strict";
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.summaryMain = exports.reviewMain = void 0;
4
4
  const constants_1 = require("./constants");
5
- const client_1 = require("./client");
6
- const readStdin = () => new Promise((resolve, reject) => {
7
- let data = "";
8
- process.stdin.setEncoding("utf8");
9
- process.stdin.on("data", (chunk) => {
10
- data += chunk;
11
- });
12
- process.stdin.on("end", () => {
13
- resolve(data);
14
- });
15
- process.stdin.on("error", (err) => {
16
- reject(err);
17
- });
18
- });
19
- function readCiContext() {
20
- const mrIid = process.env.CI_MERGE_REQUEST_IID;
21
- const commitSha = process.env.CI_COMMIT_SHA;
22
- const baseSha = process.env.CI_MERGE_REQUEST_DIFF_BASE_SHA;
23
- if (!mrIid || !commitSha || !baseSha) {
24
- return null;
25
- }
26
- return {
27
- mrIid: Number(mrIid),
28
- commitSha,
29
- baseSha,
30
- startSha: baseSha,
31
- };
32
- }
33
- async function main() {
34
- const ci = readCiContext();
35
- if (!ci) {
36
- console.error(`[${constants_1.TOOL_NAME}] 缺少 GitLab CI 环境变量(CI_MERGE_REQUEST_IID / CI_COMMIT_SHA / CI_MERGE_REQUEST_DIFF_BASE_SHA)`);
37
- console.error(`[${constants_1.TOOL_NAME}] 请确保在 merge_request pipeline 中运行`);
38
- process.exit(1);
39
- }
40
- const diff = await readStdin();
41
- if (!diff?.trim()) {
42
- console.error(`[${constants_1.TOOL_NAME}] diff 为空,跳过审查`);
43
- process.exit(0);
44
- }
45
- console.error(`[${constants_1.TOOL_NAME}] MR !${ci.mrIid} | commit ${ci.commitSha.slice(0, 8)} | base ${ci.baseSha.slice(0, 8)} | diff ${diff.length} bytes`);
46
- const result = await (0, client_1.analyzeWithCi)(diff, ci);
47
- if (result.posted) {
48
- console.error(`[${constants_1.TOOL_NAME}] 审查完成:${result.diagnosticsCount ?? 0} 条诊断,${result.postedCount ?? 0} 条已发布到 MR${result.summaryPosted ? ",汇总已发布" : ""}`);
49
- }
50
- if (result.errors && result.errors.length > 0) {
51
- console.error(`[${constants_1.TOOL_NAME}] 部分评论发布失败:`);
52
- for (const e of result.errors) {
53
- console.error(` - ${e}`);
54
- }
55
- }
56
- if (result.note) {
57
- console.error(`[${constants_1.TOOL_NAME}] ${result.note}`);
58
- }
59
- }
60
- // Keep the historical bin contract so published packages do not crash
61
- // when they invoke review/summary entry points.
62
- const reviewMain = async () => {
63
- await main();
64
- };
65
- exports.reviewMain = reviewMain;
66
- const summaryMain = async () => {
67
- await main();
68
- };
69
- exports.summaryMain = summaryMain;
5
+ const runner_1 = require("./runner");
70
6
  if (require.main === module) {
71
- if (!process.env[constants_1.ENV_PROJECT_TOKEN]) {
72
- console.error(`[${constants_1.TOOL_NAME}] 错误: ${constants_1.ENV_PROJECT_TOKEN} 未设置\n` +
73
- "该变量应在项目接入时由平台自动配置到 GitLab CI 变量中。\n" +
74
- "若需手动配置:登录 AICR 平台 -> 项目设置 -> Token 管理");
75
- process.exit(1);
76
- }
77
- const platformUrl = process.env[constants_1.ENV_PLATFORM_URL] || "(default)";
78
- console.error(`[${constants_1.TOOL_NAME}] 平台地址: ${platformUrl}`);
79
- main().catch((error) => {
7
+ const argv = process.argv.slice(2);
8
+ const args = new Set(argv);
9
+ const run = args.has("--write-reviewdog-env")
10
+ ? () => {
11
+ const idx = argv.indexOf("--write-reviewdog-env");
12
+ const outputPath = argv[idx + 1];
13
+ if (!outputPath)
14
+ throw new Error("--write-reviewdog-env 缺少输出路径");
15
+ return (0, runner_1.writeReviewdogEnvMain)(outputPath);
16
+ }
17
+ : args.has("--summary")
18
+ ? runner_1.summaryMain
19
+ : runner_1.reviewMain;
20
+ run().catch((error) => {
80
21
  console.error(`[${constants_1.TOOL_NAME}] 执行错误:`, error instanceof Error ? error.message : error);
81
22
  process.exit(1);
82
23
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,2CAAwC;AACxC,qCAA0E;AAE1E,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC;QAC3C,CAAC,CAAC,GAAG,EAAE;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YACjC,IAAI,CAAC,UAAU;gBAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YACjE,OAAO,IAAA,8BAAqB,EAAC,UAAU,CAAC,CAAC;QAC3C,CAAC;QACH,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;YACrB,CAAC,CAAC,oBAAW;YACb,CAAC,CAAC,mBAAU,CAAC;IAEjB,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;QACpB,OAAO,CAAC,KAAK,CACX,IAAI,qBAAS,SAAS,EACtB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface ModelAdapter {
2
+ call(model: string, systemPrompt: string, userPrompt: string): Promise<string | null>;
3
+ }
4
+ export declare function createModelAdapter(endpoint: string, apiKey: string): ModelAdapter;
5
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACvF;AAgGD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAQjF"}
package/dist/model.js ADDED
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createModelAdapter = createModelAdapter;
4
+ class OpenAIAdapter {
5
+ constructor(endpoint, apiKey) {
6
+ this.endpoint = endpoint;
7
+ this.apiKey = apiKey;
8
+ }
9
+ async call(model, systemPrompt, userPrompt) {
10
+ console.error(`[model] openai-compatible request start model=${model}`);
11
+ let url = this.endpoint.replace(/\/+$/, "");
12
+ if (!url.endsWith("/chat/completions")) {
13
+ url += "/chat/completions";
14
+ }
15
+ const resp = await fetch(url, {
16
+ method: "POST",
17
+ headers: {
18
+ "Content-Type": "application/json",
19
+ Authorization: `Bearer ${this.apiKey}`,
20
+ },
21
+ body: JSON.stringify({
22
+ model,
23
+ messages: [
24
+ { role: "system", content: systemPrompt },
25
+ { role: "user", content: userPrompt },
26
+ ],
27
+ stream: false,
28
+ }),
29
+ });
30
+ if (!resp.ok) {
31
+ console.error(`[model] OpenAI compatible API failed status=${resp.status}`);
32
+ return null;
33
+ }
34
+ const json = (await resp.json());
35
+ const content = json.choices?.[0]?.message?.content?.trim() || null;
36
+ console.error(content
37
+ ? `[model] openai-compatible request complete bytes=${Buffer.byteLength(content)}`
38
+ : "[model] openai-compatible response empty");
39
+ return content;
40
+ }
41
+ }
42
+ class GeminiAdapter {
43
+ constructor(endpoint, apiKey) {
44
+ this.endpoint = endpoint;
45
+ this.apiKey = apiKey;
46
+ }
47
+ async call(model, systemPrompt, userPrompt) {
48
+ console.error(`[model] gemini request start model=${model}`);
49
+ let url = this.endpoint;
50
+ if (!url.includes("key=")) {
51
+ url = `${url}${url.includes("?") ? "&" : "?"}key=${this.apiKey}`;
52
+ }
53
+ const resp = await fetch(url, {
54
+ method: "POST",
55
+ headers: { "Content-Type": "application/json" },
56
+ body: JSON.stringify({
57
+ contents: [{ parts: [{ text: `${systemPrompt}\n\n${userPrompt}` }] }],
58
+ generationConfig: { response_mime_type: "application/json" },
59
+ }),
60
+ });
61
+ if (!resp.ok) {
62
+ console.error(`[model] Gemini API failed status=${resp.status}`);
63
+ return null;
64
+ }
65
+ const json = (await resp.json());
66
+ const content = json.candidates?.[0]?.content?.parts?.[0]?.text?.trim() || null;
67
+ console.error(content
68
+ ? `[model] gemini request complete bytes=${Buffer.byteLength(content)}`
69
+ : "[model] gemini response empty");
70
+ return content;
71
+ }
72
+ }
73
+ function createModelAdapter(endpoint, apiKey) {
74
+ if (endpoint.includes("generativelanguage.googleapis.com") ||
75
+ endpoint.includes(":generateContent")) {
76
+ return new GeminiAdapter(endpoint, apiKey);
77
+ }
78
+ return new OpenAIAdapter(endpoint, apiKey);
79
+ }
80
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface RunReportPayload {
2
+ status: "SUCCESS" | "FAILED" | "TIMEOUT" | "QUOTA_EXCEEDED";
3
+ modelUsed?: string;
4
+ commentCount?: number;
5
+ duration?: number;
6
+ mrIid?: string | number;
7
+ }
8
+ export declare function postRunReport(payload: RunReportPayload, env?: NodeJS.ProcessEnv): Promise<void>;
9
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,gBAAgB,CAAC;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACzB;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,EACzB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,IAAI,CAAC,CA0Bf"}
package/dist/report.js ADDED
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.postRunReport = postRunReport;
4
+ const constants_1 = require("./constants");
5
+ async function postRunReport(payload, env = process.env) {
6
+ const platformUrl = env[constants_1.ENV_PLATFORM_URL]?.replace(/\/+$/, "");
7
+ const token = env[constants_1.ENV_PROJECT_TOKEN];
8
+ if (!platformUrl || !token)
9
+ return;
10
+ try {
11
+ console.error(`[report] posting run report status=${payload.status}`);
12
+ const resp = await fetch(`${platformUrl}${constants_1.API_RUNS_PATH}`, {
13
+ method: "POST",
14
+ headers: {
15
+ "Content-Type": "application/json",
16
+ Authorization: `Bearer ${token}`,
17
+ },
18
+ body: JSON.stringify(payload),
19
+ });
20
+ if (!resp.ok) {
21
+ console.error(`[report] 运行结果上报失败 status=${resp.status}`);
22
+ return;
23
+ }
24
+ console.error("[report] run report posted");
25
+ }
26
+ catch (error) {
27
+ console.error("[report] 运行结果上报异常:", error instanceof Error ? error.message : String(error));
28
+ }
29
+ }
30
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":";;AAUA,sCA6BC;AAvCD,2CAAiF;AAU1E,KAAK,UAAU,aAAa,CACjC,OAAyB,EACzB,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,WAAW,GAAG,GAAG,CAAC,4BAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,6BAAiB,CAAC,CAAC;IACrC,IAAI,CAAC,WAAW,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnC,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,sCAAsC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,GAAG,yBAAa,EAAE,EAAE;YACzD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,KAAK,EAAE;aACjC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,4BAA4B,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACzD,OAAO;QACT,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,oBAAoB,EACpB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AIResponse, CodeReviewConfig } from "./types";
2
+ export declare function reviewCode(diff: string, config: CodeReviewConfig): Promise<AIResponse | null>;
3
+ //# sourceMappingURL=reviewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewer.d.ts","sourceRoot":"","sources":["../src/reviewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA4D5D,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAyB5B"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reviewCode = reviewCode;
4
+ const diff_1 = require("./diff");
5
+ const model_1 = require("./model");
6
+ const COMMON_RULES = [
7
+ "重点关注潜在 bug、性能问题、可读性与安全性(如 XSS、注入、敏感信息泄露)",
8
+ "代码要有适当的错误处理",
9
+ "避免代码重复,注意抽离复用逻辑",
10
+ "函数和变量命名要语义化,见名知意",
11
+ "复杂逻辑要添加注释说明",
12
+ ];
13
+ function buildSystemPrompt() {
14
+ return "你是一个资深的代码审查助手,需要根据给定的 Git diff 和项目规范,对改动的代码进行严格的 Code Review。";
15
+ }
16
+ function buildUserPrompt(diff, rules) {
17
+ return [
18
+ "请你只针对 diff 中【新增或修改】的代码行给出审查意见。",
19
+ "输出格式要求:必须返回严格的 JSON,形如:",
20
+ '{"comments":[{"file":"src/xxx.ts","line":123,"code":"该行完整代码","severity":"warning","message":"问题描述","suggestion":"修复建议"}]}',
21
+ "注意:severity 只能是 info / warning / error;file 必须使用 diff 中出现的路径;line 必须是 new file 侧真实行号;只能评论新增行。",
22
+ "",
23
+ "可评论行索引:",
24
+ (0, diff_1.buildAddedLinesIndexText)(diff),
25
+ "",
26
+ "项目规范:",
27
+ rules.join("\n"),
28
+ "",
29
+ "Git diff:",
30
+ diff,
31
+ ].join("\n");
32
+ }
33
+ function stripFences(text) {
34
+ return text
35
+ .replace(/^```(?:json)?\s*/i, "")
36
+ .replace(/```$/i, "")
37
+ .trim();
38
+ }
39
+ function parseAIResponse(content) {
40
+ const text = stripFences(content);
41
+ const start = text.indexOf("{");
42
+ const end = text.lastIndexOf("}");
43
+ const jsonText = start >= 0 && end > start ? text.slice(start, end + 1) : text;
44
+ try {
45
+ const parsed = JSON.parse(jsonText);
46
+ return { comments: Array.isArray(parsed.comments) ? parsed.comments : [] };
47
+ }
48
+ catch (error) {
49
+ console.error("[reviewer] AI 返回 JSON 解析失败");
50
+ console.error(error);
51
+ return null;
52
+ }
53
+ }
54
+ async function reviewCode(diff, config) {
55
+ const effectiveDiff = (0, diff_1.filterDiffByIgnore)(diff, config.review?.ignore);
56
+ if (!effectiveDiff.trim())
57
+ return { comments: [] };
58
+ if (!config.ai.apiKey || !config.ai.endpoint)
59
+ return null;
60
+ const adapter = (0, model_1.createModelAdapter)(config.ai.endpoint, config.ai.apiKey);
61
+ const raw = await adapter.call(config.ai.model, buildSystemPrompt(), buildUserPrompt(effectiveDiff, [...COMMON_RULES, ...(config.rules?.custom ?? [])]));
62
+ if (!raw)
63
+ return null;
64
+ const parsed = parseAIResponse(raw);
65
+ if (!parsed)
66
+ return null;
67
+ let comments = (0, diff_1.alignCommentsToDiffAddedLines)(effectiveDiff, parsed.comments);
68
+ const severityOrder = { info: 0, warning: 1, error: 2 };
69
+ const min = severityOrder[config.review?.severity ?? "warning"];
70
+ comments = comments.filter((comment) => severityOrder[comment.severity] >= min);
71
+ const maxComments = config.review?.maxComments ?? 100;
72
+ if (comments.length > maxComments) {
73
+ comments = comments.slice(0, maxComments);
74
+ }
75
+ return { comments };
76
+ }
77
+ //# sourceMappingURL=reviewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../src/reviewer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare const readStdin: () => Promise<string>;
2
+ export declare function reviewMain(): Promise<void>;
3
+ export declare function summaryMain(): Promise<void>;
4
+ export declare function writeReviewdogEnvMain(path: string): Promise<void>;
5
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,SAAS,QAAO,OAAO,CAAC,MAAM,CASvC,CAAC;AAML,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CA+ChD;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAejD;AAMD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYvE"}
package/dist/runner.js ADDED
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readStdin = void 0;
4
+ exports.reviewMain = reviewMain;
5
+ exports.summaryMain = summaryMain;
6
+ exports.writeReviewdogEnvMain = writeReviewdogEnvMain;
7
+ const config_1 = require("./config");
8
+ const formatters_1 = require("./formatters");
9
+ const reviewer_1 = require("./reviewer");
10
+ const summarizer_1 = require("./summarizer");
11
+ const report_1 = require("./report");
12
+ const promises_1 = require("node:fs/promises");
13
+ const readStdin = () => new Promise((resolve, reject) => {
14
+ let data = "";
15
+ process.stdin.setEncoding("utf8");
16
+ process.stdin.on("data", (chunk) => {
17
+ data += chunk;
18
+ });
19
+ process.stdin.on("end", () => resolve(data));
20
+ process.stdin.on("error", reject);
21
+ });
22
+ exports.readStdin = readStdin;
23
+ function currentMrIid() {
24
+ return process.env.CI_MERGE_REQUEST_IID;
25
+ }
26
+ async function reviewMain() {
27
+ const startedAt = Date.now();
28
+ const diff = await (0, exports.readStdin)();
29
+ console.error(`[runner] review start diffBytes=${Buffer.byteLength(diff)}`);
30
+ if (!diff.trim()) {
31
+ console.error("[runner] review skipped: empty diff");
32
+ console.log(JSON.stringify((0, formatters_1.buildEmptyRdjson)()));
33
+ return;
34
+ }
35
+ const config = await (0, config_1.loadReviewConfig)();
36
+ console.error(`[runner] config source=${config.source} model=${config.ai.model} summary=${config.summary?.enabled !== false}`);
37
+ if (!config.ai.apiKey) {
38
+ console.error("[ai-code-review] 未配置模型 API Key,输出空诊断");
39
+ console.log(JSON.stringify((0, formatters_1.buildEmptyRdjson)()));
40
+ await (0, report_1.postRunReport)({
41
+ status: "FAILED",
42
+ modelUsed: config.ai.model,
43
+ duration: Date.now() - startedAt,
44
+ mrIid: currentMrIid(),
45
+ });
46
+ return;
47
+ }
48
+ const result = await (0, reviewer_1.reviewCode)(diff, config);
49
+ if (!result) {
50
+ console.error("[runner] review failed: model returned no valid result");
51
+ console.log(JSON.stringify((0, formatters_1.buildEmptyRdjson)()));
52
+ await (0, report_1.postRunReport)({
53
+ status: "FAILED",
54
+ modelUsed: config.ai.model,
55
+ duration: Date.now() - startedAt,
56
+ mrIid: currentMrIid(),
57
+ });
58
+ return;
59
+ }
60
+ console.error(`[runner] review complete comments=${result.comments.length}`);
61
+ console.log(JSON.stringify((0, formatters_1.buildRdjson)(result.comments)));
62
+ await (0, report_1.postRunReport)({
63
+ status: "SUCCESS",
64
+ modelUsed: config.ai.model,
65
+ commentCount: result.comments.length,
66
+ duration: Date.now() - startedAt,
67
+ mrIid: currentMrIid(),
68
+ });
69
+ }
70
+ async function summaryMain() {
71
+ const diff = await (0, exports.readStdin)();
72
+ console.error(`[runner] summary start diffBytes=${Buffer.byteLength(diff)}`);
73
+ if (!diff.trim())
74
+ return;
75
+ const config = await (0, config_1.loadReviewConfig)();
76
+ console.error(`[runner] config source=${config.source} model=${config.ai.model} summary=${config.summary?.enabled !== false}`);
77
+ const markdown = await (0, summarizer_1.generateSummary)(diff, config);
78
+ console.error(markdown
79
+ ? `[runner] summary complete bytes=${Buffer.byteLength(markdown)}`
80
+ : "[runner] summary skipped or empty");
81
+ if (markdown)
82
+ console.log(markdown);
83
+ }
84
+ function shellSingleQuote(value) {
85
+ return `'${value.replace(/'/g, "'\\''")}'`;
86
+ }
87
+ async function writeReviewdogEnvMain(path) {
88
+ const config = await (0, config_1.loadReviewConfig)();
89
+ if (config.gitlab?.token) {
90
+ await (0, promises_1.writeFile)(path, `export REVIEWDOG_GITLAB_API_TOKEN=${shellSingleQuote(config.gitlab.token)}\n`, { mode: 0o600 });
91
+ console.error("[runner] reviewdog token env file written");
92
+ }
93
+ else {
94
+ console.error("[runner] reviewdog token missing in config");
95
+ }
96
+ }
97
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CodeReviewConfig } from "./types";
2
+ export declare function generateSummary(diff: string, config: CodeReviewConfig): Promise<string | null>;
3
+ //# sourceMappingURL=summarizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarizer.d.ts","sourceRoot":"","sources":["../src/summarizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA0DhD,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAYxB"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateSummary = generateSummary;
4
+ const diff_1 = require("./diff");
5
+ const model_1 = require("./model");
6
+ function buildSummarySystemPrompt() {
7
+ return [
8
+ "你是一位资深开发工程师,擅长分析代码改动并生成清晰的技术摘要。",
9
+ "根据给定 Git diff 生成中文 Markdown 汇总。",
10
+ "必须直接输出纯 Markdown 文本,不要返回 JSON,不要用代码块包裹。",
11
+ ].join("\n");
12
+ }
13
+ function buildSummaryUserPrompt(diff) {
14
+ return [
15
+ "请根据以下 Git diff 生成一份代码改动汇总报告。",
16
+ "",
17
+ "## 概述",
18
+ "用 1-2 句话说明整体目的和范围。",
19
+ "",
20
+ "## 主要变更",
21
+ "按新功能、Bug 修复、重构优化、依赖更新、配置调整分类列出。",
22
+ "",
23
+ "## 受影响文件",
24
+ "用表格列出文件路径、变更类型、说明。",
25
+ "",
26
+ "## 注意事项",
27
+ "列出需要关注的风险;没有则写“无”。",
28
+ "",
29
+ "Git diff:",
30
+ diff,
31
+ ].join("\n");
32
+ }
33
+ function cleanMarkdownResponse(content) {
34
+ let text = content.trim();
35
+ if (text.startsWith("```markdown"))
36
+ text = text.slice("```markdown".length);
37
+ else if (text.startsWith("```md"))
38
+ text = text.slice("```md".length);
39
+ else if (text.startsWith("```json"))
40
+ text = text.slice("```json".length);
41
+ else if (text.startsWith("```"))
42
+ text = text.slice(3);
43
+ if (text.endsWith("```"))
44
+ text = text.slice(0, -3);
45
+ text = text.trim();
46
+ if (text.startsWith("{") || text.startsWith('"')) {
47
+ try {
48
+ const parsed = JSON.parse(text);
49
+ if (typeof parsed === "string")
50
+ return parsed.trim();
51
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
52
+ const first = Object.values(parsed).find((value) => typeof value === "string");
53
+ if (first)
54
+ return first.trim();
55
+ }
56
+ }
57
+ catch {
58
+ // keep text
59
+ }
60
+ }
61
+ return text.replace(/\\n/g, "\n").trim();
62
+ }
63
+ async function generateSummary(diff, config) {
64
+ if (config.summary?.enabled === false)
65
+ return null;
66
+ const effectiveDiff = (0, diff_1.filterDiffByIgnore)(diff, config.review?.ignore);
67
+ if (!effectiveDiff.trim())
68
+ return null;
69
+ if (!config.ai.apiKey || !config.ai.endpoint)
70
+ return null;
71
+ const adapter = (0, model_1.createModelAdapter)(config.ai.endpoint, config.ai.apiKey);
72
+ const raw = await adapter.call(config.ai.model, buildSummarySystemPrompt(), buildSummaryUserPrompt(effectiveDiff));
73
+ return raw ? cleanMarkdownResponse(raw) : null;
74
+ }
75
+ //# sourceMappingURL=summarizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../src/summarizer.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,20 +1,56 @@
1
- export interface RdjsonDiagnostic {
2
- message: string;
3
- location: {
4
- path: string;
5
- range: {
6
- start: {
7
- line: number;
8
- column: number;
9
- };
10
- };
1
+ export type Severity = "info" | "warning" | "error";
2
+ export interface AIConfig {
3
+ name?: string;
4
+ provider?: string;
5
+ model: string;
6
+ endpoint: string;
7
+ apiKey: string;
8
+ }
9
+ export interface CodeReviewConfig {
10
+ source: "devhub" | "local";
11
+ ai: AIConfig;
12
+ rules?: {
13
+ custom?: string[];
14
+ };
15
+ review?: {
16
+ severity?: Severity;
17
+ ignore?: string[];
18
+ maxComments?: number;
19
+ };
20
+ summary?: {
21
+ enabled?: boolean;
11
22
  };
12
- severity: "ERROR" | "WARNING" | "INFO";
23
+ gitlab?: {
24
+ token?: string;
25
+ };
26
+ }
27
+ export interface AIComment {
28
+ file: string;
29
+ line: number;
30
+ code?: string;
31
+ severity: Severity;
32
+ message: string;
33
+ suggestion?: string;
34
+ }
35
+ export interface AIResponse {
36
+ comments: AIComment[];
13
37
  }
14
38
  export interface RdjsonOutput {
15
39
  source: {
16
40
  name: string;
17
41
  };
18
- diagnostics: RdjsonDiagnostic[];
42
+ diagnostics: Array<{
43
+ message: string;
44
+ location: {
45
+ path: string;
46
+ range: {
47
+ start: {
48
+ line: number;
49
+ column: number;
50
+ };
51
+ };
52
+ };
53
+ severity: "ERROR" | "WARNING" | "INFO";
54
+ }>;
19
55
  }
20
56
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE;YACL,KAAK,EAAE;gBACL,IAAI,EAAE,MAAM,CAAC;gBACb,MAAM,EAAE,MAAM,CAAC;aAChB,CAAC;SACH,CAAC;KACH,CAAC;IACF,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,WAAW,EAAE,gBAAgB,EAAE,CAAC;CACjC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpD,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC3B,EAAE,EAAE,QAAQ,CAAC;IACb,KAAK,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9B,MAAM,CAAC,EAAE;QACP,QAAQ,CAAC,EAAE,QAAQ,CAAC;QACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAChC,MAAM,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7B;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB,WAAW,EAAE,KAAK,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE;gBAAE,KAAK,EAAE;oBAAE,IAAI,EAAE,MAAM,CAAC;oBAAC,MAAM,EAAE,MAAM,CAAA;iBAAE,CAAA;aAAE,CAAC;SACpD,CAAC;QACF,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;KACxC,CAAC,CAAC;CACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wuyanbin/ai-code-review-cli-remote",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "AI Code Review remote client - sends diffs to AICR platform for review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,12 +8,12 @@
8
8
  "access": "public"
9
9
  },
10
10
  "bin": {
11
- "ai-code-review-cli-remote": "bin/ai-code-review-remote.js"
11
+ "ai-code-review-cli-remote": "dist/index.js"
12
12
  },
13
13
  "scripts": {
14
14
  "build": "tsc",
15
15
  "dev": "tsc --watch",
16
- "test": "bash test/run-tests.sh",
16
+ "test": "npx tsc -p tsconfig.test.json && node --test .tmp-test-build/test/*.test.js",
17
17
  "prepublishOnly": "npm run build"
18
18
  },
19
19
  "keywords": [
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const { reviewMain, summaryMain } = require("../dist/index");
4
-
5
- const isSummary = process.argv.includes("--summary");
6
- const run = isSummary ? summaryMain : reviewMain;
7
-
8
- run().catch((error) => {
9
- console.error("[ai-code-review-cli-remote] CLI 执行错误:", error);
10
- process.exit(1);
11
- });