Files
picoclaw/pkg/utils/tool_feedback.go
T
David Siewert bcc3d447a1 feat(agent): add pretty_print and disable_escape_html options for tool feedback
- Add PrettyPrint and DisableEscapeHTML config options to ToolFeedbackConfig
- Add FormatArgsJSON helper function with configurable pretty printing and HTML escaping
- Add toolFeedbackArgsPreviewWithOptions to pass formatting options
- Update pipeline_execute.go to use new formatting options for tool feedback

This fixes the issue where '&&' would be displayed as '\u0026' in tool
feedback messages and provides optional pretty-printing for better
readability.
2026-04-25 20:46:16 +06:00

85 lines
2.2 KiB
Go

package utils
import (
"bytes"
"encoding/json"
"fmt"
"strings"
)
const ToolFeedbackContinuationHint = "Continuing the current task."
func FormatArgsJSON(args map[string]any, prettyPrint, disableEscapeHTML bool) string {
var buf bytes.Buffer
enc := json.NewEncoder(&buf)
if prettyPrint {
enc.SetIndent("", " ")
}
if disableEscapeHTML {
enc.SetEscapeHTML(false)
}
if err := enc.Encode(args); err != nil {
return "{}"
}
return strings.TrimSpace(buf.String())
}
// FormatToolFeedbackMessage renders a tool feedback message for chat channels.
// It keeps the tool name on the first line for animation and can include both
// a human explanation and the serialized tool arguments in the body.
func FormatToolFeedbackMessage(toolName, explanation, argsPreview string) string {
toolName = strings.TrimSpace(toolName)
explanation = strings.TrimSpace(explanation)
argsPreview = strings.TrimSpace(argsPreview)
bodyLines := make([]string, 0, 2)
if explanation != "" {
bodyLines = append(bodyLines, explanation)
}
if argsPreview != "" {
bodyLines = append(bodyLines, "```json\n"+argsPreview+"\n```")
}
body := strings.Join(bodyLines, "\n")
if toolName == "" {
return body
}
if body == "" {
return fmt.Sprintf("\U0001f527 `%s`", toolName)
}
return fmt.Sprintf("\U0001f527 `%s`\n%s", toolName, body)
}
// FitToolFeedbackMessage keeps tool feedback within a single outbound message.
// It preserves the first line when possible and truncates the explanation body
// instead of letting the message be split into multiple chunks.
func FitToolFeedbackMessage(content string, maxLen int) string {
content = strings.TrimSpace(content)
if content == "" || maxLen <= 0 {
return ""
}
if len([]rune(content)) <= maxLen {
return content
}
firstLine, rest, hasRest := strings.Cut(content, "\n")
firstLine = strings.TrimSpace(firstLine)
rest = strings.TrimSpace(rest)
if !hasRest || rest == "" {
return Truncate(firstLine, maxLen)
}
if len([]rune(firstLine)) >= maxLen {
return Truncate(firstLine, maxLen)
}
remaining := maxLen - len([]rune(firstLine)) - 1
if remaining <= 0 {
return Truncate(firstLine, maxLen)
}
return firstLine + "\n" + Truncate(rest, remaining)
}