"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