Forge
csharp3407750f
1namespace AgentForge.Abstractions;
2
3/// <summary>Human-layer tab / view route owned by a domain plugin (FORGE-ADR-0015 §2).</summary>
4public sealed class ForgeViewContributor
5{
6 public required string TabId { get; init; }
7
8 public required string Label { get; init; }
9
10 /// <summary>Detail route prefix, e.g. <c>/view/repos/{name}/issues</c>.</summary>
11 public required string RoutePrefix { get; init; }
12
13 public int Order { get; init; } = 100;
14
15 public required string PluginId { get; init; }
16}
17
18public sealed class ForgeViewContributorRegistry
19{
20 private readonly List<ForgeViewContributor> _contributors = [];
21 private readonly HashSet<string> _tabIds = new(StringComparer.OrdinalIgnoreCase);
22
23 public IReadOnlyList<ForgeViewContributor> Contributors => _contributors;
24
25 public void Add(ForgeViewContributor contributor)
26 {
27 ArgumentNullException.ThrowIfNull(contributor);
28 if (string.IsNullOrWhiteSpace(contributor.TabId))
29 throw new ArgumentException("TabId is required.", nameof(contributor));
30 if (string.IsNullOrWhiteSpace(contributor.RoutePrefix))
31 throw new ArgumentException("RoutePrefix is required.", nameof(contributor));
32
33 if (!_tabIds.Add(contributor.TabId.Trim()))
34 {
35 throw new InvalidOperationException(
36 $"Duplicate view tab '{contributor.TabId}' in plugin registration.");
37 }
38
39 _contributors.Add(contributor);
40 }
41}
42
43public interface IForgeViewContributorCatalog
44{
45 IReadOnlyList<ForgeViewContributor> Contributors { get; }
46
47 bool HasTab(string tabId);
48}
49
View only · write via MCP/CIDE