Skip to content

feat(chat): emoji reactions on Chat messages, both directions - #1082

Merged
selfcontained merged 1 commit into
mainfrom
agt_5e43b40f67cd/agent-0f67cd
Sep 11, 2026
Merged

feat(chat): emoji reactions on Chat messages, both directions#1082
selfcontained merged 1 commit into
mainfrom
agt_5e43b40f67cd/agent-0f67cd

Conversation

@selfcontained

Copy link
Copy Markdown
Owner

Summary

Emoji reactions in the Chat tab, in both directions.

User → agent. Hover (or, on touch, always see) the smiley action on an agent post to open a picker of 12 emoji. The reaction shows as a chip under the post and is injected into the agent's pane — through the same quiet-gated delivery as a user message — so the chip carries delivery state (dimmed while pending, ⚠ when undelivered). Tap your chip to take it back; removal is display-only.

Agent → user. Agents react to the user's posts with the new dispatch_chat_react MCP tool ({ messageId, emoji, remove? }). These render as neutral chips the user can't remove and are never injected anywhere.

Reaction envelope

Identifies the post without pasting it back:

--- DISPATCH CHAT REACTION (message id: <id>) ---
The user reacted 🎉 to your summary from 3 posts ago:
> All checks pass. PR is ready for review. …
--- END DISPATCH CHAT REACTION ---
A reaction, not a new message — reply only if it calls for one (dispatch_chat_post, replyTo: "<id>").

The latest post gets ~100 chars of quote ("your latest question"); older posts up to 300 plus how far back they are. Quoted text passes through escapeEnvelopeMarkers.

Implementation

  • DB: 0051_agent-chat-reactions — one row per (message, author, emoji), FK cascade to the message, delivered for user reactions, partial index for the startup recovery sweep. (0050 is the latest migration applied in production.)
  • Server: ChatService.addReaction/removeReaction (author-aware), shared injectDetached settlement chain for messages and reactions, POST/DELETE /agents/:id/chat/messages/:messageId/reactions, reactions aggregated onto feed chat rows and republished via chat.entry.
  • Web: new chat-reactions.tsx (picker + chip row); framer-motion pop-in/out with sibling slide, row collapses only after the last chip's exit; picker grows open with staggered emoji; reduced-motion respected; picker greys out (not hidden) when the agent can't receive; optimistic toggles that never clobber a newer stream entry.
  • Docs: docs/03-api-spec.md Chat section.

Review

  • architecture-review (#1341): 1 item (split reaction UI out of chat-entries.tsx) — fixed and verified.
  • frontend-ux-review (#1342): 4 items (disabled vs hidden picker, error attribution + in-flight chips, last-chip exit animation, touch affordance) — fixed and verified. The hover/touch × was later removed at the user's request (Slack-style tap-to-remove).

Test plan

  • pnpm run check
  • pnpm run finalize:web
  • pnpm run test (server + web + extension)
  • pnpm run test:e2e (198 passed, 12 skipped)
  • Playwright on a dev stack: add/remove via picker and chips, agent reactions via MCP with live updates, animation frames sampled, 400px layout

🤖 Generated with Claude Code

Users react to agent posts from a picker on each post; the reaction shows
as a chip and is injected into the agent's pane in a DISPATCH CHAT
REACTION envelope that names the post by id, kind, position among the
agent's posts, and a bounded quote of its opening. Agents react to the
user's posts with the new dispatch_chat_react MCP tool (display-only).

- agent_chat_reactions table (0051): one row per message/author/emoji,
  delivery state for user reactions, recovery sweep on startup.
- Reactions ride on the feed's chat rows and republish via chat.entry.
- Web: animated picker and chips (framer-motion), optimistic toggles,
  tap a chip to remove; reaction UI lives in chat-reactions.tsx.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@selfcontained
selfcontained merged commit 92f3405 into main Sep 11, 2026
1 check passed
@selfcontained
selfcontained deleted the agt_5e43b40f67cd/agent-0f67cd branch September 11, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant