diff --git a/RoslynBridge.WebApi/Controllers/HealthController.cs b/RoslynBridge.WebApi/Controllers/HealthController.cs
new file mode 100644
index 0000000..34e6a3b
--- /dev/null
+++ b/RoslynBridge.WebApi/Controllers/HealthController.cs
@@ -0,0 +1,72 @@
+using Microsoft.AspNetCore.Mvc;
+using RoslynBridge.WebApi.Models;
+using RoslynBridge.WebApi.Services;
+
+namespace RoslynBridge.WebApi.Controllers;
+
+///
+/// Health check and status controller
+///
+[ApiController]
+[Route("api/[controller]")]
+[Produces("application/json")]
+public class HealthController : ControllerBase
+{
+ private readonly IRoslynBridgeClient _bridgeClient;
+ private readonly ILogger _logger;
+
+ public HealthController(IRoslynBridgeClient bridgeClient, ILogger logger)
+ {
+ _bridgeClient = bridgeClient;
+ _logger = logger;
+ }
+
+ ///
+ /// Get the health status of the middleware and Visual Studio plugin
+ ///
+ /// Cancellation token
+ /// Health status information
+ /// Service is healthy
+ /// Service is unhealthy
+ [HttpGet]
+ [ProducesResponseType(typeof(HealthCheckResponse), StatusCodes.Status200OK)]
+ [ProducesResponseType(typeof(HealthCheckResponse), StatusCodes.Status503ServiceUnavailable)]
+ public async Task> GetHealth(CancellationToken cancellationToken)
+ {
+ var response = new HealthCheckResponse();
+
+ try
+ {
+ var isVsPluginHealthy = await _bridgeClient.IsHealthyAsync(null, cancellationToken);
+ response.VsPluginStatus = isVsPluginHealthy ? "Connected" : "Disconnected";
+
+ if (!isVsPluginHealthy)
+ {
+ response.Status = "Degraded";
+ _logger.LogWarning("Visual Studio plugin is not accessible");
+ return StatusCode(StatusCodes.Status503ServiceUnavailable, response);
+ }
+
+ _logger.LogInformation("Health check passed");
+ return Ok(response);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Health check failed");
+ response.Status = "Unhealthy";
+ response.VsPluginStatus = "Error";
+ return StatusCode(StatusCodes.Status503ServiceUnavailable, response);
+ }
+ }
+
+ ///
+ /// Simple ping endpoint
+ ///
+ /// Pong response
+ [HttpGet("ping")]
+ [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
+ public IActionResult Ping()
+ {
+ return Ok(new { message = "pong", timestamp = DateTime.UtcNow });
+ }
+}
diff --git a/RoslynBridge.WebApi/Controllers/HistoryController.cs b/RoslynBridge.WebApi/Controllers/HistoryController.cs
new file mode 100644
index 0000000..a2995f1
--- /dev/null
+++ b/RoslynBridge.WebApi/Controllers/HistoryController.cs
@@ -0,0 +1,117 @@
+using Microsoft.AspNetCore.Mvc;
+using RoslynBridge.WebApi.Models;
+using RoslynBridge.WebApi.Services;
+
+namespace RoslynBridge.WebApi.Controllers;
+
+///
+/// Controller for accessing query history
+///
+[ApiController]
+[Route("api/[controller]")]
+[Produces("application/json")]
+public class HistoryController : ControllerBase
+{
+ private readonly IHistoryService _historyService;
+ private readonly ILogger _logger;
+
+ public HistoryController(IHistoryService historyService, ILogger logger)
+ {
+ _historyService = historyService;
+ _logger = logger;
+ }
+
+ ///
+ /// Get all history entries
+ ///
+ /// List of all history entries
+ /// Returns the list of history entries
+ [HttpGet]
+ [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
+ public ActionResult> GetAll()
+ {
+ var entries = _historyService.GetAll();
+ return Ok(entries);
+ }
+
+ ///
+ /// Get a specific history entry by ID
+ ///
+ /// The history entry ID
+ /// The history entry
+ /// Returns the history entry
+ /// Entry not found
+ [HttpGet("{id}")]
+ [ProducesResponseType(typeof(QueryHistoryEntry), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public ActionResult GetById(string id)
+ {
+ var entry = _historyService.GetById(id);
+ if (entry == null)
+ {
+ return NotFound(new { message = $"History entry {id} not found" });
+ }
+
+ return Ok(entry);
+ }
+
+ ///
+ /// Get recent history entries
+ ///
+ /// Number of entries to return (default: 50, max: 500)
+ /// List of recent history entries
+ /// Returns the list of recent entries
+ [HttpGet("recent")]
+ [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
+ public ActionResult> GetRecent([FromQuery] int count = 50)
+ {
+ if (count > 500) count = 500;
+ if (count < 1) count = 1;
+
+ var entries = _historyService.GetRecent(count);
+ return Ok(entries);
+ }
+
+ ///
+ /// Get history statistics
+ ///
+ /// Statistics about history entries
+ [HttpGet("stats")]
+ [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
+ public ActionResult GetStats()
+ {
+ var entries = _historyService.GetAll();
+ var stats = new
+ {
+ totalEntries = _historyService.GetCount(),
+ successfulRequests = entries.Count(e => e.Success),
+ failedRequests = entries.Count(e => !e.Success),
+ averageDurationMs = entries.Any() ? entries.Average(e => e.DurationMs) : 0,
+ oldestEntry = entries.Any() ? entries.Last().Timestamp : (DateTime?)null,
+ newestEntry = entries.Any() ? entries.First().Timestamp : (DateTime?)null,
+ topPaths = entries
+ .GroupBy(e => e.Path)
+ .OrderByDescending(g => g.Count())
+ .Take(10)
+ .Select(g => new { path = g.Key, count = g.Count() })
+ };
+
+ return Ok(stats);
+ }
+
+ ///
+ /// Clear all history entries
+ ///
+ /// Confirmation message
+ /// History cleared successfully
+ [HttpDelete]
+ [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
+ public ActionResult Clear()
+ {
+ var count = _historyService.GetCount();
+ _historyService.Clear();
+ _logger.LogInformation("History cleared: {Count} entries removed", count);
+
+ return Ok(new { message = $"History cleared: {count} entries removed" });
+ }
+}
diff --git a/RoslynBridge.WebApi/Controllers/InstancesController.cs b/RoslynBridge.WebApi/Controllers/InstancesController.cs
new file mode 100644
index 0000000..14cc80c
--- /dev/null
+++ b/RoslynBridge.WebApi/Controllers/InstancesController.cs
@@ -0,0 +1,168 @@
+using Microsoft.AspNetCore.Mvc;
+using RoslynBridge.WebApi.Models;
+using RoslynBridge.WebApi.Services;
+
+namespace RoslynBridge.WebApi.Controllers;
+
+///
+/// Controller for managing Visual Studio instance registrations
+///
+[ApiController]
+[Route("api/[controller]")]
+[Produces("application/json")]
+public class InstancesController : ControllerBase
+{
+ private readonly IInstanceRegistryService _registryService;
+ private readonly ILogger _logger;
+
+ public InstancesController(
+ IInstanceRegistryService registryService,
+ ILogger logger)
+ {
+ _registryService = registryService;
+ _logger = logger;
+ }
+
+ ///
+ /// Register a new Visual Studio instance
+ ///
+ /// Instance information
+ /// Registration result
+ [HttpPost("register")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ public IActionResult Register([FromBody] VSInstanceInfo instance)
+ {
+ if (!ModelState.IsValid)
+ {
+ return BadRequest(ModelState);
+ }
+
+ _registryService.Register(instance);
+
+ return Ok(new
+ {
+ success = true,
+ message = "Instance registered successfully",
+ processId = instance.ProcessId,
+ port = instance.Port
+ });
+ }
+
+ ///
+ /// Unregister a Visual Studio instance
+ ///
+ /// Process ID of the instance to unregister
+ /// Unregistration result
+ [HttpPost("unregister/{processId}")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public IActionResult Unregister(int processId)
+ {
+ var removed = _registryService.Unregister(processId);
+
+ if (!removed)
+ {
+ return NotFound(new { success = false, message = "Instance not found" });
+ }
+
+ return Ok(new { success = true, message = "Instance unregistered successfully" });
+ }
+
+ ///
+ /// Update heartbeat for a Visual Studio instance
+ ///
+ /// Process ID of the instance
+ /// Heartbeat update result
+ [HttpPost("heartbeat/{processId}")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public IActionResult Heartbeat(int processId)
+ {
+ var updated = _registryService.UpdateHeartbeat(processId);
+
+ if (!updated)
+ {
+ return NotFound(new { success = false, message = "Instance not found" });
+ }
+
+ return Ok(new { success = true, message = "Heartbeat updated" });
+ }
+
+ ///
+ /// Get all registered Visual Studio instances
+ ///
+ /// List of registered instances
+ [HttpGet]
+ [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)]
+ public IActionResult GetAll()
+ {
+ var instances = _registryService.GetAllInstances();
+ return Ok(instances);
+ }
+
+ ///
+ /// Get instance by process ID
+ ///
+ /// Process ID
+ /// Instance information
+ [HttpGet("by-pid/{processId}")]
+ [ProducesResponseType(typeof(VSInstanceInfo), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public IActionResult GetByProcessId(int processId)
+ {
+ var instance = _registryService.GetByProcessId(processId);
+
+ if (instance == null)
+ {
+ return NotFound(new { success = false, message = "Instance not found" });
+ }
+
+ return Ok(instance);
+ }
+
+ ///
+ /// Get instance by solution path
+ ///
+ /// Solution file path
+ /// Instance information
+ [HttpGet("by-solution")]
+ [ProducesResponseType(typeof(VSInstanceInfo), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public IActionResult GetBySolutionPath([FromQuery] string solutionPath)
+ {
+ if (string.IsNullOrEmpty(solutionPath))
+ {
+ return BadRequest(new { success = false, message = "Solution path is required" });
+ }
+
+ var instance = _registryService.GetBySolutionPath(solutionPath);
+
+ if (instance == null)
+ {
+ return NotFound(new { success = false, message = "No instance found for this solution" });
+ }
+
+ return Ok(instance);
+ }
+
+ ///
+ /// Get instance by port
+ ///
+ /// Port number
+ /// Instance information
+ [HttpGet("by-port/{port}")]
+ [ProducesResponseType(typeof(VSInstanceInfo), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
+ public IActionResult GetByPort(int port)
+ {
+ var instance = _registryService.GetByPort(port);
+
+ if (instance == null)
+ {
+ return NotFound(new { success = false, message = "Instance not found" });
+ }
+
+ return Ok(instance);
+ }
+}
diff --git a/RoslynBridge.WebApi/Controllers/RoslynController.cs b/RoslynBridge.WebApi/Controllers/RoslynController.cs
new file mode 100644
index 0000000..dc4c630
--- /dev/null
+++ b/RoslynBridge.WebApi/Controllers/RoslynController.cs
@@ -0,0 +1,283 @@
+using Microsoft.AspNetCore.Mvc;
+using RoslynBridge.WebApi.Models;
+using RoslynBridge.WebApi.Services;
+
+namespace RoslynBridge.WebApi.Controllers;
+
+///
+/// Controller for Roslyn code analysis operations
+///
+[ApiController]
+[Route("api/[controller]")]
+[Produces("application/json")]
+public class RoslynController : ControllerBase
+{
+ private readonly IRoslynBridgeClient _bridgeClient;
+ private readonly ILogger _logger;
+
+ public RoslynController(IRoslynBridgeClient bridgeClient, ILogger logger)
+ {
+ _bridgeClient = bridgeClient;
+ _logger = logger;
+ }
+
+ ///
+ /// Execute a Roslyn query
+ ///
+ /// The query request
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// The query result
+ /// Query executed successfully
+ /// Invalid request
+ /// Internal server error
+ [HttpPost("query")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status500InternalServerError)]
+ public async Task> ExecuteQuery(
+ [FromBody] RoslynQueryRequest request,
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ if (!ModelState.IsValid)
+ {
+ return BadRequest(ModelState);
+ }
+
+ _logger.LogInformation("Received query request: {QueryType}", request.QueryType);
+
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+
+ if (!result.Success)
+ {
+ _logger.LogWarning("Query failed: {Error}", result.Error);
+ }
+
+ return Ok(result);
+ }
+
+ ///
+ /// Get all projects in the solution
+ ///
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// List of projects
+ [HttpGet("projects")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> GetProjects(
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest { QueryType = "getprojects" };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+
+ ///
+ /// Get solution overview
+ ///
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// Solution statistics and overview
+ [HttpGet("solution/overview")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> GetSolutionOverview(
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest { QueryType = "getsolutionoverview" };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+
+ ///
+ /// Get diagnostics (errors and warnings)
+ ///
+ /// Optional file path to filter diagnostics
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// List of diagnostics
+ [HttpGet("diagnostics")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> GetDiagnostics(
+ [FromQuery] string? filePath = null,
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest
+ {
+ QueryType = "getdiagnostics",
+ FilePath = filePath
+ };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+
+ ///
+ /// Get symbol information at a specific position
+ ///
+ /// File path
+ /// Line number (1-based)
+ /// Column number (0-based)
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// Symbol information
+ [HttpGet("symbol")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> GetSymbol(
+ [FromQuery] string filePath,
+ [FromQuery] int line,
+ [FromQuery] int column,
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest
+ {
+ QueryType = "getsymbol",
+ FilePath = filePath,
+ Line = line,
+ Column = column
+ };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+
+ ///
+ /// Find all references to a symbol
+ ///
+ /// File path
+ /// Line number (1-based)
+ /// Column number (0-based)
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// List of references
+ [HttpGet("references")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> FindReferences(
+ [FromQuery] string filePath,
+ [FromQuery] int line,
+ [FromQuery] int column,
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest
+ {
+ QueryType = "findreferences",
+ FilePath = filePath,
+ Line = line,
+ Column = column
+ };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+
+ ///
+ /// Search for symbols by name
+ ///
+ /// Symbol name or pattern
+ /// Optional symbol kind filter
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// List of matching symbols
+ [HttpGet("symbol/search")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> FindSymbol(
+ [FromQuery] string symbolName,
+ [FromQuery] string? kind = null,
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest
+ {
+ QueryType = "findsymbol",
+ SymbolName = symbolName
+ };
+
+ if (!string.IsNullOrEmpty(kind))
+ {
+ request.Parameters = new Dictionary { ["kind"] = kind };
+ }
+
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+
+ ///
+ /// Format a document
+ ///
+ /// File path to format
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// Format operation result
+ [HttpPost("format")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> FormatDocument(
+ [FromBody] string filePath,
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest
+ {
+ QueryType = "formatdocument",
+ FilePath = filePath
+ };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+
+ ///
+ /// Add a NuGet package to a project
+ ///
+ /// Project name
+ /// NuGet package name
+ /// Optional package version
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// Operation result
+ [HttpPost("project/package/add")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> AddNuGetPackage(
+ [FromQuery] string projectName,
+ [FromQuery] string packageName,
+ [FromQuery] string? version = null,
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest
+ {
+ QueryType = "addnugetpackage",
+ ProjectName = projectName,
+ PackageName = packageName,
+ Version = version
+ };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+
+ ///
+ /// Build a project
+ ///
+ /// Project name
+ /// Build configuration (Debug/Release)
+ /// Optional: specific VS instance port to target
+ /// Cancellation token
+ /// Build result
+ [HttpPost("project/build")]
+ [ProducesResponseType(typeof(RoslynQueryResponse), StatusCodes.Status200OK)]
+ public async Task> BuildProject(
+ [FromQuery] string projectName,
+ [FromQuery] string? configuration = null,
+ [FromQuery] int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ var request = new RoslynQueryRequest
+ {
+ QueryType = "buildproject",
+ ProjectName = projectName,
+ Configuration = configuration
+ };
+ var result = await _bridgeClient.ExecuteQueryAsync(request, instancePort, cancellationToken);
+ return Ok(result);
+ }
+}
diff --git a/RoslynBridge.WebApi/Middleware/HistoryMiddleware.cs b/RoslynBridge.WebApi/Middleware/HistoryMiddleware.cs
new file mode 100644
index 0000000..04aba08
--- /dev/null
+++ b/RoslynBridge.WebApi/Middleware/HistoryMiddleware.cs
@@ -0,0 +1,132 @@
+using System.Diagnostics;
+using System.Text;
+using System.Text.Json;
+using RoslynBridge.WebApi.Models;
+using RoslynBridge.WebApi.Services;
+
+namespace RoslynBridge.WebApi.Middleware;
+
+///
+/// Middleware to capture and log all Roslyn API requests and responses
+///
+public class HistoryMiddleware
+{
+ private readonly RequestDelegate _next;
+ private readonly ILogger _logger;
+
+ public HistoryMiddleware(RequestDelegate next, ILogger logger)
+ {
+ _next = next;
+ _logger = logger;
+ }
+
+ public async Task InvokeAsync(HttpContext context, IHistoryService historyService)
+ {
+ // Only track Roslyn API endpoints
+ if (!context.Request.Path.StartsWithSegments("/api/roslyn"))
+ {
+ await _next(context);
+ return;
+ }
+
+ var stopwatch = Stopwatch.StartNew();
+ var historyEntry = new QueryHistoryEntry
+ {
+ Timestamp = DateTime.UtcNow,
+ Path = context.Request.Path,
+ Method = context.Request.Method,
+ ClientIp = context.Connection.RemoteIpAddress?.ToString()
+ };
+
+ // Capture request
+ RoslynQueryRequest? request = null;
+ if (context.Request.Method == "POST" && context.Request.ContentLength > 0)
+ {
+ context.Request.EnableBuffering();
+ using var reader = new StreamReader(context.Request.Body, Encoding.UTF8, leaveOpen: true);
+ var requestBody = await reader.ReadToEndAsync();
+ context.Request.Body.Position = 0;
+
+ try
+ {
+ request = JsonSerializer.Deserialize(requestBody, new JsonSerializerOptions
+ {
+ PropertyNameCaseInsensitive = true
+ });
+ historyEntry.Request = request;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "Failed to deserialize request for history");
+ }
+ }
+
+ // Capture response
+ var originalBodyStream = context.Response.Body;
+ using var responseBody = new MemoryStream();
+ context.Response.Body = responseBody;
+
+ try
+ {
+ await _next(context);
+
+ stopwatch.Stop();
+ historyEntry.DurationMs = stopwatch.ElapsedMilliseconds;
+ historyEntry.Success = context.Response.StatusCode < 400;
+
+ // Read response
+ responseBody.Seek(0, SeekOrigin.Begin);
+ var responseText = await new StreamReader(responseBody).ReadToEndAsync();
+ responseBody.Seek(0, SeekOrigin.Begin);
+
+ try
+ {
+ var response = JsonSerializer.Deserialize(responseText, new JsonSerializerOptions
+ {
+ PropertyNameCaseInsensitive = true
+ });
+ historyEntry.Response = response;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "Failed to deserialize response for history");
+ }
+
+ // Copy response back
+ await responseBody.CopyToAsync(originalBodyStream);
+ }
+ catch (Exception ex)
+ {
+ stopwatch.Stop();
+ historyEntry.DurationMs = stopwatch.ElapsedMilliseconds;
+ historyEntry.Success = false;
+ _logger.LogError(ex, "Error in request processing");
+ throw;
+ }
+ finally
+ {
+ context.Response.Body = originalBodyStream;
+
+ // Add to history
+ try
+ {
+ historyService.Add(historyEntry);
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Failed to add entry to history");
+ }
+ }
+ }
+}
+
+///
+/// Extension methods for adding history middleware
+///
+public static class HistoryMiddlewareExtensions
+{
+ public static IApplicationBuilder UseHistoryTracking(this IApplicationBuilder builder)
+ {
+ return builder.UseMiddleware();
+ }
+}
diff --git a/RoslynBridge.WebApi/Models/HealthCheckResponse.cs b/RoslynBridge.WebApi/Models/HealthCheckResponse.cs
new file mode 100644
index 0000000..acd9d23
--- /dev/null
+++ b/RoslynBridge.WebApi/Models/HealthCheckResponse.cs
@@ -0,0 +1,32 @@
+namespace RoslynBridge.WebApi.Models;
+
+///
+/// Health check response for service status
+///
+public class HealthCheckResponse
+{
+ ///
+ /// Overall health status
+ ///
+ public string Status { get; set; } = "Healthy";
+
+ ///
+ /// Web API service status
+ ///
+ public string WebApiStatus { get; set; } = "Running";
+
+ ///
+ /// Visual Studio plugin connection status
+ ///
+ public string VsPluginStatus { get; set; } = "Unknown";
+
+ ///
+ /// Timestamp of the health check
+ ///
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// API version
+ ///
+ public string Version { get; set; } = "1.0.0";
+}
diff --git a/RoslynBridge.WebApi/Models/QueryHistoryEntry.cs b/RoslynBridge.WebApi/Models/QueryHistoryEntry.cs
new file mode 100644
index 0000000..e2bb6d2
--- /dev/null
+++ b/RoslynBridge.WebApi/Models/QueryHistoryEntry.cs
@@ -0,0 +1,52 @@
+namespace RoslynBridge.WebApi.Models;
+
+///
+/// Represents a single query history entry with request and response information
+///
+public class QueryHistoryEntry
+{
+ ///
+ /// Unique identifier for this history entry
+ ///
+ public string Id { get; set; } = Guid.NewGuid().ToString();
+
+ ///
+ /// Timestamp when the request was received
+ ///
+ public DateTime Timestamp { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// The endpoint path that was called
+ ///
+ public string Path { get; set; } = string.Empty;
+
+ ///
+ /// HTTP method used
+ ///
+ public string Method { get; set; } = string.Empty;
+
+ ///
+ /// The Roslyn query request
+ ///
+ public RoslynQueryRequest? Request { get; set; }
+
+ ///
+ /// The Roslyn query response
+ ///
+ public RoslynQueryResponse? Response { get; set; }
+
+ ///
+ /// Request duration in milliseconds
+ ///
+ public long DurationMs { get; set; }
+
+ ///
+ /// Whether the request was successful
+ ///
+ public bool Success { get; set; }
+
+ ///
+ /// Client IP address
+ ///
+ public string? ClientIp { get; set; }
+}
diff --git a/RoslynBridge.WebApi/Models/RoslynQueryRequest.cs b/RoslynBridge.WebApi/Models/RoslynQueryRequest.cs
new file mode 100644
index 0000000..e2fcb99
--- /dev/null
+++ b/RoslynBridge.WebApi/Models/RoslynQueryRequest.cs
@@ -0,0 +1,65 @@
+using System.ComponentModel.DataAnnotations;
+
+namespace RoslynBridge.WebApi.Models;
+
+///
+/// Request model for Roslyn query operations
+///
+public class RoslynQueryRequest
+{
+ ///
+ /// Type of query to execute (e.g., "getsymbol", "getdocument", "findreferences")
+ ///
+ [Required]
+ public string QueryType { get; set; } = string.Empty;
+
+ ///
+ /// File path for file-based operations
+ ///
+ public string? FilePath { get; set; }
+
+ ///
+ /// Symbol name for symbol-based operations
+ ///
+ public string? SymbolName { get; set; }
+
+ ///
+ /// Line number (1-based) for position-based operations
+ ///
+ public int? Line { get; set; }
+
+ ///
+ /// Column number (0-based) for position-based operations
+ ///
+ public int? Column { get; set; }
+
+ ///
+ /// Additional parameters for the query
+ ///
+ public Dictionary? Parameters { get; set; }
+
+ ///
+ /// Project name for project operations
+ ///
+ public string? ProjectName { get; set; }
+
+ ///
+ /// Package name for NuGet operations
+ ///
+ public string? PackageName { get; set; }
+
+ ///
+ /// Version for NuGet package operations
+ ///
+ public string? Version { get; set; }
+
+ ///
+ /// Build configuration (Debug/Release)
+ ///
+ public string? Configuration { get; set; }
+
+ ///
+ /// Directory path for directory operations
+ ///
+ public string? DirectoryPath { get; set; }
+}
diff --git a/RoslynBridge.WebApi/Models/RoslynQueryResponse.cs b/RoslynBridge.WebApi/Models/RoslynQueryResponse.cs
new file mode 100644
index 0000000..6f90d22
--- /dev/null
+++ b/RoslynBridge.WebApi/Models/RoslynQueryResponse.cs
@@ -0,0 +1,27 @@
+namespace RoslynBridge.WebApi.Models;
+
+///
+/// Response model for Roslyn query operations
+///
+public class RoslynQueryResponse
+{
+ ///
+ /// Indicates whether the operation was successful
+ ///
+ public bool Success { get; set; }
+
+ ///
+ /// Optional message providing additional context
+ ///
+ public string? Message { get; set; }
+
+ ///
+ /// The response data (structure varies by query type)
+ ///
+ public object? Data { get; set; }
+
+ ///
+ /// Error message if the operation failed
+ ///
+ public string? Error { get; set; }
+}
diff --git a/RoslynBridge.WebApi/Models/VSInstanceInfo.cs b/RoslynBridge.WebApi/Models/VSInstanceInfo.cs
new file mode 100644
index 0000000..21b7ab6
--- /dev/null
+++ b/RoslynBridge.WebApi/Models/VSInstanceInfo.cs
@@ -0,0 +1,42 @@
+namespace RoslynBridge.WebApi.Models;
+
+///
+/// Information about a registered Visual Studio instance
+///
+public class VSInstanceInfo
+{
+ ///
+ /// The port number where this VS instance is listening
+ ///
+ public int Port { get; set; }
+
+ ///
+ /// The process ID of the Visual Studio instance
+ ///
+ public int ProcessId { get; set; }
+
+ ///
+ /// The solution file path (if any solution is open)
+ ///
+ public string? SolutionPath { get; set; }
+
+ ///
+ /// The solution name (if any solution is open)
+ ///
+ public string? SolutionName { get; set; }
+
+ ///
+ /// When this instance was registered
+ ///
+ public DateTime RegisteredAt { get; set; }
+
+ ///
+ /// Last heartbeat time
+ ///
+ public DateTime LastHeartbeat { get; set; }
+
+ ///
+ /// List of project names in the solution
+ ///
+ public List Projects { get; set; } = new();
+}
diff --git a/RoslynBridge.WebApi/Program.cs b/RoslynBridge.WebApi/Program.cs
new file mode 100644
index 0000000..ab7e40e
--- /dev/null
+++ b/RoslynBridge.WebApi/Program.cs
@@ -0,0 +1,129 @@
+using Microsoft.OpenApi.Models;
+using RoslynBridge.WebApi.Middleware;
+using RoslynBridge.WebApi.Services;
+using System.Reflection;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add Windows Service support
+builder.Services.AddWindowsService(options =>
+{
+ options.ServiceName = "RoslynBridge Web API";
+});
+
+// Configure CORS
+builder.Services.AddCors(options =>
+{
+ options.AddPolicy("AllowAll", policy =>
+ {
+ policy.AllowAnyOrigin()
+ .AllowAnyMethod()
+ .AllowAnyHeader();
+ });
+});
+
+// Add controllers
+builder.Services.AddControllers();
+
+// Register history service as singleton for in-memory storage
+builder.Services.AddSingleton();
+
+// Register instance registry service as singleton
+builder.Services.AddSingleton();
+
+// Register background service for cleaning up stale instances
+builder.Services.AddHostedService();
+
+// Configure HttpClient for Roslyn Bridge
+var roslynBridgeUrl = builder.Configuration.GetValue("RoslynBridge:BaseUrl") ?? "http://localhost:59123";
+builder.Services.AddHttpClient(client =>
+{
+ client.BaseAddress = new Uri(roslynBridgeUrl);
+ client.Timeout = TimeSpan.FromSeconds(30);
+});
+
+// Configure Swagger/OpenAPI
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen(options =>
+{
+ options.SwaggerDoc("v1", new OpenApiInfo
+ {
+ Title = "Roslyn Bridge Web API",
+ Version = "v1.0",
+ Description = "Modern web API middleware for Roslyn Bridge - connecting Claude AI to Visual Studio code analysis",
+ Contact = new OpenApiContact
+ {
+ Name = "Roslyn Bridge",
+ Url = new Uri("https://github.com/yourusername/roslynbridge")
+ }
+ });
+
+ // Include XML comments for better documentation
+ var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
+ var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFilename);
+ if (File.Exists(xmlPath))
+ {
+ options.IncludeXmlComments(xmlPath);
+ }
+
+ // Add operation tags
+ options.TagActionsBy(api =>
+ {
+ if (api.GroupName != null)
+ {
+ return new[] { api.GroupName };
+ }
+
+ if (api.ActionDescriptor is Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor controllerActionDescriptor)
+ {
+ return new[] { controllerActionDescriptor.ControllerName };
+ }
+
+ return new[] { "Unknown" };
+ });
+});
+
+// Add health checks
+builder.Services.AddHealthChecks();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline
+if (app.Environment.IsDevelopment())
+{
+ app.UseDeveloperExceptionPage();
+}
+
+// Enable Swagger in all environments for easy access
+app.UseSwagger();
+app.UseSwaggerUI(options =>
+{
+ options.SwaggerEndpoint("/swagger/v1/swagger.json", "Roslyn Bridge API v1");
+ options.RoutePrefix = string.Empty; // Serve Swagger UI at root
+ options.DocumentTitle = "Roslyn Bridge API";
+ options.DisplayRequestDuration();
+});
+
+app.UseHttpsRedirection();
+
+// Enable CORS
+app.UseCors("AllowAll");
+
+// Enable history tracking middleware (must be before authorization and controllers)
+app.UseHistoryTracking();
+
+app.UseAuthorization();
+
+// Map controllers
+app.MapControllers();
+
+// Map health check endpoint
+app.MapHealthChecks("/health");
+
+// Log startup information
+var logger = app.Services.GetRequiredService>();
+logger.LogInformation("Roslyn Bridge Web API started");
+logger.LogInformation("Swagger UI available at: {Url}", app.Environment.IsDevelopment() ? "https://localhost:7001" : "/");
+logger.LogInformation("Connected to Roslyn Bridge at: {Url}", roslynBridgeUrl);
+
+app.Run();
diff --git a/RoslynBridge.WebApi/Properties/launchSettings.json b/RoslynBridge.WebApi/Properties/launchSettings.json
new file mode 100644
index 0000000..09d7324
--- /dev/null
+++ b/RoslynBridge.WebApi/Properties/launchSettings.json
@@ -0,0 +1,38 @@
+{
+ "$schema": "http://json.schemastore.org/launchsettings.json",
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:43446",
+ "sslPort": 44347
+ }
+ },
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "http://localhost:5113",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:7070;http://localhost:5113",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
diff --git a/RoslynBridge.WebApi/README.md b/RoslynBridge.WebApi/README.md
new file mode 100644
index 0000000..e92d82a
--- /dev/null
+++ b/RoslynBridge.WebApi/README.md
@@ -0,0 +1,378 @@
+# Roslyn Bridge Web API
+
+A modern ASP.NET Core web API that acts as middleware between Claude AI and the Roslyn Bridge Visual Studio plugin, providing RESTful access to C# code analysis capabilities.
+
+## Overview
+
+This web API serves as a bridge between external clients (like Claude AI) and the Visual Studio Roslyn Bridge plugin. It provides:
+
+- **Modern RESTful API** with comprehensive Swagger/OpenAPI documentation
+- **CORS-enabled** for web application access
+- **Health monitoring** for both the web API and Visual Studio plugin connection
+- **Simplified endpoints** for common Roslyn operations
+- **Type-safe models** with validation
+
+## Architecture
+
+```
+┌─────────────┐ HTTP/REST ┌──────────────────┐ HTTP ┌─────────────────────┐
+│ Claude │ ◄─────────────────► │ Web API (5000) │ ◄────────────► │ VS Plugin (59123) │
+│ AI │ │ Middleware │ │ Roslyn Bridge │
+└─────────────┘ └──────────────────┘ └─────────────────────┘
+```
+
+## Getting Started
+
+### Prerequisites
+
+- .NET 8.0 SDK or later
+- Visual Studio with Roslyn Bridge plugin running (default port: 59123)
+
+### Quick Installation
+
+**Option 1: Automated Installation**
+
+Open PowerShell as Administrator:
+```powershell
+cd RoslynBridge.WebApi
+.\install.ps1 -InstallService -StartService
+```
+
+This will build, publish, install as a Windows Service, and start the API automatically.
+
+For more detailed service setup options, see [SERVICE_SETUP.md](SERVICE_SETUP.md).
+
+**Option 2: Development Mode**
+
+1. **Start the Visual Studio plugin** (it should be running on port 59123)
+
+2. **Run the Web API:**
+ ```bash
+ cd RoslynBridge.WebApi
+ dotnet run
+ ```
+
+3. **Access Swagger UI:**
+ - Navigate to: `http://localhost:5000`
+ - Or: `https://localhost:7001` (with HTTPS)
+
+### Configuration
+
+Edit `appsettings.json` to configure the connection:
+
+```json
+{
+ "RoslynBridge": {
+ "BaseUrl": "http://localhost:59123",
+ "TimeoutSeconds": 30
+ }
+}
+```
+
+## API Endpoints
+
+### Health Endpoints
+
+- **GET /api/health** - Check health status of Web API and VS plugin
+- **GET /api/health/ping** - Simple ping endpoint
+
+### Roslyn Query Endpoints
+
+- **POST /api/roslyn/query** - Execute any Roslyn query
+- **GET /api/roslyn/projects** - Get all projects in solution
+- **GET /api/roslyn/solution/overview** - Get solution statistics
+- **GET /api/roslyn/diagnostics** - Get errors and warnings
+- **GET /api/roslyn/symbol** - Get symbol information at position
+- **GET /api/roslyn/references** - Find all references to symbol
+- **GET /api/roslyn/symbol/search** - Search for symbols by name
+
+### Refactoring Endpoints
+
+- **POST /api/roslyn/format** - Format a document
+- **POST /api/roslyn/project/package/add** - Add NuGet package
+- **POST /api/roslyn/project/build** - Build a project
+
+## Example Usage
+
+### Using curl
+
+```bash
+# Health check
+curl http://localhost:5000/api/health
+
+# Get all projects
+curl http://localhost:5000/api/roslyn/projects
+
+# Get solution overview
+curl http://localhost:5000/api/roslyn/solution/overview
+
+# Execute custom query
+curl -X POST http://localhost:5000/api/roslyn/query \
+ -H "Content-Type: application/json" \
+ -d '{
+ "queryType": "getsymbol",
+ "filePath": "C:\\path\\to\\file.cs",
+ "line": 10,
+ "column": 5
+ }'
+
+# Search for symbols
+curl "http://localhost:5000/api/roslyn/symbol/search?symbolName=MyClass"
+
+# Get diagnostics
+curl "http://localhost:5000/api/roslyn/diagnostics"
+```
+
+### Using JavaScript/TypeScript
+
+```typescript
+const response = await fetch('http://localhost:5000/api/roslyn/query', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ queryType: 'getprojects'
+ })
+});
+
+const result = await response.json();
+console.log(result.data);
+```
+
+### Using C#
+
+```csharp
+using var client = new HttpClient();
+client.BaseAddress = new Uri("http://localhost:5000");
+
+var request = new RoslynQueryRequest
+{
+ QueryType = "getsolutionoverview"
+};
+
+var response = await client.PostAsJsonAsync("/api/roslyn/query", request);
+var result = await response.Content.ReadFromJsonAsync();
+```
+
+## Query Types
+
+The following query types are supported:
+
+### Code Analysis
+- `getprojects` - Get all projects
+- `getdocument` - Get document information
+- `getsymbol` - Get symbol at position
+- `getsemanticmodel` - Get semantic model
+- `getsyntaxtree` - Get syntax tree
+- `getdiagnostics` - Get compilation errors/warnings
+- `findreferences` - Find all references
+- `findsymbol` - Find symbols by name
+- `gettypemembers` - Get type members
+- `gettypehierarchy` - Get type hierarchy
+- `findimplementations` - Find implementations
+- `getnamespacetypes` - Get namespace types
+- `getcallhierarchy` - Get call hierarchy
+- `getsolutionoverview` - Get solution overview
+- `getsymbolcontext` - Get symbol context
+- `searchcode` - Search code patterns
+
+### Refactoring
+- `formatdocument` - Format document
+- `organizeusings` - Organize using statements
+- `renamesymbol` - Rename symbol
+- `addmissingusing` - Add missing using
+- `applycodefix` - Apply code fix
+
+### Project Operations
+- `addnugetpackage` - Add NuGet package
+- `removenugetpackage` - Remove NuGet package
+- `buildproject` - Build project
+- `cleanproject` - Clean project
+- `restorepackages` - Restore packages
+- `createdirectory` - Create directory
+
+## Response Format
+
+All responses follow this structure:
+
+```json
+{
+ "success": true,
+ "message": "Optional message",
+ "data": { ... },
+ "error": null
+}
+```
+
+Error responses:
+
+```json
+{
+ "success": false,
+ "message": null,
+ "data": null,
+ "error": "Error description"
+}
+```
+
+## Features
+
+### CORS Support
+The API is configured with CORS enabled for all origins, making it accessible from web applications.
+
+### Swagger/OpenAPI
+Comprehensive API documentation is available at the root URL (`/`) with:
+- Detailed endpoint descriptions
+- Request/response models
+- Try-it-out functionality
+- XML documentation comments
+
+### Health Checks
+Built-in health checks monitor:
+- Web API service status
+- Visual Studio plugin connectivity
+- Request/response timing
+
+### Logging
+Structured logging with different levels:
+- Information: General operations
+- Warning: Non-critical issues
+- Error: Failed operations
+- Debug: Detailed tracing (Development only)
+
+## Development
+
+### Project Structure
+
+```
+RoslynBridge.WebApi/
+├── Controllers/
+│ ├── HealthController.cs # Health check endpoints
+│ └── RoslynController.cs # Roslyn operation endpoints
+├── Models/
+│ ├── RoslynQueryRequest.cs # Request DTOs
+│ ├── RoslynQueryResponse.cs # Response DTOs
+│ └── HealthCheckResponse.cs # Health check models
+├── Services/
+│ ├── IRoslynBridgeClient.cs # Client interface
+│ └── RoslynBridgeClient.cs # HTTP client implementation
+├── Program.cs # Application configuration
+├── appsettings.json # Configuration
+└── README.md # This file
+```
+
+### Building
+
+```bash
+dotnet build
+```
+
+### Running Tests
+
+```bash
+dotnet test
+```
+
+### Publishing
+
+```bash
+dotnet publish -c Release -o ./publish
+```
+
+## Deployment
+
+### Docker (Optional)
+
+Create a `Dockerfile`:
+
+```dockerfile
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
+WORKDIR /app
+EXPOSE 5000
+
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
+WORKDIR /src
+COPY ["RoslynBridge.WebApi.csproj", "./"]
+RUN dotnet restore
+COPY . .
+RUN dotnet build -c Release -o /app/build
+
+FROM build AS publish
+RUN dotnet publish -c Release -o /app/publish
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "RoslynBridge.WebApi.dll"]
+```
+
+Build and run:
+
+```bash
+docker build -t roslyn-bridge-api .
+docker run -p 5000:5000 roslyn-bridge-api
+```
+
+## Integration with Claude
+
+This API is designed to work seamlessly with Claude AI for code analysis tasks:
+
+1. Claude can query project structure
+2. Analyze code for errors and warnings
+3. Search for symbols and references
+4. Suggest refactorings
+5. Navigate code hierarchies
+
+Example Claude prompt:
+```
+"Using the Roslyn Bridge API at http://localhost:5000,
+analyze the current solution and identify any code quality issues."
+```
+
+## Troubleshooting
+
+### Visual Studio Plugin Not Connected
+
+Error: `{"vsPluginStatus": "Disconnected"}`
+
+**Solution:**
+1. Ensure Visual Studio is running
+2. Verify Roslyn Bridge plugin is installed and active
+3. Check plugin is listening on port 59123
+4. Update `appsettings.json` if using a different port
+
+### CORS Errors
+
+If accessing from a web app:
+- Verify CORS is enabled in `Program.cs`
+- Check browser console for specific CORS errors
+- Ensure the origin is allowed
+
+### Timeout Errors
+
+Increase timeout in `appsettings.json`:
+```json
+{
+ "RoslynBridge": {
+ "TimeoutSeconds": 60
+ }
+}
+```
+
+## License
+
+This project is part of the Roslyn Bridge suite.
+
+## Contributing
+
+Contributions are welcome! Please:
+1. Fork the repository
+2. Create a feature branch
+3. Make your changes
+4. Submit a pull request
+
+## Support
+
+For issues and questions:
+- Check the Swagger documentation at `/`
+- Review the logs in the console output
+- Verify the Visual Studio plugin is running
diff --git a/RoslynBridge.WebApi/RoslynBridge.WebApi.csproj b/RoslynBridge.WebApi/RoslynBridge.WebApi.csproj
new file mode 100644
index 0000000..35989f1
--- /dev/null
+++ b/RoslynBridge.WebApi/RoslynBridge.WebApi.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net8.0
+ enable
+ enable
+ true
+ $(NoWarn);1591
+
+
+
+
+
+
+
+
+
diff --git a/RoslynBridge.WebApi/SERVICE_SETUP.md b/RoslynBridge.WebApi/SERVICE_SETUP.md
new file mode 100644
index 0000000..75edda9
--- /dev/null
+++ b/RoslynBridge.WebApi/SERVICE_SETUP.md
@@ -0,0 +1,351 @@
+# Roslyn Bridge Web API - Windows Service Setup
+
+This guide explains how to install and run the Roslyn Bridge Web API as a Windows Service for always-on operation.
+
+## Prerequisites
+
+- **Administrator privileges** required for service installation
+- **.NET 8.0 Runtime** or SDK installed
+- **Visual Studio** with Roslyn Bridge extension must be running (the VS plugin on port 59123 is required)
+
+## Quick Start
+
+### Option 1: Automated Installation (Recommended)
+
+Open PowerShell **as Administrator** and run:
+
+```powershell
+# Navigate to the project directory
+cd C:\Path\To\RoslynBridge.WebApi
+
+# Complete installation (build, publish, install service, and start)
+.\install.ps1 -InstallService -StartService
+```
+
+This single command will:
+1. Check prerequisites (.NET SDK)
+2. Restore NuGet packages
+3. Build the project
+4. Publish to `./publish`
+5. Install as Windows Service
+6. Start the service
+
+### Option 2: Manual Step-by-Step Installation
+
+#### 1. Publish the Application
+
+```powershell
+# Navigate to the project directory
+cd C:\Path\To\RoslynBridge.WebApi
+
+# Publish the application for Release
+dotnet publish -c Release -o publish
+```
+
+This creates a self-contained deployment in the `publish` folder.
+
+#### 2. Install as Windows Service
+
+Open PowerShell **as Administrator**:
+
+```powershell
+# Install the service
+.\install-service.ps1 -Action Install
+
+# Start the service
+.\install-service.ps1 -Action Start
+
+# Check service status
+.\install-service.ps1 -Action Status
+```
+
+### 3. Verify Installation
+
+1. Open Windows Services (`services.msc`)
+2. Look for "Roslyn Bridge Web API"
+3. Verify it's running
+4. Test the API: http://localhost:5000/api/health
+
+## Installation Script Options
+
+The `install.ps1` script provides several options for different scenarios:
+
+```powershell
+# Full automated installation
+.\install.ps1 -InstallService -StartService
+
+# Build and publish only (no service installation)
+.\install.ps1
+
+# Skip build, just publish and install
+.\install.ps1 -SkipBuild -InstallService
+
+# Debug build instead of Release
+.\install.ps1 -Configuration Debug
+
+# Custom publish path
+.\install.ps1 -PublishPath "C:\MyApp\Publish" -InstallService
+
+# Reinstall after code changes
+.\install.ps1 -InstallService
+```
+
+## Service Management Commands
+
+```powershell
+# Install service
+.\install-service.ps1 -Action Install
+
+# Start service
+.\install-service.ps1 -Action Start
+
+# Stop service
+.\install-service.ps1 -Action Stop
+
+# Restart service
+.\install-service.ps1 -Action Restart
+
+# Check status
+.\install-service.ps1 -Action Status
+
+# Uninstall service
+.\install-service.ps1 -Action Uninstall
+```
+
+## Configuration
+
+### Service Settings
+
+The service is configured with:
+- **Service Name**: `RoslynBridgeWebApi`
+- **Display Name**: Roslyn Bridge Web API
+- **Startup Type**: Automatic (starts with Windows)
+- **Port**: 5000 (HTTP)
+
+### Changing the Port
+
+Edit `appsettings.json` before publishing:
+
+```json
+{
+ "Kestrel": {
+ "Endpoints": {
+ "Http": {
+ "Url": "http://localhost:YOUR_PORT"
+ }
+ }
+ }
+}
+```
+
+### Logging
+
+When running as a service, logs are written to:
+- **Windows Event Log**: Application → "Roslyn Bridge Web API"
+- **Console**: Not available when running as service
+
+To view logs:
+1. Open Event Viewer
+2. Navigate to: Windows Logs → Application
+3. Filter by source: "Roslyn Bridge Web API"
+
+## Troubleshooting
+
+### Service Won't Start
+
+**Symptom**: Service starts then immediately stops
+
+**Possible Causes**:
+1. Port 5000 is already in use
+2. Visual Studio plugin (port 59123) is not running
+3. Missing .NET runtime
+
+**Solutions**:
+```powershell
+# Check if port 5000 is in use
+netstat -ano | findstr :5000
+
+# Check if VS plugin is accessible
+curl -X POST http://localhost:59123/health -H "Content-Type: application/json" -d "{}"
+
+# Check Event Log for errors
+Get-EventLog -LogName Application -Source "Roslyn Bridge Web API" -Newest 10
+```
+
+### Service Installed but API Not Responding
+
+**Check the following**:
+1. Service is running: `.\install-service.ps1 -Action Status`
+2. Visual Studio is open with a solution loaded
+3. Firewall isn't blocking port 5000
+
+### Updating the Service
+
+When you update the code:
+
+**Option 1: Using install.ps1 (Recommended)**
+
+```powershell
+# Stop service, rebuild, republish, and restart
+.\install-service.ps1 -Action Stop
+.\install.ps1
+.\install-service.ps1 -Action Start
+```
+
+**Option 2: Manual Method**
+
+```powershell
+# 1. Stop the service
+.\install-service.ps1 -Action Stop
+
+# 2. Republish
+dotnet publish -c Release -o publish
+
+# 3. Restart the service
+.\install-service.ps1 -Action Start
+```
+
+**Option 3: Full Reinstall**
+
+```powershell
+# Uninstall, republish, and reinstall
+.\install-service.ps1 -Action Uninstall
+.\install.ps1 -InstallService -StartService
+```
+
+## Alternative: Manual Service Installation
+
+If you prefer to use `sc.exe` directly:
+
+```cmd
+# Install
+sc create RoslynBridgeWebApi binPath="C:\Path\To\publish\RoslynBridge.WebApi.exe" start=auto
+
+# Start
+sc start RoslynBridgeWebApi
+
+# Stop
+sc stop RoslynBridgeWebApi
+
+# Delete
+sc delete RoslynBridgeWebApi
+```
+
+## Running in Development
+
+For development, you don't need to install as a service. Just run:
+
+```powershell
+dotnet run --urls "http://localhost:5000"
+```
+
+The application will work the same way but won't persist after closing the terminal.
+
+## Security Considerations
+
+### Production Deployment
+
+For production environments:
+
+1. **Use HTTPS**: Configure SSL certificates in `appsettings.json`
+2. **Restrict CORS**: Update the CORS policy to allow only specific origins
+3. **Add Authentication**: Consider adding API key or OAuth authentication
+4. **Firewall**: Only allow access from trusted IPs
+
+### Network Access
+
+By default, the service only listens on `localhost:5000`. To allow external access:
+
+```json
+{
+ "Kestrel": {
+ "Endpoints": {
+ "Http": {
+ "Url": "http://0.0.0.0:5000"
+ }
+ }
+ }
+}
+```
+
+**Warning**: Only do this in trusted networks. Add authentication first!
+
+## Service Lifecycle
+
+The service:
+1. **Starts automatically** when Windows boots
+2. **Requires Visual Studio** to be running (with a solution loaded) for full functionality
+3. **Tracks request history** in memory (lost on restart)
+4. **Logs to Event Log** for monitoring
+
+## Monitoring
+
+### Check Service Status
+
+```powershell
+# PowerShell
+Get-Service RoslynBridgeWebApi
+
+# Or use the script
+.\install-service.ps1 -Action Status
+```
+
+### View Logs
+
+```powershell
+# View recent logs
+Get-EventLog -LogName Application -Source "Roslyn Bridge Web API" -Newest 20
+
+# Monitor logs in real-time
+Get-EventLog -LogName Application -Source "Roslyn Bridge Web API" -Newest 1 -AsString
+# Press Ctrl+C to stop
+```
+
+### Test API Health
+
+```powershell
+# Quick ping
+curl http://localhost:5000/api/health/ping
+
+# Full health check (includes VS plugin status)
+curl http://localhost:5000/api/health
+
+# View Swagger documentation
+Start-Process "http://localhost:5000"
+```
+
+## Uninstalling
+
+To completely remove the service:
+
+```powershell
+# Stop and uninstall
+.\install-service.ps1 -Action Uninstall
+
+# Optional: Delete the publish folder
+Remove-Item -Path ".\publish" -Recurse -Force
+```
+
+## Additional Resources
+
+- **Swagger UI**: http://localhost:5000 (when service is running)
+- **Health Check**: http://localhost:5000/api/health
+- **History Stats**: http://localhost:5000/api/history/stats
+- **Event Viewer**: Windows Logs → Application → "Roslyn Bridge Web API"
+
+## FAQ
+
+**Q: Do I need to keep Visual Studio open?**
+A: Yes, the VS plugin (port 59123) must be running. The Web API is just a middleware layer.
+
+**Q: Can I run multiple instances?**
+A: Yes, but change the port in `appsettings.json` for each instance.
+
+**Q: What happens if the service can't connect to VS plugin?**
+A: API calls will return errors, but the service remains running. History and health endpoints still work.
+
+**Q: Can I use this without the Web API?**
+A: Yes, you can call the VS plugin directly on port 59123 using POST requests (see roslyn-bridge skill).
+
+**Q: How do I backup request history?**
+A: History is in-memory only. Consider implementing database persistence for production use.
diff --git a/RoslynBridge.WebApi/Services/HistoryService.cs b/RoslynBridge.WebApi/Services/HistoryService.cs
new file mode 100644
index 0000000..03df7b5
--- /dev/null
+++ b/RoslynBridge.WebApi/Services/HistoryService.cs
@@ -0,0 +1,59 @@
+using System.Collections.Concurrent;
+using RoslynBridge.WebApi.Models;
+
+namespace RoslynBridge.WebApi.Services;
+
+///
+/// In-memory implementation of history service
+///
+public class HistoryService : IHistoryService
+{
+ private readonly ConcurrentQueue _entries = new();
+ private readonly ILogger _logger;
+ private readonly int _maxEntries;
+
+ public HistoryService(ILogger logger, IConfiguration configuration)
+ {
+ _logger = logger;
+ _maxEntries = configuration.GetValue("History:MaxEntries", 1000);
+ }
+
+ public void Add(QueryHistoryEntry entry)
+ {
+ _entries.Enqueue(entry);
+
+ // Trim old entries if we exceed max
+ while (_entries.Count > _maxEntries)
+ {
+ _entries.TryDequeue(out _);
+ }
+
+ _logger.LogDebug("Added history entry: {Id} - {Path}", entry.Id, entry.Path);
+ }
+
+ public IEnumerable GetAll()
+ {
+ return _entries.Reverse();
+ }
+
+ public QueryHistoryEntry? GetById(string id)
+ {
+ return _entries.FirstOrDefault(e => e.Id == id);
+ }
+
+ public IEnumerable GetRecent(int count = 50)
+ {
+ return _entries.Reverse().Take(count);
+ }
+
+ public void Clear()
+ {
+ _entries.Clear();
+ _logger.LogInformation("History cleared");
+ }
+
+ public int GetCount()
+ {
+ return _entries.Count;
+ }
+}
diff --git a/RoslynBridge.WebApi/Services/IHistoryService.cs b/RoslynBridge.WebApi/Services/IHistoryService.cs
new file mode 100644
index 0000000..7ad29dc
--- /dev/null
+++ b/RoslynBridge.WebApi/Services/IHistoryService.cs
@@ -0,0 +1,46 @@
+using RoslynBridge.WebApi.Models;
+
+namespace RoslynBridge.WebApi.Services;
+
+///
+/// Service for managing query history
+///
+public interface IHistoryService
+{
+ ///
+ /// Add a new history entry
+ ///
+ /// The history entry to add
+ void Add(QueryHistoryEntry entry);
+
+ ///
+ /// Get all history entries
+ ///
+ /// List of all history entries
+ IEnumerable GetAll();
+
+ ///
+ /// Get a specific history entry by ID
+ ///
+ /// The entry ID
+ /// The history entry, or null if not found
+ QueryHistoryEntry? GetById(string id);
+
+ ///
+ /// Get recent history entries
+ ///
+ /// Number of entries to return
+ /// List of recent history entries
+ IEnumerable GetRecent(int count = 50);
+
+ ///
+ /// Clear all history entries
+ ///
+ void Clear();
+
+ ///
+ /// Get total count of history entries
+ ///
+ /// Total number of entries
+ int GetCount();
+}
diff --git a/RoslynBridge.WebApi/Services/IInstanceRegistryService.cs b/RoslynBridge.WebApi/Services/IInstanceRegistryService.cs
new file mode 100644
index 0000000..9e1b218
--- /dev/null
+++ b/RoslynBridge.WebApi/Services/IInstanceRegistryService.cs
@@ -0,0 +1,49 @@
+using RoslynBridge.WebApi.Models;
+
+namespace RoslynBridge.WebApi.Services;
+
+///
+/// Service for managing registered Visual Studio instances
+///
+public interface IInstanceRegistryService
+{
+ ///
+ /// Register a new Visual Studio instance
+ ///
+ void Register(VSInstanceInfo instance);
+
+ ///
+ /// Unregister a Visual Studio instance by process ID
+ ///
+ bool Unregister(int processId);
+
+ ///
+ /// Update heartbeat for an instance
+ ///
+ bool UpdateHeartbeat(int processId);
+
+ ///
+ /// Get all registered instances
+ ///
+ IEnumerable GetAllInstances();
+
+ ///
+ /// Get instance by process ID
+ ///
+ VSInstanceInfo? GetByProcessId(int processId);
+
+ ///
+ /// Get instance by solution path
+ ///
+ VSInstanceInfo? GetBySolutionPath(string solutionPath);
+
+ ///
+ /// Get instance by port
+ ///
+ VSInstanceInfo? GetByPort(int port);
+
+ ///
+ /// Remove stale instances (no heartbeat for specified timeout)
+ ///
+ void RemoveStaleInstances(TimeSpan timeout);
+}
diff --git a/RoslynBridge.WebApi/Services/IRoslynBridgeClient.cs b/RoslynBridge.WebApi/Services/IRoslynBridgeClient.cs
new file mode 100644
index 0000000..7d95e90
--- /dev/null
+++ b/RoslynBridge.WebApi/Services/IRoslynBridgeClient.cs
@@ -0,0 +1,26 @@
+using RoslynBridge.WebApi.Models;
+
+namespace RoslynBridge.WebApi.Services;
+
+///
+/// Interface for communicating with the Roslyn Bridge Visual Studio plugin
+///
+public interface IRoslynBridgeClient
+{
+ ///
+ /// Execute a query against the Roslyn Bridge server
+ ///
+ /// The query request
+ /// Optional port of specific VS instance to target
+ /// Cancellation token
+ /// The query response
+ Task ExecuteQueryAsync(RoslynQueryRequest request, int? instancePort = null, CancellationToken cancellationToken = default);
+
+ ///
+ /// Check if the Roslyn Bridge server is healthy
+ ///
+ /// Optional port of specific VS instance to check
+ /// Cancellation token
+ /// True if healthy, false otherwise
+ Task IsHealthyAsync(int? instancePort = null, CancellationToken cancellationToken = default);
+}
diff --git a/RoslynBridge.WebApi/Services/InstanceCleanupService.cs b/RoslynBridge.WebApi/Services/InstanceCleanupService.cs
new file mode 100644
index 0000000..9694388
--- /dev/null
+++ b/RoslynBridge.WebApi/Services/InstanceCleanupService.cs
@@ -0,0 +1,50 @@
+namespace RoslynBridge.WebApi.Services;
+
+///
+/// Background service that periodically removes stale VS instances
+///
+public class InstanceCleanupService : BackgroundService
+{
+ private readonly IServiceProvider _serviceProvider;
+ private readonly ILogger _logger;
+ private readonly TimeSpan _cleanupInterval = TimeSpan.FromMinutes(1);
+ private readonly TimeSpan _staleTimeout = TimeSpan.FromMinutes(5);
+
+ public InstanceCleanupService(
+ IServiceProvider serviceProvider,
+ ILogger logger)
+ {
+ _serviceProvider = serviceProvider;
+ _logger = logger;
+ }
+
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+ {
+ _logger.LogInformation("Instance cleanup service started");
+
+ while (!stoppingToken.IsCancellationRequested)
+ {
+ try
+ {
+ await Task.Delay(_cleanupInterval, stoppingToken);
+
+ // Get the registry service from scope
+ using var scope = _serviceProvider.CreateScope();
+ var registryService = scope.ServiceProvider.GetRequiredService();
+
+ registryService.RemoveStaleInstances(_staleTimeout);
+ }
+ catch (OperationCanceledException)
+ {
+ // Expected when stopping
+ break;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error during instance cleanup");
+ }
+ }
+
+ _logger.LogInformation("Instance cleanup service stopped");
+ }
+}
diff --git a/RoslynBridge.WebApi/Services/InstanceRegistryService.cs b/RoslynBridge.WebApi/Services/InstanceRegistryService.cs
new file mode 100644
index 0000000..7fd58f1
--- /dev/null
+++ b/RoslynBridge.WebApi/Services/InstanceRegistryService.cs
@@ -0,0 +1,115 @@
+using System.Collections.Concurrent;
+using RoslynBridge.WebApi.Models;
+
+namespace RoslynBridge.WebApi.Services;
+
+///
+/// Thread-safe in-memory registry for Visual Studio instances
+///
+public class InstanceRegistryService : IInstanceRegistryService
+{
+ private readonly ConcurrentDictionary _instances = new();
+ private readonly ILogger _logger;
+
+ public InstanceRegistryService(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public void Register(VSInstanceInfo instance)
+ {
+ instance.RegisteredAt = DateTime.UtcNow;
+ instance.LastHeartbeat = DateTime.UtcNow;
+
+ _instances.AddOrUpdate(instance.ProcessId, instance, (_, existing) =>
+ {
+ // Update existing instance
+ existing.Port = instance.Port;
+ existing.SolutionPath = instance.SolutionPath;
+ existing.SolutionName = instance.SolutionName;
+ existing.Projects = instance.Projects;
+ existing.LastHeartbeat = DateTime.UtcNow;
+ return existing;
+ });
+
+ _logger.LogInformation(
+ "Registered VS instance: PID={ProcessId}, Port={Port}, Solution={Solution}",
+ instance.ProcessId,
+ instance.Port,
+ instance.SolutionName ?? "None");
+ }
+
+ public bool Unregister(int processId)
+ {
+ var removed = _instances.TryRemove(processId, out var instance);
+
+ if (removed)
+ {
+ _logger.LogInformation(
+ "Unregistered VS instance: PID={ProcessId}, Solution={Solution}",
+ processId,
+ instance?.SolutionName ?? "None");
+ }
+
+ return removed;
+ }
+
+ public bool UpdateHeartbeat(int processId)
+ {
+ if (_instances.TryGetValue(processId, out var instance))
+ {
+ instance.LastHeartbeat = DateTime.UtcNow;
+ _logger.LogDebug("Updated heartbeat for VS instance: PID={ProcessId}", processId);
+ return true;
+ }
+
+ return false;
+ }
+
+ public IEnumerable GetAllInstances()
+ {
+ return _instances.Values.ToList();
+ }
+
+ public VSInstanceInfo? GetByProcessId(int processId)
+ {
+ _instances.TryGetValue(processId, out var instance);
+ return instance;
+ }
+
+ public VSInstanceInfo? GetBySolutionPath(string solutionPath)
+ {
+ if (string.IsNullOrEmpty(solutionPath))
+ return null;
+
+ var normalizedPath = Path.GetFullPath(solutionPath).ToLowerInvariant();
+
+ return _instances.Values.FirstOrDefault(i =>
+ !string.IsNullOrEmpty(i.SolutionPath) &&
+ Path.GetFullPath(i.SolutionPath).ToLowerInvariant() == normalizedPath);
+ }
+
+ public VSInstanceInfo? GetByPort(int port)
+ {
+ return _instances.Values.FirstOrDefault(i => i.Port == port);
+ }
+
+ public void RemoveStaleInstances(TimeSpan timeout)
+ {
+ var cutoff = DateTime.UtcNow - timeout;
+ var staleInstances = _instances.Values
+ .Where(i => i.LastHeartbeat < cutoff)
+ .ToList();
+
+ foreach (var instance in staleInstances)
+ {
+ if (_instances.TryRemove(instance.ProcessId, out _))
+ {
+ _logger.LogWarning(
+ "Removed stale VS instance: PID={ProcessId}, LastHeartbeat={LastHeartbeat}",
+ instance.ProcessId,
+ instance.LastHeartbeat);
+ }
+ }
+ }
+}
diff --git a/RoslynBridge.WebApi/Services/RoslynBridgeClient.cs b/RoslynBridge.WebApi/Services/RoslynBridgeClient.cs
new file mode 100644
index 0000000..7f59199
--- /dev/null
+++ b/RoslynBridge.WebApi/Services/RoslynBridgeClient.cs
@@ -0,0 +1,174 @@
+using System.Text;
+using System.Text.Json;
+using RoslynBridge.WebApi.Models;
+
+namespace RoslynBridge.WebApi.Services;
+
+///
+/// HTTP client for communicating with the Roslyn Bridge Visual Studio plugin
+///
+public class RoslynBridgeClient : IRoslynBridgeClient
+{
+ private readonly HttpClient _httpClient;
+ private readonly IInstanceRegistryService _registryService;
+ private readonly ILogger _logger;
+ private readonly JsonSerializerOptions _jsonOptions;
+
+ public RoslynBridgeClient(
+ HttpClient httpClient,
+ IInstanceRegistryService registryService,
+ ILogger logger)
+ {
+ _httpClient = httpClient;
+ _registryService = registryService;
+ _logger = logger;
+ _jsonOptions = new JsonSerializerOptions
+ {
+ PropertyNameCaseInsensitive = true,
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase
+ };
+ }
+
+ public async Task ExecuteQueryAsync(
+ RoslynQueryRequest request,
+ int? instancePort = null,
+ CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ var targetPort = await ResolveInstancePortAsync(instancePort, request);
+
+ if (targetPort == null)
+ {
+ return new RoslynQueryResponse
+ {
+ Success = false,
+ Error = "No Visual Studio instance available"
+ };
+ }
+
+ _logger.LogInformation("Executing query: {QueryType} on port {Port}", request.QueryType, targetPort);
+
+ var json = JsonSerializer.Serialize(request, _jsonOptions);
+ var content = new StringContent(json, Encoding.UTF8, "application/json");
+
+ var url = $"http://localhost:{targetPort}/query";
+ var response = await _httpClient.PostAsync(url, content, cancellationToken);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ var errorContent = await response.Content.ReadAsStringAsync(cancellationToken);
+ _logger.LogError("Query failed with status {StatusCode}: {Error}", response.StatusCode, errorContent);
+
+ return new RoslynQueryResponse
+ {
+ Success = false,
+ Error = $"Request failed with status {response.StatusCode}: {errorContent}"
+ };
+ }
+
+ var responseContent = await response.Content.ReadAsStringAsync(cancellationToken);
+ var result = JsonSerializer.Deserialize(responseContent, _jsonOptions);
+
+ if (result == null)
+ {
+ return new RoslynQueryResponse
+ {
+ Success = false,
+ Error = "Failed to deserialize response"
+ };
+ }
+
+ _logger.LogInformation("Query executed successfully: {Success}", result.Success);
+ return result;
+ }
+ catch (HttpRequestException ex)
+ {
+ _logger.LogError(ex, "HTTP request failed while executing query");
+ return new RoslynQueryResponse
+ {
+ Success = false,
+ Error = $"Failed to connect to Roslyn Bridge server: {ex.Message}"
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Unexpected error while executing query");
+ return new RoslynQueryResponse
+ {
+ Success = false,
+ Error = $"Unexpected error: {ex.Message}"
+ };
+ }
+ }
+
+ public async Task IsHealthyAsync(int? instancePort = null, CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ var targetPort = await ResolveInstancePortAsync(instancePort, null);
+
+ if (targetPort == null)
+ {
+ return false;
+ }
+
+ var request = new RoslynQueryRequest { QueryType = "health" };
+ var json = JsonSerializer.Serialize(request, _jsonOptions);
+ var content = new StringContent(json, Encoding.UTF8, "application/json");
+
+ var url = $"http://localhost:{targetPort}/health";
+ var response = await _httpClient.PostAsync(url, content, cancellationToken);
+ return response.IsSuccessStatusCode;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogWarning(ex, "Health check failed");
+ return false;
+ }
+ }
+
+ ///
+ /// Resolves which VS instance port to use based on provided hints
+ ///
+ private Task ResolveInstancePortAsync(int? explicitPort, RoslynQueryRequest? request)
+ {
+ // If explicit port specified, use it
+ if (explicitPort.HasValue)
+ {
+ return Task.FromResult(explicitPort.Value);
+ }
+
+ // Try to find instance by solution path from request
+ if (request != null && !string.IsNullOrEmpty(request.FilePath))
+ {
+ // Extract solution path by looking for .sln file in the path hierarchy
+ var directory = Path.GetDirectoryName(request.FilePath);
+ while (!string.IsNullOrEmpty(directory))
+ {
+ var solutionFiles = Directory.GetFiles(directory, "*.sln");
+ if (solutionFiles.Length > 0)
+ {
+ var instance = _registryService.GetBySolutionPath(solutionFiles[0]);
+ if (instance != null)
+ {
+ _logger.LogDebug("Found instance by solution path: {SolutionPath}", solutionFiles[0]);
+ return Task.FromResult(instance.Port);
+ }
+ }
+ directory = Path.GetDirectoryName(directory);
+ }
+ }
+
+ // Fall back to first available instance
+ var instances = _registryService.GetAllInstances().ToList();
+ if (instances.Any())
+ {
+ _logger.LogDebug("Using first available instance: port {Port}", instances[0].Port);
+ return Task.FromResult(instances[0].Port);
+ }
+
+ _logger.LogWarning("No Visual Studio instances registered");
+ return Task.FromResult(null);
+ }
+}
diff --git a/RoslynBridge.WebApi/appsettings.Development.json b/RoslynBridge.WebApi/appsettings.Development.json
new file mode 100644
index 0000000..d9e464b
--- /dev/null
+++ b/RoslynBridge.WebApi/appsettings.Development.json
@@ -0,0 +1,12 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "RoslynBridge.WebApi": "Debug"
+ }
+ },
+ "RoslynBridge": {
+ "BaseUrl": "http://localhost:59123"
+ }
+}
diff --git a/RoslynBridge.WebApi/appsettings.json b/RoslynBridge.WebApi/appsettings.json
new file mode 100644
index 0000000..bc6705a
--- /dev/null
+++ b/RoslynBridge.WebApi/appsettings.json
@@ -0,0 +1,33 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "RoslynBridge.WebApi": "Information"
+ },
+ "EventLog": {
+ "SourceName": "Roslyn Bridge Web API",
+ "LogName": "Application",
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+ },
+ "AllowedHosts": "*",
+ "RoslynBridge": {
+ "BaseUrl": "http://localhost:59123",
+ "TimeoutSeconds": 30
+ },
+ "History": {
+ "MaxEntries": 1000,
+ "Enabled": true
+ },
+ "Kestrel": {
+ "Endpoints": {
+ "Http": {
+ "Url": "http://localhost:5001"
+ }
+ }
+ }
+}
diff --git a/RoslynBridge.WebApi/install.ps1 b/RoslynBridge.WebApi/install.ps1
new file mode 100644
index 0000000..a1092e3
--- /dev/null
+++ b/RoslynBridge.WebApi/install.ps1
@@ -0,0 +1,361 @@
+#Requires -RunAsAdministrator
+
+<#
+.SYNOPSIS
+ Complete installation script for Roslyn Bridge Web API
+
+.DESCRIPTION
+ This script performs a complete installation of the Roslyn Bridge Web API:
+ - Checks prerequisites (.NET SDK)
+ - Restores NuGet packages
+ - Builds the project
+ - Publishes the release build
+ - Optionally installs as Windows Service
+ - Tests the installation
+
+.PARAMETER SkipBuild
+ Skip the build step (use existing build)
+
+.PARAMETER SkipPublish
+ Skip the publish step (use existing publish)
+
+.PARAMETER InstallService
+ Install as Windows Service after publishing
+
+.PARAMETER StartService
+ Start the service after installation (requires -InstallService)
+
+.PARAMETER Configuration
+ Build configuration (Debug or Release). Default: Release
+
+.PARAMETER PublishPath
+ Path where the application will be published. Default: ./publish
+
+.EXAMPLE
+ .\install.ps1
+ Full installation without service setup
+
+.EXAMPLE
+ .\install.ps1 -InstallService -StartService
+ Full installation with automatic service setup and start
+
+.EXAMPLE
+ .\install.ps1 -Configuration Debug
+ Install debug build instead of release
+#>
+
+param(
+ [Parameter(Mandatory=$false)]
+ [switch]$SkipBuild,
+
+ [Parameter(Mandatory=$false)]
+ [switch]$SkipPublish,
+
+ [Parameter(Mandatory=$false)]
+ [switch]$InstallService,
+
+ [Parameter(Mandatory=$false)]
+ [switch]$StartService,
+
+ [Parameter(Mandatory=$false)]
+ [ValidateSet("Debug", "Release")]
+ [string]$Configuration = "Release",
+
+ [Parameter(Mandatory=$false)]
+ [string]$PublishPath = ".\publish"
+)
+
+# Script configuration
+$ErrorActionPreference = "Stop"
+$ProjectName = "RoslynBridge.WebApi"
+$ProjectFile = ".\RoslynBridge.WebApi.csproj"
+
+# Color output helper
+function Write-ColorOutput {
+ param(
+ [string]$Message,
+ [string]$Color = "White"
+ )
+ Write-Host $Message -ForegroundColor $Color
+}
+
+# Banner
+function Show-Banner {
+ Write-ColorOutput "`n============================================================" "Cyan"
+ Write-ColorOutput " Roslyn Bridge Web API - Installation Script" "Cyan"
+ Write-ColorOutput "============================================================`n" "Cyan"
+}
+
+# Step counter
+$script:stepNumber = 0
+function Write-Step {
+ param([string]$Message)
+ $script:stepNumber++
+ Write-ColorOutput "`n[$script:stepNumber] $Message" "Yellow"
+ Write-ColorOutput ("-" * 60) "DarkGray"
+}
+
+# Check prerequisites
+function Test-Prerequisites {
+ Write-Step "Checking Prerequisites"
+
+ # Check for .NET SDK
+ Write-Host "Checking for .NET SDK... " -NoNewline
+ try {
+ $dotnetVersion = dotnet --version 2>$null
+ if ($LASTEXITCODE -eq 0) {
+ Write-ColorOutput "Found v$dotnetVersion" "Green"
+ } else {
+ throw "dotnet command failed"
+ }
+ }
+ catch {
+ Write-ColorOutput "NOT FOUND" "Red"
+ Write-ColorOutput "`nError: .NET SDK is not installed or not in PATH." "Red"
+ Write-ColorOutput "Please download and install from: https://dot.net" "Yellow"
+ exit 1
+ }
+
+ # Check for project file
+ Write-Host "Checking for project file... " -NoNewline
+ if (Test-Path $ProjectFile) {
+ Write-ColorOutput "Found" "Green"
+ } else {
+ Write-ColorOutput "NOT FOUND" "Red"
+ Write-ColorOutput "`nError: Project file not found: $ProjectFile" "Red"
+ Write-ColorOutput "Please run this script from the RoslynBridge.WebApi directory." "Yellow"
+ exit 1
+ }
+
+ Write-ColorOutput "`nAll prerequisites satisfied!" "Green"
+}
+
+# Restore NuGet packages
+function Restore-Packages {
+ Write-Step "Restoring NuGet Packages"
+
+ try {
+ dotnet restore $ProjectFile
+ if ($LASTEXITCODE -ne 0) {
+ throw "dotnet restore failed with exit code $LASTEXITCODE"
+ }
+ Write-ColorOutput "`nPackages restored successfully!" "Green"
+ }
+ catch {
+ Write-ColorOutput "`nError during package restore: $_" "Red"
+ exit 1
+ }
+}
+
+# Build project
+function Build-Project {
+ Write-Step "Building Project ($Configuration)"
+
+ try {
+ dotnet build $ProjectFile -c $Configuration --no-restore
+ if ($LASTEXITCODE -ne 0) {
+ throw "dotnet build failed with exit code $LASTEXITCODE"
+ }
+ Write-ColorOutput "`nBuild completed successfully!" "Green"
+ }
+ catch {
+ Write-ColorOutput "`nError during build: $_" "Red"
+ exit 1
+ }
+}
+
+# Publish project
+function Publish-Project {
+ Write-Step "Publishing Project"
+
+ Write-ColorOutput "Configuration: $Configuration" "Gray"
+ Write-ColorOutput "Output Path: $PublishPath" "Gray"
+
+ try {
+ # Clean publish directory if it exists
+ if (Test-Path $PublishPath) {
+ Write-Host "`nCleaning existing publish directory... " -NoNewline
+ Remove-Item -Path $PublishPath -Recurse -Force
+ Write-ColorOutput "Done" "Green"
+ }
+
+ # Publish
+ dotnet publish $ProjectFile -c $Configuration -o $PublishPath --no-build --no-restore
+ if ($LASTEXITCODE -ne 0) {
+ throw "dotnet publish failed with exit code $LASTEXITCODE"
+ }
+
+ # Verify executable exists
+ $exePath = Join-Path $PublishPath "$ProjectName.exe"
+ if (Test-Path $exePath) {
+ Write-ColorOutput "`nProject published successfully!" "Green"
+ Write-ColorOutput "Executable: $exePath" "Gray"
+
+ # Show publish directory size
+ $publishSize = (Get-ChildItem $PublishPath -Recurse | Measure-Object -Property Length -Sum).Sum / 1MB
+ Write-ColorOutput ("Publish size: {0:N2} MB" -f $publishSize) "Gray"
+ } else {
+ throw "Executable not found after publish: $exePath"
+ }
+ }
+ catch {
+ Write-ColorOutput "`nError during publish: $_" "Red"
+ exit 1
+ }
+}
+
+# Install Windows Service
+function Install-WindowsService {
+ Write-Step "Installing Windows Service"
+
+ if (-not (Test-Path ".\install-service.ps1")) {
+ Write-ColorOutput "Error: install-service.ps1 not found" "Red"
+ return $false
+ }
+
+ try {
+ & ".\install-service.ps1" -Action Install -PublishPath $PublishPath
+ return $true
+ }
+ catch {
+ Write-ColorOutput "Error installing service: $_" "Red"
+ return $false
+ }
+}
+
+# Start Windows Service
+function Start-WindowsService {
+ Write-Step "Starting Windows Service"
+
+ if (-not (Test-Path ".\install-service.ps1")) {
+ Write-ColorOutput "Error: install-service.ps1 not found" "Red"
+ return $false
+ }
+
+ try {
+ & ".\install-service.ps1" -Action Start
+ return $true
+ }
+ catch {
+ Write-ColorOutput "Error starting service: $_" "Red"
+ return $false
+ }
+}
+
+# Test installation
+function Test-Installation {
+ Write-Step "Installation Summary"
+
+ $publishFullPath = Resolve-Path $PublishPath -ErrorAction SilentlyContinue
+ if ($publishFullPath) {
+ Write-ColorOutput "`nPublished to: $publishFullPath" "Green"
+
+ $exePath = Join-Path $publishFullPath "$ProjectName.exe"
+ if (Test-Path $exePath) {
+ Write-ColorOutput "Executable: $exePath" "Green"
+ }
+ }
+
+ if ($InstallService) {
+ $service = Get-Service -Name "RoslynBridgeWebApi" -ErrorAction SilentlyContinue
+ if ($service) {
+ Write-ColorOutput "`nWindows Service Status:" "Cyan"
+ Write-ColorOutput " Name: $($service.Name)" "Gray"
+ Write-ColorOutput " Status: $($service.Status)" $(if ($service.Status -eq "Running") { "Green" } else { "Yellow" })
+ Write-ColorOutput " Type: $($service.StartType)" "Gray"
+ }
+ }
+}
+
+# Show next steps
+function Show-NextSteps {
+ Write-Step "Next Steps"
+
+ if ($InstallService) {
+ if ($StartService) {
+ Write-ColorOutput "`nThe service is now running!" "Green"
+ Write-ColorOutput "`nAPI should be available at:" "Cyan"
+ Write-ColorOutput " http://localhost:5000" "White"
+ Write-ColorOutput " https://localhost:7001 (HTTPS)" "White"
+ Write-ColorOutput "`nSwagger UI:" "Cyan"
+ Write-ColorOutput " http://localhost:5000" "White"
+ Write-ColorOutput "`nTo manage the service:" "Yellow"
+ Write-ColorOutput " .\install-service.ps1 -Action Status" "White"
+ Write-ColorOutput " .\install-service.ps1 -Action Stop" "White"
+ Write-ColorOutput " .\install-service.ps1 -Action Restart" "White"
+ Write-ColorOutput " .\install-service.ps1 -Action Uninstall" "White"
+ } else {
+ Write-ColorOutput "`nService installed but not started." "Yellow"
+ Write-ColorOutput "`nTo start the service:" "Cyan"
+ Write-ColorOutput " .\install-service.ps1 -Action Start" "White"
+ }
+ } else {
+ Write-ColorOutput "`nTo run the application manually:" "Cyan"
+ Write-ColorOutput " cd $PublishPath" "White"
+ Write-ColorOutput " .\$ProjectName.exe" "White"
+ Write-ColorOutput "`nTo install as a Windows Service:" "Cyan"
+ Write-ColorOutput " .\install-service.ps1 -Action Install -PublishPath $PublishPath" "White"
+ Write-ColorOutput " .\install-service.ps1 -Action Start" "White"
+ Write-ColorOutput "`nOr run this script again with -InstallService -StartService flags" "Gray"
+ }
+
+ Write-ColorOutput "`nFor more information, see README.md" "Gray"
+}
+
+# Main execution
+try {
+ Show-Banner
+
+ # Show configuration
+ Write-ColorOutput "Installation Configuration:" "Cyan"
+ Write-ColorOutput " Configuration: $Configuration" "Gray"
+ Write-ColorOutput " Publish Path: $PublishPath" "Gray"
+ Write-ColorOutput " Install Service: $InstallService" "Gray"
+ Write-ColorOutput " Start Service: $StartService" "Gray"
+ Write-ColorOutput " Skip Build: $SkipBuild" "Gray"
+ Write-ColorOutput " Skip Publish: $SkipPublish" "Gray"
+
+ # Execute installation steps
+ Test-Prerequisites
+
+ if (-not $SkipBuild) {
+ Restore-Packages
+ Build-Project
+ } else {
+ Write-ColorOutput "`nSkipping build (using existing build)" "Yellow"
+ }
+
+ if (-not $SkipPublish) {
+ Publish-Project
+ } else {
+ Write-ColorOutput "`nSkipping publish (using existing publish)" "Yellow"
+ }
+
+ # Optional service installation
+ if ($InstallService) {
+ $serviceInstalled = Install-WindowsService
+
+ if ($serviceInstalled -and $StartService) {
+ Start-WindowsService
+ }
+ }
+
+ # Show results
+ Test-Installation
+ Show-NextSteps
+
+ Write-ColorOutput "`n============================================================" "Cyan"
+ Write-ColorOutput " Installation Completed Successfully!" "Cyan"
+ Write-ColorOutput "============================================================`n" "Cyan"
+
+ exit 0
+}
+catch {
+ Write-ColorOutput "`n============================================================" "Red"
+ Write-ColorOutput " Installation Failed!" "Red"
+ Write-ColorOutput "============================================================`n" "Red"
+ Write-ColorOutput "Error: $_" "Red"
+ Write-ColorOutput "`nStack Trace:" "DarkGray"
+ Write-ColorOutput $_.ScriptStackTrace "DarkGray"
+ exit 1
+}
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Abstractions.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Abstractions.dll
new file mode 100644
index 0000000..58f5b7d
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Abstractions.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Binder.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Binder.dll
new file mode 100644
index 0000000..a95f048
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Binder.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.CommandLine.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.CommandLine.dll
new file mode 100644
index 0000000..717282c
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.CommandLine.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.EnvironmentVariables.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.EnvironmentVariables.dll
new file mode 100644
index 0000000..0eda807
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.EnvironmentVariables.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.FileExtensions.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.FileExtensions.dll
new file mode 100644
index 0000000..e1f5f1d
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.FileExtensions.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Json.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Json.dll
new file mode 100644
index 0000000..e22c215
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.Json.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.UserSecrets.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.UserSecrets.dll
new file mode 100644
index 0000000..f3d8bd4
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.UserSecrets.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.dll
new file mode 100644
index 0000000..155d6f0
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Configuration.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll
new file mode 100644
index 0000000..a01968f
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.DependencyInjection.Abstractions.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.DependencyInjection.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.DependencyInjection.dll
new file mode 100644
index 0000000..7420234
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.DependencyInjection.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Diagnostics.Abstractions.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Diagnostics.Abstractions.dll
new file mode 100644
index 0000000..7b83ce0
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Diagnostics.Abstractions.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Diagnostics.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Diagnostics.dll
new file mode 100644
index 0000000..8738391
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Diagnostics.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileProviders.Abstractions.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileProviders.Abstractions.dll
new file mode 100644
index 0000000..af76139
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileProviders.Abstractions.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileProviders.Physical.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileProviders.Physical.dll
new file mode 100644
index 0000000..270f86b
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileProviders.Physical.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileSystemGlobbing.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileSystemGlobbing.dll
new file mode 100644
index 0000000..5625b24
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.FileSystemGlobbing.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.Abstractions.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.Abstractions.dll
new file mode 100644
index 0000000..f979769
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.Abstractions.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.WindowsServices.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.WindowsServices.dll
new file mode 100644
index 0000000..0ad91c0
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.WindowsServices.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.dll
new file mode 100644
index 0000000..e5fee25
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Hosting.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Abstractions.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Abstractions.dll
new file mode 100644
index 0000000..2bd9784
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Abstractions.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Configuration.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Configuration.dll
new file mode 100644
index 0000000..cee18fb
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Configuration.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Console.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Console.dll
new file mode 100644
index 0000000..1f4da9c
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Console.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Debug.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Debug.dll
new file mode 100644
index 0000000..4423ccd
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.Debug.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.EventLog.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.EventLog.dll
new file mode 100644
index 0000000..c4cc863
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.EventLog.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.EventSource.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.EventSource.dll
new file mode 100644
index 0000000..8428eb8
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.EventSource.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.dll
new file mode 100644
index 0000000..7819a6c
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Logging.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Options.ConfigurationExtensions.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Options.ConfigurationExtensions.dll
new file mode 100644
index 0000000..30d51ea
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Options.ConfigurationExtensions.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Options.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Options.dll
new file mode 100644
index 0000000..6b54341
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Options.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.Extensions.Primitives.dll b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Primitives.dll
new file mode 100644
index 0000000..5a58056
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.Extensions.Primitives.dll differ
diff --git a/RoslynBridge.WebApi/publish/Microsoft.OpenApi.dll b/RoslynBridge.WebApi/publish/Microsoft.OpenApi.dll
new file mode 100644
index 0000000..aac9a6d
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Microsoft.OpenApi.dll differ
diff --git a/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.deps.json b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.deps.json
new file mode 100644
index 0000000..688981b
--- /dev/null
+++ b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.deps.json
@@ -0,0 +1,834 @@
+{
+ "runtimeTarget": {
+ "name": ".NETCoreApp,Version=v8.0",
+ "signature": ""
+ },
+ "compilationOptions": {},
+ "targets": {
+ ".NETCoreApp,Version=v8.0": {
+ "RoslynBridge.WebApi/1.0.0": {
+ "dependencies": {
+ "Microsoft.Extensions.Hosting.WindowsServices": "9.0.10",
+ "Microsoft.Extensions.Http": "8.0.0",
+ "Swashbuckle.AspNetCore": "6.6.2"
+ },
+ "runtime": {
+ "RoslynBridge.WebApi.dll": {}
+ }
+ },
+ "Microsoft.Extensions.ApiDescription.Server/6.0.5": {},
+ "Microsoft.Extensions.Configuration/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Primitives": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Configuration.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Configuration.Abstractions/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Configuration.Binder/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Configuration.Binder.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Configuration.CommandLine/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "9.0.10",
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Configuration.CommandLine.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Configuration.EnvironmentVariables/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "9.0.10",
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Configuration.EnvironmentVariables.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Configuration.FileExtensions/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "9.0.10",
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.FileProviders.Abstractions": "9.0.10",
+ "Microsoft.Extensions.FileProviders.Physical": "9.0.10",
+ "Microsoft.Extensions.Primitives": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Configuration.FileExtensions.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Configuration.Json/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "9.0.10",
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Configuration.FileExtensions": "9.0.10",
+ "Microsoft.Extensions.FileProviders.Abstractions": "9.0.10",
+ "System.Text.Json": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Configuration.Json.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Configuration.UserSecrets/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Configuration.Json": "9.0.10",
+ "Microsoft.Extensions.FileProviders.Abstractions": "9.0.10",
+ "Microsoft.Extensions.FileProviders.Physical": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Configuration.UserSecrets.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.DependencyInjection.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.10": {
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Diagnostics/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "9.0.10",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Diagnostics.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10",
+ "System.Diagnostics.DiagnosticSource": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.FileProviders.Abstractions.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.FileProviders.Physical/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.FileProviders.Abstractions": "9.0.10",
+ "Microsoft.Extensions.FileSystemGlobbing": "9.0.10",
+ "Microsoft.Extensions.Primitives": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.FileProviders.Physical.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.FileSystemGlobbing/9.0.10": {
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.FileSystemGlobbing.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Hosting/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "9.0.10",
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Configuration.Binder": "9.0.10",
+ "Microsoft.Extensions.Configuration.CommandLine": "9.0.10",
+ "Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.10",
+ "Microsoft.Extensions.Configuration.FileExtensions": "9.0.10",
+ "Microsoft.Extensions.Configuration.Json": "9.0.10",
+ "Microsoft.Extensions.Configuration.UserSecrets": "9.0.10",
+ "Microsoft.Extensions.DependencyInjection": "9.0.10",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Diagnostics": "9.0.10",
+ "Microsoft.Extensions.FileProviders.Abstractions": "9.0.10",
+ "Microsoft.Extensions.FileProviders.Physical": "9.0.10",
+ "Microsoft.Extensions.Hosting.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging.Configuration": "9.0.10",
+ "Microsoft.Extensions.Logging.Console": "9.0.10",
+ "Microsoft.Extensions.Logging.Debug": "9.0.10",
+ "Microsoft.Extensions.Logging.EventLog": "9.0.10",
+ "Microsoft.Extensions.Logging.EventSource": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Hosting.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Hosting.Abstractions/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.10",
+ "Microsoft.Extensions.FileProviders.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Hosting.Abstractions.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Hosting.WindowsServices/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Hosting": "9.0.10",
+ "Microsoft.Extensions.Logging.EventLog": "9.0.10",
+ "System.ServiceProcess.ServiceController": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Hosting.WindowsServices.dll": {
+ "assemblyVersion": "9.0.0.10",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Http/8.0.0": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Diagnostics": "9.0.10",
+ "Microsoft.Extensions.Logging": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10"
+ }
+ },
+ "Microsoft.Extensions.Logging/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Logging.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "System.Diagnostics.DiagnosticSource": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Logging.Configuration/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration": "9.0.10",
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Configuration.Binder": "9.0.10",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Logging.Configuration.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Logging.Console/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging.Configuration": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10",
+ "System.Text.Json": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Logging.Console.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Logging.Debug/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Logging.Debug.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Logging.EventLog/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10",
+ "System.Diagnostics.EventLog": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Logging.EventLog.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Logging.EventSource/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Logging": "9.0.10",
+ "Microsoft.Extensions.Logging.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10",
+ "Microsoft.Extensions.Primitives": "9.0.10",
+ "System.Text.Json": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Logging.EventSource.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Options/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Primitives": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Options.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Options.ConfigurationExtensions/9.0.10": {
+ "dependencies": {
+ "Microsoft.Extensions.Configuration.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Configuration.Binder": "9.0.10",
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.10",
+ "Microsoft.Extensions.Options": "9.0.10",
+ "Microsoft.Extensions.Primitives": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.Extensions.Primitives/9.0.10": {
+ "runtime": {
+ "lib/net8.0/Microsoft.Extensions.Primitives.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "Microsoft.OpenApi/1.6.14": {
+ "runtime": {
+ "lib/netstandard2.0/Microsoft.OpenApi.dll": {
+ "assemblyVersion": "1.6.14.0",
+ "fileVersion": "1.6.14.0"
+ }
+ }
+ },
+ "Swashbuckle.AspNetCore/6.6.2": {
+ "dependencies": {
+ "Microsoft.Extensions.ApiDescription.Server": "6.0.5",
+ "Swashbuckle.AspNetCore.Swagger": "6.6.2",
+ "Swashbuckle.AspNetCore.SwaggerGen": "6.6.2",
+ "Swashbuckle.AspNetCore.SwaggerUI": "6.6.2"
+ }
+ },
+ "Swashbuckle.AspNetCore.Swagger/6.6.2": {
+ "dependencies": {
+ "Microsoft.OpenApi": "1.6.14"
+ },
+ "runtime": {
+ "lib/net8.0/Swashbuckle.AspNetCore.Swagger.dll": {
+ "assemblyVersion": "6.6.2.0",
+ "fileVersion": "6.6.2.401"
+ }
+ }
+ },
+ "Swashbuckle.AspNetCore.SwaggerGen/6.6.2": {
+ "dependencies": {
+ "Swashbuckle.AspNetCore.Swagger": "6.6.2"
+ },
+ "runtime": {
+ "lib/net8.0/Swashbuckle.AspNetCore.SwaggerGen.dll": {
+ "assemblyVersion": "6.6.2.0",
+ "fileVersion": "6.6.2.401"
+ }
+ }
+ },
+ "Swashbuckle.AspNetCore.SwaggerUI/6.6.2": {
+ "runtime": {
+ "lib/net8.0/Swashbuckle.AspNetCore.SwaggerUI.dll": {
+ "assemblyVersion": "6.6.2.0",
+ "fileVersion": "6.6.2.401"
+ }
+ }
+ },
+ "System.Diagnostics.DiagnosticSource/9.0.10": {
+ "runtime": {
+ "lib/net8.0/System.Diagnostics.DiagnosticSource.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "System.Diagnostics.EventLog/9.0.10": {
+ "runtime": {
+ "lib/net8.0/System.Diagnostics.EventLog.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ },
+ "runtimeTargets": {
+ "runtimes/win/lib/net8.0/System.Diagnostics.EventLog.Messages.dll": {
+ "rid": "win",
+ "assetType": "runtime",
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "0.0.0.0"
+ },
+ "runtimes/win/lib/net8.0/System.Diagnostics.EventLog.dll": {
+ "rid": "win",
+ "assetType": "runtime",
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "System.IO.Pipelines/9.0.10": {
+ "runtime": {
+ "lib/net8.0/System.IO.Pipelines.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "System.ServiceProcess.ServiceController/9.0.10": {
+ "dependencies": {
+ "System.Diagnostics.EventLog": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/System.ServiceProcess.ServiceController.dll": {
+ "assemblyVersion": "9.0.0.10",
+ "fileVersion": "9.0.1025.47515"
+ }
+ },
+ "runtimeTargets": {
+ "runtimes/win/lib/net8.0/System.ServiceProcess.ServiceController.dll": {
+ "rid": "win",
+ "assetType": "runtime",
+ "assemblyVersion": "9.0.0.10",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "System.Text.Encodings.Web/9.0.10": {
+ "runtime": {
+ "lib/net8.0/System.Text.Encodings.Web.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ },
+ "runtimeTargets": {
+ "runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll": {
+ "rid": "browser",
+ "assetType": "runtime",
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ },
+ "System.Text.Json/9.0.10": {
+ "dependencies": {
+ "System.IO.Pipelines": "9.0.10",
+ "System.Text.Encodings.Web": "9.0.10"
+ },
+ "runtime": {
+ "lib/net8.0/System.Text.Json.dll": {
+ "assemblyVersion": "9.0.0.0",
+ "fileVersion": "9.0.1025.47515"
+ }
+ }
+ }
+ }
+ },
+ "libraries": {
+ "RoslynBridge.WebApi/1.0.0": {
+ "type": "project",
+ "serviceable": false,
+ "sha512": ""
+ },
+ "Microsoft.Extensions.ApiDescription.Server/6.0.5": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-Ckb5EDBUNJdFWyajfXzUIMRkhf52fHZOQuuZg/oiu8y7zDCVwD0iHhew6MnThjHmevanpxL3f5ci2TtHQEN6bw==",
+ "path": "microsoft.extensions.apidescription.server/6.0.5",
+ "hashPath": "microsoft.extensions.apidescription.server.6.0.5.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Configuration/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-UAm3SLGAMlJdowbN+/xnh2UGJkdJoXVm4MsdhZ60dAMS8jteoyCx5WfIab5DKv0TCYpdhVecLJVUjEO3abs9UQ==",
+ "path": "microsoft.extensions.configuration/9.0.10",
+ "hashPath": "microsoft.extensions.configuration.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Configuration.Abstractions/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-ad3JxmFj0uxuFa1CT6oxTCC1lQ0xeRuOvzBRFT/I/ofIXVOnNsH/v2GZkAJWhlpZqKUvSexQZzp3EEAB2CdtJg==",
+ "path": "microsoft.extensions.configuration.abstractions/9.0.10",
+ "hashPath": "microsoft.extensions.configuration.abstractions.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Configuration.Binder/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-D6Kng+9I+w1SQPxJybc6wzw9nnnyUQPutycjtI0svv1RHaWOpUk9PPlwIRfhhoQZ3yihejkEI2wNv/7VnVtkGA==",
+ "path": "microsoft.extensions.configuration.binder/9.0.10",
+ "hashPath": "microsoft.extensions.configuration.binder.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Configuration.CommandLine/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-Sg400UyKl33kOpqklEg1MIM3lpY/aWi7QZTB2JfFpKgxnSRQl9J6tHiKYll+Rd603P+71YsDy/zqBYUE/3Xeag==",
+ "path": "microsoft.extensions.configuration.commandline/9.0.10",
+ "hashPath": "microsoft.extensions.configuration.commandline.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Configuration.EnvironmentVariables/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-Nje8x5JDRi7uzf2q3NpXiBleRRJAxJMnHcJTi0tLyqd6eGIICRuF6qxgZssMS1r8xXDoaUr/2ZLQ6Cui1Io+Qw==",
+ "path": "microsoft.extensions.configuration.environmentvariables/9.0.10",
+ "hashPath": "microsoft.extensions.configuration.environmentvariables.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Configuration.FileExtensions/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-kYWY9VRoCKQJCLKAA4Wqn74FVnytqosF7vFq1chJ8st9mGZS6SQrkoZg7GmcpqrRRUWmWDOZI4nFdoFnxsI/Ug==",
+ "path": "microsoft.extensions.configuration.fileextensions/9.0.10",
+ "hashPath": "microsoft.extensions.configuration.fileextensions.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Configuration.Json/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-bn+qnwuOaDelax8PUw30UTjLOuEd0lGWqUG4Z+oVr4D/gEWouCWOyvCVkyn+PWbftPlnmAmWxd4J+7ljwE8wVw==",
+ "path": "microsoft.extensions.configuration.json/9.0.10",
+ "hashPath": "microsoft.extensions.configuration.json.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Configuration.UserSecrets/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-l7em+qNfEdGlwRm8Qk2rkzqjT8xWb/EosoQeTvJ3kZYiRo5inMj0nNcZw51dUKwGO/LW7uNMdqNNU3P0pB5JqA==",
+ "path": "microsoft.extensions.configuration.usersecrets/9.0.10",
+ "hashPath": "microsoft.extensions.configuration.usersecrets.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.DependencyInjection/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-iEtXCkNd5XhjNJAOb/wO4IhDRdLIE2CsPxZggZQWJ/q2+sa8dmEPC393nnsiqdH8/4KV8Xn25IzgKPR1UEQ0og==",
+ "path": "microsoft.extensions.dependencyinjection/9.0.10",
+ "hashPath": "microsoft.extensions.dependencyinjection.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-r9waLiOPe9ZF1PvzUT+RDoHvpMmY8MW+lb4lqjYGObwKpnyPMLI3odVvlmshwuZcdoHynsGWOrCPA0hxZ63lIA==",
+ "path": "microsoft.extensions.dependencyinjection.abstractions/9.0.10",
+ "hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Diagnostics/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-01x2vz0AbIdfNUzEVYFq2HSeq1BmrSDpiG7nTmwjfd0d39sahQ8T7dhSXhH+YnZyaLWyMBudOq0vVa/voyNWjg==",
+ "path": "microsoft.extensions.diagnostics/9.0.10",
+ "hashPath": "microsoft.extensions.diagnostics.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Diagnostics.Abstractions/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-iwVnYi+gNKrr5riw8YFCoLCN4s0dmHtzfUmV99RIhrz8R4d6C/bsKzXhIhZWDIxJOhVzB+idSOQeRGj1/oMF+Q==",
+ "path": "microsoft.extensions.diagnostics.abstractions/9.0.10",
+ "hashPath": "microsoft.extensions.diagnostics.abstractions.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.FileProviders.Abstractions/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-3+cLxZKUWBbpfIXLLuKcEok9C91PsV1h5xxfUsEnLSXXLNMiPDfrhpb1xajNFcejFPs9Ck/Fi3z71hYDqFBwYg==",
+ "path": "microsoft.extensions.fileproviders.abstractions/9.0.10",
+ "hashPath": "microsoft.extensions.fileproviders.abstractions.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.FileProviders.Physical/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-Eg3YOEMpHWZzAgPD9YvGkQSv97AtG3II6maRQV/voDRORh4bRiyl0mVtT2PKnu1JoD9rJeYgjGCwRvVWMBaqgQ==",
+ "path": "microsoft.extensions.fileproviders.physical/9.0.10",
+ "hashPath": "microsoft.extensions.fileproviders.physical.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.FileSystemGlobbing/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-KdZAM2YMYBipVp/4tSEWPLnrocd17SL4iaXdgXjR5/nheBXbfR5QfPWYoTyh6C6IW3uKR7TRMwQr2qCvtaCTiA==",
+ "path": "microsoft.extensions.filesystemglobbing/9.0.10",
+ "hashPath": "microsoft.extensions.filesystemglobbing.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Hosting/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-63yDlitelCBNl1unJsnEWVUCZHOtxbVTbTODi7cszQJBG9bIfdPYIpB9w0UIcoqVSP1C9P6THXgukx8APWRzMw==",
+ "path": "microsoft.extensions.hosting/9.0.10",
+ "hashPath": "microsoft.extensions.hosting.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Hosting.Abstractions/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-spfXydiEQENFwxdgr3Y57wwys/FRjfmq5VjHGPh6ct1FJK7X+qNEWYbnZJCMqq0B0oJTMvnItAReOv4mi2Idog==",
+ "path": "microsoft.extensions.hosting.abstractions/9.0.10",
+ "hashPath": "microsoft.extensions.hosting.abstractions.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Hosting.WindowsServices/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-6J44fDEcblCFoc7vNwuxLQrfY9ldToc2pkfzuraCOCsRAVFg4Fajm+PdpDYQ3VzG7eh1Iqc1JMPs9LMpaIeSKA==",
+ "path": "microsoft.extensions.hosting.windowsservices/9.0.10",
+ "hashPath": "microsoft.extensions.hosting.windowsservices.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Http/8.0.0": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-cWz4caHwvx0emoYe7NkHPxII/KkTI8R/LC9qdqJqnKv2poTJ4e2qqPGQqvRoQ5kaSA4FU5IV3qFAuLuOhoqULQ==",
+ "path": "microsoft.extensions.http/8.0.0",
+ "hashPath": "microsoft.extensions.http.8.0.0.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Logging/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-UBXHqE9vyptVhaFnT1R7YJKCve7TqVI10yjjUZBNGMlW2lZ4c031Slt9hxsOzWCzlpPxxIFyf1Yk4a6Iubxx7w==",
+ "path": "microsoft.extensions.logging/9.0.10",
+ "hashPath": "microsoft.extensions.logging.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Logging.Abstractions/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-MFUPv/nN1rAQ19w43smm6bbf0JDYN/1HEPHoiMYY50pvDMFpglzWAuoTavByDmZq7UuhjaxwrET3joU69ZHoHQ==",
+ "path": "microsoft.extensions.logging.abstractions/9.0.10",
+ "hashPath": "microsoft.extensions.logging.abstractions.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Logging.Configuration/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-qwTRpxrmLOXZrbgQHRZ9wS2AtVa/61DFIYk8k1rBCCgA5qW0MBxxQC4BjkaI0wSoHHOv/IUXBeFNK+Y59qe/Ug==",
+ "path": "microsoft.extensions.logging.configuration/9.0.10",
+ "hashPath": "microsoft.extensions.logging.configuration.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Logging.Console/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-ponA8k4E4S0LlQ8J4ce4Yp1NND8rxww0lbADK9yL3omRpnnawiENb7W/CTgZUIZVJxKcmIwhm1IbUCRk6RLocQ==",
+ "path": "microsoft.extensions.logging.console/9.0.10",
+ "hashPath": "microsoft.extensions.logging.console.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Logging.Debug/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-Uj4YMaMMLawIkpHYnDWsR2/pufV/8X3dDT1/RNhkmt8RRf6/SriyA2gxH6I6bj4gFx6yMuFWZhCgFLy3wcSGTw==",
+ "path": "microsoft.extensions.logging.debug/9.0.10",
+ "hashPath": "microsoft.extensions.logging.debug.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Logging.EventLog/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-Son+9zr7gnuYv1CcuZ8b6XhZK/UQRG88Ku1iSUvAQSZ1cFjYC+lDYRD6nBVXF2QIQyv0jhjt/MPKD7sA+323TQ==",
+ "path": "microsoft.extensions.logging.eventlog/9.0.10",
+ "hashPath": "microsoft.extensions.logging.eventlog.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Logging.EventSource/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-qhqkUWsf/CVyQ9V98n5uWSQcvy7HbyRkhyhpK75OKojWuaNKoEIfBmrHRiahmdGJDuh2Qz/nDpFOjQOi/ERtZQ==",
+ "path": "microsoft.extensions.logging.eventsource/9.0.10",
+ "hashPath": "microsoft.extensions.logging.eventsource.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Options/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-zMNABt8eBv0B0XrWjFy9nZNgddavaOeq3ZdaD5IlHhRH65MrU7HM+Hd8GjWE3e2VDGFPZFfSAc6XVXC17f9fOA==",
+ "path": "microsoft.extensions.options/9.0.10",
+ "hashPath": "microsoft.extensions.options.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Options.ConfigurationExtensions/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-wLsf2TyVFFxWQPv0PRJj365it1ngIt8utlHJWSZ9OJ2k+NDa/PtBIRsGlF/NkoLwm1m+1vOePNl2MiKfk6lYfQ==",
+ "path": "microsoft.extensions.options.configurationextensions/9.0.10",
+ "hashPath": "microsoft.extensions.options.configurationextensions.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.Extensions.Primitives/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-3pl8D1O5ZwMpDkZAT2uXrhQ6NipkwEgDLMFuURiHTf72TvkoMP61QYH3Vk1yrzVHnHBdNZk3cQACz8Zc7YGNhQ==",
+ "path": "microsoft.extensions.primitives/9.0.10",
+ "hashPath": "microsoft.extensions.primitives.9.0.10.nupkg.sha512"
+ },
+ "Microsoft.OpenApi/1.6.14": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-tTaBT8qjk3xINfESyOPE2rIellPvB7qpVqiWiyA/lACVvz+xOGiXhFUfohcx82NLbi5avzLW0lx+s6oAqQijfw==",
+ "path": "microsoft.openapi/1.6.14",
+ "hashPath": "microsoft.openapi.1.6.14.nupkg.sha512"
+ },
+ "Swashbuckle.AspNetCore/6.6.2": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-+NB4UYVYN6AhDSjW0IJAd1AGD8V33gemFNLPaxKTtPkHB+HaKAKf9MGAEUPivEWvqeQfcKIw8lJaHq6LHljRuw==",
+ "path": "swashbuckle.aspnetcore/6.6.2",
+ "hashPath": "swashbuckle.aspnetcore.6.6.2.nupkg.sha512"
+ },
+ "Swashbuckle.AspNetCore.Swagger/6.6.2": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-ovgPTSYX83UrQUWiS5vzDcJ8TEX1MAxBgDFMK45rC24MorHEPQlZAHlaXj/yth4Zf6xcktpUgTEBvffRQVwDKA==",
+ "path": "swashbuckle.aspnetcore.swagger/6.6.2",
+ "hashPath": "swashbuckle.aspnetcore.swagger.6.6.2.nupkg.sha512"
+ },
+ "Swashbuckle.AspNetCore.SwaggerGen/6.6.2": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-zv4ikn4AT1VYuOsDCpktLq4QDq08e7Utzbir86M5/ZkRaLXbCPF11E1/vTmOiDzRTl0zTZINQU2qLKwTcHgfrA==",
+ "path": "swashbuckle.aspnetcore.swaggergen/6.6.2",
+ "hashPath": "swashbuckle.aspnetcore.swaggergen.6.6.2.nupkg.sha512"
+ },
+ "Swashbuckle.AspNetCore.SwaggerUI/6.6.2": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-mBBb+/8Hm2Q3Wygag+hu2jj69tZW5psuv0vMRXY07Wy+Rrj40vRP8ZTbKBhs91r45/HXT4aY4z0iSBYx1h6JvA==",
+ "path": "swashbuckle.aspnetcore.swaggerui/6.6.2",
+ "hashPath": "swashbuckle.aspnetcore.swaggerui.6.6.2.nupkg.sha512"
+ },
+ "System.Diagnostics.DiagnosticSource/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-uIpKiKp7EWlYZBK71jYP+maGYjDY9YTi/FxBlZoqDzM1ZHZB7gLqUm4jHvRFwaKfR1/Lrt2rQih9LGPIKyNEow==",
+ "path": "system.diagnostics.diagnosticsource/9.0.10",
+ "hashPath": "system.diagnostics.diagnosticsource.9.0.10.nupkg.sha512"
+ },
+ "System.Diagnostics.EventLog/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-Jc+az1pTMujPLDn2j5eqSfzlO7j/T1K/LB7THxdfRWOxujE4zaitUqBs7sv1t6/xmmvpU6Xx3IofCs4owYH0yQ==",
+ "path": "system.diagnostics.eventlog/9.0.10",
+ "hashPath": "system.diagnostics.eventlog.9.0.10.nupkg.sha512"
+ },
+ "System.IO.Pipelines/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-lwI0mhHcCxMtNSxB5ate9Gc9petWovRBUprtjz2yiIDDZPGBIaUiqNzQHJzjPuzTnvNbEMilpAXjDguKsU/2Fg==",
+ "path": "system.io.pipelines/9.0.10",
+ "hashPath": "system.io.pipelines.9.0.10.nupkg.sha512"
+ },
+ "System.ServiceProcess.ServiceController/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-dmH+qHQ5wMjvEI0M2s6J+vmaU9L9ID2D9DWMFa7FiTfINfo3e3zeL4ljX7Dg5gCnFIULPFip2ej2iIAC3X6MFw==",
+ "path": "system.serviceprocess.servicecontroller/9.0.10",
+ "hashPath": "system.serviceprocess.servicecontroller.9.0.10.nupkg.sha512"
+ },
+ "System.Text.Encodings.Web/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-znmiJFUa0GGwq7t6ShUKBDRlPsNJaudNFI7rVeyGnRBhiRMegBvu2GRcadThP/QX/a5UpGgZbe6tolDooobj/Q==",
+ "path": "system.text.encodings.web/9.0.10",
+ "hashPath": "system.text.encodings.web.9.0.10.nupkg.sha512"
+ },
+ "System.Text.Json/9.0.10": {
+ "type": "package",
+ "serviceable": true,
+ "sha512": "sha512-XM02ZBnzxk7Ti6l9YRy8Bp639wANqJzJzw4W4VYiCh+HXY9hBOWkGB4k89OLP/s/RxgM02P4a/mWcJTgFiLf1Q==",
+ "path": "system.text.json/9.0.10",
+ "hashPath": "system.text.json.9.0.10.nupkg.sha512"
+ }
+ }
+}
\ No newline at end of file
diff --git a/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.dll b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.dll
new file mode 100644
index 0000000..30a4d30
Binary files /dev/null and b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.dll differ
diff --git a/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.runtimeconfig.json b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.runtimeconfig.json
new file mode 100644
index 0000000..6a48a7e
--- /dev/null
+++ b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.runtimeconfig.json
@@ -0,0 +1,20 @@
+{
+ "runtimeOptions": {
+ "tfm": "net8.0",
+ "frameworks": [
+ {
+ "name": "Microsoft.NETCore.App",
+ "version": "8.0.0"
+ },
+ {
+ "name": "Microsoft.AspNetCore.App",
+ "version": "8.0.0"
+ }
+ ],
+ "configProperties": {
+ "System.GC.Server": true,
+ "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
+ "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.staticwebassets.endpoints.json b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.staticwebassets.endpoints.json
new file mode 100644
index 0000000..21da96b
--- /dev/null
+++ b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.staticwebassets.endpoints.json
@@ -0,0 +1 @@
+{"Version":1,"ManifestType":"Publish","Endpoints":[]}
\ No newline at end of file
diff --git a/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.xml b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.xml
new file mode 100644
index 0000000..f7793e4
--- /dev/null
+++ b/RoslynBridge.WebApi/publish/RoslynBridge.WebApi.xml
@@ -0,0 +1,576 @@
+
+
+
+ RoslynBridge.WebApi
+
+
+
+
+ Health check and status controller
+
+
+
+
+ Get the health status of the middleware and Visual Studio plugin
+
+ Cancellation token
+ Health status information
+ Service is healthy
+ Service is unhealthy
+
+
+
+ Simple ping endpoint
+
+ Pong response
+
+
+
+ Controller for accessing query history
+
+
+
+
+ Get all history entries
+
+ List of all history entries
+ Returns the list of history entries
+
+
+
+ Get a specific history entry by ID
+
+ The history entry ID
+ The history entry
+ Returns the history entry
+ Entry not found
+
+
+
+ Get recent history entries
+
+ Number of entries to return (default: 50, max: 500)
+ List of recent history entries
+ Returns the list of recent entries
+
+
+
+ Get history statistics
+
+ Statistics about history entries
+
+
+
+ Clear all history entries
+
+ Confirmation message
+ History cleared successfully
+
+
+
+ Controller for managing Visual Studio instance registrations
+
+
+
+
+ Register a new Visual Studio instance
+
+ Instance information
+ Registration result
+
+
+
+ Unregister a Visual Studio instance
+
+ Process ID of the instance to unregister
+ Unregistration result
+
+
+
+ Update heartbeat for a Visual Studio instance
+
+ Process ID of the instance
+ Heartbeat update result
+
+
+
+ Get all registered Visual Studio instances
+
+ List of registered instances
+
+
+
+ Get instance by process ID
+
+ Process ID
+ Instance information
+
+
+
+ Get instance by solution path
+
+ Solution file path
+ Instance information
+
+
+
+ Get instance by port
+
+ Port number
+ Instance information
+
+
+
+ Controller for Roslyn code analysis operations
+
+
+
+
+ Execute a Roslyn query
+
+ The query request
+ Optional: specific VS instance port to target
+ Cancellation token
+ The query result
+ Query executed successfully
+ Invalid request
+ Internal server error
+
+
+
+ Get all projects in the solution
+
+ Optional: specific VS instance port to target
+ Cancellation token
+ List of projects
+
+
+
+ Get solution overview
+
+ Optional: specific VS instance port to target
+ Cancellation token
+ Solution statistics and overview
+
+
+
+ Get diagnostics (errors and warnings)
+
+ Optional file path to filter diagnostics
+ Optional: specific VS instance port to target
+ Cancellation token
+ List of diagnostics
+
+
+
+ Get symbol information at a specific position
+
+ File path
+ Line number (1-based)
+ Column number (0-based)
+ Optional: specific VS instance port to target
+ Cancellation token
+ Symbol information
+
+
+
+ Find all references to a symbol
+
+ File path
+ Line number (1-based)
+ Column number (0-based)
+ Optional: specific VS instance port to target
+ Cancellation token
+ List of references
+
+
+
+ Search for symbols by name
+
+ Symbol name or pattern
+ Optional symbol kind filter
+ Optional: specific VS instance port to target
+ Cancellation token
+ List of matching symbols
+
+
+
+ Format a document
+
+ File path to format
+ Optional: specific VS instance port to target
+ Cancellation token
+ Format operation result
+
+
+
+ Add a NuGet package to a project
+
+ Project name
+ NuGet package name
+ Optional package version
+ Optional: specific VS instance port to target
+ Cancellation token
+ Operation result
+
+
+
+ Build a project
+
+ Project name
+ Build configuration (Debug/Release)
+ Optional: specific VS instance port to target
+ Cancellation token
+ Build result
+
+
+
+ Middleware to capture and log all Roslyn API requests and responses
+
+
+
+
+ Extension methods for adding history middleware
+
+
+
+
+ Health check response for service status
+
+
+
+
+ Overall health status
+
+
+
+
+ Web API service status
+
+
+
+
+ Visual Studio plugin connection status
+
+
+
+
+ Timestamp of the health check
+
+
+
+
+ API version
+
+
+
+
+ Represents a single query history entry with request and response information
+
+
+
+
+ Unique identifier for this history entry
+
+
+
+
+ Timestamp when the request was received
+
+
+
+
+ The endpoint path that was called
+
+
+
+
+ HTTP method used
+
+
+
+
+ The Roslyn query request
+
+
+
+
+ The Roslyn query response
+
+
+
+
+ Request duration in milliseconds
+
+
+
+
+ Whether the request was successful
+
+
+
+
+ Client IP address
+
+
+
+
+ Request model for Roslyn query operations
+
+
+
+
+ Type of query to execute (e.g., "getsymbol", "getdocument", "findreferences")
+
+
+
+
+ File path for file-based operations
+
+
+
+
+ Symbol name for symbol-based operations
+
+
+
+
+ Line number (1-based) for position-based operations
+
+
+
+
+ Column number (0-based) for position-based operations
+
+
+
+
+ Additional parameters for the query
+
+
+
+
+ Project name for project operations
+
+
+
+
+ Package name for NuGet operations
+
+
+
+
+ Version for NuGet package operations
+
+
+
+
+ Build configuration (Debug/Release)
+
+
+
+
+ Directory path for directory operations
+
+
+
+
+ Response model for Roslyn query operations
+
+
+
+
+ Indicates whether the operation was successful
+
+
+
+
+ Optional message providing additional context
+
+
+
+
+ The response data (structure varies by query type)
+
+
+
+
+ Error message if the operation failed
+
+
+
+
+ Information about a registered Visual Studio instance
+
+
+
+
+ The port number where this VS instance is listening
+
+
+
+
+ The process ID of the Visual Studio instance
+
+
+
+
+ The solution file path (if any solution is open)
+
+
+
+
+ The solution name (if any solution is open)
+
+
+
+
+ When this instance was registered
+
+
+
+
+ Last heartbeat time
+
+
+
+
+ List of project names in the solution
+
+
+
+
+ In-memory implementation of history service
+
+
+
+
+ Service for managing query history
+
+
+
+
+ Add a new history entry
+
+ The history entry to add
+
+
+
+ Get all history entries
+
+ List of all history entries
+
+
+
+ Get a specific history entry by ID
+
+ The entry ID
+ The history entry, or null if not found
+
+
+
+ Get recent history entries
+
+ Number of entries to return
+ List of recent history entries
+
+
+
+ Clear all history entries
+
+
+
+
+ Get total count of history entries
+
+ Total number of entries
+
+
+
+ Service for managing registered Visual Studio instances
+
+
+
+
+ Register a new Visual Studio instance
+
+
+
+
+ Unregister a Visual Studio instance by process ID
+
+
+
+
+ Update heartbeat for an instance
+
+
+
+
+ Get all registered instances
+
+
+
+
+ Get instance by process ID
+
+
+
+
+ Get instance by solution path
+
+
+
+
+ Get instance by port
+
+
+
+
+ Remove stale instances (no heartbeat for specified timeout)
+
+
+
+
+ Background service that periodically removes stale VS instances
+
+
+
+
+ Thread-safe in-memory registry for Visual Studio instances
+
+
+
+
+ Interface for communicating with the Roslyn Bridge Visual Studio plugin
+
+
+
+
+ Execute a query against the Roslyn Bridge server
+
+ The query request
+ Optional port of specific VS instance to target
+ Cancellation token
+ The query response
+
+
+
+ Check if the Roslyn Bridge server is healthy
+
+ Optional port of specific VS instance to check
+ Cancellation token
+ True if healthy, false otherwise
+
+
+
+ HTTP client for communicating with the Roslyn Bridge Visual Studio plugin
+
+
+
+
+ Resolves which VS instance port to use based on provided hints
+
+
+
+
diff --git a/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.Swagger.dll b/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.Swagger.dll
new file mode 100644
index 0000000..41e2fc2
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.Swagger.dll differ
diff --git a/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.SwaggerGen.dll b/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.SwaggerGen.dll
new file mode 100644
index 0000000..de7f45d
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.SwaggerGen.dll differ
diff --git a/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.SwaggerUI.dll b/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.SwaggerUI.dll
new file mode 100644
index 0000000..117b9f3
Binary files /dev/null and b/RoslynBridge.WebApi/publish/Swashbuckle.AspNetCore.SwaggerUI.dll differ
diff --git a/RoslynBridge.WebApi/publish/System.Diagnostics.DiagnosticSource.dll b/RoslynBridge.WebApi/publish/System.Diagnostics.DiagnosticSource.dll
new file mode 100644
index 0000000..535d956
Binary files /dev/null and b/RoslynBridge.WebApi/publish/System.Diagnostics.DiagnosticSource.dll differ
diff --git a/RoslynBridge.WebApi/publish/System.Diagnostics.EventLog.dll b/RoslynBridge.WebApi/publish/System.Diagnostics.EventLog.dll
new file mode 100644
index 0000000..92a5c74
Binary files /dev/null and b/RoslynBridge.WebApi/publish/System.Diagnostics.EventLog.dll differ
diff --git a/RoslynBridge.WebApi/publish/System.IO.Pipelines.dll b/RoslynBridge.WebApi/publish/System.IO.Pipelines.dll
new file mode 100644
index 0000000..12160e0
Binary files /dev/null and b/RoslynBridge.WebApi/publish/System.IO.Pipelines.dll differ
diff --git a/RoslynBridge.WebApi/publish/System.ServiceProcess.ServiceController.dll b/RoslynBridge.WebApi/publish/System.ServiceProcess.ServiceController.dll
new file mode 100644
index 0000000..5adc56d
Binary files /dev/null and b/RoslynBridge.WebApi/publish/System.ServiceProcess.ServiceController.dll differ
diff --git a/RoslynBridge.WebApi/publish/System.Text.Encodings.Web.dll b/RoslynBridge.WebApi/publish/System.Text.Encodings.Web.dll
new file mode 100644
index 0000000..596a73f
Binary files /dev/null and b/RoslynBridge.WebApi/publish/System.Text.Encodings.Web.dll differ
diff --git a/RoslynBridge.WebApi/publish/System.Text.Json.dll b/RoslynBridge.WebApi/publish/System.Text.Json.dll
new file mode 100644
index 0000000..66e9b6d
Binary files /dev/null and b/RoslynBridge.WebApi/publish/System.Text.Json.dll differ
diff --git a/RoslynBridge.WebApi/publish/appsettings.Development.json b/RoslynBridge.WebApi/publish/appsettings.Development.json
new file mode 100644
index 0000000..d9e464b
--- /dev/null
+++ b/RoslynBridge.WebApi/publish/appsettings.Development.json
@@ -0,0 +1,12 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "RoslynBridge.WebApi": "Debug"
+ }
+ },
+ "RoslynBridge": {
+ "BaseUrl": "http://localhost:59123"
+ }
+}
diff --git a/RoslynBridge.WebApi/publish/appsettings.json b/RoslynBridge.WebApi/publish/appsettings.json
new file mode 100644
index 0000000..c152051
--- /dev/null
+++ b/RoslynBridge.WebApi/publish/appsettings.json
@@ -0,0 +1,33 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "RoslynBridge.WebApi": "Information"
+ },
+ "EventLog": {
+ "SourceName": "Roslyn Bridge Web API",
+ "LogName": "Application",
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+ },
+ "AllowedHosts": "*",
+ "RoslynBridge": {
+ "BaseUrl": "http://localhost:59123",
+ "TimeoutSeconds": 30
+ },
+ "History": {
+ "MaxEntries": 1000,
+ "Enabled": true
+ },
+ "Kestrel": {
+ "Endpoints": {
+ "Http": {
+ "Url": "http://localhost:5000"
+ }
+ }
+ }
+}
diff --git a/RoslynBridge.WebApi/publish/runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll b/RoslynBridge.WebApi/publish/runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll
new file mode 100644
index 0000000..0e075ed
Binary files /dev/null and b/RoslynBridge.WebApi/publish/runtimes/browser/lib/net8.0/System.Text.Encodings.Web.dll differ
diff --git a/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.Messages.dll b/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.Messages.dll
new file mode 100644
index 0000000..893d4e9
Binary files /dev/null and b/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.Messages.dll differ
diff --git a/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.dll b/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.dll
new file mode 100644
index 0000000..1f645a4
Binary files /dev/null and b/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.Diagnostics.EventLog.dll differ
diff --git a/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.ServiceProcess.ServiceController.dll b/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.ServiceProcess.ServiceController.dll
new file mode 100644
index 0000000..9156521
Binary files /dev/null and b/RoslynBridge.WebApi/publish/runtimes/win/lib/net8.0/System.ServiceProcess.ServiceController.dll differ
diff --git a/RoslynBridge.WebApi/publish/web.config b/RoslynBridge.WebApi/publish/web.config
new file mode 100644
index 0000000..03a7f65
--- /dev/null
+++ b/RoslynBridge.WebApi/publish/web.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RoslynBridge.sln b/RoslynBridge.sln
index 1daf1bb..cd67d19 100644
--- a/RoslynBridge.sln
+++ b/RoslynBridge.sln
@@ -4,6 +4,8 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoslynBridge", "RoslynBridge\RoslynBridge.csproj", "{B2C3D4E5-F6A7-4B5C-9D8E-0F1A2B3C4D5E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RoslynBridge.WebApi", "RoslynBridge.WebApi\RoslynBridge.WebApi.csproj", "{F257A158-E5B4-569A-2B64-6EA9157F9C52}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -14,6 +16,10 @@ Global
{B2C3D4E5-F6A7-4B5C-9D8E-0F1A2B3C4D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2C3D4E5-F6A7-4B5C-9D8E-0F1A2B3C4D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2C3D4E5-F6A7-4B5C-9D8E-0F1A2B3C4D5E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F257A158-E5B4-569A-2B64-6EA9157F9C52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F257A158-E5B4-569A-2B64-6EA9157F9C52}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F257A158-E5B4-569A-2B64-6EA9157F9C52}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F257A158-E5B4-569A-2B64-6EA9157F9C52}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE