mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-16 05:37:28 +00:00
feat: operator-defined model aliases
Spec §5 (v0.2): Config.ModelAliases map[string]string, alias-first resolution precedence ahead of provider-prefix splitting, alias-OR-target authorization, lazy target resolution with a 404 naming both ids, /v1/models listing, admin overview alias table (JSON + dashboard), and construction-time validation (shape, prefix-shadow, explicit-model collision, chain, empty target). routes_unified.go/routes_media.go needed no resolution-call-site changes - both already pass the client's raw requested id through to registry.resolve, so aliases inherit the __alias echo and multipart rewrite machinery for free. cache.go needed no changes either - cacheKey already hashes requestedModel, so two aliases resolving to the same target already produce distinct cache entries. Adds registry_test.go validation table + precedence/authz/lazy-404/ listing coverage, a dedicated cache-key split test, chat/embeddings/ images/audio-transcriptions end-to-end tests, an extended admin overview test, and an integration test covering the openai-type vs anthropic-type echo asymmetry under real Traefik+Yaegi.
This commit is contained in:
@@ -195,6 +195,14 @@ func assertOAIErrorEnvelope(t *testing.T, rec *httptest.ResponseRecorder) {
|
||||
func TestAdminOverview_SortedShapeAndVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := newAdminTestConfig()
|
||||
// Two aliases, deliberately out of sorted order, proving both the
|
||||
// overview's aliases table (spec §5, v0.2) is populated AND sorted by
|
||||
// alias — "zaliased/x" is a bare target ("z-model", zeta's own
|
||||
// explicit model), "aaliased/y" is provider-prefixed.
|
||||
cfg.ModelAliases = map[string]string{
|
||||
"zaliased/x": "z-model",
|
||||
"aaliased/y": "alpha/a-model-1",
|
||||
}
|
||||
h, _ := newAdminGatewayHandle(t, cfg)
|
||||
|
||||
rec := httptest.NewRecorder()
|
||||
@@ -247,6 +255,19 @@ func TestAdminOverview_SortedShapeAndVersion(t *testing.T) {
|
||||
if got.Redis.Configured {
|
||||
t.Error("redis.configured must be false: cfg.Redis was never configured")
|
||||
}
|
||||
|
||||
wantAliases := []adminAliasView{
|
||||
{Alias: "aaliased/y", Target: "alpha/a-model-1"},
|
||||
{Alias: "zaliased/x", Target: "z-model"},
|
||||
}
|
||||
if len(got.Aliases) != len(wantAliases) {
|
||||
t.Fatalf("aliases = %+v, want exactly %+v", got.Aliases, wantAliases)
|
||||
}
|
||||
for i, want := range wantAliases {
|
||||
if got.Aliases[i] != want {
|
||||
t.Errorf("aliases[%d] = %+v, want %+v (sorted by alias)", i, got.Aliases[i], want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdminOverview_ProviderLastErrAfterFailedRefresh(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user