package multiagent import ( "context" "errors" "testing" "github.com/cloudwego/eino/adk" "github.com/cloudwego/eino/schema" "go.uber.org/zap" "go.uber.org/zap/zaptest/observer" ) func TestEinoContextOverflowRetryHandlerPreparesOnce(t *testing.T) { baseMsgs := []adk.Message{ schema.UserMessage("base"), } accumulated := []adk.Message{ schema.UserMessage("base"), schema.AssistantMessage("partial", nil), } var gotType, gotMessage string var gotData map[string]interface{} core, logs := observer.New(zap.WarnLevel) handler := newEinoContextOverflowRetryHandler(einoContextOverflowRetryConfig{ Context: context.Background(), ConversationID: "conv-1", OrchMode: "deep_agent", Args: &einoADKRunLoopArgs{}, BaseMsgs: baseMsgs, Progress: func(eventType, message string, data interface{}) { gotType = eventType gotMessage = message var ok bool gotData, ok = data.(map[string]interface{}) if !ok { t.Fatalf("progress data type = %T, want map[string]interface{}", data) } }, Logger: zap.New(core), }) result := handler.Prepare(errors.New("context length exceeded"), accumulated, len(baseMsgs)) if !result.Handled { t.Fatal("handled = false, want true") } if result.ContextSrc != einoRestartContextAccumulated { t.Fatalf("context source = %q, want %q", result.ContextSrc, einoRestartContextAccumulated) } if len(result.RestartMsgs) != len(accumulated) { t.Fatalf("restart message count = %d, want %d", len(result.RestartMsgs), len(accumulated)) } if gotType != "eino_context_overflow_retry" { t.Fatalf("event type = %q, want eino_context_overflow_retry", gotType) } if gotMessage != "上下文超限,正在激进压缩后重试…" { t.Fatalf("message = %q", gotMessage) } assertContextOverflowMapValue(t, gotData, "conversationId", "conv-1") assertContextOverflowMapValue(t, gotData, "source", "eino") assertContextOverflowMapValue(t, gotData, "orchestration", "deep_agent") assertContextOverflowMapValue(t, gotData, "contextSource", string(einoRestartContextAccumulated)) if logs.FilterMessage("eino context overflow, retrying with aggressive compaction").Len() != 1 { t.Fatalf("expected one context overflow retry log, got %d", logs.Len()) } second := handler.Prepare(errors.New("maximum context length"), accumulated, len(baseMsgs)) if second.Handled { t.Fatalf("second result = %+v, want unhandled after first retry", second) } } func TestEinoContextOverflowRetryHandlerIgnoresOtherErrors(t *testing.T) { handler := newEinoContextOverflowRetryHandler(einoContextOverflowRetryConfig{ Context: context.Background(), Args: &einoADKRunLoopArgs{}, BaseMsgs: []adk.Message{schema.UserMessage("base")}, }) result := handler.Prepare(errors.New("HTTP 429 Too Many Requests"), nil, 0) if result.Handled { t.Fatalf("result = %+v, want unhandled", result) } } func assertContextOverflowMapValue(t *testing.T, data map[string]interface{}, key string, want interface{}) { t.Helper() if got := data[key]; got != want { t.Fatalf("%s = %v, want %v", key, got, want) } }