diff --git a/server/agent_working_test.go b/server/agent_working_test.go new file mode 100644 index 0000000000000000000000000000000000000000..af825efc135fb895c982e96efd245a933d31b5c6 --- /dev/null +++ b/server/agent_working_test.go @@ -0,0 +1,103 @@ +package server + +import ( + "testing" + + "shelley.exe.dev/db" +) + +func boolPtr(b bool) *bool { + return &b +} + +func TestAgentWorking(t *testing.T) { + tests := []struct { + name string + messages []APIMessage + want bool + }{ + { + name: "empty messages", + messages: []APIMessage{}, + want: false, + }, + { + name: "agent with end_of_turn true", + messages: []APIMessage{ + {Type: string(db.MessageTypeAgent), EndOfTurn: boolPtr(true)}, + }, + want: false, + }, + { + name: "agent with end_of_turn false", + messages: []APIMessage{ + {Type: string(db.MessageTypeAgent), EndOfTurn: boolPtr(false)}, + }, + want: true, + }, + { + name: "agent with end_of_turn nil", + messages: []APIMessage{ + {Type: string(db.MessageTypeAgent), EndOfTurn: nil}, + }, + want: true, + }, + { + name: "error message", + messages: []APIMessage{ + {Type: string(db.MessageTypeError)}, + }, + want: false, + }, + { + name: "agent end_of_turn then tool message means working", + messages: []APIMessage{ + {Type: string(db.MessageTypeAgent), EndOfTurn: boolPtr(true)}, + {Type: string(db.MessageTypeTool)}, + }, + want: true, + }, + { + name: "gitinfo after agent end_of_turn should NOT indicate working", + messages: []APIMessage{ + {Type: string(db.MessageTypeAgent), EndOfTurn: boolPtr(true)}, + {Type: string(db.MessageTypeGitInfo)}, + }, + want: false, + }, + { + name: "multiple gitinfo after agent end_of_turn should NOT indicate working", + messages: []APIMessage{ + {Type: string(db.MessageTypeAgent), EndOfTurn: boolPtr(true)}, + {Type: string(db.MessageTypeGitInfo)}, + {Type: string(db.MessageTypeGitInfo)}, + }, + want: false, + }, + { + name: "gitinfo after agent not end_of_turn should indicate working", + messages: []APIMessage{ + {Type: string(db.MessageTypeAgent), EndOfTurn: boolPtr(false)}, + {Type: string(db.MessageTypeGitInfo)}, + }, + want: true, + }, + { + name: "only gitinfo messages", + messages: []APIMessage{ + {Type: string(db.MessageTypeGitInfo)}, + {Type: string(db.MessageTypeGitInfo)}, + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := agentWorking(tt.messages) + if got != tt.want { + t.Errorf("agentWorking() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/server/server.go b/server/server.go index 410c780995057d0f0d19c8b30bfb5fd7576971fa..3c5d421e52b6819abd56999601ae03a74d6c3767 100644 --- a/server/server.go +++ b/server/server.go @@ -147,7 +147,15 @@ func agentWorking(messages []APIMessage) bool { return false } - last := messages[len(messages)-1] + // Find the last non-gitinfo message (gitinfo messages are passive notifications) + lastIdx := len(messages) - 1 + for lastIdx >= 0 && messages[lastIdx].Type == string(db.MessageTypeGitInfo) { + lastIdx-- + } + if lastIdx < 0 { + return false + } + last := messages[lastIdx] // If the last message is an error, agent is not working if last.Type == string(db.MessageTypeError) { @@ -161,7 +169,7 @@ func agentWorking(messages []APIMessage) bool { return !*last.EndOfTurn } - for i := len(messages) - 1; i >= 0; i-- { + for i := lastIdx; i >= 0; i-- { msg := messages[i] if msg.Type != string(db.MessageTypeAgent) { continue