< Summary

Information
Class: NexusLabs.Needlr.AgentFramework.Generators.BootstrapCodeGenerator
Assembly: NexusLabs.Needlr.AgentFramework.Generators
File(s): /home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Generators/CodeGen/BootstrapCodeGenerator.cs
Line coverage
100%
Covered lines: 78
Uncovered lines: 0
Coverable lines: 78
Total lines: 142
Line coverage: 100%
Branch coverage
93%
Covered branches: 30
Total branches: 32
Branch coverage: 93.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GenerateBootstrapSource(...)100%11100%
GeneratePartialCompanionSource(...)100%44100%
ShortName()50%44100%
BuildToolsDocComment(...)100%2424100%

File(s)

/home/runner/work/needlr/needlr/src/NexusLabs.Needlr.AgentFramework.Generators/CodeGen/BootstrapCodeGenerator.cs

#LineLine coverage
 1// Copyright (c) NexusLabs. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System.Collections.Generic;
 5using System.Linq;
 6using System.Text;
 7
 8namespace NexusLabs.Needlr.AgentFramework.Generators;
 9
 10internal static class BootstrapCodeGenerator
 11{
 12    public static string GenerateBootstrapSource(string safeAssemblyName)
 13    {
 10114        return $@"// <auto-generated/>
 10115// Needlr AgentFramework Module Initializer
 10116#nullable enable
 10117
 10118using System.Runtime.CompilerServices;
 10119
 10120namespace {safeAssemblyName}.Generated;
 10121
 10122/// <summary>
 10123/// Auto-registers source-generated Agent Framework types with the Needlr bootstrap.
 10124/// Fires automatically when the assembly loads — no explicit <c>Add*FromGenerated()</c> calls needed.
 10125/// </summary>
 10126[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""NexusLabs.Needlr.AgentFramework.Generators"", ""1.0.0"")]
 10127internal static class NeedlrAgentFrameworkModuleInitializer
 10128{{
 10129    [ModuleInitializer]
 10130    internal static void Initialize()
 10131    {{
 10132        global::NexusLabs.Needlr.AgentFramework.AgentFrameworkGeneratedBootstrap.Register(
 10133            () => AgentFrameworkFunctionRegistry.AllFunctionTypes,
 10134            () => AgentFrameworkFunctionGroupRegistry.AllGroups,
 10135            () => AgentRegistry.AllAgentTypes,
 10136            () => AgentHandoffTopologyRegistry.AllHandoffs,
 10137            () => AgentGroupChatRegistry.AllGroups,
 10138            () => AgentSequentialTopologyRegistry.AllPipelines);
 10139        global::NexusLabs.Needlr.AgentFramework.AgentFrameworkGeneratedBootstrap.RegisterGraphTopology(
 10140            () => AgentGraphTopologyRegistry.AllGraphs);
 10141        global::NexusLabs.Needlr.AgentFramework.AgentFrameworkGeneratedBootstrap.RegisterAIFunctionProvider(
 10142            new global::{safeAssemblyName}.Generated.GeneratedAIFunctionProvider());
 10143    }}
 10144}}
 10145";
 46    }
 47
 48    public static string GeneratePartialCompanionSource(
 49        NeedlrAiAgentTypeInfo agentType,
 50        Dictionary<string, List<string>> groupedByName)
 51    {
 1152        var sb = new StringBuilder();
 1153        sb.AppendLine("// <auto-generated/>");
 1154        sb.AppendLine("#nullable enable");
 1155        sb.AppendLine();
 56
 1157        if (agentType.NamespaceName is not null)
 58        {
 1159            sb.AppendLine($"namespace {agentType.NamespaceName};");
 1160            sb.AppendLine();
 61        }
 62
 1163        sb.AppendLine($"partial class {agentType.ClassName}");
 1164        sb.AppendLine("{");
 65
 1166        sb.AppendLine("    /// <summary>The declared name of this agent, equal to the class name.</summary>");
 67
 1168        var toolsDocLines = BuildToolsDocComment(agentType, groupedByName);
 7469        foreach (var line in toolsDocLines)
 2670            sb.AppendLine(line);
 71
 1172        sb.AppendLine($"    public static string AgentName => nameof({agentType.ClassName});");
 1173        sb.AppendLine("}");
 74
 1175        return sb.ToString();
 76    }
 77
 78    private static List<string> BuildToolsDocComment(
 79        NeedlrAiAgentTypeInfo agentType,
 80        Dictionary<string, List<string>> groupedByName)
 81    {
 82        static string ShortName(string fqn)
 83        {
 284            var clean = fqn.StartsWith("global::") ? fqn.Substring(8) : fqn;
 285            var dot = clean.LastIndexOf('.');
 286            return dot >= 0 ? clean.Substring(dot + 1) : clean;
 87        }
 88
 1189        var lines = new List<string>();
 90
 91        // FunctionTypes = new Type[0] — explicitly no tools
 1192        if (agentType.HasExplicitFunctionTypes && agentType.ExplicitFunctionTypeFQNs.IsEmpty
 1193            && agentType.FunctionGroupNames.IsEmpty)
 94        {
 195            lines.Add("    /// <remarks>This agent has no tools assigned (declared with an empty <c>FunctionTypes</c>).<
 196            return lines;
 97        }
 98
 99        // Neither set — uses all registered function types
 10100        if (!agentType.HasExplicitFunctionTypes && agentType.FunctionGroupNames.IsEmpty)
 101        {
 7102            lines.Add("    /// <remarks>This agent uses all registered function types.</remarks>");
 7103            return lines;
 104        }
 105
 106        // Build the resolved list of function types
 3107        var entries = new List<(string displayName, string? groupSource)>();
 108
 10109        foreach (var group in agentType.FunctionGroupNames)
 110        {
 2111            if (groupedByName.TryGetValue(group, out var types))
 112            {
 4113                foreach (var typeFqn in types)
 1114                    entries.Add((ShortName(typeFqn), group));
 115            }
 116            else
 117            {
 1118                entries.Add(($"(unresolved group \"{group}\")", group));
 119            }
 120        }
 121
 8122        foreach (var typeFqn in agentType.ExplicitFunctionTypeFQNs)
 123        {
 1124            var shortName = ShortName(typeFqn);
 1125            if (!entries.Any(e => e.displayName == shortName))
 1126                entries.Add((shortName, null));
 127        }
 128
 3129        lines.Add("    /// <remarks>");
 3130        lines.Add("    /// <para>Agent tools:</para>");
 3131        lines.Add("    /// <list type=\"bullet\">");
 12132        foreach (var (displayName, groupSource) in entries)
 133        {
 3134            var source = groupSource is not null ? $" (group <c>\"{groupSource}\"</c>)" : " (explicit type)";
 3135            lines.Add($"    /// <item><term><see cref=\"{displayName}\"/>{source}</term></item>");
 136        }
 3137        lines.Add("    /// </list>");
 3138        lines.Add("    /// </remarks>");
 139
 3140        return lines;
 141    }
 142}