fix(tui): show conversation context

This commit is contained in:
Vincent Koc 2026-05-03 04:03:28 -07:00
parent 84b8c83747
commit 282ac2863e
No known key found for this signature in database
2 changed files with 57 additions and 1 deletions

View File

@ -3271,6 +3271,9 @@ func (m model) chatDetailLines(item Item, width int) []string {
if thread := m.threadLines(item, width); len(thread) > 0 {
lines = append(lines, "", dim(tuiRule(width)), bold("Thread"))
lines = appendLimitedDetailLines(lines, thread, detailBodyLimit(m.compactDetail))
} else if conversation := m.conversationLines(item, width); len(conversation) > 0 {
lines = append(lines, "", dim(tuiRule(width)), bold("Conversation"))
lines = appendLimitedDetailLines(lines, conversation, detailBodyLimit(m.compactDetail))
} else if message := chatBodyText(item); message != "" {
lines = append(lines, "", dim(tuiRule(width)), bold("Message"))
lines = appendLimitedDetailLines(lines, chatBubbleLines(item, message, true, width), detailBodyLimit(m.compactDetail))
@ -3508,6 +3511,7 @@ func (m model) threadLines(selected Item, width int) []string {
return nil
}
var lines []string
count := 0
for _, itemIndex := range m.currentGroupMembers() {
if itemIndex < 0 || itemIndex >= len(m.items) {
continue
@ -3516,9 +3520,42 @@ func (m model) threadLines(selected Item, width int) []string {
if threadKey(item) != key {
continue
}
count++
text := chatBodyText(item)
lines = append(lines, chatBubbleLines(item, text, item.ID == selected.ID, width)...)
}
if count <= 1 {
return nil
}
return lines
}
func (m model) conversationLines(selected Item, width int) []string {
members := m.currentGroupMembers()
if len(members) <= 1 {
return nil
}
selectedIndex := -1
for index, itemIndex := range members {
if itemIndex >= 0 && itemIndex < len(m.items) && m.items[itemIndex].ID == selected.ID {
selectedIndex = index
break
}
}
if selectedIndex < 0 {
return nil
}
radius := 8
start := maxInt(0, selectedIndex-radius)
end := minInt(len(members), selectedIndex+radius+1)
var lines []string
for _, itemIndex := range members[start:end] {
if itemIndex < 0 || itemIndex >= len(m.items) {
continue
}
item := m.items[itemIndex]
lines = append(lines, chatBubbleLines(item, chatBodyText(item), item.ID == selected.ID, width)...)
}
if len(lines) <= 1 {
return nil
}

View File

@ -486,6 +486,25 @@ func TestChatDetailRendersMarkdownTranscriptLikeGitcrawl(t *testing.T) {
}
}
func TestChatDetailFallsBackToConversationWindow(t *testing.T) {
m := newModel(Options{
Title: "discrawl archive",
Layout: LayoutChat,
Items: []Item{
Row{Kind: "message", ID: "m1", Container: "general", Author: "amy", Text: "before", CreatedAt: "2026-05-01T10:00:00Z"}.ItemForLayout(LayoutChat),
Row{Kind: "message", ID: "m2", Container: "general", Author: "bob", Text: "selected", CreatedAt: "2026-05-01T10:01:00Z"}.ItemForLayout(LayoutChat),
Row{Kind: "message", ID: "m3", Container: "general", Author: "cam", Text: "after", CreatedAt: "2026-05-01T10:02:00Z"}.ItemForLayout(LayoutChat),
},
})
m.selectItemIndex(1)
joined := stripANSI(strings.Join(m.detailLinesForWidth(m.items[1], 60), "\n"))
for _, want := range []string{"Conversation", "amy", "before", "> bob", "selected", "cam", "after"} {
if !strings.Contains(joined, want) {
t.Fatalf("conversation detail missing %q:\n%s", want, joined)
}
}
}
func TestChatDetailDoesNotTreatMetadataAsMessageBody(t *testing.T) {
m := newModel(Options{
Title: "slacrawl archive",
@ -546,7 +565,7 @@ func TestChatDetailKeepsRawIDsBelowReadableSummary(t *testing.T) {
})
m.compactDetail = false
joined := stripANSI(strings.Join(m.detailLinesForWidth(m.items[0], 64), "\n"))
firstSection := strings.Split(joined, "Thread")[0]
firstSection := strings.Split(joined, "Properties")[0]
if strings.Contains(firstSection, "C0AQ7TZR9KP") || strings.Contains(firstSection, "1776788221") {
t.Fatalf("chat summary leaked raw ids before readable content:\n%s", joined)
}