feat(desktop,service,features): show reactions in the Pull request tab's Conversation

Merged
DA
1d ago
+1050-60

C2 of the "Conversation filters and reactions" stack. It builds on C1 (#3258, merged) and targets main.

What

Emoji reactions now show under the PR description, every comment and review, and every review thread comment, the way GitHub shows them. Each reaction someone gave is a pill with its emoji and count, in GitHub's order (๐Ÿ‘ ๐Ÿ‘Ž ๐Ÿ˜„ ๐ŸŽ‰ ๐Ÿ˜• โค๏ธ ๐Ÿš€ ๐Ÿ‘€). Hovering a pill shows who gave it, using the same names as the rest of the conversation, with the reader as "You".

The member's own reactions are highlighted, but only when the read actually names the member among the reactors (see below).

This PR only reads reactions. Adding and removing a reaction comes in C3, through the shared "writes as the member" seam (W1).

How reactions are read

  • No extra requests. The conversation read already makes one GraphQL request for review threads. That same request now also asks for reactionGroups on:

    • the pull request itself (for the description),
    • its newest 100 comments and newest 100 reviews (comments(last:100) / reviews(last:100), matched to the REST entries by databaseId),
    • every thread comment.

    The 100 bound matches the conversation's bound on entries, so every entry the conversation keeps is covered.

  • viewerHasReacted is not used. The overview reads on the GitHub App's token, so viewerHasReacted describes the App's bot, not the member. Instead, reactors(first: 10) names up to ten people per reaction. They are matched to workspace members through the existing GitHub-id link (github-people.ts), and a pill is highlighted when the reader is among them.

  • Thread comments get counts only. A thread comment's reactions carry reactors { totalCount }, with no names. I measured the query's GraphQL rate-limit cost: naming reactors under every thread comment raises it from 3 points to 53, because GitHub prices each nested list it might return. As a result:

    • a thread comment's reactions are never highlighted,
    • their tooltip gives only a count ("3 reacted with ๐Ÿ‘Ž"),
    • a reaction with more than ten people that doesn't list the member is not highlighted either.

    C3 is meant to bring highlights back on thread comments by reading the member's own reactions through W1's member-token seam.

  • If the GraphQL read fails, the reactions and threads are left out, as before, and the rest of the conversation still shows.

Wire

New fields:

  • REACTION, ReactionGroup, and OVERVIEW_BOUNDS.MAX_REACTORS (10).
  • An optional reactions on conversation entries and on review-thread comments.
  • An optional descriptionReactions on the conversation answer.

Each field is left out when nothing was given, so a response from an older service and one with no reactions look the same. The two coding-agent-*-codingAgentOverviewConversationAnswer*Schema.json goldens were re-recorded with LUKE_UPDATE_FIXTURES=1. Their only change is the new optional reactions / descriptionReactions schema.

Screenshots

Reactions under the description, a review, a thread comment (count only) and a comment, with the reader's own highlighted. Below it, the tooltip (fake data from a throwaway harness):

Reactions Reaction tooltip

Tests

  • pull-request-overview.test.ts: reactions on the description, a comment, a review and a thread comment all come from the one GraphQL request, in GitHub's order, only the ones given, with reactors named. A thread comment's reactions are counted only.
  • agent-pull-request-tab.test.ts: the pills, their tooltips, and the highlight, which shows only when the read names the reader.

pnpm check:affected ran out of memory here, so I ran the per-package checks instead: tsc for desktop, service and features; vitest for features, service github and desktop tasks (1379 tests); ./scripts/oxlint.sh; pnpm knip; ./scripts/repository-checks.sh; and pnpm discarded-effect. All pass.

Made with Luke


Devin Review


Summary by cubic

Shows emoji reactions in the Pull request tab's Conversation, drawn under the PR description, every comment and review, and every review thread comment as GitHub draws them: a pill per reaction with its emoji and count in GitHub's order. Hovering a pill names who reacted using the conversation's names, with the reader as "You", and the reader's own reactions are highlighted where the read names them.

  • Reactions come from the one GraphQL ask the conversation already makes for review threads, so no extra requests are made.
  • Thread comments' reactions carry counts only โ€” no names and no highlight โ€” because naming reactors under every thread comment raises that read's rate-limit cost from 3 points to 53.
  • A kept comment the GraphQL read misses (its newest 100 count empty entries) is counted by the rollup its REST listing carries, without names.
  • The pills draw in the shared --luke-* tokens (the compatibility aliases they previously read were removed from main).
  • This change only reads reactions; adding and removing them comes in a later step.