improve(session): use first user message as preview fallback in session list
When a session has no summary (most short conversations), show the first user message content instead. Display priority: summary > preview > "(empty)". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b323131c27
commit
c917184375
3 changed files with 66 additions and 9 deletions
|
|
@ -81,7 +81,7 @@ func formatSessionList(list []session.SessionMeta) string {
|
|||
activeMarker = "[*]"
|
||||
}
|
||||
|
||||
summary := truncateSummary(item.Summary, 40)
|
||||
summary := sessionLabel(item.Summary, item.Preview, 40)
|
||||
|
||||
age := "-"
|
||||
if !item.UpdatedAt.IsZero() {
|
||||
|
|
@ -98,16 +98,21 @@ func formatSessionList(list []session.SessionMeta) string {
|
|||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
func truncateSummary(s string, maxLen int) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return "(no summary)"
|
||||
// sessionLabel picks the best display text for a session list row:
|
||||
// summary (if available) > first user message preview > "(empty)".
|
||||
func sessionLabel(summary, preview string, maxLen int) string {
|
||||
text := strings.TrimSpace(summary)
|
||||
if text == "" {
|
||||
text = strings.TrimSpace(preview)
|
||||
}
|
||||
s = strings.ReplaceAll(s, "\n", " ")
|
||||
if len(s) <= maxLen {
|
||||
return s
|
||||
if text == "" {
|
||||
return "(empty)"
|
||||
}
|
||||
return s[:maxLen] + "..."
|
||||
text = strings.ReplaceAll(text, "\n", " ")
|
||||
if len(text) <= maxLen {
|
||||
return text
|
||||
}
|
||||
return text[:maxLen] + "..."
|
||||
}
|
||||
|
||||
// extractSessionTag returns the "#N" suffix from a session key, or "#1" for
|
||||
|
|
|
|||
|
|
@ -145,6 +145,47 @@ func TestSessionHandlers_SessionList(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSessionHandlers_SessionList_PreviewFallback(t *testing.T) {
|
||||
ops := &fakeSessionOps{
|
||||
listValue: []session.SessionMeta{
|
||||
{
|
||||
Ordinal: 1,
|
||||
SessionKey: "scope#2",
|
||||
UpdatedAt: time.Date(2026, 3, 1, 9, 0, 0, 0, time.UTC),
|
||||
MessageCnt: 3,
|
||||
Active: true,
|
||||
Preview: "How do I fix this login bug?",
|
||||
},
|
||||
{
|
||||
Ordinal: 2,
|
||||
SessionKey: "scope",
|
||||
MessageCnt: 0,
|
||||
},
|
||||
},
|
||||
}
|
||||
rt := &Runtime{SessionOps: ops}
|
||||
ex := NewExecutor(NewRegistry(BuiltinDefinitions()), rt)
|
||||
|
||||
var reply string
|
||||
res := ex.Execute(context.Background(), Request{
|
||||
ScopeKey: "scope",
|
||||
Text: "/session list",
|
||||
Reply: func(text string) error { reply = text; return nil },
|
||||
})
|
||||
|
||||
if res.Outcome != OutcomeHandled {
|
||||
t.Fatalf("outcome=%v, want=%v", res.Outcome, OutcomeHandled)
|
||||
}
|
||||
// Row 1: no summary → falls back to preview
|
||||
if !strings.Contains(reply, "How do I fix this login bug?") {
|
||||
t.Fatalf("reply missing preview fallback, got %q", reply)
|
||||
}
|
||||
// Row 2: no summary, no preview, no messages → "(empty)"
|
||||
if !strings.Contains(reply, "(empty)") {
|
||||
t.Fatalf("reply missing (empty) for blank session, got %q", reply)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionHandlers_NilRuntime_Unavailable(t *testing.T) {
|
||||
ex := NewExecutor(NewRegistry(BuiltinDefinitions()), nil)
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ type SessionMeta struct {
|
|||
MessageCnt int `json:"message_cnt"`
|
||||
Active bool `json:"active"`
|
||||
Summary string `json:"summary,omitempty"`
|
||||
Preview string `json:"preview,omitempty"` // first user message content
|
||||
}
|
||||
|
||||
type SessionManager struct {
|
||||
|
|
@ -742,12 +743,22 @@ func (sm *SessionManager) buildSessionMetaListLocked(scope *scopeIndex) []Sessio
|
|||
meta.UpdatedAt = session.Updated
|
||||
meta.MessageCnt = len(session.Messages)
|
||||
meta.Summary = session.Summary
|
||||
meta.Preview = firstUserMessage(session.Messages)
|
||||
}
|
||||
list = append(list, meta)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func firstUserMessage(msgs []providers.Message) string {
|
||||
for _, m := range msgs {
|
||||
if m.Role == "user" && strings.TrimSpace(m.Content) != "" {
|
||||
return m.Content
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func prependSessionUnique(ordered []string, sessionKey string) []string {
|
||||
next := make([]string, 0, len(ordered)+1)
|
||||
next = append(next, sessionKey)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue