feat: refactor tool result summary handling by introducing BuildReducedToolResultSummary and updating related methods
This commit is contained in:
@@ -62,7 +62,7 @@ func (t *MCPTool) InvokableRun(ctx context.Context, argumentsInJSON string, opts
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return buildToolResultSummary(result), nil
|
return BuildReducedToolResultSummary(result), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildToolInfo(definition MCPToolDefinition, metadata *mcps.ToolInfo) *schema.ToolInfo {
|
func buildToolInfo(definition MCPToolDefinition, metadata *mcps.ToolInfo) *schema.ToolInfo {
|
||||||
@@ -146,37 +146,6 @@ func mergeFixedArguments(arguments map[string]any, fixedArgs map[string]string)
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildToolResultSummary(result *mcps.ToolCallResult) string {
|
|
||||||
if result == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
lines := make([]string, 0, len(result.Content)+2)
|
|
||||||
if result.IsError {
|
|
||||||
lines = append(lines, "tool returned an error")
|
|
||||||
}
|
|
||||||
if result.StructuredContent != nil {
|
|
||||||
if data, err := json.Marshal(result.StructuredContent); err == nil {
|
|
||||||
lines = append(lines, string(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, item := range result.Content {
|
|
||||||
switch item.Type {
|
|
||||||
case "text":
|
|
||||||
if text := strings.TrimSpace(item.Text); text != "" {
|
|
||||||
lines = append(lines, text)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if item.Data == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if data, err := json.Marshal(item.Data); err == nil {
|
|
||||||
lines = append(lines, string(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(strings.Join(lines, "\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuildModelToolName(definition MCPToolDefinition) string {
|
func BuildModelToolName(definition MCPToolDefinition) string {
|
||||||
if strings.TrimSpace(definition.ModelName) != "" {
|
if strings.TrimSpace(definition.ModelName) != "" {
|
||||||
return strings.TrimSpace(definition.ModelName)
|
return strings.TrimSpace(definition.ModelName)
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package adapter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"cs-agent/internal/ai/mcps"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
maxToolResultSummaryChars = 4000
|
||||||
|
maxToolResultSegments = 12
|
||||||
|
)
|
||||||
|
|
||||||
|
// BuildReducedToolResultSummary returns a bounded text summary for MCP tool results.
|
||||||
|
// It keeps the main payload visible to the model while preventing a single large tool
|
||||||
|
// response from exhausting too much context.
|
||||||
|
func BuildReducedToolResultSummary(result *mcps.ToolCallResult) string {
|
||||||
|
if result == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
segments := collectToolResultSegments(result)
|
||||||
|
if len(segments) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
text := strings.TrimSpace(strings.Join(segments, "\n"))
|
||||||
|
if text == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
runes := []rune(text)
|
||||||
|
if len(runes) <= maxToolResultSummaryChars {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
truncated := strings.TrimSpace(string(runes[:maxToolResultSummaryChars]))
|
||||||
|
return fmt.Sprintf("%s\n\n[tool result reduced: original_length=%d, kept_length=%d]", truncated, len(runes), maxToolResultSummaryChars)
|
||||||
|
}
|
||||||
|
|
||||||
|
func collectToolResultSegments(result *mcps.ToolCallResult) []string {
|
||||||
|
segments := make([]string, 0, len(result.Content)+2)
|
||||||
|
if result.IsError {
|
||||||
|
segments = append(segments, "tool returned an error")
|
||||||
|
}
|
||||||
|
if result.StructuredContent != nil {
|
||||||
|
if data, err := json.Marshal(result.StructuredContent); err == nil {
|
||||||
|
segments = appendNonBlankSegment(segments, string(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, item := range result.Content {
|
||||||
|
if len(segments) >= maxToolResultSegments {
|
||||||
|
segments = append(segments, "[tool result reduced: remaining segments omitted]")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
switch item.Type {
|
||||||
|
case "text":
|
||||||
|
segments = appendNonBlankSegment(segments, item.Text)
|
||||||
|
default:
|
||||||
|
if item.Data == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if data, err := json.Marshal(item.Data); err == nil {
|
||||||
|
segments = appendNonBlankSegment(segments, string(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return segments
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendNonBlankSegment(input []string, value string) []string {
|
||||||
|
value = strings.TrimSpace(value)
|
||||||
|
if value == "" {
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
return append(input, value)
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"cs-agent/internal/ai/mcps"
|
"cs-agent/internal/ai/mcps"
|
||||||
|
impladapter "cs-agent/internal/ai/runtime/internal/impl/adapter"
|
||||||
"cs-agent/internal/ai/runtime/registry"
|
"cs-agent/internal/ai/runtime/registry"
|
||||||
"cs-agent/internal/pkg/toolx"
|
"cs-agent/internal/pkg/toolx"
|
||||||
|
|
||||||
@@ -282,32 +283,5 @@ func cloneArguments(input map[string]any) map[string]any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildToolCallResultSummary(result *mcps.ToolCallResult) string {
|
func buildToolCallResultSummary(result *mcps.ToolCallResult) string {
|
||||||
if result == nil {
|
return impladapter.BuildReducedToolResultSummary(result)
|
||||||
return ""
|
|
||||||
}
|
|
||||||
lines := make([]string, 0, len(result.Content)+2)
|
|
||||||
if result.IsError {
|
|
||||||
lines = append(lines, "tool returned an error")
|
|
||||||
}
|
|
||||||
if result.StructuredContent != nil {
|
|
||||||
if data, err := json.Marshal(result.StructuredContent); err == nil {
|
|
||||||
lines = append(lines, string(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, item := range result.Content {
|
|
||||||
switch item.Type {
|
|
||||||
case "text":
|
|
||||||
if text := strings.TrimSpace(item.Text); text != "" {
|
|
||||||
lines = append(lines, text)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if item.Data == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if data, err := json.Marshal(item.Data); err == nil {
|
|
||||||
lines = append(lines, string(data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return strings.TrimSpace(strings.Join(lines, "\n"))
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user