< Summary

Information
Class: UIBlazor.Services.SystemPromptBuilder
Assembly: UIBlazor
File(s): /home/runner/work/InvAit/InvAit/UIBlazor/Services/SystemPromptBuilder.cs
Tag: 71_26091983037
Line coverage
98%
Covered lines: 70
Uncovered lines: 1
Coverable lines: 71
Total lines: 134
Line coverage: 98.5%
Branch coverage
96%
Covered branches: 29
Total branches: 30
Branch coverage: 96.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Options()100%11100%
PrepareSystemPromptAsync()100%1616100%
BuildSolutionFiles(...)92.85%141496.15%

File(s)

/home/runner/work/InvAit/InvAit/UIBlazor/Services/SystemPromptBuilder.cs

#LineLine coverage
 1using UIBlazor.Services.Settings;
 2
 3namespace UIBlazor.Services;
 4
 115public class SystemPromptBuilder(
 116    ICommonSettingsProvider commonSettingsProvider,
 117    IProfileManager profileManager,
 118    IToolManager toolManager,
 119    ISkillService skillService,
 1110    IRuleService ruleService,
 1111    IVsCodeContextService vsCodeContextService) : ISystemPromptBuilder
 12{
 813    public ConnectionProfile Options => profileManager.ActiveProfile;
 14
 15    public async Task<string> PrepareSystemPromptAsync(AppMode mode, CancellationToken cancellationToken)
 16    {
 17        // Загружаем метаданные скиллов и добавляем в системный промпт
 718        var skillsMetadata = await skillService.GetSkillsMetadataAsync(cancellationToken);
 719        var skillsSection = skillService.FormatSkillsForSystemPrompt(skillsMetadata);
 20
 721        var contextSection = new StringBuilder();
 722        var currentContext = vsCodeContextService.CurrentContext;
 723        if (currentContext != null)
 24        {
 425            var codeContext = new List<string>();
 426            if (commonSettingsProvider.Current.SendSolutionsStricture && currentContext.SolutionFiles.Count > 0)
 27            {
 228                codeContext.Add($"""
 229                                Solution structure:
 230                                ```
 231                                {BuildSolutionFiles(currentContext, true)}
 232                                ```
 233                                """);
 34            }
 435            if (commonSettingsProvider.Current.SendCurrentFile && !string.IsNullOrEmpty(currentContext.ActiveFilePath))
 36            {
 237                codeContext.Add($"""
 238                                ## Current (active) file
 239                                - Path: {currentContext.ActiveFilePath}
 240                                - Selected lines: {currentContext.SelectionStartLine} - {currentContext.SelectionEndLine
 241                                ```
 242                                {currentContext.ActiveFileContent}
 243                                ```
 244                                """);
 45            }
 446            if (codeContext.Count > 0)
 47            {
 348                contextSection.AppendLine("# CURRENT CODE CONTEXT");
 1449                foreach (var item in codeContext)
 50                {
 451                    contextSection.AppendLine(item);
 52                }
 53            }
 54        }
 55
 56        // Загружаем правила
 757        var rules = await ruleService.GetRulesAsync(cancellationToken);
 58        // файл agents.md
 759        var agents = await ruleService.GetAgentsMdAsync(cancellationToken);
 60
 761        List<string?> systemPromptBlocks = [Options.SystemPrompt,
 762            toolManager.GetToolUseSystemInstructions(mode, skillsMetadata.Count != 0),
 763            skillsSection,
 764            contextSection.ToString(),
 765            rules,
 766            !string.IsNullOrEmpty(agents) ? string.Join("# Agents instructions\n", agents) : null,
 767            $"Current date: {DateTime.Now:f}"];
 68
 5669        return string.Join(Environment.NewLine, systemPromptBlocks.Where(b => !string.IsNullOrEmpty(b)));
 770    }
 71
 72    public string BuildSolutionFiles(VsCodeContext currentContext, bool compress)
 73    {
 574        var sb = new StringBuilder();
 575        var lastDir = string.Empty;
 576        var difPrefix = VsCodeContext.DirPrefix.AsSpan();
 5277        foreach (var item in currentContext.SolutionFiles)
 78        {
 2179            if (compress)
 80            {
 2181                var itemSpan = item.AsSpan();
 2182                var pathIndex = -1;
 2183                if (item.StartsWith("Project"))
 84                {
 285                    lastDir = currentContext.SolutionPath;
 86                }
 87                else
 88                {
 1989                    pathIndex = item.IndexOf(VsCodeContext.DirPrefix);
 90                }
 91
 2192                if (pathIndex != -1)
 93                {
 94                    // Берем часть после префикса и обрезаем пробелы без создания строк
 795                    var pathPart = itemSpan[(pathIndex + difPrefix.Length)..].TrimStart();
 796                    lastDir = pathPart.ToString();
 97                    // В строке с префиксом (папкой) выводим item целиком
 798                    sb.Append(item).Append('\n');
 99                }
 100                else
 101                {
 14102                    var simplified = false;
 14103                    if (!string.IsNullOrEmpty(lastDir))
 104                    {
 105                        // Ищем, где в строке файла начинается путь.
 106                        // Если формат файла похож на папку (есть какой-то отступ/префикс),
 107                        // нужно найти индекс начала пути. Допустим, он всегда после какого-то символа
 108                        // или просто ищем вхождение lastDir.
 12109                        var dirPos = item.IndexOf(lastDir);
 12110                        if (dirPos != -1)
 111                        {
 112                            // Пишем всё ДО пути + сам файл ПОСЛЕ пути
 11113                            sb.Append(itemSpan[..dirPos])
 11114                              .Append(itemSpan[(dirPos + lastDir.Length + (lastDir[^1] == '\\' ? 0 : 1))..])
 11115                              .Append('\n');
 11116                            simplified = true;
 117                        }
 118                    }
 119
 14120                    if (!simplified)
 121                    {
 3122                        sb.Append(item).Append('\n');
 123                    }
 124                }
 125            }
 126            else
 127            {
 0128                sb.Append(item).Append('\n');
 129            }
 130        }
 131
 5132        return sb.ToString();
 133    }
 134}