mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
fix(review): align tool feedback reconstruction with runtime behavior
This commit is contained in:
+32
-19
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -74,12 +73,15 @@ const (
|
||||
// pkg/memory/jsonl.go so oversized lines fail consistently everywhere.
|
||||
maxSessionJSONLLineSize = 10 * 1024 * 1024
|
||||
maxSessionTitleRunes = 60
|
||||
// Keep session reconstruction aligned with tool_feedback max args preview.
|
||||
sessionToolFeedbackMaxArgsLength = 300
|
||||
|
||||
handledToolResponseSummaryText = "Requested output delivered via tool attachment."
|
||||
)
|
||||
|
||||
func defaultToolFeedbackMaxArgsLength() int {
|
||||
defaults := config.AgentDefaults{}
|
||||
return defaults.GetToolFeedbackMaxArgsLength()
|
||||
}
|
||||
|
||||
// extractPicoSessionID extracts the session UUID from a full session key.
|
||||
// Returns the UUID and true if the key matches the Pico session pattern.
|
||||
func extractPicoSessionID(key string) (string, bool) {
|
||||
@@ -206,7 +208,7 @@ func (h *Handler) readJSONLSession(dir, sessionID string) (sessionFile, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func buildSessionListItem(sessionID string, sess sessionFile) sessionListItem {
|
||||
func buildSessionListItem(sessionID string, sess sessionFile, toolFeedbackMaxArgsLength int) sessionListItem {
|
||||
preview := ""
|
||||
for _, msg := range sess.Messages {
|
||||
if msg.Role == "user" {
|
||||
@@ -223,7 +225,7 @@ func buildSessionListItem(sessionID string, sess sessionFile) sessionListItem {
|
||||
}
|
||||
title := preview
|
||||
|
||||
validMessageCount := len(visibleSessionMessages(sess.Messages))
|
||||
validMessageCount := len(visibleSessionMessages(sess.Messages, toolFeedbackMaxArgsLength))
|
||||
|
||||
return sessionListItem{
|
||||
ID: sessionID,
|
||||
@@ -264,7 +266,7 @@ func sessionMessagePreview(msg providers.Message) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func visibleSessionMessages(messages []providers.Message) []sessionChatMessage {
|
||||
func visibleSessionMessages(messages []providers.Message, toolFeedbackMaxArgsLength int) []sessionChatMessage {
|
||||
transcript := make([]sessionChatMessage, 0, len(messages))
|
||||
|
||||
for _, msg := range messages {
|
||||
@@ -279,7 +281,7 @@ func visibleSessionMessages(messages []providers.Message) []sessionChatMessage {
|
||||
}
|
||||
|
||||
case "assistant":
|
||||
toolSummaryMessages := visibleAssistantToolSummaryMessages(msg.ToolCalls)
|
||||
toolSummaryMessages := visibleAssistantToolSummaryMessages(msg.ToolCalls, toolFeedbackMaxArgsLength)
|
||||
if len(toolSummaryMessages) > 0 {
|
||||
transcript = append(transcript, toolSummaryMessages...)
|
||||
}
|
||||
@@ -311,10 +313,13 @@ func assistantMessageInternalOnly(msg providers.Message) bool {
|
||||
return strings.TrimSpace(msg.Content) == handledToolResponseSummaryText
|
||||
}
|
||||
|
||||
func visibleAssistantToolSummaryMessages(toolCalls []providers.ToolCall) []sessionChatMessage {
|
||||
func visibleAssistantToolSummaryMessages(toolCalls []providers.ToolCall, toolFeedbackMaxArgsLength int) []sessionChatMessage {
|
||||
if len(toolCalls) == 0 {
|
||||
return nil
|
||||
}
|
||||
if toolFeedbackMaxArgsLength <= 0 {
|
||||
toolFeedbackMaxArgsLength = defaultToolFeedbackMaxArgsLength()
|
||||
}
|
||||
|
||||
messages := make([]sessionChatMessage, 0, len(toolCalls))
|
||||
for _, tc := range toolCalls {
|
||||
@@ -344,17 +349,13 @@ func visibleAssistantToolSummaryMessages(toolCalls []providers.ToolCall) []sessi
|
||||
|
||||
messages = append(messages, sessionChatMessage{
|
||||
Role: "assistant",
|
||||
Content: formatToolCallSummary(name, utils.Truncate(argsPreview, sessionToolFeedbackMaxArgsLength)),
|
||||
Content: utils.FormatToolFeedbackMessage(name, utils.Truncate(argsPreview, toolFeedbackMaxArgsLength)),
|
||||
})
|
||||
}
|
||||
|
||||
return messages
|
||||
}
|
||||
|
||||
func formatToolCallSummary(name, argsPreview string) string {
|
||||
return fmt.Sprintf("\U0001f527 `%s`\n```\n%s\n```", name, argsPreview)
|
||||
}
|
||||
|
||||
func visibleAssistantToolMessages(toolCalls []providers.ToolCall) []sessionChatMessage {
|
||||
if len(toolCalls) == 0 {
|
||||
return nil
|
||||
@@ -400,7 +401,19 @@ func (h *Handler) sessionsDir() (string, error) {
|
||||
return "", err
|
||||
}
|
||||
|
||||
workspace := cfg.Agents.Defaults.Workspace
|
||||
return resolveSessionsDir(cfg.Agents.Defaults.Workspace), nil
|
||||
}
|
||||
|
||||
func (h *Handler) sessionRuntimeSettings() (string, int, error) {
|
||||
cfg, err := config.LoadConfig(h.configPath)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
return resolveSessionsDir(cfg.Agents.Defaults.Workspace), cfg.Agents.Defaults.GetToolFeedbackMaxArgsLength(), nil
|
||||
}
|
||||
|
||||
func resolveSessionsDir(workspace string) string {
|
||||
if workspace == "" {
|
||||
home, _ := os.UserHomeDir()
|
||||
workspace = filepath.Join(home, ".picoclaw", "workspace")
|
||||
@@ -416,14 +429,14 @@ func (h *Handler) sessionsDir() (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return filepath.Join(workspace, "sessions"), nil
|
||||
return filepath.Join(workspace, "sessions")
|
||||
}
|
||||
|
||||
// handleListSessions returns a list of Pico session summaries.
|
||||
//
|
||||
// GET /api/sessions
|
||||
func (h *Handler) handleListSessions(w http.ResponseWriter, r *http.Request) {
|
||||
dir, err := h.sessionsDir()
|
||||
dir, toolFeedbackMaxArgsLength, err := h.sessionRuntimeSettings()
|
||||
if err != nil {
|
||||
http.Error(w, "failed to resolve sessions directory", http.StatusInternalServerError)
|
||||
return
|
||||
@@ -507,7 +520,7 @@ func (h *Handler) handleListSessions(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
seen[sessionID] = struct{}{}
|
||||
items = append(items, buildSessionListItem(sessionID, sess))
|
||||
items = append(items, buildSessionListItem(sessionID, sess, toolFeedbackMaxArgsLength))
|
||||
}
|
||||
|
||||
// Sort by updated descending (most recent first)
|
||||
@@ -555,7 +568,7 @@ func (h *Handler) handleGetSession(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
dir, err := h.sessionsDir()
|
||||
dir, toolFeedbackMaxArgsLength, err := h.sessionRuntimeSettings()
|
||||
if err != nil {
|
||||
http.Error(w, "failed to resolve sessions directory", http.StatusInternalServerError)
|
||||
return
|
||||
@@ -582,7 +595,7 @@ func (h *Handler) handleGetSession(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
messages := visibleSessionMessages(sess.Messages)
|
||||
messages := visibleSessionMessages(sess.Messages, toolFeedbackMaxArgsLength)
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]any{
|
||||
|
||||
Reference in New Issue
Block a user