Skip to content

Commit f327c52

Browse files
Gavin Williamsclaude
andcommitted
feat(web): acknowledge review command comments with a reaction
Adds a configurable acknowledgment reaction/emoji to the triggering comment when the review agent receives a `/review` command, so users get immediate feedback that the request was received. - GitHub: reacts to the issue comment via the reactions API (default: `eyes`) - GitLab: awards an emoji on the MR note via `MergeRequestNoteAwardEmojis` - New `REVIEW_AGENT_ACK_REACTION` env var (default: `eyes`) controls the reaction - Acknowledgment failures are logged as warnings and do not block the review Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a6116ca commit f327c52

5 files changed

Lines changed: 32 additions & 5 deletions

File tree

docs/docs/configuration/environment-variables.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,12 @@ The following environment variables allow you to configure your Sourcebot deploy
7070
| `GITHUB_REVIEW_AGENT_APP_PRIVATE_KEY_PATH` | `-` | <p>The container relative path to the private key file for the GitHub App used by the review agent.</p> |
7171
| `GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET` | `-` | <p>The webhook secret for the GitHub App used by the review agent.</p> |
7272
| `OPENAI_API_KEY` | `-` | <p>The OpenAI API key used by the review agent.</p> |
73+
| `REVIEW_AGENT_ACK_REACTION` | `eyes` | <p>The reaction/emoji added to a comment when the review agent acknowledges receipt of the review command.</p> |
7374
| `REVIEW_AGENT_API_KEY` | `-` | <p>The Sourcebot API key used by the review agent.</p> |
7475
| `REVIEW_AGENT_AUTO_REVIEW_ENABLED` | `false` | <p>Enables/disables automatic code reviews by the review agent.</p> |
7576
| `REVIEW_AGENT_LOGGING_ENABLED` | `true` | <p>Enables/disables logging for the review agent. Logs are saved in `DATA_CACHE_DIR/review-agent`</p> |
7677
| `REVIEW_AGENT_REVIEW_COMMAND` | `review` | <p>The command used to trigger a code review by the review agent.</p> |
7778

7879
### Overriding environment variables from the config
7980

80-
You can override environment variables from the config file by using the `environmentOverrides` property. See [this doc](/docs/configuration/config-file#overriding-environment-variables-from-the-config) for more info.
81+
You can override environment variables from the config file by using the `environmentOverrides` property. See [this doc](/docs/configuration/config-file#overriding-environment-variables-from-the-config) for more info.

docs/docs/features/agents/review-agent.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ You can also trigger a review manually by commenting `/review` on any PR or MR.
141141

142142
| Variable | Default | Description |
143143
|---|---|---|
144+
| `REVIEW_AGENT_ACK_REACTION` | `eyes` | Reaction/emoji added to acknowledge receipt of the review command |
144145
| `REVIEW_AGENT_AUTO_REVIEW_ENABLED` | `false` | Automatically review new and updated PRs/MRs |
145-
| `REVIEW_AGENT_REVIEW_COMMAND` | `review` | Comment command that triggers a manual review (without the `/`) |
146-
| `REVIEW_AGENT_MODEL` | first configured model | `displayName` of the language model to use for reviews |
147146
| `REVIEW_AGENT_LOGGING_ENABLED` | unset | Write prompt and response logs to disk for debugging |
147+
| `REVIEW_AGENT_MODEL` | first configured model | `displayName` of the language model to use for reviews |
148+
| `REVIEW_AGENT_REVIEW_COMMAND` | `review` | Comment command that triggers a manual review (without the `/`) |

packages/shared/src/env.server.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,11 @@ const options = {
235235
GITLAB_REVIEW_AGENT_TOKEN: z.string().optional(),
236236
GITLAB_REVIEW_AGENT_HOST: z.string().default('gitlab.com').transform(s => s.replace(/^https?:\/\//, '').replace(/\/+$/, '')).refine(s => /^[a-z0-9.-]+$/i.test(s), { message: 'invalid hostname' }),
237237
// Review agent config
238-
REVIEW_AGENT_MODEL: z.string().optional(),
238+
REVIEW_AGENT_ACK_REACTION: z.string().default('eyes'),
239239
REVIEW_AGENT_API_KEY: z.string().optional(),
240-
REVIEW_AGENT_LOGGING_ENABLED: booleanSchema.default('true'),
241240
REVIEW_AGENT_AUTO_REVIEW_ENABLED: booleanSchema.default('false'),
241+
REVIEW_AGENT_LOGGING_ENABLED: booleanSchema.default('true'),
242+
REVIEW_AGENT_MODEL: z.string().optional(),
242243
REVIEW_AGENT_REVIEW_COMMAND: z.string().default('review'),
243244

244245
ANTHROPIC_API_KEY: z.string().optional(),

packages/web/src/app/api/(server)/webhook/route.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,18 @@ export const POST = async (request: NextRequest) => {
185185
const owner = body.repository.owner.login;
186186

187187
const octokit = await githubApp.getInstallationOctokit(body.installation.id);
188+
189+
try {
190+
await octokit.rest.reactions.createForIssueComment({
191+
owner,
192+
repo: repositoryName,
193+
comment_id: body.comment.id,
194+
content: env.REVIEW_AGENT_ACK_REACTION as Parameters<typeof octokit.rest.reactions.createForIssueComment>[0]['content'],
195+
});
196+
} catch (error) {
197+
logger.warn(`Failed to add acknowledgment reaction to GitHub comment: ${error}`);
198+
}
199+
188200
const { data: pullRequest } = await octokit.rest.pulls.get({
189201
owner,
190202
repo: repositoryName,
@@ -246,6 +258,17 @@ export const POST = async (request: NextRequest) => {
246258
if (noteBody === `/${env.REVIEW_AGENT_REVIEW_COMMAND}`) {
247259
logger.info('Review agent review command received on GitLab MR, processing');
248260

261+
try {
262+
await gitlabClient.MergeRequestNoteAwardEmojis.award(
263+
parsed.data.project.id,
264+
parsed.data.merge_request.iid,
265+
parsed.data.object_attributes.id,
266+
env.REVIEW_AGENT_ACK_REACTION,
267+
);
268+
} catch (error) {
269+
logger.warn(`Failed to add acknowledgment emoji to GitLab note: ${error}`);
270+
}
271+
249272
const mrPayload: GitLabMergeRequestPayload = {
250273
object_kind: "merge_request",
251274
object_attributes: {

packages/web/src/features/agents/review-agent/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export type GitLabMergeRequestPayload = z.infer<typeof gitLabMergeRequestPayload
8787
export const gitLabNotePayloadSchema = z.object({
8888
object_kind: z.literal('note'),
8989
object_attributes: z.object({
90+
id: z.number(),
9091
note: z.string(),
9192
noteable_type: z.literal('MergeRequest'),
9293
}),

0 commit comments

Comments
 (0)