| 1 | package agent |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "testing" |
| 7 | |
| 8 | "reasonix/internal/agent/testutil" |
| 9 | "reasonix/internal/event" |
| 10 | "reasonix/internal/provider" |
| 11 | ) |
| 12 | |
| 13 | func TestProviderFailurePersistsStructuredFailedTerminal(t *testing.T) { |
| 14 | apiErr := &provider.APIError{Provider: "deepseek-anthropic", ProviderDisplayName: "Deepseek2", Protocol: "openai", Status: 404} |
| 15 | mp := testutil.NewMock("m", testutil.ErrorTurn(apiErr)) |
| 16 | a := New(mp, echoRegistry(), NewSession(""), Options{}, event.Discard) |
| 17 | if err := a.Run(withNoClosedLoop(context.Background()), "check bug"); !errors.Is(err, apiErr) { |
| 18 | t.Fatalf("Run error = %v", err) |
| 19 | } |
| 20 | last := a.Session().Messages[len(a.Session().Messages)-1] |
| 21 | recovery := last.InterruptedTurn |
| 22 | if !last.LocalOnly || recovery == nil || recovery.TerminalStatus != "failed" { |
| 23 | t.Fatalf("failed recovery = %+v", last) |
| 24 | } |
| 25 | if d := recovery.FailureDiagnostic; d == nil || d.ProviderID != "deepseek-anthropic" || d.ProviderDisplayName != "Deepseek2" || d.Protocol != "openai" || d.Status != 404 { |
| 26 | t.Fatalf("failure diagnostic = %+v", d) |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | func TestInterruptedRecoveryDisplayMetadataDoesNotChangeProviderBlock(t *testing.T) { |
| 31 | base := &provider.InterruptedTurnRecovery{Pending: true, InterruptedTools: []string{"bash"}, DroppedPartialText: true} |
| 32 | enriched := *base |
| 33 | enriched.TerminalStatus = "failed" |
| 34 | enriched.FailureDiagnostic = &provider.FailureDiagnostic{Kind: "request", Status: 404, ProviderID: "deepseek-anthropic", ProviderDisplayName: "Deepseek2", Protocol: "openai"} |
| 35 | if before, after := interruptedRecoveryBlock(base), interruptedRecoveryBlock(&enriched); before != after { |
| 36 | t.Fatalf("display metadata changed provider-visible recovery\nbefore=%q\nafter=%q", before, after) |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | func TestCancelledTurnPersistsInterruptedTerminal(t *testing.T) { |
| 41 | a := New(testutil.NewMock("m"), echoRegistry(), NewSession(""), Options{}, event.Discard) |
| 42 | a.recordInterruptedDisplay("partial", "", nil, true, context.Canceled, 0) |
| 43 | last := a.Session().Messages[len(a.Session().Messages)-1] |
| 44 | if last.InterruptedTurn == nil || last.InterruptedTurn.TerminalStatus != "interrupted" || last.InterruptedTurn.FailureDiagnostic != nil { |
| 45 | t.Fatalf("cancelled recovery = %+v", last.InterruptedTurn) |
| 46 | } |
| 47 | } |
| 48 |