diff --git a/.golangci.yml b/.golangci.yml index dab57df..d2c5da5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,10 +1,16 @@ version: "2" + +run: + timeout: 10m + output: sort-order: - file + linters: default: none enable: + # === Existing linters === - bidichk - bodyclose - depguard @@ -29,6 +35,33 @@ linters: - usestdlibvars - usetesting - wastedassign + + # === Error handling (Google: Error handling section) === + - errorlint # %w vs %v, errors.Is/As checks + - nilerr # return nil when err != nil pitfall + + # === Context ("Contexts are never included in option structs") === + - containedctx # no context in struct fields + - contextcheck # correct context propagation + - noctx # HTTP/DB calls missing context + + # === Tests (Google: Tests section, especially t.Helper) === + - thelper # helpers must call t.Helper() + + # === Shadowing / naming (Google: Shadowing section) === + - predeclared # avoid shadowing len/error/url etc. + + # === Global state (Google: Global state section) === + - reassign # forbid reassigning package-level variables + + # === Modern Go idioms === + - copyloopvar # Go 1.22+ loop variable semantics (replaces exportloopref) + - intrange # Go 1.22+ `for i := range n` + + # === Documentation / performance === + - misspell # English spelling + - prealloc # aligned with "size hints" guidance + settings: depguard: rules: @@ -40,22 +73,45 @@ linters: desc: it's experimental and unreliable - pkg: github.com/pkg/errors desc: use builtin errors package instead - nolintlint: - allow-unused: false - require-explanation: true - require-specific: true + - pkg: math/rand$ + desc: use math/rand/v2 (Go 1.22+) for better API and distribution + + errorlint: + errorf: true # require %w when wrapping with fmt.Errorf + errorf-multi: true # allow Go 1.20+ multiple %w verbs + asserts: true # use errors.As rather than type assertion + comparison: true # use errors.Is rather than == + + govet: + enable: + - nilness + - unusedwrite + - shadow # Google explicitly warns about shadowing + gocritic: enabled-checks: - equalFold + - boolExprSimplify + - builtinShadow + - commentedOutCode + - emptyStringTest + - hugeParam # avoid passing large value types by value + - nestingReduce # encourages early return + - rangeValCopy # range copying large objects + - stringXbytes + - truncateCmp disabled-checks: [] + revive: severity: error rules: - name: blank-imports + - name: bool-literal-in-expr # new: avoid `x == true` - name: constant-logical-expr - name: context-as-argument - name: context-keys-type - name: dot-imports + - name: early-return # new: Google prefers early returns - name: empty-lines - name: error-return - name: error-strings @@ -63,27 +119,62 @@ linters: - name: identical-branches - name: if-return - name: increment-decrement + - name: indent-error-flow # new: no else after err != nil return - name: modifies-value-receiver - name: package-comments + - name: range-val-in-closure # new: loop variable capture in closures + - name: receiver-naming # new: consistent receiver names - name: redefines-builtin-id + - name: string-of-int # new: unsafe string(int) conversion + - name: struct-tag # new: struct tag validity - name: superfluous-else - name: time-naming - name: unexported-return + - name: unnecessary-stmt # new: redundant statements + - name: use-any # new: Google examples consistently use `any` + - name: useless-break # new: redundant break in switch/select - name: var-declaration - name: var-naming disabled: true + staticcheck: checks: - all + testifylint: {} + + thelper: + test: + first: true + name: true + begin: true + benchmark: + first: true + name: true + begin: true + tb: + first: true + name: true + begin: true + fuzz: + first: true + name: true + begin: true + usetesting: os-temp-dir: true + perfsprint: concat-loop: false - govet: - enable: - - nilness - - unusedwrite + + misspell: + locale: US + + nolintlint: + allow-unused: false + require-explanation: true + require-specific: true + exclusions: generated: lax presets: @@ -96,19 +187,29 @@ linters: - errcheck - staticcheck - unparam + - containedctx + - contextcheck + - noctx + - prealloc path: _test\.go + issues: max-issues-per-linter: 0 max-same-issues: 0 + formatters: enable: - gofmt - gofumpt + - goimports # Google Decisions specifies import grouping - golines settings: gofumpt: extra-rules: true + goimports: + local-prefixes: + - github.com/appleboy # group all appleboy org packages (CodeGPT + com/*) as local + golines: + max-len: 120 exclusions: generated: lax -run: - timeout: 10m diff --git a/cmd/cmd.go b/cmd/cmd.go index b6183a8..c60abcb 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -2,6 +2,7 @@ package cmd import ( "context" + "errors" "fmt" "log" "os" @@ -10,9 +11,10 @@ import ( "github.com/appleboy/CodeGPT/util" - "github.com/appleboy/com/file" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/appleboy/com/file" ) var rootCmd = &cobra.Command{ @@ -154,11 +156,15 @@ func initConfig() { } if err := viper.ReadInConfig(); err != nil { - if _, ok := err.(viper.ConfigFileNotFoundError); ok { - // Config file not found; ignore error if desired - _, err := os.Create(cfgFile) - if err != nil { - log.Fatal(err) + var configFileNotFoundError viper.ConfigFileNotFoundError + if errors.As(err, &configFileNotFoundError) { + // Config file not found; create an empty one. + f, createErr := os.Create(cfgFile) + if createErr != nil { + log.Fatal(createErr) + } + if closeErr := f.Close(); closeErr != nil { + log.Fatal(closeErr) } } else { // Config file was found but another error was produced diff --git a/cmd/commit.go b/cmd/commit.go index 22935c7..c387318 100644 --- a/cmd/commit.go +++ b/cmd/commit.go @@ -142,9 +142,9 @@ var commitCmd = &cobra.Command{ // Add template variables from file if templateVarsFile != "" { - allENV, err := godotenv.Read(templateVarsFile) - if err != nil { - return err + allENV, readEnvErr := godotenv.Read(templateVarsFile) + if readEnvErr != nil { + return readEnvErr } for k, v := range allENV { data[k] = v @@ -153,14 +153,14 @@ var commitCmd = &cobra.Command{ // Get code review message from diff data if _, ok := data[prompt.SummarizeMessageKey]; !ok { - out, err := util.GetTemplateByString( + out, summErr := util.GetTemplateByString( prompt.SummarizeFileDiffTemplate, util.Data{ "file_diffs": diff, }, ) - if err != nil { - return err + if summErr != nil { + return summErr } // Determine if the user wants to use the prompt only @@ -173,9 +173,9 @@ var commitCmd = &cobra.Command{ // Get summarized comment from diff data color.Cyan("Summarizing git diff...") - resp, err := callCompletion(cmd.Context(), client, out, os.Stdout) - if err != nil { - return err + resp, summErr := callCompletion(cmd.Context(), client, out, os.Stdout) + if summErr != nil { + return summErr } data[prompt.SummarizeMessageKey] = strings.TrimSpace(resp.Content) color.Magenta(resp.Usage.String()) @@ -183,14 +183,14 @@ var commitCmd = &cobra.Command{ // Get summarized title from diff data if _, ok := data[prompt.SummarizeTitleKey]; !ok { - out, err := util.GetTemplateByString( + out, titleErr := util.GetTemplateByString( prompt.SummarizeTitleTemplate, util.Data{ "summary_points": data[prompt.SummarizeMessageKey], }, ) - if err != nil { - return err + if titleErr != nil { + return titleErr } // Generate title for pull request with retry if empty @@ -202,15 +202,15 @@ var commitCmd = &cobra.Command{ var resp *core.Response for attempt := 1; attempt <= maxRetries; attempt++ { - resp, err = client.Completion(cmd.Context(), out) - if err != nil { - return err + resp, titleErr = client.Completion(cmd.Context(), out) + if titleErr != nil { + return titleErr } summarizeTitle = strings.TrimSpace(resp.Content) color.Magenta(resp.Usage.String()) - if len(summarizeTitle) > 0 { + if summarizeTitle != "" { break } @@ -220,7 +220,7 @@ var commitCmd = &cobra.Command{ } } - if len(summarizeTitle) == 0 { + if summarizeTitle == "" { return fmt.Errorf("failed to get valid title after %d attempts", maxRetries) } @@ -233,21 +233,21 @@ var commitCmd = &cobra.Command{ } if _, ok := data[prompt.SummarizePrefixKey]; !ok { - out, err := util.GetTemplateByString( + out, prefixErr := util.GetTemplateByString( prompt.ConventionalCommitTemplate, util.Data{ "summary_points": data[prompt.SummarizeMessageKey], }, ) - if err != nil { - return err + if prefixErr != nil { + return prefixErr } message := "Generating conventional commit prefix" summaryPrix := "" color.Cyan(message + " (Tools)") - resp, err := client.GetSummaryPrefix(cmd.Context(), out) - if err != nil { - return err + resp, prefixErr := client.GetSummaryPrefix(cmd.Context(), out) + if prefixErr != nil { + return prefixErr } summaryPrix = resp.Content @@ -258,9 +258,9 @@ var commitCmd = &cobra.Command{ var commitMessage string if viper.GetString("git.template_file") != "" { - format, err := os.ReadFile(viper.GetString("git.template_file")) - if err != nil { - return err + format, readErr := os.ReadFile(viper.GetString("git.template_file")) + if readErr != nil { + return readErr } commitMessage, err = util.NewTemplateByString( string(format), @@ -288,15 +288,15 @@ var commitCmd = &cobra.Command{ } if prompt.GetLanguage(viper.GetString("output.lang")) != prompt.DefaultLanguage { - out, err := util.GetTemplateByString( + out, transErr := util.GetTemplateByString( prompt.TranslationTemplate, util.Data{ "output_language": prompt.GetLanguage(viper.GetString("output.lang")), "output_message": commitMessage, }, ) - if err != nil { - return err + if transErr != nil { + return transErr } // Translate git commit message @@ -305,9 +305,9 @@ var commitCmd = &cobra.Command{ viper.GetString("output.lang"), ), ) - resp, err := callCompletion(cmd.Context(), client, out, os.Stdout) - if err != nil { - return err + resp, transErr := callCompletion(cmd.Context(), client, out, os.Stdout) + if transErr != nil { + return transErr } color.Magenta(resp.Usage.String()) commitMessage = resp.Content @@ -324,9 +324,9 @@ var commitCmd = &cobra.Command{ outputFile := viper.GetString("output.file") if outputFile == "" { - out, err := g.GitDir(cmd.Context()) - if err != nil { - return err + out, dirErr := g.GitDir(cmd.Context()) + if dirErr != nil { + return dirErr } outputFile = path.Join(strings.TrimSpace(out), "COMMIT_EDITMSG") } @@ -342,11 +342,11 @@ var commitCmd = &cobra.Command{ if noConfirm { return nil } - if ready, err := confirmation.New("Commit this preview summary?", confirmation.Yes). - RunPrompt(); err != nil || + if ready, confirmErr := confirmation.New("Commit this preview summary?", confirmation.Yes). + RunPrompt(); confirmErr != nil || !ready { - if err != nil { - return err + if confirmErr != nil { + return confirmErr } return nil } @@ -354,14 +354,14 @@ var commitCmd = &cobra.Command{ // Handle commit message change prompt when confirmation is enabled if !noConfirm { - if change, err := confirmation.New("Do you want to modify the commit message?", confirmation.No). - RunPrompt(); err != nil { - return err + if change, confirmErr := confirmation.New("Do you want to modify the commit message?", confirmation.No). + RunPrompt(); confirmErr != nil { + return confirmErr } else if change { m := initialPrompt(commitMessage) p := tea.NewProgram(m, tea.WithContext(cmd.Context())) - if _, err := p.Run(); err != nil { - return err + if _, runErr := p.Run(); runErr != nil { + return runErr } p.Wait() commitMessage = m.textarea.Value() diff --git a/cmd/hepler.go b/cmd/hepler.go index 2fb741e..479840a 100644 --- a/cmd/hepler.go +++ b/cmd/hepler.go @@ -5,12 +5,13 @@ import ( "errors" "fmt" + "github.com/spf13/viper" + "github.com/appleboy/CodeGPT/git" "github.com/appleboy/CodeGPT/prompt" "github.com/appleboy/CodeGPT/provider/openai" "github.com/appleboy/CodeGPT/util" "github.com/appleboy/com/file" - "github.com/spf13/viper" ) func check(ctx context.Context) error { @@ -69,7 +70,7 @@ func check(ctx context.Context) error { if cfgTemplateFile != "" { exists, err := file.IsFile(cfgTemplateFile) if err != nil { - return fmt.Errorf("failed to check template file: %v", err) + return fmt.Errorf("failed to check template file: %w", err) } if !exists { return fmt.Errorf("template file not found at: %s", cfgTemplateFile) @@ -79,7 +80,7 @@ func check(ctx context.Context) error { if templateVarsFile != "" { exists, err := file.IsFile(templateVarsFile) if err != nil { - return fmt.Errorf("failed to check template variables file: %v", err) + return fmt.Errorf("failed to check template variables file: %w", err) } if !exists { return fmt.Errorf("template variables file not found at: %s", templateVarsFile) @@ -90,7 +91,7 @@ func check(ctx context.Context) error { promptFolder := viper.GetString("prompt.folder") if promptFolder != "" { if err := util.LoadTemplatesFromDir(promptFolder); err != nil { - return fmt.Errorf("failed to load custom prompt templates: %s", err) + return fmt.Errorf("failed to load custom prompt templates: %w", err) } } diff --git a/cmd/prompt.go b/cmd/prompt.go index 6d61e1f..183d591 100644 --- a/cmd/prompt.go +++ b/cmd/prompt.go @@ -4,11 +4,12 @@ import ( "os" "path" - "github.com/appleboy/CodeGPT/prompt" "github.com/erikgeiser/promptkit/confirmation" "github.com/fatih/color" "github.com/spf13/cobra" "github.com/spf13/viper" + + "github.com/appleboy/CodeGPT/prompt" ) var loadPromptData bool diff --git a/cmd/version.go b/cmd/version.go index 316a357..1e88ee5 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -39,7 +39,7 @@ var versionCmd = &cobra.Command{ BuildArch: version.BuildArch, Platform: fmt.Sprintf("%s/%s", version.BuildOS, version.BuildArch), } - return printVersion(outputFormat, v) + return printVersion(outputFormat, &v) }, } @@ -63,9 +63,9 @@ printVersion prints version information in the specified format. format: "text" for colored CLI output, "json" for JSON output. v: VersionInfo struct containing version data. */ -func printVersion(format string, v VersionInfo) error { +func printVersion(format string, v *VersionInfo) error { // Use short SHA for Git commit - shortV := v + shortV := *v shortV.GitCommit = shortCommit(v.GitCommit) switch format { case "json": diff --git a/git/git.go b/git/git.go index 520d0f6..291e128 100644 --- a/git/git.go +++ b/git/git.go @@ -31,7 +31,7 @@ type Command struct { // excludeFiles returns a list of files to be excluded from git operations. // It prepends each file in the excludeList with the exclude and top options. func (c *Command) excludeFiles() []string { - var excludedFiles []string + excludedFiles := make([]string, 0, len(c.excludeList)) for _, f := range c.excludeList { excludedFiles = append(excludedFiles, ":(exclude,top)"+f) } @@ -198,7 +198,7 @@ func (c *Command) DiffFiles(ctx context.Context) (string, error) { if err != nil { return "", err } - if string(output) == "" { + if len(output) == 0 { return "", errors.New("please add your staged changes using git add ") } @@ -219,9 +219,9 @@ func (c *Command) InstallHook(ctx context.Context) error { } target := path.Join(strings.TrimSpace(string(hookPath)), HookPrepareCommitMessageTemplate) - if exists, err := file.IsFile(target); err != nil { - if !os.IsNotExist(err) { - return err + if exists, statErr := file.IsFile(target); statErr != nil { + if !os.IsNotExist(statErr) { + return statErr } } else if exists { return errors.New("hook file prepare-commit-msg exist") diff --git a/go.mod b/go.mod index 70ffb75..70be532 100644 --- a/go.mod +++ b/go.mod @@ -7,60 +7,65 @@ require ( github.com/appleboy/graceful v1.3.0 github.com/charmbracelet/bubbles v1.0.0 github.com/charmbracelet/bubbletea v1.3.10 - github.com/erikgeiser/promptkit v0.9.0 - github.com/fatih/color v1.18.0 - github.com/go-authgate/sdk-go v0.2.0 + github.com/erikgeiser/promptkit v0.11.0 + github.com/fatih/color v1.19.0 + github.com/go-authgate/sdk-go v0.11.0 github.com/joho/godotenv v1.5.1 - github.com/liushuangls/go-anthropic/v2 v2.17.2 + github.com/liushuangls/go-anthropic/v2 v2.20.1 github.com/rodaine/table v1.3.1 github.com/sashabaranov/go-openai v1.41.2 github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 github.com/yassinebenaid/godump v0.11.1 - golang.org/x/net v0.52.0 - golang.org/x/sys v0.42.0 - google.golang.org/genai v1.49.0 + golang.org/x/net v0.54.0 + golang.org/x/sys v0.44.0 + google.golang.org/genai v1.57.0 ) require ( - al.essio.dev/pkg/shellescape v1.6.0 // indirect + charm.land/bubbles/v2 v2.1.0 // indirect + charm.land/bubbletea/v2 v2.0.6 // indirect + charm.land/lipgloss/v2 v2.0.3 // indirect cloud.google.com/go v0.123.0 // indirect - cloud.google.com/go/auth v0.18.2 // indirect + cloud.google.com/go/auth v0.20.0 // indirect cloud.google.com/go/compute/metadata v0.9.0 // indirect github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/colorprofile v0.4.3 // indirect github.com/charmbracelet/lipgloss v1.1.0 // indirect - github.com/charmbracelet/x/ansi v0.11.6 // indirect + github.com/charmbracelet/ultraviolet v0.0.0-20260511121909-c840852527f3 // indirect + github.com/charmbracelet/x/ansi v0.11.7 // indirect github.com/charmbracelet/x/cellbuf v0.0.15 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect + github.com/charmbracelet/x/termios v0.1.1 // indirect + github.com/charmbracelet/x/windows v0.2.2 // indirect github.com/clipperhouse/displaywidth v0.11.0 // indirect github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/danieljoos/wincred v1.2.3 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/godbus/dbus/v5 v5.2.2 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/s2a-go v0.1.9 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect - github.com/googleapis/gax-go/v2 v2.18.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.15 // indirect + github.com/googleapis/gax-go/v2 v2.22.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/lucasb-eyer/go-colorful v1.3.0 // indirect + github.com/lucasb-eyer/go-colorful v1.4.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.22 // indirect github.com/mattn/go-localereader v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.21 // indirect + github.com/mattn/go-runewidth v0.0.23 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.16.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pelletier/go-toml/v2 v2.3.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sagikazarmark/locafero v0.12.0 // indirect github.com/spf13/afero v1.15.0 // indirect @@ -68,17 +73,19 @@ require ( github.com/spf13/pflag v1.0.10 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - github.com/zalando/go-keyring v0.2.6 // indirect + github.com/zalando/go-keyring v0.2.8 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect - go.opentelemetry.io/otel v1.42.0 // indirect - go.opentelemetry.io/otel/metric v1.42.0 // indirect - go.opentelemetry.io/otel/trace v1.42.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect + go.opentelemetry.io/otel v1.43.0 // indirect + go.opentelemetry.io/otel/metric v1.43.0 // indirect + go.opentelemetry.io/otel/trace v1.43.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.49.0 // indirect + golang.org/x/crypto v0.51.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect - golang.org/x/text v0.35.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c // indirect - google.golang.org/grpc v1.79.3 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/text v0.37.0 // indirect + google.golang.org/api v0.279.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260511170946-3700d4141b60 // indirect + google.golang.org/grpc v1.81.1 // indirect google.golang.org/protobuf v1.36.11 // indirect ) diff --git a/go.sum b/go.sum index bae4668..25da8f5 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,13 @@ -al.essio.dev/pkg/shellescape v1.6.0 h1:NxFcEqzFSEVCGN2yq7Huv/9hyCEGVa/TncnOOBBeXHA= -al.essio.dev/pkg/shellescape v1.6.0/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890= +charm.land/bubbles/v2 v2.1.0 h1:YSnNh5cPYlYjPxRrzs5VEn3vwhtEn3jVGRBT3M7/I0g= +charm.land/bubbles/v2 v2.1.0/go.mod h1:l97h4hym2hvWBVfmJDtrEHHCtkIKeTEb3TTJ4ZOB3wY= +charm.land/bubbletea/v2 v2.0.6 h1:UHN/91OyuhaOFGSrBXQ/hMZD8IO1Uc4BvHlgHXL2WJo= +charm.land/bubbletea/v2 v2.0.6/go.mod h1:MH/D8ZLlN3op37vQvijKuU29g3rqTp+aQapURFonF9g= +charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU= +charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA= cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= -cloud.google.com/go/auth v0.18.2 h1:+Nbt5Ev0xEqxlNjd6c+yYUeosQ5TtEUaNcN/3FozlaM= -cloud.google.com/go/auth v0.18.2/go.mod h1:xD+oY7gcahcu7G2SG2DsBerfFxgPAJz17zz2joOFF3M= +cloud.google.com/go/auth v0.20.0 h1:kXTssoVb4azsVDoUiF8KvxAqrsQcQtB53DcSgta74CA= +cloud.google.com/go/auth v0.20.0/go.mod h1:942/yi/itH1SsmpyrbnTMDgGfdy2BUqIKyd0cyYLc5Q= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= @@ -16,8 +20,8 @@ github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= -github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= +github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= +github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v1.0.0 h1:12J8/ak/uCZEMQ6KU7pcfwceyjLlWsDLAxB5fXonfvc= @@ -28,12 +32,20 @@ github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= -github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= +github.com/charmbracelet/ultraviolet v0.0.0-20260511121909-c840852527f3 h1:pxGjlWZFcRQMWAdtjRelpL3Gbu8iYIyuO3Eqbd037Ow= +github.com/charmbracelet/ultraviolet v0.0.0-20260511121909-c840852527f3/go.mod h1:SnKWaPaTnkTNXJgdgdquu66de12V8pW/b/qlTGaF9xg= +github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI= +github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ= github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= +github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA= +github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= +github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= +github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= +github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM= +github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k= github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8= github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0= github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= @@ -45,18 +57,18 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= -github.com/erikgeiser/promptkit v0.9.0 h1:3qL1mS/ntCrXdb8sTP/ka82CJ9kEQaGuYXNrYJkWYBc= -github.com/erikgeiser/promptkit v0.9.0/go.mod h1:pU9dtogSe3Jlc2AY77EP7R4WFP/vgD4v+iImC83KsCo= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/erikgeiser/promptkit v0.11.0 h1:GX/pGeF/V3e8ijAjQ1S6NxKbpk3sf2ucdJAP2GG4I7Y= +github.com/erikgeiser/promptkit v0.11.0/go.mod h1:Xq4u5w2exkMMMqH/lBO+qUXQX6DoGp5lSplPFa7C0jQ= +github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= +github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-authgate/sdk-go v0.2.0 h1:w22f+sAg/YMqnLOcS/4SAuMZXTbPurzkSQBsjb1hcbw= -github.com/go-authgate/sdk-go v0.2.0/go.mod h1:RGqvrFdrPnOumndoQQV8qzu8zP1KFUZPdhX0IkWduho= +github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= +github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= +github.com/go-authgate/sdk-go v0.11.0 h1:ZTfJ0rzeDn4QBqAmF9VKS3CqlKhE8+0tJxg8OGNtIzo= +github.com/go-authgate/sdk-go v0.11.0/go.mod h1:sa0ige5wtayj2WcnXlxa8wGuyi5z/c/chc0mXPJTl/Q= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -72,14 +84,12 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA6RlzjJaT4hi3kII+zYw8wmLb8= -github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= -github.com/googleapis/gax-go/v2 v2.18.0 h1:jxP5Uuo3bxm3M6gGtV94P4lliVetoCB4Wk2x8QA86LI= -github.com/googleapis/gax-go/v2 v2.18.0/go.mod h1:uSzZN4a356eRG985CzJ3WfbFSpqkLTjsnhWGJR6EwrE= +github.com/googleapis/enterprise-certificate-proxy v0.3.15 h1:xolVQTEXusUcAA5UgtyRLjelpFFHWlPQ4XfWGc7MBas= +github.com/googleapis/enterprise-certificate-proxy v0.3.15/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= +github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4= +github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -90,19 +100,19 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/liushuangls/go-anthropic/v2 v2.17.2 h1:vL3gnBYANpOxEsVHE8/YwSugJ87ooE93bMQ0bvCLrgo= -github.com/liushuangls/go-anthropic/v2 v2.17.2/go.mod h1:a550cJXPoTG2FL3DvfKG2zzD5O2vjgvo4tHtoGPzFLU= -github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= -github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/liushuangls/go-anthropic/v2 v2.20.1 h1:WH/1Zu6fRJn8ZpDNZ394y2Ek7tvTKMW0Rwbh5DRsqk0= +github.com/liushuangls/go-anthropic/v2 v2.20.1/go.mod h1:a550cJXPoTG2FL3DvfKG2zzD5O2vjgvo4tHtoGPzFLU= +github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4= +github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= +github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.21 h1:jJKAZiQH+2mIinzCJIaIG9Be1+0NR+5sz/lYEEjdM8w= -github.com/mattn/go-runewidth v0.0.21/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw= +github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= @@ -111,8 +121,8 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= +github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= @@ -149,46 +159,51 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yassinebenaid/godump v0.11.1 h1:SPujx/XaYqGDfmNh7JI3dOyCUVrG0bG2duhO3Eh2EhI= github.com/yassinebenaid/godump v0.11.1/go.mod h1:dc/0w8wmg6kVIvNGAzbKH1Oa54dXQx8SNKh4dPRyW44= -github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s= -github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= +github.com/zalando/go-keyring v0.2.8 h1:6sD/Ucpl7jNq10rM2pgqTs0sZ9V3qMrqfIIy5YPccHs= +github.com/zalando/go-keyring v0.2.8/go.mod h1:tsMo+VpRq5NGyKfxoBVjCuMrG47yj8cmakZDO5QGii0= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg= -go.opentelemetry.io/otel v1.42.0 h1:lSQGzTgVR3+sgJDAU/7/ZMjN9Z+vUip7leaqBKy4sho= -go.opentelemetry.io/otel v1.42.0/go.mod h1:lJNsdRMxCUIWuMlVJWzecSMuNjE7dOYyWlqOXWkdqCc= -go.opentelemetry.io/otel/metric v1.42.0 h1:2jXG+3oZLNXEPfNmnpxKDeZsFI5o4J+nz6xUlaFdF/4= -go.opentelemetry.io/otel/metric v1.42.0/go.mod h1:RlUN/7vTU7Ao/diDkEpQpnz3/92J9ko05BIwxYa2SSI= -go.opentelemetry.io/otel/sdk v1.42.0 h1:LyC8+jqk6UJwdrI/8VydAq/hvkFKNHZVIWuslJXYsDo= -go.opentelemetry.io/otel/sdk v1.42.0/go.mod h1:rGHCAxd9DAph0joO4W6OPwxjNTYWghRWmkHuGbayMts= -go.opentelemetry.io/otel/sdk/metric v1.42.0 h1:D/1QR46Clz6ajyZ3G8SgNlTJKBdGp84q9RKCAZ3YGuA= -go.opentelemetry.io/otel/sdk/metric v1.42.0/go.mod h1:Ua6AAlDKdZ7tdvaQKfSmnFTdHx37+J4ba8MwVCYM5hc= -go.opentelemetry.io/otel/trace v1.42.0 h1:OUCgIPt+mzOnaUTpOQcBiM/PLQ/Op7oq6g4LenLmOYY= -go.opentelemetry.io/otel/trace v1.42.0/go.mod h1:f3K9S+IFqnumBkKhRJMeaZeNk9epyhnCmQh/EysQCdc= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= +go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= +go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= +go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= +go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= +go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= +go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= +go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= +go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= +go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= +go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= -golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= -golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= -golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genai v1.49.0 h1:Se+QJaH2GYK1aaR1o5S38mlU2GD5FnVvP76nfkV7LH0= -google.golang.org/genai v1.49.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c h1:xgCzyF2LFIO/0X2UAoVRiXKU5Xg6VjToG4i2/ecSswk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260311181403-84a4fc48630c/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/api v0.279.0 h1:hsx2M2OaRcaKtVYK6vXEUnQvdjnend7ZYES+lYaot74= +google.golang.org/api v0.279.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ= +google.golang.org/genai v1.57.0 h1:qTyG2ynz5dQy2jF4CvZdLHHVslhR0heMue+zM1a4GNM= +google.golang.org/genai v1.57.0/go.mod h1:A3kkl0nyBjyFlNjgxIwKq70julKbIxpSxqKO5gw/gmk= +google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7 h1:XzmzkmB14QhVhgnawEVsOn6OFsnpyxNPRY9QV01dNB0= +google.golang.org/genproto v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:L43LFes82YgSonw6iTXTxXUX1OlULt4AQtkik4ULL/I= +google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7 h1:41r6JMbpzBMen0R/4TZeeAmGXSJC7DftGINUodzTkPI= +google.golang.org/genproto/googleapis/api v0.0.0-20260319201613-d00831a3d3e7/go.mod h1:EIQZ5bFCfRQDV4MhRle7+OgjNtZ6P1PiZBgAKuxXu/Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260511170946-3700d4141b60 h1:seT2EwLWM78plQ7wcDfuWBc/4FAEAXDDiaSol4ku4qo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260511170946-3700d4141b60/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= +google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/provider/anthropic/anthropic.go b/provider/anthropic/anthropic.go index 4e8ceb0..f8097c2 100644 --- a/provider/anthropic/anthropic.go +++ b/provider/anthropic/anthropic.go @@ -13,9 +13,10 @@ import ( "github.com/appleboy/CodeGPT/proxy" "github.com/appleboy/CodeGPT/version" - "github.com/appleboy/com/convert" "github.com/liushuangls/go-anthropic/v2" "github.com/sashabaranov/go-openai" + + "github.com/appleboy/com/convert" ) var _ core.Generative = (*Client)(nil) @@ -150,9 +151,10 @@ func (c *Client) GetSummaryPrefix(ctx context.Context, content string) (*core.Re var toolUse *anthropic.MessageContentToolUse - for _, c := range resp.Content { - if c.Type == anthropic.MessagesContentTypeToolUse { - toolUse = c.MessageContentToolUse + for i := range resp.Content { + block := &resp.Content[i] + if block.Type == anthropic.MessagesContentTypeToolUse { + toolUse = block.MessageContentToolUse } } @@ -189,7 +191,7 @@ func New(opts ...Option) (c *Client, err error) { cfg := newConfig(opts...) // Validate the config object, returning an error if it is invalid. - if err := cfg.valid(); err != nil { + if err = cfg.valid(); err != nil { return nil, err } diff --git a/provider/gemini/gemini.go b/provider/gemini/gemini.go index b8f2480..bbd2577 100644 --- a/provider/gemini/gemini.go +++ b/provider/gemini/gemini.go @@ -12,10 +12,11 @@ import ( "github.com/appleboy/CodeGPT/core/transport" "github.com/appleboy/CodeGPT/version" - "github.com/appleboy/com/convert" "github.com/sashabaranov/go-openai" "github.com/yassinebenaid/godump" "google.golang.org/genai" + + "github.com/appleboy/com/convert" ) type Client struct { @@ -215,7 +216,7 @@ func New(ctx context.Context, opts ...Option) (c *Client, err error) { cfg := newConfig(opts...) // Validate the config object, returning an error if it is invalid. - if err := cfg.valid(); err != nil { + if err = cfg.valid(); err != nil { return nil, err } diff --git a/provider/openai/func.go b/provider/openai/func.go index 3419f78..3973c3e 100644 --- a/provider/openai/func.go +++ b/provider/openai/func.go @@ -3,9 +3,10 @@ package openai import ( "encoding/json" - "github.com/appleboy/com/bytesconv" openai "github.com/sashabaranov/go-openai" "github.com/sashabaranov/go-openai/jsonschema" + + "github.com/appleboy/com/bytesconv" ) // SummaryPrefixFunc is a openai function definition. diff --git a/provider/openai/options_test.go b/provider/openai/options_test.go index 2818a5f..8bd088a 100644 --- a/provider/openai/options_test.go +++ b/provider/openai/options_test.go @@ -1,10 +1,12 @@ package openai import ( + "errors" "testing" - "github.com/appleboy/CodeGPT/core" openai "github.com/sashabaranov/go-openai" + + "github.com/appleboy/CodeGPT/core" ) func Test_config_valid(t *testing.T) { @@ -49,7 +51,7 @@ func Test_config_valid(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cfg := tt.cfg - if err := cfg.valid(); err != tt.wantErr { + if err := cfg.valid(); !errors.Is(err, tt.wantErr) { t.Errorf("config.valid() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/proxy/proxy.go b/proxy/proxy.go index baf60ca..5db0fad 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -103,13 +103,13 @@ func New(opts ...Option) (*http.Client, error) { if cfg.proxyURL != "" { proxyURL, err := url.Parse(cfg.proxyURL) if err != nil { - return nil, fmt.Errorf("invalid proxy URL: %s", err) + return nil, fmt.Errorf("invalid proxy URL: %w", err) } tr.Proxy = http.ProxyURL(proxyURL) } else if cfg.socksURL != "" { dialer, err := proxy.SOCKS5("tcp", cfg.socksURL, nil, proxy.Direct) if err != nil { - return nil, fmt.Errorf("can't connect to the SOCKS5 proxy: %s", err) + return nil, fmt.Errorf("can't connect to the SOCKS5 proxy: %w", err) } tr.DialContext = dialer.(proxy.ContextDialer).DialContext } diff --git a/util/api_key_helper_test.go b/util/api_key_helper_test.go index 21bdc90..b96fd34 100644 --- a/util/api_key_helper_test.go +++ b/util/api_key_helper_test.go @@ -289,8 +289,8 @@ func TestGetAPIKeyFromHelperWithCache_CacheExpiration(t *testing.T) { } // Update the file with a different value - if err := os.WriteFile(counterFile, []byte("value2"), 0o600); err != nil { - t.Fatalf("Failed to update counter file: %v", err) + if writeErr := os.WriteFile(counterFile, []byte("value2"), 0o600); writeErr != nil { + t.Fatalf("Failed to update counter file: %v", writeErr) } // Wait for cache to expire diff --git a/util/credstore.go b/util/credstore.go index b18259b..4f36478 100644 --- a/util/credstore.go +++ b/util/credstore.go @@ -1,6 +1,7 @@ package util import ( + "errors" "os" "path/filepath" @@ -35,7 +36,7 @@ func init() { // Returns ("", nil) if not found. func GetCredential(key string) (string, error) { val, err := credStore.Load(key) - if err == credstore.ErrNotFound { + if errors.Is(err, credstore.ErrNotFound) { return "", nil } return val, err diff --git a/util/credstore_test.go b/util/credstore_test.go index 910d4a3..fbcf111 100644 --- a/util/credstore_test.go +++ b/util/credstore_test.go @@ -1,6 +1,7 @@ package util import ( + "errors" "path/filepath" "testing" @@ -37,7 +38,7 @@ func TestCredStore_GetMissing(t *testing.T) { store := newTestCredStore(t) _, err := store.Load("nonexistent.key") - if err != credstore.ErrNotFound { + if !errors.Is(err, credstore.ErrNotFound) { t.Errorf("expected ErrNotFound, got %v", err) } } @@ -54,7 +55,7 @@ func TestCredStore_Delete(t *testing.T) { } _, err := store.Load("gemini.api_key") - if err != credstore.ErrNotFound { + if !errors.Is(err, credstore.ErrNotFound) { t.Errorf("expected ErrNotFound after delete, got %v", err) } }