mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-15 23:50:32 +02:00
138 lines
4.2 KiB
Go
138 lines
4.2 KiB
Go
package multiagent
|
|
|
|
import "testing"
|
|
|
|
func TestEinoToolResultProgressEmitterInfersPendingAndDedupes(t *testing.T) {
|
|
var events []map[string]interface{}
|
|
progress := func(eventType, _ string, data interface{}) {
|
|
if eventType != "tool_result" {
|
|
return
|
|
}
|
|
m, _ := data.(map[string]interface{})
|
|
events = append(events, m)
|
|
}
|
|
pending := newEinoPendingToolCalls("conv-1", nil)
|
|
pending.Mark(toolCallPendingInfo{
|
|
ToolCallID: "call-1",
|
|
ToolName: "execute",
|
|
EinoAgent: "worker",
|
|
EinoRole: "sub",
|
|
})
|
|
stdoutDup := newEinoExecuteStdoutSuppressor()
|
|
emitter := newEinoToolResultProgressEmitter(einoToolResultProgressEmitterConfig{
|
|
ConversationID: "conv-1",
|
|
OrchestratorName: "lead",
|
|
Progress: progress,
|
|
EinoRoleTag: func(agent string) string {
|
|
if agent == "worker" {
|
|
return "sub"
|
|
}
|
|
return "orchestrator"
|
|
},
|
|
Pending: pending,
|
|
ExecuteStdoutDup: stdoutDup,
|
|
})
|
|
|
|
if !emitter.Emit(nil, "execute", "hello", "", false, "worker") {
|
|
t.Fatal("first tool result should emit")
|
|
}
|
|
if !emitter.Emit(nil, "execute", "duplicate without id", "", false, "worker") {
|
|
t.Fatal("id-less result should still emit after pending queue is empty")
|
|
}
|
|
if emitter.Emit(nil, "execute", "duplicate", "call-1", false, "worker") {
|
|
t.Fatal("duplicate toolCallId should not emit")
|
|
}
|
|
|
|
if len(events) != 2 {
|
|
t.Fatalf("events = %#v, want two emitted results", events)
|
|
}
|
|
if events[0]["toolCallId"] != "call-1" || events[0]["einoRole"] != "sub" {
|
|
t.Fatalf("first event data = %#v", events[0])
|
|
}
|
|
if _, ok := events[1]["toolCallId"]; ok {
|
|
t.Fatalf("second event should not invent toolCallId: %#v", events[1])
|
|
}
|
|
if got := stdoutDup.Peek(); got != "duplicate without id" {
|
|
t.Fatalf("execute stdout suppressor = %q, want last emitted execute stdout", got)
|
|
}
|
|
if pending.Count() != 0 {
|
|
t.Fatalf("pending count = %d, want 0", pending.Count())
|
|
}
|
|
}
|
|
|
|
func TestEinoToolResultProgressEmitterBackgroundWaitDisplaysRunning(t *testing.T) {
|
|
var data map[string]interface{}
|
|
progress := func(eventType, _ string, raw interface{}) {
|
|
if eventType == "tool_result" {
|
|
data, _ = raw.(map[string]interface{})
|
|
}
|
|
}
|
|
body := `工具已提交到后台执行,但本次等待已到达上限。
|
|
|
|
execution_id: 3eaaa391-050b-4be1-a870-48a855923cb7
|
|
tool: exec
|
|
status: running
|
|
wait_timeout: 10s`
|
|
emitter := newEinoToolResultProgressEmitter(einoToolResultProgressEmitterConfig{
|
|
ConversationID: "conv-1",
|
|
Progress: progress,
|
|
})
|
|
|
|
if !emitter.Emit(nil, "exec", body, "call-1", true, "lead") {
|
|
t.Fatal("background wait result should emit")
|
|
}
|
|
if data["success"] != true || data["isError"] != false || data["status"] != "background_running" {
|
|
t.Fatalf("background display flags = %#v", data)
|
|
}
|
|
if data["modelFacingIsError"] != true {
|
|
t.Fatalf("modelFacingIsError = %#v", data["modelFacingIsError"])
|
|
}
|
|
if data["executionId"] != "3eaaa391-050b-4be1-a870-48a855923cb7" {
|
|
t.Fatalf("executionId = %#v", data["executionId"])
|
|
}
|
|
}
|
|
|
|
func TestEinoToolResultProgressEmitterHidesModelOutputRejectedResult(t *testing.T) {
|
|
called := false
|
|
emitter := newEinoToolResultProgressEmitter(einoToolResultProgressEmitterConfig{
|
|
ConversationID: "conv-1",
|
|
Progress: func(eventType, _ string, _ interface{}) {
|
|
if eventType == "tool_result" {
|
|
called = true
|
|
}
|
|
},
|
|
})
|
|
|
|
if emitter.Emit(nil, "task", modelOutputRejectedResultPrefix+" Tool call was not executed.", "call-1", true, "lead") {
|
|
t.Fatal("model output rejected result should not emit")
|
|
}
|
|
if called {
|
|
t.Fatal("progress should not receive model output rejected tool_result")
|
|
}
|
|
}
|
|
|
|
func TestEinoToolResultProgressEmitterTruncatesPreview(t *testing.T) {
|
|
var data map[string]interface{}
|
|
progress := func(eventType, _ string, raw interface{}) {
|
|
if eventType == "tool_result" {
|
|
data, _ = raw.(map[string]interface{})
|
|
}
|
|
}
|
|
long := ""
|
|
for i := 0; i < 205; i++ {
|
|
long += "x"
|
|
}
|
|
emitter := newEinoToolResultProgressEmitter(einoToolResultProgressEmitterConfig{
|
|
ConversationID: "conv-1",
|
|
Progress: progress,
|
|
})
|
|
emitter.Emit(nil, "", long, "", false, "")
|
|
|
|
if data["toolName"] != "unknown" {
|
|
t.Fatalf("tool name = %#v", data["toolName"])
|
|
}
|
|
if got, _ := data["resultPreview"].(string); len(got) != 203 || got[200:] != "..." {
|
|
t.Fatalf("preview = %q len=%d", got, len(got))
|
|
}
|
|
}
|