Capture resolved backend and profile resources
This commit is contained in:
@@ -278,6 +278,10 @@ not collapse runtime explicit zero or broaden accepted configuration shapes.
|
|||||||
|
|
||||||
## Stage 3: Project Resolved Backend And Profile Resources
|
## Stage 3: Project Resolved Backend And Profile Resources
|
||||||
|
|
||||||
|
**Completed:** Exact-ID resource lookups reuse captured resolved indexes; focused
|
||||||
|
configuration tests cover partial inheritance, explicit values, backend defaults,
|
||||||
|
derived queue capacity, diagnostics, missing IDs, and cancellation.
|
||||||
|
|
||||||
**Scope:** Configuration-owned views and exact-ID resource lookup.
|
**Scope:** Configuration-owned views and exact-ID resource lookup.
|
||||||
|
|
||||||
1. Add private-adapter result structs in `internal/configuration`, with fields
|
1. Add private-adapter result structs in `internal/configuration`, with fields
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ type loaded struct {
|
|||||||
promptMetadata map[string][]promptInputPresence
|
promptMetadata map[string][]promptInputPresence
|
||||||
prompts map[string]*promptEntry
|
prompts map[string]*promptEntry
|
||||||
registry *backend.Registry
|
registry *backend.Registry
|
||||||
|
backendRecords map[string]backendConfig
|
||||||
|
profileRecords map[string]profileConfig
|
||||||
indexedProfiles map[string]domain.ExecutionProfile
|
indexedProfiles map[string]domain.ExecutionProfile
|
||||||
backendIDs []string
|
backendIDs []string
|
||||||
profileIDs []string
|
profileIDs []string
|
||||||
|
|||||||
71
internal/configuration/resources.go
Normal file
71
internal/configuration/resources.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"go.maximumdirect.net/promptkit/internal/backend"
|
||||||
|
"go.maximumdirect.net/promptkit/internal/domain"
|
||||||
|
"go.maximumdirect.net/promptkit/internal/profile"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProfileResource is the resolved profile before execution completion.
|
||||||
|
// Its fields borrow immutable configuration captured by the adapter.
|
||||||
|
type ProfileResource struct {
|
||||||
|
ID string
|
||||||
|
Backend, Endpoint, Model *string
|
||||||
|
Temperature, TopP *float64
|
||||||
|
MaxTokens, TimeoutSeconds *int
|
||||||
|
ServiceTier, ReasoningEffort *string
|
||||||
|
APIKeyEnv *string
|
||||||
|
APIKeyRequired *bool
|
||||||
|
ExtraParams map[string]any
|
||||||
|
}
|
||||||
|
|
||||||
|
// BackendResource is the resolved backend and its configured diagnostics.
|
||||||
|
// Its fields borrow immutable configuration captured by the adapter.
|
||||||
|
type BackendResource struct {
|
||||||
|
ID, Endpoint string
|
||||||
|
APIKeyEnv *string
|
||||||
|
ConcurrencyLimit, QueueCapacity *int
|
||||||
|
ExtraParams map[string]any
|
||||||
|
SmokeTests *domain.BackendSmokeTestConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *loaded) InspectProfile(ctx context.Context, id string) (*ProfileResource, error) {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if state == nil {
|
||||||
|
return nil, fmt.Errorf("%w: %q", profile.ErrProfileNotFound, id)
|
||||||
|
}
|
||||||
|
config, ok := state.profileRecords[id]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%w: %q", profile.ErrProfileNotFound, id)
|
||||||
|
}
|
||||||
|
return &ProfileResource{
|
||||||
|
ID: id, Backend: config.Backend, Endpoint: config.Endpoint, Model: config.Model,
|
||||||
|
Temperature: config.Temperature, TopP: config.TopP, MaxTokens: config.MaxTokens,
|
||||||
|
TimeoutSeconds: config.TimeoutSeconds, ServiceTier: config.ServiceTier,
|
||||||
|
ReasoningEffort: config.ReasoningEffort, APIKeyEnv: config.APIKeyEnv,
|
||||||
|
APIKeyRequired: config.APIKeyRequired, ExtraParams: config.ExtraParams,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (state *loaded) InspectBackend(ctx context.Context, id string) (*BackendResource, error) {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if state == nil {
|
||||||
|
return nil, fmt.Errorf("%w: %q", backend.ErrBackendNotFound, id)
|
||||||
|
}
|
||||||
|
config, ok := state.backendRecords[id]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("%w: %q", backend.ErrBackendNotFound, id)
|
||||||
|
}
|
||||||
|
return &BackendResource{
|
||||||
|
ID: id, Endpoint: valueOrZero(config.Endpoint), APIKeyEnv: config.APIKeyEnv,
|
||||||
|
ConcurrencyLimit: config.ConcurrencyLimit, QueueCapacity: config.QueueCapacity,
|
||||||
|
ExtraParams: config.ExtraParams, SmokeTests: captureBackend(id, config).SmokeTests,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
53
internal/configuration/resources_test.go
Normal file
53
internal/configuration/resources_test.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package configuration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"go.maximumdirect.net/promptkit/internal/backend"
|
||||||
|
"go.maximumdirect.net/promptkit/internal/profile"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResolvedBackendAndProfileResources(t *testing.T) {
|
||||||
|
state, err := load(mapping("resources", map[string]any{
|
||||||
|
"backends": []any{map[string]any{"id": "local", "endpoint": "https://example.test/v1", "concurrency_limit": 2,
|
||||||
|
"extra_params": map[string]any{"backend": true}, "smoke_tests": map[string]any{"default_profile": "missing", "reachability": map[string]any{}}}},
|
||||||
|
"profiles": []any{
|
||||||
|
map[string]any{"id": "parent", "backend": "local", "temperature": 0.4},
|
||||||
|
map[string]any{"id": "child", "extends": map[string]any{"id": "parent"}, "temperature": 0, "endpoint": "", "extra_params": map[string]any{}},
|
||||||
|
},
|
||||||
|
}), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
resource, err := state.InspectProfile(context.Background(), "child")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if resource.ID != "child" || resource.Backend == nil || *resource.Backend != "local" || resource.Endpoint == nil || *resource.Endpoint != "" || resource.Temperature == nil || *resource.Temperature != 0 || resource.Model != nil || resource.ExtraParams == nil || len(resource.ExtraParams) != 0 {
|
||||||
|
t.Fatalf("profile resource = %+v", resource)
|
||||||
|
}
|
||||||
|
target, err := state.GetProfile(context.Background(), "child")
|
||||||
|
if err != nil || target.ResolvedTarget.ExtraParams["backend"] != true {
|
||||||
|
t.Fatalf("execution target = %+v, %v", target, err)
|
||||||
|
}
|
||||||
|
resourceBackend, err := state.InspectBackend(context.Background(), "local")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if resourceBackend.Endpoint != "https://example.test/v1" || resourceBackend.QueueCapacity == nil || *resourceBackend.QueueCapacity != 1024 || resourceBackend.SmokeTests == nil || resourceBackend.SmokeTests.DefaultProfile == nil || *resourceBackend.SmokeTests.DefaultProfile != "missing" || resourceBackend.SmokeTests.Reachability == nil || resourceBackend.SmokeTests.Reachability.Endpoint != nil {
|
||||||
|
t.Fatalf("backend resource = %+v", resourceBackend)
|
||||||
|
}
|
||||||
|
if _, err := state.InspectBackend(context.Background(), "missing"); !errors.Is(err, backend.ErrBackendNotFound) {
|
||||||
|
t.Fatalf("backend error = %v", err)
|
||||||
|
}
|
||||||
|
if _, err := state.InspectProfile(context.Background(), "missing"); !errors.Is(err, profile.ErrProfileNotFound) {
|
||||||
|
t.Fatalf("profile error = %v", err)
|
||||||
|
}
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
cancel()
|
||||||
|
if _, err := state.InspectBackend(ctx, "local"); !errors.Is(err, context.Canceled) {
|
||||||
|
t.Fatalf("cancellation = %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ import (
|
|||||||
func (state *loaded) buildExecutionProfiles() error {
|
func (state *loaded) buildExecutionProfiles() error {
|
||||||
backendConfigs := indexedBackends(&state.result.Config)
|
backendConfigs := indexedBackends(&state.result.Config)
|
||||||
profileConfigs := indexedProfiles(&state.result.Config)
|
profileConfigs := indexedProfiles(&state.result.Config)
|
||||||
|
state.backendRecords = backendConfigs
|
||||||
|
state.profileRecords = profileConfigs
|
||||||
definitions := make(map[string]domain.Backend, len(backendConfigs))
|
definitions := make(map[string]domain.Backend, len(backendConfigs))
|
||||||
for _, id := range sortedKeys(backendConfigs) {
|
for _, id := range sortedKeys(backendConfigs) {
|
||||||
config := backendConfigs[id]
|
config := backendConfigs[id]
|
||||||
|
|||||||
Reference in New Issue
Block a user