Show friendly Copilot (AI) name in gh pr view

Add CopilotDisplayName helper that translates known Copilot bot
logins (copilot-pull-request-reviewer, copilot-swe-agent) to the
friendly 'Copilot (AI)' display name. Applied to:

- PullRequestReview.AuthorLogin() — review comment author
- Comment.AuthorLogin() — PR/issue comment author
- parseReviewers() in pr view — reviewer list display

This ensures gh pr view shows 'Copilot (AI)' instead of the raw
'copilot-pull-request-reviewer' login for both the reviewer status
line and any review comments left by Copilot.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Kynan Ware 2026-03-06 10:58:57 -07:00
parent 93c4340f29
commit 04bc0d27f4
5 changed files with 39 additions and 14 deletions

View file

@ -129,7 +129,7 @@ func (c Comment) Identifier() string {
}
func (c Comment) AuthorLogin() string {
return c.Author.Login
return copilotDisplayName(c.Author.Login)
}
func (c Comment) Association() string {

View file

@ -52,7 +52,7 @@ func (prr PullRequestReview) Identifier() string {
}
func (prr PullRequestReview) AuthorLogin() string {
return prr.Author.Login
return copilotDisplayName(prr.Author.Login)
}
func (prr PullRequestReview) Association() string {
@ -158,8 +158,9 @@ func (r RequestedReviewer) DisplayName() string {
if r.TypeName == teamTypeName {
return fmt.Sprintf("%s/%s", r.Organization.Login, r.Slug)
}
if r.TypeName == botTypeName && r.Login == CopilotReviewerLogin {
return "Copilot (AI)"
displayName := copilotDisplayName(r.Login)
if displayName != r.Login {
return displayName
}
if r.Name != "" {
return fmt.Sprintf("%s (%s)", r.Login, r.Name)
@ -221,10 +222,7 @@ func NewReviewerBot(login string) ReviewerBot {
}
func (b ReviewerBot) DisplayName() string {
if b.login == CopilotReviewerLogin {
return fmt.Sprintf("%s (AI)", CopilotActorName)
}
return b.Login()
return copilotDisplayName(b.login)
}
func (r ReviewerBot) sealedReviewerCandidate() {}

View file

@ -1087,6 +1087,16 @@ const CopilotAssigneeLogin = "copilot-swe-agent"
const CopilotReviewerLogin = "copilot-pull-request-reviewer"
const CopilotActorName = "Copilot"
// copilotDisplayName returns "Copilot (AI)" if the login is a known Copilot bot login,
// otherwise returns the login unchanged. Use this to translate raw bot logins into
// user-friendly display names in command output.
func copilotDisplayName(login string) string {
if login == CopilotReviewerLogin || login == CopilotAssigneeLogin {
return fmt.Sprintf("%s (AI)", CopilotActorName)
}
return login
}
type AssignableActor interface {
DisplayName() string
ID() string
@ -1145,10 +1155,7 @@ func NewAssignableBot(id, login string) AssignableBot {
}
func (b AssignableBot) DisplayName() string {
if b.login == CopilotAssigneeLogin {
return fmt.Sprintf("%s (AI)", CopilotActorName)
}
return b.Login()
return copilotDisplayName(b.login)
}
func (b AssignableBot) ID() string {

View file

@ -563,6 +563,26 @@ func TestDisplayName(t *testing.T) {
}
}
func TestCopilotDisplayName(t *testing.T) {
tests := []struct {
login string
want string
}{
{login: "copilot-pull-request-reviewer", want: "Copilot (AI)"},
{login: "copilot-swe-agent", want: "Copilot (AI)"},
{login: "octocat", want: "octocat"},
{login: "", want: ""},
}
for _, tt := range tests {
t.Run(tt.login, func(t *testing.T) {
got := copilotDisplayName(tt.login)
if got != tt.want {
t.Errorf("copilotDisplayName(%q) = %q, want %q", tt.login, got, tt.want)
}
})
}
}
func TestRepoExists(t *testing.T) {
tests := []struct {
name string