package multiagent import ( "testing" "github.com/cloudwego/eino/adk" ) func TestEinoInitialIteratorStartHandlerKeepsExistingIterator(t *testing.T) { existing, gen := adk.NewAsyncIteratorPair[*adk.AgentEvent]() defer gen.Close() var started bool got := newEinoInitialIteratorStartHandler(einoInitialIteratorStartHandlerConfig{ UseTurnLoop: true, StartTurnLoop: func([]adk.Message) *adk.AsyncIterator[*adk.AgentEvent] { started = true iter, iterGen := adk.NewAsyncIteratorPair[*adk.AgentEvent]() iterGen.Close() return iter }, Progress: func(string, string, interface{}) { t.Fatal("progress should not be emitted when an iterator already exists") }, }).StartIfNeeded(existing, nil) if got != existing { t.Fatal("existing iterator should be preserved") } if started { t.Fatal("start function should not be called when an iterator already exists") } } func TestEinoInitialIteratorStartHandlerStartsRunner(t *testing.T) { wantIter, gen := adk.NewAsyncIteratorPair[*adk.AgentEvent]() defer gen.Close() var runnerStarted bool got := newEinoInitialIteratorStartHandler(einoInitialIteratorStartHandlerConfig{ StartRunner: func(msgs []adk.Message) *adk.AsyncIterator[*adk.AgentEvent] { runnerStarted = true if msgs == nil { t.Fatal("msgs should be forwarded") } return wantIter }, StartTurnLoop: func([]adk.Message) *adk.AsyncIterator[*adk.AgentEvent] { t.Fatal("turn loop should not start when UseTurnLoop is false") return nil }, Progress: func(string, string, interface{}) { t.Fatal("runner start should not emit TurnLoop takeover progress") }, }).StartIfNeeded(nil, []adk.Message{}) if !runnerStarted { t.Fatal("runner start was not called") } if got != wantIter { t.Fatal("runner iterator should be returned") } } func TestEinoInitialIteratorStartHandlerStartsTurnLoopWithTakeoverProgress(t *testing.T) { wantIter, gen := adk.NewAsyncIteratorPair[*adk.AgentEvent]() defer gen.Close() var turnLoopStarted bool var gotType, gotMessage string var gotData map[string]interface{} got := newEinoInitialIteratorStartHandler(einoInitialIteratorStartHandlerConfig{ ConversationID: "conv-1", OrchMode: "deep", UseTurnLoop: true, StartRunner: func([]adk.Message) *adk.AsyncIterator[*adk.AgentEvent] { t.Fatal("runner should not start when UseTurnLoop is true") return nil }, StartTurnLoop: func(msgs []adk.Message) *adk.AsyncIterator[*adk.AgentEvent] { turnLoopStarted = true if msgs == nil { t.Fatal("msgs should be forwarded") } return wantIter }, Progress: func(eventType, message string, data interface{}) { gotType = eventType gotMessage = message if m, ok := data.(map[string]interface{}); ok { gotData = m } }, }).StartIfNeeded(nil, []adk.Message{}) if !turnLoopStarted { t.Fatal("turn loop start was not called") } if got != wantIter { t.Fatal("turn loop iterator should be returned") } if gotType != "progress" { t.Fatalf("progress type = %q, want progress", gotType) } if gotMessage != "Eino TurnLoop 常驻多轮 runtime 已接管本轮会话。" { t.Fatalf("progress message = %q", gotMessage) } if gotData["conversationId"] != "conv-1" || gotData["source"] != "eino" || gotData["orchestration"] != "deep" { t.Fatalf("progress data = %#v", gotData) } }