feat: add /new and /clear commands to reset current chat session (#572)
This commit is contained in:
parent
4a7605ee14
commit
b41667cf06
4 changed files with 120 additions and 0 deletions
|
|
@ -1453,6 +1453,35 @@ func (al *AgentLoop) handleCommand(ctx context.Context, msg bus.InboundMessage)
|
|||
default:
|
||||
return fmt.Sprintf("Unknown switch target: %s", target), true
|
||||
}
|
||||
|
||||
case "/new", "/clear":
|
||||
route := al.registry.ResolveRoute(routing.RouteInput{
|
||||
Channel: msg.Channel,
|
||||
AccountID: msg.Metadata["account_id"],
|
||||
Peer: extractPeer(msg),
|
||||
ParentPeer: extractParentPeer(msg),
|
||||
GuildID: msg.Metadata["guild_id"],
|
||||
TeamID: msg.Metadata["team_id"],
|
||||
})
|
||||
|
||||
agent, ok := al.registry.GetAgent(route.AgentID)
|
||||
if !ok {
|
||||
agent = al.registry.GetDefaultAgent()
|
||||
}
|
||||
if agent == nil {
|
||||
return "No agent available for this conversation", true
|
||||
}
|
||||
|
||||
sessionKey := route.SessionKey
|
||||
if msg.SessionKey != "" && strings.HasPrefix(msg.SessionKey, "agent:") {
|
||||
sessionKey = msg.SessionKey
|
||||
}
|
||||
|
||||
agent.Sessions.Save(sessionKey)
|
||||
agent.Sessions.ResetSession(sessionKey)
|
||||
agent.ContextBuilder.InvalidateCache()
|
||||
|
||||
return "Started a new conversation. Previous context has been cleared for this chat.", true
|
||||
}
|
||||
|
||||
return "", false
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/sipeed/picoclaw/pkg/config"
|
||||
"github.com/sipeed/picoclaw/pkg/media"
|
||||
"github.com/sipeed/picoclaw/pkg/providers"
|
||||
"github.com/sipeed/picoclaw/pkg/routing"
|
||||
"github.com/sipeed/picoclaw/pkg/tools"
|
||||
)
|
||||
|
||||
|
|
@ -949,3 +950,38 @@ func TestResolveMediaRefs_UsesMetaContentType(t *testing.T) {
|
|||
t.Fatalf("expected jpeg prefix, got %q", result[0].Media[0][:30])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestProcessMessage_NewCommandResetsSession(t *testing.T) {
|
||||
al, _, _, _, cleanup := newTestAgentLoop(t)
|
||||
defer cleanup()
|
||||
|
||||
agent := al.registry.GetDefaultAgent()
|
||||
if agent == nil {
|
||||
t.Fatal("no default agent")
|
||||
}
|
||||
|
||||
sessionKey := routing.BuildAgentMainSessionKey(agent.ID)
|
||||
agent.Sessions.AddMessage(sessionKey, "user", "old message")
|
||||
agent.Sessions.SetSummary(sessionKey, "old summary")
|
||||
|
||||
resp, err := al.processMessage(context.Background(), bus.InboundMessage{
|
||||
Channel: "webchat",
|
||||
ChatID: "chat1",
|
||||
Content: "/new",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("processMessage error: %v", err)
|
||||
}
|
||||
if !strings.Contains(resp, "Started a new conversation") {
|
||||
t.Fatalf("unexpected response: %q", resp)
|
||||
}
|
||||
|
||||
history := agent.Sessions.GetHistory(sessionKey)
|
||||
if len(history) != 0 {
|
||||
t.Fatalf("expected session history to be cleared, got %d messages", len(history))
|
||||
}
|
||||
if summary := agent.Sessions.GetSummary(sessionKey); summary != "" {
|
||||
t.Fatalf("expected summary to be cleared, got %q", summary)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,3 +280,26 @@ func (sm *SessionManager) SetHistory(key string, history []providers.Message) {
|
|||
session.Updated = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
// ResetSession clears the conversation history and summary for a session key
|
||||
// while preserving the same session identity.
|
||||
func (sm *SessionManager) ResetSession(key string) {
|
||||
sm.mu.Lock()
|
||||
defer sm.mu.Unlock()
|
||||
|
||||
session, ok := sm.sessions[key]
|
||||
if !ok {
|
||||
session = &Session{
|
||||
Key: key,
|
||||
Messages: []providers.Message{},
|
||||
Created: time.Now(),
|
||||
Updated: time.Now(),
|
||||
}
|
||||
sm.sessions[key] = session
|
||||
return
|
||||
}
|
||||
|
||||
session.Messages = []providers.Message{}
|
||||
session.Summary = ""
|
||||
session.Updated = time.Now()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,3 +72,35 @@ func TestSave_RejectsPathTraversal(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResetSession_ClearsHistoryAndSummary(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
sm := NewSessionManager(tmpDir)
|
||||
key := "telegram:123456"
|
||||
|
||||
sm.AddMessage(key, "user", "hello")
|
||||
sm.SetSummary(key, "old summary")
|
||||
|
||||
sm.ResetSession(key)
|
||||
|
||||
history := sm.GetHistory(key)
|
||||
if len(history) != 0 {
|
||||
t.Fatalf("expected empty history after reset, got %d", len(history))
|
||||
}
|
||||
if got := sm.GetSummary(key); got != "" {
|
||||
t.Fatalf("expected empty summary after reset, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResetSession_CreatesSessionIfMissing(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
sm := NewSessionManager(tmpDir)
|
||||
key := "discord:abc"
|
||||
|
||||
sm.ResetSession(key)
|
||||
|
||||
history := sm.GetHistory(key)
|
||||
if len(history) != 0 {
|
||||
t.Fatalf("expected empty history for new reset session, got %d", len(history))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue