From e5515edcab9d5fcece9c0e344a2fbf3f53e673b7 Mon Sep 17 00:00:00 2001 From: Roland Date: Wed, 20 May 2026 06:12:54 +0200 Subject: [PATCH] - Improve UI --- .localpilot/map.txt | 65 ++- .../v18/DocumentLayout.backup.json | 471 ++++++++-------- .../v18/DocumentLayout.json | 473 ++++++++-------- AuthorBuddy.Web.csproj | 13 +- Components/Layout/MainLayout.razor | 286 +++++++++- Components/Pages/Editor.razor | 520 +++++++++++++++++- Components/Pages/OllamaAssistant.razor | 105 ++++ Components/Pages/Settings.razor | 91 +-- Components/_Imports.razor | 1 - Data/AppDbContext.cs | 81 --- Data/DocumentMetaEntity.cs | 12 - Data/DocumentVector.cs | 11 + Data/ProjectEntity.cs | 11 - Data/SettingEntity.cs | 12 +- Data/UserEntity.cs | 9 - .../20260516151053_InitialCreate.Designer.cs | 127 ----- Migrations/20260516151053_InitialCreate.cs | 93 ---- Migrations/AppDbContextModelSnapshot.cs | 124 ----- Models/Constants.cs | 2 +- Models/FileTreeItem.cs | 9 + Models/OllamaSettings.cs | 10 +- Models/WikipediaResult.cs | 18 + Program.cs | 17 +- Services/FileScannerService.cs | 81 +-- Services/IOllamaService.cs | 3 + Services/IProjectService.cs | 2 + Services/IRagService.cs | 14 + Services/ISettingsService.cs | 12 +- Services/IWikipediaService.cs | 11 + Services/OllamaService.cs | 47 ++ Services/ProjectService.cs | 87 ++- Services/RagService.cs | 145 +++++ Services/SettingsService.cs | 262 ++++++--- Services/WikipediaService.cs | 136 +++++ author_brain.db | Bin 61440 -> 0 bytes vec0.dll | Bin 307712 -> 0 bytes wwwroot/app.css | 386 ++++++++++++- wwwroot/css/themes/dark.css | 2 + wwwroot/css/themes/light.css | 2 + wwwroot/css/themes/w95.css | 2 + 40 files changed, 2538 insertions(+), 1215 deletions(-) create mode 100644 Components/Pages/OllamaAssistant.razor delete mode 100644 Data/AppDbContext.cs create mode 100644 Data/DocumentVector.cs delete mode 100644 Migrations/20260516151053_InitialCreate.Designer.cs delete mode 100644 Migrations/20260516151053_InitialCreate.cs delete mode 100644 Migrations/AppDbContextModelSnapshot.cs create mode 100644 Models/FileTreeItem.cs create mode 100644 Models/WikipediaResult.cs create mode 100644 Services/IRagService.cs create mode 100644 Services/IWikipediaService.cs create mode 100644 Services/RagService.cs create mode 100644 Services/WikipediaService.cs delete mode 100644 author_brain.db delete mode 100644 vec0.dll diff --git a/.localpilot/map.txt b/.localpilot/map.txt index f82b0b3..ba25deb 100644 --- a/.localpilot/map.txt +++ b/.localpilot/map.txt @@ -1,13 +1,13 @@ ## WORKSPACE EXECUTIVE SUMMARY (YAML) -# Generated: 2026-05-16T15:21:43.3363122+02:00 +# Generated: 2026-05-20T06:11:22.0417511+02:00 # Root: E:\ollama_net\ollama\AuthorBuddy.Web Architecture: Type: Backend (C#/.NET) - Scale: 25 relevant source files + Scale: 34 relevant source files Components: 0 Controllers: 0 - Models: 6 - Services: 8 + Models: 8 + Services: 14 --- - File: AuthorBuddy.Web.csproj Preview: " net10.0 enable en..." @@ -18,25 +18,31 @@ Architecture: - File: AuthorBuddy.Web.slnx Preview: " " - File: Program.cs - Preview: "using AuthorBuddy.Web.Components; using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using AuthorBuddy.Web.Services; using Microsoft.EntityFram..." -- File: Data\AppDbContext.cs - Symbols: [AppDbContext] - Preview: "using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; namespace AuthorBuddy.Web.Data; public class AppDbContext : DbContext { public DbS..." + Preview: "using AuthorBuddy.Web.Components; using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using AuthorBuddy.Web.Services; using LiteDB; var builder ..." - File: Data\DocumentMetaEntity.cs Symbols: [DocumentMetaEntity] - Preview: "using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace AuthorBuddy.Web.Data; [Table('DocumentMeta'..." + Preview: "namespace AuthorBuddy.Web.Data; public class DocumentMetaEntity { public int Id { get; set; } public int? ProjectId { get; set; } public string ..." +- File: Data\DocumentVector.cs + Symbols: [DocumentVector] + Preview: "namespace AuthorBuddy.Web.Data; public class DocumentVector { public int Id { get; set; } public int DocumentMetaId { get; set; } public int Pro..." - File: Data\ProjectEntity.cs Symbols: [ProjectEntity] - Preview: "using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace AuthorBuddy.Web.Data; [Table('Projects')] p..." + Preview: "namespace AuthorBuddy.Web.Data; public class ProjectEntity { public int Id { get; set; } public string Name { get; set; } = string.Empty; public..." - File: Data\SettingEntity.cs Symbols: [SettingEntity] - Preview: "using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace AuthorBuddy.Web.Data; [Table('Settings')] p..." + Preview: "using LiteDB; namespace AuthorBuddy.Web.Data; public class SettingEntity { public int Id { get; set; } public string Key { get; set; } = string.Em..." +- File: Data\UserEntity.cs + Symbols: [UserEntity] + Preview: "namespace AuthorBuddy.Web.Data; public class UserEntity { public int Id { get; set; } public string Name { get; set; } = string.Empty; public bo..." - File: Models\Chapter.cs Symbols: [Chapter] Preview: "namespace AuthorBuddy.Web.Models; public class Chapter { public string Title { get; set; } = string.Empty; public string FilePath { get; set; } = ..." - File: Models\Constants.cs Symbols: [Constants] Preview: "namespace AuthorBuddy.Web.Models; public static class Constants { public static readonly string[] SubFolders = { '00_Drafts', '01_Fakten/Per..." +- File: Models\FileTreeItem.cs + Symbols: [FileTreeItem] + Preview: "namespace AuthorBuddy.Web.Models; public class FileTreeItem { public string Name { get; set; } = string.Empty; public string FullPath { get; set; ..." - File: Models\LLM_Model.cs Symbols: [LLM_Model, LLM_Model] Preview: "using System.Text.Json; namespace AuthorBuddy.Web.Models { public class LLM_Model { public LLM_Model(JsonElement model) { if (mode..." @@ -45,35 +51,56 @@ Architecture: Preview: " //namespace AuthorBuddy.Web.Models; //public class ModelStatus //{ // public string Status { get; private set; } = 'Unknown'; // public double Prog..." - File: Models\OllamaSettings.cs Symbols: [OllamaSettings] - Preview: "namespace AuthorBuddy.Web.Models; public class OllamaSettings { public string ChatModel { get; set; } = 'llama3.2'; public string EmbedModel { get..." + Preview: "namespace AuthorBuddy.Web.Models; public class OllamaSettings { public string StyleModel { get; set; } = 'gemma4:e4b'; public string EmbedModel { ..." - File: Models\Project.cs Symbols: [Project] Preview: "namespace AuthorBuddy.Web.Models; public class Project { public int Id { get; internal set; } public string Name { get; internal set; } = string.E..." +- File: Models\WikipediaResult.cs + Symbols: [WikipediaResult] + Preview: "namespace AuthorBuddy.Web.Models; public class WikipediaResult { public string Title { get; set; } = string.Empty; public string Snippet { get; se..." - File: Properties\launchSettings.json Preview: "{ '$schema': 'https://json.schemastore.org/launchsettings.json', 'profiles': { 'http': { 'commandName': 'Project', 'dotnetRunMessages': ..." - File: Services\FileScannerService.cs Symbols: [FileScannerService] - Preview: "using AuthorBuddy.Web.Data; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; namespace AuthorBuddy.Web.Services; public class FileSca..." + Preview: "using AuthorBuddy.Web.Data; using LiteDB; namespace AuthorBuddy.Web.Services; public class FileScannerService : IFileScannerService { private readon..." - File: Services\IFileScannerService.cs Symbols: [IFileScannerService] Preview: "namespace AuthorBuddy.Web.Services; public interface IFileScannerService { Task ScanProjectFolderAsync(int projectId, string rootPath, IProgress> GetLocalModelsAsyn..." - File: Services\IProjectService.cs Symbols: [IProjectService] Preview: "using AuthorBuddy.Web.Models; namespace AuthorBuddy.Web.Services; public interface IProjectService { Task CreateNewProjectAsync(string projectN..." +- File: Services\IRagService.cs + Symbols: [IRagServi, RagSearchResult] + Preview: "namespace AuthorBuddy.Web.Services; public class RagSearchResult { public string Text { get; set; } = string.Empty; public string FilePath { get; ..." - File: Services\ISettingsService.cs Symbols: [ISettingsService] - Preview: "namespace AuthorBuddy.Web.Services; public interface ISettingsService { Task GetAsync(string key); Task SaveAsync(Dictionary GetOllamaUrlAsync(); Task> SearchAsync(strin..." - File: Services\OllamaService.cs - Symbols: [ChatStream, OllamaService, OllamaService, OllamaService, GetLocalModelsAsync, DeleteModel, ExtractResponseText, PullModelAsync, catch, catch, catch, catch, Chat, Reconfigure] - Preview: "using AuthorBuddy.Web.Models; using System.Net.Http.Json; using System.Text.Json; namespace AuthorBuddy.Web.Services; public class OllamaService : IOl..." + Symbols: [OllamaService] + Preview: "using AuthorBuddy.Web.Models; using System.Text.Json; using static System.Net.Mime.MediaTypeNames; namespace AuthorBuddy.Web.Services; public class Ol..." - File: Services\ProjectService.cs Symbols: [ProjectService] - Preview: "using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using Microsoft.EntityFrameworkCore; namespace AuthorBuddy.Web.Services; public class Projec..." + Preview: "using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using LiteDB; namespace AuthorBuddy.Web.Services; public class ProjectService : IProjectServ..." +- File: Services\RagService.cs + Symbols: [RagService] + Preview: "using AuthorBuddy.Web.Data; using LiteDB; using System.Security.Cryptography; using System.Text; namespace AuthorBuddy.Web.Services; public class RagS..." - File: Services\SettingsService.cs Symbols: [SettingsService] - Preview: "using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using Microsoft.EntityFrameworkCore; using Microsoft.JSInterop; using static System.Runtime...." + Preview: "using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using LiteDB; namespace AuthorBuddy.Web.Services; public class SettingsService : ISettingsSe..." +- File: Services\ThemeService.cs + Symbols: [ThemeService, ThemeService] + Preview: "using Microsoft.JSInterop; namespace AuthorBuddy.Web.Services; public class ThemeService : IThemeService { private readonly IJSRuntime _js; public..." +- File: Services\WikipediaService.cs + Symbols: [WikipediaService] + Preview: "using AuthorBuddy.Web.Models; using System.Text.Json; using System.Web; namespace AuthorBuddy.Web.Services; public class WikipediaService : IWikipedia..." - File: Components\Layout\ReconnectModal.razor.js Preview: "// Set up event handlers const reconnectModal = document.getElementById('components-reconnect-modal'); reconnectModal.addEventListener('components-rec..." diff --git a/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.backup.json b/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.backup.json index f54bf47..7a1ae68 100644 --- a/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.backup.json +++ b/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.backup.json @@ -3,48 +3,68 @@ "WorkspaceRootPath": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\", "Documents": [ { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\data\\appdbcontext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:data\\appdbcontext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\ollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\editor.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\editor.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\settingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\settingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\mainlayout.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\mainlayout.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\isettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\isettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\ollamasettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\ollamasettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\settingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\settingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\settings.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\settings.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\mainlayout.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\mainlayout.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\projectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\projectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\filescannerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\filescannerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\ollamasettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\ollamasettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\ollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\project.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\project.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\ragservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ragservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iragservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iragservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\editor.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\editor.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\navmenu.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\navmenu.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" + }, + { + "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Data\\AppDbContext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\settings.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\settings.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\themeservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", @@ -74,26 +94,14 @@ "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\wwwroot\\lib\\bootstrap\\dist\\css\\bootstrap-utilities.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:wwwroot\\lib\\bootstrap\\dist\\css\\bootstrap-utilities.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}" }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\navmenu.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\navmenu.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" - }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\mainlayout.razor.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\mainlayout.razor.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}" }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\projectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\projectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iprojectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iprojectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\project.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\project.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\data\\projectentity.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:data\\projectentity.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" @@ -114,7 +122,7 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 9, + "SelectedChildIndex": 7, "Children": [ { "$type": "Bookmark", @@ -122,15 +130,32 @@ }, { "$type": "Document", - "DocumentIndex": 1, - "Title": "OllamaService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs", - "RelativeDocumentMoniker": "Services\\OllamaService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs*", - "RelativeToolTip": "Services\\OllamaService.cs*", - "ViewState": "AgIAADQAAAAAAAAAAAAQwEUAAABDAAAAAAAAAA==", + "DocumentIndex": 2, + "Title": "Program.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", + "RelativeDocumentMoniker": "Program.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", + "RelativeToolTip": "Program.cs", + "ViewState": "AgIAAAMAAAAAAAAAAAApwBoAAAANAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T06:43:46.404Z", + "WhenOpened": "2026-05-20T04:07:21.54Z", + "EditorCaption": "" + }, + { + "$type": "Bookmark", + "Name": "RST:0:0:{b3f9f954-0ca5-0091-76b4-34a47f44c954}" + }, + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "ISettingsService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ISettingsService.cs", + "RelativeDocumentMoniker": "Services\\ISettingsService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ISettingsService.cs*", + "RelativeToolTip": "Services\\ISettingsService.cs*", + "ViewState": "AgIAABoAAAAAAAAAAAA8wCYAAAAPAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T13:21:26.951Z", "EditorCaption": "" }, { @@ -141,46 +166,44 @@ "RelativeDocumentMoniker": "Services\\SettingsService.cs", "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\SettingsService.cs", "RelativeToolTip": "Services\\SettingsService.cs", - "ViewState": "AgIAAMAAAAAAAAAAAAAQwMgAAAAMAAAAAAAAAA==", + "ViewState": "AgIAAAAAAAAAAAAAAAAqwAYAAAAmAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T06:05:12.928Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 11, - "Title": "ThemeService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", - "RelativeDocumentMoniker": "Services\\ThemeService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", - "RelativeToolTip": "Services\\ThemeService.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "DocumentIndex": 9, + "Title": "RagService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\RagService.cs", + "RelativeDocumentMoniker": "Services\\RagService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\RagService.cs", + "RelativeToolTip": "Services\\RagService.cs", + "ViewState": "AgIAABIAAAAAAAAAAAAxwBoAAAAIAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T13:35:33.991Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 4, - "Title": "ISettingsService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ISettingsService.cs", - "RelativeDocumentMoniker": "Services\\ISettingsService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ISettingsService.cs", - "RelativeToolTip": "Services\\ISettingsService.cs", - "ViewState": "AgIAAAsAAAAAAAAAAAA8wCEAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T13:21:26.951Z", - "EditorCaption": "" + "WhenOpened": "2026-05-18T15:40:05.413Z" }, { "$type": "Document", "DocumentIndex": 8, + "Title": "Project.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs", + "RelativeDocumentMoniker": "Models\\Project.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs", + "RelativeToolTip": "Models\\Project.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAYAAAAaAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-15T15:57:10.2Z" + }, + { + "$type": "Document", + "DocumentIndex": 0, "Title": "MainLayout.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor", "RelativeDocumentMoniker": "Components\\Layout\\MainLayout.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor", - "RelativeToolTip": "Components\\Layout\\MainLayout.razor", - "ViewState": "AgIAAG8AAAAAAAAAAAAAAH0AAAAtAAAAAAAAAA==", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor*", + "RelativeToolTip": "Components\\Layout\\MainLayout.razor*", + "ViewState": "AgIAALUAAAAAAAAAAAApwM4AAABAAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", "WhenOpened": "2026-05-15T16:04:36.444Z", "EditorCaption": "" @@ -193,160 +216,75 @@ "RelativeDocumentMoniker": "Models\\OllamaSettings.cs", "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs", "RelativeToolTip": "Models\\OllamaSettings.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAqwAYAAAA6AAAAAAAAAA==", + "ViewState": "AgIAAAIAAAAAAAAAAAAxwAUAAAA+AAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T13:39:46.179Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 9, + "DocumentIndex": 13, + "Title": "AppDbContext.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs", + "RelativeDocumentMoniker": "Data\\AppDbContext.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs", + "RelativeToolTip": "Data\\AppDbContext.cs", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-14T10:50:13.284Z" + }, + { + "$type": "Document", + "DocumentIndex": 5, "Title": "FileScannerService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\FileScannerService.cs", "RelativeDocumentMoniker": "Services\\FileScannerService.cs", "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\FileScannerService.cs", "RelativeToolTip": "Services\\FileScannerService.cs", - "ViewState": "AgIAACkAAAAAAAAAAIAwwEsAAAAfAAAAAAAAAA==", + "ViewState": "AgIAABIAAAAAAAAAAAAQwCUAAAAWAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T06:02:53.46Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 2, - "Title": "Editor.razor", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Editor.razor", - "RelativeDocumentMoniker": "Components\\Pages\\Editor.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Editor.razor", - "RelativeToolTip": "Components\\Pages\\Editor.razor", - "ViewState": "AgIAAFgAAAAAAAAAAAApwGsAAAAwAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-16T13:01:59.743Z", - "EditorCaption": "" + "DocumentIndex": 10, + "Title": "IRagService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IRagService.cs", + "RelativeDocumentMoniker": "Services\\IRagService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IRagService.cs", + "RelativeToolTip": "Services\\IRagService.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAsAAAAVAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-18T15:37:44.565Z" }, { "$type": "Document", - "DocumentIndex": 0, - "Title": "AppDbContext.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs", - "RelativeDocumentMoniker": "Data\\AppDbContext.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs", - "RelativeToolTip": "Data\\AppDbContext.cs", - "ViewState": "AgIAADgAAAAAAAAAAAAuwEsAAAAAAAAAAAAAAA==", + "DocumentIndex": 4, + "Title": "ProjectService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs", + "RelativeDocumentMoniker": "Services\\ProjectService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs", + "RelativeToolTip": "Services\\ProjectService.cs", + "ViewState": "AgIAADQAAAAAAAAAAAAqwEYAAAAWAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-14T10:50:13.284Z", + "WhenOpened": "2026-05-15T15:56:55.229Z", "EditorCaption": "" }, { "$type": "Document", "DocumentIndex": 7, - "Title": "Settings.razor", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Settings.razor", - "RelativeDocumentMoniker": "Components\\Pages\\Settings.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Settings.razor", - "RelativeToolTip": "Components\\Pages\\Settings.razor", - "ViewState": "AgIAAHMAAAAAAAAAAADwv4UAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-15T16:43:26.6Z", - "EditorCaption": "" - }, - { - "$type": "Bookmark", - "Name": "RST:0:0:{b3f9f954-0ca5-0091-76b4-34a47f44c954}" - }, - { - "$type": "Document", - "DocumentIndex": 5, - "Title": "IOllamaService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", - "RelativeDocumentMoniker": "Services\\IOllamaService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", - "RelativeToolTip": "Services\\IOllamaService.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAqwAkAAAAPAAAAAAAAAA==", + "Title": "OllamaService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs", + "RelativeDocumentMoniker": "Services\\OllamaService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs", + "RelativeToolTip": "Services\\OllamaService.cs", + "ViewState": "AgIAAHoAAAAAAAAAAAAcwCoAAAAJAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T07:20:19.212Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 10, - "Title": "Program.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", - "RelativeDocumentMoniker": "Program.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", - "RelativeToolTip": "Program.cs", - "ViewState": "AgIAAAYAAAAAAAAAAAAAABUAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T06:03:12.506Z", - "EditorCaption": "" + "WhenOpened": "2026-05-16T06:43:46.404Z" }, { "$type": "Document", "DocumentIndex": 12, - "Title": "App.razor", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", - "RelativeDocumentMoniker": "Components\\App.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", - "RelativeToolTip": "Components\\App.razor", - "ViewState": "AgIAAAYAAAAAAAAAAAAAABgAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-16T05:42:06.383Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 15, - "Title": "Models.razor", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", - "RelativeDocumentMoniker": "Components\\Pages\\Models.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", - "RelativeToolTip": "Components\\Pages\\Models.razor", - "ViewState": "AgIAAGgAAAAAAAAAAAApwHQAAAAtAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-16T12:51:13.798Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 13, - "Title": "LLM_Model.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", - "RelativeDocumentMoniker": "Models\\LLM_Model.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", - "RelativeToolTip": "Models\\LLM_Model.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAqwBQAAAAzAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T12:53:35.486Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 14, - "Title": "ModelStatus.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", - "RelativeDocumentMoniker": "Models\\ModelStatus.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", - "RelativeToolTip": "Models\\ModelStatus.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAABEAAAADAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T13:01:24.508Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 19, - "Title": "MainLayout.razor.css", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor.css", - "RelativeDocumentMoniker": "Components\\Layout\\MainLayout.razor.css", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor.css", - "RelativeToolTip": "Components\\Layout\\MainLayout.razor.css", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003000|", - "WhenOpened": "2026-05-15T16:04:50.455Z" - }, - { - "$type": "Document", - "DocumentIndex": 18, "Title": "NavMenu.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor", "RelativeDocumentMoniker": "Components\\Layout\\NavMenu.razor", @@ -356,9 +294,118 @@ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", "WhenOpened": "2026-05-15T16:04:37.739Z" }, + { + "$type": "Document", + "DocumentIndex": 11, + "Title": "Editor.razor", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Editor.razor", + "RelativeDocumentMoniker": "Components\\Pages\\Editor.razor", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Editor.razor", + "RelativeToolTip": "Components\\Pages\\Editor.razor", + "ViewState": "AgIAAAoAAACA6NuCpTYvwJkAAAAcAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-16T13:01:59.743Z", + "EditorCaption": "" + }, { "$type": "Document", "DocumentIndex": 16, + "Title": "ThemeService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", + "RelativeDocumentMoniker": "Services\\ThemeService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", + "RelativeToolTip": "Services\\ThemeService.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T13:35:33.991Z" + }, + { + "$type": "Document", + "DocumentIndex": 15, + "Title": "Settings.razor", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Settings.razor", + "RelativeDocumentMoniker": "Components\\Pages\\Settings.razor", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Settings.razor", + "RelativeToolTip": "Components\\Pages\\Settings.razor", + "ViewState": "AgIAAHMAAAAAAAAAAADwv4UAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-15T16:43:26.6Z" + }, + { + "$type": "Document", + "DocumentIndex": 14, + "Title": "IOllamaService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", + "RelativeDocumentMoniker": "Services\\IOllamaService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", + "RelativeToolTip": "Services\\IOllamaService.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAqwAkAAAAPAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T07:20:19.212Z" + }, + { + "$type": "Document", + "DocumentIndex": 17, + "Title": "App.razor", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", + "RelativeDocumentMoniker": "Components\\App.razor", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", + "RelativeToolTip": "Components\\App.razor", + "ViewState": "AgIAAAYAAAAAAAAAAAAAABgAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-16T05:42:06.383Z" + }, + { + "$type": "Document", + "DocumentIndex": 20, + "Title": "Models.razor", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", + "RelativeDocumentMoniker": "Components\\Pages\\Models.razor", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", + "RelativeToolTip": "Components\\Pages\\Models.razor", + "ViewState": "AgIAAGgAAAAAAAAAAAApwHQAAAAtAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-16T12:51:13.798Z" + }, + { + "$type": "Document", + "DocumentIndex": 18, + "Title": "LLM_Model.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", + "RelativeDocumentMoniker": "Models\\LLM_Model.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", + "RelativeToolTip": "Models\\LLM_Model.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAqwBQAAAAzAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T12:53:35.486Z" + }, + { + "$type": "Document", + "DocumentIndex": 19, + "Title": "ModelStatus.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", + "RelativeDocumentMoniker": "Models\\ModelStatus.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", + "RelativeToolTip": "Models\\ModelStatus.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAABEAAAADAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T13:01:24.508Z" + }, + { + "$type": "Document", + "DocumentIndex": 23, + "Title": "MainLayout.razor.css", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor.css", + "RelativeDocumentMoniker": "Components\\Layout\\MainLayout.razor.css", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor.css", + "RelativeToolTip": "Components\\Layout\\MainLayout.razor.css", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003000|", + "WhenOpened": "2026-05-15T16:04:50.455Z" + }, + { + "$type": "Document", + "DocumentIndex": 21, "Title": "IFileScannerService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IFileScannerService.cs", "RelativeDocumentMoniker": "Services\\IFileScannerService.cs", @@ -371,18 +418,6 @@ { "$type": "Document", "DocumentIndex": 22, - "Title": "Project.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs", - "RelativeDocumentMoniker": "Models\\Project.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs", - "RelativeToolTip": "Models\\Project.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAYAAAAaAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-15T15:57:10.2Z" - }, - { - "$type": "Document", - "DocumentIndex": 17, "Title": "bootstrap-utilities.css", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\wwwroot\\lib\\bootstrap\\dist\\css\\bootstrap-utilities.css", "RelativeDocumentMoniker": "wwwroot\\lib\\bootstrap\\dist\\css\\bootstrap-utilities.css", @@ -394,19 +429,7 @@ }, { "$type": "Document", - "DocumentIndex": 20, - "Title": "ProjectService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs", - "RelativeDocumentMoniker": "Services\\ProjectService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs", - "RelativeToolTip": "Services\\ProjectService.cs", - "ViewState": "AgIAAB4AAAAAAAAAAAAowAAAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-15T15:56:55.229Z" - }, - { - "$type": "Document", - "DocumentIndex": 23, + "DocumentIndex": 25, "Title": "ProjectEntity.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\ProjectEntity.cs", "RelativeDocumentMoniker": "Data\\ProjectEntity.cs", @@ -418,7 +441,7 @@ }, { "$type": "Document", - "DocumentIndex": 21, + "DocumentIndex": 24, "Title": "IProjectService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IProjectService.cs", "RelativeDocumentMoniker": "Services\\IProjectService.cs", @@ -430,7 +453,7 @@ }, { "$type": "Document", - "DocumentIndex": 24, + "DocumentIndex": 26, "Title": "AuthorBuddy.Web.csproj", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj", "RelativeDocumentMoniker": "AuthorBuddy.Web.csproj", @@ -442,7 +465,7 @@ }, { "$type": "Document", - "DocumentIndex": 25, + "DocumentIndex": 27, "Title": "appsettings.json", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\appsettings.json", "RelativeDocumentMoniker": "appsettings.json", diff --git a/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.json b/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.json index 7199885..4236a65 100644 --- a/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.json +++ b/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.json @@ -2,50 +2,70 @@ "Version": 1, "WorkspaceRootPath": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\", "Documents": [ - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\data\\appdbcontext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:data\\appdbcontext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\ollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\editor.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\editor.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" - }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\settingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\settingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\isettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\isettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\ollamasettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\ollamasettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\settings.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\settings.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" - }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\mainlayout.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\mainlayout.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" }, { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\filescannerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\filescannerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\isettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\isettingsservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\projectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\projectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\filescannerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\filescannerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\ollamasettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\ollamasettings.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\ollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\project.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\project.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\ragservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ragservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iragservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iragservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\editor.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\editor.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\navmenu.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\navmenu.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" + }, + { + "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:Data\\AppDbContext.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iollamaservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" + }, + { + "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\settings.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", + "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\settings.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" + }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\themeservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\themeservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" @@ -74,26 +94,14 @@ "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\wwwroot\\lib\\bootstrap\\dist\\css\\bootstrap-utilities.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:wwwroot\\lib\\bootstrap\\dist\\css\\bootstrap-utilities.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}" }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\navmenu.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\navmenu.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}" - }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\layout\\mainlayout.razor.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\layout\\mainlayout.razor.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}" }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\projectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\projectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iprojectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iprojectservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" }, - { - "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\project.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", - "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\project.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" - }, { "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\data\\projectentity.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:data\\projectentity.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" @@ -114,7 +122,7 @@ "DocumentGroups": [ { "DockedWidth": 200, - "SelectedChildIndex": 8, + "SelectedChildIndex": 4, "Children": [ { "$type": "Bookmark", @@ -127,51 +135,75 @@ { "$type": "Document", "DocumentIndex": 3, - "Title": "SettingsService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\SettingsService.cs", - "RelativeDocumentMoniker": "Services\\SettingsService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\SettingsService.cs", - "RelativeToolTip": "Services\\SettingsService.cs", - "ViewState": "AgIAAMAAAAAAAAAAAAAQwMgAAAAMAAAAAAAAAA==", + "Title": "Program.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", + "RelativeDocumentMoniker": "Program.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", + "RelativeToolTip": "Program.cs", + "ViewState": "AgIAAAMAAAAAAAAAAAApwBoAAAANAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T06:05:12.928Z", + "WhenOpened": "2026-05-20T04:07:21.54Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 11, - "Title": "ThemeService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", - "RelativeDocumentMoniker": "Services\\ThemeService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", - "RelativeToolTip": "Services\\ThemeService.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T13:35:33.991Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 4, + "DocumentIndex": 2, "Title": "ISettingsService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ISettingsService.cs", "RelativeDocumentMoniker": "Services\\ISettingsService.cs", "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ISettingsService.cs", "RelativeToolTip": "Services\\ISettingsService.cs", - "ViewState": "AgIAAAsAAAAAAAAAAAA8wCEAAAAAAAAAAAAAAA==", + "ViewState": "AgIAABoAAAAAAAAAAAA8wCYAAAAPAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T13:21:26.951Z", "EditorCaption": "" }, + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "SettingsService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\SettingsService.cs", + "RelativeDocumentMoniker": "Services\\SettingsService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\SettingsService.cs", + "RelativeToolTip": "Services\\SettingsService.cs", + "ViewState": "AgIAADcBAAAAAAAAAAAQwEoBAAAIAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T06:05:12.928Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 9, + "Title": "RagService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\RagService.cs", + "RelativeDocumentMoniker": "Services\\RagService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\RagService.cs", + "RelativeToolTip": "Services\\RagService.cs", + "ViewState": "AgIAABIAAAAAAAAAAAAxwBoAAAAIAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-18T15:40:05.413Z" + }, { "$type": "Document", "DocumentIndex": 8, + "Title": "Project.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs", + "RelativeDocumentMoniker": "Models\\Project.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs", + "RelativeToolTip": "Models\\Project.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAYAAAAaAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-15T15:57:10.2Z" + }, + { + "$type": "Document", + "DocumentIndex": 1, "Title": "MainLayout.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor", "RelativeDocumentMoniker": "Components\\Layout\\MainLayout.razor", "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor", "RelativeToolTip": "Components\\Layout\\MainLayout.razor", - "ViewState": "AgIAAG8AAAAAAAAAAAAAAH0AAAAtAAAAAAAAAA==", + "ViewState": "AgIAALUAAAAAAAAAAAApwM4AAABAAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", "WhenOpened": "2026-05-15T16:04:36.444Z", "EditorCaption": "" @@ -184,169 +216,75 @@ "RelativeDocumentMoniker": "Models\\OllamaSettings.cs", "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs", "RelativeToolTip": "Models\\OllamaSettings.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAqwAYAAAA6AAAAAAAAAA==", + "ViewState": "AgIAAAIAAAAAAAAAAAAxwAUAAAA+AAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T13:39:46.179Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 9, + "DocumentIndex": 13, + "Title": "AppDbContext.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs", + "RelativeDocumentMoniker": "Data\\AppDbContext.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs", + "RelativeToolTip": "Data\\AppDbContext.cs", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-14T10:50:13.284Z" + }, + { + "$type": "Document", + "DocumentIndex": 5, "Title": "FileScannerService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\FileScannerService.cs", "RelativeDocumentMoniker": "Services\\FileScannerService.cs", "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\FileScannerService.cs", "RelativeToolTip": "Services\\FileScannerService.cs", - "ViewState": "AgIAACkAAAAAAAAAAIAwwEsAAAAfAAAAAAAAAA==", + "ViewState": "AgIAABIAAAAAAAAAAAAQwCUAAAAWAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T06:02:53.46Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 0, - "Title": "AppDbContext.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs", - "RelativeDocumentMoniker": "Data\\AppDbContext.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs", - "RelativeToolTip": "Data\\AppDbContext.cs", - "ViewState": "AgIAADgAAAAAAAAAAAAuwEsAAAAAAAAAAAAAAA==", + "DocumentIndex": 10, + "Title": "IRagService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IRagService.cs", + "RelativeDocumentMoniker": "Services\\IRagService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IRagService.cs", + "RelativeToolTip": "Services\\IRagService.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAsAAAAVAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-14T10:50:13.284Z", - "EditorCaption": "" + "WhenOpened": "2026-05-18T15:37:44.565Z" }, { "$type": "Document", - "DocumentIndex": 1, - "Title": "OllamaService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs", - "RelativeDocumentMoniker": "Services\\OllamaService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs", - "RelativeToolTip": "Services\\OllamaService.cs", - "ViewState": "AgIAADQAAAAAAAAAAAAQwEUAAABDAAAAAAAAAA==", + "DocumentIndex": 4, + "Title": "ProjectService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs", + "RelativeDocumentMoniker": "Services\\ProjectService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs", + "RelativeToolTip": "Services\\ProjectService.cs", + "ViewState": "AgIAADQAAAAAAAAAAAAqwEYAAAAWAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T06:43:46.404Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 2, - "Title": "Editor.razor", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Editor.razor", - "RelativeDocumentMoniker": "Components\\Pages\\Editor.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Editor.razor", - "RelativeToolTip": "Components\\Pages\\Editor.razor", - "ViewState": "AgIAAFgAAAAAAAAAAAApwGsAAAAwAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-16T13:01:59.743Z", + "WhenOpened": "2026-05-15T15:56:55.229Z", "EditorCaption": "" }, { "$type": "Document", "DocumentIndex": 7, - "Title": "Settings.razor", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Settings.razor", - "RelativeDocumentMoniker": "Components\\Pages\\Settings.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Settings.razor", - "RelativeToolTip": "Components\\Pages\\Settings.razor", - "ViewState": "AgIAAHMAAAAAAAAAAADwv4UAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-15T16:43:26.6Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 5, - "Title": "IOllamaService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", - "RelativeDocumentMoniker": "Services\\IOllamaService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", - "RelativeToolTip": "Services\\IOllamaService.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAqwAkAAAAPAAAAAAAAAA==", + "Title": "OllamaService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs", + "RelativeDocumentMoniker": "Services\\OllamaService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs", + "RelativeToolTip": "Services\\OllamaService.cs", + "ViewState": "AgIAAHoAAAAAAAAAAAAcwCoAAAAJAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T07:20:19.212Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 10, - "Title": "Program.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", - "RelativeDocumentMoniker": "Program.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", - "RelativeToolTip": "Program.cs", - "ViewState": "AgIAAAYAAAAAAAAAAAAAABUAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T06:03:12.506Z", - "EditorCaption": "" + "WhenOpened": "2026-05-16T06:43:46.404Z" }, { "$type": "Document", "DocumentIndex": 12, - "Title": "App.razor", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", - "RelativeDocumentMoniker": "Components\\App.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", - "RelativeToolTip": "Components\\App.razor", - "ViewState": "AgIAAAYAAAAAAAAAAAAAABgAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-16T05:42:06.383Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 15, - "Title": "Models.razor", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", - "RelativeDocumentMoniker": "Components\\Pages\\Models.razor", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", - "RelativeToolTip": "Components\\Pages\\Models.razor", - "ViewState": "AgIAAGgAAAAAAAAAAAApwHQAAAAtAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-16T12:51:13.798Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 13, - "Title": "LLM_Model.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", - "RelativeDocumentMoniker": "Models\\LLM_Model.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", - "RelativeToolTip": "Models\\LLM_Model.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAqwBQAAAAzAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T12:53:35.486Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 14, - "Title": "ModelStatus.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", - "RelativeDocumentMoniker": "Models\\ModelStatus.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", - "RelativeToolTip": "Models\\ModelStatus.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAABEAAAADAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T13:01:24.508Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 19, - "Title": "MainLayout.razor.css", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor.css", - "RelativeDocumentMoniker": "Components\\Layout\\MainLayout.razor.css", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor.css", - "RelativeToolTip": "Components\\Layout\\MainLayout.razor.css", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003000|", - "WhenOpened": "2026-05-15T16:04:50.455Z" - }, - { - "$type": "Document", - "DocumentIndex": 18, "Title": "NavMenu.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor", "RelativeDocumentMoniker": "Components\\Layout\\NavMenu.razor", @@ -356,9 +294,118 @@ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", "WhenOpened": "2026-05-15T16:04:37.739Z" }, + { + "$type": "Document", + "DocumentIndex": 11, + "Title": "Editor.razor", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Editor.razor", + "RelativeDocumentMoniker": "Components\\Pages\\Editor.razor", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Editor.razor", + "RelativeToolTip": "Components\\Pages\\Editor.razor", + "ViewState": "AgIAAAoAAACA6NuCpTYvwJkAAAAcAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-16T13:01:59.743Z", + "EditorCaption": "" + }, { "$type": "Document", "DocumentIndex": 16, + "Title": "ThemeService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", + "RelativeDocumentMoniker": "Services\\ThemeService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", + "RelativeToolTip": "Services\\ThemeService.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T13:35:33.991Z" + }, + { + "$type": "Document", + "DocumentIndex": 15, + "Title": "Settings.razor", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Settings.razor", + "RelativeDocumentMoniker": "Components\\Pages\\Settings.razor", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Settings.razor", + "RelativeToolTip": "Components\\Pages\\Settings.razor", + "ViewState": "AgIAAHMAAAAAAAAAAADwv4UAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-15T16:43:26.6Z" + }, + { + "$type": "Document", + "DocumentIndex": 14, + "Title": "IOllamaService.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", + "RelativeDocumentMoniker": "Services\\IOllamaService.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", + "RelativeToolTip": "Services\\IOllamaService.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAqwAkAAAAPAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T07:20:19.212Z" + }, + { + "$type": "Document", + "DocumentIndex": 17, + "Title": "App.razor", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", + "RelativeDocumentMoniker": "Components\\App.razor", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", + "RelativeToolTip": "Components\\App.razor", + "ViewState": "AgIAAAYAAAAAAAAAAAAAABgAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-16T05:42:06.383Z" + }, + { + "$type": "Document", + "DocumentIndex": 20, + "Title": "Models.razor", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", + "RelativeDocumentMoniker": "Components\\Pages\\Models.razor", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", + "RelativeToolTip": "Components\\Pages\\Models.razor", + "ViewState": "AgIAAGgAAAAAAAAAAAApwHQAAAAtAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-16T12:51:13.798Z" + }, + { + "$type": "Document", + "DocumentIndex": 18, + "Title": "LLM_Model.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", + "RelativeDocumentMoniker": "Models\\LLM_Model.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", + "RelativeToolTip": "Models\\LLM_Model.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAqwBQAAAAzAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T12:53:35.486Z" + }, + { + "$type": "Document", + "DocumentIndex": 19, + "Title": "ModelStatus.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", + "RelativeDocumentMoniker": "Models\\ModelStatus.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", + "RelativeToolTip": "Models\\ModelStatus.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAAABEAAAADAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T13:01:24.508Z" + }, + { + "$type": "Document", + "DocumentIndex": 23, + "Title": "MainLayout.razor.css", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor.css", + "RelativeDocumentMoniker": "Components\\Layout\\MainLayout.razor.css", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor.css", + "RelativeToolTip": "Components\\Layout\\MainLayout.razor.css", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003000|", + "WhenOpened": "2026-05-15T16:04:50.455Z" + }, + { + "$type": "Document", + "DocumentIndex": 21, "Title": "IFileScannerService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IFileScannerService.cs", "RelativeDocumentMoniker": "Services\\IFileScannerService.cs", @@ -371,18 +418,6 @@ { "$type": "Document", "DocumentIndex": 22, - "Title": "Project.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs", - "RelativeDocumentMoniker": "Models\\Project.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs", - "RelativeToolTip": "Models\\Project.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAAAAYAAAAaAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-15T15:57:10.2Z" - }, - { - "$type": "Document", - "DocumentIndex": 17, "Title": "bootstrap-utilities.css", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\wwwroot\\lib\\bootstrap\\dist\\css\\bootstrap-utilities.css", "RelativeDocumentMoniker": "wwwroot\\lib\\bootstrap\\dist\\css\\bootstrap-utilities.css", @@ -394,19 +429,7 @@ }, { "$type": "Document", - "DocumentIndex": 20, - "Title": "ProjectService.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs", - "RelativeDocumentMoniker": "Services\\ProjectService.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs", - "RelativeToolTip": "Services\\ProjectService.cs", - "ViewState": "AgIAAB4AAAAAAAAAAAAowAAAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-15T15:56:55.229Z" - }, - { - "$type": "Document", - "DocumentIndex": 23, + "DocumentIndex": 25, "Title": "ProjectEntity.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\ProjectEntity.cs", "RelativeDocumentMoniker": "Data\\ProjectEntity.cs", @@ -418,7 +441,7 @@ }, { "$type": "Document", - "DocumentIndex": 21, + "DocumentIndex": 24, "Title": "IProjectService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IProjectService.cs", "RelativeDocumentMoniker": "Services\\IProjectService.cs", @@ -430,7 +453,7 @@ }, { "$type": "Document", - "DocumentIndex": 24, + "DocumentIndex": 26, "Title": "AuthorBuddy.Web.csproj", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj", "RelativeDocumentMoniker": "AuthorBuddy.Web.csproj", @@ -442,7 +465,7 @@ }, { "$type": "Document", - "DocumentIndex": 25, + "DocumentIndex": 27, "Title": "appsettings.json", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\appsettings.json", "RelativeDocumentMoniker": "appsettings.json", diff --git a/AuthorBuddy.Web.csproj b/AuthorBuddy.Web.csproj index 4204023..f812cf0 100644 --- a/AuthorBuddy.Web.csproj +++ b/AuthorBuddy.Web.csproj @@ -9,18 +9,7 @@ - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - PreserveNewest - + diff --git a/Components/Layout/MainLayout.razor b/Components/Layout/MainLayout.razor index 721251f..238a62d 100644 --- a/Components/Layout/MainLayout.razor +++ b/Components/Layout/MainLayout.razor @@ -1,4 +1,5 @@ @inherits LayoutComponentBase +@implements IDisposable @inject IProjectService ProjectService @inject ISettingsService SettingsService @inject IThemeService ThemeService @@ -16,24 +17,12 @@ { } - } @@ -74,17 +64,92 @@ { @foreach (var p in projects) { - + } } } - } + @if (currentProjectId > 0 && fileTree != null) + { + + } + +@if (showRenameDialog) +{ + +} + +@if (showNewFileDialog) +{ + +}
@@ -106,29 +171,93 @@ private string? activeSection; private bool showProjectList; private List? projects; + private List? fileTree; + private int currentProjectId; + private string? currentFilePath; private string statusText = "Bereit"; private bool isBusy; private double operationProgress; + private bool showRenameDialog; + private string renameNewName = string.Empty; + private FileTreeItem? renameTarget; + private bool showNewFileDialog; + private string newFileName = string.Empty; + private FileTreeItem? newFileParentDir; [Inject] private NavigationManager Navigation { get; set; } = default!; protected override async Task OnInitializedAsync() { + await SettingsService.InitializeAsync(); + Navigation.LocationChanged += OnLocationChanged; await LoadProjects(); + await LoadProjectContext(); + await AutoLoadLastProject(); + } + + private async Task AutoLoadLastProject() + { + if (currentProjectId > 0) return; + var lastId = await SettingsService.GetLastProjectIdAsync(); + if (lastId == null) return; + var project = projects?.FirstOrDefault(p => p.Id == lastId.Value); + if (project != null) + { + await SettingsService.InitializeAsync(lastId.Value); + await SelectProject(project); + } } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - await SettingsService.InitializeAsync(); var theme = OllamaSettings.Theme; if (!string.IsNullOrEmpty(theme)) await ThemeService.ApplyTheme(theme); } } + public void Dispose() + { + Navigation.LocationChanged -= OnLocationChanged; + } + + private async void OnLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e) + { + await LoadProjects(); + await LoadProjectContext(); + StateHasChanged(); + } + + private async Task LoadProjectContext() + { + currentProjectId = SettingsService.CurrentProjectId ?? 0; + currentFilePath = SettingsService.CurrentFilePath; + + if (currentProjectId > 0) + { + await LoadFileTree(); + } + else + { + fileTree = null; + } + } + + private async Task LoadFileTree() + { + try + { + fileTree = await ProjectService.GetProjectFileTreeAsync(currentProjectId); + } + catch + { + fileTree = new(); + } + } + private async Task LoadProjects() { try @@ -155,13 +284,7 @@ private void CreateNewProject() { activeSection = null; - Navigation.NavigateTo("/editor?action=newproject"); - } - - private void OpenProject() - { - activeSection = null; - Navigation.NavigateTo("/editor?action=open"); + Navigation.NavigateTo("/editor/newproject"); } private void OpenEditor() @@ -176,10 +299,123 @@ Navigation.NavigateTo(path); } - private void SelectProject(Project project) + private async Task SelectProject(Project project) { + activeSection = "files"; + SettingsService.CurrentProjectId = project.Id; + currentProjectId = project.Id; + SettingsService.CurrentFilePath = null; + await SettingsService.SaveLastProjectIdAsync(project.Id); + await SettingsService.LoadProjectSettingsAsync(); + await LoadFileTree(); + Navigation.NavigateTo($"/editor/index/{project.Id}"); + } + + private async Task RefreshFileTree() + { + await LoadFileTree(); + StateHasChanged(); + } + + private void BeginRename(FileTreeItem item) + { + renameTarget = item; + renameNewName = item.Name; + showRenameDialog = true; + } + + private void CancelRename() + { + showRenameDialog = false; + renameTarget = null; + renameNewName = string.Empty; + } + + private async Task ConfirmRename() + { + if (renameTarget == null || string.IsNullOrWhiteSpace(renameNewName)) return; + + try + { + var dir = Path.GetDirectoryName(renameTarget.FullPath)!; + var newPath = Path.Combine(dir, renameNewName); + if (File.Exists(newPath)) + { + statusText = "Datei existiert bereits."; + return; + } + File.Move(renameTarget.FullPath, newPath); + + if (currentFilePath == renameTarget.FullPath) + SettingsService.CurrentFilePath = newPath; + + statusText = $"Umbenannt zu: {renameNewName}"; + } + catch (Exception ex) + { + statusText = $"Fehler: {ex.Message}"; + } + finally + { + showRenameDialog = false; + renameTarget = null; + renameNewName = string.Empty; + await LoadFileTree(); + StateHasChanged(); + } + } + + private void BeginNewFile(FileTreeItem dir) + { + newFileParentDir = dir; + newFileName = string.Empty; + showNewFileDialog = true; + } + + private void CancelNewFile() + { + showNewFileDialog = false; + newFileParentDir = null; + newFileName = string.Empty; + } + + private async Task ConfirmNewFile() + { + if (newFileParentDir == null || string.IsNullOrWhiteSpace(newFileName)) return; + + try + { + var path = Path.Combine(newFileParentDir.FullPath, newFileName); + if (!path.EndsWith(".md", StringComparison.OrdinalIgnoreCase)) + path += ".md"; + if (File.Exists(path)) + { + statusText = "Datei existiert bereits."; + return; + } + File.WriteAllText(path, $"# {Path.GetFileNameWithoutExtension(path)}\n\n"); + statusText = $"Erstellt: {Path.GetFileName(path)}"; + } + catch (Exception ex) + { + statusText = $"Fehler: {ex.Message}"; + } + finally + { + showNewFileDialog = false; + newFileParentDir = null; + newFileName = string.Empty; + await LoadFileTree(); + StateHasChanged(); + } + } + + private void OpenFile(FileTreeItem item) + { + if (item.IsDirectory) return; activeSection = null; - Navigation.NavigateTo($"/editor?projectId={project.Id}"); + SettingsService.CurrentFilePath = item.FullPath; + Navigation.NavigateTo($"/editor/file/{currentProjectId}?t={DateTime.Now.Ticks}"); } public void SetStatus(string text, bool busy = false, double progress = 0) diff --git a/Components/Pages/Editor.razor b/Components/Pages/Editor.razor index 4997b65..050f597 100644 --- a/Components/Pages/Editor.razor +++ b/Components/Pages/Editor.razor @@ -3,12 +3,19 @@ @page "/editor/{action}/{projectId:int}" @inject IOllamaService OllamaService @inject IProjectService ProjectService +@inject IRagService RagService +@inject ISettingsService SettingsService +@inject IWikipediaService WikipediaService @inject NavigationManager Navigation +@implements IDisposable +@rendermode InteractiveServer + Editor - Author Buddy -
- +
+ +
@statusText @@ -17,30 +24,120 @@ { } - - - + + + + +
+ @if (showVersionDialog) + { + + } + +
+ + + + +
+
@searchQuery
+ + @if (showSpellDiff && !string.IsNullOrEmpty(correctedText)) + { +
+
+

Rechtschreibprüfung - Änderungen:

+ +
+
+ } + else if (ragResults != null && ragResults.Count > 0) + { +
+

Gefundene Fakten (RAG):

+ @foreach (var r in ragResults) + { +
+
Ähnlichkeit: @r.Similarity.ToString("P1")
+
@r.FilePath
+
@r.Text
+
+ } +
+ } + else if (wikipediaResults != null && wikipediaResults.Count > 0) + { +
+

Wikipedia-Recherche:

+ @foreach (var r in wikipediaResults) + { +
+
@(r.Language == "de" ? "🇩🇪" : "🇬🇧") @r.Language.ToUpper()
+
+ @r.Title +
+
@r.Snippet
+ @if (!string.IsNullOrEmpty(r.Extract)) + { +
@r.Extract
+ } +
+ + +
+
+ } +
+ } + else if (!string.IsNullOrEmpty(analysisResult)) + { +
+

Ergebnis:

+
@analysisResult
+
+ }
-@if (showSpellDiff && !string.IsNullOrEmpty(correctedText)) +@if (showCreateDialog) { -
-

Rechtschreibprüfung - Änderungen:

- -
-} -else if (!string.IsNullOrEmpty(analysisResult)) -{ -
-

Ergebnis:

-
@analysisResult
+ } @@ -52,19 +149,81 @@ else if (!string.IsNullOrEmpty(analysisResult)) public int? ProjectId { get; set; } private string editorContent = string.Empty; + private string searchQuery = string.Empty; private string statusText = "Bereit"; private bool isChecking; + private bool buttonDisabled; private double checkProgress; private string analysisResult = string.Empty; private string originalText = string.Empty; private string correctedText = string.Empty; private bool showSpellDiff; + private List? ragResults; + private List? wikipediaResults; + + private int currentProjectId; + private string? currentFile; + private bool showCreateDialog; + private string newProjectName = string.Empty; + private string newProjectPath = string.Empty; + private Dictionary loadedArticles = new(); + private bool showVersionDialog; + private string versionComment = string.Empty; + private VersionEntry? latestVersion; + + private record VersionEntry(string FilePath, DateTime Timestamp, string? Comment); protected override async Task OnInitializedAsync() { - if (Action == "newproject") + Navigation.LocationChanged += OnLocationChanged; + await LoadProjectContext(); + + if (string.Equals(Action, "newproject", StringComparison.OrdinalIgnoreCase)) { - statusText = "Bitte nutze die Einstellungen zum Erstellen eines neuen Projekts."; + showCreateDialog = true; + } + } + + private async void OnLocationChanged(object? sender, LocationChangedEventArgs e) + { + await LoadProjectContext(); + StateHasChanged(); + } + + public void Dispose() + { + Navigation.LocationChanged -= OnLocationChanged; + } + + private void HandleSearchInput(ChangeEventArgs e) + { + searchQuery = e.Value?.ToString() ?? string.Empty; + buttonDisabled = isChecking || string.IsNullOrWhiteSpace(searchQuery); + StateHasChanged(); + } + + private async Task LoadProjectContext() + { + if (ProjectId.HasValue) + { + currentProjectId = ProjectId.Value; + SettingsService.CurrentProjectId = currentProjectId; + } + else if (SettingsService.CurrentProjectId.HasValue) + { + currentProjectId = SettingsService.CurrentProjectId.Value; + } + + if (currentProjectId > 0) + await SettingsService.LoadProjectSettingsAsync(); + + var filePath = SettingsService.CurrentFilePath; + if (!string.IsNullOrEmpty(filePath) && File.Exists(filePath)) + { + currentFile = filePath; + editorContent = await File.ReadAllTextAsync(filePath); + statusText = $"Geladen: {Path.GetFileName(filePath)}"; + RefreshLatestVersion(); } } @@ -76,6 +235,8 @@ else if (!string.IsNullOrEmpty(analysisResult)) statusText = "Ollama analysiert Stil..."; checkProgress = 50; showSpellDiff = false; + ragResults = null; + wikipediaResults = null; try { @@ -101,6 +262,8 @@ else if (!string.IsNullOrEmpty(analysisResult)) statusText = "Ollama prüft Rechtschreibung..."; checkProgress = 50; showSpellDiff = false; + ragResults = null; + wikipediaResults = null; try { @@ -122,15 +285,314 @@ else if (!string.IsNullOrEmpty(analysisResult)) private async Task RagSearch() { - if (string.IsNullOrWhiteSpace(editorContent)) return; + if (string.IsNullOrWhiteSpace(searchQuery)) return; isChecking = true; statusText = "Suche verwandte Fakten..."; showSpellDiff = false; + analysisResult = string.Empty; + ragResults = null; + wikipediaResults = null; - await Task.Delay(500); - analysisResult = "RAG-Suche: Stelle sicher, dass ein Projekt geladen und indexiert wurde."; - statusText = "Bereit"; - isChecking = false; + try + { + if (currentProjectId == 0) + { + analysisResult = "Kein Projekt geladen. Öffne zuerst ein Projekt über die Sidebar."; + return; + } + + ragResults = await RagService.SearchAsync(currentProjectId, searchQuery, 5); + + if (ragResults.Count == 0) + { + analysisResult = "Keine relevanten Fakten gefunden. Indexiere das Projekt ggf. über 'Projekt indexieren'."; + } + } + catch (Exception ex) + { + analysisResult = $"RAG-Fehler: {ex.Message}"; + } + finally + { + statusText = "Bereit"; + isChecking = false; + } + } + + private async Task SearchWikipedia() + { + if (string.IsNullOrWhiteSpace(searchQuery)) return; + + isChecking = true; + statusText = "Suche auf Wikipedia..."; + showSpellDiff = false; + analysisResult = string.Empty; + ragResults = null; + wikipediaResults = null; + loadedArticles.Clear(); + + try + { + var request = new WikipediaSearchRequest + { + Query = searchQuery, + SearchGerman = true, + SearchEnglish = true, + MaxResults = 3 + }; + + wikipediaResults = await WikipediaService.SearchAsync(request); + + foreach (var result in wikipediaResults) + { + var extract = await WikipediaService.GetExtractAsync(result.Title, result.Language); + if (extract != null) + result.Extract = extract.Length > 800 ? extract[..800] + "..." : extract; + } + + if (wikipediaResults.Count == 0) + analysisResult = "Keine Wikipedia-Artikel gefunden."; + } + catch (Exception ex) + { + analysisResult = $"Wikipedia-Fehler: {ex.Message}"; + } + finally + { + statusText = "Bereit"; + isChecking = false; + } + } + + private async Task LoadFullArticle(WikipediaResult result) + { + statusText = $"Lade Artikel: {result.Title}..."; + + try + { + var fullText = await WikipediaService.GetFullArticleAsync(result.Title, result.Language); + if (fullText != null) + { + result.Extract = fullText; + loadedArticles[result.Url] = true; + statusText = "Artikel geladen."; + } + else + { + statusText = "Konnte Artikel nicht laden."; + } + } + catch (Exception ex) + { + statusText = $"Fehler: {ex.Message}"; + } + } + + private async Task SaveAsFact(WikipediaResult result) + { + if (string.IsNullOrWhiteSpace(result.Extract) || currentProjectId == 0) return; + + statusText = "Speichere als Fakt..."; + + try + { + var projects = await ProjectService.GetAllProjectsAsync(); + var project = projects.FirstOrDefault(p => p.Id == currentProjectId); + if (project == null) + { + statusText = "Projekt nicht gefunden."; + return; + } + + var factsDir = Path.Combine(project.RootPath, "01_Fakten"); + Directory.CreateDirectory(factsDir); + + var safeName = SanitizeFilename(searchQuery); + var filePath = Path.Combine(factsDir, $"{safeName}.md"); + + var content = $"# {result.Title}\n" + + $"- Quelle: [{result.Title}]({result.Url})\n" + + $"- Sprache: {result.Language.ToUpper()}\n" + + $"- Abgerufen: {DateTime.Now:dd.MM.yyyy HH:mm}\n\n" + + result.Extract; + + await File.WriteAllTextAsync(filePath, content); + statusText = $"Gespeichert als: {safeName}.md"; + } + catch (Exception ex) + { + statusText = $"Fehler beim Speichern: {ex.Message}"; + } + } + + private static string SanitizeFilename(string name) + { + var invalid = Path.GetInvalidFileNameChars(); + var sanitized = new string(name.Where(c => !invalid.Contains(c)).ToArray()); + return string.IsNullOrWhiteSpace(sanitized) ? "fakt" : sanitized.Trim(); + } + + private void CancelCreateProject() + { + showCreateDialog = false; + Navigation.NavigateTo("/editor"); + } + + private async Task CreateProject() + { + if (string.IsNullOrWhiteSpace(newProjectName) || string.IsNullOrWhiteSpace(newProjectPath)) return; + + isChecking = true; + statusText = "Erstelle Projekt..."; + + try + { + Directory.CreateDirectory(newProjectPath); + var id = await ProjectService.CreateNewProjectAsync(newProjectName, newProjectPath); + SettingsService.CurrentProjectId = id; + await SettingsService.LoadProjectSettingsAsync(); + showCreateDialog = false; + Navigation.NavigateTo($"/editor/index/{id}"); + } + catch (Exception ex) + { + analysisResult = $"Fehler beim Erstellen: {ex.Message}"; + } + finally + { + isChecking = false; + statusText = "Bereit"; + } + } + + private async Task IndexProject() + { + if (currentProjectId == 0) + { + analysisResult = "Kein Projekt geladen. Offne zuerst ein Projekt uber die Sidebar."; + return; + } + + isChecking = true; + statusText = "Indexiere Projekt..."; + analysisResult = string.Empty; + ragResults = null; + + try + { + var projects = await ProjectService.GetAllProjectsAsync(); + var project = projects.FirstOrDefault(p => p.Id == currentProjectId); + if (project == null) + { + analysisResult = "Projekt nicht gefunden."; + return; + } + + var p = new Progress(msg => + { + statusText = msg; + InvokeAsync(StateHasChanged); + }); + + await RagService.IndexProjectAsync(currentProjectId, project.RootPath, p); + analysisResult = "Projekt erfolgreich indexiert."; + } + catch (Exception ex) + { + analysisResult = $"Indexierungsfehler: {ex.Message}"; + } + finally + { + statusText = "Bereit"; + isChecking = false; + } + } + + private async Task SaveCurrentFile() + { + if (string.IsNullOrEmpty(currentFile)) return; + await File.WriteAllTextAsync(currentFile, editorContent); + statusText = $"Gespeichert: {Path.GetFileName(currentFile)}"; + } + + private void ShowVersionDialog() + { + showVersionDialog = true; + versionComment = string.Empty; + } + + private async Task SaveVersioned() + { + if (string.IsNullOrEmpty(currentFile)) return; + + var dir = Path.GetDirectoryName(currentFile)!; + var name = Path.GetFileNameWithoutExtension(currentFile); + var ext = Path.GetExtension(currentFile); + var versionsDir = Path.Combine(dir, "_versions"); + Directory.CreateDirectory(versionsDir); + + var stamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); + var versionPath = Path.Combine(versionsDir, $"{name}_{stamp}{ext}"); + + await File.WriteAllTextAsync(currentFile, editorContent); + await File.WriteAllTextAsync(versionPath, editorContent); + var meta = $"Kommentar: {versionComment}"; + await File.WriteAllTextAsync(versionPath + ".meta", meta); + + statusText = $"Version gespeichert: {name}_{stamp}{ext}"; + showVersionDialog = false; + versionComment = string.Empty; + RefreshLatestVersion(); + } + + private void RefreshLatestVersion() + { + latestVersion = null; + if (string.IsNullOrEmpty(currentFile)) return; + + var dir = Path.GetDirectoryName(currentFile)!; + var name = Path.GetFileNameWithoutExtension(currentFile); + var ext = Path.GetExtension(currentFile); + var versionsDir = Path.Combine(dir, "_versions"); + if (!Directory.Exists(versionsDir)) return; + + var pattern = $"{name}_*{ext}"; + var files = Directory.GetFiles(versionsDir, pattern).OrderByDescending(f => f).ToList(); + if (files.Count == 0) return; + + var latest = files.First(); + var metaFile = latest + ".meta"; + string? comment = null; + if (File.Exists(metaFile)) + { + var lines = File.ReadAllLines(metaFile); + if (lines.Length > 0 && lines[0].StartsWith("Kommentar: ")) + comment = lines[0]["Kommentar: ".Length..]; + } + + var fileName = Path.GetFileNameWithoutExtension(latest); + var stamp = fileName[(name.Length + 1)..]; + var parsed = DateTime.TryParseExact(stamp, "yyyyMMdd_HHmmss", null, + System.Globalization.DateTimeStyles.None, out var dt); + latestVersion = new VersionEntry( + latest, + parsed ? dt : File.GetLastWriteTime(latest), + comment + ); + } + + private async Task LoadLatestVersion() + { + if (latestVersion == null) return; + try + { + editorContent = await File.ReadAllTextAsync(latestVersion.FilePath); + statusText = $"Version vom {latestVersion.Timestamp:dd.MM.yyyy HH:mm} geladen."; + } + catch (Exception ex) + { + statusText = $"Fehler: {ex.Message}"; + } } } diff --git a/Components/Pages/OllamaAssistant.razor b/Components/Pages/OllamaAssistant.razor new file mode 100644 index 0000000..9b92693 --- /dev/null +++ b/Components/Pages/OllamaAssistant.razor @@ -0,0 +1,105 @@ +@page "/assistant" +@inject IOllamaService OllamaService +@inject ISettingsService SettingsService +@inject NavigationManager Navigation + +@rendermode InteractiveServer + +Assistent - Author Buddy + +
+
+ + + @statusText + @if (isRunning) + { + + } +
+ +
+
+

