-
Notifications
You must be signed in to change notification settings - Fork 0
feat: compact message format for thread replies #82
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
Conversation
Thread replies now use a condensed format since context (repo, PR/issue number, title) is already visible in the anchor message. Format: emoji + content preview + user + link 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
WalkthroughThis PR adds an extractPreview utility and updates webhook formatters (issue comment, pull request review, review comment) to accept an optional isThreadReply flag. When isThreadReply is true the formatters emit a condensed single-line thread reply (preview, user, URL); otherwise they preserve the full message while reusing the new preview and unified user extraction. The event processor computes isThreadReply from threadingContext (true when threadingContext exists and isAnchor is false), passes it to formatters, and derives threadId/send-path based on that flag. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
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.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/formatters/webhook-events.ts(4 hunks)src/github-app/event-processor.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
**/*.ts: Store context externally - maintain stateless bot architecture with no message history, thread context, or conversation memory
Use<@{userId}>for mentions in messages AND add mentions in sendMessage options - do not use @username format
Implement event handlers for onMessage, onSlashCommand, onReaction, onTip, and onInteractionResponse to respond to Towns Protocol events
Define slash commands in src/commands.ts as a const array with name and description properties, then register handlers using bot.onSlashCommand()
Set ID in interaction requests and match ID in responses to correlate form submissions, button clicks, and transaction/signature responses
Use readContract for reading smart contract state, writeContract for SimpleAccount operations, and execute() for external contract interactions
Fund bot.appAddress (Smart Account) for on-chain operations, not bot.botId (Gas Wallet/EOA)
Use bot.* handler methods directly (outside event handlers) for unprompted messages via webhooks, timers, or tasks - requires channelId, spaceId, or other context stored externally
Always check permissions using handler.hasAdminPermission() before performing admin operations like ban, redact, or pin
User IDs are hex addresses in format 0x..., not usernames - use them consistently throughout event handling and message sending
Slash commands do not trigger onMessage - register slash command handlers using bot.onSlashCommand() instead
Use getSmartAccountFromUserId() to retrieve a user's wallet address from their userId
Include required environment variables: APP_PRIVATE_DATA (bot credentials) and JWT_SECRET (webhook security token)
Files:
src/github-app/event-processor.tssrc/formatters/webhook-events.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Provide alt text for image attachments and use appropriate MIME types for chunked attachments (videos, screenshots)
Files:
src/github-app/event-processor.tssrc/formatters/webhook-events.ts
🧠 Learnings (2)
📚 Learning: 2025-11-25T03:24:12.463Z
Learnt from: CR
Repo: HereNotThere/bot-github PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T03:24:12.463Z
Learning: All event handlers receive a base payload including userId, spaceId, channelId, eventId, and createdAt - use eventId as threadId/replyId when responding to maintain event threading
Applied to files:
src/github-app/event-processor.ts
📚 Learning: 2025-11-25T03:24:12.463Z
Learnt from: CR
Repo: HereNotThere/bot-github PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T03:24:12.463Z
Learning: Applies to **/*.ts : Use bot.* handler methods directly (outside event handlers) for unprompted messages via webhooks, timers, or tasks - requires channelId, spaceId, or other context stored externally
Applied to files:
src/github-app/event-processor.ts
🧬 Code graph analysis (1)
src/formatters/webhook-events.ts (1)
src/types/webhooks.ts (3)
IssueCommentPayload(19-19)PullRequestReviewPayload(20-20)PullRequestReviewCommentPayload(21-22)
🔇 Additional comments (4)
src/github-app/event-processor.ts (1)
85-85: Formatter signature extension is compatible with existing call sitesThe new
(event: T, isThreadReply?: boolean) => stringsignature is fine, and existing formatters that ignore the second argument (e.g., branch create/delete wrapper) remain type-safe since extra arguments are ignored at runtime.src/formatters/webhook-events.ts (3)
143-168: Thread reply format for issue comments looks correct and consistentThe new
formatIssueComment(payload, isThreadReply?):
- Uses a shared
previewanduserfor both paths, avoiding duplication.- Returns
💬 ${preview} 👤 ${user} 🔗 ${comment.html_url}whenisThreadReplyis true, which matches the desired compact pattern (emoji + preview + user + link).- Preserves the previous rich, multi-line message when
isThreadReplyis falsy.Logic and truncation behavior are sound.
170-195: PR review compact formatting and state normalization are reasonableThe updated
formatPullRequestReview(payload, isThreadReply?):
- Normalizes
review.stateviareview.state.replace("_", " "), improving readability for"changes_requested"while leaving other states unchanged.- Introduces a compact reply format
${emoji} ${state} 👤 ${user} 🔗 ${review.html_url}whenisThreadReplyis true.- Reuses the same
stateanduserin the full message path, keeping behavior consistent.This cleanly supports thread replies without regressing the full PR review message.
200-225: Review comment thread reply format matches the compact specIn
formatPullRequestReviewComment(payload, isThreadReply?):
previewanduserare shared between thread and non-thread paths.- The thread reply variant
💬 ${preview} 👤 ${user} 🔗 ${comment.html_url}aligns with the compact format requirement.- The existing multi-line message (with repo, PR number, preview, user, link) is preserved for non-threaded usage.
No functional issues spotted; this is a straightforward extension.
TypeScript's control flow analysis already narrows threadingContext in the ternary, so only the explicit boolean coercion was needed. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add extractPreview helper to strip HTML comments and markdown formatting - Apply to formatIssueComment, formatPullRequestReview, formatPullRequestReviewComment - PR reviews now show body preview when available 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
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.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/formatters/webhook-events.ts (1)
197-205: Good null check pattern; consider global replace for robustness.The
review.body ? extractPreview(...) : ""pattern on line 201 correctly guards against null bodies—this is the pattern that should also be applied informatIssueCommentandformatPullRequestReviewComment.Minor:
replace("_", " ")only replaces the first underscore. While current states likechanges_requestedonly have one underscore, usingreplaceAllwould be more future-proof.- const state = review.state.replace("_", " "); + const state = review.state.replaceAll("_", " ");
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/formatters/webhook-events.ts(5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
**/*.ts: Store context externally - maintain stateless bot architecture with no message history, thread context, or conversation memory
Use<@{userId}>for mentions in messages AND add mentions in sendMessage options - do not use @username format
Implement event handlers for onMessage, onSlashCommand, onReaction, onTip, and onInteractionResponse to respond to Towns Protocol events
Define slash commands in src/commands.ts as a const array with name and description properties, then register handlers using bot.onSlashCommand()
Set ID in interaction requests and match ID in responses to correlate form submissions, button clicks, and transaction/signature responses
Use readContract for reading smart contract state, writeContract for SimpleAccount operations, and execute() for external contract interactions
Fund bot.appAddress (Smart Account) for on-chain operations, not bot.botId (Gas Wallet/EOA)
Use bot.* handler methods directly (outside event handlers) for unprompted messages via webhooks, timers, or tasks - requires channelId, spaceId, or other context stored externally
Always check permissions using handler.hasAdminPermission() before performing admin operations like ban, redact, or pin
User IDs are hex addresses in format 0x..., not usernames - use them consistently throughout event handling and message sending
Slash commands do not trigger onMessage - register slash command handlers using bot.onSlashCommand() instead
Use getSmartAccountFromUserId() to retrieve a user's wallet address from their userId
Include required environment variables: APP_PRIVATE_DATA (bot credentials) and JWT_SECRET (webhook security token)
Files:
src/formatters/webhook-events.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Provide alt text for image attachments and use appropriate MIME types for chunked attachments (videos, screenshots)
Files:
src/formatters/webhook-events.ts
🧬 Code graph analysis (1)
src/formatters/webhook-events.ts (1)
src/types/webhooks.ts (3)
IssueCommentPayload(19-19)PullRequestReviewPayload(20-20)PullRequestReviewCommentPayload(21-22)
🔇 Additional comments (2)
src/formatters/webhook-events.ts (2)
160-184: Clean implementation of thread reply format.The condensed format
💬 "${preview}" 👤 ${user} 🔗 ${url}aligns well with the PR objective. The logic correctly gates onisThreadReplyand preserves backward compatibility when the flag is not provided.
219-243: Consistent implementation with other formatters.The thread reply format and logic mirror
formatIssueComment, maintaining good consistency. Once the null guard is added toextractPreview, this function will also be protected.
- Add null/undefined guard for body parameter - Join all lines for more context - Keep markdown formatting since Towns renders it 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Thread replies now use a condensed format since context (repo, PR/issue number, title) is already visible in the anchor message.
Format: emoji + content preview + user + link
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.