Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ agentapi server -- goose
```

> [!NOTE]
> When using Codex, Gemini, Amp or CursorCLI, always specify the agent type explicitly (eg: `agentapi server --type=codex -- codex`), or message formatting may break.
> 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.

An OpenAPI schema is available in [openapi.json](openapi.json).

Expand Down
22 changes: 12 additions & 10 deletions cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ import (
type AgentType = msgfmt.AgentType

const (
AgentTypeClaude AgentType = msgfmt.AgentTypeClaude
AgentTypeGoose AgentType = msgfmt.AgentTypeGoose
AgentTypeAider AgentType = msgfmt.AgentTypeAider
AgentTypeCodex AgentType = msgfmt.AgentTypeCodex
AgentTypeGemini AgentType = msgfmt.AgentTypeGemini
AgentTypeAmp AgentType = msgfmt.AgentTypeAmp
AgentTypeCursor AgentType = msgfmt.AgentTypeCursor
AgentTypeAuggie AgentType = msgfmt.AgentTypeAuggie
AgentTypeAmazonQ AgentType = msgfmt.AgentTypeAmazonQ
AgentTypeCustom AgentType = msgfmt.AgentTypeCustom
AgentTypeClaude AgentType = msgfmt.AgentTypeClaude
AgentTypeGoose AgentType = msgfmt.AgentTypeGoose
AgentTypeAider AgentType = msgfmt.AgentTypeAider
AgentTypeCodex AgentType = msgfmt.AgentTypeCodex
AgentTypeGemini AgentType = msgfmt.AgentTypeGemini
AgentTypeAmp AgentType = msgfmt.AgentTypeAmp
AgentTypeCursor AgentType = msgfmt.AgentTypeCursor
AgentTypeAuggie AgentType = msgfmt.AgentTypeAuggie
AgentTypeAmazonQ AgentType = msgfmt.AgentTypeAmazonQ
AgentTypeOpencode AgentType = msgfmt.AgentTypeOpencode
AgentTypeCustom AgentType = msgfmt.AgentTypeCustom
)

// agentTypeAliases contains the mapping of possible input agent type strings to their canonical AgentType values
Expand All @@ -48,6 +49,7 @@ var agentTypeAliases = map[string]AgentType{
"cursor-agent": AgentTypeCursor,
"q": AgentTypeAmazonQ,
"amazonq": AgentTypeAmazonQ,
"opencode": AgentTypeOpencode,
"custom": AgentTypeCustom,
}

Expand Down
10 changes: 10 additions & 0 deletions cmd/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ func TestParseAgentType(t *testing.T) {
agentTypeVar: "",
want: AgentTypeAmazonQ,
},
{
firstArg: "opencode",
agentTypeVar: "",
want: AgentTypeOpencode,
},
{
firstArg: "auggie",
agentTypeVar: "",
Expand Down Expand Up @@ -117,6 +122,11 @@ func TestParseAgentType(t *testing.T) {
agentTypeVar: "q",
want: AgentTypeAmazonQ,
},
{
firstArg: "claude",
agentTypeVar: "opencode",
want: AgentTypeOpencode,
},
{
firstArg: "claude",
agentTypeVar: "cursor-agent",
Expand Down
3 changes: 2 additions & 1 deletion lib/httpapi/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ func NewServer(ctx context.Context, config ServerConfig) (*Server, error) {
return mf.FormatAgentMessage(config.AgentType, message, userInput)
}
conversation := st.NewConversation(ctx, st.ConversationConfig{
AgentIO: config.Process,
AgentType: config.AgentType,
AgentIO: config.Process,
GetTime: func() time.Time {
return time.Now()
},
Expand Down
19 changes: 19 additions & 0 deletions lib/msgfmt/message_box.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,22 @@ func removeCodexInputBox(msg string) string {
}
return strings.Join(lines, "\n")
}

func removeOpencodeMessageBox(msg string) string {
lines := strings.Split(msg, "\n")
// Check the last 3 lines for
//
// ┃ ┃
// ┃ > ┃
// ┃ ┃
// We only check for the first ┃ and then an empty line above it - as sometimes the full input block does not load within a snapshot,
// this leads to displaying a bunch of newlines.
for i := len(lines) - 1; i >= 1; i-- {
if strings.TrimSpace(lines[i-1]) == "" &&
strings.ReplaceAll(lines[i], " ", "") == "┃┃" {
lines = lines[:i-1]
break
}
}
return strings.Join(lines, "\n")
}
17 changes: 17 additions & 0 deletions lib/msgfmt/msgfmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,13 @@ func RemoveUserInput(msgRaw string, userInputRaw string, agentType AgentType) st
if idx, found := skipTrailingInputBoxLine(msgLines, lastUserInputLineIdx, "┘", "└"); found {
lastUserInputLineIdx = idx
}
} else if agentType == AgentTypeOpencode {
// skip +2 lines after the input
// ┃ jkmr (08:46 PM) ┃
// ┃ ┃
if lastUserInputLineIdx+2 < len(msgLines) {
lastUserInputLineIdx += 2
}
}

return strings.Join(msgLines[lastUserInputLineIdx+1:], "\n")
Expand Down Expand Up @@ -234,6 +241,7 @@ const (
AgentTypeCursor AgentType = "cursor"
AgentTypeAuggie AgentType = "auggie"
AgentTypeAmazonQ AgentType = "amazonq"
AgentTypeOpencode AgentType = "opencode"
AgentTypeCustom AgentType = "custom"
)

Expand All @@ -251,6 +259,13 @@ func formatCodexMessage(message string, userInput string) string {
return message
}

func formatOpencodeMessage(message string, userInput string) string {
message = RemoveUserInput(message, userInput, AgentTypeOpencode)
message = removeOpencodeMessageBox(message)
message = trimEmptyLines(message)
return message
}

func FormatAgentMessage(agentType AgentType, message string, userInput string) string {
switch agentType {
case AgentTypeClaude:
Expand All @@ -271,6 +286,8 @@ func FormatAgentMessage(agentType AgentType, message string, userInput string) s
return formatGenericMessage(message, userInput, agentType)
case AgentTypeAmazonQ:
return formatGenericMessage(message, userInput, agentType)
case AgentTypeOpencode:
return formatOpencodeMessage(message, userInput)
case AgentTypeCustom:
return formatGenericMessage(message, userInput, agentType)
default:
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, AgentTypeAmp, AgentTypeCodex, AgentTypeCursor, AgentTypeAuggie, AgentTypeAmazonQ, AgentTypeCustom}
agentTypes := []AgentType{AgentTypeClaude, AgentTypeGoose, AgentTypeAider, AgentTypeGemini, AgentTypeAmp, AgentTypeCodex, AgentTypeCursor, AgentTypeAuggie, AgentTypeAmazonQ, AgentTypeOpencode, AgentTypeCustom}
for _, agentType := range agentTypes {
t.Run(string(agentType), func(t *testing.T) {
cases, err := testdataDir.ReadDir(path.Join(dir, string(agentType)))
Expand Down
12 changes: 12 additions & 0 deletions lib/msgfmt/testdata/format/opencode/first_message/expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
█▀▀█ █▀▀█ █▀▀ █▀▀▄ █▀▀ █▀▀█ █▀▀▄ █▀▀
█░░█ █░░█ █▀▀ █░░█ █░░ █░░█ █░░█ █▀▀
▀▀▀▀ █▀▀▀ ▀▀▀ ▀ ▀ ▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀▀
v0.6.8

/new new session ctrl+x n
/help show help ctrl+x h
/share share session ctrl+x s
/models list models ctrl+x m


Grok Code is free for a limited time
Loading