feat: Add bot API endpoints for reading messages and adding reactions#190
feat: Add bot API endpoints for reading messages and adding reactions#190jpshackelford wants to merge 6 commits intobasecamp:mainfrom
Conversation
Adds a new GET endpoint at /rooms/:room_id/:bot_key/messages that allows bots to read messages from rooms they are members of. The endpoint returns JSON with: - Room info (id, name) - Messages array with body (plain/html), created_at, and creator info - Pagination info (oldest_id, newest_id, has_more) Supports pagination via ?before=:id and ?after=:id query parameters, consistent with the existing pagination in the messages controller. This enables AI bots and other automated agents to understand conversation context when responding to messages, rather than only receiving the single message that triggered the webhook. Co-authored-by: openhands <openhands@all-hands.dev>
Added explicit RecordNotFound handling to return 404 when a bot tries to read messages from a room it's not a member of. This matches the security model used by the create action. Added tests to verify: - Bot gets 404 when trying to read from room it's not a member of - Bot can successfully read from room it IS a member of Co-authored-by: openhands <openhands@all-hands.dev>
There was a problem hiding this comment.
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| test "index supports pagination with after parameter" do | ||
| get room_bot_messages_index_url(@room, users(:bender).bot_key, after: Message.first.id) | ||
| assert_response :success | ||
| end |
There was a problem hiding this comment.
This test uses Message.first.id which is 1, but message 1 belongs to the 'designers' room, not the 'watercooler' room (@room). When the controller tries to find this message in the watercooler room, it will raise a RecordNotFound error. Use a message ID that actually belongs to the watercooler room, such as creating a message in setup or using a message ID from the watercooler fixtures.
There was a problem hiding this comment.
Fixed in commit c82a8d3 - now using messages(:fourth) and messages(:thirteenth) which are fixtures belonging to the watercooler room where the bender bot is a member.
Both create and index now return HTTP 404 Not Found when a bot tries to access a room it's not a member of. This is consistent with REST API security best practices (not revealing resource existence) and ensures read and write permissions are handled identically. Changed create action to no longer call super (which rendered HTML) and instead directly handle the request with proper JSON API error responses. Added test to verify create returns 404 for non-member rooms. Co-authored-by: openhands <openhands@all-hands.dev>
Fixed test bug identified by Copilot code review: pagination tests were using Message.first and Message.last which could return messages from different rooms than the test's @room (watercooler). Now explicitly using messages(:fourth) and messages(:thirteenth) which are fixtures belonging to the watercooler room where bender bot is a member. Co-authored-by: openhands <openhands@all-hands.dev>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| creator: { | ||
| id: message.creator.id, | ||
| name: message.creator.name, | ||
| is_bot: message.creator.role == "bot" |
There was a problem hiding this comment.
Use the enum predicate method bot? instead of comparing to the string "bot". This is consistent with how the codebase checks enum values elsewhere (e.g., administrator? in User::Role) and is the idiomatic Rails pattern for enum checks.
There was a problem hiding this comment.
Fixed in e8c1349 - now using message.creator.bot? which is the idiomatic Rails enum predicate pattern.
Changed `message.creator.role == "bot"` to `message.creator.bot?` per Copilot code review. This is the idiomatic Rails pattern for enum checks and consistent with how other role checks are done in the codebase. Co-authored-by: openhands <openhands@all-hands.dev>
|
@flavorjones This is the same level of rights we have for the OpenHands agent in our Slack integration which allows humans to discuss an issue in channel and then one can just ask the agent to fix it and the agent then can obtain the context needed to start work without requiring a user to reiterate the entire discussion in a new message to the bot. |
Updated setup script to use jpshackelford/once-campfire:bot-read-messages which includes the bot message reading API (PR #190 to basecamp/once-campfire). This allows bots to read conversation context when responding to messages. Changes: - Default image changed to fork with bot read API - Added --campfire-image flag for custom image - Added --use-official-campfire flag to use upstream image Once PR #190 is merged upstream, we can switch back to the official image. PR: basecamp/once-campfire#190 Co-authored-by: openhands <openhands@all-hands.dev>
Adds a new endpoint that allows bots to add emoji reactions (boosts) to messages: POST /rooms/:room_id/:bot_key/messages/:message_id/boosts This enables bots to acknowledge messages with reactions like 👀 (eyes) when mentioned, providing immediate feedback to users before generating a full response. The endpoint: - Validates the bot is a member of the room - Validates the message exists in the room - Broadcasts the boost to connected clients via Turbo Streams - Returns 201 Created on success, 404 if room/message not found Co-authored-by: openhands <openhands@all-hands.dev>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Adds two new API endpoints for bots:
/rooms/:room_id/:bot_key/messages- Read messages from rooms/rooms/:room_id/:bot_key/messages/:message_id/boosts- Add emoji reactions to messagesMotivation
Currently, bots can only receive individual messages via webhooks when they are @mentioned (or all messages in DMs). This makes it difficult for AI-powered bots and other automated agents to understand the conversation context when formulating responses.
These changes enable bots to:
Changes
Endpoint 1: Read Messages
Response Format (JSON):
{ "room": { "id": 1, "name": "General" }, "messages": [ { "id": 123, "body": { "plain": "Hello world", "html": "<p>Hello world</p>" }, "created_at": "2024-01-15T10:30:00Z", "creator": { "id": 42, "name": "Jane Doe", "is_bot": false } } ], "pagination": { "oldest_id": 100, "newest_id": 123, "has_more": true } }Pagination:
?before=:id- Get messages before this message ID?after=:id- Get messages after this message IDEndpoint 2: Add Reaction (Boost)
Request Body:
{ "content": "👀" }Behavior:
Security Considerations
/rooms/:room_id/messagesendpoint remains forbidden for botsTests
Added tests for:
Read Messages endpoint:
Add Reaction endpoint:
This PR was created by an AI assistant (OpenHands) on behalf of @jpshackelford.