From 44e84585d61432813c9e472328ef00a960bf72c4 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 28 Mar 2026 08:55:07 +0000 Subject: [PATCH] ci: fix linter errors in CI pipeline - Fixed `musttag` errors in `web/backend/api/config.go` by explicitly decoding JSON into an anonymous struct. - Fixed a `govet` shadow error in `pkg/providers/common/http_logger.go`. - Fixed formatting errors reported by `golines` and `gci` in `pkg/config/config.go`, `pkg/config/security.go`, and `pkg/providers/anthropic_messages/provider.go`. Co-authored-by: TanLuong <28281768+TanLuong@users.noreply.github.com> --- pkg/config/config.go | 10 +++--- pkg/config/security.go | 4 ++- pkg/providers/anthropic_messages/provider.go | 26 +++++++++++---- pkg/providers/common/http_logger.go | 4 +-- web/backend/api/config.go | 34 +++++++++++++++++--- 5 files changed, 58 insertions(+), 20 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 3b558d780..70ab3339f 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1048,10 +1048,10 @@ type SearXNGConfig struct { } type GLMSearchConfig struct { - Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_WEB_GLM_ENABLED"` - apiKey string - secDirty bool - BaseURL string `json:"base_url" env:"PICOCLAW_TOOLS_WEB_GLM_BASE_URL"` + Enabled bool `json:"enabled" env:"PICOCLAW_TOOLS_WEB_GLM_ENABLED"` + apiKey string + secDirty bool + BaseURL string `json:"base_url" env:"PICOCLAW_TOOLS_WEB_GLM_BASE_URL"` // SearchEngine specifies the search backend: "search_std" (default), // "search_pro", "search_pro_sogou", or "search_pro_quark". SearchEngine string `json:"search_engine" env:"PICOCLAW_TOOLS_WEB_GLM_SEARCH_ENGINE"` @@ -1766,7 +1766,7 @@ func SaveConfig(path string, cfg *Config) error { m.secModelName = newName } - + cfg.security.ModelList = newModelList if cfg.Channels.Pico.secDirty { cfg.security.Channels.Pico = &PicoSecurity{ diff --git a/pkg/config/security.go b/pkg/config/security.go index f5fc51b5c..3603d1ab0 100644 --- a/pkg/config/security.go +++ b/pkg/config/security.go @@ -239,6 +239,7 @@ func (c *Config) MergeAndApplySecurity(newer *SecurityConfig) error { c.security = mergeSecurityConfig(c.security, newer) return applySecurityConfig(c, c.security) } + // mergeSecurityConfig merges two SecurityConfig instances, preferring non-empty values from 'newer'. // This is used during config migration to preserve existing security data while adding new entries. func mergeSecurityConfig(existing, newer *SecurityConfig) *SecurityConfig { @@ -335,7 +336,8 @@ func mergeChannelsSecurity(dst, src *ChannelsSecurity) { if src.Pico != nil && src.Pico.Token != "" { dst.Pico = src.Pico } - if src.IRC != nil && (src.IRC.Password != "" || src.IRC.NickServPassword != "" || src.IRC.SASLPassword != "") { + if src.IRC != nil && + (src.IRC.Password != "" || src.IRC.NickServPassword != "" || src.IRC.SASLPassword != "") { dst.IRC = src.IRC } } diff --git a/pkg/providers/anthropic_messages/provider.go b/pkg/providers/anthropic_messages/provider.go index 4093f6a74..679a4e966 100644 --- a/pkg/providers/anthropic_messages/provider.go +++ b/pkg/providers/anthropic_messages/provider.go @@ -58,8 +58,8 @@ func NewProviderWithTimeout(apiKey, apiBase string, timeoutSeconds int) *Provide } return &Provider{ - apiKey: apiKey, - apiBase: baseURL, + apiKey: apiKey, + apiBase: baseURL, httpClient: common.NewHTTPClientWithTimeout("", timeout), } } @@ -102,7 +102,10 @@ func (p *Provider) Chat( // Set headers req.Header.Set("Content-Type", "application/json") - req.Header.Set("X-API-Key", p.apiKey) //nolint:canonicalheader // Anthropic API requires exact header name + req.Header.Set( + "X-API-Key", + p.apiKey, + ) //nolint:canonicalheader // Anthropic API requires exact header name req.Header.Set("Anthropic-Version", defaultAPIVersion) // Execute request @@ -134,7 +137,11 @@ func (p *Provider) Chat( return nil, fmt.Errorf("service unavailable (503): %s", string(body)) default: if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("API request failed with status %d: %s", resp.StatusCode, string(body)) + return nil, fmt.Errorf( + "API request failed with status %d: %s", + resp.StatusCode, + string(body), + ) } } @@ -194,7 +201,8 @@ func buildRequestBody( "content": msg.Content, } if len(apiMessages) > 0 { - if prev, ok := apiMessages[len(apiMessages)-1].(map[string]any); ok && prev["role"] == "user" { + if prev, ok := apiMessages[len(apiMessages)-1].(map[string]any); ok && + prev["role"] == "user" { if content, ok := prev["content"].([]map[string]any); ok { prev["content"] = append(content, toolResultBlock) continue @@ -258,7 +266,8 @@ func buildRequestBody( "content": msg.Content, } if len(apiMessages) > 0 { - if prev, ok := apiMessages[len(apiMessages)-1].(map[string]any); ok && prev["role"] == "user" { + if prev, ok := apiMessages[len(apiMessages)-1].(map[string]any); ok && + prev["role"] == "user" { if content, ok := prev["content"].([]map[string]any); ok { prev["content"] = append(content, toolResultBlock) continue @@ -310,7 +319,10 @@ func parseResponseBody(body []byte) (*LLMResponse, error) { // Extract content and tool calls var content strings.Builder - toolCalls := make([]ToolCall, 0) // Initialize as empty slice (not nil) for consistent JSON serialization + toolCalls := make( + []ToolCall, + 0, + ) // Initialize as empty slice (not nil) for consistent JSON serialization for _, block := range resp.Content { switch block.Type { diff --git a/pkg/providers/common/http_logger.go b/pkg/providers/common/http_logger.go index c999d93ac..e916a9f2f 100644 --- a/pkg/providers/common/http_logger.go +++ b/pkg/providers/common/http_logger.go @@ -48,8 +48,8 @@ func (lrt *LoggingRoundTripper) RoundTrip(req *http.Request) (*http.Response, er // Optional: Log Response Body if res.Body != nil { - bodyBytes, err := io.ReadAll(res.Body) - if err == nil { + bodyBytes, readErr := io.ReadAll(res.Body) + if readErr == nil { res.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) // Truncate response body if too long to avoid flooding logs respStr := string(bodyBytes) diff --git a/web/backend/api/config.go b/web/backend/api/config.go index 20aebef30..db8167311 100644 --- a/web/backend/api/config.go +++ b/web/backend/api/config.go @@ -66,9 +66,22 @@ func (h *Handler) handleUpdateConfig(w http.ResponseWriter, r *http.Request) { cfg.SecurityCopyFrom(oldCfg) // Intercept explicitly provided security tokens from JSON payload that json.Unmarshal drops. - var incomingSec config.SecurityConfig + // We need to decode into an anonymous struct with json tags because SecurityConfig + // doesn't have json tags for its fields (it uses yaml tags). + var incomingSec struct { + ModelList map[string]config.ModelSecurityEntry `json:"model_list"` + Channels *config.ChannelsSecurity `json:"channels,omitempty"` + Web *config.WebToolsSecurity `json:"web,omitempty"` + Skills *config.SkillsSecurity `json:"skills,omitempty"` + } if err := json.Unmarshal(body, &incomingSec); err == nil { - cfg.MergeAndApplySecurity(&incomingSec) + secConfig := config.SecurityConfig{ + ModelList: incomingSec.ModelList, + Channels: incomingSec.Channels, + Web: incomingSec.Web, + Skills: incomingSec.Skills, + } + cfg.MergeAndApplySecurity(&secConfig) } else { cfg.ApplySecurity() } @@ -164,9 +177,20 @@ func (h *Handler) handlePatchConfig(w http.ResponseWriter, r *http.Request) { // Restore security fields from existing config and merge explicitly provided overrides. newCfg.SecurityCopyFrom(cfg) - var incomingSec config.SecurityConfig - if err := json.Unmarshal(patchBody, &incomingSec); err == nil { - newCfg.MergeAndApplySecurity(&incomingSec) + var patchSec struct { + ModelList map[string]config.ModelSecurityEntry `json:"model_list"` + Channels *config.ChannelsSecurity `json:"channels,omitempty"` + Web *config.WebToolsSecurity `json:"web,omitempty"` + Skills *config.SkillsSecurity `json:"skills,omitempty"` + } + if err := json.Unmarshal(patchBody, &patchSec); err == nil { + secConfig := config.SecurityConfig{ + ModelList: patchSec.ModelList, + Channels: patchSec.Channels, + Web: patchSec.Web, + Skills: patchSec.Skills, + } + newCfg.MergeAndApplySecurity(&secConfig) } else { newCfg.ApplySecurity() }