internal/app/tier_fallback_integration_test.go
Rama main · réplica de lectura del repositorio original.
//go:build !nobundledharness
package app
import (
"context"
"encoding/json"
"log/slog"
"net/http"
"net/http/httptest"
"strings"
"sync"
"testing"
"github.com/yeomyeonggeori/blueclaw/internal/llm"
)
func TestLowTierEscalatesToMediumThroughRealCapabilityTransport(t *testing.T) {
requestedModels := []string{}
var requestedModelsLock sync.Mutex
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
if !strings.HasSuffix(request.URL.Path, "/llm/structured") {
http.Error(responseWriter, "unexpected path "+request.URL.Path, http.StatusNotFound)
return
}
var document map[string]any
if errorValue := json.NewDecoder(request.Body).Decode(&document); errorValue != nil {
http.Error(responseWriter, errorValue.Error(), http.StatusBadRequest)
return
}
modelName, _ := document["model"].(string)
requestedModelsLock.Lock()
requestedModels = append(requestedModels, modelName)
requestedModelsLock.Unlock()
if modelName == "vendor/low" {
http.Error(responseWriter, "provider returned error (502)", http.StatusBadGateway)
return
}
json.NewEncoder(responseWriter).Encode(map[string]any{
"provider": "example-gateway",
"model": modelName,
"content": `{"action":"reply","final":true}`,
})
}))
defer server.Close()
runtimeConfiguration := configuredModelTierRuntime("")
runtimeConfiguration.Capabilities.Endpoint = server.URL
providers, errorValue := resolveTaskTierLanguageModelProviders(runtimeConfiguration, slog.New(slog.DiscardHandler))
if errorValue != nil {
t.Fatal(errorValue)
}
response, errorValue := providers.Low.GenerateStructuredResponse(context.Background(), llm.StructuredResponseRequest{
Messages: []llm.Message{{Role: "user", Content: "test"}},
StructuredOutputSchema: llm.StructuredOutputSchema{
Name: "bluecollar_agent_turn_action",
Document: `{"type":"object"}`,
},
})
if errorValue != nil {
t.Fatalf("expected the low tier to escalate to medium and succeed, got error: %v (models requested: %v)", errorValue, requestedModels)
}
if !response.UsedFallback {
t.Fatalf("expected UsedFallback to be marked, got %+v (models requested: %v)", response, requestedModels)
}
if response.ModelTier != "medium" {
t.Fatalf("expected the successful fallback response to report medium tier, got %+v", response)
}
requestedModelsLock.Lock()
defer requestedModelsLock.Unlock()
if len(requestedModels) < 2 || requestedModels[len(requestedModels)-1] != "vendor/medium" {
t.Fatalf("expected a final vendor/medium request after vendor/low failures, got %v", requestedModels)
}
}
func TestCappedHighTierReportsLowModelTier(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
if !strings.HasSuffix(request.URL.Path, "/llm/structured") {
http.Error(responseWriter, "unexpected path "+request.URL.Path, http.StatusNotFound)
return
}
json.NewEncoder(responseWriter).Encode(map[string]any{
"provider": "example-gateway",
"model": "vendor/low",
"content": `{"action":"reply","final":true}`,
})
}))
defer server.Close()
runtimeConfiguration := configuredModelTierRuntime("low")
runtimeConfiguration.Capabilities.Endpoint = server.URL
providers, errorValue := resolveTaskTierLanguageModelProviders(runtimeConfiguration, slog.New(slog.DiscardHandler))
if errorValue != nil {
t.Fatal(errorValue)
}
response, errorValue := providers.High.GenerateStructuredResponse(context.Background(), llm.StructuredResponseRequest{
StructuredOutputSchema: llm.StructuredOutputSchema{Name: "bluecollar_agent_turn_action", Document: `{"type":"object"}`},
})
if errorValue != nil {
t.Fatalf("expected capped high provider to succeed: %v", errorValue)
}
if response.ModelTier != "low" {
t.Fatalf("expected capped high provider to report low tier, got %+v", response)
}
}