Add typed prompt sources and backend inheritance
This commit is contained in:
@@ -19,10 +19,13 @@ const BackendLocal = "local"
|
||||
// explicit zero or blank values. A nil ExtraParams map is omitted; a non-nil
|
||||
// empty map supplies an empty mapping. A nil SmokeTests pointer is omitted; a
|
||||
// non-nil pointer supplies a smoke_tests mapping. Use raw ConfigKit Mapping
|
||||
// inputs for explicit null. BackendConfig has no stable JSON representation.
|
||||
// inputs for explicit null. Extends names a sibling backend in the same list.
|
||||
// BackendConfig has no stable JSON representation.
|
||||
type BackendConfig struct {
|
||||
// ID is the local backend identity within its resource list.
|
||||
ID string
|
||||
// Extends names a sibling backend to inherit through ConfigKit.
|
||||
Extends *string
|
||||
// Endpoint is the required absolute HTTP(S) base URL after all layers merge.
|
||||
Endpoint *string
|
||||
// APIKeyEnv optionally names an environment variable, not a credential.
|
||||
@@ -84,6 +87,9 @@ func BackendSource(label string, backends []BackendConfig) configkit.Source {
|
||||
definitions := make([]any, 0, len(backends))
|
||||
for _, config := range backends {
|
||||
fields := map[string]any{"id": config.ID}
|
||||
if config.Extends != nil {
|
||||
fields["extends"] = map[string]any{"id": *config.Extends}
|
||||
}
|
||||
if config.Endpoint != nil {
|
||||
fields["endpoint"] = *config.Endpoint
|
||||
}
|
||||
|
||||
@@ -470,6 +470,10 @@ Do not introduce benchmark thresholds or additional release gates.
|
||||
|
||||
## Stage 9: Add Typed Backend Inheritance And Prompt Sources
|
||||
|
||||
**Completed:** Backend inheritance and the typed prompt mapping constructor
|
||||
follow the existing ConfigKit source pattern. Existing focused programmatic
|
||||
source and inspection tests pass; composition coverage follows next.
|
||||
|
||||
**Scope:** Public mapping-constructor implementation and GoDoc.
|
||||
|
||||
1. Add `Extends *string` to `BackendConfig` and encode it in `BackendSource`
|
||||
|
||||
129
prompts.go
Normal file
129
prompts.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package promptkit
|
||||
|
||||
import "go.maximumdirect.net/configkit"
|
||||
|
||||
// PromptConfig is a presence-aware source input for one prompt. Extends names
|
||||
// a sibling prompt. Nil optional pointers and slices are omitted; non-nil
|
||||
// pointers and slices preserve explicit zero, blank, and empty values. These
|
||||
// inputs are mapping constructors, not serialized inspection values. Raw
|
||||
// ConfigKit mappings can express explicit null and other composition controls.
|
||||
type PromptConfig struct {
|
||||
ID string
|
||||
Extends, DefaultProfile, Description, SessionID *string
|
||||
Inputs []PromptInputConfig
|
||||
Messages []PromptMessageConfig
|
||||
Output *PromptOutputConfig
|
||||
}
|
||||
|
||||
// PromptInputConfig supplies an input declaration. Name is always supplied;
|
||||
// nil optional pointers omit their fields.
|
||||
type PromptInputConfig struct {
|
||||
Name string
|
||||
Required *bool
|
||||
ContentType, Description *string
|
||||
}
|
||||
|
||||
// PromptMessageConfig supplies message fields, including inline content or a
|
||||
// content-file reference. Final content selection is validated by NewEngine.
|
||||
type PromptMessageConfig struct {
|
||||
Role, Content, ContentFile *string
|
||||
CacheControl *PromptCacheControlConfig
|
||||
}
|
||||
|
||||
// PromptCacheControlConfig supplies optional cache-control source fields.
|
||||
type PromptCacheControlConfig struct{ Type, TTL *string }
|
||||
|
||||
// PromptOutputConfig supplies optional output contract source fields.
|
||||
type PromptOutputConfig struct {
|
||||
Format, ValidationMode, SchemaPath *string
|
||||
RepairAttempts *int
|
||||
}
|
||||
|
||||
// PromptSource creates a labeled ConfigKit mapping in caller order. Nil
|
||||
// top-level input supplies an empty prompts sequence. Records may be partial:
|
||||
// sibling inheritance and layered sources can complete them before NewEngine
|
||||
// validates the final configuration. Mapping snapshots supported values when
|
||||
// constructed; the helper neither resolves inheritance nor reads files.
|
||||
// Relative content files use the ConfigKit Input filesystem context of the
|
||||
// contributing field. Raw mappings remain available for explicit null and
|
||||
// generic ConfigKit operations.
|
||||
func PromptSource(label string, prompts []PromptConfig) configkit.Source {
|
||||
definitions := make([]any, 0, len(prompts))
|
||||
for _, config := range prompts {
|
||||
fields := map[string]any{"id": config.ID}
|
||||
if config.Extends != nil {
|
||||
fields["extends"] = map[string]any{"id": *config.Extends}
|
||||
}
|
||||
if config.DefaultProfile != nil {
|
||||
fields["default_profile"] = *config.DefaultProfile
|
||||
}
|
||||
if config.Description != nil {
|
||||
fields["description"] = *config.Description
|
||||
}
|
||||
if config.SessionID != nil {
|
||||
fields["session_id"] = *config.SessionID
|
||||
}
|
||||
if config.Inputs != nil {
|
||||
inputs := make([]any, 0, len(config.Inputs))
|
||||
for _, input := range config.Inputs {
|
||||
item := map[string]any{"name": input.Name}
|
||||
if input.Required != nil {
|
||||
item["required"] = *input.Required
|
||||
}
|
||||
if input.ContentType != nil {
|
||||
item["content_type"] = *input.ContentType
|
||||
}
|
||||
if input.Description != nil {
|
||||
item["description"] = *input.Description
|
||||
}
|
||||
inputs = append(inputs, item)
|
||||
}
|
||||
fields["inputs"] = inputs
|
||||
}
|
||||
if config.Messages != nil {
|
||||
messages := make([]any, 0, len(config.Messages))
|
||||
for _, message := range config.Messages {
|
||||
item := make(map[string]any)
|
||||
if message.Role != nil {
|
||||
item["role"] = *message.Role
|
||||
}
|
||||
if message.Content != nil {
|
||||
item["content"] = *message.Content
|
||||
}
|
||||
if message.ContentFile != nil {
|
||||
item["content_file"] = *message.ContentFile
|
||||
}
|
||||
if message.CacheControl != nil {
|
||||
cache := make(map[string]any)
|
||||
if message.CacheControl.Type != nil {
|
||||
cache["type"] = *message.CacheControl.Type
|
||||
}
|
||||
if message.CacheControl.TTL != nil {
|
||||
cache["ttl"] = *message.CacheControl.TTL
|
||||
}
|
||||
item["cache_control"] = cache
|
||||
}
|
||||
messages = append(messages, item)
|
||||
}
|
||||
fields["messages"] = messages
|
||||
}
|
||||
if config.Output != nil {
|
||||
output := make(map[string]any)
|
||||
if config.Output.Format != nil {
|
||||
output["format"] = *config.Output.Format
|
||||
}
|
||||
if config.Output.ValidationMode != nil {
|
||||
output["validation_mode"] = *config.Output.ValidationMode
|
||||
}
|
||||
if config.Output.SchemaPath != nil {
|
||||
output["schema_path"] = *config.Output.SchemaPath
|
||||
}
|
||||
if config.Output.RepairAttempts != nil {
|
||||
output["repair_attempts"] = *config.Output.RepairAttempts
|
||||
}
|
||||
fields["output"] = output
|
||||
}
|
||||
definitions = append(definitions, fields)
|
||||
}
|
||||
return configkit.Mapping(label, map[string]any{"prompts": definitions})
|
||||
}
|
||||
Reference in New Issue
Block a user