Skip to content

feat: add golangci && resolve current lint errors #104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all 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
27 changes: 27 additions & 0 deletions .github/workflows/golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: golangci-lint
on:
push:
branches:
- main
pull_request:

permissions:
contents: read

jobs:
golangci:
strategy:
matrix:
go: [stable]
os: [ubuntu-latest, macos-latest, windows-latest]
name: lint
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: v2.0
5 changes: 2 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import (
"time"

tea "github.com/charmbracelet/bubbletea"
zone "github.com/lrstanley/bubblezone"
"github.com/opencode-ai/opencode/internal/app"
"github.com/opencode-ai/opencode/internal/config"
"github.com/opencode-ai/opencode/internal/db"
@@ -16,7 +17,6 @@ import (
"github.com/opencode-ai/opencode/internal/pubsub"
"github.com/opencode-ai/opencode/internal/tui"
"github.com/opencode-ai/opencode/internal/version"
zone "github.com/lrstanley/bubblezone"
"github.com/spf13/cobra"
)

@@ -29,8 +29,7 @@ to assist developers in writing, debugging, and understanding code directly from
RunE: func(cmd *cobra.Command, args []string) error {
// If the help flag is set, show the help message
if cmd.Flag("help").Changed {
cmd.Help()
return nil
return cmd.Help()
}
if cmd.Flag("version").Changed {
fmt.Println(version.Version)
14 changes: 8 additions & 6 deletions internal/app/lsp.go
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ func (app *App) initLSPClients(ctx context.Context) {
func (app *App) createAndStartLSPClient(ctx context.Context, name string, command string, args ...string) {
// Create a specific context for initialization with a timeout
logging.Info("Creating LSP client", "name", name, "command", command, "args", args)

// Create the LSP client
lspClient, err := lsp.NewClient(ctx, command, args...)
if err != nil {
@@ -36,13 +36,13 @@ func (app *App) createAndStartLSPClient(ctx context.Context, name string, comman
// Create a longer timeout for initialization (some servers take time to start)
initCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()

// Initialize with the initialization context
_, err = lspClient.InitializeLSPClient(initCtx, config.WorkingDirectory())
if err != nil {
logging.Error("Initialize failed", "name", name, "error", err)
// Clean up the client to prevent resource leaks
lspClient.Close()
lspClient.Close() //nolint:errcheck
return
}

@@ -57,13 +57,15 @@ func (app *App) createAndStartLSPClient(ctx context.Context, name string, comman
}

logging.Info("LSP client initialized", "name", name)

// Create a child context that can be canceled when the app is shutting down
watchCtx, cancelFunc := context.WithCancel(ctx)

// Create a context with the server name for better identification
//nolint:staticcheck
//lint:ignore SA1029 will be resolved in the future
watchCtx = context.WithValue(watchCtx, "serverName", name)

// Create the workspace watcher
workspaceWatcher := watcher.NewWorkspaceWatcher(lspClient)

9 changes: 6 additions & 3 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -127,7 +127,9 @@ func Load(workingDir string, debug bool) (*Config, error) {
}

// Load and merge local config
mergeLocalConfig(workingDir)
if err := mergeLocalConfig(workingDir); err != nil {
return cfg, err
}

// Apply configuration to the struct
if err := viper.Unmarshal(cfg); err != nil {
@@ -315,16 +317,17 @@ func readConfig(err error) error {
}

// mergeLocalConfig loads and merges configuration from the local directory.
func mergeLocalConfig(workingDir string) {
func mergeLocalConfig(workingDir string) error {
local := viper.New()
local.SetConfigName(fmt.Sprintf(".%s", appName))
local.SetConfigType("json")
local.AddConfigPath(workingDir)

// Merge local config if it exists
if err := local.ReadInConfig(); err == nil {
viper.MergeConfigMap(local.AllSettings())
return viper.MergeConfigMap(local.AllSettings())
}
return nil
}

// applyDefaultValues sets default values for configuration fields that need processing.
3 changes: 1 addition & 2 deletions internal/config/init.go
Original file line number Diff line number Diff line change
@@ -54,8 +54,7 @@ func MarkProjectInitialized() error {
if err != nil {
return fmt.Errorf("failed to create init flag file: %w", err)
}
defer file.Close()
defer file.Close() //nolint:errcheck

return nil
}

2 changes: 1 addition & 1 deletion internal/db/connect.go
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ func Connect() (*sql.DB, error) {

// Verify connection
if err = db.Ping(); err != nil {
db.Close()
db.Close() //nolint:errcheck
return nil, fmt.Errorf("failed to connect to database: %w", err)
}

2 changes: 1 addition & 1 deletion internal/history/file.go
Original file line number Diff line number Diff line change
@@ -121,7 +121,7 @@ func (s *service) createWithVersion(ctx context.Context, sessionID, path, conten
})
if txErr != nil {
// Rollback the transaction
tx.Rollback()
tx.Rollback() //nolint:errcheck

// Check if this is a uniqueness constraint violation
if strings.Contains(txErr.Error(), "UNIQUE constraint failed") {
2 changes: 1 addition & 1 deletion internal/llm/agent/agent.go
Original file line number Diff line number Diff line change
@@ -222,7 +222,7 @@ func (a *agent) processGeneration(ctx context.Context, sessionID, content string
if err != nil {
if errors.Is(err, context.Canceled) {
agentMessage.AddFinish(message.FinishReasonCanceled)
a.messages.Update(context.Background(), agentMessage)
a.messages.Update(context.Background(), agentMessage) //nolint:errcheck
return a.err(ErrRequestCancelled)
}
return a.err(fmt.Errorf("failed to process events: %w", err))
4 changes: 2 additions & 2 deletions internal/llm/agent/mcp-tools.go
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ func (b *mcpTool) Info() tools.ToolInfo {
}

func runTool(ctx context.Context, c MCPClient, toolName string, input string) (tools.ToolResponse, error) {
defer c.Close()
defer c.Close() //nolint:errcheck
initRequest := mcp.InitializeRequest{}
initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
initRequest.Params.ClientInfo = mcp.Implementation{
@@ -158,7 +158,7 @@ func getTools(ctx context.Context, name string, m config.MCPServer, permissions
for _, t := range tools.Tools {
stdioTools = append(stdioTools, NewMcpTool(name, t, permissions, m))
}
defer c.Close()
defer c.Close() //nolint:errcheck
return stdioTools
}

2 changes: 1 addition & 1 deletion internal/llm/prompt/prompt.go
Original file line number Diff line number Diff line change
@@ -71,7 +71,7 @@ func processContextPaths(workDir string, paths []string) string {
defer wg.Done()

if strings.HasSuffix(p, "/") {
filepath.WalkDir(filepath.Join(workDir, p), func(path string, d os.DirEntry, err error) error {
filepath.WalkDir(filepath.Join(workDir, p), func(path string, d os.DirEntry, err error) error { //nolint:errcheck
if err != nil {
return err
}
16 changes: 3 additions & 13 deletions internal/llm/provider/anthropic.go
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ import (
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/bedrock"
"github.com/anthropics/anthropic-sdk-go/option"
"github.com/opencode-ai/opencode/internal/config"
"github.com/opencode-ai/opencode/internal/llm/tools"
"github.com/opencode-ai/opencode/internal/logging"
"github.com/opencode-ai/opencode/internal/message"
@@ -194,11 +193,6 @@ func (a *anthropicClient) preparedMessages(messages []anthropic.MessageParam, to

func (a *anthropicClient) send(ctx context.Context, messages []message.Message, tools []tools.BaseTool) (resposne *ProviderResponse, err error) {
preparedMessages := a.preparedMessages(a.convertMessages(messages), a.convertTools(tools))
cfg := config.Get()
if cfg.Debug {
// jsonData, _ := json.Marshal(preparedMessages)
// logging.Debug("Prepared messages", "messages", string(jsonData))
}
attempts := 0
for {
attempts++
@@ -241,11 +235,6 @@ func (a *anthropicClient) send(ctx context.Context, messages []message.Message,

func (a *anthropicClient) stream(ctx context.Context, messages []message.Message, tools []tools.BaseTool) <-chan ProviderEvent {
preparedMessages := a.preparedMessages(a.convertMessages(messages), a.convertTools(tools))
cfg := config.Get()
if cfg.Debug {
// jsonData, _ := json.Marshal(preparedMessages)
// logging.Debug("Prepared messages", "messages", string(jsonData))
}
attempts := 0
eventChan := make(chan ProviderEvent)
go func() {
@@ -268,9 +257,10 @@ func (a *anthropicClient) stream(ctx context.Context, messages []message.Message

switch event := event.AsAny().(type) {
case anthropic.ContentBlockStartEvent:
if event.ContentBlock.Type == "text" {
switch event.ContentBlock.Type {
case "text":
eventChan <- ProviderEvent{Type: EventContentStart}
} else if event.ContentBlock.Type == "tool_use" {
case "tool_use":
currentToolCallID = event.ContentBlock.ID
eventChan <- ProviderEvent{
Type: EventToolUseStart,
8 changes: 4 additions & 4 deletions internal/llm/provider/bedrock.go
Original file line number Diff line number Diff line change
@@ -55,7 +55,7 @@ func newBedrockClient(opts providerClientOptions) BedrockClient {
if strings.Contains(string(opts.model.APIModel), "anthropic") {
// Create Anthropic client with Bedrock configuration
anthropicOpts := opts
anthropicOpts.anthropicOptions = append(anthropicOpts.anthropicOptions,
anthropicOpts.anthropicOptions = append(anthropicOpts.anthropicOptions,
WithAnthropicBedrock(true),
WithAnthropicDisableCache(),
)
@@ -84,7 +84,7 @@ func (b *bedrockClient) send(ctx context.Context, messages []message.Message, to

func (b *bedrockClient) stream(ctx context.Context, messages []message.Message, tools []tools.BaseTool) <-chan ProviderEvent {
eventChan := make(chan ProviderEvent)

if b.childProvider == nil {
go func() {
eventChan <- ProviderEvent{
@@ -95,6 +95,6 @@ func (b *bedrockClient) stream(ctx context.Context, messages []message.Message,
}()
return eventChan
}

return b.childProvider.stream(ctx, messages, tools)
}
}
9 changes: 5 additions & 4 deletions internal/llm/provider/gemini.go
Original file line number Diff line number Diff line change
@@ -141,10 +141,10 @@ func (g *geminiClient) convertTools(tools []tools.BaseTool) []*genai.Tool {
}

func (g *geminiClient) finishReason(reason genai.FinishReason) message.FinishReason {
switch {
case reason == genai.FinishReasonStop:
switch reason {
case genai.FinishReasonStop:
return message.FinishReasonEndTurn
case reason == genai.FinishReasonMaxTokens:
case genai.FinishReasonMaxTokens:
return message.FinishReasonMaxTokens
default:
return message.FinishReasonUnknown
@@ -392,7 +392,7 @@ func (g *geminiClient) shouldRetry(attempts int, err error) (bool, int64, error)
}

errMsg := err.Error()
isRateLimit := false
var isRateLimit bool

// Check for common rate limit error messages
if contains(errMsg, "rate limit", "quota exceeded", "too many requests") {
@@ -411,6 +411,7 @@ func (g *geminiClient) shouldRetry(attempts int, err error) (bool, int64, error)
return true, int64(retryMs), nil
}

//lint:ignore U1000 will be used in the future
func (g *geminiClient) toolCalls(resp *genai.GenerateContentResponse) []message.ToolCall {
var toolCalls []message.ToolCall

2 changes: 1 addition & 1 deletion internal/llm/provider/openai.go
Original file line number Diff line number Diff line change
@@ -148,7 +148,7 @@ func (o *openaiClient) preparedParams(messages []openai.ChatCompletionMessagePar
Tools: tools,
}

if o.providerOptions.model.CanReason == true {
if o.providerOptions.model.CanReason {
params.MaxCompletionTokens = openai.Int(o.providerOptions.maxTokens)
switch o.options.reasoningEffort {
case "low":
2 changes: 1 addition & 1 deletion internal/llm/tools/fetch.go
Original file line number Diff line number Diff line change
@@ -158,7 +158,7 @@ func (t *fetchTool) Run(ctx context.Context, call ToolCall) (ToolResponse, error
if err != nil {
return ToolResponse{}, fmt.Errorf("failed to fetch URL: %w", err)
}
defer resp.Body.Close()
defer resp.Body.Close() //nolint:errcheck

if resp.StatusCode != http.StatusOK {
return NewTextErrorResponse(fmt.Sprintf("Request failed with status code: %d", resp.StatusCode)), nil
2 changes: 1 addition & 1 deletion internal/llm/tools/grep.go
Original file line number Diff line number Diff line change
@@ -328,7 +328,7 @@ func fileContainsPattern(filePath string, pattern *regexp.Regexp) (bool, int, st
if err != nil {
return false, 0, "", err
}
defer file.Close()
defer file.Close() //nolint:errcheck

scanner := bufio.NewScanner(file)
lineNum := 0
Loading