Skip to content

Commit 96f3a73

Browse files
mingmxrenclaude
andcommitted
improve(session): redesign /session list display for clarity
- Show summary (truncated to 40 chars) as primary identifier - Move #id to trailing parentheses to reduce visual noise - Use relative time (2h ago) instead of absolute timestamps - Add Summary field to SessionMeta, populated from Session.Summary - List row number = resume parameter, zero ambiguity Before: 1. [*] agent:main:telegram:direct:300900269#10 | updated: 2026-03-01 23:22 | messages: 8 After: 1. [*] Discussing React performance... | 8 msgs | 2h ago (sipeed#10) Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent 84e945c commit 96f3a73

3 files changed

Lines changed: 62 additions & 9 deletions

File tree

pkg/commands/cmd_session.go

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"strconv"
77
"strings"
8+
"time"
89

910
"github.com/sipeed/picoclaw/pkg/session"
1011
)
@@ -72,20 +73,65 @@ func sessionResumeHandler() Handler {
7273

7374
func formatSessionList(list []session.SessionMeta) string {
7475
lines := make([]string, 0, len(list)+1)
75-
lines = append(lines, "Sessions for current chat:")
76+
lines = append(lines, "Sessions:")
77+
now := time.Now()
7678
for _, item := range list {
77-
activeMarker := " "
79+
activeMarker := " "
7880
if item.Active {
79-
activeMarker = "*"
81+
activeMarker = "[*]"
8082
}
81-
updated := "-"
83+
84+
summary := truncateSummary(item.Summary, 40)
85+
86+
age := "-"
8287
if !item.UpdatedAt.IsZero() {
83-
updated = item.UpdatedAt.Format("2006-01-02 15:04")
88+
age = relativeTime(now, item.UpdatedAt)
8489
}
90+
91+
tag := extractSessionTag(item.SessionKey)
92+
8593
lines = append(lines, fmt.Sprintf(
86-
"%d. [%s] %s | updated: %s | messages: %d",
87-
item.Ordinal, activeMarker, item.SessionKey, updated, item.MessageCnt,
94+
"%d. %s %s | %d msgs | %s (%s)",
95+
item.Ordinal, activeMarker, summary, item.MessageCnt, age, tag,
8896
))
8997
}
9098
return strings.Join(lines, "\n")
9199
}
100+
101+
func truncateSummary(s string, maxLen int) string {
102+
s = strings.TrimSpace(s)
103+
if s == "" {
104+
return "(no summary)"
105+
}
106+
s = strings.ReplaceAll(s, "\n", " ")
107+
if len(s) <= maxLen {
108+
return s
109+
}
110+
return s[:maxLen] + "..."
111+
}
112+
113+
// extractSessionTag returns the "#N" suffix from a session key, or "#1" for
114+
// the initial session that has no "#" separator.
115+
func extractSessionTag(sessionKey string) string {
116+
if i := strings.LastIndex(sessionKey, "#"); i >= 0 {
117+
return "#" + sessionKey[i+1:]
118+
}
119+
return "#1"
120+
}
121+
122+
func relativeTime(now, t time.Time) string {
123+
d := now.Sub(t)
124+
switch {
125+
case d < time.Minute:
126+
return "just now"
127+
case d < time.Hour:
128+
m := int(d.Minutes())
129+
return fmt.Sprintf("%dm ago", m)
130+
case d < 24*time.Hour:
131+
h := int(d.Hours())
132+
return fmt.Sprintf("%dh ago", h)
133+
default:
134+
days := int(d.Hours() / 24)
135+
return fmt.Sprintf("%dd ago", days)
136+
}
137+
}

pkg/commands/session_handlers_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package commands
33
import (
44
"context"
55
"errors"
6+
"strings"
67
"testing"
78
"time"
89

@@ -119,6 +120,7 @@ func TestSessionHandlers_SessionList(t *testing.T) {
119120
UpdatedAt: time.Date(2026, 3, 1, 9, 7, 0, 0, time.UTC),
120121
MessageCnt: 4,
121122
Active: true,
123+
Summary: "Discussing React performance",
122124
},
123125
},
124126
}
@@ -135,8 +137,11 @@ func TestSessionHandlers_SessionList(t *testing.T) {
135137
if res.Outcome != OutcomeHandled {
136138
t.Fatalf("outcome=%v, want=%v", res.Outcome, OutcomeHandled)
137139
}
138-
if reply != "Sessions for current chat:\n1. [*] scope#3 | updated: 2026-03-01 09:07 | messages: 4" {
139-
t.Fatalf("reply=%q", reply)
140+
// Check key elements: header, active marker, summary, message count, session tag
141+
for _, want := range []string{"Sessions:", "[*]", "Discussing React performance", "4 msgs", "(#3)"} {
142+
if !strings.Contains(reply, want) {
143+
t.Fatalf("reply missing %q, got %q", want, reply)
144+
}
140145
}
141146
}
142147

pkg/session/manager.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type SessionMeta struct {
5151
UpdatedAt time.Time `json:"updated_at"`
5252
MessageCnt int `json:"message_cnt"`
5353
Active bool `json:"active"`
54+
Summary string `json:"summary,omitempty"`
5455
}
5556

5657
type SessionManager struct {
@@ -740,6 +741,7 @@ func (sm *SessionManager) buildSessionMetaListLocked(scope *scopeIndex) []Sessio
740741
if session, ok := sm.sessions[key]; ok {
741742
meta.UpdatedAt = session.Updated
742743
meta.MessageCnt = len(session.Messages)
744+
meta.Summary = session.Summary
743745
}
744746
list = append(list, meta)
745747
}

0 commit comments

Comments
 (0)