101 lines
2.8 KiB
Go
101 lines
2.8 KiB
Go
package usecase
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
|
|
)
|
|
|
|
type resolvedProfileSelection struct {
|
|
id string
|
|
profile *domain.ExecutionProfile
|
|
backend *domain.Backend
|
|
}
|
|
|
|
func (r *Runner) resolveProfileSelection(
|
|
ctx context.Context,
|
|
profileID string,
|
|
) (*resolvedProfileSelection, error) {
|
|
normalizedID := strings.TrimSpace(profileID)
|
|
if normalizedID == "" {
|
|
return nil, fmt.Errorf("%w: profile id is required", ErrInvalidRequest)
|
|
}
|
|
if r == nil || r.profiles == nil {
|
|
return nil, fmt.Errorf("%w: profile repository is not configured", ErrProfileLoad)
|
|
}
|
|
|
|
selectedProfile, err := r.profiles.GetProfile(ctx, normalizedID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: %w", ErrProfileLoad, err)
|
|
}
|
|
if selectedProfile == nil {
|
|
return nil, fmt.Errorf("%w: profile repository returned nil profile", ErrProfileLoad)
|
|
}
|
|
|
|
profileValue := *selectedProfile
|
|
profileValue.BackendID = strings.TrimSpace(profileValue.BackendID)
|
|
|
|
var selectedBackend *domain.Backend
|
|
if profileValue.BackendID != "" {
|
|
if r.backends == nil {
|
|
return nil, fmt.Errorf("%w: backend %q cannot be resolved", ErrProfileLoad, profileValue.BackendID)
|
|
}
|
|
backendValue, err := r.backends.GetBackend(profileValue.BackendID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: backend %q: %w", ErrProfileLoad, profileValue.BackendID, err)
|
|
}
|
|
selectedBackend = &backendValue
|
|
}
|
|
|
|
return &resolvedProfileSelection{
|
|
id: normalizedID,
|
|
profile: &profileValue,
|
|
backend: selectedBackend,
|
|
}, nil
|
|
}
|
|
|
|
func validateResolvedExecutionTarget(target domain.ExecutionTarget) error {
|
|
if strings.TrimSpace(target.Endpoint) == "" {
|
|
return errors.New("execution endpoint is required")
|
|
}
|
|
if strings.TrimSpace(target.Model) == "" {
|
|
return errors.New("execution model is required")
|
|
}
|
|
return domain.ValidateExecutionTargetSettings(target)
|
|
}
|
|
|
|
// InspectProfile resolves one explicit profile without prompt or execution work.
|
|
func (r *Runner) InspectProfile(
|
|
ctx context.Context,
|
|
profileID string,
|
|
) (*domain.ProfileInspection, error) {
|
|
normalizedID := strings.TrimSpace(profileID)
|
|
if normalizedID == "" {
|
|
return nil, fmt.Errorf("%w: profile id is required", ErrInvalidRequest)
|
|
}
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil, fmt.Errorf("%w: %w", ErrProfileLoad, ctx.Err())
|
|
default:
|
|
}
|
|
|
|
selection, err := r.resolveProfileSelection(ctx, normalizedID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
target, _ := resolveExecutionTarget(selection.backend, selection.profile, nil)
|
|
if err := validateResolvedExecutionTarget(target); err != nil {
|
|
return nil, fmt.Errorf("%w: %w", ErrProfileLoad, err)
|
|
}
|
|
target.APIKey = ""
|
|
|
|
return &domain.ProfileInspection{
|
|
ProfileID: selection.id,
|
|
EffectiveModelParams: target,
|
|
APIKeyRequired: target.APIKeyRequired,
|
|
}, nil
|
|
}
|