42 lines
1.8 KiB
Go
42 lines
1.8 KiB
Go
package domain
|
|
|
|
import (
|
|
"fmt"
|
|
"git.cin.su/m/Assistant/contracts/configuration"
|
|
"sort"
|
|
)
|
|
|
|
var ErrInvalidConfigurationCommand = fmt.Errorf("invalid conversational configuration command")
|
|
|
|
func Resolve(definition configuration.SettingDefinition, assignments []configuration.SettingAssignment, selector configuration.ScopeSelector) (configuration.EffectiveSetting, error) {
|
|
if err := definition.Validate(); err != nil {
|
|
return configuration.EffectiveSetting{}, err
|
|
}
|
|
var matches []configuration.SettingAssignment
|
|
for _, a := range assignments {
|
|
if err := a.Validate(); err != nil {
|
|
return configuration.EffectiveSetting{}, err
|
|
}
|
|
if a.DefinitionRef == string(definition.ID) && a.Lifecycle == configuration.SettingActive && a.Selector.PrincipalRef == selector.PrincipalRef && a.Selector.SkillRef == selector.SkillRef {
|
|
matches = append(matches, a)
|
|
}
|
|
}
|
|
if len(matches) == 0 {
|
|
return configuration.EffectiveSetting{DefinitionRef: string(definition.ID), Value: definition.DefaultValue, ResolutionTrace: []string{"system-default"}}, nil
|
|
}
|
|
sort.SliceStable(matches, func(i, j int) bool { return specificity(matches[i].Selector) > specificity(matches[j].Selector) })
|
|
if len(matches) > 1 && specificity(matches[0].Selector) == specificity(matches[1].Selector) {
|
|
return configuration.EffectiveSetting{}, fmt.Errorf("configuration conflict")
|
|
}
|
|
return configuration.EffectiveSetting{DefinitionRef: string(definition.ID), Value: matches[0].TypedValue, WinningAssignmentRef: string(matches[0].ID), ResolutionTrace: []string{"specificity-selected"}}, nil
|
|
}
|
|
func specificity(s configuration.ScopeSelector) int {
|
|
return len(s.RequiredContextBindings) + boolInt(s.SkillRef != "") + boolInt(s.TaskRef != "") + boolInt(s.SessionRef != "") + boolInt(s.TemporaryOverride)
|
|
}
|
|
func boolInt(v bool) int {
|
|
if v {
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|