< Summary

Information
Class: Orchestrator.Commands.Shared.PredictionServiceCommandSupport
Assembly: Orchestrator
File(s): /home/runner/work/KicktippAi/KicktippAi/src/Orchestrator/Commands/Shared/PredictionServiceCommandSupport.cs
Line coverage
93%
Covered lines: 44
Uncovered lines: 3
Coverable lines: 47
Total lines: 117
Line coverage: 93.6%
Branch coverage
75%
Covered branches: 12
Total branches: 16
Branch coverage: 75%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
CreatePredictionService(...)71.43%141493.75%
UsesLangfusePromptSource(...)100%11100%
NormalizeReasoningEffort(...)100%11100%
CreateModelConfig(...)100%11100%
ResolveModel(...)100%22100%

File(s)

/home/runner/work/KicktippAi/KicktippAi/src/Orchestrator/Commands/Shared/PredictionServiceCommandSupport.cs

#LineLine coverage
 1using EHonda.KicktippAi.Core;
 2using OpenAiIntegration;
 3using Orchestrator.Infrastructure;
 4using Orchestrator.Infrastructure.Factories;
 5using Orchestrator.Infrastructure.Langfuse;
 6using Spectre.Console;
 7
 8namespace Orchestrator.Commands.Shared;
 9
 10internal static class PredictionServiceCommandSupport
 11{
 12    public const string WorldCupDevDefaultModel = "gpt-5-nano";
 13    public const string WorldCupDevDefaultReasoningEffort = "minimal";
 14
 15    public static IPredictionService CreatePredictionService(
 16        IOpenAiServiceFactory openAiServiceFactory,
 17        ILangfusePublicApiClient? langfuseClient,
 18        IAnsiConsole console,
 19        string model,
 20        string competition,
 21        string community,
 22        string communityContext,
 23        string? promptSource,
 24        string? langfusePromptName,
 25        string? langfusePromptLabel,
 26        int? langfusePromptVersion,
 27        string? reasoningEffort,
 28        int? maxOutputTokenCount,
 29        bool bonusPrompt)
 30    {
 131        var metadata = CompetitionResolver.ResolveRuntimeMetadata(
 132            competition,
 133            community,
 134            communityContext,
 135            promptSource,
 136            langfusePromptName,
 137            langfusePromptLabel,
 138            bonusPrompt);
 39
 140        var options = PredictionServiceOptions.FlexProcessingWithStandardFallback with
 141        {
 142            ReasoningEffort = NormalizeReasoningEffort(reasoningEffort),
 143            MaxOutputTokenCount = maxOutputTokenCount ?? PredictionServiceOptions.FlexProcessingWithStandardFallback.Max
 144        };
 45
 146        if (!string.Equals(metadata.PromptSource, CompetitionResolver.LangfusePromptSource, StringComparison.OrdinalIgno
 47        {
 148            return openAiServiceFactory.CreatePredictionService(model, options);
 49        }
 50
 151        if (langfuseClient is null)
 52        {
 053            throw new InvalidOperationException("Langfuse prompt source requires a Langfuse public API client.");
 54        }
 55
 156        var promptName = metadata.PromptName;
 157        if (string.IsNullOrWhiteSpace(promptName))
 58        {
 059            throw new InvalidOperationException("--langfuse-prompt-name is required when --prompt-source langfuse is use
 60        }
 61
 162        var fallbackModel = string.IsNullOrWhiteSpace(metadata.FallbackPromptModel)
 163            ? model
 164            : metadata.FallbackPromptModel;
 65
 166        var templateProvider = new LangfuseTextPromptTemplateProvider(
 167            langfuseClient,
 168            promptName,
 169            string.IsNullOrWhiteSpace(metadata.PromptLabel) ? null : metadata.PromptLabel,
 170            langfusePromptVersion,
 171            promptKind: bonusPrompt ? LangfusePromptKind.Bonus : LangfusePromptKind.Match,
 172            fallbackTemplateProvider: new InstructionsTemplateProvider(PromptsFileProvider.Create()),
 173            fallbackModel: fallbackModel,
 074            fallbackWarning: message => console.MarkupLine($"[yellow]Warning:[/] {Markup.Escape(message)}"));
 75
 176        return openAiServiceFactory.CreatePredictionService(model, options, templateProvider);
 77    }
 78
 79    public static bool UsesLangfusePromptSource(
 80        string competition,
 81        string community,
 82        string communityContext,
 83        string? promptSource,
 84        bool bonusPrompt)
 85    {
 186        var metadata = CompetitionResolver.ResolveRuntimeMetadata(
 187            competition,
 188            community,
 189            communityContext,
 190            promptSource,
 191            langfusePromptName: null,
 192            langfusePromptLabel: null,
 193            bonusPrompt);
 94
 195        return string.Equals(metadata.PromptSource, CompetitionResolver.LangfusePromptSource, StringComparison.OrdinalIg
 96    }
 97
 98    public static string? NormalizeReasoningEffort(string? reasoningEffort)
 99    {
 1100        return PredictionModelConfig.NormalizeReasoningEffort(reasoningEffort);
 101    }
 102
 103    public static PredictionModelConfig CreateModelConfig(string? model, string? reasoningEffort)
 104    {
 1105        return PredictionModelConfig.Create(ResolveModel(model), reasoningEffort);
 106    }
 107
 108    public static string ResolveModel(string? model)
 109    {
 1110        if (!string.IsNullOrWhiteSpace(model))
 111        {
 1112            return model.Trim();
 113        }
 114
 1115        throw new ArgumentException("MODEL is required.", nameof(model));
 116    }
 117}