Skip to content

Commit 8a08d9e

Browse files
authored
fix: refactor agent type parsing and run lint in CI (#36)
1 parent f486499 commit 8a08d9e

File tree

7 files changed

+84
-52
lines changed

7 files changed

+84
-52
lines changed

.github/workflows/go-test.yml

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,34 @@ name: Go Tests
22

33
on:
44
push:
5-
branches: [ main ]
5+
branches: [main]
66
pull_request:
7-
branches: [ main ]
87

98
jobs:
109
test:
1110
runs-on: ubuntu-latest
1211
steps:
13-
- uses: actions/checkout@v4
12+
- uses: actions/checkout@v4
1413

15-
- name: Set up Go
16-
uses: actions/setup-go@v5
17-
with:
18-
go-version: 'stable'
14+
- name: Set up Go
15+
uses: actions/setup-go@v5
16+
with:
17+
go-version: "stable"
1918

20-
- name: Test
21-
run: go test -count=1 -v ./...
19+
- name: Test
20+
run: go test -count=1 -v ./...
21+
22+
lint:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Set up Go
28+
uses: actions/setup-go@v5
29+
with:
30+
go-version: "stable"
31+
32+
- name: golangci-lint
33+
uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0
34+
with:
35+
version: v2.1

.golangci.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: "2"
2+
linters:
3+
enable:
4+
- exhaustive
5+
settings:
6+
exhaustive:
7+
check:
8+
- "switch"
9+
- "map"
10+
staticcheck:
11+
checks:
12+
- "-QF1001" # disable "could apply De Morgan's law"

cmd/attach/attach.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ func ReadScreenOverHTTP(ctx context.Context, url string, ch chan<- httpapi.Scree
8080
if err != nil {
8181
return xerrors.Errorf("failed to do request: %w", err)
8282
}
83-
defer res.Body.Close()
83+
defer func() {
84+
_ = res.Body.Close()
85+
}()
8486

8587
for ev, err := range sse.Read(res.Body, &sse.ReadConfig{
8688
// 256KB: screen can be big. The default terminal size is 80x1000,
@@ -115,7 +117,9 @@ func WriteRawInputOverHTTP(ctx context.Context, url string, msg string) error {
115117
if err != nil {
116118
return xerrors.Errorf("failed to do request: %w", err)
117119
}
118-
defer res.Body.Close()
120+
defer func() {
121+
_ = res.Body.Close()
122+
}()
119123
if res.StatusCode != http.StatusOK {
120124
return xerrors.Errorf("failed to write raw input: %w", errors.New(res.Status))
121125
}
@@ -132,7 +136,9 @@ func runAttach(remoteUrl string) error {
132136
if err != nil {
133137
return xerrors.Errorf("failed to make raw: %w", err)
134138
}
135-
defer term.Restore(stdin, oldState)
139+
defer func() {
140+
_ = term.Restore(stdin, oldState)
141+
}()
136142

137143
stdinWriter := &ChannelWriter{
138144
ch: make(chan []byte, 4096),

cmd/server/server.go

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"log/slog"
88
"net/http"
99
"os"
10+
"sort"
1011
"strings"
1112

1213
"github.com/spf13/cobra"
@@ -38,45 +39,31 @@ const (
3839
AgentTypeCustom AgentType = msgfmt.AgentTypeCustom
3940
)
4041

42+
// exhaustiveness of this map is checked by the exhaustive linter
43+
var agentTypeMap = map[AgentType]bool{
44+
AgentTypeClaude: true,
45+
AgentTypeGoose: true,
46+
AgentTypeAider: true,
47+
AgentTypeCodex: true,
48+
AgentTypeGemini: true,
49+
AgentTypeCustom: true,
50+
}
51+
4152
func parseAgentType(firstArg string, agentTypeVar string) (AgentType, error) {
42-
var agentType AgentType
43-
switch agentTypeVar {
44-
case string(AgentTypeClaude):
45-
agentType = AgentTypeClaude
46-
case string(AgentTypeGoose):
47-
agentType = AgentTypeGoose
48-
case string(AgentTypeAider):
49-
agentType = AgentTypeAider
50-
case string(AgentTypeGemini):
51-
agentType = AgentTypeGemini
52-
case string(AgentTypeCustom):
53-
agentType = AgentTypeCustom
54-
case string(AgentTypeCodex):
55-
agentType = AgentTypeCodex
56-
case "":
57-
// do nothing
58-
default:
59-
return "", fmt.Errorf("invalid agent type: %s", agentTypeVar)
53+
// if the agent type is provided, use it
54+
castedAgentType := AgentType(agentTypeVar)
55+
if _, ok := agentTypeMap[castedAgentType]; ok {
56+
return castedAgentType, nil
6057
}
61-
if agentType != "" {
62-
return agentType, nil
58+
if agentTypeVar != "" {
59+
return AgentTypeCustom, fmt.Errorf("invalid agent type: %s", agentTypeVar)
6360
}
64-
65-
switch firstArg {
66-
case string(AgentTypeClaude):
67-
agentType = AgentTypeClaude
68-
case string(AgentTypeGoose):
69-
agentType = AgentTypeGoose
70-
case string(AgentTypeAider):
71-
agentType = AgentTypeAider
72-
case string(AgentTypeCodex):
73-
agentType = AgentTypeCodex
74-
case string(AgentTypeGemini):
75-
agentType = AgentTypeGemini
76-
default:
77-
agentType = AgentTypeCustom
61+
// if the agent type is not provided, guess it from the first argument
62+
castedFirstArg := AgentType(firstArg)
63+
if _, ok := agentTypeMap[castedFirstArg]; ok {
64+
return castedFirstArg, nil
7865
}
79-
return agentType, nil
66+
return AgentTypeCustom, nil
8067
}
8168

8269
func runServer(ctx context.Context, logger *slog.Logger, argsToPass []string) error {
@@ -139,10 +126,19 @@ func runServer(ctx context.Context, logger *slog.Logger, argsToPass []string) er
139126
return nil
140127
}
141128

129+
var agentNames = (func() []string {
130+
names := make([]string, 0, len(agentTypeMap))
131+
for agentType := range agentTypeMap {
132+
names = append(names, string(agentType))
133+
}
134+
sort.Strings(names)
135+
return names
136+
})()
137+
142138
var ServerCmd = &cobra.Command{
143139
Use: "server [agent]",
144140
Short: "Run the server",
145-
Long: `Run the server with the specified agent (claude, goose, aider, gemini, codex)`,
141+
Long: fmt.Sprintf("Run the server with the specified agent (one of: %s)", strings.Join(agentNames, ", ")),
146142
Args: cobra.MinimumNArgs(1),
147143
Run: func(cmd *cobra.Command, args []string) {
148144
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
@@ -155,7 +151,7 @@ var ServerCmd = &cobra.Command{
155151
}
156152

157153
func init() {
158-
ServerCmd.Flags().StringVarP(&agentTypeVar, "type", "t", "", "Override the agent type (one of: claude, goose, aider, custom)")
154+
ServerCmd.Flags().StringVarP(&agentTypeVar, "type", "t", "", fmt.Sprintf("Override the agent type (one of: %s, custom)", strings.Join(agentNames, ", ")))
159155
ServerCmd.Flags().IntVarP(&port, "port", "p", 3284, "Port to run the server on")
160156
ServerCmd.Flags().BoolVarP(&printOpenAPI, "print-openapi", "P", false, "Print the OpenAPI schema to stdout and exit")
161157
ServerCmd.Flags().StringVarP(&chatBasePath, "chat-base-path", "c", "/chat", "Base path for assets and routes used in the static files of the chat interface")

lib/httpapi/embed.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ func FileServerWithIndexFallback(chatBasePath string) http.Handler {
8787
// Try to serve the file directly
8888
f, err := chatFS.Open(trimmedPath)
8989
if err == nil {
90-
defer f.Close()
90+
defer func() {
91+
_ = f.Close()
92+
}()
9193
fileServer.ServeHTTP(w, r)
9294
return
9395
}

lib/httpapi/server_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ func TestOpenAPISchema(t *testing.T) {
5555
if err != nil {
5656
t.Fatalf("failed to open disk schema: %s", err)
5757
}
58-
defer diskSchemaFile.Close()
58+
defer func() {
59+
_ = diskSchemaFile.Close()
60+
}()
5961

6062
diskSchemaBytes, err := io.ReadAll(diskSchemaFile)
6163
if err != nil {

lib/screentracker/conversation_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func TestMessages(t *testing.T) {
186186
assert.Equal(t, []st.ConversationMessage{
187187
agentMsg(0, "1"),
188188
}, msgs)
189-
nowWrapper.Time = nowWrapper.Time.Add(1 * time.Second)
189+
nowWrapper.Time = nowWrapper.Add(1 * time.Second)
190190
c.AddSnapshot("1")
191191
assert.Equal(t, msgs, c.Messages())
192192
})

0 commit comments

Comments
 (0)