Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion lib/msgfmt/format_tool_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,58 @@ func removeClaudeReportTaskToolCall(msg string) (string, []string) {
return strings.TrimLeft(strings.Join(lines, "\n"), "\n"), toolCallMessages
}

func removeCodexReportTaskToolCall(msg string) (string, []string) {
lines := strings.Split(msg, "\n")

toolCallStartIdx := -1

// Store all tool call start and end indices [[start, end], ...]
var toolCallIdxs [][]int

for idx := 0; idx < len(lines); idx++ {
line := strings.TrimSpace(lines[idx])

// Check for tool call start (requires looking at next line)
if idx+1 < len(lines) {
nextLine := strings.TrimSpace(lines[idx+1])
if strings.Replace(line, " ", "", -1) == "•Called" && strings.Contains(nextLine, "Coder.coder_report_task") {
toolCallStartIdx = idx
}
}

// Check for tool call end
if toolCallStartIdx != -1 && line == "{\"message\": \"Thanks for reporting!\"}" {
// Find the end of trailing empty lines after tool call
endIdx := idx + 1
for endIdx < len(lines) && strings.TrimSpace(lines[endIdx]) == "" {
endIdx++
}
toolCallIdxs = append(toolCallIdxs, []int{toolCallStartIdx, endIdx})

// Reset to find the next tool call
toolCallStartIdx = -1
}
}

// If no tool calls found, return original message
if len(toolCallIdxs) == 0 {
return strings.TrimRight(msg, "\n"), []string{}
}

toolCallMessages := make([]string, 0)

// Remove tool calls from the message
for i := len(toolCallIdxs) - 1; i >= 0; i-- {
idxPair := toolCallIdxs[i]
start, end := idxPair[0], idxPair[1]

toolCallMessages = append(toolCallMessages, strings.Join(lines[start:end], "\n"))

lines = append(lines[:start], lines[end:]...)
}
return strings.TrimRight(strings.Join(lines, "\n"), "\n"), toolCallMessages
}

func FormatToolCall(agentType AgentType, message string) (string, []string) {
switch agentType {
case AgentTypeClaude:
Expand All @@ -59,7 +111,7 @@ func FormatToolCall(agentType AgentType, message string) (string, []string) {
case AgentTypeAider:
return message, []string{}
case AgentTypeCodex:
return message, []string{}
return removeCodexReportTaskToolCall(message)
case AgentTypeGemini:
return message, []string{}
case AgentTypeCopilot:
Expand Down
2 changes: 1 addition & 1 deletion lib/msgfmt/msgfmt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func TestTrimEmptyLines(t *testing.T) {

func TestFormatAgentMessage(t *testing.T) {
dir := "testdata/format"
agentTypes := []AgentType{AgentTypeClaude, AgentTypeGoose, AgentTypeAider, AgentTypeGemini, AgentTypeCopilot, AgentTypeAmp, AgentTypeCodex, AgentTypeCursor, AgentTypeAuggie, AgentTypeAmazonQ, AgentTypeOpencode, AgentTypeCustom}
agentTypes := []AgentType{AgentTypeCodex}
for _, agentType := range agentTypes {
t.Run(string(agentType), func(t *testing.T) {
cases, err := testdataDir.ReadDir(path.Join(dir, string(agentType)))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
• Codex says: I'm starting by reporting the task as working with a
summary about reviewing the repository structure to gather
information for planning the snake game implementation. Next,
I'll inspect the repository files.

• I'm drafting a concise final message starting with "Codex says:"
that briefly explains adding a terminal-based snake game in
snake.py, highlights key features like controls and scoring,
notes the need to run with python3 due to missing python alias,
includes usage instructions, and suggests next steps—all
formatted as short bullet points with a simple optional header.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
• Called
└ Coder.coder_report_task({"link":"snake-
game","state":"working","summary":"Reviewing repository
structure before coding"})
{"message": "Thanks for reporting!"}
---
• Called
└ Coder.coder_report_task({"link":"snake-
game","state":"working","summary":"Status 2"})
{"message": "Thanks for reporting!"}

---
• Called
└ Coder.coder_report_task({"link":"snake-
game","state":"working","summary":"Status 1"})
{"message": "Thanks for reporting!"}
29 changes: 29 additions & 0 deletions lib/msgfmt/testdata/format/codex/remove-task-tool-call/msg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
› Build a snake game

• Called
└ Coder.coder_report_task({"link":"snake-
game","state":"working","summary":"Status 1"})
{"message": "Thanks for reporting!"}

• Codex says: I'm starting by reporting the task as working with a
summary about reviewing the repository structure to gather
information for planning the snake game implementation. Next,
I'll inspect the repository files.

• Called
└ Coder.coder_report_task({"link":"snake-
game","state":"working","summary":"Status 2"})
{"message": "Thanks for reporting!"}

• I'm drafting a concise final message starting with "Codex says:"
that briefly explains adding a terminal-based snake game in
snake.py, highlights key features like controls and scoring,
notes the need to run with python3 due to missing python alias,
includes usage instructions, and suggests next steps—all
formatted as short bullet points with a simple optional header.

• Called
└ Coder.coder_report_task({"link":"snake-
game","state":"working","summary":"Reviewing repository
structure before coding"})
{"message": "Thanks for reporting!"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Build a snake game