Inspect requirements by profile identity
This commit is contained in:
@@ -44,11 +44,14 @@ collaborators. The root [`Engine.InspectPrompt`](../../engine.go) GoDoc owns
|
|||||||
the public operation's exact contract.
|
the public operation's exact contract.
|
||||||
|
|
||||||
`InspectRequirements` uses the same prompt selection boundary, then selects the
|
`InspectRequirements` uses the same prompt selection boundary, then selects the
|
||||||
request profile or prompt default for identity and obtains the exact captured
|
request profile or prompt default through an optional identity-only repository
|
||||||
requirement snapshot. It analyzes that snapshot with the supplied caller
|
capability, then obtains the exact captured requirement snapshot. Internal
|
||||||
variables and normalized direct-session bypass; it does not resolve target
|
repositories without that capability use the full-profile selection boundary;
|
||||||
readiness or enter the preparation pipeline. Missing snapshot capability is a
|
both paths preserve the exact selected ID, and the fallback retains its
|
||||||
prompt-load failure rather than a source fallback. The root
|
profile/target validity checks. It analyzes the snapshot with the supplied
|
||||||
|
caller variables and normalized direct-session bypass; it does not resolve
|
||||||
|
target readiness or enter the preparation pipeline. Missing snapshot
|
||||||
|
capability is a prompt-load failure rather than a source fallback. The root
|
||||||
[`Engine.InspectRequirements`](../../requirements.go) GoDoc owns the public
|
[`Engine.InspectRequirements`](../../requirements.go) GoDoc owns the public
|
||||||
operation's exact contract.
|
operation's exact contract.
|
||||||
|
|
||||||
|
|||||||
@@ -15,16 +15,27 @@ type resolvedProfileSelection struct {
|
|||||||
profile *domain.ExecutionProfile
|
profile *domain.ExecutionProfile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type profileIdentityRepository interface {
|
||||||
|
GetProfileIdentity(context.Context, string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Runner) profileLookupID(profileID string) (string, error) {
|
||||||
|
if strings.TrimSpace(profileID) == "" {
|
||||||
|
return "", fmt.Errorf("%w: profile id is required", ErrInvalidRequest)
|
||||||
|
}
|
||||||
|
if r == nil || r.profiles == nil {
|
||||||
|
return "", fmt.Errorf("%w: profile repository is not configured", ErrProfileLoad)
|
||||||
|
}
|
||||||
|
return profileID, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Runner) resolveProfileSelection(
|
func (r *Runner) resolveProfileSelection(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
profileID string,
|
profileID string,
|
||||||
) (*resolvedProfileSelection, error) {
|
) (*resolvedProfileSelection, error) {
|
||||||
lookupID := profileID
|
lookupID, err := r.profileLookupID(profileID)
|
||||||
if strings.TrimSpace(lookupID) == "" {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%w: profile id is required", ErrInvalidRequest)
|
return nil, err
|
||||||
}
|
|
||||||
if r == nil || r.profiles == nil {
|
|
||||||
return nil, fmt.Errorf("%w: profile repository is not configured", ErrProfileLoad)
|
|
||||||
}
|
}
|
||||||
selectedProfile, err := r.profiles.GetProfile(ctx, lookupID)
|
selectedProfile, err := r.profiles.GetProfile(ctx, lookupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -45,6 +56,25 @@ func (r *Runner) resolveProfileSelection(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Runner) resolveProfileIdentity(ctx context.Context, profileID string) (string, error) {
|
||||||
|
lookupID, err := r.profileLookupID(profileID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if indexed, ok := r.profiles.(profileIdentityRepository); ok {
|
||||||
|
identity, err := indexed.GetProfileIdentity(ctx, lookupID)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("%w: %w", ErrProfileLoad, err)
|
||||||
|
}
|
||||||
|
return identity, nil
|
||||||
|
}
|
||||||
|
selection, err := r.resolveProfileSelection(ctx, lookupID)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return selection.id, nil
|
||||||
|
}
|
||||||
|
|
||||||
func normalizeResolvedExecutionTarget(target domain.ExecutionTarget) (domain.ExecutionTarget, error) {
|
func normalizeResolvedExecutionTarget(target domain.ExecutionTarget) (domain.ExecutionTarget, error) {
|
||||||
endpoint, err := domain.NormalizeOpenAICompatibleBaseEndpoint(target.Endpoint)
|
endpoint, err := domain.NormalizeOpenAICompatibleBaseEndpoint(target.Endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ func (r *Runner) InspectRequirements(
|
|||||||
if strings.TrimSpace(selectedProfileID) == "" {
|
if strings.TrimSpace(selectedProfileID) == "" {
|
||||||
return nil, fmt.Errorf("%w: %w: profile id is required either in request or prompt default_profile", ErrInvalidRequest, ErrProfileRequired)
|
return nil, fmt.Errorf("%w: %w: profile id is required either in request or prompt default_profile", ErrInvalidRequest, ErrProfileRequired)
|
||||||
}
|
}
|
||||||
profileSelection, err := r.resolveProfileSelection(ctx, selectedProfileID)
|
profileIdentity, err := r.resolveProfileIdentity(ctx, selectedProfileID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -74,6 +74,6 @@ func (r *Runner) InspectRequirements(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%w: %w", ErrPromptLoad, err)
|
return nil, fmt.Errorf("%w: %w", ErrPromptLoad, err)
|
||||||
}
|
}
|
||||||
inspection.ProfileID = profileSelection.id
|
inspection.ProfileID = profileIdentity
|
||||||
return &inspection, nil
|
return &inspection, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,23 @@ type requirementInspectionPromptRepository struct {
|
|||||||
snapshotVersion string
|
snapshotVersion string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type inspectionProfileIdentityRepository struct {
|
||||||
|
*inspectionProfileRepository
|
||||||
|
identity string
|
||||||
|
identityErr error
|
||||||
|
identityID string
|
||||||
|
identityCalls int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repository *inspectionProfileIdentityRepository) GetProfileIdentity(
|
||||||
|
_ context.Context,
|
||||||
|
id string,
|
||||||
|
) (string, error) {
|
||||||
|
repository.identityCalls++
|
||||||
|
repository.identityID = id
|
||||||
|
return repository.identity, repository.identityErr
|
||||||
|
}
|
||||||
|
|
||||||
func (repository *requirementInspectionPromptRepository) GetPromptDefinition(
|
func (repository *requirementInspectionPromptRepository) GetPromptDefinition(
|
||||||
context.Context,
|
context.Context,
|
||||||
string,
|
string,
|
||||||
@@ -94,6 +111,68 @@ func TestRunnerInspectRequirementsUsesCapturedSelectionWithoutExecutionWork(t *t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRunnerInspectRequirementsUsesProfileIdentityCapabilityOrFallback(t *testing.T) {
|
||||||
|
message, err := prompt.CompileTemplate("message", `{{.name}}`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
definition := &domain.PromptDefinition{ID: "selected", Version: "v1"}
|
||||||
|
makePromptRepository := func() *requirementInspectionPromptRepository {
|
||||||
|
return &requirementInspectionPromptRepository{
|
||||||
|
definition: definition, snapshotFound: true,
|
||||||
|
snapshot: prompt.RequirementSnapshot{Templates: prompt.CompiledTemplates{Messages: []*template.Template{message}}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestedID := " literal-profile "
|
||||||
|
|
||||||
|
t.Run("optional capability", func(t *testing.T) {
|
||||||
|
profiles := &inspectionProfileIdentityRepository{
|
||||||
|
inspectionProfileRepository: &inspectionProfileRepository{profile: &domain.ExecutionProfile{
|
||||||
|
ID: "repository-profile", ResolvedTarget: &domain.ExecutionTarget{},
|
||||||
|
}},
|
||||||
|
identity: requestedID,
|
||||||
|
}
|
||||||
|
inspection, err := (&Runner{promptDefs: makePromptRepository(), profiles: profiles}).InspectRequirements(
|
||||||
|
context.Background(), RequirementInspectionRequest{
|
||||||
|
PromptID: "selected", ProfileID: requestedID, Vars: map[string]string{"name": "Ada"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil || inspection.ProfileID != requestedID || profiles.identityCalls != 1 ||
|
||||||
|
profiles.identityID != requestedID || profiles.calls != 0 {
|
||||||
|
t.Fatalf("identity capability inspection=(%+v, %v), capability calls=%d id=%q full lookups=%d",
|
||||||
|
inspection, err, profiles.identityCalls, profiles.identityID, profiles.calls)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("full-profile fallback", func(t *testing.T) {
|
||||||
|
profiles := &inspectionProfileRepository{profile: &domain.ExecutionProfile{
|
||||||
|
ID: "repository-profile", ResolvedTarget: &domain.ExecutionTarget{},
|
||||||
|
}}
|
||||||
|
inspection, err := (&Runner{promptDefs: makePromptRepository(), profiles: profiles}).InspectRequirements(
|
||||||
|
context.Background(), RequirementInspectionRequest{
|
||||||
|
PromptID: "selected", ProfileID: requestedID, Vars: map[string]string{"name": "Ada"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil || inspection.ProfileID != requestedID || profiles.calls != 1 || profiles.id != requestedID {
|
||||||
|
t.Fatalf("fallback inspection=(%+v, %v), full lookup=(%d,%q)", inspection, err, profiles.calls, profiles.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("capability failure", func(t *testing.T) {
|
||||||
|
lookupErr := errors.New("profile identity lookup failed")
|
||||||
|
profiles := &inspectionProfileIdentityRepository{
|
||||||
|
inspectionProfileRepository: &inspectionProfileRepository{},
|
||||||
|
identityErr: lookupErr,
|
||||||
|
}
|
||||||
|
_, err := (&Runner{promptDefs: makePromptRepository(), profiles: profiles}).InspectRequirements(
|
||||||
|
context.Background(), RequirementInspectionRequest{PromptID: "selected", ProfileID: requestedID},
|
||||||
|
)
|
||||||
|
if !errors.Is(err, ErrProfileLoad) || !errors.Is(err, lookupErr) || profiles.identityCalls != 1 || profiles.calls != 0 {
|
||||||
|
t.Fatalf("capability failure=(%v), capability calls=%d full lookups=%d", err, profiles.identityCalls, profiles.calls)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestRunnerInspectRequirementsUsesPromptDefaultAndIncludesSessionWhenNotBypassed(t *testing.T) {
|
func TestRunnerInspectRequirementsUsesPromptDefaultAndIncludesSessionWhenNotBypassed(t *testing.T) {
|
||||||
message, err := prompt.CompileTemplate("message", `{{input "message-input"}}`)
|
message, err := prompt.CompileTemplate("message", `{{input "message-input"}}`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user