Forge
csharp3407750f
1using System.Text.Json;
2using AgentForge.Options;
3using AgentForge.Services;
4using Microsoft.Extensions.Options;
5
6namespace AgentForge.Endpoints;
7
8internal static class ForgeRegistryEndpoints
9{
10 private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
11
12 internal static RouteGroupBuilder MapRegistryEndpoints(this RouteGroupBuilder api)
13 {
14 var registry = api.MapGroup("/registry/v1");
15 registry.MapGet("/plugins", ListPlugins);
16 registry.MapGet("/plugins/{id}/versions", ListVersions);
17 return api;
18 }
19
20 private static IResult ListPlugins(IOptions<ForgeOptions> options)
21 {
22 var index = LoadIndex(options.Value);
23 var items = index.Plugins.Select(p => new
24 {
25 p.Id,
26 p.DisplayName,
27 p.Tier,
28 p.Publisher,
29 }).ToList();
30 return Results.Ok(new { total = items.Count, plugins = items });
31 }
32
33 private static IResult ListVersions(string id, IOptions<ForgeOptions> options)
34 {
35 var index = LoadIndex(options.Value);
36 var plugin = index.Plugins.FirstOrDefault(p => string.Equals(p.Id, id, StringComparison.OrdinalIgnoreCase));
37 if (plugin is null)
38 throw new ForgeApiException(404, $"Plugin '{id}' not found in registry.");
39
40 return Results.Ok(new
41 {
42 id = plugin.Id,
43 versions = new[]
44 {
45 new
46 {
47 version = plugin.LatestVersion,
48 forgeAbi = plugin.ForgeAbi,
49 downloadUrl = (string?)null,
50 },
51 },
52 });
53 }
54
55 private static RegistryIndex LoadIndex(ForgeOptions options)
56 {
57 var path = Path.Combine(AppContext.BaseDirectory, options.RegistryIndexPath);
58 if (!File.Exists(path))
59 throw new ForgeApiException(503, "Plugin registry index is not configured on this host.");
60
61 var json = File.ReadAllText(path);
62 return JsonSerializer.Deserialize<RegistryIndex>(json, JsonOptions)
63 ?? throw new ForgeApiException(500, "Registry index parse failed.");
64 }
65
66 private sealed class RegistryIndex
67 {
68 public List<RegistryPluginEntry> Plugins { get; set; } = [];
69 }
70
71 private sealed class RegistryPluginEntry
72 {
73 public string Id { get; set; } = "";
74
75 public string DisplayName { get; set; } = "";
76
77 public string Tier { get; set; } = "";
78
79 public string Publisher { get; set; } = "";
80
81 public string LatestVersion { get; set; } = "";
82
83 public string ForgeAbi { get; set; } = "";
84 }
85}
86
View only · write via MCP/CIDE