Skip to content

Commit 6480c25

Browse files
authored
Merge branch 'main' into feat-file-upload
2 parents e1c39b6 + 7aee8a6 commit 6480c25

File tree

23 files changed

+505
-54
lines changed

23 files changed

+505
-54
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## v0.8.0
4+
5+
### Features
6+
- Add Support for GitHub Copilot
7+
- Fix inconsistent openapi generation
8+
39
## v0.7.1
410

511
### Fixes

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# AgentAPI
22

3-
Control [Claude Code](https://github.com/anthropics/claude-code), [AmazonQ](https://aws.amazon.com/developer/learning/q-developer-cli/), [Opencode](https://opencode.ai/), [Goose](https://github.com/block/goose), [Aider](https://github.com/Aider-AI/aider), [Gemini](https://github.com/google-gemini/gemini-cli), [Sourcegraph Amp](https://github.com/sourcegraph/amp-cli), [Codex](https://github.com/openai/codex), [Auggie](https://docs.augmentcode.com/cli/overview), and [Cursor CLI](https://cursor.com/en/cli) with an HTTP API.
3+
Control [Claude Code](https://github.com/anthropics/claude-code), [AmazonQ](https://aws.amazon.com/developer/learning/q-developer-cli/), [Opencode](https://opencode.ai/), [Goose](https://github.com/block/goose), [Aider](https://github.com/Aider-AI/aider), [Gemini](https://github.com/google-gemini/gemini-cli), [GitHub Copilot](https://github.com/github/copilot-cli), [Sourcegraph Amp](https://github.com/sourcegraph/amp-cli), [Codex](https://github.com/openai/codex), [Auggie](https://docs.augmentcode.com/cli/overview), and [Cursor CLI](https://cursor.com/en/cli) with an HTTP API.
44

55
![agentapi-chat](https://github.com/user-attachments/assets/57032c9f-4146-4b66-b219-09e38ab7690d)
66

@@ -65,7 +65,7 @@ agentapi server -- goose
6565
```
6666

6767
> [!NOTE]
68-
> When using Codex, Opencode, Gemini, Amp or CursorCLI, always specify the agent type explicitly (eg: `agentapi server --type=codex -- codex`), or message formatting may break.
68+
> When using Codex, Opencode, Copilot, Gemini, Amp or CursorCLI, always specify the agent type explicitly (eg: `agentapi server --type=codex -- codex`), or message formatting may break.
6969
7070
An OpenAPI schema is available in [openapi.json](openapi.json).
7171

chat/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,5 @@
4949
"start": "next start",
5050
"storybook": "storybook dev -p 6006"
5151
},
52-
"version": "0.7.1"
52+
"version": "0.8.0"
5353
}

cmd/server/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const (
2828
AgentTypeAider AgentType = msgfmt.AgentTypeAider
2929
AgentTypeCodex AgentType = msgfmt.AgentTypeCodex
3030
AgentTypeGemini AgentType = msgfmt.AgentTypeGemini
31+
AgentTypeCopilot AgentType = msgfmt.AgentTypeCopilot
3132
AgentTypeAmp AgentType = msgfmt.AgentTypeAmp
3233
AgentTypeCursor AgentType = msgfmt.AgentTypeCursor
3334
AgentTypeAuggie AgentType = msgfmt.AgentTypeAuggie
@@ -43,6 +44,7 @@ var agentTypeAliases = map[string]AgentType{
4344
"aider": AgentTypeAider,
4445
"codex": AgentTypeCodex,
4546
"gemini": AgentTypeGemini,
47+
"copilot": AgentTypeCopilot,
4648
"amp": AgentTypeAmp,
4749
"auggie": AgentTypeAuggie,
4850
"cursor": AgentTypeCursor,

cmd/server/server_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ func TestParseAgentType(t *testing.T) {
4747
agentTypeVar: "",
4848
want: AgentTypeGemini,
4949
},
50+
{
51+
firstArg: "copilot",
52+
agentTypeVar: "",
53+
want: AgentTypeCopilot,
54+
},
5055
{
5156
firstArg: "cursor-agent",
5257
agentTypeVar: "",
@@ -102,6 +107,11 @@ func TestParseAgentType(t *testing.T) {
102107
agentTypeVar: "goose",
103108
want: AgentTypeGoose,
104109
},
110+
{
111+
firstArg: "claude",
112+
agentTypeVar: "copilot",
113+
want: AgentTypeCopilot,
114+
},
105115
{
106116
firstArg: "goose",
107117
agentTypeVar: "claude",

internal/version/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
package version
44

5-
var Version = "0.7.1"
5+
var Version = "0.8.0"

lib/httpapi/server.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"os"
1414
"path/filepath"
1515
"slices"
16+
"sort"
1617
"strings"
1718
"sync"
1819
"time"
@@ -46,6 +47,27 @@ type Server struct {
4647
chatBasePath string
4748
}
4849

50+
func (s *Server) NormalizeSchema(schema any) any {
51+
switch val := (schema).(type) {
52+
case *any:
53+
s.NormalizeSchema(*val)
54+
case []any:
55+
for i := range val {
56+
s.NormalizeSchema(&val[i])
57+
}
58+
sort.SliceStable(val, func(i, j int) bool {
59+
return fmt.Sprintf("%v", val[i]) < fmt.Sprintf("%v", val[j])
60+
})
61+
case map[string]any:
62+
for k := range val {
63+
valUnderKey := val[k]
64+
s.NormalizeSchema(&valUnderKey)
65+
val[k] = valUnderKey
66+
}
67+
}
68+
return schema
69+
}
70+
4971
func (s *Server) GetOpenAPI() string {
5072
jsonBytes, err := s.api.OpenAPI().MarshalJSON()
5173
if err != nil {
@@ -56,7 +78,11 @@ func (s *Server) GetOpenAPI() string {
5678
if err := json.Unmarshal(jsonBytes, &jsonObj); err != nil {
5779
return ""
5880
}
59-
prettyJSON, err := json.MarshalIndent(jsonObj, "", " ")
81+
82+
// Normalize
83+
normalized := s.NormalizeSchema(jsonObj)
84+
85+
prettyJSON, err := json.MarshalIndent(normalized, "", " ")
6086
if err != nil {
6187
return ""
6288
}

lib/httpapi/server_test.go

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ package httpapi_test
33
import (
44
"context"
55
"encoding/json"
6-
"fmt"
76
"io"
87
"log/slog"
98
"net/http"
109
"net/http/httptest"
1110
"os"
12-
"sort"
1311
"testing"
1412

1513
"github.com/coder/agentapi/lib/httpapi"
@@ -19,28 +17,6 @@ import (
1917
"github.com/stretchr/testify/require"
2018
)
2119

22-
func normalizeSchema(t *testing.T, schema any) any {
23-
t.Helper()
24-
switch val := (schema).(type) {
25-
case *any:
26-
normalizeSchema(t, *val)
27-
case []any:
28-
for i := range val {
29-
normalizeSchema(t, &val[i])
30-
}
31-
sort.SliceStable(val, func(i, j int) bool {
32-
return fmt.Sprintf("%v", val[i]) < fmt.Sprintf("%v", val[j])
33-
})
34-
case map[string]any:
35-
for k := range val {
36-
valUnderKey := val[k]
37-
normalizeSchema(t, &valUnderKey)
38-
val[k] = valUnderKey
39-
}
40-
}
41-
return schema
42-
}
43-
4420
// Ensure the OpenAPI schema on disk is up to date.
4521
// To update the schema, run `go run main.go server --print-openapi dummy > openapi.json`.
4622
func TestOpenAPISchema(t *testing.T) {
@@ -79,9 +55,6 @@ func TestOpenAPISchema(t *testing.T) {
7955
t.Fatalf("failed to unmarshal disk schema: %s", err)
8056
}
8157

82-
normalizeSchema(t, &currentSchema)
83-
normalizeSchema(t, &diskSchema)
84-
8558
require.Equal(t, currentSchema, diskSchema)
8659
}
8760

lib/msgfmt/msgfmt.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func RemoveUserInput(msgRaw string, userInputRaw string, agentType AgentType) st
188188
lastUserInputLineIdx := msgRuneLineLocations[userInputEndIdx]
189189

190190
// Skip Gemini/Cursor trailing input box line
191-
if agentType == AgentTypeGemini {
191+
if agentType == AgentTypeGemini || agentType == AgentTypeCopilot {
192192
if idx, found := skipTrailingInputBoxLine(msgLines, lastUserInputLineIdx, "╯", "╰"); found {
193193
lastUserInputLineIdx = idx
194194
}
@@ -232,17 +232,18 @@ func trimEmptyLines(message string) string {
232232
type AgentType string
233233

234234
const (
235-
AgentTypeClaude AgentType = "claude"
236-
AgentTypeGoose AgentType = "goose"
237-
AgentTypeAider AgentType = "aider"
238-
AgentTypeCodex AgentType = "codex"
239-
AgentTypeGemini AgentType = "gemini"
240-
AgentTypeAmp AgentType = "amp"
241-
AgentTypeCursor AgentType = "cursor"
242-
AgentTypeAuggie AgentType = "auggie"
243-
AgentTypeAmazonQ AgentType = "amazonq"
244-
AgentTypeOpencode AgentType = "opencode"
245-
AgentTypeCustom AgentType = "custom"
235+
AgentTypeClaude AgentType = "claude"
236+
AgentTypeGoose AgentType = "goose"
237+
AgentTypeAider AgentType = "aider"
238+
AgentTypeCodex AgentType = "codex"
239+
AgentTypeGemini AgentType = "gemini"
240+
AgentTypeCopilot AgentType = "copilot"
241+
AgentTypeAmp AgentType = "amp"
242+
AgentTypeCursor AgentType = "cursor"
243+
AgentTypeAuggie AgentType = "auggie"
244+
AgentTypeAmazonQ AgentType = "amazonq"
245+
AgentTypeOpencode AgentType = "opencode"
246+
AgentTypeCustom AgentType = "custom"
246247
)
247248

248249
func formatGenericMessage(message string, userInput string, agentType AgentType) string {
@@ -278,6 +279,8 @@ func FormatAgentMessage(agentType AgentType, message string, userInput string) s
278279
return formatCodexMessage(message, userInput)
279280
case AgentTypeGemini:
280281
return formatGenericMessage(message, userInput, agentType)
282+
case AgentTypeCopilot:
283+
return formatGenericMessage(message, userInput, agentType)
281284
case AgentTypeAmp:
282285
return formatGenericMessage(message, userInput, agentType)
283286
case AgentTypeCursor:

lib/msgfmt/msgfmt_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func TestTrimEmptyLines(t *testing.T) {
218218

219219
func TestFormatAgentMessage(t *testing.T) {
220220
dir := "testdata/format"
221-
agentTypes := []AgentType{AgentTypeClaude, AgentTypeGoose, AgentTypeAider, AgentTypeGemini, AgentTypeAmp, AgentTypeCodex, AgentTypeCursor, AgentTypeAuggie, AgentTypeAmazonQ, AgentTypeOpencode, AgentTypeCustom}
221+
agentTypes := []AgentType{AgentTypeClaude, AgentTypeGoose, AgentTypeAider, AgentTypeGemini, AgentTypeCopilot, AgentTypeAmp, AgentTypeCodex, AgentTypeCursor, AgentTypeAuggie, AgentTypeAmazonQ, AgentTypeOpencode, AgentTypeCustom}
222222
for _, agentType := range agentTypes {
223223
t.Run(string(agentType), func(t *testing.T) {
224224
cases, err := testdataDir.ReadDir(path.Join(dir, string(agentType)))

0 commit comments

Comments
 (0)