Separate final configuration record validation
This commit is contained in:
@@ -419,101 +419,110 @@ func validateEffective(config *document, validation *configkit.Validation) {
|
||||
}
|
||||
for _, resources := range sets {
|
||||
for index, backend := range resources.backends {
|
||||
base := resources.bases.backends.Index(index)
|
||||
validateBackendEndpoints(backend, base, validation)
|
||||
if !domain.IsValidLocalResourceKey(backend.ID) {
|
||||
validation.Error(base.Key("id"), "backend ID must be a nonblank local key without a slash")
|
||||
}
|
||||
if backend.Endpoint == nil || *backend.Endpoint == "" {
|
||||
validation.Error(base.Key("endpoint"), "endpoint is required")
|
||||
}
|
||||
if backend.APIKeyEnv != nil && *backend.APIKeyEnv != "" && !envName.MatchString(*backend.APIKeyEnv) {
|
||||
validation.Error(base.Key("api_key_env"), "environment variable name is invalid")
|
||||
}
|
||||
if backend.ConcurrencyLimit != nil && *backend.ConcurrencyLimit < 0 {
|
||||
validation.Error(base.Key("concurrency_limit"), "concurrency limit must not be negative")
|
||||
}
|
||||
if backend.QueueCapacity != nil {
|
||||
if *backend.QueueCapacity < 0 {
|
||||
validation.Error(base.Key("queue_capacity"), "queue capacity must not be negative")
|
||||
}
|
||||
if backend.ConcurrencyLimit == nil || *backend.ConcurrencyLimit <= 0 {
|
||||
validation.Error(base.Key("queue_capacity"), "queue capacity requires a positive concurrency limit")
|
||||
} else if *backend.QueueCapacity > int(^uint(0)>>1)-*backend.ConcurrencyLimit {
|
||||
validation.Error(base.Key("queue_capacity"), "total capacity overflows int")
|
||||
}
|
||||
}
|
||||
validateExtraParams(backend.ExtraParams, base.Key("extra_params"), true, validation)
|
||||
if smokeTests := backend.SmokeTests; smokeTests != nil {
|
||||
smokePath := base.Key("smoke_tests")
|
||||
if smokeTests.DefaultProfile != nil {
|
||||
if strings.TrimSpace(*smokeTests.DefaultProfile) == "" {
|
||||
validation.Error(smokePath.Key("default_profile"), "default profile must not be blank")
|
||||
} else if !domain.IsValidResourceID(*smokeTests.DefaultProfile) {
|
||||
validation.Error(smokePath.Key("default_profile"), "default profile reference is malformed")
|
||||
}
|
||||
}
|
||||
if authentication := smokeTests.Authentication; authentication != nil {
|
||||
kindPath := smokePath.Key("authentication").Key("kind")
|
||||
if authentication.Kind == nil {
|
||||
validation.Error(kindPath, "authentication kind is required")
|
||||
} else if *authentication.Kind != "none" && *authentication.Kind != "openrouter_key" {
|
||||
validation.Error(kindPath, "authentication kind must be none or openrouter_key")
|
||||
}
|
||||
}
|
||||
}
|
||||
validateBackendRecord(backend, resources.bases.backends.Index(index), validation)
|
||||
}
|
||||
for index, profile := range resources.profiles {
|
||||
base := resources.bases.profiles.Index(index)
|
||||
if profile.Endpoint != nil && *profile.Endpoint != "" {
|
||||
if _, err := domain.NormalizeOpenAICompatibleBaseEndpoint(*profile.Endpoint); err != nil {
|
||||
validation.Error(base.Key("endpoint"), err.Error())
|
||||
}
|
||||
}
|
||||
if !domain.IsValidLocalResourceKey(profile.ID) {
|
||||
validation.Error(base.Key("id"), "profile ID must be a nonblank local key without a slash")
|
||||
}
|
||||
if profile.Backend != nil && *profile.Backend != "" {
|
||||
if !domain.IsValidResourceID(*profile.Backend) {
|
||||
validation.Error(base.Key("backend"), "backend reference is malformed")
|
||||
} else if _, exists := backendIDs[*profile.Backend]; !exists {
|
||||
validation.Error(base.Key("backend"), "backend is not defined")
|
||||
}
|
||||
}
|
||||
if profile.Model != nil && *profile.Model != "" && strings.TrimSpace(*profile.Model) == "" {
|
||||
validation.Error(base.Key("model"), "model must not be blank")
|
||||
}
|
||||
if profile.Temperature != nil {
|
||||
if err := domain.ValidateExecutionTargetSettings(domain.ExecutionTarget{Temperature: *profile.Temperature}); err != nil {
|
||||
validation.Error(base.Key("temperature"), err.Error())
|
||||
}
|
||||
}
|
||||
if profile.TopP != nil {
|
||||
if err := domain.ValidateExecutionTargetSettings(domain.ExecutionTarget{TopP: *profile.TopP}); err != nil {
|
||||
validation.Error(base.Key("top_p"), err.Error())
|
||||
}
|
||||
}
|
||||
if profile.MaxTokens != nil {
|
||||
if err := domain.ValidateExecutionTargetSettings(domain.ExecutionTarget{MaxTokens: *profile.MaxTokens}); err != nil {
|
||||
validation.Error(base.Key("max_tokens"), err.Error())
|
||||
}
|
||||
}
|
||||
if profile.TimeoutSeconds != nil {
|
||||
if err := domain.ValidateExecutionTargetSettings(domain.ExecutionTarget{TimeoutSeconds: *profile.TimeoutSeconds}); err != nil {
|
||||
validation.Error(base.Key("timeout_seconds"), err.Error())
|
||||
}
|
||||
}
|
||||
validateExtraParams(profile.ExtraParams, base.Key("extra_params"), false, validation)
|
||||
validateProfileRecord(profile, resources.bases.profiles.Index(index), backendIDs, validation)
|
||||
}
|
||||
for index, prompt := range resources.prompts {
|
||||
base := resources.bases.prompts.Index(index)
|
||||
if !domain.IsValidLocalResourceKey(prompt.ID) {
|
||||
validation.Error(base.Key("id"), "prompt ID must be a nonblank local key without a slash")
|
||||
}
|
||||
if prompt.DefaultProfile != nil && *prompt.DefaultProfile != "" && !domain.IsValidResourceID(*prompt.DefaultProfile) {
|
||||
validation.Error(base.Key("default_profile"), "default profile reference is malformed")
|
||||
validatePromptRecord(prompt, resources.bases.prompts.Index(index), validation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func validateBackendRecord(backend backendConfig, base configkit.Path, validation *configkit.Validation) {
|
||||
validateBackendEndpoints(backend, base, validation)
|
||||
if !domain.IsValidLocalResourceKey(backend.ID) {
|
||||
validation.Error(base.Key("id"), "backend ID must be a nonblank local key without a slash")
|
||||
}
|
||||
if backend.Endpoint == nil || *backend.Endpoint == "" {
|
||||
validation.Error(base.Key("endpoint"), "endpoint is required")
|
||||
}
|
||||
if backend.APIKeyEnv != nil && *backend.APIKeyEnv != "" && !envName.MatchString(*backend.APIKeyEnv) {
|
||||
validation.Error(base.Key("api_key_env"), "environment variable name is invalid")
|
||||
}
|
||||
if backend.ConcurrencyLimit != nil && *backend.ConcurrencyLimit < 0 {
|
||||
validation.Error(base.Key("concurrency_limit"), "concurrency limit must not be negative")
|
||||
}
|
||||
if backend.QueueCapacity != nil {
|
||||
if *backend.QueueCapacity < 0 {
|
||||
validation.Error(base.Key("queue_capacity"), "queue capacity must not be negative")
|
||||
}
|
||||
if backend.ConcurrencyLimit == nil || *backend.ConcurrencyLimit <= 0 {
|
||||
validation.Error(base.Key("queue_capacity"), "queue capacity requires a positive concurrency limit")
|
||||
} else if *backend.QueueCapacity > int(^uint(0)>>1)-*backend.ConcurrencyLimit {
|
||||
validation.Error(base.Key("queue_capacity"), "total capacity overflows int")
|
||||
}
|
||||
}
|
||||
validateExtraParams(backend.ExtraParams, base.Key("extra_params"), true, validation)
|
||||
if smokeTests := backend.SmokeTests; smokeTests != nil {
|
||||
smokePath := base.Key("smoke_tests")
|
||||
if smokeTests.DefaultProfile != nil {
|
||||
if strings.TrimSpace(*smokeTests.DefaultProfile) == "" {
|
||||
validation.Error(smokePath.Key("default_profile"), "default profile must not be blank")
|
||||
} else if !domain.IsValidResourceID(*smokeTests.DefaultProfile) {
|
||||
validation.Error(smokePath.Key("default_profile"), "default profile reference is malformed")
|
||||
}
|
||||
}
|
||||
if authentication := smokeTests.Authentication; authentication != nil {
|
||||
kindPath := smokePath.Key("authentication").Key("kind")
|
||||
if authentication.Kind == nil {
|
||||
validation.Error(kindPath, "authentication kind is required")
|
||||
} else if *authentication.Kind != "none" && *authentication.Kind != "openrouter_key" {
|
||||
validation.Error(kindPath, "authentication kind must be none or openrouter_key")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func validateProfileRecord(profile profileConfig, base configkit.Path, backendIDs map[string]struct{}, validation *configkit.Validation) {
|
||||
if profile.Endpoint != nil && *profile.Endpoint != "" {
|
||||
if _, err := domain.NormalizeOpenAICompatibleBaseEndpoint(*profile.Endpoint); err != nil {
|
||||
validation.Error(base.Key("endpoint"), err.Error())
|
||||
}
|
||||
}
|
||||
if !domain.IsValidLocalResourceKey(profile.ID) {
|
||||
validation.Error(base.Key("id"), "profile ID must be a nonblank local key without a slash")
|
||||
}
|
||||
if profile.Backend != nil && *profile.Backend != "" {
|
||||
if !domain.IsValidResourceID(*profile.Backend) {
|
||||
validation.Error(base.Key("backend"), "backend reference is malformed")
|
||||
} else if _, exists := backendIDs[*profile.Backend]; !exists {
|
||||
validation.Error(base.Key("backend"), "backend is not defined")
|
||||
}
|
||||
}
|
||||
if profile.Model != nil && *profile.Model != "" && strings.TrimSpace(*profile.Model) == "" {
|
||||
validation.Error(base.Key("model"), "model must not be blank")
|
||||
}
|
||||
if profile.Temperature != nil {
|
||||
if err := domain.ValidateExecutionTargetSettings(domain.ExecutionTarget{Temperature: *profile.Temperature}); err != nil {
|
||||
validation.Error(base.Key("temperature"), err.Error())
|
||||
}
|
||||
}
|
||||
if profile.TopP != nil {
|
||||
if err := domain.ValidateExecutionTargetSettings(domain.ExecutionTarget{TopP: *profile.TopP}); err != nil {
|
||||
validation.Error(base.Key("top_p"), err.Error())
|
||||
}
|
||||
}
|
||||
if profile.MaxTokens != nil {
|
||||
if err := domain.ValidateExecutionTargetSettings(domain.ExecutionTarget{MaxTokens: *profile.MaxTokens}); err != nil {
|
||||
validation.Error(base.Key("max_tokens"), err.Error())
|
||||
}
|
||||
}
|
||||
if profile.TimeoutSeconds != nil {
|
||||
if err := domain.ValidateExecutionTargetSettings(domain.ExecutionTarget{TimeoutSeconds: *profile.TimeoutSeconds}); err != nil {
|
||||
validation.Error(base.Key("timeout_seconds"), err.Error())
|
||||
}
|
||||
}
|
||||
validateExtraParams(profile.ExtraParams, base.Key("extra_params"), false, validation)
|
||||
}
|
||||
|
||||
func validatePromptRecord(prompt promptConfig, base configkit.Path, validation *configkit.Validation) {
|
||||
if !domain.IsValidLocalResourceKey(prompt.ID) {
|
||||
validation.Error(base.Key("id"), "prompt ID must be a nonblank local key without a slash")
|
||||
}
|
||||
if prompt.DefaultProfile != nil && *prompt.DefaultProfile != "" && !domain.IsValidResourceID(*prompt.DefaultProfile) {
|
||||
validation.Error(base.Key("default_profile"), "default profile reference is malformed")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user