@wuyanbin/ai-code-review-cli-remote 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/client.d.ts.map +1 -1
  2. package/dist/client.js +1 -45
  3. package/dist/client.js.map +1 -1
  4. package/dist/config.d.ts +11 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +147 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/constants.d.ts +2 -0
  9. package/dist/constants.d.ts.map +1 -1
  10. package/dist/constants.js +3 -1
  11. package/dist/constants.js.map +1 -1
  12. package/dist/diff.d.ts +6 -0
  13. package/dist/diff.d.ts.map +1 -0
  14. package/dist/diff.js +127 -0
  15. package/dist/diff.js.map +1 -0
  16. package/dist/formatters.d.ts +4 -0
  17. package/dist/formatters.d.ts.map +1 -0
  18. package/dist/formatters.js +30 -0
  19. package/dist/formatters.js.map +1 -0
  20. package/dist/gitlab.d.ts +7 -0
  21. package/dist/gitlab.d.ts.map +1 -0
  22. package/dist/gitlab.js +55 -0
  23. package/dist/gitlab.js.map +1 -0
  24. package/dist/index.js +15 -69
  25. package/dist/index.js.map +1 -1
  26. package/dist/model.d.ts +5 -0
  27. package/dist/model.d.ts.map +1 -0
  28. package/dist/model.js +80 -0
  29. package/dist/model.js.map +1 -0
  30. package/dist/report.d.ts +9 -0
  31. package/dist/report.d.ts.map +1 -0
  32. package/dist/report.js +30 -0
  33. package/dist/report.js.map +1 -0
  34. package/dist/reviewer.d.ts +3 -0
  35. package/dist/reviewer.d.ts.map +1 -0
  36. package/dist/reviewer.js +77 -0
  37. package/dist/reviewer.js.map +1 -0
  38. package/dist/runner.d.ts +5 -0
  39. package/dist/runner.d.ts.map +1 -0
  40. package/dist/runner.js +102 -0
  41. package/dist/runner.js.map +1 -0
  42. package/dist/summarizer.d.ts +3 -0
  43. package/dist/summarizer.d.ts.map +1 -0
  44. package/dist/summarizer.js +75 -0
  45. package/dist/summarizer.js.map +1 -0
  46. package/dist/types.d.ts +56 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +3 -0
  49. package/dist/types.js.map +1 -0
  50. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -2,76 +2,22 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
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
- }
5
+ const runner_1 = require("./runner");
60
6
  if (require.main === module) {
61
- if (!process.env[constants_1.ENV_PROJECT_TOKEN]) {
62
- console.error(`[${constants_1.TOOL_NAME}] 错误: ${constants_1.ENV_PROJECT_TOKEN} 未设置\n` +
63
- "该变量应在项目接入时由平台自动配置到 GitLab CI 变量中。\n" +
64
- "若需手动配置:登录 AICR 平台 -> 项目设置 -> Token 管理");
65
- process.exit(1);
66
- }
67
- if (!process.env[constants_1.ENV_PLATFORM_URL]) {
68
- console.error(`[${constants_1.TOOL_NAME}] 错误: ${constants_1.ENV_PLATFORM_URL} 未设置\n` +
69
- "该变量应在项目接入时由平台自动配置到 GitLab CI 变量中。");
70
- process.exit(1);
71
- }
72
- const platformUrl = process.env[constants_1.ENV_PLATFORM_URL];
73
- console.error(`[${constants_1.TOOL_NAME}] 平台地址: ${platformUrl}`);
74
- 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) => {
75
21
  console.error(`[${constants_1.TOOL_NAME}] 执行错误:`, error instanceof Error ? error.message : error);
76
22
  process.exit(1);
77
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":"AAQA,eAAO,MAAM,SAAS,QAAO,OAAO,CAAC,MAAM,CASvC,CAAC;AAML,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAmDhD;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,102 @@
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 gitlab_1 = require("./gitlab");
13
+ const promises_1 = require("node:fs/promises");
14
+ const readStdin = () => new Promise((resolve, reject) => {
15
+ let data = "";
16
+ process.stdin.setEncoding("utf8");
17
+ process.stdin.on("data", (chunk) => {
18
+ data += chunk;
19
+ });
20
+ process.stdin.on("end", () => resolve(data));
21
+ process.stdin.on("error", reject);
22
+ });
23
+ exports.readStdin = readStdin;
24
+ function currentMrIid() {
25
+ return process.env.CI_MERGE_REQUEST_IID;
26
+ }
27
+ async function reviewMain() {
28
+ const startedAt = Date.now();
29
+ const diff = await (0, exports.readStdin)();
30
+ console.error(`[runner] review start diffBytes=${Buffer.byteLength(diff)}`);
31
+ if (!diff.trim()) {
32
+ console.error("[runner] review skipped: empty diff");
33
+ console.log(JSON.stringify((0, formatters_1.buildEmptyRdjson)()));
34
+ return;
35
+ }
36
+ const config = await (0, config_1.loadReviewConfig)();
37
+ console.error(`[runner] config source=${config.source} model=${config.ai.model} summary=${config.summary?.enabled !== false}`);
38
+ if (!config.ai.apiKey) {
39
+ console.error("[ai-code-review] 未配置模型 API Key,输出空诊断");
40
+ console.log(JSON.stringify((0, formatters_1.buildEmptyRdjson)()));
41
+ await (0, report_1.postRunReport)({
42
+ status: "FAILED",
43
+ modelUsed: config.ai.model,
44
+ duration: Date.now() - startedAt,
45
+ mrIid: currentMrIid(),
46
+ });
47
+ return;
48
+ }
49
+ const result = await (0, reviewer_1.reviewCode)(diff, config);
50
+ if (!result) {
51
+ console.error("[runner] review failed: model returned no valid result");
52
+ console.log(JSON.stringify((0, formatters_1.buildEmptyRdjson)()));
53
+ await (0, report_1.postRunReport)({
54
+ status: "FAILED",
55
+ modelUsed: config.ai.model,
56
+ duration: Date.now() - startedAt,
57
+ mrIid: currentMrIid(),
58
+ });
59
+ return;
60
+ }
61
+ console.error(`[runner] review complete comments=${result.comments.length}`);
62
+ await (0, gitlab_1.postGitlabDiagnosticsNote)({
63
+ comments: result.comments,
64
+ token: config.gitlab?.token,
65
+ });
66
+ console.log(JSON.stringify((0, formatters_1.buildRdjson)(result.comments)));
67
+ await (0, report_1.postRunReport)({
68
+ status: "SUCCESS",
69
+ modelUsed: config.ai.model,
70
+ commentCount: result.comments.length,
71
+ duration: Date.now() - startedAt,
72
+ mrIid: currentMrIid(),
73
+ });
74
+ }
75
+ async function summaryMain() {
76
+ const diff = await (0, exports.readStdin)();
77
+ console.error(`[runner] summary start diffBytes=${Buffer.byteLength(diff)}`);
78
+ if (!diff.trim())
79
+ return;
80
+ const config = await (0, config_1.loadReviewConfig)();
81
+ console.error(`[runner] config source=${config.source} model=${config.ai.model} summary=${config.summary?.enabled !== false}`);
82
+ const markdown = await (0, summarizer_1.generateSummary)(diff, config);
83
+ console.error(markdown
84
+ ? `[runner] summary complete bytes=${Buffer.byteLength(markdown)}`
85
+ : "[runner] summary skipped or empty");
86
+ if (markdown)
87
+ console.log(markdown);
88
+ }
89
+ function shellSingleQuote(value) {
90
+ return `'${value.replace(/'/g, "'\\''")}'`;
91
+ }
92
+ async function writeReviewdogEnvMain(path) {
93
+ const config = await (0, config_1.loadReviewConfig)();
94
+ if (config.gitlab?.token) {
95
+ await (0, promises_1.writeFile)(path, `export REVIEWDOG_GITLAB_API_TOKEN=${shellSingleQuote(config.gitlab.token)}\n`, { mode: 0o600 });
96
+ console.error("[runner] reviewdog token env file written");
97
+ }
98
+ else {
99
+ console.error("[runner] reviewdog token missing in config");
100
+ }
101
+ }
102
+ //# 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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"}
@@ -0,0 +1,56 @@
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;
22
+ };
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[];
37
+ }
38
+ export interface RdjsonOutput {
39
+ source: {
40
+ name: string;
41
+ };
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
+ }>;
55
+ }
56
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
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/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}