chore: apply modernize linter, fix lint errors

This commit is contained in:
Marcus Ramberg 2026-03-02 12:19:38 +01:00
parent b82bb9acc0
commit eb4c9b790e
No known key found for this signature in database
16 changed files with 115 additions and 137 deletions

View file

@ -47,7 +47,6 @@ linters:
- lll - lll
- maintidx - maintidx
- mnd - mnd
- modernize
- nestif - nestif
- nilnil - nilnil
- paralleltest - paralleltest

View file

@ -1,5 +1,4 @@
//go:build !windows //go:build !windows
// +build !windows
package ui package ui

View file

@ -1,5 +1,4 @@
//go:build windows //go:build windows
// +build windows
package ui package ui

View file

@ -61,10 +61,7 @@ func (b *LogBuffer) LinesSince(offset int) (lines []string, total int, runID int
buffered := len(b.lines) buffered := len(b.lines)
// How many new lines since offset // How many new lines since offset
newCount := b.total - offset newCount := min(b.total-offset, buffered)
if newCount > buffered {
newCount = buffered
}
result := make([]string, newCount) result := make([]string, newCount)

View file

@ -101,13 +101,11 @@ func TestLogBuffer_Concurrent(t *testing.T) {
// 5 readers // 5 readers
for range 5 { for range 5 {
wg.Add(1) wg.Go(func() {
go func() {
defer wg.Done()
for range 100 { for range 100 {
buf.LinesSince(0) buf.LinesSince(0)
} }
}() })
} }
wg.Wait() wg.Wait()

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"maps"
"net" "net"
"net/http" "net/http"
"os" "os"
@ -170,9 +171,7 @@ func handleStatusGateway(w http.ResponseWriter, r *http.Request, absPath string)
data["error"] = "invalid response from gateway" data["error"] = "invalid response from gateway"
} else { } else {
// Gateway is running and responded properly — merge health data // Gateway is running and responded properly — merge health data
for k, v := range healthData { maps.Copy(data, healthData)
data[k] = v
}
data["process_status"] = "running" data["process_status"] = "running"
} }
} }

View file

