Files
LocalAI/core/config/meta/registry_test.go
T
mudler-agentandEttore Di Giacinto 0177e4988c feat(images): add ESRGAN upscaling and Studio workflow (#12620)
* feat(images): add upscale model capabilities

* fix(config): keep SD GGML upscale opt-in

* feat(stablediffusion): add lazy ESRGAN upscale bridge

Keep native image ownership in C++ and serialize context creation, inference and teardown. Use upscale_scale in backend options as the explicit upscale-only marker because ModelOptions does not carry usecases.

Assisted-by: Codex:gpt-5

* fix(stablediffusion): validate ESRGAN settings

* fix(upscale): forward typed settings and contain resolved model paths

Typed settings replace legacy options without duplicates. Resolve model and trusted root symlinks before caching the model path, rejecting missing files and escapes.

Assisted-by: Codex:gpt-5

* fix(upscale): validate scale and clean failed HTTP outputs

Require an explicit scale bounded to 1-16, check backend results, and keep destination cleanup owned by the allocating endpoint. Cover validation, result failures, cleanup, and successful URL responses.

Assisted-by: Codex:gpt-5

* feat(studio): add inline image upscale workflow

Assisted-by: OpenAI:gpt-5

* test(studio): serve upscale capability fixtures

* fix(stablediffusion): default ESRGAN tiling to full frame

* feat(gallery): add RealESRGAN anime upscaler

* fix(stablediffusion): allow full-frame ESRGAN tiles

* fix(routes): select explicit upscale models

Give image upscaling dedicated usecase-filtered middleware and keep ordinary image models out of the endpoint. Mark and verify the legacy Diffusers x4 gallery model as an explicit upscaler.

Assisted-by: OpenAI:gpt-5 [shell]

* refactor(upscale): keep settings in backend options

* test(config): keep upscale options backend-specific

* fix: keep upscale routing metadata out of backend options

---------

Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
2026-10-11 00:30:09 +02:00

100 lines
3.4 KiB
Go

package meta_test
import (
"reflect"
"github.com/mudler/LocalAI/core/config"
"github.com/mudler/LocalAI/core/config/meta"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("alias field metadata", func() {
It("registers the alias field as a model-select in the alias section", func() {
reg := meta.DefaultRegistry()
f, ok := reg["alias"]
Expect(ok).To(BeTrue(), "alias field should have a registry override")
Expect(f.Section).To(Equal("alias"))
Expect(f.Component).To(Equal("model-select"))
})
It("defines an alias section", func() {
var found bool
for _, s := range meta.DefaultSections() {
if s.ID == "alias" {
found = true
}
}
Expect(found).To(BeTrue(), "DefaultSections should include an alias section")
})
It("registers the failover section", func() {
reg := meta.DefaultRegistry()
Expect(reg).To(HaveKey("failover.targets"))
Expect(reg["failover.targets"].Section).To(Equal("failover"))
Expect(reg["failover.targets"].Component).To(Equal("failover-targets"))
var ids []string
for _, s := range meta.DefaultSections() {
ids = append(ids, s.ID)
}
Expect(ids).To(ContainElement("failover"))
})
})
var _ = Describe("MCP field metadata", func() {
var fields map[string]meta.FieldMeta
BeforeEach(func() {
md := meta.BuildForTest(reflect.TypeOf(config.ModelConfig{}), meta.DefaultRegistry())
fields = make(map[string]meta.FieldMeta, len(md.Fields))
for _, field := range md.Fields {
fields[field.Path] = field
}
})
DescribeTable("registers embedded MCP configuration as YAML code",
func(path, label, transportDetail string) {
f, ok := fields[path]
Expect(ok).To(BeTrue(), "%s should be present in generated metadata", path)
Expect(f.Section).To(Equal("mcp"))
Expect(f.Label).To(Equal(label))
Expect(f.Description).To(ContainSubstring("mcpServers"))
Expect(f.Description).To(ContainSubstring(transportDetail))
Expect(f.Component).To(Equal("code-editor"))
Expect(f.Language).To(Equal("yaml"))
},
Entry("remote servers", "mcp.remote", "Remote MCP Servers", "Streamable HTTP"),
Entry("stdio servers", "mcp.stdio", "MCP STDIO Servers", "local commands"),
)
})
var _ = Describe("Decisions router metadata", func() {
It("offers decisions alongside existing classifiers", func() {
f := meta.DefaultRegistry()["router.classifier"]
Expect(f.Options).To(ContainElement(meta.FieldOption{Value: "decisions", Label: "Decisions (native probabilities)"}))
md := meta.BuildForTest(reflect.TypeOf(config.ModelConfig{}), meta.DefaultRegistry())
for _, field := range md.Fields {
if field.Path == "router.classifier_model" {
Expect(field.AutocompleteBy).NotTo(BeNil())
Expect(field.AutocompleteBy.Field).To(Equal("router.classifier"))
Expect(field.AutocompleteBy.Providers).To(HaveKeyWithValue("decisions", "models:decisions"))
Expect(field.AutocompleteBy.Providers).To(HaveKeyWithValue("colbert", "models:rerank"))
Expect(field.AutocompleteProvider).To(Equal(meta.ProviderModelsScore))
}
}
})
})
var _ = Describe("backend-only upscale options", func() {
It("does not expose scale or tile size as generic root configuration", func() {
reg := meta.DefaultRegistry()
Expect(reg).NotTo(HaveKey("upscale_scale"))
Expect(reg).NotTo(HaveKey("upscale_tile_size"))
md := meta.BuildForTest(reflect.TypeOf(config.ModelConfig{}), reg)
for _, field := range md.Fields {
Expect(field.Path).NotTo(BeElementOf("upscale_scale", "upscale_tile_size"))
}
})
})