72 lines
2.1 KiB
Go
72 lines
2.1 KiB
Go
package agentconfig
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"sort"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// Load reads exactly one strict YAML document, normalizes deterministic order,
|
|
// and validates all references before returning.
|
|
func Load(path string) (Catalog, error) {
|
|
file, err := os.Open(path)
|
|
if err != nil {
|
|
return Catalog{}, fmt.Errorf("agentconfig: open catalog: %w", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
decoder := yaml.NewDecoder(file)
|
|
decoder.KnownFields(true)
|
|
var catalog Catalog
|
|
if err := decoder.Decode(&catalog); err != nil {
|
|
return Catalog{}, fmt.Errorf("agentconfig: decode catalog: %w", err)
|
|
}
|
|
var extra any
|
|
if err := decoder.Decode(&extra); err != io.EOF {
|
|
if err == nil {
|
|
return Catalog{}, fmt.Errorf("agentconfig: catalog must contain exactly one YAML document")
|
|
}
|
|
return Catalog{}, fmt.Errorf("agentconfig: decode trailing document: %w", err)
|
|
}
|
|
|
|
return Normalize(catalog)
|
|
}
|
|
|
|
// Normalize applies non-policy defaults and stable ordering, then validates.
|
|
func Normalize(catalog Catalog) (Catalog, error) {
|
|
for i := range catalog.Providers {
|
|
provider := &catalog.Providers[i]
|
|
if provider.VersionProbe.TimeoutMS == 0 {
|
|
provider.VersionProbe.TimeoutMS = DefaultProbeTimeoutMS
|
|
}
|
|
if provider.Authentication.TimeoutMS == 0 {
|
|
provider.Authentication.TimeoutMS = DefaultProbeTimeoutMS
|
|
}
|
|
if len(provider.ModelProbe.Args) > 0 && provider.ModelProbe.TimeoutMS == 0 {
|
|
provider.ModelProbe.TimeoutMS = DefaultProbeTimeoutMS
|
|
}
|
|
sort.Strings(provider.Capabilities)
|
|
}
|
|
for i := range catalog.Profiles {
|
|
if catalog.Profiles[i].MaxConcurrency == 0 {
|
|
catalog.Profiles[i].MaxConcurrency = 1
|
|
}
|
|
sort.Strings(catalog.Profiles[i].Capabilities)
|
|
}
|
|
sort.Slice(catalog.Providers, func(i, j int) bool {
|
|
return catalog.Providers[i].ID < catalog.Providers[j].ID
|
|
})
|
|
sort.Slice(catalog.Models, func(i, j int) bool {
|
|
return catalog.Models[i].ID < catalog.Models[j].ID
|
|
})
|
|
sort.Slice(catalog.Profiles, func(i, j int) bool {
|
|
return catalog.Profiles[i].ID < catalog.Profiles[j].ID
|
|
})
|
|
if err := catalog.Validate(); err != nil {
|
|
return Catalog{}, err
|
|
}
|
|
return catalog, nil
|
|
}
|