diff --git a/.vs/AuthorBuddy.Web.slnx/FileContentIndex/2f8b1e0b-4d4d-43c8-9474-2f7ef9baca64.vsidx b/.vs/AuthorBuddy.Web.slnx/FileContentIndex/2f8b1e0b-4d4d-43c8-9474-2f7ef9baca64.vsidx deleted file mode 100644 index 74cc3f8..0000000 Binary files a/.vs/AuthorBuddy.Web.slnx/FileContentIndex/2f8b1e0b-4d4d-43c8-9474-2f7ef9baca64.vsidx and /dev/null differ diff --git a/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.backup.json b/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.backup.json index 38c9533..f54bf47 100644 --- a/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.backup.json +++ b/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.backup.json @@ -3,29 +3,41 @@ "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\\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\\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\\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\\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}" @@ -46,10 +58,6 @@ "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\llm_model.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\llm_model.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\\models\\modelstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\modelstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" @@ -58,18 +66,10 @@ "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\models.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\models.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\\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\\services\\ifilescannerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ifilescannerservice.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\\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\\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}" @@ -122,33 +122,85 @@ }, { "$type": "Document", - "DocumentIndex": 5, - "Title": "OllamaSettings.cs", - "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs", - "RelativeDocumentMoniker": "Models\\OllamaSettings.cs", - "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs", - "RelativeToolTip": "Models\\OllamaSettings.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAqwAQAAAAcAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T13:39:46.179Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 4, + "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": "AgIAAAAAAAAAAAAAAAAAAAAAAAAdAAAAAAAAAA==", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaService.cs*", + "RelativeToolTip": "Services\\OllamaService.cs*", + "ViewState": "AgIAADQAAAAAAAAAAAAQwEUAAABDAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T06:43:46.404Z", "EditorCaption": "" }, + { + "$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==", + "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==", + "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": "" + }, + { + "$type": "Document", + "DocumentIndex": 8, + "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==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", + "WhenOpened": "2026-05-15T16:04:36.444Z", + "EditorCaption": "" + }, { "$type": "Document", "DocumentIndex": 6, + "Title": "OllamaSettings.cs", + "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs", + "RelativeDocumentMoniker": "Models\\OllamaSettings.cs", + "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs", + "RelativeToolTip": "Models\\OllamaSettings.cs", + "ViewState": "AgIAAAAAAAAAAAAAAAAqwAYAAAA6AAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-16T13:39:46.179Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 9, "Title": "FileScannerService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\FileScannerService.cs", "RelativeDocumentMoniker": "Services\\FileScannerService.cs", @@ -162,58 +214,49 @@ { "$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": "" + }, + { + "$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==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-14T10:50:13.284Z", + "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": "AgIAADcAAAAAAAAAAADwv0wAAAAAAAAAAAAAAA==", + "ViewState": "AgIAAHMAAAAAAAAAAADwv4UAAAAAAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", "WhenOpened": "2026-05-15T16:43:26.6Z", "EditorCaption": "" }, { - "$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": "AgIAAEwAAAAAAAAAAAAewFoAAAAnAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T06:05:12.928Z", - "EditorCaption": "" + "$type": "Bookmark", + "Name": "RST:0:0:{b3f9f954-0ca5-0091-76b4-34a47f44c954}" }, { "$type": "Document", - "DocumentIndex": 8, - "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": 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": "AgIAAAIAAAAAAAAAAAAxwBcAAAAbAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T13:21:26.951Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 14, + "DocumentIndex": 5, "Title": "IOllamaService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaService.cs", "RelativeDocumentMoniker": "Services\\IOllamaService.cs", @@ -226,20 +269,7 @@ }, { "$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==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-15T16:04:36.444Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 7, + "DocumentIndex": 10, "Title": "Program.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", "RelativeDocumentMoniker": "Program.cs", @@ -252,7 +282,7 @@ }, { "$type": "Document", - "DocumentIndex": 9, + "DocumentIndex": 12, "Title": "App.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", "RelativeDocumentMoniker": "Components\\App.razor", @@ -263,13 +293,9 @@ "WhenOpened": "2026-05-16T05:42:06.383Z", "EditorCaption": "" }, - { - "$type": "Bookmark", - "Name": "RST:0:0:{b3f9f954-0ca5-0091-76b4-34a47f44c954}" - }, { "$type": "Document", - "DocumentIndex": 13, + "DocumentIndex": 15, "Title": "Models.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", "RelativeDocumentMoniker": "Components\\Pages\\Models.razor", @@ -282,7 +308,7 @@ }, { "$type": "Document", - "DocumentIndex": 10, + "DocumentIndex": 13, "Title": "LLM_Model.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", "RelativeDocumentMoniker": "Models\\LLM_Model.cs", @@ -295,7 +321,7 @@ }, { "$type": "Document", - "DocumentIndex": 12, + "DocumentIndex": 14, "Title": "ModelStatus.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", "RelativeDocumentMoniker": "Models\\ModelStatus.cs", @@ -306,19 +332,6 @@ "WhenOpened": "2026-05-16T13:01:24.508Z", "EditorCaption": "" }, - { - "$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": "AgIAAFkAAAAAAAAAAAApwGAAAAAOAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-16T13:01:59.743Z", - "EditorCaption": "" - }, { "$type": "Document", "DocumentIndex": 19, @@ -345,7 +358,7 @@ }, { "$type": "Document", - "DocumentIndex": 15, + "DocumentIndex": 16, "Title": "IFileScannerService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IFileScannerService.cs", "RelativeDocumentMoniker": "Services\\IFileScannerService.cs", @@ -367,18 +380,6 @@ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-15T15:57:10.2Z" }, - { - "$type": "Document", - "DocumentIndex": 16, - "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": "AgIAABoAAAAAAAAAAAAQwD4AAAAIAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-14T10:50:13.284Z" - }, { "$type": "Document", "DocumentIndex": 17, diff --git a/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.json b/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.json index 0f833c9..7199885 100644 --- a/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.json +++ b/.vs/AuthorBuddy.Web.slnx/v18/DocumentLayout.json @@ -3,16 +3,32 @@ "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\\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\\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\\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\\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}", @@ -22,10 +38,6 @@ "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\\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}" @@ -46,10 +58,6 @@ "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\models\\llm_model.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\llm_model.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\\models\\modelstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:models\\modelstatus.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}" @@ -58,18 +66,10 @@ "AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\models.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\models.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\\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\\services\\ifilescannerservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}", "RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ifilescannerservice.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\\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\\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}" @@ -124,48 +124,22 @@ "$type": "Bookmark", "Name": "RST:0:0:{b3f9f954-0ca5-0091-76b4-34a47f44c954}" }, - { - "$type": "Document", - "DocumentIndex": 2, - "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": "AgIAACMAAAAAAAAAAAAwwAAAAAAdAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-16T06:43:46.404Z", - "EditorCaption": "" - }, { "$type": "Document", "DocumentIndex": 3, - "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": "AgIAAF8AAAAAAAAAAADwv3EAAAAAAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-15T16:43:26.6Z", - "EditorCaption": "" - }, - { - "$type": "Document", - "DocumentIndex": 1, "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": "AgIAAEoAAAAAAAAAAAAAAGUAAAA7AAAAAAAAAA==", + "ViewState": "AgIAAMAAAAAAAAAAAAAQwMgAAAAMAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T06:05:12.928Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 8, + "DocumentIndex": 11, "Title": "ThemeService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs", "RelativeDocumentMoniker": "Services\\ThemeService.cs", @@ -178,20 +152,20 @@ }, { "$type": "Document", - "DocumentIndex": 5, + "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": "AgIAAAIAAAAAAAAAAAAxwBcAAAAbAAAAAAAAAA==", + "ViewState": "AgIAAAsAAAAAAAAAAAA8wCEAAAAAAAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T13:21:26.951Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 4, + "DocumentIndex": 8, "Title": "MainLayout.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\MainLayout.razor", "RelativeDocumentMoniker": "Components\\Layout\\MainLayout.razor", @@ -204,20 +178,20 @@ }, { "$type": "Document", - "DocumentIndex": 0, + "DocumentIndex": 6, "Title": "OllamaSettings.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs", "RelativeDocumentMoniker": "Models\\OllamaSettings.cs", "ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs", "RelativeToolTip": "Models\\OllamaSettings.cs", - "ViewState": "AgIAAAAAAAAAAAAAAAAqwBMAAAAgAAAAAAAAAA==", + "ViewState": "AgIAAAAAAAAAAAAAAAAqwAYAAAA6AAAAAAAAAA==", "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-16T13:39:46.179Z", "EditorCaption": "" }, { "$type": "Document", - "DocumentIndex": 6, + "DocumentIndex": 9, "Title": "FileScannerService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\FileScannerService.cs", "RelativeDocumentMoniker": "Services\\FileScannerService.cs", @@ -230,7 +204,59 @@ }, { "$type": "Document", - "DocumentIndex": 14, + "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==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", + "WhenOpened": "2026-05-14T10:50:13.284Z", + "EditorCaption": "" + }, + { + "$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==", + "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", + "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", @@ -243,7 +269,7 @@ }, { "$type": "Document", - "DocumentIndex": 7, + "DocumentIndex": 10, "Title": "Program.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Program.cs", "RelativeDocumentMoniker": "Program.cs", @@ -256,7 +282,7 @@ }, { "$type": "Document", - "DocumentIndex": 9, + "DocumentIndex": 12, "Title": "App.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor", "RelativeDocumentMoniker": "Components\\App.razor", @@ -269,7 +295,7 @@ }, { "$type": "Document", - "DocumentIndex": 13, + "DocumentIndex": 15, "Title": "Models.razor", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor", "RelativeDocumentMoniker": "Components\\Pages\\Models.razor", @@ -282,7 +308,7 @@ }, { "$type": "Document", - "DocumentIndex": 10, + "DocumentIndex": 13, "Title": "LLM_Model.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs", "RelativeDocumentMoniker": "Models\\LLM_Model.cs", @@ -295,7 +321,7 @@ }, { "$type": "Document", - "DocumentIndex": 12, + "DocumentIndex": 14, "Title": "ModelStatus.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs", "RelativeDocumentMoniker": "Models\\ModelStatus.cs", @@ -306,19 +332,6 @@ "WhenOpened": "2026-05-16T13:01:24.508Z", "EditorCaption": "" }, - { - "$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": "AgIAAFkAAAAAAAAAAAApwGAAAAAOAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|", - "WhenOpened": "2026-05-16T13:01:59.743Z", - "EditorCaption": "" - }, { "$type": "Document", "DocumentIndex": 19, @@ -345,7 +358,7 @@ }, { "$type": "Document", - "DocumentIndex": 15, + "DocumentIndex": 16, "Title": "IFileScannerService.cs", "DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IFileScannerService.cs", "RelativeDocumentMoniker": "Services\\IFileScannerService.cs", @@ -367,18 +380,6 @@ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", "WhenOpened": "2026-05-15T15:57:10.2Z" }, - { - "$type": "Document", - "DocumentIndex": 16, - "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": "AgIAABoAAAAAAAAAAAAQwD4AAAAIAAAAAAAAAA==", - "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|", - "WhenOpened": "2026-05-14T10:50:13.284Z" - }, { "$type": "Document", "DocumentIndex": 17, diff --git a/AuthorBuddy.Web.csproj b/AuthorBuddy.Web.csproj index 3df2811..4204023 100644 --- a/AuthorBuddy.Web.csproj +++ b/AuthorBuddy.Web.csproj @@ -8,7 +8,12 @@ + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + diff --git a/Components/DiffView.razor b/Components/DiffView.razor new file mode 100644 index 0000000..f9c93c6 --- /dev/null +++ b/Components/DiffView.razor @@ -0,0 +1,31 @@ +@using DiffPlex +@using DiffPlex.DiffBuilder +@using DiffPlex.DiffBuilder.Model + +
+ @if (lines is not null) + { + @foreach (var line in lines.Lines) + { +
+ @line.Position + @line.Text +
+ } + } +
+ +@code { + [Parameter] + public string Original { get; set; } = string.Empty; + + [Parameter] + public string Corrected { get; set; } = string.Empty; + + private DiffPaneModel? lines; + + protected override void OnParametersSet() + { + lines = InlineDiffBuilder.Diff(Original, Corrected); + } +} diff --git a/Components/Pages/Editor.razor b/Components/Pages/Editor.razor index ffc1079..4997b65 100644 --- a/Components/Pages/Editor.razor +++ b/Components/Pages/Editor.razor @@ -29,11 +29,18 @@ -@if (!string.IsNullOrEmpty(analysisResult)) +@if (showSpellDiff && !string.IsNullOrEmpty(correctedText)) { -
-

Ergebnis:

-
@analysisResult
+
+

Rechtschreibprüfung - Änderungen:

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

Ergebnis:

+
@analysisResult
} @@ -49,13 +56,14 @@ private bool isChecking; private double checkProgress; private string analysisResult = string.Empty; + private string originalText = string.Empty; + private string correctedText = string.Empty; + private bool showSpellDiff; protected override async Task OnInitializedAsync() { if (Action == "newproject") { - // The native folder dialog isn't available in Blazor. - // In a real app, you'd provide a form to enter project name and path. statusText = "Bitte nutze die Einstellungen zum Erstellen eines neuen Projekts."; } } @@ -67,6 +75,7 @@ isChecking = true; statusText = "Ollama analysiert Stil..."; checkProgress = 50; + showSpellDiff = false; try { @@ -91,10 +100,13 @@ isChecking = true; statusText = "Ollama prüft Rechtschreibung..."; checkProgress = 50; + showSpellDiff = false; try { - //analysisResult = await OllamaService.QuickSpellCheckAsync(editorContent); + originalText = editorContent; + correctedText = await OllamaService.QuickSpellCheckAsync(editorContent); + showSpellDiff = true; } catch (Exception ex) { @@ -114,6 +126,7 @@ isChecking = true; statusText = "Suche verwandte Fakten..."; + showSpellDiff = false; await Task.Delay(500); analysisResult = "RAG-Suche: Stelle sicher, dass ein Projekt geladen und indexiert wurde."; diff --git a/Components/Pages/Settings.razor b/Components/Pages/Settings.razor index 3841d13..f289df2 100644 --- a/Components/Pages/Settings.razor +++ b/Components/Pages/Settings.razor @@ -10,6 +10,26 @@
+
+

Benutzer

+
+ + +
+
+ +
+ + +
+
+
+
@@ -123,23 +143,31 @@ private string factCheckTemplate = string.Empty; private string spellingPrompt = string.Empty; private string newProjectName = string.Empty; + private string newUserName = string.Empty; private string statusMessage = string.Empty; private List availableModels = new(); + private List users = new(); + private int selectedUserId; protected override async Task OnInitializedAsync() { - 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; + users = await SettingsService.GetUsersAsync(); + 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; try { - var models = await OllamaService.GetLocalModelsAsync(); availableModels = models.ToList(); } @@ -149,6 +177,47 @@ } } + private async Task<(string ragModel, string styleModel, string spellingModel, string selectedTheme, string ollamaUrl, string lektorPrompt, string factCheckTemplate, string spellingPrompt)> LoadUserSettingsAsync() + { + 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 + ); + } + + private async Task SwitchUser(ChangeEventArgs e) + { + var userId = int.Parse(e.Value?.ToString() ?? "0"); + 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; + } + + private async Task AddUser() + { + if (string.IsNullOrWhiteSpace(newUserName)) return; + + var user = await SettingsService.CreateUserAsync(newUserName); + users.Add(user); + newUserName = string.Empty; + statusMessage = $"Benutzer '{user.Name}' erstellt."; + } + private async Task SaveSettings() { await SettingsService.SaveOllamaUrlAsync(ollamaUrl); @@ -164,7 +233,4 @@ statusMessage = "Einstellungen gespeichert."; await ThemeService.ApplyTheme(selectedTheme); } - - - } diff --git a/Data/AppDbContext.cs b/Data/AppDbContext.cs index 178a3fa..1338d93 100644 --- a/Data/AppDbContext.cs +++ b/Data/AppDbContext.cs @@ -8,6 +8,7 @@ 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) { } @@ -25,9 +26,19 @@ public class AppDbContext : DbContext modelBuilder.Entity(entity => { entity.ToTable("Settings"); - entity.HasKey(e => e.Key); - entity.Property(e => e.Key).HasColumnName("key"); + 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 => @@ -41,7 +52,7 @@ public class AppDbContext : DbContext }); } - public static void InitializeDatabase(string connectionString) + public static void SetupVecExtension(string connectionString) { using var connection = new SqliteConnection(connectionString); connection.Open(); @@ -62,25 +73,6 @@ public class AppDbContext : DbContext using var createVecCmd = connection.CreateCommand(); createVecCmd.CommandText = @" - CREATE TABLE IF NOT EXISTS Projects ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - RootPath TEXT NOT NULL, - LastOpened DATETIME - ); - CREATE TABLE IF NOT EXISTS Settings ( - key TEXT NOT NULL UNIQUE, - value TEXT NOT NULL - ); - CREATE TABLE IF NOT EXISTS DocumentMeta ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - project_id INTEGER, - file_path TEXT UNIQUE, - last_modified DATETIME, - hash TEXT, - file_type TEXT, - FOREIGN KEY(project_id) REFERENCES Projects(id) - ); CREATE VIRTUAL TABLE IF NOT EXISTS vec_documents USING vec0( embedding float[1024] );"; diff --git a/Data/SettingEntity.cs b/Data/SettingEntity.cs index 94ba2de..fa31c04 100644 --- a/Data/SettingEntity.cs +++ b/Data/SettingEntity.cs @@ -7,8 +7,16 @@ namespace AuthorBuddy.Web.Data; 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 new file mode 100644 index 0000000..5070a76 --- /dev/null +++ b/Data/UserEntity.cs @@ -0,0 +1,17 @@ +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 new file mode 100644 index 0000000..8473c70 --- /dev/null +++ b/Migrations/20260516151053_InitialCreate.Designer.cs @@ -0,0 +1,127 @@ +// +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 new file mode 100644 index 0000000..2a9f35c --- /dev/null +++ b/Migrations/20260516151053_InitialCreate.cs @@ -0,0 +1,93 @@ +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 new file mode 100644 index 0000000..089a0a3 --- /dev/null +++ b/Migrations/AppDbContextModelSnapshot.cs @@ -0,0 +1,124 @@ +// +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/Program.cs b/Program.cs index d821f15..1e900a9 100644 --- a/Program.cs +++ b/Program.cs @@ -21,7 +21,13 @@ builder.Services.AddDbContextFactory(options => var app = builder.Build(); -AppDbContext.InitializeDatabase(Constants.SQLiteConnection); +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(); if (!app.Environment.IsDevelopment()) { diff --git a/Services/IOllamaService.cs b/Services/IOllamaService.cs index 6408792..954cac7 100644 --- a/Services/IOllamaService.cs +++ b/Services/IOllamaService.cs @@ -8,10 +8,6 @@ public interface IOllamaService { Task> GetLocalModelsAsync(); Task PullModelAsync(string modelName, IProgress progress); - //Task> GetEmbeddingAsync(string text); - //Task StreamStyleCheckAsync(string input); - //Task AnswerBasedOnFactsAsync(string question, string facts); - //Task QuickSpellCheckAsync(string text); + Task QuickSpellCheckAsync(string text); void Reconfigure(string ollamaUrl); - } diff --git a/Services/ISettingsService.cs b/Services/ISettingsService.cs index d853f81..761bbed 100644 --- a/Services/ISettingsService.cs +++ b/Services/ISettingsService.cs @@ -1,4 +1,6 @@ -namespace AuthorBuddy.Web.Services; +using AuthorBuddy.Web.Data; + +namespace AuthorBuddy.Web.Services; public interface ISettingsService { @@ -21,5 +23,12 @@ public interface ISettingsService Task SaveFactCheckTemplateAsync(string prompt); Task SaveSpellingPromptAsync(string prompt); + Task> GetUsersAsync(); + Task GetCurrentUserAsync(); + Task SetCurrentUserAsync(int userId); + Task CreateUserAsync(string name); + + int? CurrentProjectId { get; set; } + Task InitializeAsync(); } diff --git a/Services/OllamaService.cs b/Services/OllamaService.cs index fa49caf..b083082 100644 --- a/Services/OllamaService.cs +++ b/Services/OllamaService.cs @@ -1,15 +1,19 @@ using AuthorBuddy.Web.Models; using System.Text.Json; +using static System.Net.Mime.MediaTypeNames; namespace AuthorBuddy.Web.Services; public class OllamaService : IOllamaService { private readonly HttpClient _httpClient; + private readonly OllamaSettings _settings; private string _baseUrl = "http://localhost:11434"; - public OllamaService() + public OllamaService(OllamaSettings settings) { + _settings = settings; + _baseUrl = settings.OllamaUrl; _httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(300) }; } @@ -49,6 +53,27 @@ public class OllamaService : IOllamaService } } + public async Task QuickSpellCheckAsync(string text) + { + return await Chat(_settings.SpellingModel, text, _settings.SpellingPrompt); + } + + public async Task StreamStyleCheckAsync(string text) + { + var systemPrompt = _settings.LektorSystemPrompt; + return await Chat(_settings.StyleModel, text, systemPrompt); + + } + + public async Task AnswerBasedOnFactsAsync(string question, string facts) + { + var prompt = _settings.GetFactCheckPrompt(question, facts); + + return await Chat(_settings.EmbedModel, prompt); + } + + + public async Task Chat(string model, string userMessage, string? systemPrompt = null) { try @@ -57,6 +82,7 @@ public class OllamaService : IOllamaService { model = model, prompt = userMessage, + system = systemPrompt, stream = false }; diff --git a/Services/SettingsService.cs b/Services/SettingsService.cs index 649b78e..8d37810 100644 --- a/Services/SettingsService.cs +++ b/Services/SettingsService.cs @@ -17,6 +17,8 @@ public class SettingsService : ISettingsService private readonly IDbContextFactory _contextFactory; private readonly OllamaSettings _ollamaConfig; + private int? _currentUserId; + private int? _currentProjectId; public SettingsService(IDbContextFactory contextFactory, OllamaSettings ollamaConfig) { @@ -24,35 +26,69 @@ public class SettingsService : ISettingsService _ollamaConfig = ollamaConfig; } - private async Task GetAsync(string key) + public int? CurrentProjectId + { + get => _currentProjectId; + set => _currentProjectId = value; + } + + private async Task GetSettingAsync(string key, int? userId, int? projectId) { await using var context = await _contextFactory.CreateDbContextAsync(); - var setting = await context.Settings.FindAsync(key); + + var matches = context.Settings.Where(s => + s.Key == key && + (s.UserId == userId || s.UserId == null) && + (s.ProjectId == projectId || s.ProjectId == null)); + + var setting = await matches + .OrderByDescending(s => s.UserId != null) + .ThenByDescending(s => s.ProjectId != null) + .FirstOrDefaultAsync(); + return setting?.Value; } + private async Task GetAsync(string key) + { + return await GetSettingAsync(key, _currentUserId, _currentProjectId); + } + + private async Task SetAsync(string key, string value) + { + await using var context = await _contextFactory.CreateDbContextAsync(); + + var existing = await context.Settings + .Where(s => s.Key == key && s.UserId == _currentUserId && s.ProjectId == _currentProjectId) + .FirstOrDefaultAsync(); + + if (existing != null) + { + existing.Value = value; + } + else + { + context.Settings.Add(new SettingEntity + { + Key = key, + Value = value, + UserId = _currentUserId, + ProjectId = _currentProjectId + }); + } + + 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); - private async Task SetAsync(string key, string value) - { - await using var context = await _contextFactory.CreateDbContextAsync(); - var existing = await context.Settings.FindAsync(key); - if (existing != null) - existing.Value = value; - else - context.Settings.Add(new SettingEntity { Key = key, Value = value }); - await context.SaveChangesAsync(); - } - public async Task SaveOllamaUrlAsync(string url) { await SetAsync(KeyOllamaUrl, url); @@ -82,6 +118,7 @@ public class SettingsService : ISettingsService await SetAsync(KeyFactCheckTemplate, prompt); _ollamaConfig.FactCheckTemplate = prompt; } + public async Task SaveSpellingPromptAsync(string prompt) { await SetAsync(KeySpellingPrompt, prompt); @@ -97,10 +134,56 @@ public class SettingsService : ISettingsService public Task SaveThemeAsync(string theme) => SetAsync(KeyTheme, theme); + public async Task> GetUsersAsync() + { + await using var context = await _contextFactory.CreateDbContextAsync(); + return await context.Users.ToListAsync(); + } + + public async Task GetCurrentUserAsync() + { + await using var context = await _contextFactory.CreateDbContextAsync(); + var user = await context.Users.FirstOrDefaultAsync(u => u.IsCurrent); + return user ?? await context.Users.FirstAsync(); + } + + public async Task SetCurrentUserAsync(int userId) + { + await using var context = await _contextFactory.CreateDbContextAsync(); + var users = await context.Users.ToListAsync(); + foreach (var u in users) + u.IsCurrent = u.Id == userId; + await context.SaveChangesAsync(); + _currentUserId = userId; + } + + public async Task CreateUserAsync(string name) + { + await using var context = await _contextFactory.CreateDbContextAsync(); + var user = new UserEntity { Name = name }; + context.Users.Add(user); + await context.SaveChangesAsync(); + return user; + } + public async Task InitializeAsync() { await using var context = await _contextFactory.CreateDbContextAsync(); + var userExists = await context.Users.AnyAsync(); + if (!userExists) + { + var defaultUser = new UserEntity { Name = "Standardbenutzer", IsCurrent = true }; + context.Users.Add(defaultUser); + await context.SaveChangesAsync(); + _currentUserId = defaultUser.Id; + } + else + { + var current = await context.Users.FirstOrDefaultAsync(u => u.IsCurrent); + _currentUserId = current?.Id ?? (await context.Users.FirstAsync()).Id; + } + var entries = new (string Key, string Default)[] { (KeyOllamaUrl, _ollamaConfig.OllamaUrl), @@ -115,7 +198,10 @@ public class SettingsService : ISettingsService foreach (var entry in entries) { - var existing = await context.Settings.FindAsync(entry.Key); + var existing = await context.Settings + .Where(s => s.Key == entry.Key && s.UserId == _currentUserId && s.ProjectId == null) + .FirstOrDefaultAsync(); + if (existing != null) { var val = existing.Value; @@ -130,7 +216,13 @@ public class SettingsService : ISettingsService } else { - context.Settings.Add(new SettingEntity { Key = entry.Key, Value = entry.Default }); + context.Settings.Add(new SettingEntity + { + Key = entry.Key, + Value = entry.Default, + UserId = _currentUserId, + ProjectId = null + }); } } diff --git a/author_brain.db b/author_brain.db index 6c9e6fb..9345e48 100644 Binary files a/author_brain.db and b/author_brain.db differ diff --git a/wwwroot/app.css b/wwwroot/app.css index 717f523..e2ce31b 100644 --- a/wwwroot/app.css +++ b/wwwroot/app.css @@ -398,6 +398,68 @@ button.primary { font-size: 13px; } +/* Diff view */ +.diff-panel { + border-top: 2px solid var(--border-color); + padding: 12px; + max-height: 400px; + overflow-y: auto; +} + +.diff-panel h4, .result-panel h4 { + margin-bottom: 8px; + font-size: 14px; +} + +.diff-view { + font-family: monospace; + font-size: 13px; + line-height: 1.5; +} + +.diff-line { + display: flex; + gap: 8px; + padding: 1px 4px; +} + +.diff-line-num { + color: var(--border-color); + min-width: 32px; + text-align: right; + user-select: none; +} + +.diff-line-text { + white-space: pre-wrap; + word-break: break-word; +} + +.diff-inserted { + background: rgba(0, 200, 0, 0.15); +} + +.diff-deleted { + background: rgba(200, 0, 0, 0.15); +} + +.diff-modified { + background: rgba(200, 200, 0, 0.15); +} + +.result-panel { + border-top: 2px solid var(--border-color); + padding: 12px; + max-height: 300px; + overflow-y: auto; +} + +.result-text { + white-space: pre-wrap; + font-size: 13px; + line-height: 1.5; +} + /* Scrollbar styling */ ::-webkit-scrollbar { width: 8px;