Eingabetext

+ +
+
+

Ergebnis

+
+ @if (!string.IsNullOrEmpty(outputText)) + { +
@outputText
+ } + else if (!string.IsNullOrEmpty(errorMessage)) + { +
@errorMessage
+ } + else + { + Ergebnis erscheint hier nach der Ausführung. + } +
+
+
+
+ +@code { + private string selectedMode = "advocatus"; + private string inputText = string.Empty; + private string outputText = string.Empty; + private string errorMessage = string.Empty; + private string statusText = "Bereit"; + private bool isRunning; + private double progress; + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + } + + private async Task RunAssistant() + { + if (string.IsNullOrWhiteSpace(inputText)) return; + + isRunning = true; + progress = 50; + outputText = string.Empty; + errorMessage = string.Empty; + statusText = "Verarbeite..."; + + try + { + var systemPrompt = selectedMode switch + { + "advocatus" => await SettingsService.GetAdvocatusDiaboliPromptAsync() ?? string.Empty, + "hookfinder" => await SettingsService.GetHookFinderPromptAsync() ?? string.Empty, + "eli5" => await SettingsService.GetEli5PromptAsync() ?? string.Empty, + _ => string.Empty + }; + + if (string.IsNullOrEmpty(systemPrompt)) + { + errorMessage = "Kein System-Prompt für diesen Modus konfiguriert. Bitte in den Einstellungen hinterlegen."; + return; + } + + var model = await SettingsService.GetStyleModelAsync() ?? "llama3.2"; + outputText = await OllamaService.Chat(model, inputText, systemPrompt); + statusText = "Fertig."; + } + catch (Exception ex) + { + errorMessage = $"Fehler: {ex.Message}"; + statusText = "Fehler"; + } + finally + { + isRunning = false; + progress = 0; + } + } +} diff --git a/Components/Pages/Settings.razor b/Components/Pages/Settings.razor index f289df2..c95a6ac 100644 --- a/Components/Pages/Settings.razor +++ b/Components/Pages/Settings.razor @@ -32,7 +32,7 @@
-
+

