diff --git a/RoslynBridge.WebApi/Controllers/RoslynController.cs b/RoslynBridge.WebApi/Controllers/RoslynController.cs
index dc4c630..f98223e 100644
--- a/RoslynBridge.WebApi/Controllers/RoslynController.cs
+++ b/RoslynBridge.WebApi/Controllers/RoslynController.cs
@@ -1,5 +1,8 @@
using Microsoft.AspNetCore.Mvc;
using RoslynBridge.WebApi.Models;
+using System.Text;
+using System.Text.Json;
+using System.Linq;
using RoslynBridge.WebApi.Services;
namespace RoslynBridge.WebApi.Controllers;
@@ -91,6 +94,130 @@ public class RoslynController : ControllerBase
return Ok(result);
}
+ ///
+ /// Get a compact summary of the solution overview
+ ///
+ /// How many projects to list (by file count)
+ /// Include top-level namespaces in summary
+ /// One of: json | text | yaml
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// Compact summary as JSON or plain text
+ [HttpGet("solution/overview/summary")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task GetSolutionOverviewSummary(
+ [FromQuery] int topNProjects = 5,
+ [FromQuery] bool includeNamespaces = true,
+ [FromQuery] string? format = "json",
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest { QueryType = "getsolutionoverview" };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+
+ if (!result.Success)
+ {
+ if (string.Equals(format, "json", StringComparison.OrdinalIgnoreCase))
+ {
+ return Ok(result);
+ }
+ var err = result.Error ?? "Unknown error";
+ return Content($"error: {err}", "text/plain", Encoding.UTF8);
+ }
+
+ // Expect Data as JsonElement; shape per Models.SolutionOverview
+ int projectCount = 0;
+ int documentCount = 0;
+ var projectsSummary = new List<(string Name, int FileCount)>();
+ var topLevelNamespaces = new List();
+
+ if (result.Data is JsonElement dataEl && dataEl.ValueKind == JsonValueKind.Object)
+ {
+ if (dataEl.TryGetProperty("projectCount", out var pc)) projectCount = pc.GetInt32();
+ if (dataEl.TryGetProperty("documentCount", out var dc)) documentCount = dc.GetInt32();
+ if (includeNamespaces && dataEl.TryGetProperty("topLevelNamespaces", out var nsEl) && nsEl.ValueKind == JsonValueKind.Array)
+ {
+ foreach (var ns in nsEl.EnumerateArray())
+ {
+ if (ns.ValueKind == JsonValueKind.String)
+ {
+ topLevelNamespaces.Add(ns.GetString() ?? string.Empty);
+ }
+ }
+ }
+ if (dataEl.TryGetProperty("projects", out var prEl) && prEl.ValueKind == JsonValueKind.Array)
+ {
+ foreach (var p in prEl.EnumerateArray())
+ {
+ string name = p.TryGetProperty("name", out var nEl) && nEl.ValueKind == JsonValueKind.String ? (nEl.GetString() ?? string.Empty) : string.Empty;
+ int files = p.TryGetProperty("fileCount", out var fEl) && fEl.ValueKind == JsonValueKind.Number ? fEl.GetInt32() : 0;
+ projectsSummary.Add((name, files));
+ }
+ }
+ }
+
+ var topProjects = projectsSummary
+ .OrderByDescending(p => p.FileCount)
+ .ThenBy(p => p.Name)
+ .Take(Math.Max(0, topNProjects))
+ .ToList();
+
+ if (string.Equals(format, "json", StringComparison.OrdinalIgnoreCase))
+ {
+ var compact = new
+ {
+ projectCount,
+ documentCount,
+ projects = topProjects.Select(p => new { name = p.Name, files = p.FileCount }).ToList(),
+ topLevelNamespaces = includeNamespaces ? topLevelNamespaces : null
+ };
+
+ return Ok(new RoslynQueryResponse
+ {
+ Success = true,
+ Message = "Compact solution overview",
+ Data = compact,
+ Error = null
+ });
+ }
+
+ // text or yaml: render a compact string
+ var sb = new StringBuilder();
+ if (string.Equals(format, "yaml", StringComparison.OrdinalIgnoreCase))
+ {
+ sb.AppendLine($"projectCount: {projectCount}");
+ sb.AppendLine($"documentCount: {documentCount}");
+ if (includeNamespaces)
+ {
+ sb.Append("topLevelNamespaces: [");
+ sb.Append(string.Join(", ", topLevelNamespaces));
+ sb.AppendLine("]");
+ }
+ sb.AppendLine("projects:");
+ foreach (var p in topProjects)
+ {
+ sb.AppendLine($" - name: {p.Name}");
+ sb.AppendLine($" files: {p.FileCount}");
+ }
+ }
+ else
+ {
+ // text
+ sb.AppendLine($"Projects: {projectCount} | Documents: {documentCount}");
+ if (includeNamespaces && topLevelNamespaces.Count > 0)
+ {
+ sb.AppendLine($"TopNamespaces: {string.Join(", ", topLevelNamespaces)}");
+ }
+ sb.AppendLine("Top Projects:");
+ foreach (var p in topProjects)
+ {
+ sb.AppendLine($" - {p.Name} ({p.FileCount})");
+ }
+ }
+
+ return Content(sb.ToString(), "text/plain", Encoding.UTF8);
+ }
+
///
/// Get diagnostics (errors and warnings)
///