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 normalizeResolvedExecutionTarget(target domain.ExecutionTarget) (domain.ExecutionTarget, error) { endpoint, err := domain.NormalizeOpenAICompatibleBaseEndpoint(target.Endpoint) if err != nil { return domain.ExecutionTarget{}, fmt.Errorf("execution endpoint: %w", err) } target.Endpoint = endpoint if strings.TrimSpace(target.Model) == "" { return domain.ExecutionTarget{}, errors.New("execution model is required") } if err := domain.ValidateExecutionTargetSettings(target); err != nil { return domain.ExecutionTarget{}, err } return target, nil } // 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) target, err = normalizeResolvedExecutionTarget(target) if err != nil { return nil, fmt.Errorf("%w: %w", ErrProfileLoad, err) } target.APIKey = "" return &domain.ProfileInspection{ ProfileID: selection.id, EffectiveModelParams: target, APIKeyRequired: target.APIKeyRequired, }, nil }