run go fix

This commit is contained in:
Александр Мелентьев 2026-02-21 10:33:14 +03:00
parent 80c8b57533
commit 884c62423e
21 changed files with 66 additions and 87 deletions

View file

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"slices"
"testing" "testing"
"time" "time"
@ -175,13 +176,7 @@ func TestToolRegistry_ToolRegistration(t *testing.T) {
toolsList := toolsInfo["names"].([]string) toolsList := toolsInfo["names"].([]string)
// Check that our custom tool name is in the list // Check that our custom tool name is in the list
found := false found := slices.Contains(toolsList, "mock_custom")
for _, name := range toolsList {
if name == "mock_custom" {
found = true
break
}
}
if !found { if !found {
t.Error("Expected custom tool to be registered") t.Error("Expected custom tool to be registered")
} }
@ -250,13 +245,7 @@ func TestToolRegistry_GetDefinitions(t *testing.T) {
toolsList := toolsInfo["names"].([]string) toolsList := toolsInfo["names"].([]string)
// Check that our custom tool name is in the list // Check that our custom tool name is in the list
found := false found := slices.Contains(toolsList, "mock_custom")
for _, name := range toolsList {
if name == "mock_custom" {
found = true
break
}
}
if !found { if !found {
t.Error("Expected custom tool to be registered") t.Error("Expected custom tool to be registered")
} }

View file

@ -104,7 +104,7 @@ func (ms *MemoryStore) GetRecentDailyNotes(days int) string {
var sb strings.Builder var sb strings.Builder
first := true first := true
for i := 0; i < days; i++ { for i := range days {
date := time.Now().AddDate(0, 0, -i) date := time.Now().AddDate(0, 0, -i)
dateStr := date.Format("20060102") // YYYYMMDD dateStr := date.Format("20060102") // YYYYMMDD
monthDir := dateStr[:6] // YYYYMM monthDir := dateStr[:6] // YYYYMM

View file

@ -596,7 +596,7 @@ func pkcs7UnpadWeCom(data []byte) ([]byte, error) {
return nil, fmt.Errorf("padding size larger than data") return nil, fmt.Errorf("padding size larger than data")
} }
// Verify all padding bytes // Verify all padding bytes
for i := 0; i < padding; i++ { for i := range padding {
if data[len(data)-1-i] != byte(padding) { if data[len(data)-1-i] != byte(padding) {
return nil, fmt.Errorf("invalid padding byte at position %d", i) return nil, fmt.Errorf("invalid padding byte at position %d", i)
} }

View file

@ -46,7 +46,7 @@ func encryptTestMessageApp(message, aesKey string) (string, error) {
// Prepare message: random(16) + msg_len(4) + msg + corp_id // Prepare message: random(16) + msg_len(4) + msg + corp_id
random := make([]byte, 0, 16) random := make([]byte, 0, 16)
for i := 0; i < 16; i++ { for i := range 16 {
random = append(random, byte(i+1)) random = append(random, byte(i+1))
} }

View file

@ -45,7 +45,7 @@ func encryptTestMessage(message, aesKey string) (string, error) {
// Prepare message: random(16) + msg_len(4) + msg + receiveid // Prepare message: random(16) + msg_len(4) + msg + receiveid
random := make([]byte, 0, 16) random := make([]byte, 0, 16)
for i := 0; i < 16; i++ { for i := range 16 {
random = append(random, byte(i)) random = append(random, byte(i))
} }

View file

@ -63,7 +63,7 @@ func TestGetModelConfig_RoundRobin(t *testing.T) {
// Test round-robin distribution // Test round-robin distribution
results := make(map[string]int) results := make(map[string]int)
for i := 0; i < 30; i++ { for range 30 {
result, err := cfg.GetModelConfig("lb-model") result, err := cfg.GetModelConfig("lb-model")
if err != nil { if err != nil {
t.Fatalf("GetModelConfig() error = %v", err) t.Fatalf("GetModelConfig() error = %v", err)
@ -93,17 +93,15 @@ func TestGetModelConfig_Concurrent(t *testing.T) {
var wg sync.WaitGroup var wg sync.WaitGroup
errors := make(chan error, goroutines*iterations) errors := make(chan error, goroutines*iterations)
for i := 0; i < goroutines; i++ { for range goroutines {
wg.Add(1) wg.Go(func() {
go func() { for range iterations {
defer wg.Done()
for j := 0; j < iterations; j++ {
_, err := cfg.GetModelConfig("concurrent-model") _, err := cfg.GetModelConfig("concurrent-model")
if err != nil { if err != nil {
errors <- err errors <- err
} }
} }
}() })
} }
wg.Wait() wg.Wait()

View file

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"maps"
"net/http" "net/http"
"sync" "sync"
"time" "time"
@ -122,9 +123,7 @@ func (s *Server) readyHandler(w http.ResponseWriter, r *http.Request) {
s.mu.RLock() s.mu.RLock()
ready := s.ready ready := s.ready
checks := make(map[string]Check) checks := make(map[string]Check)
for k, v := range s.checks { maps.Copy(checks, s.checks)
checks[k] = v
}
s.mu.RUnlock() s.mu.RUnlock()
if !ready { if !ready {

View file

@ -199,14 +199,14 @@ func translateTools(tools []ToolDefinition) []anthropic.ToolUnionParam {
} }
func parseResponse(resp *anthropic.Message) *LLMResponse { func parseResponse(resp *anthropic.Message) *LLMResponse {
var content string var content strings.Builder
var toolCalls []ToolCall var toolCalls []ToolCall
for _, block := range resp.Content { for _, block := range resp.Content {
switch block.Type { switch block.Type {
case "text": case "text":
tb := block.AsText() tb := block.AsText()
content += tb.Text content.WriteString(tb.Text)
case "tool_use": case "tool_use":
tu := block.AsToolUse() tu := block.AsToolUse()
var args map[string]any var args map[string]any
@ -233,7 +233,7 @@ func parseResponse(resp *anthropic.Message) *LLMResponse {
} }
return &LLMResponse{ return &LLMResponse{
Content: content, Content: content.String(),
ToolCalls: toolCalls, ToolCalls: toolCalls,
FinishReason: finishReason, FinishReason: finishReason,
Usage: &UsageInfo{ Usage: &UsageInfo{
@ -251,8 +251,8 @@ func normalizeBaseURL(apiBase string) string {
} }
base = strings.TrimRight(base, "/") base = strings.TrimRight(base, "/")
if strings.HasSuffix(base, "/v1") { if before, ok := strings.CutSuffix(base, "/v1"); ok {
base = strings.TrimSuffix(base, "/v1") base = before
} }
if base == "" { if base == "" {
return defaultBaseURL return defaultBaseURL

View file

@ -163,8 +163,8 @@ func resolveCodexModel(model string) (string, string) {
return codexDefaultModel, "empty model" return codexDefaultModel, "empty model"
} }
if strings.HasPrefix(m, "openai/") { if after, ok := strings.CutPrefix(m, "openai/"); ok {
m = strings.TrimPrefix(m, "openai/") m = after
} else if strings.Contains(m, "/") { } else if strings.Contains(m, "/") {
return codexDefaultModel, "non-openai model namespace" return codexDefaultModel, "non-openai model namespace"
} }

View file

@ -138,7 +138,7 @@ func TestCooldown_FailureWindowReset(t *testing.T) {
ct, current := newTestTracker(now) ct, current := newTestTracker(now)
// 4 errors → 1h cooldown // 4 errors → 1h cooldown
for i := 0; i < 4; i++ { for range 4 {
ct.MarkFailure("openai", FailoverRateLimit) ct.MarkFailure("openai", FailoverRateLimit)
*current = current.Add(2 * time.Second) // small advance between errors *current = current.Add(2 * time.Second) // small advance between errors
} }
@ -230,7 +230,7 @@ func TestCooldown_ConcurrentAccess(t *testing.T) {
ct := NewCooldownTracker() ct := NewCooldownTracker()
var wg sync.WaitGroup var wg sync.WaitGroup
for i := 0; i < 100; i++ { for range 100 {
wg.Add(3) wg.Add(3)
go func() { go func() {
defer wg.Done() defer wg.Done()

View file

@ -229,8 +229,8 @@ func parseResponse(body []byte) (*LLMResponse, error) {
} }
func normalizeModel(model, apiBase string) string { func normalizeModel(model, apiBase string) string {
idx := strings.Index(model, "/") before, after, ok := strings.Cut(model, "/")
if idx == -1 { if !ok {
return model return model
} }
@ -238,10 +238,10 @@ func normalizeModel(model, apiBase string) string {
return model return model
} }
prefix := strings.ToLower(model[:idx]) prefix := strings.ToLower(before)
switch prefix { switch prefix {
case "moonshot", "nvidia", "groq", "ollama", "deepseek", "google", "openrouter", "zhipu": case "moonshot", "nvidia", "groq", "ollama", "deepseek", "google", "openrouter", "zhipu":
return model[idx+1:] return after
default: default:
return model return model
} }

View file

@ -1,6 +1,9 @@
package routing package routing
import "testing" import (
"strings"
"testing"
)
func TestNormalizeAgentID_Empty(t *testing.T) { func TestNormalizeAgentID_Empty(t *testing.T) {
if got := NormalizeAgentID(""); got != DefaultAgentID { if got := NormalizeAgentID(""); got != DefaultAgentID {
@ -57,11 +60,11 @@ func TestNormalizeAgentID_AllInvalid(t *testing.T) {
} }
func TestNormalizeAgentID_TruncatesAt64(t *testing.T) { func TestNormalizeAgentID_TruncatesAt64(t *testing.T) {
long := "" var long strings.Builder
for i := 0; i < 100; i++ { for range 100 {
long += "a" long.WriteString("a")
} }
got := NormalizeAgentID(long) got := NormalizeAgentID(long.String())
if len(got) > MaxAgentIDLength { if len(got) > MaxAgentIDLength {
t.Errorf("length = %d, want <= %d", len(got), MaxAgentIDLength) t.Errorf("length = %d, want <= %d", len(got), MaxAgentIDLength)
} }

View file

@ -298,7 +298,7 @@ func (sl *SkillsLoader) parseSimpleYAML(content string) map[string]string {
normalized := strings.ReplaceAll(content, "\r\n", "\n") normalized := strings.ReplaceAll(content, "\r\n", "\n")
normalized = strings.ReplaceAll(normalized, "\r", "\n") normalized = strings.ReplaceAll(normalized, "\r", "\n")
for _, line := range strings.Split(normalized, "\n") { for line := range strings.SplitSeq(normalized, "\n") {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
if line == "" || strings.HasPrefix(line, "#") { if line == "" || strings.HasPrefix(line, "#") {
continue continue

View file

@ -1,7 +1,7 @@
package skills package skills
import ( import (
"sort" "slices"
"strings" "strings"
"sync" "sync"
"time" "time"
@ -183,7 +183,7 @@ func buildTrigrams(s string) []uint32 {
} }
// Sort and Deduplication // Sort and Deduplication
sort.Slice(trigrams, func(i, j int) bool { return trigrams[i] < trigrams[j] }) slices.Sort(trigrams)
n := 1 n := 1
for i := 1; i < len(trigrams); i++ { for i := 1; i < len(trigrams); i++ {
if trigrams[i] != trigrams[i-1] { if trigrams[i] != trigrams[i-1] {

View file

@ -153,7 +153,7 @@ func TestSearchCacheConcurrency(t *testing.T) {
// Concurrent writes // Concurrent writes
go func() { go func() {
for i := 0; i < 100; i++ { for i := range 100 {
cache.Put("query-write-"+string(rune('a'+i%26)), []SearchResult{{Slug: "x"}}) cache.Put("query-write-"+string(rune('a'+i%26)), []SearchResult{{Slug: "x"}})
} }
done <- struct{}{} done <- struct{}{}
@ -161,7 +161,7 @@ func TestSearchCacheConcurrency(t *testing.T) {
// Concurrent reads // Concurrent reads
go func() { go func() {
for i := 0; i < 100; i++ { for range 100 {
cache.Get("query-write-a") cache.Get("query-write-a")
} }
done <- struct{}{} done <- struct{}{}

View file

@ -135,7 +135,7 @@ func TestConcurrentAccess(t *testing.T) {
// Test concurrent writes // Test concurrent writes
done := make(chan bool, 10) done := make(chan bool, 10)
for i := 0; i < 10; i++ { for i := range 10 {
go func(idx int) { go func(idx int) {
channel := fmt.Sprintf("channel-%d", idx) channel := fmt.Sprintf("channel-%d", idx)
sm.SetLastChannel(channel) sm.SetLastChannel(channel)
@ -144,7 +144,7 @@ func TestConcurrentAccess(t *testing.T) {
} }
// Wait for all goroutines to complete // Wait for all goroutines to complete
for i := 0; i < 10; i++ { for range 10 {
<-done <-done
} }

View file

@ -3,6 +3,7 @@ package tools
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"sync" "sync"
"time" "time"
@ -218,7 +219,8 @@ func (t *CronTool) listJobs() *ToolResult {
return SilentResult("No scheduled jobs") return SilentResult("No scheduled jobs")
} }
result := "Scheduled jobs:\n" var result strings.Builder
result.WriteString("Scheduled jobs:\n")
for _, j := range jobs { for _, j := range jobs {
var scheduleInfo string var scheduleInfo string
if j.Schedule.Kind == "every" && j.Schedule.EveryMS != nil { if j.Schedule.Kind == "every" && j.Schedule.EveryMS != nil {
@ -230,10 +232,10 @@ func (t *CronTool) listJobs() *ToolResult {
} else { } else {
scheduleInfo = "unknown" scheduleInfo = "unknown"
} }
result += fmt.Sprintf("- %s (id: %s, %s)\n", j.Name, j.ID, scheduleInfo) result.WriteString(fmt.Sprintf("- %s (id: %s, %s)\n", j.Name, j.ID, scheduleInfo))
} }
return SilentResult(result) return SilentResult(result.String())
} }
func (t *CronTool) removeJob(args map[string]any) *ToolResult { func (t *CronTool) removeJob(args map[string]any) *ToolResult {

View file

@ -236,14 +236,14 @@ func (t *ListDirTool) Execute(ctx context.Context, args map[string]any) *ToolRes
return ErrorResult(fmt.Sprintf("failed to read directory: %v", err)) return ErrorResult(fmt.Sprintf("failed to read directory: %v", err))
} }
result := "" var result strings.Builder
for _, entry := range entries { for _, entry := range entries {
if entry.IsDir() { if entry.IsDir() {
result += "DIR: " + entry.Name() + "\n" result.WriteString("DIR: " + entry.Name() + "\n")
} else { } else {
result += "FILE: " + entry.Name() + "\n" result.WriteString("FILE: " + entry.Name() + "\n")
} }
} }
return NewToolResult(result) return NewToolResult(result.String())
} }

View file

@ -191,15 +191,15 @@ func TestShellTool_WorkingDir_OutsideWorkspace(t *testing.T) {
root := t.TempDir() root := t.TempDir()
workspace := filepath.Join(root, "workspace") workspace := filepath.Join(root, "workspace")
outsideDir := filepath.Join(root, "outside") outsideDir := filepath.Join(root, "outside")
if err := os.MkdirAll(workspace, 0755); err != nil { if err := os.MkdirAll(workspace, 0o755); err != nil {
t.Fatalf("failed to create workspace: %v", err) t.Fatalf("failed to create workspace: %v", err)
} }
if err := os.MkdirAll(outsideDir, 0755); err != nil { if err := os.MkdirAll(outsideDir, 0o755); err != nil {
t.Fatalf("failed to create outside dir: %v", err) t.Fatalf("failed to create outside dir: %v", err)
} }
tool := NewExecTool(workspace, true) tool := NewExecTool(workspace, true)
result := tool.Execute(context.Background(), map[string]interface{}{ result := tool.Execute(context.Background(), map[string]any{
"command": "pwd", "command": "pwd",
"working_dir": outsideDir, "working_dir": outsideDir,
}) })
@ -218,13 +218,13 @@ func TestShellTool_WorkingDir_SymlinkEscape(t *testing.T) {
root := t.TempDir() root := t.TempDir()
workspace := filepath.Join(root, "workspace") workspace := filepath.Join(root, "workspace")
secretDir := filepath.Join(root, "secret") secretDir := filepath.Join(root, "secret")
if err := os.MkdirAll(workspace, 0755); err != nil { if err := os.MkdirAll(workspace, 0o755); err != nil {
t.Fatalf("failed to create workspace: %v", err) t.Fatalf("failed to create workspace: %v", err)
} }
if err := os.MkdirAll(secretDir, 0755); err != nil { if err := os.MkdirAll(secretDir, 0o755); err != nil {
t.Fatalf("failed to create secret dir: %v", err) t.Fatalf("failed to create secret dir: %v", err)
} }
os.WriteFile(filepath.Join(secretDir, "secret.txt"), []byte("top secret"), 0644) os.WriteFile(filepath.Join(secretDir, "secret.txt"), []byte("top secret"), 0o644)
// symlink lives inside the workspace but resolves to secretDir outside it // symlink lives inside the workspace but resolves to secretDir outside it
link := filepath.Join(workspace, "escape") link := filepath.Join(workspace, "escape")
@ -233,7 +233,7 @@ func TestShellTool_WorkingDir_SymlinkEscape(t *testing.T) {
} }
tool := NewExecTool(workspace, true) tool := NewExecTool(workspace, true)
result := tool.Execute(context.Background(), map[string]interface{}{ result := tool.Execute(context.Background(), map[string]any{
"command": "cat secret.txt", "command": "cat secret.txt",
"working_dir": link, "working_dir": link,
}) })

View file

@ -141,7 +141,7 @@ func (p *DuckDuckGoSearchProvider) extractResults(html string, count int, query
maxItems := min(len(matches), count) maxItems := min(len(matches), count)
for i := 0; i < maxItems; i++ { for i := range maxItems {
urlStr := matches[i][1] urlStr := matches[i][1]
title := stripTags(matches[i][2]) title := stripTags(matches[i][2])
title = strings.TrimSpace(title) title = strings.TrimSpace(title)
@ -149,9 +149,9 @@ func (p *DuckDuckGoSearchProvider) extractResults(html string, count int, query
// URL decoding if needed // URL decoding if needed
if strings.Contains(urlStr, "uddg=") { if strings.Contains(urlStr, "uddg=") {
if u, err := url.QueryUnescape(urlStr); err == nil { if u, err := url.QueryUnescape(urlStr); err == nil {
idx := strings.Index(u, "uddg=") _, after, ok := strings.Cut(u, "uddg=")
if idx != -1 { if ok {
urlStr = u[idx+5:] urlStr = after
} }
} }
} }

View file

@ -13,10 +13,7 @@ func SplitMessage(content string, maxLen int) []string {
var messages []string var messages []string
// Dynamic buffer: 10% of maxLen, but at least 50 chars if possible // Dynamic buffer: 10% of maxLen, but at least 50 chars if possible
codeBlockBuffer := maxLen / 10 codeBlockBuffer := max(maxLen/10, 50)
if codeBlockBuffer < 50 {
codeBlockBuffer = 50
}
if codeBlockBuffer > maxLen/2 { if codeBlockBuffer > maxLen/2 {
codeBlockBuffer = maxLen / 2 codeBlockBuffer = maxLen / 2
} }
@ -28,10 +25,7 @@ func SplitMessage(content string, maxLen int) []string {
} }
// Effective split point: maxLen minus buffer, to leave room for code blocks // Effective split point: maxLen minus buffer, to leave room for code blocks
effectiveLimit := maxLen - codeBlockBuffer effectiveLimit := max(maxLen-codeBlockBuffer, maxLen/2)
if effectiveLimit < maxLen/2 {
effectiveLimit = maxLen / 2
}
// Find natural split point within the effective limit // Find natural split point within the effective limit
msgEnd := findLastNewline(content[:effectiveLimit], 200) msgEnd := findLastNewline(content[:effectiveLimit], 200)
@ -151,10 +145,7 @@ func findNextClosingCodeBlock(text string, startIdx int) int {
// findLastNewline finds the last newline character within the last N characters // findLastNewline finds the last newline character within the last N characters
// Returns the position of the newline or -1 if not found // Returns the position of the newline or -1 if not found
func findLastNewline(s string, searchWindow int) int { func findLastNewline(s string, searchWindow int) int {
searchStart := len(s) - searchWindow searchStart := max(len(s)-searchWindow, 0)
if searchStart < 0 {
searchStart = 0
}
for i := len(s) - 1; i >= searchStart; i-- { for i := len(s) - 1; i >= searchStart; i-- {
if s[i] == '\n' { if s[i] == '\n' {
return i return i
@ -166,10 +157,7 @@ func findLastNewline(s string, searchWindow int) int {
// findLastSpace finds the last space character within the last N characters // findLastSpace finds the last space character within the last N characters
// Returns the position of the space or -1 if not found // Returns the position of the space or -1 if not found
func findLastSpace(s string, searchWindow int) int { func findLastSpace(s string, searchWindow int) int {
searchStart := len(s) - searchWindow searchStart := max(len(s)-searchWindow, 0)
if searchStart < 0 {
searchStart = 0
}
for i := len(s) - 1; i >= searchStart; i-- { for i := len(s) - 1; i >= searchStart; i-- {
if s[i] == ' ' || s[i] == '\t' { if s[i] == ' ' || s[i] == '\t' {
return i return i