Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions EssentialCSharp.Chat.Shared/Services/AIChatService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,21 +341,17 @@ private static async Task<ResponseCreationOptions> CreateResponseOptionsAsync(
string responseText = string.Empty;
string responseId = response.Value.Id;

foreach (var outputItem in response.Value.OutputItems)
{
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
if (outputItem is MessageResponseItem messageItem &&
messageItem.Role == MessageRole.Assistant)
{
var textContent = messageItem.Content?.FirstOrDefault()?.Text;
if (!string.IsNullOrEmpty(textContent))
{
responseText = textContent;
break;
}
}
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
var assistantMessage = response.Value.OutputItems
.OfType<MessageResponseItem>()
.FirstOrDefault(m => m.Role == MessageRole.Assistant &&
!string.IsNullOrEmpty(m.Content?.FirstOrDefault()?.Text));

if (assistantMessage is not null)
{
responseText = assistantMessage.Content?.FirstOrDefault()?.Text ?? string.Empty;
}
#pragma warning restore OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.

return (responseText, responseId);
}
Expand Down
31 changes: 16 additions & 15 deletions EssentialCSharp.Chat.Shared/Services/ChunkingResultExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Security.Cryptography;
using System.Text;
using System.Linq;
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The using System.Linq; directive is redundant in .NET 6+ when ImplicitUsings is enabled (which is the default). System.Linq is automatically included in implicit usings. Consider removing this explicit using statement to align with modern .NET conventions.

Suggested change
using System.Linq;

Copilot uses AI. Check for mistakes.
using EssentialCSharp.Chat.Common.Models;

namespace EssentialCSharp.Chat.Common.Services;
Expand All @@ -8,24 +9,24 @@ public static partial class ChunkingResultExtensions
{
public static List<BookContentChunk> ToBookContentChunks(this FileChunkingResult result)
{
var chunks = new List<BookContentChunk>();
int? chapterNumber = ExtractChapterNumber(result.FileName);

foreach (var chunk in result.Chunks)
{
string chunkText = chunk;
string contentHash = ComputeSha256Hash(chunkText);

chunks.Add(new BookContentChunk
var chunks = result.Chunks
.Select(chunkText =>
{
Id = Guid.NewGuid().ToString(),
FileName = result.FileName,
Heading = ExtractHeading(chunkText),
ChunkText = chunkText,
ChapterNumber = chapterNumber,
ContentHash = contentHash
});
}
var contentHash = ComputeSha256Hash(chunkText);
return new BookContentChunk
{
Id = Guid.NewGuid().ToString(),
FileName = result.FileName,
Heading = ExtractHeading(chunkText),
ChunkText = chunkText,
ChapterNumber = chapterNumber,
ContentHash = contentHash
};
})
.ToList();

return chunks;
}

Expand Down
2 changes: 1 addition & 1 deletion EssentialCSharp.Chat/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ void WriteChunkingResult(FileChunkingResult result, TextWriter writer)
outputDirectory.Create();
foreach (var result in results)
{
var outputFile = Path.Combine(outputDirectory.FullName, Path.GetFileNameWithoutExtension(result.FileName) + ".chunks.txt");
var outputFile = Path.Join(outputDirectory.FullName, Path.GetFileNameWithoutExtension(result.FileName) + ".chunks.txt");
using var writer = new StreamWriter(outputFile, false);
WriteChunkingResult(result, writer);
Console.WriteLine($"Wrote: {outputFile}");
Expand Down
2 changes: 1 addition & 1 deletion EssentialCSharp.Web.Tests/ListingSourceCodeServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ private static ListingSourceCodeService CreateService()
private static DirectoryInfo GetTestDataPath()
{
string baseDirectory = AppContext.BaseDirectory;
string testDataPath = Path.Combine(baseDirectory, "TestData");
string testDataPath = Path.Join(baseDirectory, "TestData");

DirectoryInfo testDataDirectory = new(testDataPath);

Expand Down
2 changes: 1 addition & 1 deletion EssentialCSharp.Web.Tests/WebApplicationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder)
// Replace IListingSourceCodeService with one backed by TestData
services.RemoveAll<IListingSourceCodeService>();

string testDataPath = Path.Combine(AppContext.BaseDirectory, "TestData");
string testDataPath = Path.Join(AppContext.BaseDirectory, "TestData");
var fileProvider = new PhysicalFileProvider(testDataPath);
services.AddSingleton<IListingSourceCodeService>(sp =>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,8 @@ public async Task<IActionResult> OnPost(string? returnUrl = null)
{
await signInManager.SignOutAsync();
logger.LogInformation("User logged out.");
if (returnUrl is not null)
{
return LocalRedirect(returnUrl);
}
else
{
// This needs to be a redirect so that the browser performs a new
// request and the identity for the user gets updated.
Comment on lines 14 to 15
Copy link

Copilot AI Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment indentation is incorrect. The comment should be aligned at the same level as the code it describes (the return statement), not indented further. Comments should maintain consistent indentation with the code they document.

Copilot uses AI. Check for mistakes.
return RedirectToPage();
}
return returnUrl is not null ? LocalRedirect(returnUrl) : RedirectToPage();
}
}
4 changes: 2 additions & 2 deletions EssentialCSharp.Web/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public IActionResult Index()
}
else if (siteMapping is not null)
{
string filePath = Path.Combine(hostingEnvironment.ContentRootPath, Path.Combine(siteMapping.PagePath));
string filePath = Path.Join(hostingEnvironment.ContentRootPath, Path.Join(siteMapping.PagePath));
HtmlDocument doc = new();
doc.Load(filePath);
string headHtml = doc.DocumentNode.Element("html").Element("head").InnerHtml;
Expand Down Expand Up @@ -74,7 +74,7 @@ public IActionResult Home()
public IActionResult Guidelines()
{
ViewBag.PageTitle = "Coding Guidelines";
FileInfo fileInfo = new(Path.Combine(hostingEnvironment.ContentRootPath, "Guidelines", "guidelines.json"));
FileInfo fileInfo = new(Path.Join(hostingEnvironment.ContentRootPath, "Guidelines", "guidelines.json"));
if (!fileInfo.Exists)
{
return RedirectToAction(nameof(Error), new { errorMessage = "Guidelines could not be found", statusCode = 404 });
Expand Down
11 changes: 3 additions & 8 deletions EssentialCSharp.Web/Extensions/SiteMappingListExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,9 @@ public static class SiteMappingListExtensions
{
return siteMappings.FirstOrDefault();
}
foreach (string? potentialMatch in key.GetPotentialMatches())
{
if (siteMappings.FirstOrDefault(x => x.Keys.Any(x => x == potentialMatch)) is { } siteMap)
{
return siteMap;
}
}
return null;
return key.GetPotentialMatches()
.Select(potentialMatch => siteMappings.FirstOrDefault(x => x.Keys.Any(k => k == potentialMatch)))
.FirstOrDefault(siteMap => siteMap != null);
}
/// <summary>
/// Finds percent complete based on a key.
Expand Down
2 changes: 1 addition & 1 deletion EssentialCSharp.Web/Helpers/SitemapXmlHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static void GenerateAndSerializeSitemapXml(DirectoryInfo wwwrootDirectory
{
GenerateSitemapXml(wwwrootDirectory, siteMappings, routeConfigurationService, baseUrl, out List<SitemapNode> nodes);
XmlSerializer sitemapProvider = new();
var xmlPath = Path.Combine(wwwrootDirectory.FullName, "sitemap.xml");
var xmlPath = Path.Join(wwwrootDirectory.FullName, "sitemap.xml");
sitemapProvider.Serialize(new SitemapModel(nodes), xmlPath, true);
logger.LogInformation("sitemap.xml successfully written to {XmlPath}", xmlPath);
}
Expand Down
13 changes: 6 additions & 7 deletions EssentialCSharp.Web/Services/RouteConfigurationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,13 @@ private HashSet<string> ExtractStaticRoutes()

// For actions without attribute routes, use conventional routing
if (actionDescriptor.AttributeRouteInfo?.Template == null &&
actionDescriptor.RouteValues.TryGetValue("action", out var actionName) &&
actionDescriptor.RouteValues.TryGetValue("controller", out var controllerName))
actionDescriptor.RouteValues.TryGetValue("action", out var actionName) &&
actionDescriptor.RouteValues.TryGetValue("controller", out var controllerName) &&
controllerName?.Equals("Home", StringComparison.OrdinalIgnoreCase) == true &&
actionName != null)
{
if (controllerName?.Equals("Home", StringComparison.OrdinalIgnoreCase) == true && actionName != null)
{
// Use the action name directly as the route
routes.Add(actionName.ToLowerInvariant());
}
// Use the action name directly as the route
routes.Add(actionName.ToLowerInvariant());
}
}

Expand Down
2 changes: 1 addition & 1 deletion EssentialCSharp.Web/Services/SiteMappingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class SiteMappingService : ISiteMappingService

public SiteMappingService(IWebHostEnvironment webHostEnvironment)
{
string path = Path.Combine(webHostEnvironment.ContentRootPath, "Chapters", "sitemap.json");
string path = Path.Join(webHostEnvironment.ContentRootPath, "Chapters", "sitemap.json");
List<SiteMapping>? siteMappings = System.Text.Json.JsonSerializer.Deserialize<List<SiteMapping>>(File.OpenRead(path)) ?? throw new InvalidOperationException("No table of contents found");
SiteMappings = siteMappings;
}
Expand Down
Loading