Skip to content

Commit b21a3f7

Browse files
authored
Merge branch 'main' into feat-clickable-links
2 parents a44f3dd + b62ca12 commit b21a3f7

File tree

26 files changed

+663
-54
lines changed

26 files changed

+663
-54
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: PR Preview Release Binaries
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
build:
8+
name: Build Release Binaries
9+
runs-on: depot-ubuntu-22.04-4
10+
permissions:
11+
contents: write
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v5
18+
with:
19+
go-version: 'stable'
20+
21+
- name: Set up Bun
22+
uses: oven-sh/setup-bun@v2
23+
24+
- name: Install Chat Dependencies
25+
run: cd chat && bun install
26+
27+
- name: Run make gen and check for unstaged changes
28+
run: |
29+
make gen
30+
./check_unstaged.sh
31+
32+
- name: Build
33+
env:
34+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35+
shell: bash
36+
run: |
37+
build_variants=(
38+
"linux amd64 agentapi-linux-amd64"
39+
"linux arm64 agentapi-linux-arm64"
40+
"darwin amd64 agentapi-darwin-amd64"
41+
"darwin arm64 agentapi-darwin-arm64"
42+
"windows amd64 agentapi-windows-amd64.exe"
43+
)
44+
45+
for variant in "${build_variants[@]}"; do
46+
read -r goos goarch artifact_name <<< "$variant"
47+
48+
echo "Building for GOOS=$goos GOARCH=$goarch..."
49+
CGO_ENABLED=0 GOOS=$goos GOARCH=$goarch BINPATH="out/$artifact_name" make build
50+
done
51+
52+
- name: Upload Build Artifact
53+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
54+
with:
55+
name: agentapi-preview-build
56+
path: ${{ github.workspace }}/out
57+
retention-days: 7
58+
59+
- name: Save PR number
60+
run: |
61+
mkdir -p ./pr
62+
echo ${{ github.event.pull_request.number }} > ./pr/number
63+
64+
- name: Upload PR number
65+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
66+
with:
67+
name: pr-number
68+
path: pr/
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: PR Preview Cleanup
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
7+
permissions:
8+
contents: write
9+
10+
jobs:
11+
cleanup:
12+
name: Delete PR Release
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Delete PR Release
17+
env:
18+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19+
RELEASE_TAG: 'agentapi_${{ github.event.pull_request.number }}'
20+
run: |
21+
gh release delete "$RELEASE_TAG" --cleanup-tag --yes --repo ${{ github.repository }} || true
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: PR Preview Release
2+
3+
on:
4+
workflow_run:
5+
workflows: ["PR Preview Build"]
6+
types:
7+
- completed
8+
9+
permissions:
10+
contents: write
11+
pull-requests: write
12+
13+
jobs:
14+
release:
15+
name: Create Release
16+
runs-on: ubuntu-latest
17+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
18+
19+
steps:
20+
- name: Download PR number
21+
uses: actions/download-artifact@v4
22+
with:
23+
name: pr-number
24+
github-token: ${{ secrets.GITHUB_TOKEN }}
25+
run-id: ${{ github.event.workflow_run.id }}
26+
27+
- name: Read PR number
28+
id: pr
29+
run: echo "number=$(cat number)" >> $GITHUB_OUTPUT
30+
31+
- name: Download Build Artifacts
32+
uses: actions/download-artifact@v4
33+
with:
34+
name: agentapi-build-${{ steps.pr.outputs.number }}
35+
path: ./out
36+
github-token: ${{ secrets.GITHUB_TOKEN }}
37+
run-id: ${{ github.event.workflow_run.id }}
38+
39+
40+
- name: Create or Update PR Release
41+
env:
42+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
43+
RELEASE_TAG: 'agentapi_${{ github.event.pull_request.number }}'
44+
45+
run: |
46+
# Check if release exists
47+
if gh release view "$RELEASE_TAG" &>/dev/null; then
48+
echo "Updating release $RELEASE_TAG"
49+
gh release upload "$RELEASE_TAG" "$GITHUB_WORKSPACE"/out/* --clobber
50+
else
51+
echo "Creating release $RELEASE_TAG"
52+
gh release create "$RELEASE_TAG" "$GITHUB_WORKSPACE"/out/* \
53+
--title "$RELEASE_TAG" \
54+
--notes "Preview release for PR #${PR_NUMBER}" \
55+
--draft --latest=false
56+
fi
57+
58+
- name: Comment on PR
59+
uses: actions/github-script@v7
60+
with:
61+
script: |
62+
const prNumber = ${{ steps.pr.outputs.number }};
63+
const releaseTag = `agentapi_${prNumber}`;
64+
github.rest.issues.createComment({
65+
issue_number: prNumber,
66+
owner: context.repo.owner,
67+
repo: context.repo.repo,
68+
body: `✅ Preview binaries are ready!\n\nTo test with modules: \`\`\`agentapi: ${prNumber}\`\`\` or download from: ${repoUrl}/releases/tag/${releaseTag}`
69+
});

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
@@ -44,5 +44,5 @@
4444
"start": "next start",
4545
"storybook": "storybook dev -p 6006"
4646
},
47-
"version": "0.7.1"
47+
"version": "0.8.0"
4848
}

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
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"net/url"
1010
"slices"
11+
"sort"
1112
"strings"
1213
"sync"
1314
"time"
@@ -41,6 +42,27 @@ type Server struct {
4142
chatBasePath string
4243
}
4344

45+
func (s *Server) NormalizeSchema(schema any) any {
46+
switch val := (schema).(type) {
47+
case *any:
48+
s.NormalizeSchema(*val)
49+
case []any:
50+
for i := range val {
51+
s.NormalizeSchema(&val[i])
52+
}
53+
sort.SliceStable(val, func(i, j int) bool {
54+
return fmt.Sprintf("%v", val[i]) < fmt.Sprintf("%v", val[j])
55+
})
56+
case map[string]any:
57+
for k := range val {
58+
valUnderKey := val[k]
59+
s.NormalizeSchema(&valUnderKey)
60+
val[k] = valUnderKey
61+
}
62+
}
63+
return schema
64+
}
65+
4466
func (s *Server) GetOpenAPI() string {
4567
jsonBytes, err := s.api.OpenAPI().MarshalJSON()
4668
if err != nil {
@@ -51,7 +73,11 @@ func (s *Server) GetOpenAPI() string {
5173
if err := json.Unmarshal(jsonBytes, &jsonObj); err != nil {
5274
return ""
5375
}
54-
prettyJSON, err := json.MarshalIndent(jsonObj, "", " ")
76+
77+
// Normalize
78+
normalized := s.NormalizeSchema(jsonObj)
79+
80+
prettyJSON, err := json.MarshalIndent(normalized, "", " ")
5581
if err != nil {
5682
return ""
5783
}

0 commit comments

Comments
 (0)