mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
fix(reasoning): persist canonical history for DeepSeek and web chat
This commit is contained in:
+36
-12
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/sipeed/picoclaw/pkg/config"
|
||||
"github.com/sipeed/picoclaw/pkg/memory"
|
||||
"github.com/sipeed/picoclaw/pkg/providers"
|
||||
"github.com/sipeed/picoclaw/pkg/providers/messageutil"
|
||||
"github.com/sipeed/picoclaw/pkg/session"
|
||||
"github.com/sipeed/picoclaw/pkg/utils"
|
||||
)
|
||||
@@ -48,6 +49,7 @@ type sessionListItem struct {
|
||||
type sessionChatMessage struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Media []string `json:"media,omitempty"`
|
||||
Attachments []sessionChatAttachment `json:"attachments,omitempty"`
|
||||
}
|
||||
@@ -473,6 +475,18 @@ func sessionChatMessagePreview(msg sessionChatMessage) string {
|
||||
}
|
||||
|
||||
func visibleSessionMessages(messages []providers.Message, toolFeedbackMaxArgsLength int) []sessionChatMessage {
|
||||
return sessionTranscriptMessages(messages, toolFeedbackMaxArgsLength, false)
|
||||
}
|
||||
|
||||
func detailSessionMessages(messages []providers.Message, toolFeedbackMaxArgsLength int) []sessionChatMessage {
|
||||
return sessionTranscriptMessages(messages, toolFeedbackMaxArgsLength, true)
|
||||
}
|
||||
|
||||
func sessionTranscriptMessages(
|
||||
messages []providers.Message,
|
||||
toolFeedbackMaxArgsLength int,
|
||||
includeThoughts bool,
|
||||
) []sessionChatMessage {
|
||||
transcript := make([]sessionChatMessage, 0, len(messages))
|
||||
|
||||
for _, msg := range messages {
|
||||
@@ -494,11 +508,14 @@ func visibleSessionMessages(messages []providers.Message, toolFeedbackMaxArgsLen
|
||||
}
|
||||
|
||||
case "assistant":
|
||||
// Reasoning-only assistant messages are transient display artifacts and
|
||||
// should not be restored from session history.
|
||||
if assistantMessageTransientThought(msg) {
|
||||
if messageutil.IsTransientAssistantThoughtMessage(msg) {
|
||||
continue
|
||||
}
|
||||
if includeThoughts {
|
||||
if thoughtMsg, ok := assistantThoughtMessage(msg); ok {
|
||||
transcript = append(transcript, thoughtMsg)
|
||||
}
|
||||
}
|
||||
|
||||
toolSummaryMessages := visibleAssistantToolSummaryMessages(msg.ToolCalls, toolFeedbackMaxArgsLength)
|
||||
if len(toolSummaryMessages) > 0 {
|
||||
@@ -672,18 +689,25 @@ func sessionAttachmentType(attachment providers.Attachment) string {
|
||||
}
|
||||
}
|
||||
|
||||
func assistantMessageTransientThought(msg providers.Message) bool {
|
||||
return strings.TrimSpace(msg.Content) == "" &&
|
||||
strings.TrimSpace(msg.ReasoningContent) != "" &&
|
||||
len(msg.ToolCalls) == 0 &&
|
||||
len(msg.Media) == 0 &&
|
||||
len(msg.Attachments) == 0
|
||||
}
|
||||
|
||||
func assistantMessageInternalOnly(msg providers.Message) bool {
|
||||
return strings.TrimSpace(msg.Content) == handledToolResponseSummaryText
|
||||
}
|
||||
|
||||
func assistantThoughtMessage(msg providers.Message) (sessionChatMessage, bool) {
|
||||
reasoning := strings.TrimSpace(msg.ReasoningContent)
|
||||
if reasoning == "" {
|
||||
return sessionChatMessage{}, false
|
||||
}
|
||||
if reasoning == strings.TrimSpace(msg.Content) {
|
||||
return sessionChatMessage{}, false
|
||||
}
|
||||
return sessionChatMessage{
|
||||
Role: "assistant",
|
||||
Content: reasoning,
|
||||
Kind: "thought",
|
||||
}, true
|
||||
}
|
||||
|
||||
func visibleAssistantToolSummaryMessages(
|
||||
toolCalls []providers.ToolCall,
|
||||
toolFeedbackMaxArgsLength int,
|
||||
@@ -962,7 +986,7 @@ func (h *Handler) handleGetSession(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
messages := visibleSessionMessages(sess.Messages, toolFeedbackMaxArgsLength)
|
||||
messages := detailSessionMessages(sess.Messages, toolFeedbackMaxArgsLength)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]any{
|
||||
|
||||
Reference in New Issue
Block a user