PRIX / lib /src /review-comment.js
Rachit-Tw's picture
Upload 169 files
9284ad7 verified
Raw
History Blame Contribute Delete
7.92 kB
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.run = exports.handleReviewComment = exports.repo = exports.context = void 0;
// Removed @actions imports for Probot migration
const commenter_1 = require("./commenter");
const inputs_1 = require("./inputs");
const options_1 = require("./options");
const octokit_1 = require("./octokit");
const bot_1 = require("./bot");
const tokenizer_1 = require("./tokenizer");
const context_1 = require("./context");
const sanitizer_1 = require("./utils/sanitizer");
let info = console.log;
let warning = console.warn;
exports.context = new Proxy({}, {
get(target, prop) {
return (context_1.als.getStore()?.probotContext)[prop];
}
});
exports.repo = new Proxy({}, {
get(target, prop) {
return (context_1.als.getStore()?.repo)[prop];
}
});
const ASK_BOT = '@prix';
const handleReviewComment = async (heavyBot, options, prompts) => {
const commenter = new commenter_1.Commenter();
const inputs = new inputs_1.Inputs();
if (exports.context.name !== 'pull_request_review_comment') {
warning(`Skipped: ${exports.context.name} is not a pull_request_review_comment event`);
return;
}
if (!exports.context.payload) {
warning(`Skipped: ${exports.context.name} event is missing payload`);
return;
}
const comment = exports.context.payload.comment;
if (comment == null) {
warning(`Skipped: ${exports.context.name} event is missing comment`);
return;
}
if (exports.context.payload.pull_request == null ||
exports.context.payload.repository == null) {
warning(`Skipped: ${exports.context.name} event is missing pull_request`);
return;
}
inputs.title = exports.context.payload.pull_request.title;
if (exports.context.payload.pull_request.body) {
inputs.description = commenter.getDescription(exports.context.payload.pull_request.body);
}
// check if the comment was created and not edited or deleted
if (exports.context.payload.action !== 'created') {
warning(`Skipped: ${exports.context.name} event is not created`);
return;
}
// Check if the comment is not from the bot itself
if (!comment.body.includes(commenter_1.COMMENT_TAG) &&
!comment.body.includes(commenter_1.COMMENT_REPLY_TAG)) {
const pullNumber = exports.context.payload.pull_request.number;
// Sanitize user comment before using in prompts
inputs.comment = (0, sanitizer_1.sanitizePrompt)(`${comment.user.login}: ${comment.body}`);
inputs.diff = comment.diff_hunk;
inputs.filename = comment.path;
const { chain: commentChain, topLevelComment } = await commenter.getCommentChain(pullNumber, comment);
if (!topLevelComment) {
warning('Failed to find the top-level comment to reply to');
return;
}
inputs.commentChain = commentChain;
// check whether this chain contains replies from the bot
if (commentChain.includes(commenter_1.COMMENT_TAG) ||
commentChain.includes(commenter_1.COMMENT_REPLY_TAG) ||
comment.body.includes(ASK_BOT)) {
let fileDiff = '';
try {
// get diff for this file by comparing the base and head commits
const diffAll = await octokit_1.octokit.rest.repos.compareCommits({
owner: exports.repo.owner,
repo: exports.repo.repo,
base: exports.context.payload.pull_request.base.sha,
head: exports.context.payload.pull_request.head.sha
});
if (diffAll.data) {
const files = diffAll.data.files;
if (files != null) {
const file = files.find(f => f.filename === comment.path);
if (file != null && file.patch) {
fileDiff = file.patch;
}
}
}
}
catch (error) {
warning(`Failed to get file diff: ${error}, skipping.`);
}
// use file diff if no diff was found in the comment
if (inputs.diff.length === 0) {
if (fileDiff.length > 0) {
inputs.diff = fileDiff;
fileDiff = '';
}
else {
await commenter.reviewCommentReply(pullNumber, topLevelComment, 'Cannot reply to this comment as diff could not be found.');
return;
}
}
// get tokens so far
let tokens = (0, tokenizer_1.getTokenCount)(prompts.renderComment(inputs));
if (tokens > options.heavyTokenLimits.requestTokens) {
await commenter.reviewCommentReply(pullNumber, topLevelComment, 'Cannot reply to this comment as diff being commented is too large and exceeds the token limit.');
return;
}
// pack file diff into the inputs if they are not too long
if (fileDiff.length > 0) {
// count occurrences of $file_diff in prompt
const fileDiffCount = prompts.comment.split('$file_diff').length - 1;
const fileDiffTokens = (0, tokenizer_1.getTokenCount)(fileDiff);
if (fileDiffCount > 0 &&
tokens + fileDiffTokens * fileDiffCount <=
options.heavyTokenLimits.requestTokens) {
tokens += fileDiffTokens * fileDiffCount;
inputs.fileDiff = fileDiff;
}
}
// get summary of the PR
const summary = await commenter.findCommentWithTag(commenter_1.SUMMARIZE_TAG, pullNumber);
if (summary) {
// pack short summary into the inputs if it is not too long
const shortSummary = commenter.getShortSummary(summary.body);
const shortSummaryTokens = (0, tokenizer_1.getTokenCount)(shortSummary);
if (tokens + shortSummaryTokens <=
options.heavyTokenLimits.requestTokens) {
tokens += shortSummaryTokens;
inputs.shortSummary = shortSummary;
}
}
const [reply] = await heavyBot.chat(prompts.renderComment(inputs), {});
await commenter.reviewCommentReply(pullNumber, topLevelComment, reply);
}
}
else {
info(`Skipped: ${exports.context.name} event is from the bot itself`);
}
};
exports.handleReviewComment = handleReviewComment;
/**
* PRIX entry point for Review Comments (Chat with Bot).
* Adapts the action logic to Probot context.
*/
const run = async (probotContext, options, prompts) => {
// Setup logger shim
info = (msg) => probotContext.log.info(msg);
warning = (msg) => probotContext.log.warn(msg);
// context and repo are now handled via Proxy + AsyncLocalStorage
(0, commenter_1.setCommenterContext)(probotContext);
// Setup octokit shim
(0, octokit_1.setOctokit)(probotContext.octokit);
// Initialize heavy bot (used for comments)
const heavyAIOptions = new options_1.AIOptions(options.heavyModel, options.heavyTokenLimits);
const heavyBot = new bot_1.Bot(options, heavyAIOptions);
probotContext.log.info(`PRIX Chat starting for Comment in PR #${probotContext.payload.pull_request.number}`);
try {
await (0, exports.handleReviewComment)(heavyBot, options, prompts);
probotContext.log.info(`PRIX Chat completed for PR #${probotContext.payload.pull_request.number}`);
}
catch (err) {
probotContext.log.error(`PRIX Chat failed: ${err.message}`);
throw err;
}
};
exports.run = run;
//# sourceMappingURL=review-comment.js.map