Build presence-aware execution targets from effective configuration
This commit is contained in:
@@ -36,6 +36,9 @@ func (r *Runner) resolveProfileSelection(
|
||||
}
|
||||
|
||||
profileValue := *selectedProfile
|
||||
if profileValue.ResolvedTarget != nil {
|
||||
return &resolvedProfileSelection{id: normalizedID, profile: &profileValue}, nil
|
||||
}
|
||||
profileValue.BackendID = strings.TrimSpace(profileValue.BackendID)
|
||||
|
||||
var selectedBackend *domain.Backend
|
||||
@@ -92,9 +95,11 @@ func (r *Runner) InspectProfile(
|
||||
return nil, err
|
||||
}
|
||||
target, _ := resolveExecutionTarget(selection.backend, selection.profile, nil)
|
||||
target, err = normalizeResolvedExecutionTarget(target)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %w", ErrProfileLoad, err)
|
||||
if selection.profile.ResolvedTarget == nil {
|
||||
target, err = normalizeResolvedExecutionTarget(target)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %w", ErrProfileLoad, err)
|
||||
}
|
||||
}
|
||||
target.APIKey = ""
|
||||
|
||||
|
||||
85
internal/usecase/resolved_targets_test.go
Normal file
85
internal/usecase/resolved_targets_test.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package usecase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/promptkit/internal/defaults"
|
||||
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
|
||||
)
|
||||
|
||||
func TestInspectProfileAllowsIncompleteResolvedTarget(t *testing.T) {
|
||||
profile := &domain.ExecutionProfile{ID: "partial", ResolvedTarget: &domain.ExecutionTarget{
|
||||
TimeoutSeconds: defaults.ExecutionDefaultTimeoutSeconds,
|
||||
}}
|
||||
runner := &Runner{profiles: staticExecutionProfileRepo{profile: profile}}
|
||||
inspection, err := runner.InspectProfile(context.Background(), "partial")
|
||||
if err != nil {
|
||||
t.Fatalf("partial profile inspection failed: %v", err)
|
||||
}
|
||||
if inspection.EffectiveModelParams.Endpoint != "" || inspection.EffectiveModelParams.Model != "" {
|
||||
t.Fatalf("inspection invented a runnable target: %+v", inspection)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPreparationCompletesResolvedTargetThroughRequestOverrides(t *testing.T) {
|
||||
profile := &domain.ExecutionProfile{ID: "partial", ResolvedTarget: &domain.ExecutionTarget{
|
||||
TimeoutSeconds: defaults.ExecutionDefaultTimeoutSeconds,
|
||||
Temperature: 0, ExtraParams: map[string]any{"configured": true},
|
||||
}, TargetPresence: domain.ExecutionTargetPresence{Temperature: true}}
|
||||
runner := &Runner{
|
||||
promptDefs: staticPromptRepo{def: &domain.PromptDefinition{ID: "prompt", Version: "v1", Validation: domain.OutputContract{
|
||||
Format: domain.FormatText, ValidationMode: domain.ValidationNone,
|
||||
}}},
|
||||
profiles: staticExecutionProfileRepo{profile: profile}, renderer: staticRenderer{},
|
||||
}
|
||||
if _, err := runner.Prepare(context.Background(), domain.RunRequest{PromptID: "prompt", ProfileID: "partial"}); err == nil {
|
||||
t.Fatal("incomplete target was accepted without overrides")
|
||||
}
|
||||
zero := 0.0
|
||||
prepared, err := runner.Prepare(context.Background(), domain.RunRequest{
|
||||
PromptID: "prompt", ProfileID: "partial",
|
||||
Execution: &domain.ExecutionTargetOverride{
|
||||
Endpoint: "https://runtime.example/v1", Model: "runtime-model", Temperature: &zero,
|
||||
ExtraParams: map[string]any{"request": true},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("request did not complete partial target: %v", err)
|
||||
}
|
||||
if prepared.EffectiveModelParams.Endpoint != "https://runtime.example/v1" ||
|
||||
prepared.EffectiveModelParams.Model != "runtime-model" || !prepared.TargetPresence.Temperature ||
|
||||
prepared.EffectiveModelParams.ExtraParams["request"] != true {
|
||||
t.Fatalf("request overrides were not applied: %+v", prepared)
|
||||
}
|
||||
if _, exists := prepared.EffectiveModelParams.ExtraParams["configured"]; exists {
|
||||
t.Fatal("nonempty request provider map did not replace configured map")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvedTargetCredentialAvailability(t *testing.T) {
|
||||
profile := &domain.ExecutionProfile{ID: "direct", ResolvedTarget: &domain.ExecutionTarget{
|
||||
Endpoint: "https://provider.example/v1", Model: "model", APIKeyRequired: true,
|
||||
}}
|
||||
runner := &Runner{
|
||||
promptDefs: staticPromptRepo{def: &domain.PromptDefinition{ID: "prompt", Version: "v1", Validation: domain.OutputContract{
|
||||
Format: domain.FormatText, ValidationMode: domain.ValidationNone,
|
||||
}}},
|
||||
profiles: staticExecutionProfileRepo{profile: profile}, renderer: staticRenderer{},
|
||||
}
|
||||
request := domain.RunRequest{PromptID: "prompt", ProfileID: "direct"}
|
||||
if _, err := runner.Prepare(context.Background(), request); !errors.Is(err, ErrAPIKeyRequired) {
|
||||
t.Fatalf("missing required direct key: %v", err)
|
||||
}
|
||||
request.APIKey = "direct-secret"
|
||||
if _, err := runner.Prepare(context.Background(), request); err != nil {
|
||||
t.Fatalf("direct key should satisfy requirement: %v", err)
|
||||
}
|
||||
request.APIKey = ""
|
||||
t.Setenv("REQUEST_KEY", "runtime-secret")
|
||||
request.Execution = &domain.ExecutionTargetOverride{APIKeyEnv: "REQUEST_KEY"}
|
||||
if _, err := runner.Prepare(context.Background(), request); err != nil {
|
||||
t.Fatalf("request environment override should satisfy requirement: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -620,9 +620,8 @@ func mergeExecutionTarget(base domain.ExecutionTarget, override domain.Execution
|
||||
return out
|
||||
}
|
||||
|
||||
func mergeExecutionTargetOverride(base domain.ExecutionTarget, override domain.ExecutionTargetOverride) (domain.ExecutionTarget, domain.ExecutionTargetPresence) {
|
||||
func mergeExecutionTargetOverride(base domain.ExecutionTarget, presence domain.ExecutionTargetPresence, override domain.ExecutionTargetOverride) (domain.ExecutionTarget, domain.ExecutionTargetPresence) {
|
||||
out := base
|
||||
var presence domain.ExecutionTargetPresence
|
||||
if override.Endpoint != "" {
|
||||
out.Endpoint = override.Endpoint
|
||||
}
|
||||
@@ -661,12 +660,21 @@ func mergeExecutionTargetOverride(base domain.ExecutionTarget, override domain.E
|
||||
}
|
||||
|
||||
func resolveExecutionTarget(backendValue *domain.Backend, profileValue *domain.ExecutionProfile, override *domain.ExecutionTargetOverride) (domain.ExecutionTarget, domain.ExecutionTargetPresence) {
|
||||
if profileValue != nil && profileValue.ResolvedTarget != nil {
|
||||
out := *profileValue.ResolvedTarget
|
||||
out.ExtraParams = copyExtraParams(out.ExtraParams)
|
||||
presence := profileValue.TargetPresence
|
||||
if override != nil {
|
||||
return mergeExecutionTargetOverride(out, presence, *override)
|
||||
}
|
||||
return out, presence
|
||||
}
|
||||
out := defaults.ExecutionTargetDefault()
|
||||
out = mergeExecutionTarget(out, backendToTarget(backendValue))
|
||||
out = mergeExecutionTarget(out, executionProfileToTarget(profileValue))
|
||||
var presence domain.ExecutionTargetPresence
|
||||
if override != nil {
|
||||
out, presence = mergeExecutionTargetOverride(out, *override)
|
||||
out, presence = mergeExecutionTargetOverride(out, presence, *override)
|
||||
}
|
||||
return out, presence
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user