package consumers import ( "strings" configkit "gitea.maximumdirect.net/eric/ConfigKit" ) // PromptCatalogConfig is an application-owned prompt collection shape. type PromptCatalogConfig struct { Prompts []PromptRecord `yaml:"prompts"` } // PromptRecord keeps its identity and message meaning in the consumer. type PromptRecord struct { ID string `yaml:"id"` Name string `yaml:"name"` Messages []string `yaml:"messages"` } // LoadPromptCatalog composes explicitly registered prompt records in the main // tier and replaces the lower-priority default collection as a whole. func LoadPromptCatalog(mainPath string) (*configkit.Result[PromptCatalogConfig], error) { return configkit.LoadLayered(configkit.Input{ Source: configkit.File(mainPath), Imports: true, }, configkit.LayeredOptions[PromptCatalogConfig]{ Underlays: []configkit.Underlay{{Inputs: []configkit.Input{{ Source: configkit.Bytes("default prompts", []byte("prompts:\n - id: default\n name: Default prompt\n messages: [Default message]\n")), }}}}, Definition: configkit.Definition[PromptCatalogConfig]{ SequenceCompositions: []configkit.SequenceComposition{{ Path: configkit.Keys("prompts"), IdentityField: "id", }}, Validate: validatePromptCatalog, }, }) } func validatePromptCatalog(configuration *PromptCatalogConfig, validation *configkit.Validation) { for index, prompt := range configuration.Prompts { if strings.TrimSpace(prompt.Name) == "" { validation.Error(configkit.Keys("prompts").Index(index).Key("name"), "must not be empty") } if len(prompt.Messages) == 0 { validation.Error(configkit.Keys("prompts").Index(index).Key("messages"), "must contain at least one message") } } if len(configuration.Prompts) == 0 { validation.Error(configkit.Keys("prompts"), "must contain at least one prompt") } }