test(agent): regression test for stuck typing indicator after command
Demonstrates the bug fixed in the previous commit: sentInRound must be reset before handleCommand so the Run loop does not suppress PublishOutbound for command responses. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
6ed6e2d076
commit
0b441f6af0
1 changed files with 55 additions and 0 deletions
|
|
@ -949,3 +949,58 @@ func TestResolveMediaRefs_UsesMetaContentType(t *testing.T) {
|
||||||
t.Fatalf("expected jpeg prefix, got %q", result[0].Media[0][:30])
|
t.Fatalf("expected jpeg prefix, got %q", result[0].Media[0][:30])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestProcessMessage_CommandAfterLLMRound_ResetsSentInRound is a regression
|
||||||
|
// test for the stuck typing indicator bug. When a command arrives after an LLM
|
||||||
|
// round that used the message tool, sentInRound must be reset to false before
|
||||||
|
// handleCommand runs. Without the fix the Run loop sees alreadySent=true,
|
||||||
|
// skips PublishOutbound, and the typing indicator is never cancelled.
|
||||||
|
func TestProcessMessage_CommandAfterLLMRound_ResetsSentInRound(t *testing.T) {
|
||||||
|
al, _, _, _, cleanup := newTestAgentLoop(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
defaultAgent := al.registry.GetDefaultAgent()
|
||||||
|
if defaultAgent == nil {
|
||||||
|
t.Fatal("expected default agent")
|
||||||
|
}
|
||||||
|
toolIface, ok := defaultAgent.Tools.Get("message")
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("expected message tool registered on default agent")
|
||||||
|
}
|
||||||
|
mt, ok := toolIface.(*tools.MessageTool)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("expected *tools.MessageTool")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate state left by a previous LLM round: message tool was invoked,
|
||||||
|
// setting sentInRound=true.
|
||||||
|
mt.SetContext("telegram", "chat-1")
|
||||||
|
mt.SetSendCallback(func(channel, chatID, content string) error { return nil })
|
||||||
|
mt.Execute(context.Background(), map[string]any{"content": "LLM response"})
|
||||||
|
if !mt.HasSentInRound() {
|
||||||
|
t.Fatal("precondition: expected sentInRound=true after Execute")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now process a command on the same channel/chat.
|
||||||
|
msg := bus.InboundMessage{
|
||||||
|
Channel: "telegram",
|
||||||
|
ChatID: "chat-1",
|
||||||
|
SenderID: "user1",
|
||||||
|
Content: "/show channel",
|
||||||
|
}
|
||||||
|
response, err := al.processMessage(context.Background(), msg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("processMessage failed: %v", err)
|
||||||
|
}
|
||||||
|
if response == "" {
|
||||||
|
t.Error("expected non-empty response from /show channel command")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Critical: sentInRound must be false so the Run loop's alreadySent check
|
||||||
|
// does not suppress PublishOutbound (which would leave the typing indicator
|
||||||
|
// stuck on and silently drop the command response).
|
||||||
|
if mt.HasSentInRound() {
|
||||||
|
t.Error("sentInRound is still true after command: Run loop would skip " +
|
||||||
|
"PublishOutbound, leaving the typing indicator stuck on")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue