Spaces:
Paused
Paused
| ; | |
| 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 |