package stream import ( "errors" "net" "testing" ) func TestClassifyError_TimeoutIsTransient(t *testing.T) { info := ClassifyError(errors.New("context deadline exceeded"), "dialogue_generating", "req_1", "sess_1", "") if info.Class != ErrorClassTransient { t.Fatalf("class=%s", info.Class) } if info.Code != "CHAT_TIMEOUT" && info.Code != "TRANSIENT_ERROR" { // Accept either stable code chosen in implementation; prefer CHAT_TIMEOUT when message contains timeout/deadline t.Fatalf("code=%s", info.Code) } if len(info.Actions) != 1 || info.Actions[0] != "retry" { t.Fatalf("actions=%v", info.Actions) } if info.RequestID != "req_1" || info.PhaseID != "dialogue_generating" { t.Fatalf("meta=%+v", info) } } func TestClassifyError_GenericIsFatal(t *testing.T) { info := ClassifyError(errors.New("invalid project config"), "intent_recognizing", "req_2", "sess_1", "") if info.Class != ErrorClassFatal { t.Fatalf("class=%s", info.Class) } hasRestart := false for _, a := range info.Actions { if a == "restart" { hasRestart = true } } if !hasRestart { t.Fatalf("expected restart action, got %v", info.Actions) } } func TestClassifyError_WorkspaceHintIsResumable(t *testing.T) { info := ClassifyError(errors.New("step failed mid-run"), "step_executing", "req_3", "sess_1", "research_123") if info.Class != ErrorClassResumable { t.Fatalf("class=%s", info.Class) } hasContinue := false hasRestart := false for _, a := range info.Actions { if a == "continue" { hasContinue = true } if a == "restart" { hasRestart = true } } if !hasContinue { t.Fatalf("expected continue, got %v", info.Actions) } if !hasRestart { t.Fatalf("expected restart, got %v", info.Actions) } } func TestClassifyError_DialogueNotNetwork(t *testing.T) { info := ClassifyError(errors.New("dialogue generation failed"), "dialogue_generating", "req_5", "sess_1", "") if info.Class == ErrorClassTransient { t.Fatalf("dialogue substring must not classify as transient/network, class=%s code=%s", info.Class, info.Code) } if info.Class != ErrorClassFatal { t.Fatalf("class=%s", info.Class) } } func TestClassifyError_NetworkIsTransient(t *testing.T) { info := ClassifyError(&net.OpError{Op: "dial", Err: errors.New("connection refused")}, "dialogue_generating", "req_4", "sess_1", "") if info.Class != ErrorClassTransient { t.Fatalf("class=%s", info.Class) } }