Skip to content

Commit dde7836

Browse files
authored
feat: support gemini cli (#32)
1 parent 433e919 commit dde7836

File tree

16 files changed

+143
-5
lines changed

16 files changed

+143
-5
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ snapshot2-*.log
66
schema.yaml
77
**/.claude/settings.local.json
88
out
9+
10+
11+
#IDEs
12+
.idea

README.md

Lines changed: 1 addition & 1 deletion
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), [Goose](https://github.com/block/goose), [Aider](https://github.com/Aider-AI/aider), and [Codex](https://github.com/openai/codex) with an HTTP API.
3+
Control [Claude Code](https://github.com/anthropics/claude-code), [Goose](https://github.com/block/goose), [Aider](https://github.com/Aider-AI/aider), [Gemini](https://github.com/google-gemini/gemini-cli) and [Codex](https://github.com/openai/codex) with an HTTP API.
44

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

cmd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
var rootCmd = &cobra.Command{
1313
Use: "agentapi",
1414
Short: "AgentAPI CLI",
15-
Long: `AgentAPI - HTTP API for Claude Code, Goose, Aider, and Codex`,
15+
Long: `AgentAPI - HTTP API for Claude Code, Goose, Aider, Gemini and Codex`,
1616
Version: "0.2.3",
1717
}
1818

cmd/server/server.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const (
3434
AgentTypeGoose AgentType = msgfmt.AgentTypeGoose
3535
AgentTypeAider AgentType = msgfmt.AgentTypeAider
3636
AgentTypeCodex AgentType = msgfmt.AgentTypeCodex
37+
AgentTypeGemini AgentType = msgfmt.AgentTypeGemini
3738
AgentTypeCustom AgentType = msgfmt.AgentTypeCustom
3839
)
3940

@@ -46,6 +47,8 @@ func parseAgentType(firstArg string, agentTypeVar string) (AgentType, error) {
4647
agentType = AgentTypeGoose
4748
case string(AgentTypeAider):
4849
agentType = AgentTypeAider
50+
case string(AgentTypeGemini):
51+
agentType = AgentTypeGemini
4952
case string(AgentTypeCustom):
5053
agentType = AgentTypeCustom
5154
case string(AgentTypeCodex):
@@ -68,6 +71,8 @@ func parseAgentType(firstArg string, agentTypeVar string) (AgentType, error) {
6871
agentType = AgentTypeAider
6972
case string(AgentTypeCodex):
7073
agentType = AgentTypeCodex
74+
case string(AgentTypeGemini):
75+
agentType = AgentTypeGemini
7176
default:
7277
agentType = AgentTypeCustom
7378
}
@@ -137,7 +142,7 @@ func runServer(ctx context.Context, logger *slog.Logger, argsToPass []string) er
137142
var ServerCmd = &cobra.Command{
138143
Use: "server [agent]",
139144
Short: "Run the server",
140-
Long: `Run the server with the specified agent (claude, goose, aider, codex)`,
145+
Long: `Run the server with the specified agent (claude, goose, aider, gemini, codex)`,
141146
Args: cobra.MinimumNArgs(1),
142147
Run: func(cmd *cobra.Command, args []string) {
143148
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))

cmd/server/server_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ func TestParseAgentType(t *testing.T) {
2323
agentTypeVar: "",
2424
want: AgentTypeClaude,
2525
},
26+
{
27+
firstArg: "gemini",
28+
agentTypeVar: "",
29+
want: AgentTypeGemini,
30+
},
2631
{
2732
firstArg: "goose",
2833
agentTypeVar: "",
@@ -48,6 +53,11 @@ func TestParseAgentType(t *testing.T) {
4853
agentTypeVar: "claude",
4954
want: AgentTypeClaude,
5055
},
56+
{
57+
firstArg: "claude",
58+
agentTypeVar: "gemini",
59+
want: AgentTypeGemini,
60+
},
5161
{
5262
firstArg: "aider",
5363
agentTypeVar: "claude",

lib/msgfmt/msgfmt.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package msgfmt
22

3-
import "strings"
3+
import (
4+
"strings"
5+
)
46

57
const WhiteSpaceChars = " \t\n\r\f\v"
68

@@ -166,6 +168,12 @@ func RemoveUserInput(msgRaw string, userInputRaw string) string {
166168
// Return the original message starting with the first line
167169
// that doesn't contain the echoed user input.
168170
lastUserInputLineIdx := msgRuneLineLocations[userInputEndIdx]
171+
172+
// In case of Gemini, the user input echoed back is wrapped in a rounded box, so we remove it.
173+
if lastUserInputLineIdx+1 < len(msgLines) && strings.Contains(msgLines[lastUserInputLineIdx+1], "╯") && strings.Contains(msgLines[lastUserInputLineIdx+1], "╰") {
174+
lastUserInputLineIdx += 1
175+
}
176+
169177
return strings.Join(msgLines[lastUserInputLineIdx+1:], "\n")
170178
}
171179

@@ -197,6 +205,7 @@ const (
197205
AgentTypeGoose AgentType = "goose"
198206
AgentTypeAider AgentType = "aider"
199207
AgentTypeCodex AgentType = "codex"
208+
AgentTypeGemini AgentType = "gemini"
200209
AgentTypeCustom AgentType = "custom"
201210
)
202211

@@ -217,6 +226,8 @@ func FormatAgentMessage(agentType AgentType, message string, userInput string) s
217226
return formatGenericMessage(message, userInput)
218227
case AgentTypeCodex:
219228
return formatGenericMessage(message, userInput)
229+
case AgentTypeGemini:
230+
return formatGenericMessage(message, userInput)
220231
case AgentTypeCustom:
221232
return formatGenericMessage(message, userInput)
222233
default:

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, AgentTypeCodex, AgentTypeCustom}
221+
agentTypes := []AgentType{AgentTypeClaude, AgentTypeGoose, AgentTypeAider, AgentTypeGemini, AgentTypeCodex, 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)))
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Tips for getting started:
2+
1. Ask questions, edit files, or run commands.
3+
2. Be specific for the best results.
4+
3. Create GEMINI.md files to customize your interactions with Gemini.
5+
4. /help for more information.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Tips for getting started:
2+
1. Ask questions, edit files, or run commands.
3+
2. Be specific for the best results.
4+
3. Create GEMINI.md files to customize your interactions with Gemini.
5+
4. /help for more information.
6+
7+
8+
9+
╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
10+
│ > Type your message or @path/to/file │
11+
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
12+
13+
~/Documents/work/agentapi (feat-claude-cli*) no sandbox (see /docs) gemini-2.5-pro (100% context left)

lib/msgfmt/testdata/format/gemini/first_message/user.txt

Whitespace-only changes.

0 commit comments

Comments
 (0)