Modelle

@@ -81,7 +81,7 @@
-
Adresse des Ollama-Servers (z. B. http://192.168.1.100:11434)
+
Adresse des Ollama-Servers
@@ -98,7 +98,7 @@
-
+

Lektor-System-Prompt

@@ -121,6 +121,29 @@
+
+
+

Advocatus Diaboli

+
+ +
+
+ +
+

Hook-Finder

+
+ +
+
+ +
+

ELI5-Vereinfachung

+
+ +
+
+
+
@@ -142,6 +165,9 @@ private string lektorPrompt = string.Empty; private string factCheckTemplate = string.Empty; private string spellingPrompt = string.Empty; + private string advocatusDiaboliPrompt = string.Empty; + private string hookFinderPrompt = string.Empty; + private string eli5Prompt = string.Empty; private string newProjectName = string.Empty; private string newUserName = string.Empty; private string statusMessage = string.Empty; @@ -155,16 +181,7 @@ var current = await SettingsService.GetCurrentUserAsync(); selectedUserId = current.Id; - var userSettings = await LoadUserSettingsAsync(); - - ragModel = userSettings.ragModel; - styleModel = userSettings.styleModel; - spellingModel = userSettings.spellingModel; - selectedTheme = userSettings.selectedTheme; - ollamaUrl = userSettings.ollamaUrl; - lektorPrompt = userSettings.lektorPrompt; - factCheckTemplate = userSettings.factCheckTemplate; - spellingPrompt = userSettings.spellingPrompt; + await LoadUserSettings(); try { @@ -177,18 +194,19 @@ } } - private async Task<(string ragModel, string styleModel, string spellingModel, string selectedTheme, string ollamaUrl, string lektorPrompt, string factCheckTemplate, string spellingPrompt)> LoadUserSettingsAsync() + private async Task LoadUserSettings() { - return ( - await SettingsService.GetRagModelAsync() ?? "llama3.2", - await SettingsService.GetStyleModelAsync() ?? "llama3.2", - await SettingsService.GetSpellingModelAsync() ?? "phi3:mini", - await SettingsService.GetThemeAsync() ?? "light", - await SettingsService.GetOllamaUrlAsync() ?? "http://localhost:11434", - await SettingsService.GetLektorSystemPromptAsync() ?? string.Empty, - await SettingsService.GetFactCheckTemplateAsync() ?? string.Empty, - await SettingsService.GetSpellingPromptAsync() ?? string.Empty - ); + ragModel = await SettingsService.GetRagModelAsync() ?? "llama3.2"; + styleModel = await SettingsService.GetStyleModelAsync() ?? "llama3.2"; + spellingModel = await SettingsService.GetSpellingModelAsync() ?? "phi3:mini"; + selectedTheme = await SettingsService.GetThemeAsync() ?? "light"; + ollamaUrl = await SettingsService.GetOllamaUrlAsync() ?? "http://localhost:11434"; + lektorPrompt = await SettingsService.GetLektorSystemPromptAsync() ?? string.Empty; + factCheckTemplate = await SettingsService.GetFactCheckTemplateAsync() ?? string.Empty; + spellingPrompt = await SettingsService.GetSpellingPromptAsync() ?? string.Empty; + advocatusDiaboliPrompt = await SettingsService.GetAdvocatusDiaboliPromptAsync() ?? string.Empty; + hookFinderPrompt = await SettingsService.GetHookFinderPromptAsync() ?? string.Empty; + eli5Prompt = await SettingsService.GetEli5PromptAsync() ?? string.Empty; } private async Task SwitchUser(ChangeEventArgs e) @@ -197,15 +215,7 @@ await SettingsService.SetCurrentUserAsync(userId); selectedUserId = userId; - var userSettings = await LoadUserSettingsAsync(); - ragModel = userSettings.ragModel; - styleModel = userSettings.styleModel; - spellingModel = userSettings.spellingModel; - selectedTheme = userSettings.selectedTheme; - ollamaUrl = userSettings.ollamaUrl; - lektorPrompt = userSettings.lektorPrompt; - factCheckTemplate = userSettings.factCheckTemplate; - spellingPrompt = userSettings.spellingPrompt; + await LoadUserSettings(); } private async Task AddUser() @@ -221,6 +231,17 @@ private async Task SaveSettings() { await SettingsService.SaveOllamaUrlAsync(ollamaUrl); + OllamaService.Reconfigure(ollamaUrl); + + if (!string.IsNullOrWhiteSpace(ragModel)) + { + var ok = await OllamaService.TestEmbeddingAsync(ragModel); + if (!ok) + { + statusMessage = $"Modell '{ragModel}' unterstützt keine Embeddings. RAG-Modell nicht gespeichert."; + return; + } + } await SettingsService.SaveRagModelAsync(ragModel); await SettingsService.SaveStyleModelAsync(styleModel); await SettingsService.SaveSpellingModelAsync(spellingModel); @@ -228,7 +249,9 @@ await SettingsService.SaveLektorSystemPromptAsync(lektorPrompt); await SettingsService.SaveFactCheckTemplateAsync(factCheckTemplate); await SettingsService.SaveSpellingPromptAsync(spellingPrompt); - OllamaService.Reconfigure(ollamaUrl); + await SettingsService.SaveAdvocatusDiaboliPromptAsync(advocatusDiaboliPrompt); + await SettingsService.SaveHookFinderPromptAsync(hookFinderPrompt); + await SettingsService.SaveEli5PromptAsync(eli5Prompt); statusMessage = "Einstellungen gespeichert."; await ThemeService.ApplyTheme(selectedTheme); diff --git a/Components/_Imports.razor b/Components/_Imports.razor index 37a6891..16d44bb 100644 --- a/Components/_Imports.razor +++ b/Components/_Imports.razor @@ -12,4 +12,3 @@ @using AuthorBuddy.Web.Models @using AuthorBuddy.Web.Services @using AuthorBuddy.Web.Data -@using Microsoft.EntityFrameworkCore diff --git a/Data/AppDbContext.cs b/Data/AppDbContext.cs deleted file mode 100644 index 1338d93..0000000 --- a/Data/AppDbContext.cs +++ /dev/null @@ -1,81 +0,0 @@ -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; - -namespace AuthorBuddy.Web.Data; - -public class AppDbContext : DbContext -{ - public DbSet Projects => Set(); - public DbSet Settings => Set(); - public DbSet DocumentMeta => Set(); - public DbSet Users => Set(); - - public AppDbContext(DbContextOptions options) : base(options) { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity(entity => - { - entity.ToTable("Projects"); - entity.HasKey(e => e.Id); - entity.Property(e => e.Name).IsRequired(); - entity.Property(e => e.RootPath).IsRequired(); - entity.Property(e => e.LastOpened); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("Settings"); - entity.HasKey(e => e.Id); - entity.Property(e => e.Key).HasColumnName("key").IsRequired(); - entity.Property(e => e.Value).HasColumnName("value").IsRequired(); - entity.Property(e => e.UserId).HasColumnName("user_id"); - entity.Property(e => e.ProjectId).HasColumnName("project_id"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("Users"); - entity.HasKey(e => e.Id); - entity.Property(e => e.Name).HasColumnName("name").IsRequired(); - entity.Property(e => e.IsCurrent).HasColumnName("is_current"); - }); - - modelBuilder.Entity(entity => - { - entity.ToTable("DocumentMeta"); - entity.HasKey(e => e.Id); - entity.Property(e => e.FilePath).HasColumnName("file_path").IsRequired(); - entity.Property(e => e.LastModified).HasColumnName("last_modified"); - entity.Property(e => e.FileType).HasColumnName("file_type"); - entity.Property(e => e.ProjectId).HasColumnName("project_id"); - }); - } - - public static void SetupVecExtension(string connectionString) - { - using var connection = new SqliteConnection(connectionString); - connection.Open(); - connection.EnableExtensions(true); - - try - { - connection.LoadExtension("vec0"); - using var testCmd = connection.CreateCommand(); - testCmd.CommandText = "SELECT vec_version();"; - var version = testCmd.ExecuteScalar(); - Console.WriteLine($"sqlite-vec Version: {version}"); - } - catch (SqliteException ex) - { - Console.WriteLine($"Fehler beim Laden von vec0: {ex.Message}"); - } - - using var createVecCmd = connection.CreateCommand(); - createVecCmd.CommandText = @" - CREATE VIRTUAL TABLE IF NOT EXISTS vec_documents USING vec0( - embedding float[1024] - );"; - createVecCmd.ExecuteNonQuery(); - } -} diff --git a/Data/DocumentMetaEntity.cs b/Data/DocumentMetaEntity.cs index 7a86abe..ea60b33 100644 --- a/Data/DocumentMetaEntity.cs +++ b/Data/DocumentMetaEntity.cs @@ -1,23 +1,11 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - namespace AuthorBuddy.Web.Data; -[Table("DocumentMeta")] public class DocumentMetaEntity { - [Key] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } - public int? ProjectId { get; set; } - - [Required] public string FilePath { get; set; } = string.Empty; - public DateTime? LastModified { get; set; } - public string? Hash { get; set; } - public string? FileType { get; set; } } diff --git a/Data/DocumentVector.cs b/Data/DocumentVector.cs new file mode 100644 index 0000000..9c87b4b --- /dev/null +++ b/Data/DocumentVector.cs @@ -0,0 +1,11 @@ +namespace AuthorBuddy.Web.Data; + +public class DocumentVector +{ + public int Id { get; set; } + public int DocumentMetaId { get; set; } + public int ProjectId { get; set; } + public string Text { get; set; } = string.Empty; + public string Hash { get; set; } = string.Empty; + public float[] Embedding { get; set; } = Array.Empty(); +} diff --git a/Data/ProjectEntity.cs b/Data/ProjectEntity.cs index 6fe345f..1f7b03c 100644 --- a/Data/ProjectEntity.cs +++ b/Data/ProjectEntity.cs @@ -1,20 +1,9 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - namespace AuthorBuddy.Web.Data; -[Table("Projects")] public class ProjectEntity { - [Key] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } - - [Required] public string Name { get; set; } = string.Empty; - - [Required] public string RootPath { get; set; } = string.Empty; - public DateTime? LastOpened { get; set; } } diff --git a/Data/SettingEntity.cs b/Data/SettingEntity.cs index fa31c04..ccaf505 100644 --- a/Data/SettingEntity.cs +++ b/Data/SettingEntity.cs @@ -1,22 +1,12 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; +using LiteDB; namespace AuthorBuddy.Web.Data; -[Table("Settings")] public class SettingEntity { - [Key] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } - - [Required] public string Key { get; set; } = string.Empty; - - [Required] public string Value { get; set; } = string.Empty; - public int? UserId { get; set; } - public int? ProjectId { get; set; } } diff --git a/Data/UserEntity.cs b/Data/UserEntity.cs index 5070a76..7ecf395 100644 --- a/Data/UserEntity.cs +++ b/Data/UserEntity.cs @@ -1,17 +1,8 @@ -using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; - namespace AuthorBuddy.Web.Data; -[Table("Users")] public class UserEntity { - [Key] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } - - [Required] public string Name { get; set; } = string.Empty; - public bool IsCurrent { get; set; } } diff --git a/Migrations/20260516151053_InitialCreate.Designer.cs b/Migrations/20260516151053_InitialCreate.Designer.cs deleted file mode 100644 index 8473c70..0000000 --- a/Migrations/20260516151053_InitialCreate.Designer.cs +++ /dev/null @@ -1,127 +0,0 @@ -// -using System; -using AuthorBuddy.Web.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace AuthorBuddy.Web.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20260516151053_InitialCreate")] - partial class InitialCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "10.0.8"); - - modelBuilder.Entity("AuthorBuddy.Web.Data.DocumentMetaEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("FilePath") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("file_path"); - - b.Property("FileType") - .HasColumnType("TEXT") - .HasColumnName("file_type"); - - b.Property("Hash") - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT") - .HasColumnName("last_modified"); - - b.Property("ProjectId") - .HasColumnType("INTEGER") - .HasColumnName("project_id"); - - b.HasKey("Id"); - - b.ToTable("DocumentMeta", (string)null); - }); - - modelBuilder.Entity("AuthorBuddy.Web.Data.ProjectEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastOpened") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("RootPath") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Projects", (string)null); - }); - - modelBuilder.Entity("AuthorBuddy.Web.Data.SettingEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("key"); - - b.Property("ProjectId") - .HasColumnType("INTEGER") - .HasColumnName("project_id"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("user_id"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("value"); - - b.HasKey("Id"); - - b.ToTable("Settings", (string)null); - }); - - modelBuilder.Entity("AuthorBuddy.Web.Data.UserEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("IsCurrent") - .HasColumnType("INTEGER") - .HasColumnName("is_current"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("name"); - - b.HasKey("Id"); - - b.ToTable("Users", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Migrations/20260516151053_InitialCreate.cs b/Migrations/20260516151053_InitialCreate.cs deleted file mode 100644 index 2a9f35c..0000000 --- a/Migrations/20260516151053_InitialCreate.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace AuthorBuddy.Web.Migrations -{ - /// - public partial class InitialCreate : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "DocumentMeta", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - project_id = table.Column(type: "INTEGER", nullable: true), - file_path = table.Column(type: "TEXT", nullable: false), - last_modified = table.Column(type: "TEXT", nullable: true), - Hash = table.Column(type: "TEXT", nullable: true), - file_type = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_DocumentMeta", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Projects", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Name = table.Column(type: "TEXT", nullable: false), - RootPath = table.Column(type: "TEXT", nullable: false), - LastOpened = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Projects", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Settings", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - key = table.Column(type: "TEXT", nullable: false), - value = table.Column(type: "TEXT", nullable: false), - user_id = table.Column(type: "INTEGER", nullable: true), - project_id = table.Column(type: "INTEGER", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Settings", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Users", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - name = table.Column(type: "TEXT", nullable: false), - is_current = table.Column(type: "INTEGER", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Users", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "DocumentMeta"); - - migrationBuilder.DropTable( - name: "Projects"); - - migrationBuilder.DropTable( - name: "Settings"); - - migrationBuilder.DropTable( - name: "Users"); - } - } -} diff --git a/Migrations/AppDbContextModelSnapshot.cs b/Migrations/AppDbContextModelSnapshot.cs deleted file mode 100644 index 089a0a3..0000000 --- a/Migrations/AppDbContextModelSnapshot.cs +++ /dev/null @@ -1,124 +0,0 @@ -// -using System; -using AuthorBuddy.Web.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace AuthorBuddy.Web.Migrations -{ - [DbContext(typeof(AppDbContext))] - partial class AppDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "10.0.8"); - - modelBuilder.Entity("AuthorBuddy.Web.Data.DocumentMetaEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("FilePath") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("file_path"); - - b.Property("FileType") - .HasColumnType("TEXT") - .HasColumnName("file_type"); - - b.Property("Hash") - .HasColumnType("TEXT"); - - b.Property("LastModified") - .HasColumnType("TEXT") - .HasColumnName("last_modified"); - - b.Property("ProjectId") - .HasColumnType("INTEGER") - .HasColumnName("project_id"); - - b.HasKey("Id"); - - b.ToTable("DocumentMeta", (string)null); - }); - - modelBuilder.Entity("AuthorBuddy.Web.Data.ProjectEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastOpened") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("RootPath") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Projects", (string)null); - }); - - modelBuilder.Entity("AuthorBuddy.Web.Data.SettingEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("key"); - - b.Property("ProjectId") - .HasColumnType("INTEGER") - .HasColumnName("project_id"); - - b.Property("UserId") - .HasColumnType("INTEGER") - .HasColumnName("user_id"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("value"); - - b.HasKey("Id"); - - b.ToTable("Settings", (string)null); - }); - - modelBuilder.Entity("AuthorBuddy.Web.Data.UserEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("IsCurrent") - .HasColumnType("INTEGER") - .HasColumnName("is_current"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasColumnName("name"); - - b.HasKey("Id"); - - b.ToTable("Users", (string)null); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Models/Constants.cs b/Models/Constants.cs index e48f311..f8a9a23 100644 --- a/Models/Constants.cs +++ b/Models/Constants.cs @@ -10,5 +10,5 @@ public static class Constants "Exports" }; - public const string SQLiteConnection = "Data Source=author_brain.db"; + public const string DbFile = "author_brain.db"; } diff --git a/Models/FileTreeItem.cs b/Models/FileTreeItem.cs new file mode 100644 index 0000000..e81651b --- /dev/null +++ b/Models/FileTreeItem.cs @@ -0,0 +1,9 @@ +namespace AuthorBuddy.Web.Models; + +public class FileTreeItem +{ + public string Name { get; set; } = string.Empty; + public string FullPath { get; set; } = string.Empty; + public bool IsDirectory { get; set; } + public List Children { get; set; } = new(); +} diff --git a/Models/OllamaSettings.cs b/Models/OllamaSettings.cs index c88e17b..8f66ebe 100644 --- a/Models/OllamaSettings.cs +++ b/Models/OllamaSettings.cs @@ -2,8 +2,8 @@ namespace AuthorBuddy.Web.Models; public class OllamaSettings { - public string StyleModel { get; set; } = "llama3.2"; - public string EmbedModel { get; set; } = "mxbai-embed-large"; + public string StyleModel { get; set; } = "gemma4:e4b"; + public string EmbedModel { get; set; } = "nomic-embed-text"; public string SpellingModel { get; set; } = "phi3:mini"; public string OllamaUrl { get; set; } = "http://localhost:11434"; public string Theme { get; set; } = "light"; @@ -20,6 +20,12 @@ public class OllamaSettings public string SpellingPrompt { get; set; } = "Du bist ein Rechtschreibprüfer. Korrigiere NUR Fehler (Rechtschreibung/Grammatik). " + "Ändere den Stil nicht. Gib nur den korrigierten Text zurück."; + public string AdvocatusDiaboliPrompt { get; set; } = "Nimm eine radikale Gegenposition zu meinem Text ein. Welche Schwachstellen in meiner Argumentation fallen dir auf?"; + + public string HookFinderPrompt { get; set; } = "Generiere mir 5 emotionale, packende Einstiegssätze (Hooks) für diesen Text, die den Leser sofort fesseln."; + + public string Eli5Prompt { get; set; } = "Wo ist der Text zu kompliziert geschrieben? Liefere mir konkrete Vorschläge, wie ich komplexe Absätze einfacher formulieren kann, ohne den Kern zu verlieren."; + public string GetFactCheckPrompt(string question, string facts) { return string.Format(FactCheckTemplate, question, facts); diff --git a/Models/WikipediaResult.cs b/Models/WikipediaResult.cs new file mode 100644 index 0000000..6a8a3d9 --- /dev/null +++ b/Models/WikipediaResult.cs @@ -0,0 +1,18 @@ +namespace AuthorBuddy.Web.Models; + +public class WikipediaResult +{ + public string Title { get; set; } = string.Empty; + public string Snippet { get; set; } = string.Empty; + public string Url { get; set; } = string.Empty; + public string Language { get; set; } = "de"; + public string? Extract { get; set; } +} + +public class WikipediaSearchRequest +{ + public string Query { get; set; } = string.Empty; + public bool SearchGerman { get; set; } = true; + public bool SearchEnglish { get; set; } = true; + public int MaxResults { get; set; } = 3; +} diff --git a/Program.cs b/Program.cs index 1e900a9..4291a7a 100644 --- a/Program.cs +++ b/Program.cs @@ -2,32 +2,29 @@ using AuthorBuddy.Web.Components; using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; using AuthorBuddy.Web.Services; -using Microsoft.EntityFrameworkCore; +using LiteDB; var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); +var dbPath = Path.Combine(AppContext.BaseDirectory, Constants.DbFile); +builder.Services.AddSingleton(new LiteDatabase($"Filename={dbPath};Connection=direct")); + builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddSingleton(); - -builder.Services.AddDbContextFactory(options => - options.UseSqlite(Constants.SQLiteConnection)); +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); var app = builder.Build(); -AppDbContext.SetupVecExtension(Constants.SQLiteConnection); - -await using var db = await app.Services.GetRequiredService>().CreateDbContextAsync(); -await db.Database.MigrateAsync(); - var settingsInit = app.Services.GetRequiredService(); -await settingsInit.InitializeAsync(); +settingsInit.InitializeAsync().GetAwaiter().GetResult(); if (!app.Environment.IsDevelopment()) { diff --git a/Services/FileScannerService.cs b/Services/FileScannerService.cs index 42d2d5e..2948ba4 100644 --- a/Services/FileScannerService.cs +++ b/Services/FileScannerService.cs @@ -1,20 +1,17 @@ using AuthorBuddy.Web.Data; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; +using LiteDB; namespace AuthorBuddy.Web.Services; public class FileScannerService : IFileScannerService { private readonly IOllamaService _ollama; - private readonly IDbContextFactory _contextFactory; - private readonly string _connectionString; + private readonly ILiteDatabase _db; - public FileScannerService(IOllamaService ollama, IDbContextFactory contextFactory) + public FileScannerService(IOllamaService ollama, ILiteDatabase db) { _ollama = ollama; - _contextFactory = contextFactory; - _connectionString = Models.Constants.SQLiteConnection; + _db = db; } public async Task ScanProjectFolderAsync(int projectId, string rootPath, IProgress progress) @@ -25,77 +22,55 @@ public class FileScannerService : IFileScannerService foreach (var file in files) { var fileInfo = new FileInfo(file); - bool needsUpdate = await CheckIfUpdateRequired(projectId, file, fileInfo.LastWriteTimeUtc); + bool needsUpdate = CheckIfUpdateRequired(projectId, file, fileInfo.LastWriteTimeUtc); if (needsUpdate) { progress?.Report($"Verarbeite: {fileInfo.Name}..."); - await ProcessAndVectorizeFile(projectId, file, fileInfo.LastWriteTimeUtc); + await ProcessFile(projectId, file, fileInfo.LastWriteTimeUtc); } } progress?.Report("Scan abgeschlossen."); } - private async Task CheckIfUpdateRequired(int projectId, string file, DateTime lastWriteTimeUtc) + private bool CheckIfUpdateRequired(int projectId, string file, DateTime lastWriteTimeUtc) { - await using var context = await _contextFactory.CreateDbContextAsync(); - - var meta = await context.DocumentMeta - .Where(m => m.ProjectId == projectId && m.FilePath == file) - .Select(m => m.LastModified) - .FirstOrDefaultAsync(); - + var col = _db.GetCollection("documentMeta"); + var meta = col.FindOne(m => m.ProjectId == projectId && m.FilePath == file); if (meta == null) return true; - return meta.Value < lastWriteTimeUtc; + return meta.LastModified < lastWriteTimeUtc; } - private async Task ProcessAndVectorizeFile(int projectId, string path, DateTime lastModified) + private async Task ProcessFile(int projectId, string path, DateTime lastModified) { string content = await File.ReadAllTextAsync(path); - //var vector = await _ollama.GetEmbeddingAsync(content); - - using var connection = new SqliteConnection(_connectionString); - connection.Open(); - using var transaction = connection.BeginTransaction(); - try { - var cmdMeta = connection.CreateCommand(); - cmdMeta.CommandText = @" - INSERT INTO DocumentMeta (project_id, file_path, last_modified) - VALUES (@pid, @path, @mod) - ON CONFLICT(file_path) DO UPDATE SET last_modified = @mod - RETURNING id;"; - cmdMeta.Parameters.AddWithValue("@pid", projectId); - cmdMeta.Parameters.AddWithValue("@path", path); - cmdMeta.Parameters.AddWithValue("@mod", lastModified); + var col = _db.GetCollection("documentMeta"); + var existing = col.FindOne(m => m.ProjectId == projectId && m.FilePath == path); - var docId = await cmdMeta.ExecuteScalarAsync(); + if (existing != null) + { + existing.LastModified = lastModified; + col.Update(existing); + } + else + { + col.Insert(new DocumentMetaEntity + { + ProjectId = projectId, + FilePath = path, + LastModified = lastModified, + FileType = ".md" + }); + } - byte[] blob = [];// ConvertVectorToBytes(vector); - var cmdVec = connection.CreateCommand(); - cmdVec.CommandText = "INSERT INTO vec_documents(rowid, embedding) VALUES (@id, @vec) " + - "ON CONFLICT(rowid) DO UPDATE SET embedding = @vec;"; - cmdVec.Parameters.AddWithValue("@id", docId); - cmdVec.Parameters.AddWithValue("@vec", blob); - await cmdVec.ExecuteNonQueryAsync(); - - transaction.Commit(); return true; } catch { - transaction.Rollback(); return false; } } - - private static byte[] ConvertVectorToBytes(IList vector) - { - float[] floatVector = vector.Select(d => (float)d).ToArray(); - byte[] bytes = new byte[floatVector.Length * sizeof(float)]; - Buffer.BlockCopy(floatVector, 0, bytes, 0, bytes.Length); - return bytes; - } } diff --git a/Services/IOllamaService.cs b/Services/IOllamaService.cs index 954cac7..4afa12d 100644 --- a/Services/IOllamaService.cs +++ b/Services/IOllamaService.cs @@ -9,5 +9,8 @@ public interface IOllamaService Task> GetLocalModelsAsync(); Task PullModelAsync(string modelName, IProgress progress); Task QuickSpellCheckAsync(string text); + Task GetEmbeddingAsync(string text); + Task TestEmbeddingAsync(string model); + Task Chat(string model, string userMessage, string? systemPrompt = null); void Reconfigure(string ollamaUrl); } diff --git a/Services/IProjectService.cs b/Services/IProjectService.cs index f7742be..6896e6d 100644 --- a/Services/IProjectService.cs +++ b/Services/IProjectService.cs @@ -6,5 +6,7 @@ public interface IProjectService { Task CreateNewProjectAsync(string projectName, string rootPath); Task> GetAllProjectsAsync(); + Task GetProjectAsync(int projectId); + Task> GetProjectFileTreeAsync(int projectId); Task SyncProjectFilesAsync(int projectId, string directoryPath, IProgress progress); } diff --git a/Services/IRagService.cs b/Services/IRagService.cs new file mode 100644 index 0000000..a5b7ae0 --- /dev/null +++ b/Services/IRagService.cs @@ -0,0 +1,14 @@ +namespace AuthorBuddy.Web.Services; + +public class RagSearchResult +{ + public string Text { get; set; } = string.Empty; + public string FilePath { get; set; } = string.Empty; + public double Similarity { get; set; } +} + +public interface IRagService +{ + Task IndexProjectAsync(int projectId, string rootPath, IProgress progress); + Task> SearchAsync(int projectId, string query, int topN = 5); +} diff --git a/Services/ISettingsService.cs b/Services/ISettingsService.cs index 761bbed..7feea40 100644 --- a/Services/ISettingsService.cs +++ b/Services/ISettingsService.cs @@ -18,10 +18,16 @@ public interface ISettingsService Task GetLektorSystemPromptAsync(); Task GetFactCheckTemplateAsync(); Task GetSpellingPromptAsync(); + Task GetAdvocatusDiaboliPromptAsync(); + Task GetHookFinderPromptAsync(); + Task GetEli5PromptAsync(); Task SaveLektorSystemPromptAsync(string prompt); Task SaveFactCheckTemplateAsync(string prompt); Task SaveSpellingPromptAsync(string prompt); + Task SaveAdvocatusDiaboliPromptAsync(string prompt); + Task SaveHookFinderPromptAsync(string prompt); + Task SaveEli5PromptAsync(string prompt); Task> GetUsersAsync(); Task GetCurrentUserAsync(); @@ -29,6 +35,10 @@ public interface ISettingsService Task CreateUserAsync(string name); int? CurrentProjectId { get; set; } + string? CurrentFilePath { get; set; } + Task GetLastProjectIdAsync(); + Task SaveLastProjectIdAsync(int projectId); + Task LoadProjectSettingsAsync(); - Task InitializeAsync(); + Task InitializeAsync(int projectId = -1); } diff --git a/Services/IWikipediaService.cs b/Services/IWikipediaService.cs new file mode 100644 index 0000000..d1b3134 --- /dev/null +++ b/Services/IWikipediaService.cs @@ -0,0 +1,11 @@ +using AuthorBuddy.Web.Models; + +namespace AuthorBuddy.Web.Services; + +public interface IWikipediaService +{ + Task> SearchAsync(string query, int maxResults = 3); + Task> SearchAsync(WikipediaSearchRequest request); + Task GetExtractAsync(string title, string language = "de"); + Task GetFullArticleAsync(string title, string language = "de"); +} diff --git a/Services/OllamaService.cs b/Services/OllamaService.cs index b083082..470dfff 100644 --- a/Services/OllamaService.cs +++ b/Services/OllamaService.cs @@ -22,6 +22,53 @@ public class OllamaService : IOllamaService _baseUrl = url; } + public async Task TestEmbeddingAsync(string model) + { + try + { + var request = new { model = model, prompt = "test" }; + var response = await _httpClient.PostAsJsonAsync($"{_baseUrl}/api/embeddings", request); + if (!response.IsSuccessStatusCode) return false; + + var content = await response.Content.ReadAsStringAsync(); + using var doc = JsonDocument.Parse(content); + if (doc.RootElement.TryGetProperty("embedding", out var embedding)) + return embedding.EnumerateArray().Any(); + + return false; + } + catch + { + return false; + } + } + + public async Task GetEmbeddingAsync(string text) + { + try + { + var request = new { model = _settings.EmbedModel, prompt = text }; + var response = await _httpClient.PostAsJsonAsync($"{_baseUrl}/api/embeddings", request); + if (response.IsSuccessStatusCode) + { + var content = await response.Content.ReadAsStringAsync(); + using var doc = JsonDocument.Parse(content); + if (doc.RootElement.TryGetProperty("embedding", out var embedding)) + { + var list = new List(); + foreach (var val in embedding.EnumerateArray()) + list.Add(val.GetSingle()); + return list.ToArray(); + } + } + return Array.Empty(); + } + catch + { + return Array.Empty(); + } + } + public async Task> GetLocalModelsAsync() { try diff --git a/Services/ProjectService.cs b/Services/ProjectService.cs index 4aedc48..e4369b0 100644 --- a/Services/ProjectService.cs +++ b/Services/ProjectService.cs @@ -1,21 +1,21 @@ using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; -using Microsoft.EntityFrameworkCore; +using LiteDB; namespace AuthorBuddy.Web.Services; public class ProjectService : IProjectService { - private readonly IDbContextFactory _contextFactory; + private readonly ILiteDatabase _db; private readonly IFileScannerService _fileScannerService; - public ProjectService(IDbContextFactory contextFactory, IFileScannerService fileScannerService) + public ProjectService(ILiteDatabase db, IFileScannerService fileScannerService) { - _contextFactory = contextFactory; + _db = db; _fileScannerService = fileScannerService; } - public async Task CreateNewProjectAsync(string projectName, string rootPath) + public Task CreateNewProjectAsync(string projectName, string rootPath) { string[] subFolders = { "00_Drafts", "01_Fakten", "02_Characters", "03_Archive" }; foreach (var subFolder in subFolders) @@ -24,10 +24,9 @@ public class ProjectService : IProjectService } string readmePath = Path.Combine(rootPath, "00_Projekt_Info.md"); - await File.WriteAllTextAsync(readmePath, $"# Projekt: {projectName}\nErstellt am: {DateTime.Now}"); - - await using var context = await _contextFactory.CreateDbContextAsync(); + File.WriteAllText(readmePath, $"# Projekt: {projectName}\nErstellt am: {DateTime.Now}"); + var col = _db.GetCollection("projects"); var entity = new ProjectEntity { Name = projectName, @@ -35,17 +34,14 @@ public class ProjectService : IProjectService LastOpened = DateTime.Now }; - context.Projects.Add(entity); - await context.SaveChangesAsync(); - - return entity.Id; + col.Insert(entity); + return Task.FromResult(entity.Id); } - public async Task> GetAllProjectsAsync() + public Task> GetAllProjectsAsync() { - await using var context = await _contextFactory.CreateDbContextAsync(); - - return await context.Projects + var col = _db.GetCollection("projects"); + var list = col.FindAll() .OrderByDescending(p => p.LastOpened) .Select(p => new Project { @@ -53,7 +49,64 @@ public class ProjectService : IProjectService Name = p.Name, RootPath = p.RootPath }) - .ToListAsync(); + .ToList(); + return Task.FromResult(list); + } + + public Task GetProjectAsync(int projectId) + { + var col = _db.GetCollection("projects"); + var entity = col.FindById(projectId); + if (entity == null) return Task.FromResult(null); + return Task.FromResult(new Project + { + Id = entity.Id, + Name = entity.Name, + RootPath = entity.RootPath + }); + } + + public Task> GetProjectFileTreeAsync(int projectId) + { + var col = _db.GetCollection("projects"); + var entity = col.FindById(projectId); + if (entity == null || !Directory.Exists(entity.RootPath)) + return Task.FromResult(new List()); + + var result = new List(); + BuildTree(entity.RootPath, result, 0); + return Task.FromResult(result); + } + + private static void BuildTree(string directory, List items, int depth) + { + if (depth > 4) return; + + var dirInfo = new DirectoryInfo(directory); + if (!dirInfo.Exists) return; + + foreach (var dir in dirInfo.GetDirectories().OrderBy(d => d.Name)) + { + var node = new FileTreeItem + { + Name = dir.Name, + FullPath = dir.FullName, + IsDirectory = true + }; + BuildTree(dir.FullName, node.Children, depth + 1); + if (node.Children.Count > 0 || dir.Name.StartsWith("00_") || dir.Name.StartsWith("01_") || dir.Name.StartsWith("02_")) + items.Add(node); + } + + foreach (var file in dirInfo.GetFiles("*.md").OrderBy(f => f.Name)) + { + items.Add(new FileTreeItem + { + Name = file.Name, + FullPath = file.FullName, + IsDirectory = false + }); + } } public async Task SyncProjectFilesAsync(int projectId, string directoryPath, IProgress progress) diff --git a/Services/RagService.cs b/Services/RagService.cs new file mode 100644 index 0000000..e20faa7 --- /dev/null +++ b/Services/RagService.cs @@ -0,0 +1,145 @@ +using AuthorBuddy.Web.Data; +using LiteDB; +using System.Security.Cryptography; +using System.Text; + +namespace AuthorBuddy.Web.Services; + +public class RagService : IRagService +{ + private readonly ILiteDatabase _db; + private readonly IOllamaService _ollama; + + public RagService(ILiteDatabase db, IOllamaService ollama) + { + _db = db; + _ollama = ollama; + } + + public async Task IndexProjectAsync(int projectId, string rootPath, IProgress progress) + { + var files = Directory.GetFiles(rootPath, "*.md", SearchOption.AllDirectories) + .Where(f => f.Contains("00_Drafts") || f.Contains("01_Fakten")); + + var metaCol = _db.GetCollection("documentMeta"); + var vecCol = _db.GetCollection("vectors"); + + foreach (var file in files) + { + progress?.Report($"Indexiere: {Path.GetFileName(file)}..."); + + string content = await File.ReadAllTextAsync(file); + string hash = ComputeHash(content); + + var meta = metaCol.FindOne(m => m.ProjectId == projectId && m.FilePath == file); + + if (meta != null && meta.Hash == hash) + { + var existingVec = vecCol.FindOne(v => v.DocumentMetaId == meta.Id); + if (existingVec != null) + { + progress?.Report($" ↳ unverändert, übersprungen"); + continue; + } + } + + var embedding = await _ollama.GetEmbeddingAsync(content); + if (embedding.Length == 0) + { + progress?.Report($" ↳ Fehler beim Embedding, übersprungen"); + continue; + } + + if (meta == null) + { + meta = new DocumentMetaEntity + { + ProjectId = projectId, + FilePath = file, + LastModified = File.GetLastWriteTimeUtc(file), + Hash = hash, + FileType = ".md" + }; + metaCol.Insert(meta); + } + else + { + meta.LastModified = File.GetLastWriteTimeUtc(file); + meta.Hash = hash; + metaCol.Update(meta); + } + + var vec = vecCol.FindOne(v => v.DocumentMetaId == meta.Id); + if (vec != null) + { + vec.Text = content; + vec.Hash = hash; + vec.Embedding = embedding; + vecCol.Update(vec); + } + else + { + vecCol.Insert(new DocumentVector + { + DocumentMetaId = meta.Id, + ProjectId = projectId, + Text = content, + Hash = hash, + Embedding = embedding + }); + } + + progress?.Report($" ↳ ✓ {embedding.Length} Dimensionen"); + } + + progress?.Report("Indexierung abgeschlossen."); + } + + public async Task> SearchAsync(int projectId, string query, int topN = 5) + { + var queryVec = await _ollama.GetEmbeddingAsync(query); + if (queryVec.Length == 0) + return new List(); + + var vecCol = _db.GetCollection("vectors"); + var metaCol = _db.GetCollection("documentMeta"); + + var vectors = vecCol.Find(v => v.ProjectId == projectId).ToList(); + var results = new List(); + + foreach (var vec in vectors) + { + var sim = CosineSimilarity(queryVec, vec.Embedding); + if (sim > 0) + { + var meta = metaCol.FindById(vec.DocumentMetaId); + results.Add(new RagSearchResult + { + Text = vec.Text.Length > 500 ? vec.Text[..500] + "..." : vec.Text, + FilePath = meta?.FilePath ?? "", + Similarity = sim + }); + } + } + + return results.OrderByDescending(r => r.Similarity).Take(topN).ToList(); + } + + private static string ComputeHash(string content) + { + var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(content)); + return Convert.ToHexStringLower(bytes); + } + + private static double CosineSimilarity(float[] a, float[] b) + { + double dotProduct = 0.0, l2A = 0.0, l2B = 0.0; + for (int i = 0; i < a.Length; i++) + { + dotProduct += a[i] * b[i]; + l2A += Math.Pow(a[i], 2); + l2B += Math.Pow(b[i], 2); + } + return dotProduct / (Math.Sqrt(l2A) * Math.Sqrt(l2B)); + } +} diff --git a/Services/SettingsService.cs b/Services/SettingsService.cs index 8d37810..7df40ec 100644 --- a/Services/SettingsService.cs +++ b/Services/SettingsService.cs @@ -1,6 +1,6 @@ using AuthorBuddy.Web.Data; using AuthorBuddy.Web.Models; -using Microsoft.EntityFrameworkCore; +using LiteDB; namespace AuthorBuddy.Web.Services; @@ -14,15 +14,18 @@ public class SettingsService : ISettingsService private const string KeyLektorPrompt = "ollama_lektor_prompt"; private const string KeyFactCheckTemplate = "ollama_fact_check"; private const string KeySpellingPrompt = "ollama_spelling_prompt"; + private const string KeyAdvocatusDiaboli = "ollama_advocatus_diaboli"; + private const string KeyHookFinder = "ollama_hook_finder"; + private const string KeyEli5 = "ollama_eli5"; - private readonly IDbContextFactory _contextFactory; + private readonly ILiteDatabase _db; private readonly OllamaSettings _ollamaConfig; private int? _currentUserId; private int? _currentProjectId; - public SettingsService(IDbContextFactory contextFactory, OllamaSettings ollamaConfig) + public SettingsService(ILiteDatabase db, OllamaSettings ollamaConfig) { - _contextFactory = contextFactory; + _db = db; _ollamaConfig = ollamaConfig; } @@ -32,156 +35,250 @@ public class SettingsService : ISettingsService set => _currentProjectId = value; } - private async Task GetSettingAsync(string key, int? userId, int? projectId) - { - await using var context = await _contextFactory.CreateDbContextAsync(); + public string? CurrentFilePath { get; set; } - var matches = context.Settings.Where(s => + private const string KeyLastProjectId = "last_project_id"; + + public Task GetLastProjectIdAsync() + { + var col = _db.GetCollection("settings"); + var setting = col.FindOne(s => s.Key == KeyLastProjectId && s.UserId == _currentUserId && s.ProjectId == null); + if (setting != null && int.TryParse(setting.Value, out var id)) + return Task.FromResult(id); + return Task.FromResult(null); + } + + public Task SaveLastProjectIdAsync(int projectId) + { + var col = _db.GetCollection("settings"); + var existing = col.FindOne(s => s.Key == KeyLastProjectId && s.UserId == _currentUserId && s.ProjectId == null); + if (existing != null) + { + existing.Value = projectId.ToString(); + col.Update(existing); + } + else + { + col.Insert(new SettingEntity + { + Key = KeyLastProjectId, + Value = projectId.ToString(), + UserId = _currentUserId, + ProjectId = null + }); + } + return Task.CompletedTask; + } + + private string? GetSetting(string key, int? userId, int? projectId) + { + var col = _db.GetCollection("settings"); + + var matches = col.Find(s => s.Key == key && (s.UserId == userId || s.UserId == null) && (s.ProjectId == projectId || s.ProjectId == null)); - var setting = await matches + return matches .OrderByDescending(s => s.UserId != null) .ThenByDescending(s => s.ProjectId != null) - .FirstOrDefaultAsync(); - - return setting?.Value; + .FirstOrDefault()?.Value; } - private async Task GetAsync(string key) + private string? Get(string key) { - return await GetSettingAsync(key, _currentUserId, _currentProjectId); + return GetSetting(key, _currentUserId, null); } - private async Task SetAsync(string key, string value) + private void Set(string key, string value) { - await using var context = await _contextFactory.CreateDbContextAsync(); + var col = _db.GetCollection("settings"); - var existing = await context.Settings - .Where(s => s.Key == key && s.UserId == _currentUserId && s.ProjectId == _currentProjectId) - .FirstOrDefaultAsync(); + var existing = col.FindOne(s => + s.Key == key && s.UserId == _currentUserId && s.ProjectId == null); if (existing != null) { existing.Value = value; + col.Update(existing); } else { - context.Settings.Add(new SettingEntity + col.Insert(new SettingEntity { Key = key, Value = value, UserId = _currentUserId, - ProjectId = _currentProjectId + ProjectId = null }); } - - await context.SaveChangesAsync(); } - public Task GetOllamaUrlAsync() => GetAsync(KeyOllamaUrl); - public Task GetRagModelAsync() => GetAsync(KeyRagModel); - public Task GetStyleModelAsync() => GetAsync(KeyStyleModel); - public Task GetLektorSystemPromptAsync() => GetAsync(KeyLektorPrompt); - public Task GetFactCheckTemplateAsync() => GetAsync(KeyFactCheckTemplate); - public Task GetSpellingPromptAsync() => GetAsync(KeySpellingPrompt); - public Task GetSpellingModelAsync() => GetAsync(KeySpellingModel); - public Task GetThemeAsync() => GetAsync(KeyTheme); + public Task GetOllamaUrlAsync() => Task.FromResult(Get(KeyOllamaUrl)); + public Task GetRagModelAsync() => Task.FromResult(Get(KeyRagModel)); + public Task GetStyleModelAsync() => Task.FromResult(Get(KeyStyleModel)); + public Task GetLektorSystemPromptAsync() => Task.FromResult(Get(KeyLektorPrompt)); + public Task GetFactCheckTemplateAsync() => Task.FromResult(Get(KeyFactCheckTemplate)); + public Task GetSpellingPromptAsync() => Task.FromResult(Get(KeySpellingPrompt)); + public Task GetSpellingModelAsync() => Task.FromResult(Get(KeySpellingModel)); + public Task GetAdvocatusDiaboliPromptAsync() => Task.FromResult(Get(KeyAdvocatusDiaboli)); + public Task GetHookFinderPromptAsync() => Task.FromResult(Get(KeyHookFinder)); + public Task GetEli5PromptAsync() => Task.FromResult(Get(KeyEli5)); + public Task GetThemeAsync() => Task.FromResult(Get(KeyTheme)); - public async Task SaveOllamaUrlAsync(string url) + public Task SaveOllamaUrlAsync(string url) { - await SetAsync(KeyOllamaUrl, url); + Set(KeyOllamaUrl, url); _ollamaConfig.OllamaUrl = url; + return Task.CompletedTask; } - public async Task SaveRagModelAsync(string model) + public Task SaveRagModelAsync(string model) { - await SetAsync(KeyRagModel, model); + Set(KeyRagModel, model); + _ollamaConfig.EmbedModel = model; + return Task.CompletedTask; + } + + public Task SaveStyleModelAsync(string model) + { + Set(KeyStyleModel, model); _ollamaConfig.StyleModel = model; + return Task.CompletedTask; } - public async Task SaveStyleModelAsync(string model) + public Task SaveLektorSystemPromptAsync(string prompt) { - await SetAsync(KeyStyleModel, model); - _ollamaConfig.StyleModel = model; - } - - public async Task SaveLektorSystemPromptAsync(string prompt) - { - await SetAsync(KeyLektorPrompt, prompt); + Set(KeyLektorPrompt, prompt); _ollamaConfig.LektorSystemPrompt = prompt; + return Task.CompletedTask; } - public async Task SaveFactCheckTemplateAsync(string prompt) + public Task SaveFactCheckTemplateAsync(string prompt) { - await SetAsync(KeyFactCheckTemplate, prompt); + Set(KeyFactCheckTemplate, prompt); _ollamaConfig.FactCheckTemplate = prompt; + return Task.CompletedTask; } - public async Task SaveSpellingPromptAsync(string prompt) + public Task SaveSpellingPromptAsync(string prompt) { - await SetAsync(KeySpellingPrompt, prompt); + Set(KeySpellingPrompt, prompt); _ollamaConfig.SpellingPrompt = prompt; + return Task.CompletedTask; } - public async Task SaveSpellingModelAsync(string model) + public Task SaveSpellingModelAsync(string model) { - await SetAsync(KeySpellingModel, model); + Set(KeySpellingModel, model); _ollamaConfig.SpellingModel = model; + return Task.CompletedTask; + } + + public Task SaveAdvocatusDiaboliPromptAsync(string prompt) + { + Set(KeyAdvocatusDiaboli, prompt); + _ollamaConfig.AdvocatusDiaboliPrompt = prompt; + return Task.CompletedTask; + } + + public Task SaveHookFinderPromptAsync(string prompt) + { + Set(KeyHookFinder, prompt); + _ollamaConfig.HookFinderPrompt = prompt; + return Task.CompletedTask; + } + + public Task SaveEli5PromptAsync(string prompt) + { + Set(KeyEli5, prompt); + _ollamaConfig.Eli5Prompt = prompt; + return Task.CompletedTask; } public Task SaveThemeAsync(string theme) - => SetAsync(KeyTheme, theme); - - public async Task> GetUsersAsync() { - await using var context = await _contextFactory.CreateDbContextAsync(); - return await context.Users.ToListAsync(); + Set(KeyTheme, theme); + return Task.CompletedTask; } - public async Task GetCurrentUserAsync() + public Task> GetUsersAsync() { - await using var context = await _contextFactory.CreateDbContextAsync(); - var user = await context.Users.FirstOrDefaultAsync(u => u.IsCurrent); - return user ?? await context.Users.FirstAsync(); + var col = _db.GetCollection("users"); + return Task.FromResult(col.FindAll().ToList()); } - public async Task SetCurrentUserAsync(int userId) + public Task GetCurrentUserAsync() { - await using var context = await _contextFactory.CreateDbContextAsync(); - var users = await context.Users.ToListAsync(); + var col = _db.GetCollection("users"); + var user = col.FindOne(u => u.IsCurrent); + return Task.FromResult(user ?? col.FindAll().First()); + } + + public Task SetCurrentUserAsync(int userId) + { + var col = _db.GetCollection("users"); + var users = col.FindAll().ToList(); foreach (var u in users) + { u.IsCurrent = u.Id == userId; - await context.SaveChangesAsync(); + col.Update(u); + } _currentUserId = userId; + return Task.CompletedTask; } - public async Task CreateUserAsync(string name) + public Task CreateUserAsync(string name) { - await using var context = await _contextFactory.CreateDbContextAsync(); + var col = _db.GetCollection("users"); var user = new UserEntity { Name = name }; - context.Users.Add(user); - await context.SaveChangesAsync(); - return user; + col.Insert(user); + return Task.FromResult(user); } - public async Task InitializeAsync() + public Task LoadProjectSettingsAsync() { - await using var context = await _contextFactory.CreateDbContextAsync(); + var settings = _db.GetCollection("settings"); + var entries = new (string Key, Action Setter)[] + { + (KeyOllamaUrl, val => _ollamaConfig.OllamaUrl = val), + (KeyRagModel, val => _ollamaConfig.EmbedModel = val), + (KeyStyleModel, val => _ollamaConfig.StyleModel = val), + (KeySpellingModel, val => _ollamaConfig.SpellingModel = val), + (KeyTheme, val => _ollamaConfig.Theme = val), + (KeyLektorPrompt, val => _ollamaConfig.LektorSystemPrompt = val), + (KeyFactCheckTemplate, val => _ollamaConfig.FactCheckTemplate = val), + (KeySpellingPrompt, val => _ollamaConfig.SpellingPrompt = val), + (KeyAdvocatusDiaboli, val => _ollamaConfig.AdvocatusDiaboliPrompt = val), + (KeyHookFinder, val => _ollamaConfig.HookFinderPrompt = val), + (KeyEli5, val => _ollamaConfig.Eli5Prompt = val), + }; - var userExists = await context.Users.AnyAsync(); + foreach (var entry in entries) + { + var val = Get(entry.Key); + if (val != null) entry.Setter(val); + } + + return Task.CompletedTask; + } + + public Task InitializeAsync(int projectId = -1) + { + var users = _db.GetCollection("users"); + var settings = _db.GetCollection("settings"); + + var userExists = users.FindAll().Any(); if (!userExists) { var defaultUser = new UserEntity { Name = "Standardbenutzer", IsCurrent = true }; - context.Users.Add(defaultUser); - await context.SaveChangesAsync(); + users.Insert(defaultUser); _currentUserId = defaultUser.Id; } else { - var current = await context.Users.FirstOrDefaultAsync(u => u.IsCurrent); - _currentUserId = current?.Id ?? (await context.Users.FirstAsync()).Id; + var current = users.FindOne(u => u.IsCurrent); + _currentUserId = current?.Id ?? users.FindAll().First().Id; } var entries = new (string Key, string Default)[] @@ -194,29 +291,34 @@ public class SettingsService : ISettingsService (KeyLektorPrompt, _ollamaConfig.LektorSystemPrompt), (KeyFactCheckTemplate, _ollamaConfig.FactCheckTemplate), (KeySpellingPrompt, _ollamaConfig.SpellingPrompt), + (KeyAdvocatusDiaboli, _ollamaConfig.AdvocatusDiaboliPrompt), + (KeyHookFinder, _ollamaConfig.HookFinderPrompt), + (KeyEli5, _ollamaConfig.Eli5Prompt), }; foreach (var entry in entries) { - var existing = await context.Settings - .Where(s => s.Key == entry.Key && s.UserId == _currentUserId && s.ProjectId == null) - .FirstOrDefaultAsync(); + var existing = settings.FindOne(s => + s.Key == entry.Key && s.UserId == _currentUserId && s.ProjectId == projectId); if (existing != null) { var val = existing.Value; if (entry.Key == KeyOllamaUrl) _ollamaConfig.OllamaUrl = val; - else if (entry.Key == KeyRagModel) _ollamaConfig.StyleModel = val; + else if (entry.Key == KeyRagModel) _ollamaConfig.EmbedModel = val; else if (entry.Key == KeyStyleModel) _ollamaConfig.StyleModel = val; else if (entry.Key == KeySpellingModel) _ollamaConfig.SpellingModel = val; else if (entry.Key == KeyTheme) _ollamaConfig.Theme = val; else if (entry.Key == KeyLektorPrompt) _ollamaConfig.LektorSystemPrompt = val; else if (entry.Key == KeyFactCheckTemplate) _ollamaConfig.FactCheckTemplate = val; else if (entry.Key == KeySpellingPrompt) _ollamaConfig.SpellingPrompt = val; + else if (entry.Key == KeyAdvocatusDiaboli) _ollamaConfig.AdvocatusDiaboliPrompt = val; + else if (entry.Key == KeyHookFinder) _ollamaConfig.HookFinderPrompt = val; + else if (entry.Key == KeyEli5) _ollamaConfig.Eli5Prompt = val; } else { - context.Settings.Add(new SettingEntity + settings.Insert(new SettingEntity { Key = entry.Key, Value = entry.Default, @@ -226,6 +328,6 @@ public class SettingsService : ISettingsService } } - await context.SaveChangesAsync(); + return Task.CompletedTask; } } diff --git a/Services/WikipediaService.cs b/Services/WikipediaService.cs new file mode 100644 index 0000000..8f0d76c --- /dev/null +++ b/Services/WikipediaService.cs @@ -0,0 +1,136 @@ +using AuthorBuddy.Web.Models; +using System.Text.Json; +using System.Web; + +namespace AuthorBuddy.Web.Services; + +public class WikipediaService : IWikipediaService +{ + private readonly HttpClient _http; + private readonly string[] _languages = { "de", "en" }; + + public WikipediaService() + { + _http = new HttpClient { Timeout = TimeSpan.FromSeconds(15) }; + _http.DefaultRequestHeaders.UserAgent.ParseAdd("AuthorBuddy/1.0 (writing-assistant)"); + } + + public async Task> SearchAsync(string query, int maxResults = 3) + { + return await SearchAsync(new WikipediaSearchRequest + { + Query = query, + MaxResults = maxResults + }); + } + + public async Task> SearchAsync(WikipediaSearchRequest request) + { + var results = new List(); + + foreach (var lang in _languages) + { + if (lang == "de" && !request.SearchGerman) continue; + if (lang == "en" && !request.SearchEnglish) continue; + + try + { + var langResults = await SearchLanguageAsync(lang, request.Query, request.MaxResults); + results.AddRange(langResults); + } + catch + { + // Sprache überspringen bei Fehler + } + } + + return results; + } + + public async Task GetExtractAsync(string title, string language = "de") + { + try + { + var url = $"https://{language}.wikipedia.org/w/api.php" + + "?action=query" + + "&prop=extracts" + + "&exintro&explaintext" + + $"&titles={HttpUtility.UrlEncode(title)}" + + "&format=json&utf8=1"; + + var response = await _http.GetStringAsync(url); + using var doc = JsonDocument.Parse(response); + var pages = doc.RootElement.GetProperty("query").GetProperty("pages"); + + foreach (var page in pages.EnumerateObject()) + { + if (page.Value.TryGetProperty("extract", out var extract)) + return extract.GetString(); + } + } + catch { } + + return null; + } + + public async Task GetFullArticleAsync(string title, string language = "de") + { + try + { + var url = $"https://{language}.wikipedia.org/w/api.php" + + "?action=query" + + "&prop=extracts" + + "&explaintext" + + $"&titles={HttpUtility.UrlEncode(title)}" + + "&format=json&utf8=1"; + + var response = await _http.GetStringAsync(url); + using var doc = JsonDocument.Parse(response); + var pages = doc.RootElement.GetProperty("query").GetProperty("pages"); + + foreach (var page in pages.EnumerateObject()) + { + if (page.Value.TryGetProperty("extract", out var extract)) + return extract.GetString(); + } + } + catch { } + + return null; + } + + private async Task> SearchLanguageAsync(string lang, string query, int maxResults) + { + var results = new List(); + + var url = $"https://{lang}.wikipedia.org/w/api.php" + + "?action=query" + + "&list=search" + + $"&srsearch={HttpUtility.UrlEncode(query)}" + + $"&srlimit={maxResults}" + + "&format=json&utf8=1"; + + var response = await _http.GetStringAsync(url); + using var doc = JsonDocument.Parse(response); + var search = doc.RootElement.GetProperty("query").GetProperty("search"); + + foreach (var item in search.EnumerateArray()) + { + var title = item.GetProperty("title").GetString() ?? ""; + results.Add(new WikipediaResult + { + Title = title, + Snippet = StripHtml(item.GetProperty("snippet").GetString() ?? ""), + Url = $"https://{lang}.wikipedia.org/wiki/{HttpUtility.UrlEncode(title)}", + Language = lang + }); + } + + return results; + } + + private static string StripHtml(string html) + { + return System.Text.RegularExpressions.Regex.Replace(html, "<[^>]*>", ""); + } +} diff --git a/author_brain.db b/author_brain.db deleted file mode 100644 index 9345e48d312d1954dc307f00e00e4a097a9a42a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61440 zcmeI)&2JlN9S884IJF%&>3|l=i$v)|pfuh(jwh)b8X<&}I%zhEopqej3hj<2_T%_j z&x?2FnWPDDaHzN&;=(gykCREAmtKIB?u8TXP;RA6ipSXY4 z-7zWmlgxx-N=p1YlH%R?wK6sF*NI<@zr6nU@tMfWT{f#s#S}koJ?-6Y5i3;tE(Hu>Qk~-dP<7hwaRK)^t@3j*RuV-EZwA& zq*i(&y6JZnRxwwrdyYdb{_5r?Qkm}IjYRt9P5H+wLGW9Yb7t+j;q8rR3Ssf4tY!j-DXb*hx=e83J@1`$Jmiuhjd=e=yNYUI~)l?6q{m+lgrMVe#uF zf4tU($(PR_#j0)dO`W&Sz**N_Ug=Pa3WMG(5C9^D#yE=jkB9hj!gF#Z1_s zTt9h#Jeugqs@F?4y5@xmcg`4^aOj%Mpjzkbv<;EAX4(zbWRc9n^&jc(KN!IY{{IPiD5y777R?LId>+$sa^RmRO27Ts!WQe0(P4~DRJl2M8M^lFu zU+)&j5@}VHkEVwxt=si>bTz+Z>^vX8!7-DTkw~ws z$lduMhdo-?8vUn+tBFTqq_uj>v)XPxe{N+Wn%TK+C#M{HpEV+(_O|7c#r4YK;FUY` zG#O8uD`$d zxZ)K#+yV9r>}J!YJS@y?UW=#i-j$yQq4sC3OF#0cRi~#OUW){Hs&dNTJ!Zw4neOsv zkp9ukko0>a9!iai`_Fn$o74cQ)Vv@pX* zf+u13ts!|Zt7%6=^h-w0%fW9To`hoWOE`VTNylNP?i>(NkR`#Mm+00(W+@g=e^0&K z#Pqv7JsbV9m^iLW`p0(Nq?}0Kxs&X^_i7H2@cV&3Uai))i|hTPsYna5y|r3iA)+il z6&zgo2Uy`k%^likh=Ur^G;E!JU(L_ndq2`DGa_{7T%x0s#m>00Izz z00bZa0SG_<0uX?}e?Z{v(O5z5o%m~yOVzE_N?F@1)|MWn(y>^fe?f6jv$0yPRMR7| zLh{rq8^w1kRU*eSccT@1`J9?l^V7P~Y3aGSl*njQ`K6@%P5Hg@iMWFW0uX=z1Rwwb z2tWV=5P$##AOL~?hQQlrTn`u>QW0DZhz+aoF9(c#F_t-X0l|O&Uwr5v3j`nl0SG_< z0uX=z1Rwwb2tWV=Z?J%W{y(DpMNI?4w(ZcY4f{L?F*7Q%-B1Rwwb2tWV=5P$## z-e`gDOfn%oI8w(X+c0!f*W3;@3})?W9mh61{Gms7n9B)e7OB#Di@WufL)lKpdGSe; zIytgtI}Y1r)S;xjT_wx3Wl)Dqoowq_yE7|}Zkjr0?M#lmcy2ZP_6=&0EzS&LG0}03 ztgszoc}`H?4!h-|QH?(1hu%H}yK#>MdGtFBjKpr7|gQZ;^+k zDtTBGj~0vNwT09V@;^$YmaD~;5}6@um2$20q$WyLQM#zRe)Lv@=w36}_Ojj;Dm+#A#-MNf3$=18T(nHhMqmKDV8hi4rJCL-4@5xedg z!d29GA~)CD`A}?t?e)!br0nrSN?fixZAu36$BU6+cg{%8hbZQE)) z)GvE1QmeO&7a#9ZD|h2sTuQ$+Ch-HdR4i+^J@F3sN>a1Q3EDY`K_EjG7cGK-N| zTvCtch06~Nss&AgsXdpQ{pv_unm%sf=)2MSZ_07$YYzt7@f@SYd1ql}#<1(U(Xw5> zpsM%g?)AR^@1>-?e4}3+kQ@Xc009U<00Izz00bZa0SG|g|3u(R@~AXDw#9X;p*sz6 Kjl{od;`|%#OrwGT diff --git a/vec0.dll b/vec0.dll deleted file mode 100644 index e897f7f3a100d9139266ec50f8e75958b5e6725c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 307712 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 diff --git a/wwwroot/app.css b/wwwroot/app.css index e2ce31b..036b90d 100644 --- a/wwwroot/app.css +++ b/wwwroot/app.css @@ -193,15 +193,68 @@ body { line-height: 1.5; } -/* Editor */ -.editor-container { +.fact-similarity { + font-size: 11px; + color: var(--accent-color); + font-weight: bold; + margin-bottom: 4px; +} + +.fact-path { + font-size: 11px; + color: var(--border-color); + margin-bottom: 6px; + font-family: monospace; +} + +.fact-text { + font-size: 13px; + white-space: pre-wrap; + word-break: break-word; +} + +.fact-extract { + font-size: 12px; + margin-top: 6px; + padding-top: 6px; + border-top: 1px solid var(--border-color); + white-space: pre-wrap; + word-break: break-word; +} + +.fact-card a { + color: var(--accent-color); + text-decoration: none; +} + +.fact-card a:hover { + text-decoration: underline; +} + +.fact-actions { + display: flex; + gap: 6px; + margin-top: 8px; + padding-top: 8px; + border-top: 1px solid var(--border-color); +} + +.fact-actions button { + font-size: 12px; + padding: 4px 10px; +} + +/* Editor page - no scroll */ +.editor-page { display: flex; flex-direction: column; height: 100%; + overflow: hidden; } -.editor-container textarea { +.editor-area { flex: 1; + min-height: 0; font-family: 'Consolas', 'Courier New', monospace; font-size: 14pt; padding: 20px; @@ -213,13 +266,55 @@ body { line-height: 1.6; } -.editor-container .editor-toolbar { +.editor-toolbar { display: flex; justify-content: flex-end; padding: 8px 16px; gap: 8px; border-top: 1px solid var(--border-color); + border-bottom: 1px solid var(--border-color); background: var(--menu-bg); + flex-shrink: 0; +} + +/* Results area - scrollable box */ +.results-area { + max-height: 140px; + overflow-y: auto; + border-top: 1px solid var(--border-color); + background: var(--window-bg); + flex-shrink: 0; +} + +/* Version list */ +.version-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 6px 8px; + border-bottom: 1px solid var(--border-color); + font-size: 13px; +} + +.version-item:last-child { + border-bottom: none; +} + +.version-meta { + display: flex; + gap: 8px; + align-items: center; +} + +.version-date { + font-weight: bold; + color: var(--accent-color); + font-family: monospace; +} + +.version-comment { + color: var(--border-color); + font-style: italic; } /* Buttons */ @@ -237,6 +332,18 @@ button:hover { color: white; } +button:disabled { + background: var(--disabled-bg); + color: var(--disabled-text); + cursor: default; + border-color: var(--border-color); +} + +button:disabled:hover { + background: var(--disabled-bg); + color: var(--disabled-text); +} + button.primary { background: var(--accent-color); color: white; @@ -295,6 +402,176 @@ button.primary { background: transparent; } +/* Search section below editor */ +.search-section { + display: flex; + gap: 8px; + align-items: center; + padding: 6px 12px; + background: var(--menu-bg); + flex-shrink: 0; +} + +.search-section input { + flex: 1; + padding: 6px 10px; + border: 1px solid var(--border-color); + background: var(--editor-bg); + color: var(--text-color); + font-size: 13px; +} + +.search-section input::placeholder { + color: var(--border-color); +} + + + +/* Modal overlay */ +.modal-overlay { + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0,0,0,0.4); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; +} + +.modal-dialog { + background: var(--window-bg); + border: 2px solid var(--border-color); + min-width: 400px; + box-shadow: 4px 4px 8px rgba(0,0,0,0.3); +} + +.modal-title { + background: var(--accent-color); + color: white; + padding: 6px 12px; + font-weight: bold; + font-size: 14px; +} + +.modal-body { + padding: 16px; +} + +.modal-actions { + display: flex; + gap: 8px; + justify-content: flex-end; + padding: 12px 16px; + border-top: 1px solid var(--border-color); +} + +.modal-dialog .form-group { + margin-bottom: 12px; +} + +.modal-dialog .form-group:last-child { + margin-bottom: 0; +} + +.modal-dialog .form-group label { + display: block; + font-weight: bold; + margin-bottom: 4px; + font-size: 13px; +} + +.modal-dialog .form-group input { + width: 100%; + padding: 6px 8px; + border: 1px solid var(--border-color); + background: var(--editor-bg); + color: var(--text-color); + font-size: 13px; +} + +/* File tree in sidebar */ +.tree-item { + display: flex; + align-items: center; + gap: 4px; + padding: 3px 12px; + cursor: pointer; + font-size: 12px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.tree-item:hover { + background: var(--accent-color); + color: white; +} + +.tree-item.active { + background: var(--accent-color); + color: white; + font-weight: bold; +} + +.tree-item.file { + padding-left: 28px; +} + +.tree-item.tree-child { + padding-left: 44px; +} + +.tree-icon { + flex-shrink: 0; + font-size: 11px; +} + +.tree-name { + overflow: hidden; + text-overflow: ellipsis; + flex: 1; +} + +.tree-rename { + background: none; + border: none; + cursor: pointer; + font-size: 12px; + padding: 0 4px; + opacity: 0.4; + color: inherit; + flex-shrink: 0; +} + +.tree-rename:hover { + opacity: 1; +} + +.nav-header-actions { + margin-left: auto; + display: flex; + gap: 2px; +} + +.nav-item-icon { + background: none; + border: none; + cursor: pointer; + font-size: 14px; + padding: 0 4px; + opacity: 0.5; + color: inherit; +} + +.nav-item-icon:hover { + opacity: 1; +} + +.nav-item-sub.active { + background: var(--accent-color); + color: white; +} + /* Progress */ .progress-bar { width: 100%; @@ -340,21 +617,16 @@ button.primary { } .settings-layout { - display: flex; + display: grid; + grid-template-columns: 1fr 1fr 1fr; gap: 16px; } -.settings-layout-left { - flex: 1; +.settings-column { min-width: 0; } -.settings-layout-right { - flex: 1; - min-width: 0; -} - -.settings-layout-right .form-group textarea { +.settings-column .form-group textarea { min-height: 120px; font-family: monospace; font-size: 12px; @@ -450,7 +722,7 @@ button.primary { .result-panel { border-top: 2px solid var(--border-color); padding: 12px; - max-height: 300px; + max-height: 400px; overflow-y: auto; } @@ -465,6 +737,92 @@ button.primary { width: 8px; } +/* Assistant page */ +.assistant-page { + display: flex; + flex-direction: column; + height: 100%; +} + +.assistant-toolbar { + display: flex; + gap: 8px; + align-items: center; + padding: 8px 0; + border-bottom: 1px solid var(--border-color); + margin-bottom: 8px; +} + +.assistant-toolbar select { + padding: 4px 8px; + border: 1px solid var(--border-color); + background: var(--input-bg); + color: var(--text-color); + font-size: 13px; +} + +.assistant-panels { + display: flex; + gap: 12px; + flex: 1; + min-height: 0; +} + +.assistant-input-panel, +.assistant-output-panel { + flex: 1; + display: flex; + flex-direction: column; +} + +.assistant-input-panel h4, +.assistant-output-panel h4 { + margin: 0 0 6px 0; + font-size: 13px; + font-weight: bold; +} + +.assistant-textarea { + flex: 1; + resize: none; + padding: 8px; + border: 1px solid var(--border-color); + background: var(--input-bg); + color: var(--text-color); + font-family: monospace; + font-size: 13px; + min-height: 200px; +} + +.assistant-output { + flex: 1; + padding: 8px; + border: 1px solid var(--border-color); + background: var(--card-bg); + color: var(--text-color); + font-family: monospace; + font-size: 13px; + overflow-y: auto; + white-space: pre-wrap; + min-height: 200px; +} + +.assistant-output pre { + margin: 0; + white-space: pre-wrap; + font-family: inherit; + font-size: inherit; +} + +.assistant-error { + color: red; +} + +.assistant-hint { + color: var(--border-color); + font-style: italic; +} + ::-webkit-scrollbar-track { background: var(--window-bg); } diff --git a/wwwroot/css/themes/dark.css b/wwwroot/css/themes/dark.css index 32c5ab6..5e075e0 100644 --- a/wwwroot/css/themes/dark.css +++ b/wwwroot/css/themes/dark.css @@ -7,4 +7,6 @@ --menu-bg: #252526; --card-bg: #2d2d2d; --status-bar-bg: #007acc; + --disabled-bg: #2a2a2a; + --disabled-text: #606060; } diff --git a/wwwroot/css/themes/light.css b/wwwroot/css/themes/light.css index 6433b50..56eca8a 100644 --- a/wwwroot/css/themes/light.css +++ b/wwwroot/css/themes/light.css @@ -7,4 +7,6 @@ --menu-bg: #e0e0e0; --card-bg: #ffffff; --status-bar-bg: #dcdcdc; + --disabled-bg: #e8e8e8; + --disabled-text: #a0a0a0; } diff --git a/wwwroot/css/themes/w95.css b/wwwroot/css/themes/w95.css index 00cfb62..3ade6a9 100644 --- a/wwwroot/css/themes/w95.css +++ b/wwwroot/css/themes/w95.css @@ -7,4 +7,6 @@ --menu-bg: #c0c0c0; --card-bg: #ffffff; --status-bar-bg: #c0c0c0; + --disabled-bg: #c0c0c0; + --disabled-text: #808080; }