Skip to content

Commit 003cd7a

Browse files
committed
optimize review result
1 parent 9cfc5a7 commit 003cd7a

2 files changed

Lines changed: 38 additions & 116 deletions

File tree

action/index.cjs

Lines changed: 32 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -150544,17 +150544,25 @@ const robot = (app) => {
150544150544
continue;
150545150545
}
150546150546
try {
150547-
// Split patch into individual hunks (by @@ markers)
150548-
const hunks = splitPatchIntoHunks(patch);
150549-
for (const hunk of hunks) {
150550-
const res = await chat?.codeReview(hunk.content);
150551-
if (!res.lgtm && !!res.review_comment) {
150552-
const { line, side } = computeLineAndSideFromPatch(hunk.content);
150547+
const res = await chat?.codeReview(patch);
150548+
// res can be a single review or an array of reviews (one for each hunk)
150549+
const reviews = Array.isArray(res) ? res : [res];
150550+
for (const review of reviews) {
150551+
if (!review.lgtm && !!review.review_comment) {
150552+
let line;
150553+
let side = 'RIGHT';
150554+
// Extract line number from hunk header if available
150555+
if (review.hunk_header) {
150556+
const hunkMatch = review.hunk_header.match(/@@\s+-\d+(?:,\d+)?\s+\+(\d+)(?:,(\d+))?\s+@@/);
150557+
if (hunkMatch) {
150558+
line = parseInt(hunkMatch[1], 10);
150559+
}
150560+
}
150553150561
ress.push({
150554150562
path: file.filename,
150555-
body: res.review_comment,
150556-
line: hunk.newStart + line - 1,
150557-
side,
150563+
body: review.review_comment,
150564+
line: line,
150565+
side: side,
150558150566
});
150559150567
}
150560150568
}
@@ -150601,109 +150609,6 @@ const matchPatterns = (patterns, path) => {
150601150609
}
150602150610
});
150603150611
};
150604-
const computeLineAndSideFromPatch = (patch) => {
150605-
// Returns first suitable line number and side for a review comment.
150606-
// Preference order: first added line ('+' -> RIGHT), then context (' ' -> RIGHT), then deletion ('-' -> LEFT).
150607-
if (!patch)
150608-
return { line: 1, side: 'RIGHT' };
150609-
const lines = patch.split('\n');
150610-
let currentOld = 0;
150611-
let currentNew = 0;
150612-
// helper to parse the hunk header like: @@ -oldStart,oldCount +newStart,newCount @@
150613-
const parseHunkHeader = (hdr) => {
150614-
const m = hdr.match(/@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@/);
150615-
if (!m)
150616-
return null;
150617-
const oldStart = parseInt(m[1], 10);
150618-
const newStart = parseInt(m[3], 10);
150619-
return { oldStart, newStart };
150620-
};
150621-
// track first matches
150622-
let firstAdded = null;
150623-
let firstContext = null;
150624-
let firstDeleted = null;
150625-
for (let i = 0; i < lines.length; i++) {
150626-
const line = lines[i];
150627-
if (line.startsWith('@@')) {
150628-
const parsed = parseHunkHeader(line);
150629-
if (parsed) {
150630-
currentOld = parsed.oldStart;
150631-
currentNew = parsed.newStart;
150632-
}
150633-
continue;
150634-
}
150635-
if (line.startsWith('+')) {
150636-
// addition: belongs to new file
150637-
if (firstAdded === null)
150638-
firstAdded = currentNew;
150639-
currentNew++;
150640-
continue;
150641-
}
150642-
if (line.startsWith('-')) {
150643-
// deletion: belongs to old file
150644-
if (firstDeleted === null)
150645-
firstDeleted = currentOld;
150646-
currentOld++;
150647-
continue;
150648-
}
150649-
// context line (starts with space or other)
150650-
if (line.startsWith(' ') || line.length === 0) {
150651-
if (firstContext === null)
150652-
firstContext = currentNew;
150653-
currentOld++;
150654-
currentNew++;
150655-
continue;
150656-
}
150657-
}
150658-
if (firstAdded !== null)
150659-
return { line: firstAdded, side: 'RIGHT' };
150660-
if (firstContext !== null)
150661-
return { line: firstContext, side: 'RIGHT' };
150662-
if (firstDeleted !== null)
150663-
return { line: firstDeleted, side: 'LEFT' };
150664-
return { line: 1, side: 'RIGHT' };
150665-
};
150666-
const splitPatchIntoHunks = (patch) => {
150667-
// Split patch into individual hunks by @@ markers
150668-
const hunks = [];
150669-
const lines = patch.split('\n');
150670-
let currentHunk = [];
150671-
let currentHeader = '';
150672-
let currentNewStart = 0;
150673-
const parseHunkHeader = (hdr) => {
150674-
const m = hdr.match(/@@\s+-\d+(?:,\d+)?\s+\+(\d+)(?:,\d+)?\s+@@/);
150675-
if (!m)
150676-
return 0;
150677-
return parseInt(m[1], 10);
150678-
};
150679-
for (const line of lines) {
150680-
if (line.startsWith('@@')) {
150681-
// Save previous hunk if it exists
150682-
if (currentHunk.length > 0) {
150683-
hunks.push({
150684-
header: currentHeader,
150685-
newStart: currentNewStart,
150686-
content: currentHunk.join('\n'),
150687-
});
150688-
}
150689-
currentHeader = line;
150690-
currentNewStart = parseHunkHeader(line);
150691-
currentHunk = [line];
150692-
}
150693-
else if (currentHunk.length > 0) {
150694-
currentHunk.push(line);
150695-
}
150696-
}
150697-
// Save the last hunk
150698-
if (currentHunk.length > 0) {
150699-
hunks.push({
150700-
header: currentHeader,
150701-
newStart: currentNewStart,
150702-
content: currentHunk.join('\n'),
150703-
});
150704-
}
150705-
return hunks;
150706-
};
150707150612

