Skip to content

Commit 90486c5

Browse files
authored
feat(claude): remove coder_report_task tool call message (#157)
1 parent 449ca91 commit 90486c5

File tree

8 files changed

+182
-5
lines changed

8 files changed

+182
-5
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ agentapi server -- goose
7373
```
7474

7575
> [!NOTE]
76-
> 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.
76+
> When using Claude, Codex, Opencode, Copilot, Gemini, Amp or CursorCLI, always specify the agent type explicitly (eg: `agentapi server --type=codex -- codex`), or message formatting may break.
7777
7878
An OpenAPI schema is available in [openapi.json](openapi.json).
7979

lib/httpapi/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func NewServer(ctx context.Context, config ServerConfig) (*Server, error) {
226226
humaConfig.Info.Description = "HTTP API for Claude Code, Goose, and Aider.\n\nhttps://github.com/coder/agentapi"
227227
api := humachi.New(router, humaConfig)
228228
formatMessage := func(message string, userInput string) string {
229-
return mf.FormatAgentMessage(config.AgentType, message, userInput)
229+
return mf.FormatAgentMessage(config.AgentType, message, userInput, logger)
230230
}
231231

232232
isAgentReadyForInitialPrompt := func(message string) bool {

lib/msgfmt/message_box.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package msgfmt
22

33
import (
4+
"log/slog"
45
"strings"
56
)
67

@@ -100,3 +101,57 @@ func removeAmpMessageBox(msg string) string {
100101
}
101102
return formattedMsg
102103
}
104+
105+
func removeClaudeReportTaskToolCall(msg string, logger *slog.Logger) string {
106+
// Remove all tool calls that start with `● coder - coder_report_task (MCP)` till we encounter the next line starting with ●
107+
lines := strings.Split(msg, "\n")
108+
109+
toolCallStartIdx := -1
110+
newLineAfterToolCallIdx := -1
111+
112+
// Store all tool call start and end indices [[start, end], ...]
113+
var toolCallIdxs [][]int
114+
115+
for i := 0; i < len(lines); i++ {
116+
line := strings.TrimSpace(lines[i])
117+
118+
if strings.HasPrefix(line, "● coder - coder_report_task (MCP)") {
119+
toolCallStartIdx = i
120+
} else if toolCallStartIdx != -1 && strings.HasPrefix(line, "●") {
121+
// Store [start, end] pair
122+
toolCallIdxs = append(toolCallIdxs, []int{toolCallStartIdx, i})
123+
124+
// Reset to find the next tool call
125+
toolCallStartIdx = -1
126+
newLineAfterToolCallIdx = -1
127+
}
128+
if len(line) == 0 && toolCallStartIdx != -1 && newLineAfterToolCallIdx == -1 {
129+
newLineAfterToolCallIdx = i
130+
}
131+
}
132+
133+
// Handle the case where the last tool call goes till the end of the message
134+
// And a failsafe when the next message is not prefixed with ●
135+
if toolCallStartIdx != -1 && newLineAfterToolCallIdx != -1 {
136+
toolCallIdxs = append(toolCallIdxs, []int{toolCallStartIdx, newLineAfterToolCallIdx})
137+
}
138+
139+
// If no tool calls found, return original message
140+
if len(toolCallIdxs) == 0 {
141+
return msg
142+
}
143+
144+
// Remove tool calls from the message
145+
for i := len(toolCallIdxs) - 1; i >= 0; i-- {
146+
idxPair := toolCallIdxs[i]
147+
start, end := idxPair[0], idxPair[1]
148+
149+
// Capture the tool call content before removing it
150+
toolCallContent := strings.Join(lines[start:end], "\n")
151+
logger.Info("Removing tool call", "content", toolCallContent)
152+
153+
lines = append(lines[:start], lines[end:]...)
154+
}
155+
156+
return strings.Join(lines, "\n")
157+
}

lib/msgfmt/msgfmt.go

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

33
import (
4+
"log/slog"
45
"strings"
56
)
67

@@ -254,6 +255,14 @@ func formatGenericMessage(message string, userInput string, agentType AgentType)
254255
return message
255256
}
256257

258+
func formatClaudeMessage(message string, userInput string, logger *slog.Logger) string {
259+
message = RemoveUserInput(message, userInput, AgentTypeClaude)
260+
message = removeMessageBox(message)
261+
message = removeClaudeReportTaskToolCall(message, logger)
262+
message = trimEmptyLines(message)
263+
return message
264+
}
265+
257266
func formatCodexMessage(message string, userInput string) string {
258267
message = RemoveUserInput(message, userInput, AgentTypeCodex)
259268
message = removeCodexInputBox(message)
@@ -275,10 +284,10 @@ func formatAmpMessage(message string, userInput string) string {
275284
return message
276285
}
277286

278-
func FormatAgentMessage(agentType AgentType, message string, userInput string) string {
287+
func FormatAgentMessage(agentType AgentType, message string, userInput string, logger *slog.Logger) string {
279288
switch agentType {
280289
case AgentTypeClaude:
281-
return formatGenericMessage(message, userInput, agentType)
290+
return formatClaudeMessage(message, userInput, logger)
282291
case AgentTypeGoose:
283292
return formatGenericMessage(message, userInput, agentType)
284293
case AgentTypeAider:

lib/msgfmt/msgfmt_test.go

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

33
import (
44
"embed"
5+
"log/slog"
56
"path"
67
"strings"
78
"testing"
@@ -233,7 +234,7 @@ func TestFormatAgentMessage(t *testing.T) {
233234
assert.NoError(t, err)
234235
expected, err := testdataDir.ReadFile(path.Join(dir, string(agentType), c.Name(), "expected.txt"))
235236
assert.NoError(t, err)
236-
assert.Equal(t, string(expected), FormatAgentMessage(agentType, string(msg), string(userInput)))
237+
assert.Equal(t, string(expected), FormatAgentMessage(agentType, string(msg), string(userInput), slog.Default()))
237238
})
238239
}
239240
})
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
● I'll build a snake game for you. Let me start by reporting my
2+
progress and creating a task list.
3+
4+
● Now I'll create a complete snake game with HTML, CSS, and
5+
JavaScript:
6+
7+
● Write(snake-game.html)
8+
⎿ Wrote 344 lines to snake-game.html
9+
<!DOCTYPE html>
10+
<html lang="en">
11+
<head>
12+
<meta charset="UTF-8">
13+
<meta name="viewport" content="width=device-width,
14+
initial-scale=1.0">
15+
<title>Snake Game</title>
16+
<style>
17+
* {
18+
margin: 0;
19+
padding: 0;
20+
… +334 lines (ctrl+o to expand)
21+
22+
● I've built a complete snake game for you! The game is saved
23+
at /home/coder/snake-game.html.
24+
25+
Features:
26+
- Classic snake gameplay with smooth controls
27+
- Use arrow keys to control the snake
28+
- Press SPACE to pause/unpause
29+
- Score tracking with increasing difficulty (speed increases
30+
every 5 points)
31+
- Colorful gradient background and styled UI
32+
- Game over screen with restart option
33+
- Snake grows when eating food
34+
- Collision detection for walls and self-collision
35+
36+
How to play:
37+
Open the HTML file in your web browser and use the arrow keys
38+
to move the snake. Collect the red food to grow and increase
39+
your score!
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
> Build a snake game
2+
3+
● I'll build a snake game for you. Let me start by reporting my
4+
progress and creating a task list.
5+
6+
● coder - coder_report_task (MCP)(summary: "Building a snake game
7+
with HTML/CSS/JavaScript", link:
8+
"", state: "working")
9+
⎿ {
10+
"message": "Thanks for reporting!"
11+
}
12+
13+
● Now I'll create a complete snake game with HTML, CSS, and
14+
JavaScript:
15+
16+
● Write(snake-game.html)
17+
⎿ Wrote 344 lines to snake-game.html
18+
<!DOCTYPE html>
19+
<html lang="en">
20+
<head>
21+
<meta charset="UTF-8">
22+
<meta name="viewport" content="width=device-width,
23+
initial-scale=1.0">
24+
<title>Snake Game</title>
25+
<style>
26+
* {
27+
margin: 0;
28+
padding: 0;
29+
… +334 lines (ctrl+o to expand)
30+
31+
● coder - coder_report_task (MCP)(summary: "Snake game created
32+
successfully at snake-game.html",
33+
link: "file:///home/coder/snake-ga
34+
me.html", state: "working")
35+
⎿ {
36+
"message": "Thanks for reporting!"
37+
}
38+
39+
40+
● I've built a complete snake game for you! The game is saved
41+
at /home/coder/snake-game.html.
42+
43+
Features:
44+
- Classic snake gameplay with smooth controls
45+
- Use arrow keys to control the snake
46+
- Press SPACE to pause/unpause
47+
- Score tracking with increasing difficulty (speed increases
48+
every 5 points)
49+
- Colorful gradient background and styled UI
50+
- Game over screen with restart option
51+
- Snake grows when eating food
52+
- Collision detection for walls and self-collision
53+
54+
How to play:
55+
Open the HTML file in your web browser and use the arrow keys
56+
to move the snake. Collect the red food to grow and increase
57+
your score!
58+
59+
● coder - coder_report_task (MCP)(summary: "Snake game created
60+
successfully at snake-game.html",
61+
link: "file:///home/coder/snake-ga
62+
me.html", state: "working")
63+
⎿ {
64+
"message": "Thanks for reporting!"
65+
}
66+
67+
68+
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
69+
70+
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
71+
? for shortcuts ⧉ In message_box.go
72+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Build a snake game

0 commit comments

Comments
 (0)