Design Improvements

This commit is contained in:
Roland 2026-07-04 10:32:35 +02:00
parent a5d2c80c70
commit e64a38ccdf
21 changed files with 1349 additions and 687 deletions

View file

@ -6,6 +6,46 @@
"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\\wwwroot\\app.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:wwwroot\\app.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\\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\\authorbuddy.web.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:authorbuddy.web.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
},
{
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\quickmarkdown.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\quickmarkdown.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\\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\\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\\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\\ollamabackend.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ollamabackend.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\\services\\chatservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\chatservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\resources\\en.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:resources\\en.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
@ -30,22 +70,10 @@
"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\\services\\ollamabackend.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ollamabackend.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\\illmbackend.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\illmbackend.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\\chatservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\chatservice.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\\data\\userentity.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:data\\userentity.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
@ -62,10 +90,6 @@
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\ollamaassistant.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\ollamaassistant.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\\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\\pages\\dbadmin.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\dbadmin.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}"
@ -84,10 +108,6 @@
"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\\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\\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}"
@ -96,10 +116,6 @@
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iollamasetupservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iollamasetupservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\authorbuddy.web.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:authorbuddy.web.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
},
{
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\install.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:install.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
@ -192,7 +208,7 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 6,
"SelectedChildIndex": 5,
"Children": [
{
"$type": "Bookmark",
@ -201,30 +217,43 @@
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "en.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\en.json",
"RelativeDocumentMoniker": "Resources\\en.json",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\en.json",
"RelativeToolTip": "Resources\\en.json",
"ViewState": "AgIAABQBAAAAAAAAAAAAACQBAAAfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
"WhenOpened": "2026-06-14T06:03:36.064Z"
"Title": "app.css",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\wwwroot\\app.css",
"RelativeDocumentMoniker": "wwwroot\\app.css",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\wwwroot\\app.css",
"RelativeToolTip": "wwwroot\\app.css",
"ViewState": "AgIAAJYCAAAAAAAAAAAiwKoCAAAJAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003000|",
"WhenOpened": "2026-07-04T08:22:21.143Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "de.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\de.json",
"RelativeDocumentMoniker": "Resources\\de.json",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\de.json",
"RelativeToolTip": "Resources\\de.json",
"ViewState": "AgIAABoBAAAAAAAAAAAAACQBAAACAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
"WhenOpened": "2026-06-14T06:02:40.854Z"
"DocumentIndex": 5,
"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": "AgIAAC0AAAAAAAAAAAAAABIAAAAKAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-16T13:01:59.743Z"
},
{
"$type": "Document",
"DocumentIndex": 4,
"DocumentIndex": 9,
"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": "AgIAAAAAAAAAAAAAAAAAAA0AAAAUAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-22T18:01:10.082Z"
},
{
"$type": "Document",
"DocumentIndex": 14,
"Title": "Chat.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Chat.razor",
"RelativeDocumentMoniker": "Components\\Pages\\Chat.razor",
@ -236,19 +265,57 @@
},
{
"$type": "Document",
"DocumentIndex": 7,
"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": "AgIAADIAAAAAAAAAAAApwEUAAAByAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:04:36.444Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 6,
"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": "AgIAAEcAAAAAAAAAAAAQwFoAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-05-20T04:07:21.54Z"
},
{
"$type": "Document",
"DocumentIndex": 8,
"Title": "OllamaBackend.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaBackend.cs",
"RelativeDocumentMoniker": "Services\\OllamaBackend.cs",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaBackend.cs",
"RelativeToolTip": "Services\\OllamaBackend.cs",
"ViewState": "AgIAACUAAAAAAAAAAAASwDUAAAAeAAAAAAAAAA==",
"ViewState": "AgIAACkAAAAAAAAAAAAQwEEAAAAMAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-14T05:03:24.305Z"
},
{
"$type": "Document",
"DocumentIndex": 17,
"DocumentIndex": 2,
"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": "AgIAABIAAAAAAAAAAAAAADMAAAAfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:43:26.6Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 23,
"Title": "DbAdminService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\DbAdminService.cs",
"RelativeDocumentMoniker": "Services\\DbAdminService.cs",
@ -260,20 +327,43 @@
},
{
"$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": "AgIAAFAAAAAAAAAAAAAQwGEAAAAZAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:04:36.444Z",
"EditorCaption": ""
"DocumentIndex": 3,
"Title": "AuthorBuddy.Web.csproj",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj",
"RelativeDocumentMoniker": "AuthorBuddy.Web.csproj",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj",
"RelativeToolTip": "AuthorBuddy.Web.csproj",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
"WhenOpened": "2026-05-14T10:14:30.128Z"
},
{
"$type": "Document",
"DocumentIndex": 12,
"DocumentIndex": 7,
"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": "AgIAAK8AAAAAAAAAAAAqwLwAAAAIAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-26T13:33:25.661Z"
},
{
"$type": "Document",
"DocumentIndex": 4,
"Title": "QuickMarkdown.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\QuickMarkdown.razor",
"RelativeDocumentMoniker": "Components\\Pages\\QuickMarkdown.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\QuickMarkdown.razor",
"RelativeToolTip": "Components\\Pages\\QuickMarkdown.razor",
"ViewState": "AgIAACkAAAAAAAAAAAAiwEoAAABfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-07-01T16:53:16.035Z"
},
{
"$type": "Document",
"DocumentIndex": 19,
"Title": "Login.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Login.razor",
"RelativeDocumentMoniker": "Components\\Pages\\Login.razor",
@ -285,7 +375,7 @@
},
{
"$type": "Document",
"DocumentIndex": 13,
"DocumentIndex": 20,
"Title": "FirstRunSetup.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\FirstRunSetup.razor",
"RelativeDocumentMoniker": "Components\\Pages\\FirstRunSetup.razor",
@ -297,7 +387,7 @@
},
{
"$type": "Document",
"DocumentIndex": 3,
"DocumentIndex": 13,
"Title": "SettingsService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\SettingsService.cs",
"RelativeDocumentMoniker": "Services\\SettingsService.cs",
@ -310,79 +400,6 @@
{
"$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": "AgIAAFAAAAAAAAAAAAAQwGMAAAAhAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-05-20T04:07:21.54Z"
},
{
"$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": "AgIAAJsAAAAAAAAAAAAAAKwAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:43:26.6Z"
},
{
"$type": "Document",
"DocumentIndex": 21,
"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": "AgIAAFsCAAAAAAAAAAAiwEgDAAAkAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-16T13:01:59.743Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 6,
"Title": "NavMenu.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor",
"RelativeDocumentMoniker": "Components\\Layout\\NavMenu.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor",
"RelativeToolTip": "Components\\Layout\\NavMenu.razor",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:04:37.739Z"
},
{
"$type": "Document",
"DocumentIndex": 5,
"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": 16,
"Title": "DbAdmin.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\DbAdmin.razor",
"RelativeDocumentMoniker": "Components\\Pages\\DbAdmin.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\DbAdmin.razor",
"RelativeToolTip": "Components\\Pages\\DbAdmin.razor",
"ViewState": "AgIAAFwAAAAAAAAAAAApwKMAAAAcAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-06-10T17:34:42.97Z"
},
{
"$type": "Document",
"DocumentIndex": 9,
"Title": "ChatService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ChatService.cs",
"RelativeDocumentMoniker": "Services\\ChatService.cs",
@ -394,7 +411,67 @@
},
{
"$type": "Document",
"DocumentIndex": 8,
"DocumentIndex": 12,
"Title": "de.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\de.json",
"RelativeDocumentMoniker": "Resources\\de.json",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\de.json",
"RelativeToolTip": "Resources\\de.json",
"ViewState": "AgIAABoBAAAAAAAAAAAAACQBAAACAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
"WhenOpened": "2026-06-14T06:02:40.854Z"
},
{
"$type": "Document",
"DocumentIndex": 11,
"Title": "en.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\en.json",
"RelativeDocumentMoniker": "Resources\\en.json",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\en.json",
"RelativeToolTip": "Resources\\en.json",
"ViewState": "AgIAABQBAAAAAAAAAAAAACQBAAAfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
"WhenOpened": "2026-06-14T06:03:36.064Z"
},
{
"$type": "Document",
"DocumentIndex": 16,
"Title": "NavMenu.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor",
"RelativeDocumentMoniker": "Components\\Layout\\NavMenu.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor",
"RelativeToolTip": "Components\\Layout\\NavMenu.razor",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:04:37.739Z"
},
{
"$type": "Document",
"DocumentIndex": 15,
"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": 22,
"Title": "DbAdmin.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\DbAdmin.razor",
"RelativeDocumentMoniker": "Components\\Pages\\DbAdmin.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\DbAdmin.razor",
"RelativeToolTip": "Components\\Pages\\DbAdmin.razor",
"ViewState": "AgIAAFwAAAAAAAAAAAApwKMAAAAcAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-06-10T17:34:42.97Z"
},
{
"$type": "Document",
"DocumentIndex": 17,
"Title": "ILLMBackend.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ILLMBackend.cs",
"RelativeDocumentMoniker": "Services\\ILLMBackend.cs",
@ -406,7 +483,7 @@
},
{
"$type": "Document",
"DocumentIndex": 11,
"DocumentIndex": 18,
"Title": "UserEntity.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\UserEntity.cs",
"RelativeDocumentMoniker": "Data\\UserEntity.cs",
@ -418,7 +495,7 @@
},
{
"$type": "Document",
"DocumentIndex": 14,
"DocumentIndex": 21,
"Title": "OllamaAssistant.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\OllamaAssistant.razor",
"RelativeDocumentMoniker": "Components\\Pages\\OllamaAssistant.razor",
@ -430,7 +507,7 @@
},
{
"$type": "Document",
"DocumentIndex": 22,
"DocumentIndex": 27,
"Title": "ProjectService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs",
"RelativeDocumentMoniker": "Services\\ProjectService.cs",
@ -442,7 +519,7 @@
},
{
"$type": "Document",
"DocumentIndex": 23,
"DocumentIndex": 28,
"Title": "IOllamaSetupService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaSetupService.cs",
"RelativeDocumentMoniker": "Services\\IOllamaSetupService.cs",
@ -454,7 +531,7 @@
},
{
"$type": "Document",
"DocumentIndex": 18,
"DocumentIndex": 24,
"Title": "SafeFileHandle.Windows.cs",
"DocumentMoniker": "C:\\Users\\HP\\AppData\\Local\\SourceServer\\dddeb33c46e3c746b90c5f64463103c08ec03b9a85e92eab3b21c11218135d28\\src\\runtime\\src\\libraries\\System.Private.CoreLib\\src\\Microsoft\\Win32\\SafeHandles\\SafeFileHandle.Windows.cs",
"ToolTip": "C:\\Users\\HP\\AppData\\Local\\SourceServer\\dddeb33c46e3c746b90c5f64463103c08ec03b9a85e92eab3b21c11218135d28\\src\\runtime\\src\\libraries\\System.Private.CoreLib\\src\\Microsoft\\Win32\\SafeHandles\\SafeFileHandle.Windows.cs [Schreibgesch\u00FCtzt]",
@ -465,7 +542,7 @@
},
{
"$type": "Document",
"DocumentIndex": 19,
"DocumentIndex": 25,
"Title": "A7405018.jpg",
"DocumentMoniker": "C:\\Users\\HP\\Desktop\\Website\\A7405018.jpg",
"ToolTip": "C:\\Users\\HP\\Desktop\\Website\\A7405018.jpg",
@ -474,19 +551,7 @@
},
{
"$type": "Document",
"DocumentIndex": 24,
"Title": "AuthorBuddy.Web.csproj",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj",
"RelativeDocumentMoniker": "AuthorBuddy.Web.csproj",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj",
"RelativeToolTip": "AuthorBuddy.Web.csproj",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
"WhenOpened": "2026-05-14T10:14:30.128Z"
},
{
"$type": "Document",
"DocumentIndex": 25,
"DocumentIndex": 29,
"Title": "INSTALL.md",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\INSTALL.md",
"RelativeDocumentMoniker": "INSTALL.md",
@ -498,7 +563,7 @@
},
{
"$type": "Document",
"DocumentIndex": 26,
"DocumentIndex": 30,
"Title": "IThemeService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IThemeService.cs",
"RelativeDocumentMoniker": "Services\\IThemeService.cs",
@ -510,7 +575,7 @@
},
{
"$type": "Document",
"DocumentIndex": 27,
"DocumentIndex": 31,
"Title": "RedirectToLogin.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\RedirectToLogin.razor",
"RelativeDocumentMoniker": "Components\\RedirectToLogin.razor",
@ -522,7 +587,7 @@
},
{
"$type": "Document",
"DocumentIndex": 28,
"DocumentIndex": 32,
"Title": "ISettingsService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ISettingsService.cs",
"RelativeDocumentMoniker": "Services\\ISettingsService.cs",
@ -534,7 +599,7 @@
},
{
"$type": "Document",
"DocumentIndex": 29,
"DocumentIndex": 33,
"Title": "IRagService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IRagService.cs",
"RelativeDocumentMoniker": "Services\\IRagService.cs",
@ -546,7 +611,7 @@
},
{
"$type": "Document",
"DocumentIndex": 30,
"DocumentIndex": 34,
"Title": "ThemeService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs",
"RelativeDocumentMoniker": "Services\\ThemeService.cs",
@ -558,7 +623,7 @@
},
{
"$type": "Document",
"DocumentIndex": 31,
"DocumentIndex": 35,
"Title": "logo.jpg",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Assets\\logo.jpg",
"RelativeDocumentMoniker": "Assets\\logo.jpg",
@ -569,7 +634,7 @@
},
{
"$type": "Document",
"DocumentIndex": 32,
"DocumentIndex": 36,
"Title": "OllamaSettings.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs",
"RelativeDocumentMoniker": "Models\\OllamaSettings.cs",
@ -581,7 +646,7 @@
},
{
"$type": "Document",
"DocumentIndex": 20,
"DocumentIndex": 26,
"Title": "AppDbContext.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs",
"RelativeDocumentMoniker": "Data\\AppDbContext.cs",
@ -592,7 +657,7 @@
},
{
"$type": "Document",
"DocumentIndex": 33,
"DocumentIndex": 37,
"Title": "FileScannerService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\FileScannerService.cs",
"RelativeDocumentMoniker": "Services\\FileScannerService.cs",
@ -604,7 +669,7 @@
},
{
"$type": "Document",
"DocumentIndex": 34,
"DocumentIndex": 38,
"Title": "TotpHelper.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\TotpHelper.cs",
"RelativeDocumentMoniker": "Services\\TotpHelper.cs",
@ -616,7 +681,7 @@
},
{
"$type": "Document",
"DocumentIndex": 35,
"DocumentIndex": 39,
"Title": "Project.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs",
"RelativeDocumentMoniker": "Models\\Project.cs",
@ -628,7 +693,7 @@
},
{
"$type": "Document",
"DocumentIndex": 36,
"DocumentIndex": 40,
"Title": "RagService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\RagService.cs",
"RelativeDocumentMoniker": "Services\\RagService.cs",
@ -640,7 +705,7 @@
},
{
"$type": "Document",
"DocumentIndex": 37,
"DocumentIndex": 41,
"Title": "App.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor",
"RelativeDocumentMoniker": "Components\\App.razor",
@ -652,7 +717,7 @@
},
{
"$type": "Document",
"DocumentIndex": 38,
"DocumentIndex": 42,
"Title": "Models.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor",
"RelativeDocumentMoniker": "Components\\Pages\\Models.razor",
@ -664,7 +729,7 @@
},
{
"$type": "Document",
"DocumentIndex": 39,
"DocumentIndex": 43,
"Title": "LLM_Model.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs",
"RelativeDocumentMoniker": "Models\\LLM_Model.cs",
@ -676,7 +741,7 @@
},
{
"$type": "Document",
"DocumentIndex": 40,
"DocumentIndex": 44,
"Title": "ModelStatus.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs",
"RelativeDocumentMoniker": "Models\\ModelStatus.cs",
@ -688,7 +753,7 @@
},
{
"$type": "Document",
"DocumentIndex": 41,
"DocumentIndex": 45,
"Title": "IFileScannerService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IFileScannerService.cs",
"RelativeDocumentMoniker": "Services\\IFileScannerService.cs",
@ -700,7 +765,7 @@
},
{
"$type": "Document",
"DocumentIndex": 42,
"DocumentIndex": 46,
"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",
@ -712,7 +777,7 @@
},
{
"$type": "Document",
"DocumentIndex": 43,
"DocumentIndex": 47,
"Title": "ProjectEntity.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\ProjectEntity.cs",
"RelativeDocumentMoniker": "Data\\ProjectEntity.cs",
@ -724,7 +789,7 @@
},
{
"$type": "Document",
"DocumentIndex": 44,
"DocumentIndex": 48,
"Title": "IProjectService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IProjectService.cs",
"RelativeDocumentMoniker": "Services\\IProjectService.cs",
@ -736,7 +801,7 @@
},
{
"$type": "Document",
"DocumentIndex": 45,
"DocumentIndex": 49,
"Title": "appsettings.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\appsettings.json",
"RelativeDocumentMoniker": "appsettings.json",

View file

@ -6,6 +6,46 @@
"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\\wwwroot\\app.css||{A5401142-F49D-43DB-90B1-F57BA349E55C}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:wwwroot\\app.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\\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\\authorbuddy.web.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:authorbuddy.web.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
},
{
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\quickmarkdown.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\quickmarkdown.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\\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\\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\\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\\ollamabackend.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ollamabackend.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\\services\\chatservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\chatservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\resources\\en.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:resources\\en.json||{90A6B3A7-C1A3-4009-A288-E2FF89E96FA0}"
@ -30,22 +70,10 @@
"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\\services\\ollamabackend.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\ollamabackend.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\\illmbackend.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\illmbackend.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\\chatservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\chatservice.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\\data\\userentity.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:data\\userentity.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
@ -62,10 +90,6 @@
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\components\\pages\\ollamaassistant.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\ollamaassistant.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\\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\\pages\\dbadmin.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:components\\pages\\dbadmin.razor||{40D31677-CBC0-4297-A9EF-89D907823A98}"
@ -84,10 +108,6 @@
"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\\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\\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}"
@ -96,10 +116,6 @@
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\services\\iollamasetupservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:services\\iollamasetupservice.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
},
{
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\authorbuddy.web.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:authorbuddy.web.csproj||{FA3CD31E-987B-443A-9B81-186104E8DAC1}"
},
{
"AbsoluteMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|e:\\ollama_net\\ollama\\authorbuddy.web\\install.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
"RelativeMoniker": "D:0:0:{4F4697EF-EFFA-26AC-C8A1-C9859805D247}|AuthorBuddy.Web.csproj|solutionrelative:install.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
@ -192,7 +208,7 @@
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 6,
"SelectedChildIndex": 5,
"Children": [
{
"$type": "Bookmark",
@ -201,30 +217,43 @@
{
"$type": "Document",
"DocumentIndex": 1,
"Title": "en.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\en.json",
"RelativeDocumentMoniker": "Resources\\en.json",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\en.json",
"RelativeToolTip": "Resources\\en.json",
"ViewState": "AgIAABQBAAAAAAAAAAAAACQBAAAfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
"WhenOpened": "2026-06-14T06:03:36.064Z"
"Title": "app.css",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\wwwroot\\app.css",
"RelativeDocumentMoniker": "wwwroot\\app.css",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\wwwroot\\app.css",
"RelativeToolTip": "wwwroot\\app.css",
"ViewState": "AgIAAJYCAAAAAAAAAAAiwKoCAAAJAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003000|",
"WhenOpened": "2026-07-04T08:22:21.143Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 2,
"Title": "de.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\de.json",
"RelativeDocumentMoniker": "Resources\\de.json",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\de.json",
"RelativeToolTip": "Resources\\de.json",
"ViewState": "AgIAABoBAAAAAAAAAAAAACQBAAACAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
"WhenOpened": "2026-06-14T06:02:40.854Z"
"DocumentIndex": 5,
"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": "AgIAAC0AAAAAAAAAAAAAABIAAAAKAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-16T13:01:59.743Z"
},
{
"$type": "Document",
"DocumentIndex": 4,
"DocumentIndex": 9,
"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": "AgIAAAAAAAAAAAAAAAAAAA0AAAAUAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-22T18:01:10.082Z"
},
{
"$type": "Document",
"DocumentIndex": 14,
"Title": "Chat.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Chat.razor",
"RelativeDocumentMoniker": "Components\\Pages\\Chat.razor",
@ -236,19 +265,57 @@
},
{
"$type": "Document",
"DocumentIndex": 7,
"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": "AgIAADIAAAAAAAAAAAApwEUAAAByAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:04:36.444Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 6,
"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": "AgIAAEcAAAAAAAAAAAAQwFoAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-05-20T04:07:21.54Z"
},
{
"$type": "Document",
"DocumentIndex": 8,
"Title": "OllamaBackend.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaBackend.cs",
"RelativeDocumentMoniker": "Services\\OllamaBackend.cs",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\OllamaBackend.cs",
"RelativeToolTip": "Services\\OllamaBackend.cs",
"ViewState": "AgIAACUAAAAAAAAAAAASwDUAAAAeAAAAAAAAAA==",
"ViewState": "AgIAACkAAAAAAAAAAAAQwEEAAAAMAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-14T05:03:24.305Z"
},
{
"$type": "Document",
"DocumentIndex": 17,
"DocumentIndex": 2,
"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": "AgIAABIAAAAAAAAAAAAAADMAAAAfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:43:26.6Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 23,
"Title": "DbAdminService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\DbAdminService.cs",
"RelativeDocumentMoniker": "Services\\DbAdminService.cs",
@ -260,20 +327,43 @@
},
{
"$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": "AgIAAFAAAAAAAAAAAAAQwFUAAAApAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:04:36.444Z",
"EditorCaption": ""
"DocumentIndex": 3,
"Title": "AuthorBuddy.Web.csproj",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj",
"RelativeDocumentMoniker": "AuthorBuddy.Web.csproj",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj",
"RelativeToolTip": "AuthorBuddy.Web.csproj",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
"WhenOpened": "2026-05-14T10:14:30.128Z"
},
{
"$type": "Document",
"DocumentIndex": 12,
"DocumentIndex": 7,
"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": "AgIAAK8AAAAAAAAAAAAqwLwAAAAIAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-06-26T13:33:25.661Z"
},
{
"$type": "Document",
"DocumentIndex": 4,
"Title": "QuickMarkdown.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\QuickMarkdown.razor",
"RelativeDocumentMoniker": "Components\\Pages\\QuickMarkdown.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\QuickMarkdown.razor",
"RelativeToolTip": "Components\\Pages\\QuickMarkdown.razor",
"ViewState": "AgIAACkAAAAAAAAAAAAiwEoAAABfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-07-01T16:53:16.035Z"
},
{
"$type": "Document",
"DocumentIndex": 19,
"Title": "Login.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Login.razor",
"RelativeDocumentMoniker": "Components\\Pages\\Login.razor",
@ -285,7 +375,7 @@
},
{
"$type": "Document",
"DocumentIndex": 13,
"DocumentIndex": 20,
"Title": "FirstRunSetup.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\FirstRunSetup.razor",
"RelativeDocumentMoniker": "Components\\Pages\\FirstRunSetup.razor",
@ -297,7 +387,7 @@
},
{
"$type": "Document",
"DocumentIndex": 3,
"DocumentIndex": 13,
"Title": "SettingsService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\SettingsService.cs",
"RelativeDocumentMoniker": "Services\\SettingsService.cs",
@ -310,79 +400,6 @@
{
"$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": "AgIAAFAAAAAAAAAAAAAQwGMAAAAhAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-05-20T04:07:21.54Z"
},
{
"$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": "AgIAAJsAAAAAAAAAAAAAAKwAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:43:26.6Z"
},
{
"$type": "Document",
"DocumentIndex": 21,
"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": "AgIAAFsCAAAAAAAAAAAiwEgDAAAkAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-16T13:01:59.743Z",
"EditorCaption": ""
},
{
"$type": "Document",
"DocumentIndex": 6,
"Title": "NavMenu.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor",
"RelativeDocumentMoniker": "Components\\Layout\\NavMenu.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor",
"RelativeToolTip": "Components\\Layout\\NavMenu.razor",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:04:37.739Z"
},
{
"$type": "Document",
"DocumentIndex": 5,
"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": 16,
"Title": "DbAdmin.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\DbAdmin.razor",
"RelativeDocumentMoniker": "Components\\Pages\\DbAdmin.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\DbAdmin.razor",
"RelativeToolTip": "Components\\Pages\\DbAdmin.razor",
"ViewState": "AgIAAFwAAAAAAAAAAAApwKMAAAAcAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-06-10T17:34:42.97Z"
},
{
"$type": "Document",
"DocumentIndex": 9,
"Title": "ChatService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ChatService.cs",
"RelativeDocumentMoniker": "Services\\ChatService.cs",
@ -394,7 +411,67 @@
},
{
"$type": "Document",
"DocumentIndex": 8,
"DocumentIndex": 12,
"Title": "de.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\de.json",
"RelativeDocumentMoniker": "Resources\\de.json",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\de.json",
"RelativeToolTip": "Resources\\de.json",
"ViewState": "AgIAABoBAAAAAAAAAAAAACQBAAACAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
"WhenOpened": "2026-06-14T06:02:40.854Z"
},
{
"$type": "Document",
"DocumentIndex": 11,
"Title": "en.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\en.json",
"RelativeDocumentMoniker": "Resources\\en.json",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Resources\\en.json",
"RelativeToolTip": "Resources\\en.json",
"ViewState": "AgIAABQBAAAAAAAAAAAAACQBAAAfAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|",
"WhenOpened": "2026-06-14T06:03:36.064Z"
},
{
"$type": "Document",
"DocumentIndex": 16,
"Title": "NavMenu.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor",
"RelativeDocumentMoniker": "Components\\Layout\\NavMenu.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Layout\\NavMenu.razor",
"RelativeToolTip": "Components\\Layout\\NavMenu.razor",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-05-15T16:04:37.739Z"
},
{
"$type": "Document",
"DocumentIndex": 15,
"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": 22,
"Title": "DbAdmin.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\DbAdmin.razor",
"RelativeDocumentMoniker": "Components\\Pages\\DbAdmin.razor",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\DbAdmin.razor",
"RelativeToolTip": "Components\\Pages\\DbAdmin.razor",
"ViewState": "AgIAAFwAAAAAAAAAAAApwKMAAAAcAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000759|",
"WhenOpened": "2026-06-10T17:34:42.97Z"
},
{
"$type": "Document",
"DocumentIndex": 17,
"Title": "ILLMBackend.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ILLMBackend.cs",
"RelativeDocumentMoniker": "Services\\ILLMBackend.cs",
@ -406,7 +483,7 @@
},
{
"$type": "Document",
"DocumentIndex": 11,
"DocumentIndex": 18,
"Title": "UserEntity.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\UserEntity.cs",
"RelativeDocumentMoniker": "Data\\UserEntity.cs",
@ -418,7 +495,7 @@
},
{
"$type": "Document",
"DocumentIndex": 14,
"DocumentIndex": 21,
"Title": "OllamaAssistant.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\OllamaAssistant.razor",
"RelativeDocumentMoniker": "Components\\Pages\\OllamaAssistant.razor",
@ -430,7 +507,7 @@
},
{
"$type": "Document",
"DocumentIndex": 22,
"DocumentIndex": 27,
"Title": "ProjectService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ProjectService.cs",
"RelativeDocumentMoniker": "Services\\ProjectService.cs",
@ -442,7 +519,7 @@
},
{
"$type": "Document",
"DocumentIndex": 23,
"DocumentIndex": 28,
"Title": "IOllamaSetupService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IOllamaSetupService.cs",
"RelativeDocumentMoniker": "Services\\IOllamaSetupService.cs",
@ -454,7 +531,7 @@
},
{
"$type": "Document",
"DocumentIndex": 18,
"DocumentIndex": 24,
"Title": "SafeFileHandle.Windows.cs",
"DocumentMoniker": "C:\\Users\\HP\\AppData\\Local\\SourceServer\\dddeb33c46e3c746b90c5f64463103c08ec03b9a85e92eab3b21c11218135d28\\src\\runtime\\src\\libraries\\System.Private.CoreLib\\src\\Microsoft\\Win32\\SafeHandles\\SafeFileHandle.Windows.cs",
"ToolTip": "C:\\Users\\HP\\AppData\\Local\\SourceServer\\dddeb33c46e3c746b90c5f64463103c08ec03b9a85e92eab3b21c11218135d28\\src\\runtime\\src\\libraries\\System.Private.CoreLib\\src\\Microsoft\\Win32\\SafeHandles\\SafeFileHandle.Windows.cs [Schreibgesch\u00FCtzt]",
@ -465,7 +542,7 @@
},
{
"$type": "Document",
"DocumentIndex": 19,
"DocumentIndex": 25,
"Title": "A7405018.jpg",
"DocumentMoniker": "C:\\Users\\HP\\Desktop\\Website\\A7405018.jpg",
"ToolTip": "C:\\Users\\HP\\Desktop\\Website\\A7405018.jpg",
@ -474,19 +551,7 @@
},
{
"$type": "Document",
"DocumentIndex": 24,
"Title": "AuthorBuddy.Web.csproj",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj",
"RelativeDocumentMoniker": "AuthorBuddy.Web.csproj",
"ToolTip": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\AuthorBuddy.Web.csproj",
"RelativeToolTip": "AuthorBuddy.Web.csproj",
"ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000758|",
"WhenOpened": "2026-05-14T10:14:30.128Z"
},
{
"$type": "Document",
"DocumentIndex": 25,
"DocumentIndex": 29,
"Title": "INSTALL.md",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\INSTALL.md",
"RelativeDocumentMoniker": "INSTALL.md",
@ -498,7 +563,7 @@
},
{
"$type": "Document",
"DocumentIndex": 26,
"DocumentIndex": 30,
"Title": "IThemeService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IThemeService.cs",
"RelativeDocumentMoniker": "Services\\IThemeService.cs",
@ -510,7 +575,7 @@
},
{
"$type": "Document",
"DocumentIndex": 27,
"DocumentIndex": 31,
"Title": "RedirectToLogin.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\RedirectToLogin.razor",
"RelativeDocumentMoniker": "Components\\RedirectToLogin.razor",
@ -522,7 +587,7 @@
},
{
"$type": "Document",
"DocumentIndex": 28,
"DocumentIndex": 32,
"Title": "ISettingsService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ISettingsService.cs",
"RelativeDocumentMoniker": "Services\\ISettingsService.cs",
@ -534,7 +599,7 @@
},
{
"$type": "Document",
"DocumentIndex": 29,
"DocumentIndex": 33,
"Title": "IRagService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IRagService.cs",
"RelativeDocumentMoniker": "Services\\IRagService.cs",
@ -546,7 +611,7 @@
},
{
"$type": "Document",
"DocumentIndex": 30,
"DocumentIndex": 34,
"Title": "ThemeService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\ThemeService.cs",
"RelativeDocumentMoniker": "Services\\ThemeService.cs",
@ -558,7 +623,7 @@
},
{
"$type": "Document",
"DocumentIndex": 31,
"DocumentIndex": 35,
"Title": "logo.jpg",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Assets\\logo.jpg",
"RelativeDocumentMoniker": "Assets\\logo.jpg",
@ -569,7 +634,7 @@
},
{
"$type": "Document",
"DocumentIndex": 32,
"DocumentIndex": 36,
"Title": "OllamaSettings.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\OllamaSettings.cs",
"RelativeDocumentMoniker": "Models\\OllamaSettings.cs",
@ -581,7 +646,7 @@
},
{
"$type": "Document",
"DocumentIndex": 20,
"DocumentIndex": 26,
"Title": "AppDbContext.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\AppDbContext.cs",
"RelativeDocumentMoniker": "Data\\AppDbContext.cs",
@ -592,7 +657,7 @@
},
{
"$type": "Document",
"DocumentIndex": 33,
"DocumentIndex": 37,
"Title": "FileScannerService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\FileScannerService.cs",
"RelativeDocumentMoniker": "Services\\FileScannerService.cs",
@ -604,7 +669,7 @@
},
{
"$type": "Document",
"DocumentIndex": 34,
"DocumentIndex": 38,
"Title": "TotpHelper.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\TotpHelper.cs",
"RelativeDocumentMoniker": "Services\\TotpHelper.cs",
@ -616,7 +681,7 @@
},
{
"$type": "Document",
"DocumentIndex": 35,
"DocumentIndex": 39,
"Title": "Project.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\Project.cs",
"RelativeDocumentMoniker": "Models\\Project.cs",
@ -628,7 +693,7 @@
},
{
"$type": "Document",
"DocumentIndex": 36,
"DocumentIndex": 40,
"Title": "RagService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\RagService.cs",
"RelativeDocumentMoniker": "Services\\RagService.cs",
@ -640,7 +705,7 @@
},
{
"$type": "Document",
"DocumentIndex": 37,
"DocumentIndex": 41,
"Title": "App.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\App.razor",
"RelativeDocumentMoniker": "Components\\App.razor",
@ -652,7 +717,7 @@
},
{
"$type": "Document",
"DocumentIndex": 38,
"DocumentIndex": 42,
"Title": "Models.razor",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Components\\Pages\\Models.razor",
"RelativeDocumentMoniker": "Components\\Pages\\Models.razor",
@ -664,7 +729,7 @@
},
{
"$type": "Document",
"DocumentIndex": 39,
"DocumentIndex": 43,
"Title": "LLM_Model.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\LLM_Model.cs",
"RelativeDocumentMoniker": "Models\\LLM_Model.cs",
@ -676,7 +741,7 @@
},
{
"$type": "Document",
"DocumentIndex": 40,
"DocumentIndex": 44,
"Title": "ModelStatus.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Models\\ModelStatus.cs",
"RelativeDocumentMoniker": "Models\\ModelStatus.cs",
@ -688,7 +753,7 @@
},
{
"$type": "Document",
"DocumentIndex": 41,
"DocumentIndex": 45,
"Title": "IFileScannerService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IFileScannerService.cs",
"RelativeDocumentMoniker": "Services\\IFileScannerService.cs",
@ -700,7 +765,7 @@
},
{
"$type": "Document",
"DocumentIndex": 42,
"DocumentIndex": 46,
"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",
@ -712,7 +777,7 @@
},
{
"$type": "Document",
"DocumentIndex": 43,
"DocumentIndex": 47,
"Title": "ProjectEntity.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Data\\ProjectEntity.cs",
"RelativeDocumentMoniker": "Data\\ProjectEntity.cs",
@ -724,7 +789,7 @@
},
{
"$type": "Document",
"DocumentIndex": 44,
"DocumentIndex": 48,
"Title": "IProjectService.cs",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\Services\\IProjectService.cs",
"RelativeDocumentMoniker": "Services\\IProjectService.cs",
@ -736,7 +801,7 @@
},
{
"$type": "Document",
"DocumentIndex": 45,
"DocumentIndex": 49,
"Title": "appsettings.json",
"DocumentMoniker": "E:\\ollama_net\\ollama\\AuthorBuddy.Web\\appsettings.json",
"RelativeDocumentMoniker": "appsettings.json",

View file

@ -68,7 +68,6 @@ else
<div class="nav-separator"></div>
<button class="nav-item" @onclick='() => NavigateTo("/user-management")'>@Loc["nav.menu.extras.user_management"]</button>
<button class="nav-item" @onclick='() => NavigateTo("/db-admin")'>📊 DB-Admin</button>
<button class="nav-item" @onclick='() => NavigateTo("/chat")'>💬 Chat</button>
}
else
{
@ -297,7 +296,7 @@ else
</div>
<div class="modal-actions">
<button @onclick="CancelCopyProject">@Loc["common.cancel"]</button>
<button @onclick="ConfirmCopyProject" disabled="@(string.IsNullOrWhiteSpace(copyProjectName) || string.IsNullOrWhiteSpace(copyProjectPath))" class="primary">@Loc["nav.copy_project.button.copy"]</button>
<button @onclick="ConfirmCopyProject" disabled="@_copyProjectDisabled" class="primary">@Loc["nav.copy_project.button.copy"]</button>
</div>
</div>
</div>
@ -444,6 +443,7 @@ else
private string? currentFilePath;
private string copyProjectName = string.Empty;
private string copyProjectPath = string.Empty;
private bool _copyProjectDisabled => string.IsNullOrWhiteSpace(copyProjectName) || string.IsNullOrWhiteSpace(copyProjectPath);
private Project? copyProjectSource;
private bool showRenameDialog;
private string renameNewName = string.Empty;

View file

@ -6,6 +6,7 @@
@inject ISettingsService SettingsService
@inject IAuthService AuthService
@inject NavigationManager Navigation
@inject IJSRuntime JS
@rendermode InteractiveServer
@ -31,7 +32,7 @@
</div>
<div class="form-group">
<label for="chatTemp">Temperatur: @_temperature.ToString("F2")</label>
<input id="chatTemp" type="range" min="0" max="2" step="0.05" @bind="_temperature" />
<input id="chatTemp" type="range" min="0" max="2" step="0.05" @bind="_temperature" @bind:event="oninput" />
<div class="qm-range-labels">
<span>präzise (0)</span>
<span>kreativ (2)</span>
@ -70,11 +71,11 @@
</div>
<div class="chat-input">
<textarea class="chat-textarea" @bind="_input" rows="3"
placeholder="Nachricht eingeben…"
@onkeydown="HandleKeyDown"
disabled="@_isBusy"></textarea>
<button class="btn btn-primary" @onclick="Send" disabled="@(_isBusy || string.IsNullOrWhiteSpace(_input))">
<textarea class="chat-textarea" @bind="_input" @bind:event="oninput" rows="3"
placeholder="Nachricht eingeben…"
@onkeydown="HandleKeyDown"
disabled="@_isBusy"></textarea>
<button class="btn btn-primary" @onclick="Send" disabled="@_sendDisabled">
Senden
</button>
</div>
@ -92,8 +93,10 @@
private bool _isBusy;
private int _userId;
private bool _showSettings;
private bool _sendDisabled => _isBusy || string.IsNullOrWhiteSpace(_input);
private string _systemPrompt = string.Empty;
private double _temperature = 0.7;
private bool _needsScroll;
protected override async Task OnInitializedAsync()
{
@ -108,6 +111,16 @@
_systemPrompt = await SettingsService.GetChatPromptAsync()
?? Settings.GetChatDefaultPrompt(Settings.Language);
_temperature = await SettingsService.GetChatTempAsync();
_needsScroll = true;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (_needsScroll)
{
_needsScroll = false;
await ScrollToBottom();
}
}
private void ToggleSettings()
@ -144,6 +157,7 @@
_input = string.Empty;
_error = string.Empty;
_isBusy = true;
_needsScroll = true;
try
{
@ -159,6 +173,7 @@
};
await ChatService.AddMessageAsync(msg);
_messages.Add(msg);
_needsScroll = true;
}
catch (Exception ex)
{
@ -167,6 +182,8 @@
finally
{
_isBusy = false;
_input = string.Empty;
_needsScroll = true;
}
}
@ -176,6 +193,11 @@
_messages.Clear();
}
private async Task ScrollToBottom()
{
await JS.InvokeVoidAsync("eval", "document.getElementById('chat-messages').scrollTop = document.getElementById('chat-messages').scrollHeight");
}
private MarkupString MarkdownToHtml(string text)
{
if (string.IsNullOrEmpty(text)) return new MarkupString(string.Empty);

View file

@ -189,7 +189,7 @@
? Loc["editor.wikipedia.status.loaded"]
: Loc["editor.wikipedia.button.load"])
</button>
<button @onclick="() => SaveAsFact(r)" disabled="@(string.IsNullOrWhiteSpace(r.Extract) || currentProjectId == 0)">
<button @onclick="() => SaveAsFact(r)" disabled="@IsSaveFactDisabled(r)">
@Loc["editor.wikipedia.button.save_as_fact"]
</button>
</div>
@ -238,7 +238,7 @@
</div>
<div class="modal-actions">
<button @onclick="CancelCreateProject">@Loc["common.cancel"]</button>
<button @onclick="CreateProject" disabled="@(() => string.IsNullOrWhiteSpace(newProjectName) || string.IsNullOrWhiteSpace(newProjectPath))" class="primary">@Loc["editor.button.create"]</button>
<button @onclick="CreateProject" disabled="@_createProjectDisabled" class="primary">@Loc["editor.button.create"]</button>
</div>
</div>
</div>
@ -270,6 +270,7 @@
private bool showCreateDialog;
private string newProjectName = string.Empty;
private string newProjectPath = string.Empty;
private bool _createProjectDisabled => string.IsNullOrWhiteSpace(newProjectName) || string.IsNullOrWhiteSpace(newProjectPath);
private ProjectTemplate selectedTemplate = ProjectTemplate.Novel;
private Dictionary<string, bool> loadedArticles = new();
private bool showVersionDialog;
@ -594,6 +595,8 @@
}
}
private bool IsSaveFactDisabled(WikipediaResult r) => string.IsNullOrWhiteSpace(r.Extract) || currentProjectId == 0;
private async Task SaveAsFact(WikipediaResult result)
{
if (string.IsNullOrWhiteSpace(result.Extract) || currentProjectId == 0) return;

View file

@ -23,7 +23,7 @@
<input id="adminUsername" @bind="_username" disabled="@_isBusy" />
</div>
<button @onclick="GeneratePassword" disabled="@(() => _isBusy || string.IsNullOrWhiteSpace(_username))">Passwort generieren</button>
<button @onclick="GeneratePassword" disabled="@_generateDisabled">Passwort generieren</button>
@if (!string.IsNullOrEmpty(_generatedPassword))
{
@ -41,7 +41,7 @@
<input id="adminPassword" type="password" @bind="_password" />
</div>
<button @onclick="CreateAdmin" disabled="@(() => _isBusy || _password != _generatedPassword)">Admin erstellen</button>
<button @onclick="CreateAdmin" disabled="@_createAdminDisabled">Admin erstellen</button>
}
}
else
@ -66,6 +66,8 @@
private string _errorMessage = string.Empty;
private bool _isBusy;
private bool _setupComplete;
private bool _generateDisabled => _isBusy || string.IsNullOrWhiteSpace(_username);
private bool _createAdminDisabled => _isBusy || _password != _generatedPassword;
protected override async Task OnInitializedAsync()
{

View file

@ -26,10 +26,17 @@ else
@foreach (var model in localModels)
{
<div class="model-card">
<div class="model-name">@model.Name</div>
<div class="model-details">
@Loc["models.label.size"] @FormatSize(model.Size) |
@Loc["models.label.modified"] @model.ModifiedAt?.ToString("g")
<div style="display:flex;justify-content:space-between;align-items:flex-start;">
<div>
<div class="model-name">@model.Name</div>
<div class="model-details">
@Loc["models.label.size"] @FormatSize(model.Size) |
@Loc["models.label.modified"] @model.ModifiedAt?.ToString("g")
</div>
</div>
<button class="btn-sm" @onclick="() => DeleteModel(model.Name)" style="color:#c0392b;flex-shrink:0;">
Löschen
</button>
</div>
</div>
}
@ -41,9 +48,9 @@ else
<div style="display: flex; gap: 8px; align-items: flex-end;">
<div class="form-group" style="flex: 1; margin-bottom: 0;">
<label for="pullModelName">@Loc["models.pull.label.name"]</label>
<input id="pullModelName" @bind="modelToPull" placeholder="@Loc["models.pull.placeholder"]" />
<input id="pullModelName" @bind="modelToPull" @bind:event="oninput" placeholder="@Loc["models.pull.placeholder"]" />
</div>
<button @onclick="PullModel" disabled="@(isPulling || string.IsNullOrWhiteSpace(modelToPull))">
<button @onclick="PullModel" disabled="@_pullDisabled">
@Loc["models.pull.button.download"]
</button>
</div>
@ -65,16 +72,34 @@ else
</div>
}
@if (_confirmDeleteModel != null)
{
<div class="modal-overlay">
<div class="modal-dialog modal-sm">
<div class="modal-title">Modell löschen</div>
<div class="modal-body">
<p>Soll das Modell <strong>@_confirmDeleteModel</strong> wirklich gelöscht werden?</p>
</div>
<div class="modal-actions">
<button @onclick="CancelDelete">Abbrechen</button>
<button @onclick="ConfirmDelete" class="btn-danger">Löschen</button>
</div>
</div>
</div>
}
@code {
private List<LLM_Model> localModels = new();
private bool isLoading;
private string? errorMessage;
private string modelToPull = string.Empty;
private bool isPulling;
private bool _pullDisabled => isPulling || string.IsNullOrWhiteSpace(modelToPull);
private double pullProgress;
private string pullStatus = string.Empty;
private string? pullResult;
private string pullPercentDisplay => $"{pullProgress:F0}%";
private string? _confirmDeleteModel;
protected override async Task OnInitializedAsync()
{
@ -116,6 +141,9 @@ else
var progress = new Progress<string>(status =>
{
pullStatus = status;
var m = System.Text.RegularExpressions.Regex.Match(status, @"\((\d+)%\)");
if (m.Success && double.TryParse(m.Groups[1].Value, out var pct))
pullProgress = pct;
InvokeAsync(StateHasChanged);
});
@ -134,6 +162,38 @@ else
}
}
private void DeleteModel(string name)
{
_confirmDeleteModel = name;
}
private void CancelDelete()
{
_confirmDeleteModel = null;
}
private async Task ConfirmDelete()
{
if (_confirmDeleteModel == null) return;
try
{
var deleted = await OllamaService.DeleteModelAsync(_confirmDeleteModel);
if (deleted)
await RefreshModels();
else
errorMessage = $"Fehler beim Löschen von '{_confirmDeleteModel}'";
}
catch (Exception ex)
{
errorMessage = $"Fehler: {ex.Message}";
}
finally
{
_confirmDeleteModel = null;
}
}
private static string FormatSize(long? bytes)
{
if (!bytes.HasValue) return "---";

View file

@ -31,7 +31,7 @@
<option value="tech_risiko">@Loc["assistant.mode.tech_risiko"]</option>
}
</select>
<button @onclick="RunAssistant" disabled="@(() => isRunning || string.IsNullOrWhiteSpace(inputText))">@Loc["assistant.button.execute"]</button>
<button @onclick="RunAssistant" disabled="@_runDisabled">@Loc["assistant.button.execute"]</button>
@if (!string.IsNullOrEmpty(outputText))
{
<button @onclick="SendToEditor" class="primary">@Loc["assistant.button.send_to_editor"]</button>
@ -95,6 +95,7 @@
private string errorMessage = string.Empty;
private string statusText = string.Empty;
private bool isRunning;
private bool _runDisabled => isRunning || string.IsNullOrWhiteSpace(inputText);
private double progress;
private bool showPromptEditor;
private string promptOverride = string.Empty;

View file

@ -5,6 +5,7 @@
@inject IJSRuntime JS
@inject IAuthService AuthService
@inject ISettingsService SettingsService
@inject IQuickMarkdownService QuickMarkdownService
@inject NavigationManager Navigation
@rendermode InteractiveServer
@ -17,6 +18,30 @@
<div class="qm-layout">
<div class="qm-input-panel">
<div class="form-group">
<label>Prompt-Verwaltung</label>
<div class="qm-prompt-selector">
<select class="qm-prompt-select" value="@_selectedPromptId" @onchange="SwitchPrompt">
<option value="0">— Standard-Prompt —</option>
@foreach (var p in _savedPrompts)
{
<option value="@p.Id">@p.Name</option>
}
</select>
<button class="btn btn-sm" @onclick="ShowSavePromptDialog">+ Als Prompt speichern</button>
<button class="btn btn-sm" @onclick="DeleteCurrentPrompt" disabled="@(_selectedPromptId == 0)">Löschen</button>
</div>
@if (_showPromptNameInput)
{
<div class="qm-prompt-name-row">
<input @bind="_newPromptName" placeholder="Name für den Prompt…" />
<button class="btn btn-sm btn-primary" @onclick="ConfirmSavePrompt">Speichern</button>
<button class="btn btn-sm" @onclick="CancelSavePrompt">Abbrechen</button>
</div>
}
</div>
<div class="form-group">
<label>System-Prompt</label>
<textarea class="qm-textarea qm-prompt" @bind="_systemPrompt" rows="4"></textarea>
@ -31,28 +56,26 @@
</div>
</div>
<div class="form-group">
<div class="qm-prompt-actions">
<button class="btn btn-secondary" @onclick="SaveSettings">System-Prompt & Temperatur speichern</button>
<button class="btn btn-secondary" @onclick="ResetToDefault">Auf Standard zurücksetzen</button>
</div>
</div>
<div class="form-group">
<label>Text</label>
<textarea class="qm-textarea" @bind="_inputText" rows="12" placeholder="Text hier eingeben…"></textarea>
<textarea class="qm-textarea" @bind="_inputText" @bind:event="oninput" rows="12" placeholder="Text hier eingeben…"></textarea>
</div>
<button class="btn btn-primary" @onclick="Generate" disabled="@_isBusy || string.IsNullOrWhiteSpace(_inputText)">
@if (_isBusy)
{
<span>Generiere…</span>
}
else
{
<span>Markdown erzeugen</span>
}
</button>
<div class="qm-generate-row">
<button class="btn btn-primary" @onclick="Generate" disabled="@_generateDisabled">
@if (_isBusy)
{
<span>Generiere…</span>
}
else
{
<span>Markdown erzeugen</span>
}
</button>
<button class="btn btn-sm" @onclick="SaveEntry" disabled="@_saveEntryDisabled">
Eingabe & Ergebnis speichern
</button>
</div>
</div>
<div class="qm-output-panel">
@ -63,10 +86,27 @@
<button class="btn btn-small" @onclick="ClearOutput">🗑 Leeren</button>
</div>
</div>
<textarea class="qm-textarea qm-output" @bind="_output" rows="20" readonly></textarea>
<textarea class="qm-textarea qm-output" @bind="_output" rows="30" readonly></textarea>
</div>
</div>
@if (_savedEntries.Count > 0)
{
<div class="qm-saved-list">
<h4>Gespeicherte Texte</h4>
@foreach (var e in _savedEntries)
{
<div class="qm-saved-item" @onclick="() => LoadEntry(e.Id)">
<div class="qm-saved-meta">
<span class="qm-saved-date">@e.Timestamp.ToLocalTime().ToString("g")</span>
<span class="qm-saved-preview">@(e.InputText.Length > 60 ? e.InputText[..60] + "…" : e.InputText)</span>
</div>
<button class="btn btn-sm" @onclick="() => DeleteEntry(e.Id)" title="Löschen">🗑</button>
</div>
}
</div>
}
@if (!string.IsNullOrEmpty(_error))
{
<div class="auth-error">@_error</div>
@ -85,7 +125,15 @@
private string _error = string.Empty;
private string _modelNotice = string.Empty;
private bool _isBusy;
private bool _generateDisabled => _isBusy || string.IsNullOrWhiteSpace(_inputText);
private bool _saveEntryDisabled => string.IsNullOrWhiteSpace(_inputText) && string.IsNullOrWhiteSpace(_output);
private double _temperature = 0.3;
private int _userId;
private List<QuickMarkdownEntry> _savedEntries = new();
private List<QuickMarkdownPrompt> _savedPrompts = new();
private int _selectedPromptId;
private bool _showPromptNameInput;
private string _newPromptName = string.Empty;
protected override async Task OnInitializedAsync()
{
@ -95,25 +143,132 @@
Navigation.NavigateTo("/");
return;
}
_userId = user.Id;
_savedPrompts = await QuickMarkdownService.GetPromptsAsync(_userId);
_systemPrompt = await SettingsService.GetQuickMarkdownPromptAsync()
?? Settings.GetQuickMarkdownDefaultPrompt(Settings.Language);
_temperature = await SettingsService.GetQuickMarkdownTempAsync();
_savedEntries = await QuickMarkdownService.GetAllAsync(_userId);
_modelNotice = $"Verwendetes Modell: {Settings.StyleModel} (via {Settings.Backend})";
}
private async Task SaveSettings()
private async Task SwitchPrompt(ChangeEventArgs e)
{
await SettingsService.SaveQuickMarkdownPromptAsync(_systemPrompt);
await SettingsService.SaveQuickMarkdownTempAsync(_temperature);
var id = int.Parse(e.Value?.ToString() ?? "0");
_selectedPromptId = id;
if (id == 0)
{
_systemPrompt = Settings.GetQuickMarkdownDefaultPrompt(Settings.Language);
_temperature = Settings.QuickMarkdownTemp;
}
else
{
var prompt = _savedPrompts.FirstOrDefault(p => p.Id == id);
if (prompt != null)
{
_systemPrompt = prompt.PromptText;
_temperature = prompt.Temperature;
}
}
}
private async Task ResetToDefault()
private void ShowSavePromptDialog()
{
_newPromptName = string.Empty;
_showPromptNameInput = true;
}
private async Task ConfirmSavePrompt()
{
if (string.IsNullOrWhiteSpace(_newPromptName))
return;
var existing = _savedPrompts.FirstOrDefault(p =>
p.Name == _newPromptName && p.Id != _selectedPromptId);
if (existing != null)
{
existing.PromptText = _systemPrompt;
existing.Temperature = _temperature;
existing.Timestamp = DateTime.UtcNow;
await QuickMarkdownService.SavePromptAsync(existing);
_selectedPromptId = existing.Id;
}
else
{
var prompt = new QuickMarkdownPrompt
{
UserId = _userId,
Name = _newPromptName,
PromptText = _systemPrompt,
Temperature = _temperature,
Timestamp = DateTime.UtcNow
};
await QuickMarkdownService.SavePromptAsync(prompt);
_selectedPromptId = prompt.Id;
}
_savedPrompts = await QuickMarkdownService.GetPromptsAsync(_userId);
_showPromptNameInput = false;
_newPromptName = string.Empty;
}
private void CancelSavePrompt()
{
_showPromptNameInput = false;
_newPromptName = string.Empty;
}
private async Task DeleteCurrentPrompt()
{
if (_selectedPromptId == 0)
return;
await QuickMarkdownService.DeletePromptAsync(_selectedPromptId);
_savedPrompts = await QuickMarkdownService.GetPromptsAsync(_userId);
_selectedPromptId = 0;
_systemPrompt = Settings.GetQuickMarkdownDefaultPrompt(Settings.Language);
_temperature = Settings.QuickMarkdownTemp;
await SaveSettings();
}
private async Task SaveEntry()
{
if (string.IsNullOrWhiteSpace(_inputText) && string.IsNullOrWhiteSpace(_output))
return;
var entry = new QuickMarkdownEntry
{
UserId = _userId,
InputText = _inputText,
OutputText = _output,
SystemPrompt = _systemPrompt,
Temperature = _temperature,
Timestamp = DateTime.UtcNow
};
await QuickMarkdownService.SaveAsync(entry);
_savedEntries = await QuickMarkdownService.GetAllAsync(_userId);
}
private async Task LoadEntry(int id)
{
var entry = await QuickMarkdownService.GetByIdAsync(id);
if (entry == null) return;
_inputText = entry.InputText;
_output = entry.OutputText;
if (!string.IsNullOrEmpty(entry.SystemPrompt))
{
_systemPrompt = entry.SystemPrompt;
_temperature = entry.Temperature;
}
}
private async Task DeleteEntry(int id)
{
await QuickMarkdownService.DeleteAsync(id);
_savedEntries = await QuickMarkdownService.GetAllAsync(_userId);
}
private async Task Generate()

View file

@ -26,6 +26,12 @@
</div>
<div class="settings-tabs">
@if (_isAdmin)
{
<button class="settings-tab @(_activePromptTab == "admin" ? "active" : "")" @onclick="SwitchToAdminTab">
Admin
</button>
}
<button class="settings-tab @(_activePromptTab == "novel" ? "active" : "")" @onclick="SwitchToNovelTab">
Roman
</button>
@ -35,239 +41,250 @@
</div>
<div class="settings-layout">
@if (_isAdmin && _activePromptTab == "admin")
{
<div class="settings-two-column">
<div class="settings-column">
@if (_isAdmin)
{
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.user"]</h3>
<div class="form-group">
<label for="userSelect">@Loc["settings.user.label.active"]</label>
<select id="userSelect" value="@selectedUserId" @onchange="SwitchUser">
@foreach (var u in users)
{
<option value="@u.Id">@u.Name (@(u.IsAdministrator ? Loc["settings.user.role.admin"] : Loc["settings.user.role.author"]))</option>
}
</select>
</div>
<div class="form-group">
<label for="newUserName">@Loc["settings.user.label.new"]</label>
<div style="display: flex; gap: 8px;">
<input id="newUserName" @bind="newUserName" placeholder="@Loc["settings.user.placeholder.name"]" style="flex: 1;" />
<button class="btn btn-secondary" @onclick="AddUser">@Loc["settings.user.button.add"]</button>
<div class="settings-column">
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.user"]</h3>
<div class="form-group">
<label for="userSelect">@Loc["settings.user.label.active"]</label>
<select id="userSelect" value="@selectedUserId" @onchange="SwitchUser">
@foreach (var u in users)
{
<option value="@u.Id">@u.Name (@(u.IsAdministrator ? Loc["settings.user.role.admin"] : Loc["settings.user.role.author"]))</option>
}
</select>
</div>
<div class="form-group">
<label for="newUserName">@Loc["settings.user.label.new"]</label>
<div style="display: flex; gap: 8px;">
<input id="newUserName" @bind="newUserName" placeholder="@Loc["settings.user.placeholder.name"]" style="flex: 1;" />
<button class="btn btn-secondary" @onclick="AddUser">@Loc["settings.user.button.add"]</button>
</div>
</div>
</div>
</div>
<div class="settings-section" style="margin-bottom:16px;">
<button class="btn btn-secondary" @onclick='() => Navigation.NavigateTo("/setup-2fa")'>@Loc["settings.user.link.2fa"]</button>
</div>
<div class="settings-section" style="margin-bottom:16px;">
<button class="btn btn-secondary" @onclick='() => Navigation.NavigateTo("/setup-2fa")'>@Loc["settings.user.link.2fa"]</button>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.models"]</h3>
<div class="form-group">
<label for="ragModel">@Loc["settings.models.label.rag"]</label>
<select id="ragModel" @bind="ragModel">
@if (availableModels.Count == 0)
{
<option value="">@Loc["settings.models.empty"]</option>
}
@foreach (var m in availableModels)
{
<option value="@m.Name">@m.Name</option>
}
</select>
</div>
<div class="form-group">
<label for="styleModel">@Loc["settings.models.label.style"]</label>
<select id="styleModel" @bind="styleModel">
@if (availableModels.Count == 0)
{
<option value="">@Loc["settings.models.empty"]</option>
}
@foreach (var m in availableModels)
{
<option value="@m.Name">@m.Name</option>
}
</select>
</div>
<div class="form-group">
<label for="spellingModel">@Loc["settings.models.label.spellcheck"]</label>
<select id="spellingModel" @bind="spellingModel">
@if (availableModels.Count == 0)
{
<option value="">@Loc["settings.models.empty"]</option>
}
@foreach (var m in availableModels)
{
<option value="@m.Name">@m.Name</option>
}
</select>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.ollama_server"]</h3>
<div class="form-group">
<label for="backendSelect">Backend</label>
<select id="backendSelect" @bind="selectedBackend">
<option value="Ollama">Ollama</option>
<option value="llama.cpp">llama.cpp</option>
</select>
</div>
<div class="form-group">
<label for="ollamaUrl">@Loc["settings.ollama.label.url"] (Ollama)</label>
<div class="input-with-button">
<input id="ollamaUrl" @bind="ollamaUrl" placeholder="http://localhost:11434" />
<button @onclick="TestConnection" class="btn-sm" disabled="@_isTestingConnection">@Loc["settings.ollama.test"]</button>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.models"]</h3>
<div class="form-group">
<label for="ragModel">@Loc["settings.models.label.rag"]</label>
<select id="ragModel" @bind="ragModel">
@if (availableModels.Count == 0)
{
<option value="">@Loc["settings.models.empty"]</option>
}
@foreach (var m in availableModels)
{
<option value="@m.Name">@m.Name</option>
}
</select>
</div>
@if (_connectionTested)
<div class="form-group">
<label for="styleModel">@Loc["settings.models.label.style"]</label>
<select id="styleModel" @bind="styleModel">
@if (availableModels.Count == 0)
{
<option value="">@Loc["settings.models.empty"]</option>
}
@foreach (var m in availableModels)
{
<option value="@m.Name">@m.Name</option>
}
</select>
</div>
<div class="form-group">
<label for="spellingModel">@Loc["settings.models.label.spellcheck"]</label>
<select id="spellingModel" @bind="spellingModel">
@if (availableModels.Count == 0)
{
<option value="">@Loc["settings.models.empty"]</option>
}
@foreach (var m in availableModels)
{
<option value="@m.Name">@m.Name</option>
}
</select>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.ollama_server"]</h3>
<div class="form-group">
<label for="backendSelect">Backend</label>
<select id="backendSelect" @bind="selectedBackend">
<option value="Ollama">Ollama</option>
<option value="llama.cpp">llama.cpp</option>
</select>
</div>
<div class="form-group">
<label for="ollamaUrl">@Loc["settings.ollama.label.url"] (Ollama)</label>
<div class="input-with-button">
<input id="ollamaUrl" @bind="ollamaUrl" placeholder="http://localhost:11434" />
<button @onclick="TestConnection" class="btn-sm" disabled="@_isTestingConnection">@Loc["settings.ollama.test"]</button>
</div>
@if (_connectionTested)
{
<div class="ollama-status @(_connectionOk ? "ollama-ok" : "ollama-fail")">
@(_connectionOk
? $"✓ {_connectionLatency} ms {Loc["settings.ollama.online"]}"
: $"✗ {Loc["settings.ollama.offline"]}")
</div>
}
<div class="form-hint">@Loc["settings.ollama.hint.url"]</div>
</div>
<div class="form-group">
<label for="llamaCppUrl">URL (llama.cpp)</label>
<input id="llamaCppUrl" @bind="llamaCppUrl" placeholder="http://localhost:8080" />
<div class="form-hint">Nur aktiv wenn Backend auf "llama.cpp" gesetzt ist</div>
</div>
</div>
</div>
<div class="settings-column">
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.diagnostics"]</h3>
<button @onclick="RunAllDiagnostics" class="btn-sm" disabled="@_isDiagnosing">@Loc["settings.diagnostics.run"]</button>
@if (_diagnosticsResults != null)
{
<div class="ollama-status @(_connectionOk ? "ollama-ok" : "ollama-fail")">
@(_connectionOk
? $"✓ {_connectionLatency} ms {Loc["settings.ollama.online"]}"
: $"✗ {Loc["settings.ollama.offline"]}")
<div class="diagnostics-results">
@foreach (var line in _diagnosticsResults)
{
<div class="diagnostics-line">@line</div>
}
</div>
}
<div class="form-hint">@Loc["settings.ollama.hint.url"]</div>
</div>
<div class="form-group">
<label for="llamaCppUrl">URL (llama.cpp)</label>
<input id="llamaCppUrl" @bind="llamaCppUrl" placeholder="http://localhost:8080" />
<div class="form-hint">Nur aktiv wenn Backend auf "llama.cpp" gesetzt ist</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.diagnostics"]</h3>
<button @onclick="RunAllDiagnostics" class="btn-sm" disabled="@_isDiagnosing">@Loc["settings.diagnostics.run"]</button>
@if (_diagnosticsResults != null)
{
<div class="diagnostics-results">
@foreach (var line in _diagnosticsResults)
{
<div class="diagnostics-line">@line</div>
}
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.appearance"]</h3>
<div class="form-group">
<label for="themeSelect">@Loc["settings.appearance.label.theme"]</label>
<select id="themeSelect" @bind="selectedTheme">
<option value="light">@Loc["settings.appearance.theme.light"]</option>
<option value="dark">@Loc["settings.appearance.theme.dark"]</option>
<option value="w95">W95 @Loc["settings.appearance.theme.retro"]</option>
</select>
</div>
}
</div>
}
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.language"]</h3>
<div class="form-group">
<label for="languageSelect">@Loc["settings.language.label"]</label>
<select id="languageSelect" @bind="selectedLanguage">
<option value="de">Deutsch</option>
<option value="en">English</option>
</select>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.appearance"]</h3>
<div class="form-group">
<label for="themeSelect">@Loc["settings.appearance.label.theme"]</label>
<select id="themeSelect" @bind="selectedTheme">
<option value="light">@Loc["settings.appearance.theme.light"]</option>
<option value="dark">@Loc["settings.appearance.theme.dark"]</option>
<option value="w95">W95 @Loc["settings.appearance.theme.retro"]</option>
</select>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.language"]</h3>
<div class="form-group">
<label for="languageSelect">@Loc["settings.language.label"]</label>
<select id="languageSelect" @bind="selectedLanguage">
<option value="de">Deutsch</option>
<option value="en">English</option>
</select>
</div>
</div>
</div>
}
@if (_activePromptTab == "novel")
{
<div class="settings-column settings-column-wide">
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.editor_prompt"]</h3>
<div class="form-group">
<textarea id="lektorPrompt" @bind="lektorPrompt" rows="6"></textarea>
<div class="settings-two-column">
<div class="settings-column">
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.editor_prompt"]</h3>
<div class="form-group">
<textarea id="lektorPrompt" @bind="lektorPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@lektorTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(lektorTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => lektorTemp = v))" />
<div class="temp-category">@GetTempCategory(lektorTemp)</div>
<div class="temp-desc">@GetTempDescription(lektorTemp)</div>
</div>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@lektorTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(lektorTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => lektorTemp = v))" />
<div class="temp-category">@GetTempCategory(lektorTemp)</div>
<div class="temp-desc">@GetTempDescription(lektorTemp)</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.factcheck_template"]</h3>
<div class="form-group">
<textarea id="factCheckTemplate" @bind="factCheckTemplate" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@factCheckTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(factCheckTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => factCheckTemp = v))" />
<div class="temp-category">@GetTempCategory(factCheckTemp)</div>
<div class="temp-desc">@GetTempDescription(factCheckTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.spellcheck_prompt"]</h3>
<div class="form-group">
<textarea id="spellingPrompt" @bind="spellingPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@spellingTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(spellingTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => spellingTemp = v))" />
<div class="temp-category">@GetTempCategory(spellingTemp)</div>
<div class="temp-desc">@GetTempDescription(spellingTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.advocatus_diaboli"]</h3>
<div class="form-group">
<textarea id="advocatusDiaboliPrompt" @bind="advocatusDiaboliPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@advocatusDiaboliTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(advocatusDiaboliTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => advocatusDiaboliTemp = v))" />
<div class="temp-category">@GetTempCategory(advocatusDiaboliTemp)</div>
<div class="temp-desc">@GetTempDescription(advocatusDiaboliTemp)</div>
</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.factcheck_template"]</h3>
<div class="form-group">
<textarea id="factCheckTemplate" @bind="factCheckTemplate" rows="6"></textarea>
<div class="settings-column">
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.hook_finder"]</h3>
<div class="form-group">
<textarea id="hookFinderPrompt" @bind="hookFinderPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@hookFinderTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(hookFinderTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => hookFinderTemp = v))" />
<div class="temp-category">@GetTempCategory(hookFinderTemp)</div>
<div class="temp-desc">@GetTempDescription(hookFinderTemp)</div>
</div>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@factCheckTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(factCheckTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => factCheckTemp = v))" />
<div class="temp-category">@GetTempCategory(factCheckTemp)</div>
<div class="temp-desc">@GetTempDescription(factCheckTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.spellcheck_prompt"]</h3>
<div class="form-group">
<textarea id="spellingPrompt" @bind="spellingPrompt" rows="6"></textarea>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.eli5"]</h3>
<div class="form-group">
<textarea id="eli5Prompt" @bind="eli5Prompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@eli5Temp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(eli5Temp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => eli5Temp = v))" />
<div class="temp-category">@GetTempCategory(eli5Temp)</div>
<div class="temp-desc">@GetTempDescription(eli5Temp)</div>
</div>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@spellingTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(spellingTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => spellingTemp = v))" />
<div class="temp-category">@GetTempCategory(spellingTemp)</div>
<div class="temp-desc">@GetTempDescription(spellingTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.advocatus_diaboli"]</h3>
<div class="form-group">
<textarea id="advocatusDiaboliPrompt" @bind="advocatusDiaboliPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@advocatusDiaboliTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(advocatusDiaboliTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => advocatusDiaboliTemp = v))" />
<div class="temp-category">@GetTempCategory(advocatusDiaboliTemp)</div>
<div class="temp-desc">@GetTempDescription(advocatusDiaboliTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.hook_finder"]</h3>
<div class="form-group">
<textarea id="hookFinderPrompt" @bind="hookFinderPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@hookFinderTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(hookFinderTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => hookFinderTemp = v))" />
<div class="temp-category">@GetTempCategory(hookFinderTemp)</div>
<div class="temp-desc">@GetTempDescription(hookFinderTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.eli5"]</h3>
<div class="form-group">
<textarea id="eli5Prompt" @bind="eli5Prompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@eli5Temp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(eli5Temp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => eli5Temp = v))" />
<div class="temp-category">@GetTempCategory(eli5Temp)</div>
<div class="temp-desc">@GetTempDescription(eli5Temp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.coauthor_brainstorming"]</h3>
<div class="form-group">
<textarea id="coAuthorPrompt" @bind="coAuthorPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@coAuthorTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(coAuthorTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => coAuthorTemp = v))" />
<div class="temp-category">@GetTempCategory(coAuthorTemp)</div>
<div class="temp-desc">@GetTempDescription(coAuthorTemp)</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.coauthor_brainstorming"]</h3>
<div class="form-group">
<textarea id="coAuthorPrompt" @bind="coAuthorPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@coAuthorTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(coAuthorTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => coAuthorTemp = v))" />
<div class="temp-category">@GetTempCategory(coAuthorTemp)</div>
<div class="temp-desc">@GetTempDescription(coAuthorTemp)</div>
</div>
</div>
</div>
</div>
@ -275,95 +292,99 @@
@if (_activePromptTab == "technical")
{
<div class="settings-column settings-column-wide">
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_lastenheft"]</h3>
<div class="form-group">
<textarea id="techLastenheftPrompt" @bind="techLastenheftPrompt" rows="6"></textarea>
<div class="settings-two-column">
<div class="settings-column">
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_lastenheft"]</h3>
<div class="form-group">
<textarea id="techLastenheftPrompt" @bind="techLastenheftPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techLastenheftTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techLastenheftTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techLastenheftTemp = v))" />
<div class="temp-category">@GetTempCategory(techLastenheftTemp)</div>
<div class="temp-desc">@GetTempDescription(techLastenheftTemp)</div>
</div>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techLastenheftTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techLastenheftTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techLastenheftTemp = v))" />
<div class="temp-category">@GetTempCategory(techLastenheftTemp)</div>
<div class="temp-desc">@GetTempDescription(techLastenheftTemp)</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_pflichtenheft"]</h3>
<div class="form-group">
<textarea id="techPflichtenheftPrompt" @bind="techPflichtenheftPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techPflichtenheftTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techPflichtenheftTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techPflichtenheftTemp = v))" />
<div class="temp-category">@GetTempCategory(techPflichtenheftTemp)</div>
<div class="temp-desc">@GetTempDescription(techPflichtenheftTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_usecase"]</h3>
<div class="form-group">
<textarea id="techUseCasePrompt" @bind="techUseCasePrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techUseCaseTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techUseCaseTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techUseCaseTemp = v))" />
<div class="temp-category">@GetTempCategory(techUseCaseTemp)</div>
<div class="temp-desc">@GetTempDescription(techUseCaseTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_stakeholder"]</h3>
<div class="form-group">
<textarea id="techStakeholderPrompt" @bind="techStakeholderPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techStakeholderTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techStakeholderTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techStakeholderTemp = v))" />
<div class="temp-category">@GetTempCategory(techStakeholderTemp)</div>
<div class="temp-desc">@GetTempDescription(techStakeholderTemp)</div>
</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_pflichtenheft"]</h3>
<div class="form-group">
<textarea id="techPflichtenheftPrompt" @bind="techPflichtenheftPrompt" rows="6"></textarea>
<div class="settings-column">
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_glossar"]</h3>
<div class="form-group">
<textarea id="techGlossarPrompt" @bind="techGlossarPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techGlossarTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techGlossarTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techGlossarTemp = v))" />
<div class="temp-category">@GetTempCategory(techGlossarTemp)</div>
<div class="temp-desc">@GetTempDescription(techGlossarTemp)</div>
</div>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techPflichtenheftTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techPflichtenheftTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techPflichtenheftTemp = v))" />
<div class="temp-category">@GetTempCategory(techPflichtenheftTemp)</div>
<div class="temp-desc">@GetTempDescription(techPflichtenheftTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_usecase"]</h3>
<div class="form-group">
<textarea id="techUseCasePrompt" @bind="techUseCasePrompt" rows="6"></textarea>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_qualitaet"]</h3>
<div class="form-group">
<textarea id="techQualitaetPrompt" @bind="techQualitaetPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techQualitaetTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techQualitaetTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techQualitaetTemp = v))" />
<div class="temp-category">@GetTempCategory(techQualitaetTemp)</div>
<div class="temp-desc">@GetTempDescription(techQualitaetTemp)</div>
</div>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techUseCaseTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techUseCaseTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techUseCaseTemp = v))" />
<div class="temp-category">@GetTempCategory(techUseCaseTemp)</div>
<div class="temp-desc">@GetTempDescription(techUseCaseTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_stakeholder"]</h3>
<div class="form-group">
<textarea id="techStakeholderPrompt" @bind="techStakeholderPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techStakeholderTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techStakeholderTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techStakeholderTemp = v))" />
<div class="temp-category">@GetTempCategory(techStakeholderTemp)</div>
<div class="temp-desc">@GetTempDescription(techStakeholderTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_glossar"]</h3>
<div class="form-group">
<textarea id="techGlossarPrompt" @bind="techGlossarPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techGlossarTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techGlossarTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techGlossarTemp = v))" />
<div class="temp-category">@GetTempCategory(techGlossarTemp)</div>
<div class="temp-desc">@GetTempDescription(techGlossarTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_qualitaet"]</h3>
<div class="form-group">
<textarea id="techQualitaetPrompt" @bind="techQualitaetPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techQualitaetTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techQualitaetTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techQualitaetTemp = v))" />
<div class="temp-category">@GetTempCategory(techQualitaetTemp)</div>
<div class="temp-desc">@GetTempDescription(techQualitaetTemp)</div>
</div>
</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_risiko"]</h3>
<div class="form-group">
<textarea id="techRisikoPrompt" @bind="techRisikoPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techRisikoTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techRisikoTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techRisikoTemp = v))" />
<div class="temp-category">@GetTempCategory(techRisikoTemp)</div>
<div class="temp-desc">@GetTempDescription(techRisikoTemp)</div>
<div class="settings-section">
<h3 class="settings-section-title">@Loc["settings.section.tech_risiko"]</h3>
<div class="form-group">
<textarea id="techRisikoPrompt" @bind="techRisikoPrompt" rows="6"></textarea>
</div>
<div class="temp-slider">
<label class="temp-label">@Loc["settings.temperature.label"] <span class="temp-value">@techRisikoTemp.ToString("F1")</span></label>
<input type="range" min="0" max="2" step="0.1" value="@Fmt(techRisikoTemp)" @oninput="@((ChangeEventArgs e) => SetTemp(e, v => techRisikoTemp = v))" />
<div class="temp-category">@GetTempCategory(techRisikoTemp)</div>
<div class="temp-desc">@GetTempDescription(techRisikoTemp)</div>
</div>
</div>
</div>
</div>
@ -386,6 +407,7 @@
private void SwitchToNovelTab() => _activePromptTab = "novel";
private void SwitchToTechnicalTab() => _activePromptTab = "technical";
private void SwitchToAdminTab() => _activePromptTab = "admin";
private string ragModel = "llama3.2";
private string styleModel = "llama3.2";
private string spellingModel = "phi3:mini";

View file

@ -45,7 +45,7 @@
</div>
<div class="auth-actions">
<button @onclick="Enable2FA" disabled="@isBusy || string.IsNullOrWhiteSpace(verificationCode)">@Loc["setup2fa.button.enable"]</button>
<button @onclick="Enable2FA" disabled="@_enableDisabled">@Loc["setup2fa.button.enable"]</button>
<button @onclick="Cancel">@Loc["common.cancel"]</button>
</div>
}
@ -73,6 +73,7 @@
private bool isEnabled;
private bool isBusy;
private string? username;
private bool _enableDisabled => isBusy || string.IsNullOrWhiteSpace(verificationCode);
protected override async Task OnInitializedAsync()
{

View file

@ -110,7 +110,7 @@
</div>
<div class="modal-actions">
<button @onclick="CancelCreate">Abbrechen</button>
<button @onclick="CreateUser" class="primary" disabled="@(string.IsNullOrWhiteSpace(_newUsername) || string.IsNullOrWhiteSpace(_newPassword))">Anlegen</button>
<button @onclick="CreateUser" class="primary" disabled="@_createUserDisabled">Anlegen</button>
</div>
</div>
</div>
@ -172,6 +172,7 @@
private string _newEmail = string.Empty;
private List<string> _newRoles = new() { "Author" };
private string _newPassword = string.Empty;
private bool _createUserDisabled => string.IsNullOrWhiteSpace(_newUsername) || string.IsNullOrWhiteSpace(_newPassword);
private string? _generatedPassword;
private bool showEditDialog;

View file

@ -0,0 +1,12 @@
namespace AuthorBuddy.Web.Data;
public class QuickMarkdownEntry
{
public int Id { get; set; }
public int UserId { get; set; }
public string InputText { get; set; } = string.Empty;
public string OutputText { get; set; } = string.Empty;
public string SystemPrompt { get; set; } = string.Empty;
public double Temperature { get; set; }
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

View file

@ -0,0 +1,11 @@
namespace AuthorBuddy.Web.Data;
public class QuickMarkdownPrompt
{
public int Id { get; set; }
public int UserId { get; set; }
public string Name { get; set; } = string.Empty;
public string PromptText { get; set; } = string.Empty;
public double Temperature { get; set; }
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

View file

@ -42,6 +42,7 @@ builder.Services.AddSingleton<IDbAdminService, DbAdminService>();
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddSingleton<IEmailService, EmailService>();
builder.Services.AddSingleton<IChatService, ChatService>();
builder.Services.AddSingleton<IQuickMarkdownService, QuickMarkdownService>();
var smtpSettings = new SmtpSettings();
builder.Configuration.GetSection("Smtp").Bind(smtpSettings);

View file

@ -3,7 +3,7 @@
<Project>
<PropertyGroup>
<_PublishTargetUrl>E:\ollama_net\ollama\AuthorBuddy.Web\bin\Release\net10.0\publish\</_PublishTargetUrl>
<History>True|2026-06-14T06:09:44.9432726Z||;</History>
<History>True|2026-07-04T08:31:55.1105019Z||;True|2026-07-03T19:42:19.2725521+02:00||;True|2026-07-03T19:14:41.2291817+02:00||;True|2026-06-26T17:29:16.2419779+02:00||;True|2026-06-14T08:09:44.9432726+02:00||;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>

View file

@ -16,6 +16,7 @@ public interface IOllamaService
Task<string> AnswerBasedOnFactsAsync(string question, string facts);
Task<(bool Success, long LatencyMs)> TestConnectionAsync();
Task<bool> ModelExistsAsync(string model);
Task<bool> DeleteModelAsync(string modelName);
Task<(bool Success, int ContextWindow)> GetModelContextWindowAsync(string model);
Task<long> MeasureLatencyAsync(string model);
void Reconfigure(string ollamaUrl);

View file

@ -0,0 +1,16 @@
using AuthorBuddy.Web.Data;
namespace AuthorBuddy.Web.Services;
public interface IQuickMarkdownService
{
Task<List<QuickMarkdownEntry>> GetAllAsync(int userId);
Task<QuickMarkdownEntry?> GetByIdAsync(int id);
Task SaveAsync(QuickMarkdownEntry entry);
Task DeleteAsync(int id);
Task<List<QuickMarkdownPrompt>> GetPromptsAsync(int userId);
Task<QuickMarkdownPrompt?> GetPromptByIdAsync(int id);
Task SavePromptAsync(QuickMarkdownPrompt prompt);
Task DeletePromptAsync(int id);
}

View file

@ -21,6 +21,9 @@ public class OllamaService : IOllamaService
private ILLMBackend ActiveBackend =>
_backends.FirstOrDefault(b => b.Name == _settings.Backend) ?? _backends.First();
private readonly object _warmLock = new();
private bool _warmupAttempted;
private async Task EnsureRunningAsync()
{
if (ActiveBackend.Name != "Ollama")
@ -28,7 +31,10 @@ public class OllamaService : IOllamaService
var reachable = await ActiveBackend.TestConnectionAsync();
if (reachable)
{
await WarmupModelAsync();
return;
}
lock (_startLock)
{
@ -60,6 +66,7 @@ public class OllamaService : IOllamaService
if (reachable)
{
_opState.AppendThought(" Ollama ist bereit");
await WarmupModelAsync();
return;
}
_opState.AppendThought(".");
@ -68,6 +75,39 @@ public class OllamaService : IOllamaService
_opState.AppendThought(" Zeitüberschreitung");
}
private async Task WarmupModelAsync()
{
lock (_warmLock)
{
if (_warmupAttempted) return;
_warmupAttempted = true;
}
var modelsToWarm = new[] { _settings.StyleModel, _settings.EmbedModel }
.Where(m => !string.IsNullOrWhiteSpace(m))
.Distinct()
.ToList();
if (modelsToWarm.Count == 0) return;
_opState.SetThought("Lade Modelle in den Arbeitsspeicher...");
foreach (var model in modelsToWarm)
{
_opState.AppendThought($" {model}...");
try
{
var warmCts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
var dummy = await ActiveBackend.ChatAsync(model, " ", null, 0.0);
_opState.AppendThought(" ✓");
}
catch (Exception ex)
{
_opState.AppendThought($" ✗ ({ex.Message})");
}
}
_opState.AppendThought(" Fertig");
}
public void Reconfigure(string url)
{
_settings.OllamaUrl = url;
@ -175,4 +215,13 @@ public class OllamaService : IOllamaService
_opState.AppendThought(result ? " Erfolgreich" : " Fehlgeschlagen");
return result;
}
public async Task<bool> DeleteModelAsync(string modelName)
{
await EnsureRunningAsync();
_opState.SetThought($"Lösche Modell {modelName}...");
var result = await ActiveBackend.DeleteModelAsync(modelName);
_opState.AppendThought(result ? " Erfolgreich" : " Fehlgeschlagen");
return result;
}
}

View file

@ -0,0 +1,76 @@
using AuthorBuddy.Web.Data;
using LiteDB;
namespace AuthorBuddy.Web.Services;
public class QuickMarkdownService : IQuickMarkdownService
{
private readonly ILiteDatabase _db;
public QuickMarkdownService(ILiteDatabase db)
{
_db = db;
}
public Task<List<QuickMarkdownEntry>> GetAllAsync(int userId)
{
var col = _db.GetCollection<QuickMarkdownEntry>("quick_md");
return Task.FromResult(col.Find(e => e.UserId == userId)
.OrderByDescending(e => e.Timestamp)
.ToList());
}
public Task<QuickMarkdownEntry?> GetByIdAsync(int id)
{
var col = _db.GetCollection<QuickMarkdownEntry>("quick_md");
return Task.FromResult<QuickMarkdownEntry?>(col.FindById(id));
}
public Task SaveAsync(QuickMarkdownEntry entry)
{
var col = _db.GetCollection<QuickMarkdownEntry>("quick_md");
if (entry.Id > 0)
col.Update(entry);
else
col.Insert(entry);
return Task.CompletedTask;
}
public Task DeleteAsync(int id)
{
var col = _db.GetCollection<QuickMarkdownEntry>("quick_md");
col.Delete(id);
return Task.CompletedTask;
}
public Task<List<QuickMarkdownPrompt>> GetPromptsAsync(int userId)
{
var col = _db.GetCollection<QuickMarkdownPrompt>("quick_md_prompts");
return Task.FromResult(col.Find(p => p.UserId == userId)
.OrderByDescending(p => p.Timestamp)
.ToList());
}
public Task<QuickMarkdownPrompt?> GetPromptByIdAsync(int id)
{
var col = _db.GetCollection<QuickMarkdownPrompt>("quick_md_prompts");
return Task.FromResult<QuickMarkdownPrompt?>(col.FindById(id));
}
public Task SavePromptAsync(QuickMarkdownPrompt prompt)
{
var col = _db.GetCollection<QuickMarkdownPrompt>("quick_md_prompts");
if (prompt.Id > 0)
col.Update(prompt);
else
col.Insert(prompt);
return Task.CompletedTask;
}
public Task DeletePromptAsync(int id)
{
var col = _db.GetCollection<QuickMarkdownPrompt>("quick_md_prompts");
col.Delete(id);
return Task.CompletedTask;
}
}

View file

@ -775,8 +775,8 @@ button.primary {
}
.settings-layout {
display: grid;
grid-template-columns: 1fr 2fr;
display: flex;
flex-direction: column;
gap: 16px;
}
@ -784,9 +784,10 @@ button.primary {
min-width: 0;
}
.settings-column-wide {
min-width: 0;
grid-column: 2;
.settings-two-column {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
.settings-column .form-group textarea {
@ -1497,6 +1498,95 @@ button.primary {
gap: 8px;
}
.qm-generate-row {
display: flex;
gap: 8px;
align-items: center;
}
.qm-prompt-selector {
display: flex;
gap: 6px;
align-items: center;
}
.qm-prompt-select {
flex: 1;
padding: 6px 8px;
border: 1px solid var(--border-color);
background: var(--input-bg, var(--editor-bg));
color: var(--text-color);
font-size: 13px;
}
.qm-prompt-name-row {
display: flex;
gap: 6px;
margin-top: 6px;
align-items: center;
}
.qm-prompt-name-row input {
flex: 1;
padding: 6px 8px;
border: 1px solid var(--border-color);
background: var(--input-bg, var(--editor-bg));
color: var(--text-color);
font-size: 13px;
}
.qm-saved-list {
margin-top: 16px;
border-top: 1px solid var(--border-color);
padding-top: 12px;
}
.qm-saved-list h4 {
font-size: 14px;
margin-bottom: 8px;
}
.qm-saved-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 6px 8px;
border: 1px solid var(--border-color);
margin-bottom: 4px;
cursor: pointer;
font-size: 13px;
}
.qm-saved-item:hover {
background: var(--accent-color);
color: white;
}
.qm-saved-meta {
flex: 1;
min-width: 0;
}
.qm-saved-date {
font-weight: bold;
margin-right: 12px;
white-space: nowrap;
}
.qm-saved-preview {
color: var(--text-color);
opacity: 0.7;
}
.qm-saved-item:hover .qm-saved-preview {
color: white;
}
.qm-saved-item button {
flex-shrink: 0;
margin-left: 8px;
}
/* Chat page */
.chat-page {
display: flex;
@ -1656,6 +1746,10 @@ button.primary {
grid-template-columns: 1fr;
}
.settings-two-column {
grid-template-columns: 1fr;
}
.qm-layout {
grid-template-columns: 1fr;
}
@ -1733,6 +1827,11 @@ button.primary {
grid-template-columns: 1fr;
}
.settings-two-column {
grid-template-columns: 1fr;
grid-column: 1;
}
.settings-page {
padding: 8px;
}