Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions pkg/agent/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -249,10 +250,8 @@ func (cb *ContextBuilder) sourceFilesChangedLocked() bool {
}

// Check tracked source files (bootstrap + memory).
for _, p := range cb.sourcePaths() {
if cb.fileChangedSince(p) {
return true
}
if slices.ContainsFunc(cb.sourcePaths(), cb.fileChangedSince) {
return true
}

// --- Skills directory (handled separately from sourcePaths) ---
Expand Down
4 changes: 2 additions & 2 deletions pkg/agent/context_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,11 +404,11 @@ func TestConcurrentBuildSystemPromptWithCache(t *testing.T) {
var wg sync.WaitGroup
errs := make(chan string, goroutines*iterations)

for g := 0; g < goroutines; g++ {
for g := range goroutines {
wg.Add(1)
go func(id int) {
defer wg.Done()
for i := 0; i < iterations; i++ {
for i := range iterations {
result := cb.BuildSystemPromptWithCache()
if result == "" {
errs <- "empty prompt returned"
Expand Down
17 changes: 3 additions & 14 deletions pkg/agent/loop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"testing"
"time"

Expand Down Expand Up @@ -175,13 +176,7 @@ func TestToolRegistry_ToolRegistration(t *testing.T) {
toolsList := toolsInfo["names"].([]string)

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

// Check that our custom tool name is in the list
found := false
for _, name := range toolsList {
if name == "mock_custom" {
found = true
break
}
}
found := slices.Contains(toolsList, "mock_custom")
if !found {
t.Error("Expected custom tool to be registered")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/agent/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (ms *MemoryStore) GetRecentDailyNotes(days int) string {
var sb strings.Builder
first := true

for i := 0; i < days; i++ {
for i := range days {
date := time.Now().AddDate(0, 0, -i)
dateStr := date.Format("20060102") // YYYYMMDD
monthDir := dateStr[:6] // YYYYMM
Expand Down
9 changes: 3 additions & 6 deletions pkg/channels/onebot.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,7 @@ func (c *OneBotChannel) sendAPIRequest(action string, params any, timeout time.D
}

func (c *OneBotChannel) reconnectLoop() {
interval := time.Duration(c.config.ReconnectInterval) * time.Second
if interval < 5*time.Second {
interval = 5 * time.Second
}
interval := max(time.Duration(c.config.ReconnectInterval)*time.Second, 5*time.Second)

for {
select {
Expand Down Expand Up @@ -975,8 +972,8 @@ func (c *OneBotChannel) checkGroupTrigger(
if prefix == "" {
continue
}
if strings.HasPrefix(content, prefix) {
return true, strings.TrimSpace(strings.TrimPrefix(content, prefix))
if after, ok := strings.CutPrefix(content, prefix); ok {
return true, strings.TrimSpace(after)
}
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/channels/wecom.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ func pkcs7UnpadWeCom(data []byte) ([]byte, error) {
return nil, fmt.Errorf("padding size larger than data")
}
// Verify all padding bytes
for i := 0; i < padding; i++ {
for i := range padding {
if data[len(data)-1-i] != byte(padding) {
return nil, fmt.Errorf("invalid padding byte at position %d", i)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/channels/wecom_app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func encryptTestMessageApp(message, aesKey string) (string, error) {

// Prepare message: random(16) + msg_len(4) + msg + corp_id
random := make([]byte, 0, 16)
for i := 0; i < 16; i++ {
for i := range 16 {
random = append(random, byte(i+1))
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/channels/wecom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func encryptTestMessage(message, aesKey string) (string, error) {

// Prepare message: random(16) + msg_len(4) + msg + receiveid
random := make([]byte, 0, 16)
for i := 0; i < 16; i++ {
for i := range 16 {
random = append(random, byte(i))
}

Expand Down
12 changes: 5 additions & 7 deletions pkg/config/model_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestGetModelConfig_RoundRobin(t *testing.T) {

// Test round-robin distribution
results := make(map[string]int)
for i := 0; i < 30; i++ {
for range 30 {
result, err := cfg.GetModelConfig("lb-model")
if err != nil {
t.Fatalf("GetModelConfig() error = %v", err)
Expand Down Expand Up @@ -94,17 +94,15 @@ func TestGetModelConfig_Concurrent(t *testing.T) {
var wg sync.WaitGroup
errors := make(chan error, goroutines*iterations)

for i := 0; i < goroutines; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < iterations; j++ {
for range goroutines {
wg.Go(func() {
for range iterations {
_, err := cfg.GetModelConfig("concurrent-model")
if err != nil {
errors <- err
}
}
}()
})
}

wg.Wait()
Expand Down
5 changes: 2 additions & 3 deletions pkg/health/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"maps"
"net/http"
"sync"
"time"
Expand Down Expand Up @@ -122,9 +123,7 @@ func (s *Server) readyHandler(w http.ResponseWriter, r *http.Request) {
s.mu.RLock()
ready := s.ready
checks := make(map[string]Check)
for k, v := range s.checks {
checks[k] = v
}
maps.Copy(checks, s.checks)
s.mu.RUnlock()

if !ready {
Expand Down
10 changes: 5 additions & 5 deletions pkg/providers/anthropic/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,14 +212,14 @@ func translateTools(tools []ToolDefinition) []anthropic.ToolUnionParam {
}

func parseResponse(resp *anthropic.Message) *LLMResponse {
var content string
var content strings.Builder
var toolCalls []ToolCall

for _, block := range resp.Content {
switch block.Type {
case "text":
tb := block.AsText()
content += tb.Text
content.WriteString(tb.Text)
case "tool_use":
tu := block.AsToolUse()
var args map[string]any
Expand All @@ -246,7 +246,7 @@ func parseResponse(resp *anthropic.Message) *LLMResponse {
}

return &LLMResponse{
Content: content,
Content: content.String(),
ToolCalls: toolCalls,
FinishReason: finishReason,
Usage: &UsageInfo{
Expand All @@ -264,8 +264,8 @@ func normalizeBaseURL(apiBase string) string {
}

base = strings.TrimRight(base, "/")
if strings.HasSuffix(base, "/v1") {
base = strings.TrimSuffix(base, "/v1")
if before, ok := strings.CutSuffix(base, "/v1"); ok {
base = before
}
if base == "" {
return defaultBaseURL
Expand Down
4 changes: 2 additions & 2 deletions pkg/providers/codex_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ func resolveCodexModel(model string) (string, string) {
return codexDefaultModel, "empty model"
}

if strings.HasPrefix(m, "openai/") {
m = strings.TrimPrefix(m, "openai/")
if after, ok := strings.CutPrefix(m, "openai/"); ok {
m = after
} else if strings.Contains(m, "/") {
return codexDefaultModel, "non-openai model namespace"
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/providers/cooldown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func TestCooldown_FailureWindowReset(t *testing.T) {
ct, current := newTestTracker(now)

// 4 errors β†’ 1h cooldown
for i := 0; i < 4; i++ {
for range 4 {
ct.MarkFailure("openai", FailoverRateLimit)
*current = current.Add(2 * time.Second) // small advance between errors
}
Expand Down Expand Up @@ -230,7 +230,7 @@ func TestCooldown_ConcurrentAccess(t *testing.T) {
ct := NewCooldownTracker()
var wg sync.WaitGroup

for i := 0; i < 100; i++ {
for range 100 {
wg.Add(3)
go func() {
defer wg.Done()
Expand Down
8 changes: 4 additions & 4 deletions pkg/providers/openai_compat/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,19 +307,19 @@ func stripSystemParts(messages []Message) []openaiMessage {
}

func normalizeModel(model, apiBase string) string {
idx := strings.Index(model, "/")
if idx == -1 {
before, after, ok := strings.Cut(model, "/")
if !ok {
return model
}

if strings.Contains(strings.ToLower(apiBase), "openrouter.ai") {
return model
}

prefix := strings.ToLower(model[:idx])
prefix := strings.ToLower(before)
switch prefix {
case "moonshot", "nvidia", "groq", "ollama", "deepseek", "google", "openrouter", "zhipu", "mistral":
return model[idx+1:]
return after
default:
return model
}
Expand Down
13 changes: 8 additions & 5 deletions pkg/routing/agent_id_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package routing

import "testing"
import (
"strings"
"testing"
)

func TestNormalizeAgentID_Empty(t *testing.T) {
if got := NormalizeAgentID(""); got != DefaultAgentID {
Expand Down Expand Up @@ -57,11 +60,11 @@ func TestNormalizeAgentID_AllInvalid(t *testing.T) {
}

func TestNormalizeAgentID_TruncatesAt64(t *testing.T) {
long := ""
for i := 0; i < 100; i++ {
long += "a"
var long strings.Builder
for range 100 {
long.WriteString("a")
}
got := NormalizeAgentID(long)
got := NormalizeAgentID(long.String())
if len(got) > MaxAgentIDLength {
t.Errorf("length = %d, want <= %d", len(got), MaxAgentIDLength)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/skills/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ func (sl *SkillsLoader) parseSimpleYAML(content string) map[string]string {
normalized := strings.ReplaceAll(content, "\r\n", "\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)
if line == "" || strings.HasPrefix(line, "#") {
continue
Expand Down
4 changes: 2 additions & 2 deletions pkg/skills/search_cache.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package skills

import (
"sort"
"slices"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -183,7 +183,7 @@ func buildTrigrams(s string) []uint32 {
}

// Sort and Deduplication
sort.Slice(trigrams, func(i, j int) bool { return trigrams[i] < trigrams[j] })
slices.Sort(trigrams)
n := 1
for i := 1; i < len(trigrams); i++ {
if trigrams[i] != trigrams[i-1] {
Expand Down
4 changes: 2 additions & 2 deletions pkg/skills/search_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,15 @@ func TestSearchCacheConcurrency(t *testing.T) {

// Concurrent writes
go func() {
for i := 0; i < 100; i++ {
for i := range 100 {
cache.Put("query-write-"+string(rune('a'+i%26)), []SearchResult{{Slug: "x"}})
}
done <- struct{}{}
}()

// Concurrent reads
go func() {
for i := 0; i < 100; i++ {
for range 100 {
cache.Get("query-write-a")
}
done <- struct{}{}
Expand Down
4 changes: 2 additions & 2 deletions pkg/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func TestConcurrentAccess(t *testing.T) {

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

// Wait for all goroutines to complete
for i := 0; i < 10; i++ {
for range 10 {
<-done
}

Expand Down
8 changes: 5 additions & 3 deletions pkg/tools/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tools
import (
"context"
"fmt"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -218,7 +219,8 @@ func (t *CronTool) listJobs() *ToolResult {
return SilentResult("No scheduled jobs")
}

result := "Scheduled jobs:\n"
var result strings.Builder
result.WriteString("Scheduled jobs:\n")
for _, j := range jobs {
var scheduleInfo string
if j.Schedule.Kind == "every" && j.Schedule.EveryMS != nil {
Expand All @@ -230,10 +232,10 @@ func (t *CronTool) listJobs() *ToolResult {
} else {
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 {
Expand Down
Loading