@ -288,11 +288,9 @@ func (cb *ContextBuilder) sourceFilesChangedLocked() bool {
// For each root: // For each root:
// 1. Creation/deletion and root directory mtime changes are tracked by fileChangedSince. // 1. Creation/deletion and root directory mtime changes are tracked by fileChangedSince.
// 2. Nested file create/delete/mtime changes are tracked by the skill file snapshot. // 2. Nested file create/delete/mtime changes are tracked by the skill file snapshot.
for _, root := range cb.skillRoots() { if slices.ContainsFunc(cb.skillRoots(), cb.fileChangedSince) {
if cb.fileChangedSince(root) {
return true return true
} }
}
if skillFilesChangedSince(cb.skillRoots(), cb.skillFilesAtCache) { if skillFilesChangedSince(cb.skillRoots(), cb.skillFilesAtCache) {
return true return true
} }

View file

@ -13,7 +13,7 @@ type AuthCredential struct {
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token,omitempty"` RefreshToken string `json:"refresh_token,omitempty"`
AccountID string `json:"account_id,omitempty"` AccountID string `json:"account_id,omitempty"`
ExpiresAt time.Time `json:"expires_at,omitempty"` ExpiresAt time.Time `json:"expires_at"`
Provider string `json:"provider"` Provider string `json:"provider"`
AuthMethod string `json:"auth_method"` AuthMethod string `json:"auth_method"`
Email string `json:"email,omitempty"` Email string `json:"email,omitempty"`

View file

@ -23,10 +23,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 := max(maxLen/10, 50) codeBlockBuffer := min(max(maxLen/10, 50), maxLen/2)
if codeBlockBuffer > maxLen/2 {
codeBlockBuffer = maxLen / 2
}
start := 0 start := 0
for start < totalLen { for start < totalLen {

View file

@ -142,7 +142,7 @@ func TestGenerateStreamID(t *testing.T) {
// Generate multiple IDs and check they are unique // Generate multiple IDs and check they are unique
ids := make(map[string]bool) ids := make(map[string]bool)
for i := 0; i < 100; i++ { for range 100 {
id := ch.generateStreamID() id := ch.generateStreamID()
if len(id) != 10 { if len(id) != 10 {

View file

@ -77,7 +77,7 @@ type WeComBotReplyMessage struct {
MsgType string `json:"msgtype"` MsgType string `json:"msgtype"`
Text struct { Text struct {
Content string `json:"content"` Content string `json:"content"`
} `json:"text,omitempty"` } `json:"text"`
} }
// NewWeComBotChannel creates a new WeCom Bot channel instance // NewWeComBotChannel creates a new WeCom Bot channel instance

View file

@ -25,7 +25,7 @@ func TestMessageDeduplicator_ConcurrentSameMessage(t *testing.T) {
wg.Add(goroutines) wg.Add(goroutines)
results := make(chan bool, goroutines) results := make(chan bool, goroutines)
for i := 0; i < goroutines; i++ { for range goroutines {
go func() { go func() {
defer wg.Done() defer wg.Done()
results <- d.MarkMessageProcessed("msg-concurrent") results <- d.MarkMessageProcessed("msg-concurrent")

View file

@ -50,9 +50,9 @@ func (f *FlexibleStringSlice) UnmarshalJSON(data []byte) error {
type Config struct { type Config struct {
Agents AgentsConfig `json:"agents"` Agents AgentsConfig `json:"agents"`
Bindings []AgentBinding `json:"bindings,omitempty"` Bindings []AgentBinding `json:"bindings,omitempty"`
Session SessionConfig `json:"session,omitempty"` Session SessionConfig `json:"session"`
Channels ChannelsConfig `json:"channels"` Channels ChannelsConfig `json:"channels"`
Providers ProvidersConfig `json:"providers,omitempty"` Providers ProvidersConfig `json:"providers"`
ModelList []ModelConfig `json:"model_list"` // New model-centric provider configuration ModelList []ModelConfig `json:"model_list"` // New model-centric provider configuration
Gateway GatewayConfig `json:"gateway"` Gateway GatewayConfig `json:"gateway"`
Tools ToolsConfig `json:"tools"` Tools ToolsConfig `json:"tools"`
@ -252,9 +252,9 @@ type TelegramConfig struct {
BaseURL string `json:"base_url" env:"PICOCLAW_CHANNELS_TELEGRAM_BASE_URL"` BaseURL string `json:"base_url" env:"PICOCLAW_CHANNELS_TELEGRAM_BASE_URL"`
Proxy string `json:"proxy" env:"PICOCLAW_CHANNELS_TELEGRAM_PROXY"` Proxy string `json:"proxy" env:"PICOCLAW_CHANNELS_TELEGRAM_PROXY"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_TELEGRAM_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_TELEGRAM_ALLOW_FROM"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
Typing TypingConfig `json:"typing,omitempty"` Typing TypingConfig `json:"typing"`
Placeholder PlaceholderConfig `json:"placeholder,omitempty"` Placeholder PlaceholderConfig `json:"placeholder"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_TELEGRAM_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_TELEGRAM_REASONING_CHANNEL_ID"`
} }
@ -265,8 +265,8 @@ type FeishuConfig struct {
EncryptKey string `json:"encrypt_key" env:"PICOCLAW_CHANNELS_FEISHU_ENCRYPT_KEY"` EncryptKey string `json:"encrypt_key" env:"PICOCLAW_CHANNELS_FEISHU_ENCRYPT_KEY"`
VerificationToken string `json:"verification_token" env:"PICOCLAW_CHANNELS_FEISHU_VERIFICATION_TOKEN"` VerificationToken string `json:"verification_token" env:"PICOCLAW_CHANNELS_FEISHU_VERIFICATION_TOKEN"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_FEISHU_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_FEISHU_ALLOW_FROM"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
Placeholder PlaceholderConfig `json:"placeholder,omitempty"` Placeholder PlaceholderConfig `json:"placeholder"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_FEISHU_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_FEISHU_REASONING_CHANNEL_ID"`
} }
@ -276,9 +276,9 @@ type DiscordConfig struct {
Proxy string `json:"proxy" env:"PICOCLAW_CHANNELS_DISCORD_PROXY"` Proxy string `json:"proxy" env:"PICOCLAW_CHANNELS_DISCORD_PROXY"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_DISCORD_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_DISCORD_ALLOW_FROM"`
MentionOnly bool `json:"mention_only" env:"PICOCLAW_CHANNELS_DISCORD_MENTION_ONLY"` MentionOnly bool `json:"mention_only" env:"PICOCLAW_CHANNELS_DISCORD_MENTION_ONLY"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
Typing TypingConfig `json:"typing,omitempty"` Typing TypingConfig `json:"typing"`
Placeholder PlaceholderConfig `json:"placeholder,omitempty"` Placeholder PlaceholderConfig `json:"placeholder"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_DISCORD_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_DISCORD_REASONING_CHANNEL_ID"`
} }
@ -295,7 +295,7 @@ type QQConfig struct {
AppID string `json:"app_id" env:"PICOCLAW_CHANNELS_QQ_APP_ID"` AppID string `json:"app_id" env:"PICOCLAW_CHANNELS_QQ_APP_ID"`
AppSecret string `json:"app_secret" env:"PICOCLAW_CHANNELS_QQ_APP_SECRET"` AppSecret string `json:"app_secret" env:"PICOCLAW_CHANNELS_QQ_APP_SECRET"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_QQ_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_QQ_ALLOW_FROM"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_QQ_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_QQ_REASONING_CHANNEL_ID"`
} }
@ -304,7 +304,7 @@ type DingTalkConfig struct {
ClientID string `json:"client_id" env:"PICOCLAW_CHANNELS_DINGTALK_CLIENT_ID"` ClientID string `json:"client_id" env:"PICOCLAW_CHANNELS_DINGTALK_CLIENT_ID"`
ClientSecret string `json:"client_secret" env:"PICOCLAW_CHANNELS_DINGTALK_CLIENT_SECRET"` ClientSecret string `json:"client_secret" env:"PICOCLAW_CHANNELS_DINGTALK_CLIENT_SECRET"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_DINGTALK_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_DINGTALK_ALLOW_FROM"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_DINGTALK_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_DINGTALK_REASONING_CHANNEL_ID"`
} }
@ -313,9 +313,9 @@ type SlackConfig struct {
BotToken string `json:"bot_token" env:"PICOCLAW_CHANNELS_SLACK_BOT_TOKEN"` BotToken string `json:"bot_token" env:"PICOCLAW_CHANNELS_SLACK_BOT_TOKEN"`
AppToken string `json:"app_token" env:"PICOCLAW_CHANNELS_SLACK_APP_TOKEN"` AppToken string `json:"app_token" env:"PICOCLAW_CHANNELS_SLACK_APP_TOKEN"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_SLACK_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_SLACK_ALLOW_FROM"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
Typing TypingConfig `json:"typing,omitempty"` Typing TypingConfig `json:"typing"`
Placeholder PlaceholderConfig `json:"placeholder,omitempty"` Placeholder PlaceholderConfig `json:"placeholder"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_SLACK_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_SLACK_REASONING_CHANNEL_ID"`
} }
@ -327,9 +327,9 @@ type LINEConfig struct {
WebhookPort int `json:"webhook_port" env:"PICOCLAW_CHANNELS_LINE_WEBHOOK_PORT"` WebhookPort int `json:"webhook_port" env:"PICOCLAW_CHANNELS_LINE_WEBHOOK_PORT"`
WebhookPath string `json:"webhook_path" env:"PICOCLAW_CHANNELS_LINE_WEBHOOK_PATH"` WebhookPath string `json:"webhook_path" env:"PICOCLAW_CHANNELS_LINE_WEBHOOK_PATH"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_LINE_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_LINE_ALLOW_FROM"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
Typing TypingConfig `json:"typing,omitempty"` Typing TypingConfig `json:"typing"`
Placeholder PlaceholderConfig `json:"placeholder,omitempty"` Placeholder PlaceholderConfig `json:"placeholder"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_LINE_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_LINE_REASONING_CHANNEL_ID"`
} }
@ -340,9 +340,9 @@ type OneBotConfig struct {
ReconnectInterval int `json:"reconnect_interval" env:"PICOCLAW_CHANNELS_ONEBOT_RECONNECT_INTERVAL"` ReconnectInterval int `json:"reconnect_interval" env:"PICOCLAW_CHANNELS_ONEBOT_RECONNECT_INTERVAL"`
GroupTriggerPrefix []string `json:"group_trigger_prefix" env:"PICOCLAW_CHANNELS_ONEBOT_GROUP_TRIGGER_PREFIX"` GroupTriggerPrefix []string `json:"group_trigger_prefix" env:"PICOCLAW_CHANNELS_ONEBOT_GROUP_TRIGGER_PREFIX"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_ONEBOT_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_ONEBOT_ALLOW_FROM"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
Typing TypingConfig `json:"typing,omitempty"` Typing TypingConfig `json:"typing"`
Placeholder PlaceholderConfig `json:"placeholder,omitempty"` Placeholder PlaceholderConfig `json:"placeholder"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_ONEBOT_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_ONEBOT_REASONING_CHANNEL_ID"`
} }
@ -356,7 +356,7 @@ type WeComConfig struct {
WebhookPath string `json:"webhook_path" env:"PICOCLAW_CHANNELS_WECOM_WEBHOOK_PATH"` WebhookPath string `json:"webhook_path" env:"PICOCLAW_CHANNELS_WECOM_WEBHOOK_PATH"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WECOM_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WECOM_ALLOW_FROM"`
ReplyTimeout int `json:"reply_timeout" env:"PICOCLAW_CHANNELS_WECOM_REPLY_TIMEOUT"` ReplyTimeout int `json:"reply_timeout" env:"PICOCLAW_CHANNELS_WECOM_REPLY_TIMEOUT"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_WECOM_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_WECOM_REASONING_CHANNEL_ID"`
} }
@ -372,7 +372,7 @@ type WeComAppConfig struct {
WebhookPath string `json:"webhook_path" env:"PICOCLAW_CHANNELS_WECOM_APP_WEBHOOK_PATH"` WebhookPath string `json:"webhook_path" env:"PICOCLAW_CHANNELS_WECOM_APP_WEBHOOK_PATH"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WECOM_APP_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WECOM_APP_ALLOW_FROM"`
ReplyTimeout int `json:"reply_timeout" env:"PICOCLAW_CHANNELS_WECOM_APP_REPLY_TIMEOUT"` ReplyTimeout int `json:"reply_timeout" env:"PICOCLAW_CHANNELS_WECOM_APP_REPLY_TIMEOUT"`
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"` GroupTrigger GroupTriggerConfig `json:"group_trigger"`
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_WECOM_APP_REASONING_CHANNEL_ID"` ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_WECOM_APP_REASONING_CHANNEL_ID"`
} }
@ -398,7 +398,7 @@ type PicoConfig struct {
WriteTimeout int `json:"write_timeout,omitempty"` WriteTimeout int `json:"write_timeout,omitempty"`
MaxConnections int `json:"max_connections,omitempty"` MaxConnections int `json:"max_connections,omitempty"`
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_PICO_ALLOW_FROM"` AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_PICO_ALLOW_FROM"`
Placeholder PlaceholderConfig `json:"placeholder,omitempty"` Placeholder PlaceholderConfig `json:"placeholder"`
} }
type HeartbeatConfig struct { type HeartbeatConfig struct {

View file

@ -5,6 +5,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"maps"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
@ -332,9 +333,7 @@ func (m *Manager) ConnectServer(
if err != nil { if err != nil {
return fmt.Errorf("failed to load env file %s: %w", cfg.EnvFile, err) return fmt.Errorf("failed to load env file %s: %w", cfg.EnvFile, err)
} }
for k, v := range envVars { maps.Copy(envMap, envVars)
envMap[k] = v
}
logger.DebugCF("mcp", "Loaded environment variables from file", logger.DebugCF("mcp", "Loaded environment variables from file",
map[string]any{ map[string]any{
"server": name, "server": name,
@ -344,9 +343,7 @@ func (m *Manager) ConnectServer(
} }
// Environment variables from config override those from file // Environment variables from config override those from file
for k, v := range cfg.Env { maps.Copy(envMap, cfg.Env)
envMap[k] = v
}
// Convert map to slice // Convert map to slice
env := make([]string, 0, len(envMap)) env := make([]string, 0, len(envMap))
@ -420,9 +417,7 @@ func (m *Manager) GetServers() map[string]*ServerConnection {
defer m.mu.RUnlock() defer m.mu.RUnlock()
result := make(map[string]*ServerConnection, len(m.servers)) result := make(map[string]*ServerConnection, len(m.servers))
for k, v := range m.servers { maps.Copy(result, m.servers)
result[k] = v
}
return result return result
} }

View file

@ -2,6 +2,7 @@ package mcp
import ( import (
"context" "context"
"maps"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -168,12 +169,8 @@ SHARED_VAR=from_file`
// Merge: envFile first, then config overrides // Merge: envFile first, then config overrides
merged := make(map[string]string) merged := make(map[string]string)
for k, v := range envVars { maps.Copy(merged, envVars)
merged[k] = v maps.Copy(merged, configEnv)
}
for k, v := range configEnv {
merged[k] = v
}
// Verify priority: config.Env should override envFile // Verify priority: config.Env should override envFile
if merged["SHARED_VAR"] != "from_config" { if merged["SHARED_VAR"] != "from_config" {

View file

@ -198,7 +198,7 @@ func (t *I2CTool) readDevice(args map[string]any) *ToolResult {
// Format as hex bytes // Format as hex bytes
hexBytes := make([]string, n) hexBytes := make([]string, n)
intBytes := make([]int, n) intBytes := make([]int, n)
for i := 0; i < n; i++ { for i := range n {
hexBytes[i] = fmt.Sprintf("0x%02x", buf[i]) hexBytes[i] = fmt.Sprintf("0x%02x", buf[i])
intBytes[i] = int(buf[i]) intBytes[i] = int(buf[i])
} }