(t *testing.T)
| 293 | } |
| 294 | |
| 295 | func TestFallback429SkipsToNextModel(t *testing.T) { |
| 296 | t.Parallel() |
| 297 | |
| 298 | synctest.Test(t, func(t *testing.T) { |
| 299 | primary := &countingProvider{ |
| 300 | id: "primary/rate-limited", failCount: 100, |
| 301 | err: errors.New("POST /v1/chat/completions: 429 Too Many Requests"), |
| 302 | } |
| 303 | successStream := newStreamBuilder(). |
| 304 | AddContent("Success from fallback"). |
| 305 | AddStopWithUsage(10, 5). |
| 306 | Build() |
| 307 | fallback := &mockProvider{id: "fallback/success", stream: successStream} |
| 308 | |
| 309 | root := agent.New("root", "test", |
| 310 | agent.WithModel(primary), |
| 311 | agent.WithFallbackModel(fallback), |
| 312 | agent.WithFallbackRetries(5), |
| 313 | ) |
| 314 | |
| 315 | tm := team.New(team.WithAgents(root)) |
| 316 | rt, err := NewLocalRuntime(t.Context(), tm, WithSessionCompaction(false), WithModelStore(mockModelStore{})) |
| 317 | require.NoError(t, err) |
| 318 | |
| 319 | sess := session.New(session.WithUserMessage("test")) |
| 320 | sess.Title = "429 Skip Test" |
| 321 | |
| 322 | var gotContent bool |
| 323 | for ev := range rt.RunStream(t.Context(), sess) { |
| 324 | if choice, ok := ev.(*AgentChoiceEvent); ok && choice.Content == "Success from fallback" { |
| 325 | gotContent = true |
| 326 | } |
| 327 | } |
| 328 | assert.True(t, gotContent, "should receive content from fallback") |
| 329 | assert.Equal(t, 1, primary.callCount, "primary should only be called once (429 is not retryable)") |
| 330 | }) |
| 331 | } |
| 332 | |
| 333 | func TestFallbackCooldownState(t *testing.T) { |
| 334 | t.Parallel() |
nothing calls this directly
no test coverage detected