chore: import clean Agent Desk snapshot (2/7)

This commit is contained in:
2026-10-16 11:57:21 +00:00
parent 79176541c7
commit 89c5231c4c
461 changed files with 60092 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
package tooling
import (
"fmt"
"hash/crc32"
"regexp"
"strings"
)
var toolNameSanitizer = regexp.MustCompile(`[^a-zA-Z0-9_]`)
type MCPToolDefinition struct {
ToolCode string
ServerCode string
ToolName string
ModelName string
Title string
Description string
FixedArgs map[string]string
}
func BuildModelToolName(definition MCPToolDefinition) string {
if strings.TrimSpace(definition.ModelName) != "" {
return strings.TrimSpace(definition.ModelName)
}
base := "mcp_" + strings.TrimSpace(definition.ServerCode) + "_" + strings.TrimSpace(definition.ToolName)
base = toolNameSanitizer.ReplaceAllString(base, "_")
base = strings.Trim(base, "_")
if base == "" {
base = "mcp_tool"
}
checksum := crc32.ChecksumIEEE([]byte(definition.ToolCode))
return fmt.Sprintf("%s_%08x", base, checksum)
}

View File

@@ -0,0 +1,42 @@
package tooling
import (
"encoding/json"
"strings"
)
type ToolResult struct {
Handled bool `json:"handled"`
Terminal bool `json:"terminal"`
Action string `json:"action"`
ReplyText string `json:"replyText,omitempty"`
ReplySent bool `json:"replySent,omitempty"`
ShouldRetry bool `json:"shouldRetry"`
}
func MarshalToolResult(result ToolResult) string {
result.Action = strings.TrimSpace(result.Action)
result.ReplyText = strings.TrimSpace(result.ReplyText)
buf, err := json.Marshal(result)
if err != nil {
return ""
}
return string(buf)
}
func ParseToolResult(raw string) (ToolResult, bool) {
raw = strings.TrimSpace(raw)
if raw == "" {
return ToolResult{}, false
}
var result ToolResult
if err := json.Unmarshal([]byte(raw), &result); err != nil {
return ToolResult{}, false
}
result.Action = strings.TrimSpace(result.Action)
result.ReplyText = strings.TrimSpace(result.ReplyText)
if result.Action == "" && result.ReplyText == "" && !result.Handled && !result.Terminal {
return ToolResult{}, false
}
return result, true
}

View File

@@ -0,0 +1,124 @@
package tooling
import (
"encoding/json"
"fmt"
"regexp"
"strconv"
"strings"
"agent-desk/internal/ai/mcps"
)
const (
maxToolResultSummaryChars = 2500
maxToolResultSegments = 12
)
var reductionInfoPattern = regexp.MustCompile(`\[tool result reduced: original_length=(\d+), kept_length=(\d+)\]`)
type ReductionInfo struct {
Reduced bool
OriginalChars int
KeptChars int
}
// 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 ParseReductionInfo(summary string) ReductionInfo {
matches := reductionInfoPattern.FindStringSubmatch(strings.TrimSpace(summary))
if len(matches) != 3 {
return ReductionInfo{}
}
originalChars, err1 := strconv.Atoi(matches[1])
keptChars, err2 := strconv.Atoi(matches[2])
if err1 != nil || err2 != nil {
return ReductionInfo{}
}
return ReductionInfo{
Reduced: true,
OriginalChars: originalChars,
KeptChars: keptChars,
}
}
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
}
key := canonicalToolResultSegment(value)
for _, existing := range input {
if canonicalToolResultSegment(existing) == key {
return input
}
}
return append(input, value)
}
func canonicalToolResultSegment(value string) string {
value = strings.TrimSpace(value)
if value == "" {
return ""
}
var payload any
if err := json.Unmarshal([]byte(value), &payload); err != nil {
return value
}
data, err := json.Marshal(payload)
if err != nil {
return value
}
return string(data)
}

View File

@@ -0,0 +1,99 @@
package tooling
import (
"strings"
"testing"
"agent-desk/internal/ai/mcps"
)
func TestBuildReducedToolResultSummaryDeduplicatesStructuredAndTextContent(t *testing.T) {
result := &mcps.ToolCallResult{
StructuredContent: map[string]any{
"timestamp": "2026-07-28 11:51:52",
"timezone": "Local",
},
Content: []mcps.ToolResultContent{{
Type: "text",
Text: `{"timezone":"Local","timestamp":"2026-07-28 11:51:52"}`,
}},
}
summary := BuildReducedToolResultSummary(result)
if strings.Count(summary, "timestamp") != 1 {
t.Fatalf("duplicate MCP result was not removed: %q", summary)
}
if summary != `{"timestamp":"2026-07-28 11:51:52","timezone":"Local"}` {
t.Fatalf("unexpected reduced result: %q", summary)
}
}
func TestBuildReducedToolResultSummaryKeepsDistinctSegments(t *testing.T) {
result := &mcps.ToolCallResult{
StructuredContent: map[string]any{"status": "ok"},
Content: []mcps.ToolResultContent{{
Type: "text",
Text: "additional context",
}},
}
summary := BuildReducedToolResultSummary(result)
if !strings.Contains(summary, `{"status":"ok"}`) || !strings.Contains(summary, "additional context") {
t.Fatalf("distinct MCP result segments were lost: %q", summary)
}
}
func TestBuildReducedToolResultSummaryTruncatesAt2500Runes(t *testing.T) {
longText := strings.Repeat("x", 3000)
result := &mcps.ToolCallResult{
Content: []mcps.ToolResultContent{{
Type: "text",
Text: longText,
}},
}
summary := BuildReducedToolResultSummary(result)
expectedMarker := "[tool result reduced: original_length=3000, kept_length=2500]"
if !strings.Contains(summary, expectedMarker) {
t.Fatalf("expected reduction marker %q in summary, got: %q", expectedMarker, summary)
}
info := ParseReductionInfo(summary)
if !info.Reduced || info.OriginalChars != 3000 || info.KeptChars != 2500 {
t.Fatalf("unexpected ReductionInfo: %+v", info)
}
// Exactly 2500 runes should not be reduced
exactText := strings.Repeat("y", 2500)
exactResult := &mcps.ToolCallResult{
Content: []mcps.ToolResultContent{{
Type: "text",
Text: exactText,
}},
}
exactSummary := BuildReducedToolResultSummary(exactResult)
if strings.Contains(exactSummary, "[tool result reduced:") {
t.Fatalf("2500-rune payload should not be reduced, got: %q", exactSummary)
}
if exactSummary != exactText {
t.Fatalf("expected exact text, got length %d", len(exactSummary))
}
// Multibyte runes test
chineseText := strings.Repeat("测", 2600)
chineseResult := &mcps.ToolCallResult{
Content: []mcps.ToolResultContent{{
Type: "text",
Text: chineseText,
}},
}
chineseSummary := BuildReducedToolResultSummary(chineseResult)
expectedChineseMarker := "[tool result reduced: original_length=2600, kept_length=2500]"
if !strings.Contains(chineseSummary, expectedChineseMarker) {
t.Fatalf("expected multibyte reduction marker %q, got: %q", expectedChineseMarker, chineseSummary)
}
chineseInfo := ParseReductionInfo(chineseSummary)
if !chineseInfo.Reduced || chineseInfo.OriginalChars != 2600 || chineseInfo.KeptChars != 2500 {
t.Fatalf("unexpected chinese ReductionInfo: %+v", chineseInfo)
}
}