150708150613

150709150614
/***/ }),
@@ -150747,10 +150652,16 @@ class Chat {
150747150652
const userPrompt = process.env.PROMPT || 'Please review the following code patch. Focus on potential bugs, risks, and improvement suggestions.';
150748150653
const jsonFormatRequirement = '\nProvide your feedback in a strict JSON format with the following structure:\n' +
150749150654
'{\n' +
150750-
' "lgtm": boolean, // true if the code looks good to merge, false if there are concerns\n' +
150751-
' "review_comment": string // Your detailed review comments. You can use markdown syntax in this string, but the overall response must be a valid JSON\n' +
150655+
' "reviews": [\n' +
150656+
' {\n' +
150657+
' "hunk_header": string, // The @@ hunk header (e.g., "@@ -10,5 +10,7 @@"), optional\n' +
150658+
' "lgtm": boolean, // true if this hunk looks good, false if there are concerns\n' +
150659+
' "review_comment": string // Your detailed review comments for this hunk. Can use markdown syntax. Empty string if lgtm is true.\n' +
150660+
' }\n' +
150661+
' ]\n' +
150752150662
'}\n' +
150753-
'Ensure your response is a valid JSON object.\n';
150663+
'Review each hunk (marked by @@) separately and provide feedback for hunks that need improvement.\n' +
150664+
'Ensure your response is a valid JSON object with a reviews array.\n';
150754150665
return `${userPrompt}${jsonFormatRequirement} ${answerLanguage}:
150755150666
${patch}
150756150667
`;
@@ -150783,11 +150694,17 @@ class Chat {
150783150694
if (res.choices.length) {
150784150695
try {
150785150696
const json = JSON.parse(res.choices[0].message.content || "");
150697+
// If response has a 'reviews' array, return it directly
150698+
if (json.reviews && Array.isArray(json.reviews)) {
150699+
return json.reviews;
150700+
}
150701+
// Otherwise, treat as a single review response
150786150702
return json;
150787150703
}
150788150704
catch (e) {
150789150705
return {
150790150706
lgtm: false,
150707+
hunk_header: patch.split('\n')[0].startsWith('@@') ? patch.split('\n')[0] : undefined,
150791150708
review_comment: res.choices[0].message.content || ""
150792150709
};
150793150710
}

action/src/chat.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@ export declare class Chat {
44
private isGithubModels;
55
constructor(apikey: string);
66
private generatePrompt;
7-
codeReview: (patch: string) => Promise<{
7+
codeReview: (patch: string) => Promise<Array<{
88
lgtm: boolean;
99
review_comment: string;
10+
hunk_header?: string;
11+
}> | {
12+
lgtm: boolean;
13+
review_comment: string;
14+
hunk_header?: string;
1015
}>;
1116
}

0 commit comments

Comments
 (0)