Skip to content

Commit 51667f8

Browse files
gouravjshahclaude
andauthored
fix: GitHub PR reviews now post single response instead of multiple comments (#94)
Skip intermediate acknowledgment messages ("Thinking...", "Processing...") for Git platforms (GitHub, GitLab, Bitbucket) since they create new comments instead of updating existing ones. This keeps PR threads clean. - Chat platforms (Slack/Telegram/Discord) still show progress indicators - Only final response is posted for Git platforms - Updated docs with Git platform behavior section 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <[email protected]>
1 parent 0bbedda commit 51667f8

File tree

3 files changed

+92
-25
lines changed

3 files changed

+92
-25
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Changed from tracing (default level: error) to println for critical startup messages
1313
- Users can now see server bind address, registered platforms, loaded agents/flows
1414
- Error messages use stderr for proper output separation
15+
- GitHub/GitLab/Bitbucket PR reviews now post a single response instead of multiple comments
16+
- Intermediate acknowledgment messages ("Thinking...", "Processing...") are skipped for Git platforms
17+
- Only the final response is posted, keeping PR threads clean
18+
- Slack/Telegram/Discord still show real-time progress indicators
1519

1620
## [0.3.1-beta] - 2025-12-26
1721

crates/aof-triggers/src/handler/mod.rs

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,12 @@ impl TriggerHandler {
977977
};
978978

979979
// Auto-acknowledge if enabled
980-
if self.config.auto_ack {
980+
// Skip for GitHub/GitLab/Bitbucket - they create new comments instead of updating
981+
let is_git_platform = matches!(
982+
platform_impl.platform_name(),
983+
"github" | "gitlab" | "bitbucket"
984+
);
985+
if self.config.auto_ack && !is_git_platform {
981986
let ack = TriggerResponseBuilder::new()
982987
.text("Processing your request...")
983988
.build();
@@ -1765,11 +1770,17 @@ impl TriggerHandler {
17651770
// Trigger the selected flow
17661771
info!("Triggering flow: {}", callback_value);
17671772

1768-
// Send acknowledgment
1769-
let ack = TriggerResponseBuilder::new()
1770-
.text(format!("Running flow: *{}*...", callback_value))
1771-
.build();
1772-
let _ = platform_impl.send_response(&message.channel_id, ack).await;
1773+
// Send acknowledgment (skip for Git platforms - they create new comments)
1774+
let is_git_platform = matches!(
1775+
platform_impl.platform_name(),
1776+
"github" | "gitlab" | "bitbucket"
1777+
);
1778+
if !is_git_platform {
1779+
let ack = TriggerResponseBuilder::new()
1780+
.text(format!("Running flow: *{}*...", callback_value))
1781+
.build();
1782+
let _ = platform_impl.send_response(&message.channel_id, ack).await;
1783+
}
17731784

17741785
// Execute the flow if we have a router
17751786
if let Some(ref router) = self.flow_router {
@@ -1896,11 +1907,17 @@ impl TriggerHandler {
18961907
if let Some(flow) = router.get_flow(flow_name) {
18971908
info!("Executing flow '{}' for message: {}", flow_name, message.text);
18981909

1899-
// Send acknowledgment
1900-
let ack = TriggerResponseBuilder::new()
1901-
.text(format!("🔄 Running {} flow...", flow_name))
1902-
.build();
1903-
let _ = platform_impl.send_response(&message.channel_id, ack).await;
1910+
// Send acknowledgment (skip for Git platforms - they create new comments)
1911+
let is_git_platform = matches!(
1912+
platform_impl.platform_name(),
1913+
"github" | "gitlab" | "bitbucket"
1914+
);
1915+
if !is_git_platform {
1916+
let ack = TriggerResponseBuilder::new()
1917+
.text(format!("🔄 Running {} flow...", flow_name))
1918+
.build();
1919+
let _ = platform_impl.send_response(&message.channel_id, ack).await;
1920+
}
19041921

19051922
// Create FlowMatch and execute
19061923
let flow_match = FlowMatch {
@@ -1933,11 +1950,17 @@ impl TriggerHandler {
19331950
if let Some(fleet_config) = self.available_fleets.get(fleet_name) {
19341951
info!("Executing fleet '{}' for message: {}", fleet_name, message.text);
19351952

1936-
// Send acknowledgment
1937-
let ack = TriggerResponseBuilder::new()
1938-
.text(format!("{} Running {} fleet...", fleet_config.emoji, fleet_config.display_name))
1939-
.build();
1940-
let _ = platform_impl.send_response(&message.channel_id, ack).await;
1953+
// Send acknowledgment (skip for Git platforms - they create new comments)
1954+
let is_git_platform = matches!(
1955+
platform_impl.platform_name(),
1956+
"github" | "gitlab" | "bitbucket"
1957+
);
1958+
if !is_git_platform {
1959+
let ack = TriggerResponseBuilder::new()
1960+
.text(format!("{} Running {} fleet...", fleet_config.emoji, fleet_config.display_name))
1961+
.build();
1962+
let _ = platform_impl.send_response(&message.channel_id, ack).await;
1963+
}
19411964

19421965
// Set user's fleet context
19431966
self.set_user_fleet(&message.user.id, fleet_name);
@@ -2060,10 +2083,18 @@ impl TriggerHandler {
20602083
self.add_to_conversation(&message.channel_id, thread_id, "user", &input);
20612084

20622085
// Send typing indicator / acknowledgment
2063-
let ack = TriggerResponseBuilder::new()
2064-
.text("🤔 Thinking...")
2065-
.build();
2066-
let _ = platform_impl.send_response(&message.channel_id, ack).await;
2086+
// Skip for GitHub/GitLab/Bitbucket - they create new comments instead of updating existing ones
2087+
// This prevents noisy "Thinking..." comments in PR threads
2088+
let is_git_platform = matches!(
2089+
platform_impl.platform_name(),
2090+
"github" | "gitlab" | "bitbucket"
2091+
);
2092+
if !is_git_platform {
2093+
let ack = TriggerResponseBuilder::new()
2094+
.text("🤔 Thinking...")
2095+
.build();
2096+
let _ = platform_impl.send_response(&message.channel_id, ack).await;
2097+
}
20672098

20682099
// Build the full input with conversation context
20692100
let input_with_context = if conversation_context.is_empty() {
@@ -2326,11 +2357,17 @@ impl TriggerHandler {
23262357

23272358
info!("Executing AgentFlow '{}' with input: {}", flow_name, input);
23282359

2329-
// Send typing indicator / acknowledgment
2330-
let ack = TriggerResponseBuilder::new()
2331-
.text(format!("🔄 Processing with flow `{}`...", flow_name))
2332-
.build();
2333-
let _ = platform_impl.send_response(&message.channel_id, ack).await;
2360+
// Send typing indicator / acknowledgment (skip for Git platforms - they create new comments)
2361+
let is_git_platform = matches!(
2362+
platform_impl.platform_name(),
2363+
"github" | "gitlab" | "bitbucket"
2364+
);
2365+
if !is_git_platform {
2366+
let ack = TriggerResponseBuilder::new()
2367+
.text(format!("🔄 Processing with flow `{}`...", flow_name))
2368+
.build();
2369+
let _ = platform_impl.send_response(&message.channel_id, ack).await;
2370+
}
23342371

23352372
// Create AgentFlowExecutor
23362373
let mut executor = AgentFlowExecutor::new(

docs/reference/daemon-config.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,32 @@ The server exposes these endpoints for each platform:
475475
| Telegram | `https://your-domain/webhook/telegram` |
476476
| Discord | `https://your-domain/webhook/discord` |
477477
| WhatsApp | `https://your-domain/webhook/whatsapp` |
478+
| GitHub | `https://your-domain/webhook/github` |
479+
| GitLab | `https://your-domain/webhook/gitlab` |
480+
| Bitbucket | `https://your-domain/webhook/bitbucket` |
481+
482+
---
483+
484+
## Git Platform Behavior
485+
486+
GitHub, GitLab, and Bitbucket handle responses differently from chat platforms:
487+
488+
| Aspect | Chat Platforms (Slack/Telegram/Discord) | Git Platforms (GitHub/GitLab/Bitbucket) |
489+
|--------|----------------------------------------|----------------------------------------|
490+
| Response style | Real-time updates | Single response only |
491+
| Progress indicators | "🤔 Thinking...", "🔄 Processing..." shown | Skipped (would create noisy comment threads) |
492+
| Message updates | Can edit existing messages | Creates new comments |
493+
| Best for | Interactive conversations | PR reviews, issue triage |
494+
495+
**Why single responses for Git platforms:**
496+
- Each `send_response` creates a NEW comment in GitHub/GitLab/Bitbucket
497+
- Progress indicators like "Thinking..." would flood PR threads with multiple comments
498+
- Only the final response is posted, keeping PR reviews clean and professional
499+
500+
**Example: `/review` on GitHub PR**
501+
1. User posts `/review` comment on PR
502+
2. Bot processes (no intermediate comments)
503+
3. Bot posts ONE comment with the complete review
478504

479505
---
480506

0 commit comments

Comments
 (0)