-
Notifications
You must be signed in to change notification settings - Fork 0
feat: testing anthropic version #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@claude review this PR |
1 similar comment
|
@claude review this PR |
|
Claude finished @gwilkes-rv's task —— View job I'll review this PR that transitions from OpenAI to Anthropic's Claude models.
PR SummaryThis PR implements a complete transition from OpenAI to Anthropic's Claude models for the Red Rover PR reviewer and summarizer. The changes include:
Code ReviewModel and API Integration
Token Handling and Limits
Configuration
Response Parsing
Potential Issues
Suggestions
Overall AssessmentThe PR represents a well-executed transition from OpenAI to Anthropic's Claude models. The code maintains the existing architecture while adapting to Claude's different API requirements. The changes are thorough and maintain compatibility with the existing GitHub integration workflow. The implementation is clean, follows good practices, and should provide a solid foundation for using Claude models going forward. |
|
🐶 RedRover 🐶 RedRover 🐶 RedRover 🐶 RedRover 🐶 RedRover 🐶 RedRover 🐶 RedRover 🐶 RedRover Currently reviewing new changes in this PR... Files selected (15)
Files ignored due to filter (4)
🐶 RedRover It looks like you’d like me to adopt that summary as “context7.” Could you clarify what you’d like me to do next with context7? For example: • Draft a PR description or release notes using that summary Let me know how I can help! |
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (4)
- LICENSE
- README.md
- package.json
- src/prompts.ts
Review comments generated (78)
- Review: 4
- LGTM: 74
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (3)
- LICENSE
- package-lock.json
- src/prompts.ts
Review comments generated (69)
- Review: 9
- LGTM: 60
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| if (Array.isArray(response.content) && response.content.length > 0) { | ||
| const textContent = response.content.find(item => item.type === 'text'); | ||
| if (textContent && 'text' in textContent) { | ||
| responseText = textContent.text; | ||
|
|
||
| // Trim leading and trailing whitespace | ||
| responseText = responseText.trim(); | ||
|
|
||
| // Check if the response starts with "reviews": | ||
| if (responseText.startsWith('"reviews":')) { | ||
| responseText = `{${responseText}`; | ||
| } | ||
|
|
||
| // Replace escaped newlines with actual newlines | ||
| responseText = responseText.replace(/\\u000a/g, '\n'); | ||
|
|
||
| try { | ||
| // Attempt to parse the JSON content | ||
| const parsedContent = JSON.parse(responseText); | ||
|
|
||
| // Ensure the structure is correct | ||
| if (!parsedContent.reviews) { | ||
| parsedContent.reviews = []; | ||
| } | ||
| if (typeof parsedContent.lgtm === 'undefined') { | ||
| parsedContent.lgtm = false; | ||
| } | ||
|
|
||
| responseText = JSON.stringify(parsedContent, null, 2); // Pretty print the JSON | ||
| } catch (parseError) { | ||
| warning(`Failed to parse response as JSON: ${parseError}`); | ||
| info(`Raw Response Text: ${responseText}`); | ||
| } | ||
| } else { | ||
| warning('No text content found in the response'); | ||
| } | ||
| } else { | ||
| warning(`Unexpected content structure in the response: ${JSON.stringify(response.content)}`); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The logic for parsing the Anthropic response assumes that the content array will always contain an object with a type of 'text' and a text property. However, if the API changes or returns a different structure, this could cause runtime errors. Consider adding more robust error handling or type checking to ensure that textContent.text exists and is a string before attempting to use it.
Additionally, forcibly wrapping the response in {} if it starts with "reviews": (line 103) may lead to invalid JSON if the response is not exactly as expected. This could cause parsing errors or incorrect data extraction. It's safer to validate the response format before attempting such string manipulations.
- if (responseText.startsWith('"reviews":')) {
- responseText = `{${responseText}`;
- }
+ if (responseText.startsWith('"reviews":')) {
+ responseText = `{${responseText}`;
+ // Optionally, check if responseText ends with '}' and add if missing
+ if (!responseText.trim().endsWith('}')) {
+ responseText = `${responseText}}`;
+ }
+ }| @@ -1,15 +1,18 @@ | |||
| # RedRover - An OpenAI ChatGPT-based PR reviewer and summarizer | |||
| <h1><img align="center" height="60" src="https://github.com/user-attachments/assets/84111c2e-fe44-4de1-b82d-45f38199724a"> Red Rover</h1> | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The image link in the <img> tag appears to be broken or points to a user-attachments path that may not be accessible to all users. Consider hosting the image in a public location or using a valid image URL to ensure the logo renders correctly for all users.
-<h1><img align="center" height="60" src="https://github.com/user-attachments/assets/84111c2e-fe44-4de1-b82d-45f38199724a"> Red Rover</h1>
+<h1><img align="center" height="60" src="https://github.com/RedVentures/red-rover/assets/64108082/9ee5df3f-bc3f-4bfc-878e-171d7ccca96e"> Red Rover</h1>|
|
||
| constructor(model = 'gpt-4o-mini') { | ||
| this.knowledgeCutOff = '2021-09-01' | ||
| if (model === 'gpt-4-32k') { | ||
| this.maxTokens = 32600 | ||
| constructor(model = 'anthropic.claude-instant-v1') { | ||
| if (model === 'anthropic.claude-instant-v1') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 4000 | ||
| } else if (model === 'gpt-3.5-turbo-16k') { | ||
| this.maxTokens = 16300 | ||
| } else if (model === 'anthropic.claude-v2') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 3000 | ||
| } else if (model === 'gpt-4') { | ||
| this.maxTokens = 8192 | ||
| this.responseTokens = 8192 | ||
| } else if (model === 'gpt-4o') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 4096 | ||
| } else if (model === 'o1-mini') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 65536 | ||
| } else if (model === 'o1-preview') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 32768 | ||
| } else { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 16384 | ||
| // The latest models usually have this level of limits. | ||
| this.maxTokens = 200_000 | ||
| this.responseTokens = 4096 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The indentation is inconsistent on lines 9 and 12. The assignment to this.responseTokens is indented one space further than the surrounding code. This could reduce code readability and should be fixed.
- this.responseTokens = 4000
+ this.responseTokens = 4000- this.responseTokens = 3000
+ this.responseTokens = 3000| // eslint-disable-next-line no-unused-vars | ||
| patches: Array<[number, number, string]> | ||
| ): Review[] { | ||
| const reviews: Review[] = [] | ||
|
|
||
| response = sanitizeResponse(response.trim()) | ||
|
|
||
| const lines = response.split('\n') | ||
| const lineNumberRangeRegex = /(?:^|\s)(\d+)-(\d+):\s*$/ | ||
| const commentSeparator = '---' | ||
|
|
||
| let currentStartLine: number | null = null | ||
| let currentEndLine: number | null = null | ||
| let currentComment = '' | ||
| function storeReview(): void { | ||
| if (currentStartLine !== null && currentEndLine !== null) { | ||
| const review: Review = { | ||
| startLine: currentStartLine, | ||
| endLine: currentEndLine, | ||
| comment: currentComment | ||
| } | ||
|
|
||
| let withinPatch = false | ||
| let bestPatchStartLine = -1 | ||
| let bestPatchEndLine = -1 | ||
| let maxIntersection = 0 | ||
|
|
||
| for (const [startLine, endLine] of patches) { | ||
| const intersectionStart = Math.max(review.startLine, startLine) | ||
| const intersectionEnd = Math.min(review.endLine, endLine) | ||
| const intersectionLength = Math.max( | ||
| 0, | ||
| intersectionEnd - intersectionStart + 1 | ||
| ) | ||
|
|
||
| if (intersectionLength > maxIntersection) { | ||
| maxIntersection = intersectionLength | ||
| bestPatchStartLine = startLine | ||
| bestPatchEndLine = endLine | ||
| withinPatch = | ||
| intersectionLength === review.endLine - review.startLine + 1 | ||
| } | ||
|
|
||
| if (withinPatch) break | ||
| } | ||
|
|
||
| if (!withinPatch) { | ||
| if (bestPatchStartLine !== -1 && bestPatchEndLine !== -1) { | ||
| review.comment = `> Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [${review.startLine}-${review.endLine}] | ||
|
|
||
| ${review.comment}` | ||
| review.startLine = bestPatchStartLine | ||
| review.endLine = bestPatchEndLine | ||
| } else { | ||
| review.comment = `> Note: This review was outside of the patch, but no patch was found that overlapped with it. Original lines [${review.startLine}-${review.endLine}] | ||
|
|
||
| ${review.comment}` | ||
| review.startLine = patches[0][0] | ||
| review.endLine = patches[0][1] | ||
| } | ||
| try { | ||
| const rawReviews = JSON.parse(response).reviews | ||
| for (const r of rawReviews) { | ||
| if (r.comment) { | ||
| reviews.push({ | ||
| startLine: r.line_start ?? 0, | ||
| endLine: r.line_end ?? 0, | ||
| comment: r.comment | ||
| }) | ||
| } | ||
|
|
||
| reviews.push(review) | ||
|
|
||
| info( | ||
| `Stored comment for line range ${currentStartLine}-${currentEndLine}: ${currentComment.trim()}` | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| function sanitizeCodeBlock(comment: string, codeBlockLabel: string): string { | ||
| const codeBlockStart = `\`\`\`${codeBlockLabel}` | ||
| const codeBlockEnd = '```' | ||
| const lineNumberRegex = /^ *(\d+): /gm | ||
|
|
||
| let codeBlockStartIndex = comment.indexOf(codeBlockStart) | ||
|
|
||
| while (codeBlockStartIndex !== -1) { | ||
| const codeBlockEndIndex = comment.indexOf( | ||
| codeBlockEnd, | ||
| codeBlockStartIndex + codeBlockStart.length | ||
| ) | ||
|
|
||
| if (codeBlockEndIndex === -1) break | ||
|
|
||
| const codeBlock = comment.substring( | ||
| codeBlockStartIndex + codeBlockStart.length, | ||
| codeBlockEndIndex | ||
| ) | ||
| const sanitizedBlock = codeBlock.replace(lineNumberRegex, '') | ||
|
|
||
| comment = | ||
| comment.slice(0, codeBlockStartIndex + codeBlockStart.length) + | ||
| sanitizedBlock + | ||
| comment.slice(codeBlockEndIndex) | ||
|
|
||
| codeBlockStartIndex = comment.indexOf( | ||
| codeBlockStart, | ||
| codeBlockStartIndex + | ||
| codeBlockStart.length + | ||
| sanitizedBlock.length + | ||
| codeBlockEnd.length | ||
| ) | ||
| } | ||
|
|
||
| return comment | ||
| } | ||
|
|
||
| function sanitizeResponse(comment: string): string { | ||
| comment = sanitizeCodeBlock(comment, 'suggestion') | ||
| comment = sanitizeCodeBlock(comment, 'diff') | ||
| return comment | ||
| } | ||
|
|
||
| for (const line of lines) { | ||
| const lineNumberRangeMatch = line.match(lineNumberRangeRegex) | ||
|
|
||
| if (lineNumberRangeMatch != null) { | ||
| storeReview() | ||
| currentStartLine = parseInt(lineNumberRangeMatch[1], 10) | ||
| currentEndLine = parseInt(lineNumberRangeMatch[2], 10) | ||
| currentComment = '' | ||
| if (debug) { | ||
| info(`Found line number range: ${currentStartLine}-${currentEndLine}`) | ||
| } | ||
| continue | ||
| } | ||
|
|
||
| if (line.trim() === commentSeparator) { | ||
| storeReview() | ||
| currentStartLine = null | ||
| currentEndLine = null | ||
| currentComment = '' | ||
| if (debug) { | ||
| info('Found comment separator') | ||
| } | ||
| continue | ||
| } | ||
|
|
||
| if (currentStartLine !== null && currentEndLine !== null) { | ||
| currentComment += `${line}\n` | ||
| } | ||
| } catch (e: any) { | ||
| error(e.message) | ||
| return [] | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
If the Anthropic API ever returns a response that is not valid JSON or does not contain a reviews array, this will throw and silently return an empty array. Consider adding a check to ensure rawReviews is an array before iterating, and provide a more descriptive error message for easier debugging.
- const rawReviews = JSON.parse(response).reviews
- for (const r of rawReviews) {
- if (r.comment) {
- reviews.push({
- startLine: r.line_start ?? 0,
- endLine: r.line_end ?? 0,
- comment: r.comment
- })
- }
- }
+ const parsed = JSON.parse(response)
+ const rawReviews = Array.isArray(parsed.reviews) ? parsed.reviews : []
+ for (const r of rawReviews) {
+ if (r.comment) {
+ reviews.push({
+ startLine: r.line_start ?? 0,
+ endLine: r.line_end ?? 0,
+ comment: r.comment
+ })
+ }
+ }
+ if (!Array.isArray(parsed.reviews)) {
+ error('Anthropic response did not contain a "reviews" array.')
+ }
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files not reviewed due to errors (10)
- src/bot.ts (no response)
- .github/workflows/redrover_review.yml (no response)
- src/commenter.ts (no response)
- src/inputs.ts (no response)
- src/limits.ts (no response)
- action.yml (no response)
- src/main.ts (no response)
- src/options.ts (no response)
- src/review-comment.ts (no response)
- src/review.ts (no response)
Files skipped from review due to trivial changes (5)
- LICENSE
- README.md
- package-lock.json
- package.json
- src/prompts.ts
Review comments generated (0)
- Review: 0
- LGTM: 0
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (4)
- LICENSE
- package-lock.json
- package.json
- src/prompts.ts
Review comments generated (56)
- Review: 31
- LGTM: 25
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| async composeCommentChain(reviewComments: any[], topLevelComment: any) { | ||
| const conversationChain = reviewComments | ||
| .filter((cmt: any) => cmt.in_reply_to_id === topLevelComment.id) | ||
| .map((cmt: any) => `${cmt.user.login}: ${cmt.body}`) | ||
| .map((cmt: any) => `${this.getRole(cmt.user.login)} ${cmt.body}`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Indentation is inconsistent. Align the async composeCommentChain signature and its chained calls with the rest of the class (2 spaces), and make sure .map lines up under .filter:
- async composeCommentChain(reviewComments: any[], topLevelComment: any) {
+ async composeCommentChain(reviewComments: any[], topLevelComment: any) {
const conversationChain = reviewComments
- .filter((cmt: any) => cmt.in_reply_to_id === topLevelComment.id)
- .map((cmt: any) => `${this.getRole(cmt.user.login)} ${cmt.body}`)
+ .filter((cmt: any) => cmt.in_reply_to_id === topLevelComment.id)
+ .map((cmt: any) => `${this.getRole(cmt.user.login)} ${cmt.body}`)| ) | ||
|
|
||
| return conversationChain.join('\n---\n') | ||
| return `${conversationChain.join('\n')}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
No need for a template literal when directly returning the joined string. Simplify to:
- return `${conversationChain.join('\n')}`
+ return conversationChain.join('\n')| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Environment variables are inconsistently indented under env:. Align both keys at the same level:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}| debug: true | ||
| poem_enabled: true | ||
| less_verbose_review: false | ||
| review_comment_lgtm: false | ||
| openai_heavy_model: gpt-4 | ||
| path_filters: | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Keys under with: have mismatched indentation. Align them consistently:
- debug: true
- poem_enabled: true
- less_verbose_review: false
- review_comment_lgtm: false
- path_filters: |
+ debug: true
+ poem_enabled: true
+ less_verbose_review: false
+ review_comment_lgtm: false
+ path_filters: || !dist/** | ||
| !**/*.lock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
List items under path_filters: need to be indented uniformly two spaces deeper than the pipe:
- !dist/**
- !**/*.lock
+ !dist/**
+ !**/*.lock| if (options.maxFiles <= 0 || summaryPromises.length < options.maxFiles) { | ||
| summaryPromises.push( | ||
| openaiConcurrencyLimit( | ||
| anthropicConcurrencyLimit( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Remove one extra space before anthropicConcurrencyLimit( so it nests correctly under summaryPromises.push(:
- anthropicConcurrencyLimit(
+ anthropicConcurrencyLimit(| // ask Anthropic to summarize the summaries | ||
| const [summarizeResp] = await heavyBot.chat( | ||
| prompts.renderSummarizeChangesets(inputs), | ||
| {} | ||
| prompts.renderSummarizeChangesets(inputs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
These lines are indented one space too far. They should align with the other heavyBot.chat calls:
- // ask Anthropic to summarize the summaries
+ // ask Anthropic to summarize the summaries
- const [summarizeResp] = await heavyBot.chat(
+ const [summarizeResp] = await heavyBot.chat(
- prompts.renderSummarizeChangesets(inputs)
+ prompts.renderSummarizeChangesets(inputs)| const [summarizeFinalResponse] = await heavyBot.chat( | ||
| prompts.renderSummarize(inputs), | ||
| {} | ||
| prompts.renderSummarize(inputs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Adjust indentation to match the surrounding chat call:
- prompts.renderSummarize(inputs)
+ prompts.renderSummarize(inputs)| const [releaseNotesResponse] = await heavyBot.chat( | ||
| prompts.renderSummarizeReleaseNotes(inputs), | ||
| {} | ||
| prompts.renderSummarizeReleaseNotes(inputs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Drop one space so the argument lines line up under heavyBot.chat(:
- prompts.renderSummarizeReleaseNotes(inputs)
+ prompts.renderSummarizeReleaseNotes(inputs)| const [summarizeShortResponse] = await heavyBot.chat( | ||
| prompts.renderSummarizeShort(inputs), | ||
| {} | ||
| prompts.renderSummarizeShort(inputs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Align this line with the other chat arguments by removing one leading space:
- prompts.renderSummarizeShort(inputs)
+ prompts.renderSummarizeShort(inputs)
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (2)
- LICENSE
- src/prompts.ts
Review comments generated (85)
- Review: 13
- LGTM: 72
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| default: 'claude-3-5-sonnet-latest' | ||
| anthropic_model_temperature: | ||
| required: false | ||
| description: 'Temperature for GPT model' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The description references “GPT model” but should refer to the Anthropic/Claude model for clarity.
- description: 'Temperature for GPT model'
+ description: 'Temperature for Anthropic model'| } | ||
|
|
||
| getRole(login: string) { | ||
| if (login === SELF_LOGIN) return '\nA (You): ' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The returned string for the bot role has a trailing space, which combined with the template’s extra space causes two spaces before the comment body. Remove the extra space inside the string literal:
- if (login === SELF_LOGIN) return '\nA (You): '
+ if (login === SELF_LOGIN) return '\nA (You):'| }; | ||
| response = await pRetry( | ||
| () => | ||
| this.client.messages.create(params), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The Anthropic SDK v0.29.0 does not expose client.messages.create. Use the chat completions endpoint instead and correct parameter names:
- this.client.messages.create(params),
+ this.client.chat.completions.create({
+ model: params.model,
+ messages: params.messages,
+ max_tokens_to_sample: params.max_tokens,
+ }),| if (tokenLimits != null) { | ||
| this.tokenLimits = tokenLimits |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The tokenLimits property is only assigned when tokenLimits is non-null, leaving it undefined otherwise. You should default it (e.g., to new TokenLimits(this.model)) to ensure it's always initialized:
- if (tokenLimits != null) {
- this.tokenLimits = tokenLimits
+ if (tokenLimits != null) {
+ this.tokenLimits = tokenLimits
+ } else {
+ this.tokenLimits = new TokenLimits(this.model)
+ }| prompts.renderReviewFileDiff(ins), | ||
| {} | ||
| '{' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The second argument to heavyBot.chat is incorrect; passing a string '{ instead of an options object. It should only receive the prompt call without a trailing comma or extra argument.
- prompts.renderReviewFileDiff(ins),
- '{'
+ prompts.renderReviewFileDiff(ins)| // eslint-disable-next-line no-unused-vars | ||
| patches: Array<[number, number, string]> | ||
| ): Review[] { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The patches parameter is no longer used due to removal of mapping logic, which may cause comments outside patch ranges to be posted incorrectly. Consider reintroducing logic to map or validate review line ranges against the original patches.
| review.endLine = patches[0][1] | ||
| } | ||
| try { | ||
| const rawReviews = JSON.parse(response).reviews |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Relying solely on JSON.parse(response).reviews assumes the model always returns valid JSON with a reviews field. If the response deviates, parsing will fail silently, returning an empty array. Consider adding sanitization or fallback handling for non-JSON outputs.
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (4)
- LICENSE
- README.md
- package-lock.json
- src/prompts.ts
Review comments generated (44)
- Review: 8
- LGTM: 36
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| if (this.reviewFileDiff) { | ||
| content = content.replace('$review_file_diff', this.reviewFileDiff) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The conditional replacement may leave the $review_file_diff placeholder in the content when reviewFileDiff is empty. It’s safer to always replace it, even if the value is an empty string.
- if (this.reviewFileDiff) {
- content = content.replace('$review_file_diff', this.reviewFileDiff)
- }
+ content = content.replace('$review_file_diff', this.reviewFileDiff)| getRole(login: string) { | ||
| if (login === SELF_LOGIN) return '\nA (You): ' | ||
| return `\nH (@${login}):` | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The leading \n in each role string will introduce extra blank lines when building the conversation. It’s clearer to return the role without a newline and rely on the join for line breaks:
@@ 496-499
- getRole(login: string) {
- if (login === SELF_LOGIN) return '\nA (You): '
- return `\nH (@${login}):`
- }
+ getRole(login: string) {
+ if (login === SELF_LOGIN) return 'A (You):'
+ return `H (@${login}):`
+ }| bot_icon: | ||
| required: false | ||
| description: 'The icon for Red Rover' | ||
| default: 🐶 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The emoji default value should be quoted to ensure valid YAML.
- default: 🐶
+ default: '🐶'| throw new Error(err) | ||
| } | ||
| this.anthropicOptions = anthropicOptions | ||
| this.client = new Anthropic(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The Anthropic client needs your API key to authenticate. You should pass it in the constructor instead of calling new Anthropic() with no arguments.
- this.client = new Anthropic();
+ this.client = new Anthropic({ apiKey: this.anthropicOptions.apiKey });| getInput('openai_retries'), | ||
| getInput('openai_timeout_ms'), | ||
| getInput('openai_concurrency_limit'), | ||
| getInput('review_file_diff'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The input review_file_diff appears to be a boolean flag. Consider using getBooleanInput to correctly parse it as a boolean:
- getInput('review_file_diff'),
+ getBooleanInput('review_file_diff'),| const [response] = await heavyBot.chat( | ||
| prompts.renderReviewFileDiff(ins), | ||
| {} | ||
| '{' | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The second argument '{’ passed to heavyBot.chat is incorrect. Remove it so that only the prompt is passed to chat.
- const [response] = await heavyBot.chat(
- prompts.renderReviewFileDiff(ins),
- '{'
- )
+ const [response] = await heavyBot.chat(
+ prompts.renderReviewFileDiff(ins)
+ )
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files not summarized due to errors (15)
- action.yml (nothing fetched from RedRover)
- README.md (nothing fetched from RedRover)
- package.json (nothing fetched from RedRover)
- package-lock.json (nothing fetched from RedRover)
- .github/workflows/redrover_review.yml (nothing fetched from RedRover)
- LICENSE (nothing fetched from RedRover)
- src/commenter.ts (nothing fetched from RedRover)
- src/inputs.ts (nothing fetched from RedRover)
- src/bot.ts (nothing fetched from RedRover)
- src/main.ts (nothing fetched from RedRover)
- src/limits.ts (nothing fetched from RedRover)
- src/options.ts (nothing fetched from RedRover)
- src/prompts.ts (nothing fetched from RedRover)
- src/review-comment.ts (nothing fetched from RedRover)
- src/review.ts (nothing fetched from RedRover)
Review comments generated (92)
- Review: 9
- LGTM: 83
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| constructor(model = 'anthropic.claude-instant-v1') { | ||
| if (model === 'anthropic.claude-instant-v1') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 4000 | ||
| } else if (model === 'gpt-3.5-turbo-16k') { | ||
| this.maxTokens = 16300 | ||
| } else if (model === 'anthropic.claude-v2') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 3000 | ||
| } else if (model === 'gpt-4') { | ||
| this.maxTokens = 8192 | ||
| this.responseTokens = 8192 | ||
| } else if (model === 'gpt-4o') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 4096 | ||
| } else if (model === 'o1-mini') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 65536 | ||
| } else if (model === 'o1-preview') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 32768 | ||
| } else { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 16384 | ||
| // The latest models usually have this level of limits. | ||
| this.maxTokens = 200_000 | ||
| this.responseTokens = 4096 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The model string comparisons use incorrect model identifiers for Anthropic's Claude models. The correct model names should be claude-instant-1.2 and claude-2.1 (or similar versioned names), not the AWS Bedrock format.
- constructor(model = 'anthropic.claude-instant-v1') {
- if (model === 'anthropic.claude-instant-v1') {
+ constructor(model = 'claude-instant-1.2') {
+ if (model === 'claude-instant-1.2') {
this.maxTokens = 100_000
this.responseTokens = 4000
- } else if (model === 'anthropic.claude-v2') {
+ } else if (model === 'claude-2.1') {
this.maxTokens = 100_000
this.responseTokens = 3000
} else {| reviewFileDiff = '', | ||
| anthropicLightModel: string, | ||
| anthropicHeavyModel: string, | ||
| anthropicModelTemperature = '0.0', | ||
| anthropicRetries = '3', | ||
| anthropicTimeoutMS = '120000', | ||
| anthropicConcurrencyLimit = '6', | ||
| githubConcurrencyLimit = '6', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The constructor parameters for anthropicLightModel and anthropicHeavyModel are missing default values, which could cause runtime errors if these parameters are not provided.
- anthropicLightModel: string,
- anthropicHeavyModel: string,
+ anthropicLightModel = 'claude-instant-v1',
+ anthropicHeavyModel = 'claude-v2',| 24: | ||
| 24: def multiply(x, y): | ||
| 25: return x * y |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
There's a duplicate line number in the example input.
- 24:
- 24: def multiply(x, y):
+ 23:
+ 24: def multiply(x, y):| Here is the diff that is now comment on. | ||
|
|
||
| \`\`\`diff | ||
| <partial_diff> | ||
| $diff | ||
| \`\`\` | ||
| <partial_diff> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
There's malformed XML with inconsistent closing tags in the partial_diff section.
- <partial_diff>
- no diff
- <partial_diff>
+ <partial_diff>
+ no diff
+ </partial_diff>| <comment_chains> | ||
| \`\`\` | ||
| ${commentChain} | ||
| \`\`\` | ||
| </comment_chains> | ||
| ` | ||
| } | ||
|
|
||
| ins.patches += ` | ||
| ---end_change_section--- | ||
| ` | ||
| } | ||
|
|
||
| if (patchesPacked > 0) { | ||
| // perform review | ||
| try { | ||
| const [response] = await heavyBot.chat( | ||
| prompts.renderReviewFileDiff(ins), | ||
| {} | ||
| '{' | ||
| ) | ||
| if (response === '') { | ||
| info('review: nothing obtained from openai') | ||
| info('review: nothing obtained from anthropic') | ||
| reviewsFailed.push(`${filename} (no response)`) | ||
| return | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The heavyBot.chat() call is missing proper error handling for the JSON parsing that occurs in parseReview(). If the response is malformed JSON, this will cause the review to fail silently.
const [response] = await heavyBot.chat(
prompts.renderReviewFileDiff(ins),
'{'
)
if (response === '') {
info('review: nothing obtained from anthropic')
reviewsFailed.push(`${filename} (no response)`)
return
}
+ if (!response.startsWith('{')) {
+ warning(`Invalid JSON response from Anthropic for ${filename}`)
+ reviewsFailed.push(`${filename} (invalid response format)`)
+ return
+ }
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files not summarized due to errors (15)
- LICENSE (nothing fetched from RedRover)
- package.json (nothing fetched from RedRover)
- action.yml (nothing fetched from RedRover)
- package-lock.json (nothing fetched from RedRover)
- README.md (nothing fetched from RedRover)
- .github/workflows/redrover_review.yml (nothing fetched from RedRover)
- src/bot.ts (nothing fetched from RedRover)
- src/commenter.ts (nothing fetched from RedRover)
- src/limits.ts (nothing fetched from RedRover)
- src/inputs.ts (nothing fetched from RedRover)
- src/main.ts (nothing fetched from RedRover)
- src/options.ts (nothing fetched from RedRover)
- src/prompts.ts (nothing fetched from RedRover)
- src/review-comment.ts (nothing fetched from RedRover)
- src/review.ts (nothing fetched from RedRover)
Review comments generated (100)
- Review: 12
- LGTM: 88
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| constructor(model = 'anthropic.claude-instant-v1') { | ||
| if (model === 'anthropic.claude-instant-v1') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 4000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
There's inconsistent indentation in the responseTokens assignment.
- this.responseTokens = 4000
+ this.responseTokens = 4000| this.maxTokens = 16300 | ||
| } else if (model === 'anthropic.claude-v2') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 3000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
There's inconsistent indentation in the responseTokens assignment.
- this.responseTokens = 3000
+ this.responseTokens = 3000| } else if (model === 'o1-preview') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 32768 | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
There's inconsistent indentation in the else clause.
- } else {
+ } else {| chat = async (message: string, prefix?: string): Promise<[string, Ids]> => { | ||
| let res: [string, Ids] = ['', {}] | ||
| try { | ||
| res = await this.chat_(message, ids) | ||
| res = await this.chat_(message, prefix) | ||
| return res | ||
| } catch (e: unknown) { | ||
| if (e instanceof ChatGPTError) { | ||
| warning(`Failed to chat: ${e}, backtrace: ${e.stack}`) | ||
| } | ||
| warning(`Failed to chat: ${e}`) | ||
| return res | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The method signature changed from accepting ids: Ids to prefix?: string but the return type still includes Ids. This inconsistency could break existing callers.
| let responseText = '' | ||
| const newIds: Ids = {}; | ||
|
|
||
| if (response != null) { | ||
| responseText = response.text | ||
| info(`Response type: ${typeof response}`); | ||
| info(`Response keys: ${Object.keys(response).join(', ')}`); | ||
|
|
||
| if (Array.isArray(response.content) && response.content.length > 0) { | ||
| const textContent = response.content.find(item => item.type === 'text'); | ||
| if (textContent && 'text' in textContent) { | ||
| responseText = textContent.text; | ||
|
|
||
| // Trim leading and trailing whitespace | ||
| responseText = responseText.trim(); | ||
|
|
||
| // Check if the response starts with "reviews": | ||
| if (responseText.startsWith('"reviews":')) { | ||
| responseText = `{${responseText}`; | ||
| } | ||
|
|
||
| // Replace escaped newlines with actual newlines | ||
| responseText = responseText.replace(/\\u000a/g, '\n'); | ||
|
|
||
| try { | ||
| // Attempt to parse the JSON content | ||
| const parsedContent = JSON.parse(responseText); | ||
|
|
||
| // Ensure the structure is correct | ||
| if (!parsedContent.reviews) { | ||
| parsedContent.reviews = []; | ||
| } | ||
| if (typeof parsedContent.lgtm === 'undefined') { | ||
| parsedContent.lgtm = false; | ||
| } | ||
|
|
||
| responseText = JSON.stringify(parsedContent, null, 2); // Pretty print the JSON | ||
| } catch (parseError) { | ||
| warning(`Failed to parse response as JSON: ${parseError}`); | ||
| info(`Raw Response Text: ${responseText}`); | ||
| } | ||
| } else { | ||
| warning('No text content found in the response'); | ||
| } | ||
| } else { | ||
| warning(`Unexpected content structure in the response: ${JSON.stringify(response.content)}`); | ||
| } | ||
|
|
||
| newIds.parentMessageId = response.id; | ||
| } else { | ||
| warning('openai response is null') | ||
| } | ||
| // remove the prefix "with " in the response | ||
| if (responseText.startsWith('with ')) { | ||
| responseText = responseText.substring(5) | ||
| warning('Anthropic response is null'); | ||
| } | ||
|
|
||
| if (this.options.debug) { | ||
| info(`openai responses: ${responseText}`) | ||
| } | ||
| const newIds: Ids = { | ||
| parentMessageId: response?.id, | ||
| conversationId: response?.conversationId | ||
| info(`Anthropic response text: ${responseText}\n-----------`); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The JSON parsing logic assumes the response will always be in a specific format and attempts to fix malformed JSON by prepending {. This could mask actual API response issues and create unpredictable behavior.
- // Check if the response starts with "reviews":
- if (responseText.startsWith('"reviews":')) {
- responseText = `{${responseText}`;
- }| comment = ` | ||
| $system_message | ||
|
|
||
| ## GitHub PR Title | ||
| A comment was made on a GitHub PR review for a diff hunk on a file - \`$filename\`. I would like you to follow the instructions in that comment. | ||
|
|
||
| \`$title\` | ||
| <pull_request_title> | ||
| $title | ||
| </pull_request_title> | ||
|
|
||
| ## Description | ||
|
|
||
| \`\`\` | ||
| <pull_request_description> | ||
| $description | ||
| \`\`\` | ||
| </pull_request_description> | ||
|
|
||
| ## Summary generated by the AI bot | ||
|
|
||
| \`\`\` | ||
| <short_summary> | ||
| $short_summary | ||
| \`\`\` | ||
|
|
||
| ## Entire diff | ||
| </short_summary> | ||
|
|
||
| \`\`\`diff | ||
| <entire_diff> | ||
| $file_diff | ||
| \`\`\` | ||
| </entire_diff> | ||
|
|
||
| ## Diff being commented on | ||
| Here is the diff that is now comment on. | ||
|
|
||
| \`\`\`diff | ||
| <partial_diff> | ||
| $diff | ||
| \`\`\` | ||
| <partial_diff> | ||
|
|
||
| ## Instructions | ||
|
|
||
| Please reply directly to the new comment (instead of suggesting | ||
| a reply) and your reply will be posted as-is. | ||
| Please reply directly to the new comment (instead of suggesting a reply) and your reply will be posted as-is. | ||
|
|
||
| If the comment contains instructions/requests for you, please comply. | ||
| For example, if the comment is asking you to generate documentation | ||
| comments on the code, in your reply please generate the required code. | ||
|
|
||
| In your reply, please make sure to begin the reply by tagging the user | ||
| with "@user". | ||
| For example, if the comment is asking you to generate documentation comments on the code, in your reply please generate the required code. | ||
|
|
||
| ## Comment format | ||
| In your reply, please make sure to begin the reply by tagging the user with "@user". | ||
|
|
||
| \`user: comment\` | ||
| <example> | ||
| @username You are right. Thanks for the explanation! | ||
| </example> | ||
|
|
||
| ## Comment chain (including the new comment) | ||
| Here is the comment history YOU and the users had. Note that H=human and A=you(assistant). | ||
|
|
||
| \`\`\` | ||
| <history> | ||
| $comment_chain | ||
| \`\`\` | ||
|
|
||
| ## The comment/request that you need to directly reply to | ||
| </history> | ||
|
|
||
| \`\`\` | ||
| This is the comment/request that you need to directly reply to | ||
| <comment> | ||
| $comment | ||
| \`\`\` | ||
| </comment> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
There's an incomplete tag in the partial_diff section that will cause XML parsing issues.
- <partial_diff>
- no diff
- <partial_diff>
+ <partial_diff>
+ no diff
+ </partial_diff>| anthropicLightModel: string, | ||
| anthropicHeavyModel: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The parameter type definitions for anthropicLightModel and anthropicHeavyModel are missing. These parameters lack type annotations while other string parameters have them.
- anthropicLightModel: string,
- anthropicHeavyModel: string,
+ anthropicLightModel = 'claude-instant-1.2',
+ anthropicHeavyModel = 'claude-2.1',| "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==" | ||
| }, | ||
| "node_modules/@types/normalize-package-data": { | ||
| "version": "2.4.1", | ||
| "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", | ||
| "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", | ||
| "dev": true | ||
| "node_modules/@types/node-fetch": { | ||
| "version": "2.6.11", | ||
| "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", | ||
| "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", | ||
| "dependencies": { | ||
| "@types/node": "*", | ||
| "form-data": "^4.0.0" | ||
| } | ||
| }, | ||
| "node_modules/@types/node-fetch/node_modules/form-data": { | ||
| "version": "4.0.1", | ||
| "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", | ||
| "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", | ||
| "dependencies": { | ||
| "asynckit": "^0.4.0", | ||
| "combined-stream": "^1.0.8", | ||
| "mime-types": "^2.1.12" | ||
| }, | ||
| "engines": { | ||
| "node": ">= 6" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
There's an issue with the dev dependency flag for @types/node being removed. The package should remain a dev dependency since it's only needed during development.
- "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw=="
+ "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==",
+ "dev": true
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (2)
- LICENSE
- src/prompts.ts
Review comments generated (93)
- Review: 8
- LGTM: 85
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| private readonly client: Anthropic | ||
|
|
||
| private readonly options: Options | ||
| private readonly anthropicOptions: AnthropicOptions | ||
|
|
||
| constructor(options: Options, openaiOptions: OpenAIOptions) { | ||
| constructor(options: Options, anthropicOptions: AnthropicOptions) { | ||
| this.options = options | ||
| if (process.env.OPENAI_API_KEY) { | ||
| const currentDate = new Date().toISOString().split('T')[0] | ||
| const systemMessage = `${options.systemMessage} | ||
| Knowledge cutoff: ${openaiOptions.tokenLimits.knowledgeCutOff} | ||
| Current date: ${currentDate} | ||
|
|
||
| IMPORTANT: Entire response must be in the language with ISO code: ${options.language} | ||
| ` | ||
|
|
||
| const apiConfig: any = { | ||
| apiBaseUrl: options.apiBaseUrl, | ||
| apiKey: process.env.OPENAI_API_KEY, | ||
| apiOrg: process.env.OPENAI_API_ORG ?? undefined, | ||
| debug: options.debug, | ||
| maxModelTokens: openaiOptions.tokenLimits.maxTokens, | ||
| maxResponseTokens: openaiOptions.tokenLimits.responseTokens, | ||
| completionParams: { | ||
| temperature: 1, | ||
| model: openaiOptions.model | ||
| } | ||
| } | ||
|
|
||
| if (!openaiOptions.model.startsWith('o1')) { | ||
| apiConfig.systemMessage = systemMessage | ||
| apiConfig.completionParams.temperature = options.openaiModelTemperature | ||
| } | ||
|
|
||
| this.api = new ChatGPTAPI(apiConfig) | ||
| } else { | ||
| const err = | ||
| "Unable to initialize the OpenAI API, both 'OPENAI_API_KEY' environment variable are not available" | ||
| throw new Error(err) | ||
| } | ||
| this.anthropicOptions = anthropicOptions | ||
| this.client = new Anthropic(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The Anthropic client is initialized without passing the API key or any configuration. This could cause authentication failures.
- this.client = new Anthropic();
+ this.client = new Anthropic({
+ apiKey: process.env.ANTHROPIC_API_KEY
+ });| reviewFileDiff = '', | ||
| anthropicLightModel: string, | ||
| anthropicHeavyModel: string, | ||
| anthropicModelTemperature = '0.0', | ||
| anthropicRetries = '3', | ||
| anthropicTimeoutMS = '120000', | ||
| anthropicConcurrencyLimit = '6', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The constructor parameters anthropicLightModel and anthropicHeavyModel are missing default values, which will cause runtime errors when these parameters are not provided.
- anthropicLightModel: string,
- anthropicHeavyModel: string,
+ anthropicLightModel = 'claude-instant-v1',
+ anthropicHeavyModel = 'claude-v2',| constructor(model = 'anthropic.claude-instant-v1') { | ||
| if (model === 'anthropic.claude-instant-v1') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The model name format is inconsistent with typical Anthropic model naming conventions. Anthropic models are usually referenced as claude-instant-v1 or claude-2, not with the anthropic. prefix.
- constructor(model = 'anthropic.claude-instant-v1') {
- if (model === 'anthropic.claude-instant-v1') {
+ constructor(model = 'claude-instant-v1') {
+ if (model === 'claude-instant-v1') {| this.maxTokens = 100_000 | ||
| this.responseTokens = 4000 | ||
| } else if (model === 'gpt-3.5-turbo-16k') { | ||
| this.maxTokens = 16300 | ||
| } else if (model === 'anthropic.claude-v2') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 3000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Inconsistent indentation with extra spaces before this.responseTokens.
if (model === 'claude-instant-v1') {
this.maxTokens = 100_000
- this.responseTokens = 4000
+ this.responseTokens = 4000
} else if (model === 'claude-v2') {
this.maxTokens = 100_000
- this.responseTokens = 3000
+ this.responseTokens = 3000| this.responseTokens = 4000 | ||
| } else if (model === 'gpt-3.5-turbo-16k') { | ||
| this.maxTokens = 16300 | ||
| } else if (model === 'anthropic.claude-v2') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The model name should be claude-2 instead of claude-v2 to match Anthropic's actual model naming.
- } else if (model === 'anthropic.claude-v2') {
+ } else if (model === 'claude-2') {| // eslint-disable-next-line no-unused-vars | ||
| patches: Array<[number, number, string]> | ||
| ): Review[] { | ||
| const reviews: Review[] = [] | ||
|
|
||
| response = sanitizeResponse(response.trim()) | ||
|
|
||
| const lines = response.split('\n') | ||
| const lineNumberRangeRegex = /(?:^|\s)(\d+)-(\d+):\s*$/ | ||
| const commentSeparator = '---' | ||
|
|
||
| let currentStartLine: number | null = null | ||
| let currentEndLine: number | null = null | ||
| let currentComment = '' | ||
| function storeReview(): void { | ||
| if (currentStartLine !== null && currentEndLine !== null) { | ||
| const review: Review = { | ||
| startLine: currentStartLine, | ||
| endLine: currentEndLine, | ||
| comment: currentComment | ||
| } | ||
|
|
||
| let withinPatch = false | ||
| let bestPatchStartLine = -1 | ||
| let bestPatchEndLine = -1 | ||
| let maxIntersection = 0 | ||
|
|
||
| for (const [startLine, endLine] of patches) { | ||
| const intersectionStart = Math.max(review.startLine, startLine) | ||
| const intersectionEnd = Math.min(review.endLine, endLine) | ||
| const intersectionLength = Math.max( | ||
| 0, | ||
| intersectionEnd - intersectionStart + 1 | ||
| ) | ||
|
|
||
| if (intersectionLength > maxIntersection) { | ||
| maxIntersection = intersectionLength | ||
| bestPatchStartLine = startLine | ||
| bestPatchEndLine = endLine | ||
| withinPatch = | ||
| intersectionLength === review.endLine - review.startLine + 1 | ||
| } | ||
|
|
||
| if (withinPatch) break | ||
| } | ||
|
|
||
| if (!withinPatch) { | ||
| if (bestPatchStartLine !== -1 && bestPatchEndLine !== -1) { | ||
| review.comment = `> Note: This review was outside of the patch, so it was mapped to the patch with the greatest overlap. Original lines [${review.startLine}-${review.endLine}] | ||
|
|
||
| ${review.comment}` | ||
| review.startLine = bestPatchStartLine | ||
| review.endLine = bestPatchEndLine | ||
| } else { | ||
| review.comment = `> Note: This review was outside of the patch, but no patch was found that overlapped with it. Original lines [${review.startLine}-${review.endLine}] | ||
|
|
||
| ${review.comment}` | ||
| review.startLine = patches[0][0] | ||
| review.endLine = patches[0][1] | ||
| } | ||
| try { | ||
| const rawReviews = JSON.parse(response).reviews | ||
| for (const r of rawReviews) { | ||
| if (r.comment) { | ||
| reviews.push({ | ||
| startLine: r.line_start ?? 0, | ||
| endLine: r.line_end ?? 0, | ||
| comment: r.comment | ||
| }) | ||
| } | ||
|
|
||
| reviews.push(review) | ||
|
|
||
| info( | ||
| `Stored comment for line range ${currentStartLine}-${currentEndLine}: ${currentComment.trim()}` | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| function sanitizeCodeBlock(comment: string, codeBlockLabel: string): string { | ||
| const codeBlockStart = `\`\`\`${codeBlockLabel}` | ||
| const codeBlockEnd = '```' | ||
| const lineNumberRegex = /^ *(\d+): /gm | ||
|
|
||
| let codeBlockStartIndex = comment.indexOf(codeBlockStart) | ||
|
|
||
| while (codeBlockStartIndex !== -1) { | ||
| const codeBlockEndIndex = comment.indexOf( | ||
| codeBlockEnd, | ||
| codeBlockStartIndex + codeBlockStart.length | ||
| ) | ||
|
|
||
| if (codeBlockEndIndex === -1) break | ||
|
|
||
| const codeBlock = comment.substring( | ||
| codeBlockStartIndex + codeBlockStart.length, | ||
| codeBlockEndIndex | ||
| ) | ||
| const sanitizedBlock = codeBlock.replace(lineNumberRegex, '') | ||
|
|
||
| comment = | ||
| comment.slice(0, codeBlockStartIndex + codeBlockStart.length) + | ||
| sanitizedBlock + | ||
| comment.slice(codeBlockEndIndex) | ||
|
|
||
| codeBlockStartIndex = comment.indexOf( | ||
| codeBlockStart, | ||
| codeBlockStartIndex + | ||
| codeBlockStart.length + | ||
| sanitizedBlock.length + | ||
| codeBlockEnd.length | ||
| ) | ||
| } | ||
|
|
||
| return comment | ||
| } | ||
|
|
||
| function sanitizeResponse(comment: string): string { | ||
| comment = sanitizeCodeBlock(comment, 'suggestion') | ||
| comment = sanitizeCodeBlock(comment, 'diff') | ||
| return comment | ||
| } | ||
|
|
||
| for (const line of lines) { | ||
| const lineNumberRangeMatch = line.match(lineNumberRangeRegex) | ||
|
|
||
| if (lineNumberRangeMatch != null) { | ||
| storeReview() | ||
| currentStartLine = parseInt(lineNumberRangeMatch[1], 10) | ||
| currentEndLine = parseInt(lineNumberRangeMatch[2], 10) | ||
| currentComment = '' | ||
| if (debug) { | ||
| info(`Found line number range: ${currentStartLine}-${currentEndLine}`) | ||
| } | ||
| continue | ||
| } | ||
|
|
||
| if (line.trim() === commentSeparator) { | ||
| storeReview() | ||
| currentStartLine = null | ||
| currentEndLine = null | ||
| currentComment = '' | ||
| if (debug) { | ||
| info('Found comment separator') | ||
| } | ||
| continue | ||
| } | ||
|
|
||
| if (currentStartLine !== null && currentEndLine !== null) { | ||
| currentComment += `${line}\n` | ||
| } | ||
| } catch (e: any) { | ||
| error(e.message) | ||
| return [] | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The parseReview function has a logic issue. The JSON parsing assumes a specific structure with reviews array containing objects with line_start, line_end, and comment properties, but there's no validation that these properties exist before accessing them.
- for (const r of rawReviews) {
- if (r.comment) {
- reviews.push({
- startLine: r.line_start ?? 0,
- endLine: r.line_end ?? 0,
- comment: r.comment
- })
- }
- }
+ for (const r of rawReviews) {
+ if (r.comment && typeof r.line_start === 'number' && typeof r.line_end === 'number') {
+ reviews.push({
+ startLine: r.line_start,
+ endLine: r.line_end,
+ comment: r.comment
+ })
+ }
+ }
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (3)
- LICENSE
- package-lock.json
- src/prompts.ts
Review comments generated (49)
- Review: 4
- LGTM: 45
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| with: | ||
| debug: false | ||
| debug: true | ||
| poem_enabled: true | ||
| less_verbose_review: false | ||
| review_comment_lgtm: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The env: and with: blocks aren’t indented correctly relative to the - uses: line, which will break YAML parsing. They should be indented two spaces under - uses:. For example:
- - uses: RedVentures/red-rover@anthropic
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- with:
- debug: true
- poem_enabled: true
- less_verbose_review: false
- review_comment_lgtm: false
+ - uses: RedVentures/red-rover@anthropic
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
+ with:
+ debug: true
+ poem_enabled: true
+ less_verbose_review: false
+ review_comment_lgtm: false| ### Inspect the messages between Anthropic server | ||
|
|
||
| Set `debug: true` in the workflow file to enable debug mode, which will show the | ||
| messages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The removal of the OpenAI‐specific disclaimer also removed any notice about data being sent to Anthropic. It’s important to inform users about data transmission and link to Anthropic’s data usage policy. For example:
+### Disclaimer
+
+- Your code, diffs, and PR metadata will be sent to Anthropic’s servers for processing. Please review Anthropic’s API data usage policy [here](https://console.anthropic.com/policies) before using this action.| const params: Anthropic.MessageCreateParams = { | ||
| model: this.anthropicOptions.model, | ||
| max_tokens: 4096, | ||
| messages: [ | ||
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The max_tokens parameter is hard-coded, which may not respect the configured token limits. Consider using the response token limit from anthropicOptions.tokenLimits.responseTokens instead of a fixed value.
- max_tokens: 4096,
+ max_tokens: this.anthropicOptions.tokenLimits.responseTokens,| warning(`Unexpected content structure in the response: ${JSON.stringify(response.content)}`); | ||
| } | ||
|
|
||
| newIds.parentMessageId = response.id; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The conversationId returned by Anthropic is not being captured, so multi-turn context may be lost. You should set newIds.conversationId from the response (e.g., response.conversationId or response.conversation_id).
+ newIds.conversationId = response.conversationId ?? response.conversation_id;
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (3)
- LICENSE
- package-lock.json
- src/prompts.ts
Review comments generated (47)
- Review: 7
- LGTM: 40
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| - uses: RedVentures/red-rover@anthropic | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| with: | ||
| debug: false | ||
| debug: true | ||
| poem_enabled: true | ||
| less_verbose_review: false | ||
| review_comment_lgtm: false | ||
| openai_heavy_model: gpt-4 | ||
| path_filters: | | ||
| !dist/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The env: and with: mappings under the - uses: step aren’t aligned properly and will break YAML parsing. They should be indented two spaces further under the list item. For example:
- - uses: RedVentures/red-rover@anthropic
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
- with:
- debug: true
- poem_enabled: true
- less_verbose_review: false
- review_comment_lgtm: false
- path_filters: |
- !dist/**
- !**/*.lock
+ - uses: RedVentures/red-rover@anthropic
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
+ with:
+ debug: true
+ poem_enabled: true
+ less_verbose_review: false
+ review_comment_lgtm: false
+ path_filters: |
+ !dist/**
+ !**/*.lock|  | ||
|
|
||
| ## Overview | ||
| ### Overview |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The heading “### Overview” is one level too deep under your <h1>; please use ## Overview to maintain proper Markdown hierarchy.
| you can refer to the sections below. | ||
|
|
||
| ### Reviewer Features: | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Similarly, “### Reviewer Features:” should be ## Reviewer Features: to follow the <h1> → ## → ### structure.
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} | ||
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | ||
| with: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The env: and with: keys under the - uses: step are over-indented and may break the YAML. They should align two spaces under the step, for example:
- uses: RedVentures/red-rover@anthropic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
debug: false
review_simple_changes: false
review_comment_lgtm: false| response = await pRetry( | ||
| () => | ||
| this.client.messages.create(params), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The SDK does not expose messages.create; use the chat completions endpoint instead:
- () =>
- this.client.messages.create(params),
+ () =>
+ this.client.chat.completions.create(params),
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (5)
- LICENSE
- README.md
- package.json
- src/prompts.ts
- package-lock.json (diff too large)
Review comments generated (38)
- Review: 3
- LGTM: 35
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| default: | | ||
| - Do NOT provide general feedback, summaries, explanations of changes, or praises for making good additions. | ||
| - Focus solely on offering specific, objective insights based on the given context and refrain from making broad comments about potential impacts on the system or question intentions behind the changes. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The summarize_release_notes key is mis-indented and won’t be recognized under inputs. It should align with the other input keys (2 spaces).
- summarize_release_notes:
+ summarize_release_notes:| ) | ||
| const params: Anthropic.MessageCreateParams = { | ||
| model: this.anthropicOptions.model, | ||
| max_tokens: 4096, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The max_tokens parameter is hard-coded to 4096. To respect model-specific token limits provided by AnthropicOptions, use its tokenLimits.responseTokens instead:
- max_tokens: 4096,
+ max_tokens: this.anthropicOptions.tokenLimits.responseTokens,| if (login === SELF_LOGIN) return '\nA (You): ' | ||
| return `\nH (@${login}):` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The returned strings include a leading newline and inconsistent trailing spaces, which can introduce unwanted blank lines and spacing in the composed comment chain. Remove the leading \n and ensure both branches include a single trailing space:
- if (login === SELF_LOGIN) return '\nA (You): '
+ if (login === SELF_LOGIN) return 'A (You): '
- return `\nH (@${login}):`
+ return `H (@${login}): `
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (4)
- LICENSE
- README.md
- package-lock.json
- src/prompts.ts
Review comments generated (43)
- Review: 5
- LGTM: 38
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| path_filters: | | ||
| !dist/** | ||
| !**/*.lock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
- path_filters: |
- !dist/**
- !**/*.lock
+ path_filters: |
+ !dist/**
+ !**/*.lock| const params: Anthropic.MessageCreateParams = { | ||
| model: this.anthropicOptions.model, | ||
| max_tokens: 4096, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The Anthropic request parameters don’t include a temperature setting, so the model always uses its default randomness. You should pass the configured anthropicModelTemperature from options into the params:
const params: Anthropic.MessageCreateParams = {
model: this.anthropicOptions.model,
- max_tokens: 4096,
+ max_tokens: 4096,
+ temperature: this.options.anthropicModelTemperature,
messages: [
{
role: 'user',
content: message
},| github_concurrency_limit: | ||
| required: false | ||
| description: 'How many concurrent API calls to make to GitHub?' | ||
| default: '6' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The github_concurrency_limit block is over-indented, which will break the YAML structure. It should align with the other top-level inputs:
- github_concurrency_limit:
- required: false
- description: 'How many concurrent API calls to make to GitHub?'
- default: '6'
+ github_concurrency_limit:
+ required: false
+ description: 'How many concurrent API calls to make to GitHub?'
+ default: '6'|
|
||
| summarize_release_notes: | ||
| required: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The summarize_release_notes key (and its children) is under-indented and falls outside the inputs mapping. It needs one fewer leading space:
- summarize_release_notes:
- required: false
- description:
+ summarize_release_notes:
+ required: false
+ description:| constructor(model = 'anthropic.claude-instant-v1') { | ||
| if (model === 'anthropic.claude-instant-v1') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 4000 | ||
| } else if (model === 'gpt-3.5-turbo-16k') { | ||
| this.maxTokens = 16300 | ||
| } else if (model === 'anthropic.claude-v2') { | ||
| this.maxTokens = 100_000 | ||
| this.responseTokens = 3000 | ||
| } else if (model === 'gpt-4') { | ||
| this.maxTokens = 8192 | ||
| this.responseTokens = 8192 | ||
| } else if (model === 'gpt-4o') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 4096 | ||
| } else if (model === 'o1-mini') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 65536 | ||
| } else if (model === 'o1-preview') { | ||
| this.maxTokens = 128000 | ||
| this.responseTokens = 32768 | ||
| } else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The constructor’s checks expect model names prefixed with anthropic., but the inputs/defaults use bare model IDs like claude-instant-v1 and claude-v2. As a result, both cases fall through to the else branch. Update the comparisons (and the default) to match the actual model strings:
- constructor(model = 'anthropic.claude-instant-v1') {
- if (model === 'anthropic.claude-instant-v1') {
+ constructor(model = 'claude-instant-v1') {
+ if (
+ model === 'claude-instant-v1' ||
+ model === 'anthropic.claude-instant-v1'
+ ) {
this.maxTokens = 100_000
this.responseTokens = 4000
- } else if (model === 'anthropic.claude-v2') {
+ } else if (
+ model === 'claude-v2' ||
+ model === 'anthropic.claude-v2'
+ ) {
this.maxTokens = 100_000
this.responseTokens = 3000
} else {
gwilkes-rv
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Files selected (15)
- .github/workflows/redrover_review.yml (1)
- LICENSE (1)
- README.md (6)
- action.yml (3)
- package-lock.json (35)
- package.json (4)
- src/bot.ts (2)
- src/commenter.ts (2)
- src/inputs.ts (5)
- src/limits.ts (1)
- src/main.ts (4)
- src/options.ts (6)
- src/prompts.ts (4)
- src/review-comment.ts (1)
- src/review.ts (12)
Files ignored due to filter (4)
- dist/37.index.js
- dist/73.index.js
- dist/index.js
- dist/licenses.txt
Files skipped from review due to trivial changes (4)
- LICENSE
- README.md
- package-lock.json
- src/prompts.ts
Review comments generated (40)
- Review: 8
- LGTM: 32
Tips
Chat with RedRover (@redrover)
- Reply on review comments left by this bot to ask follow-up questions. A review comment is a comment on a diff or a file.
- Invite the bot into a review comment chain by tagging
@redroverin a reply.
Code suggestions
- The bot may make code suggestions, but please review them carefully before committing since the line number ranges may be misaligned.
- You can edit the comment made by the bot and manually tweak the suggestion if it is slightly off.
Pausing incremental reviews
- Add
@redrover: ignoreanywhere in the PR description to pause further reviews from the bot.
| !dist/** | ||
| !**/*.lock | ||
| system_message: ${{ steps.file.outputs.content }} | ||
| # system_message: ${{ steps.file.outputs.content }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
You’ve left the system_message input commented out, so the custom prompt you read isn’t passed into the action. If you intend to use it, uncomment or add the correct input. For example:
- # system_message: ${{ steps.file.outputs.content }}
+ system_message: ${{ steps.file.outputs.content }}| getRole(login: string) { | ||
| if (login === SELF_LOGIN) return '\nA (You): ' | ||
| return `\nH (@${login}):` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The leading \n in the role prefixes causes an extra blank line before each comment. It’s clearer to let the joiner insert newlines.
- getRole(login: string) {
- if (login === SELF_LOGIN) return '\nA (You): '
- return `\nH (@${login}):`
- }
+ getRole(login: string) {
+ if (login === SELF_LOGIN) return 'A (You):'
+ return `H (@${login}):`
+ }|
|
||
| return conversationChain.join('\n---\n') | ||
| return `${conversationChain.join('\n')}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Switching from '\n---\n' to '\n' removes the visual separators between comments and may reduce readability. Consider restoring a clear delimiter:
- return `${conversationChain.join('\n')}`
+ return conversationChain.join('\n---\n')| icon: 'git-merge' | ||
| color: 'orange' | ||
| author: 'CodeRabbit LLC' | ||
| author: 'gwilkes-rv' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
There's an extra space before author—it should align with name at the root level.
- author: 'gwilkes-rv'
+author: 'gwilkes-rv'| anthropic_light_model: | ||
| required: false | ||
| description: | ||
| 'Model to use for simple tasks like summarizing diff on a file.' | ||
| default: 'gpt-4o-mini' | ||
| openai_heavy_model: | ||
| default: 'claude-3-haiku-20240307' | ||
| anthropic_heavy_model: | ||
| required: false | ||
| description: 'Model to use for complex tasks such as code reviews.' | ||
| default: 'gpt-4o' | ||
| openai_model_temperature: | ||
| default: 'claude-3-5-sonnet-latest' | ||
| anthropic_model_temperature: | ||
| required: false | ||
| description: 'Temperature for GPT model' | ||
| default: '0.05' | ||
| openai_retries: | ||
| anthropic_retries: | ||
| required: false | ||
| description: | ||
| 'How many times to retry OpenAI API in case of timeouts or errors?' | ||
| 'How many times to retry Anthropic API in case of timeouts or errors?' | ||
| default: '5' | ||
| openai_timeout_ms: | ||
| anthropic_timeout_ms: | ||
| required: false | ||
| description: 'Timeout for OpenAI API call in millis' | ||
| description: 'Timeout for Anthropic API call in millis' | ||
| default: '360000' | ||
| openai_concurrency_limit: | ||
| anthropic_concurrency_limit: | ||
| required: false | ||
| description: 'How many concurrent API calls to make to OpenAI servers?' | ||
| description: 'How many concurrent API calls to make to Anthropic servers?' | ||
| default: '6' | ||
| github_concurrency_limit: | ||
| required: false | ||
| description: 'How many concurrent API calls to make to GitHub?' | ||
| default: '6' | ||
| system_message: | ||
| required: false | ||
| description: 'System message to be sent to OpenAI' | ||
| description: 'System message to be sent to Anthropic' | ||
| default: | | ||
| You are `@redrover` (aka `github-actions[bot]`), a language model | ||
| trained by OpenAI. Your purpose is to act as a highly experienced | ||
| software engineer and provide a thorough review of the code hunks | ||
| and suggest code snippets to improve key areas such as: | ||
| - Logic | ||
| - Security | ||
| - Performance | ||
| - Data races | ||
| - Consistency | ||
| - Error handling | ||
| - Maintainability | ||
| - Modularity | ||
| - Complexity | ||
| - Optimization | ||
| - Best practices: DRY, SOLID, KISS | ||
| You are `@redrover` (aka `github-actions[bot]`), a language model | ||
| trained by Anthropic. Your purpose is to act as a highly experienced | ||
| software engineer and provide a thorough review of the code, related documents, and articles | ||
| and suggest code snippets to improve these with various aspects. | ||
|
|
||
| Do not comment on minor code style issues, missing | ||
| comments/documentation. Identify and resolve significant | ||
| concerns to improve overall code quality while deliberately | ||
| disregarding minor issues. | ||
| Follow the following instructions. | ||
| summarize: | ||
| required: false | ||
| description: 'The prompt for final summarization response' | ||
| default: | | ||
| Provide your final response in markdown with the following content: | ||
|
|
||
| **Walkthrough**: A high-level summary of the overall change instead of | ||
| specific files within 80 words. | ||
| **Changes**: A markdown table of files and their summaries. Group files | ||
| with similar changes together into a single row to save space. | ||
| - **Walkthrough**: A high-level summary of the overall change instead of | ||
| specific files within 80 words. | ||
| - **Changes**: A markdown table of files and their summaries. Group files | ||
| with similar changes together into a single row to save space. | ||
|
|
||
| Avoid additional commentary as this summary will be added as a comment on the | ||
| GitHub pull request. Use the titles "Walkthrough" and "Changes" and they must be H2. | ||
| review_file_diff: | ||
| required: false | ||
| description: 'The additional instruction for reviewing file diff' | ||
| default: | | ||
| - Do NOT provide general feedback, summaries, explanations of changes, or praises for making good additions. | ||
| - Focus solely on offering specific, objective insights based on the given context and refrain from making broad comments about potential impacts on the system or question intentions behind the changes. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The nested keys under each anthropic_* (and related inputs) are over-indented by two spaces, which will break YAML parsing. All required, description, and default lines should be indented exactly 4 spaces from the document root (2 under inputs: and 2 for nesting), not 6. For example:
- required: false
+ required: false
- description: 'Model to use for simple tasks like summarizing diff on a file.'
+ description: 'Model to use for simple tasks like summarizing diff on a file.'
...Please correct the indentation for the entire anthropic inputs block.
| inputs.commentChain = inputs.commentChain | ||
| .replace(COMMENT_TAG, '') | ||
| .replace(COMMENT_REPLY_TAG, '') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The current .replace() calls only remove the first occurrence of each tag. To ensure all instances are stripped, use .replaceAll() (or a global regex) instead:
- inputs.commentChain = inputs.commentChain
- .replace(COMMENT_TAG, '')
- .replace(COMMENT_REPLY_TAG, '')
+ inputs.commentChain = inputs.commentChain
+ .replaceAll(COMMENT_TAG, '')
+ .replaceAll(COMMENT_REPLY_TAG, '')| const params: Anthropic.MessageCreateParams = { | ||
| model: this.anthropicOptions.model, | ||
| max_tokens: 4096, | ||
| messages: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
Hardcoding max_tokens: 4096 may exceed the model’s configured response limit and ignores the token limits provided in AnthropicOptions. Consider pulling the response token limit from this.anthropicOptions.tokenLimits.responseTokens:
- max_tokens: 4096,
+ max_tokens: this.anthropicOptions.tokenLimits.responseTokens,| if (Array.isArray(response.content) && response.content.length > 0) { | ||
| const textContent = response.content.find(item => item.type === 'text'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐶 RedRover
The code only handles the case where response.content is an array. If the SDK returns a simple string, it will fall through and be ignored. You should add a branch to handle string content, for example:
if (typeof response.content === 'string') {
responseText = response.content.trim();
}
Summary by RedRover
Here’s a draft Pull Request description using the provided “context7” summary:
Title
Rebrand to “red-rover” / Swap OpenAI → Anthropic (Claude)
Description
This PR rebrands our GitHub Action and package from “openai-pr-reviewer” to “red-rover” and replaces all OpenAI integrations with Anthropic’s Claude models. It updates workflows, action metadata, code, prompts, README, licensing, and dependencies accordingly.
What changed?
Project metadata & licensing
• Renamed project from
openai-pr-reviewer→red-rover• Appended “tmokmss (2023)” to the MIT header in LICENSE
CI workflow & Action manifest
•
.github/workflows/redrover_review.yml– Uses
RedVentures/red-rover@anthropic– Swaps
OPENAI_API_KEY→ANTHROPIC_API_KEY– Removes OpenAI models/inputs, enables debug mode
•
action.yml– Renamed inputs (
openai_*→anthropic_*), addedreview_file_diff&bot_icon– Commented out leftover OpenAI entries (
system_message,openai_heavy_model)– Updated descriptions, prompts, and default values
Documentation & examples
•
README.md– All usage, examples and environment variables now reference Anthropic (claude-instant-v1, claude-v2)
– Updated SDK instructions, cost/disclaimer, debug guidance
Dependencies & packaging
•
package.json&package-lock.json– Renamed package, updated metadata, removed
chatgptdependency– Added
@anthropic-ai/sdk@0.29.0and sub-depsCore source changes
•
src/*files renamed types and options from OpenAI → Anthropic• main.ts
– Instantiates
BotwithAnthropicOptions, enforcesANTHROPIC_API_KEY– Wires in new
review_file_diffinput• inputs.ts & options.ts
– Support include/exclude path filters
– Define Claude token limits (100 000 total; 4 000/3 000 response)
• bot.ts
– Replaces OpenAI client with Anthropic SDK (
createMessage) and retry logic• review.ts & review-comment.ts
– Wrap diffs in XML tags, remove OpenAI concurrency, parse JSON from Claude
– Strip tags before rendering comments
• prompts.ts
– All templates refactored to XML-style tags, new JSON schema examples, new
reviewFileDiff&commenttemplates• commenter.ts
– Adds
SELF_LOGINlogic to prefix comments as “A (You):” or “H (@username):”How to test
ANTHROPIC_API_KEYin your environment or repository secrets.red-rover_review.ymlworkflow.claude-instant-v1orclaude-v2as configuredNotes
Please review and let me know if anything’s missing or if you spot residual OpenAI references.