Files
MAF1/PluginHost/NodeCatalogService.cs
T

112 lines
3.7 KiB
C#
Raw Normal View History

2026-08-26 18:06:02 +08:00
using MAF1.PluginContract;
using MAF1.Web;
namespace MAF1.Plugins;
public sealed class NodeCatalogSnapshot
{
public string PluginsRoot { get; init; } = "";
public List<AgentTypeInfo> System { get; init; } = [];
public List<AgentTypeInfo> Plugins { get; init; } = [];
public List<AgentTypeInfo> Nodes { get; init; } = [];
public List<CatalogIssue> Issues { get; init; } = [];
public IReadOnlyList<LoadedPlugin> LoadedPlugins { get; init; } = [];
}
public sealed class NodeCatalogService(PluginScanner scanner)
{
public NodeCatalogSnapshot Load()
{
PluginScanResult scan = scanner.Scan();
List<CatalogIssue> issues = [.. scan.Issues];
List<AgentTypeInfo> system = AgentCatalog.SystemNodes
.Select(Clone)
.ToList();
foreach (AgentTypeInfo item in system)
{
item.Origin = "system";
}
Dictionary<string, AgentTypeInfo> systemByType = system.ToDictionary(n => n.Type, StringComparer.OrdinalIgnoreCase);
List<AgentTypeInfo> plugins = [];
foreach (LoadedPlugin plugin in scan.Plugins)
{
AgentTypeInfo info = ToTypeInfo(plugin);
if (systemByType.ContainsKey(info.Type))
{
issues.Add(new CatalogIssue
{
Level = "info",
Source = info.Type,
Message = $"插件 `{info.Type}` 覆盖了同名系统节点,画布运行将走插件进程。",
});
systemByType[info.Type].Overridden = true;
}
plugins.Add(info);
}
Dictionary<string, AgentTypeInfo> merged = systemByType
.ToDictionary(kv => kv.Key, kv => kv.Value, StringComparer.OrdinalIgnoreCase);
foreach (AgentTypeInfo plugin in plugins)
{
merged[plugin.Type] = plugin;
}
return new NodeCatalogSnapshot
{
PluginsRoot = scan.Root,
System = system,
Plugins = plugins,
Nodes = merged.Values.OrderBy(n => n.Origin).ThenBy(n => n.Name).ToList(),
Issues = issues,
LoadedPlugins = scan.Plugins,
};
}
public LoadedPlugin? FindPlugin(string type)
=> Load().LoadedPlugins.FirstOrDefault(p => p.Manifest.Id.Equals(type, StringComparison.OrdinalIgnoreCase));
private static AgentTypeInfo ToTypeInfo(LoadedPlugin plugin)
{
PluginManifest manifest = plugin.Manifest;
return new AgentTypeInfo
{
Type = manifest.Id,
Name = string.IsNullOrWhiteSpace(manifest.Name) ? manifest.Id : manifest.Name,
Description = manifest.Description,
Origin = "plugin",
Version = manifest.Version,
Folder = plugin.FolderName,
Inputs = manifest.Inputs.Select(ToPort).ToList(),
Outputs = manifest.Outputs.Select(ToPort).ToList(),
Credentials = manifest.Credentials,
};
}
private static PortInfo ToPort(PluginPort port)
=> new()
{
Name = port.Name,
Type = port.Type,
Description = port.Description,
Required = port.Required,
};
private static AgentTypeInfo Clone(AgentTypeInfo source)
=> new()
{
Type = source.Type,
Name = source.Name,
Description = source.Description,
Origin = source.Origin,
Version = source.Version,
Folder = source.Folder,
Overridden = source.Overridden,
Handler = source.Handler,
Inputs = source.Inputs,
Outputs = source.Outputs,
Credentials = source.Credentials,
};
}