790 lines
34 KiB
C#
790 lines
34 KiB
C#
using AuthorBuddy.Web.Data;
|
|
using AuthorBuddy.Web.Models;
|
|
using LiteDB;
|
|
|
|
namespace AuthorBuddy.Web.Services;
|
|
|
|
public class SettingsService : ISettingsService
|
|
{
|
|
private const string KeyOllamaUrl = "ollama_url";
|
|
private const string KeyLlamaCppUrl = "llama_cpp_url";
|
|
private const string KeyBackend = "llm_backend";
|
|
private const string KeyRagModel = "ollama_rag_model";
|
|
private const string KeyStyleModel = "ollama_style_model";
|
|
private const string KeySpellingModel = "ollama_spelling_model";
|
|
private const string KeyTheme = "theme";
|
|
private const string KeyLektorPrompt = "ollama_lektor_prompt";
|
|
private const string KeyFactCheckTemplate = "ollama_fact_check";
|
|
private const string KeySpellingPrompt = "ollama_spelling_prompt";
|
|
private const string KeyAdvocatusDiaboli = "ollama_advocatus_diaboli";
|
|
private const string KeyHookFinder = "ollama_hook_finder";
|
|
private const string KeyEli5 = "ollama_eli5";
|
|
private const string KeyCoAuthor = "ollama_coauthor";
|
|
private const string KeyLektorTemp = "ollama_lektor_temp";
|
|
private const string KeyFactCheckTemp = "ollama_fact_check_temp";
|
|
private const string KeySpellingTemp = "ollama_spelling_temp";
|
|
private const string KeyAdvocatusDiaboliTemp = "ollama_advocatus_diaboli_temp";
|
|
private const string KeyHookFinderTemp = "ollama_hook_finder_temp";
|
|
private const string KeyEli5Temp = "ollama_eli5_temp";
|
|
private const string KeyCoAuthorTemp = "ollama_coauthor_temp";
|
|
private const string KeyTechLastenheft = "tech_lastenheft";
|
|
private const string KeyTechPflichtenheft = "tech_pflichtenheft";
|
|
private const string KeyTechUseCase = "tech_usecase";
|
|
private const string KeyTechStakeholder = "tech_stakeholder";
|
|
private const string KeyTechGlossar = "tech_glossar";
|
|
private const string KeyTechQualitaet = "tech_qualitaet";
|
|
private const string KeyTechRisiko = "tech_risiko";
|
|
private const string KeyTechLastenheftTemp = "tech_lastenheft_temp";
|
|
private const string KeyTechPflichtenheftTemp = "tech_pflichtenheft_temp";
|
|
private const string KeyTechUseCaseTemp = "tech_usecase_temp";
|
|
private const string KeyTechStakeholderTemp = "tech_stakeholder_temp";
|
|
private const string KeyTechGlossarTemp = "tech_glossar_temp";
|
|
private const string KeyTechQualitaetTemp = "tech_qualitaet_temp";
|
|
private const string KeyTechRisikoTemp = "tech_risiko_temp";
|
|
private const string KeyLanguage = "language";
|
|
|
|
private const string KeyLastProjectId = "last_project_id";
|
|
|
|
private readonly ILiteDatabase _db;
|
|
private readonly OllamaSettings _ollamaConfig;
|
|
private int? _currentUserId;
|
|
private int? _currentProjectId;
|
|
|
|
public SettingsService(ILiteDatabase db, OllamaSettings ollamaConfig)
|
|
{
|
|
_db = db;
|
|
_ollamaConfig = ollamaConfig;
|
|
}
|
|
|
|
public int? CurrentProjectId
|
|
{
|
|
get => _currentProjectId;
|
|
set => _currentProjectId = value;
|
|
}
|
|
|
|
public string? CurrentFilePath { get; set; }
|
|
public string? PendingAssistantInput { get; set; }
|
|
public string? PendingAssistantOutput { get; set; }
|
|
|
|
public Task<int?> GetLastProjectIdAsync()
|
|
{
|
|
var col = _db.GetCollection<SettingEntity>("settings");
|
|
var setting = col.FindOne(s => s.Key == KeyLastProjectId && s.UserId == _currentUserId && s.ProjectId == null);
|
|
if (setting != null && int.TryParse(setting.Value, out var id))
|
|
return Task.FromResult<int?>(id);
|
|
return Task.FromResult<int?>(null);
|
|
}
|
|
|
|
public Task SaveLastProjectIdAsync(int projectId)
|
|
{
|
|
var col = _db.GetCollection<SettingEntity>("settings");
|
|
var existing = col.FindOne(s => s.Key == KeyLastProjectId && s.UserId == _currentUserId && s.ProjectId == null);
|
|
if (existing != null)
|
|
{
|
|
existing.Value = projectId.ToString();
|
|
col.Update(existing);
|
|
}
|
|
else
|
|
{
|
|
col.Insert(new SettingEntity
|
|
{
|
|
Key = KeyLastProjectId,
|
|
Value = projectId.ToString(),
|
|
UserId = _currentUserId,
|
|
ProjectId = null
|
|
});
|
|
}
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private string? GetSetting(string key, int? userId, int? projectId)
|
|
{
|
|
var col = _db.GetCollection<SettingEntity>("settings");
|
|
|
|
var matches = col.Find(s =>
|
|
s.Key == key &&
|
|
(s.UserId == userId || s.UserId == null) &&
|
|
(s.ProjectId == projectId || s.ProjectId == null));
|
|
|
|
return matches
|
|
.OrderByDescending(s => s.UserId != null)
|
|
.ThenByDescending(s => s.ProjectId != null)
|
|
.FirstOrDefault()?.Value;
|
|
}
|
|
|
|
private string? Get(string key)
|
|
{
|
|
return GetSetting(key, _currentUserId, _currentProjectId);
|
|
}
|
|
|
|
private string? GetGlobal(string key)
|
|
{
|
|
var col = _db.GetCollection<SettingEntity>("settings");
|
|
return col.FindOne(s => s.Key == key && s.UserId == null && s.ProjectId == null)?.Value;
|
|
}
|
|
|
|
private void SetGlobal(string key, string value)
|
|
{
|
|
var col = _db.GetCollection<SettingEntity>("settings");
|
|
var existing = col.FindOne(s => s.Key == key && s.UserId == null && s.ProjectId == null);
|
|
if (existing != null)
|
|
{
|
|
existing.Value = value;
|
|
col.Update(existing);
|
|
}
|
|
else
|
|
{
|
|
col.Insert(new SettingEntity { Key = key, Value = value, UserId = null, ProjectId = null });
|
|
}
|
|
}
|
|
|
|
private void Set(string key, string value)
|
|
{
|
|
var col = _db.GetCollection<SettingEntity>("settings");
|
|
|
|
var existing = col.FindOne(s =>
|
|
s.Key == key && s.UserId == _currentUserId && s.ProjectId == null);
|
|
|
|
if (existing != null)
|
|
{
|
|
existing.Value = value;
|
|
col.Update(existing);
|
|
}
|
|
else
|
|
{
|
|
col.Insert(new SettingEntity
|
|
{
|
|
Key = key,
|
|
Value = value,
|
|
UserId = _currentUserId,
|
|
ProjectId = null
|
|
});
|
|
}
|
|
}
|
|
|
|
public Task<string?> GetOllamaUrlAsync() => Task.FromResult(GetGlobal(KeyOllamaUrl));
|
|
public Task<string?> GetLlamaCppUrlAsync() => Task.FromResult(GetGlobal(KeyLlamaCppUrl));
|
|
public Task<string?> GetBackendAsync() => Task.FromResult(GetGlobal(KeyBackend));
|
|
public Task<string?> GetRagModelAsync() => Task.FromResult(GetGlobal(KeyRagModel));
|
|
public Task<string?> GetStyleModelAsync() => Task.FromResult(GetGlobal(KeyStyleModel));
|
|
public Task<string?> GetLektorSystemPromptAsync() => Task.FromResult(Get(KeyLektorPrompt));
|
|
public Task<string?> GetFactCheckTemplateAsync() => Task.FromResult(Get(KeyFactCheckTemplate));
|
|
public Task<string?> GetSpellingPromptAsync() => Task.FromResult(Get(KeySpellingPrompt));
|
|
public Task<string?> GetSpellingModelAsync() => Task.FromResult(GetGlobal(KeySpellingModel));
|
|
public Task<string?> GetAdvocatusDiaboliPromptAsync() => Task.FromResult(Get(KeyAdvocatusDiaboli));
|
|
public Task<string?> GetHookFinderPromptAsync() => Task.FromResult(Get(KeyHookFinder));
|
|
public Task<string?> GetEli5PromptAsync() => Task.FromResult(Get(KeyEli5));
|
|
public Task<string?> GetCoAuthorBrainstormingPromptAsync() => Task.FromResult(Get(KeyCoAuthor));
|
|
public Task<double> GetLektorTempAsync() => Task.FromResult(double.TryParse(Get(KeyLektorTemp), out var v) ? v : _ollamaConfig.LektorTemp);
|
|
public Task<double> GetFactCheckTempAsync() => Task.FromResult(double.TryParse(Get(KeyFactCheckTemp), out var v) ? v : _ollamaConfig.FactCheckTemp);
|
|
public Task<double> GetSpellingTempAsync() => Task.FromResult(double.TryParse(Get(KeySpellingTemp), out var v) ? v : _ollamaConfig.SpellingTemp);
|
|
public Task<double> GetAdvocatusDiaboliTempAsync() => Task.FromResult(double.TryParse(Get(KeyAdvocatusDiaboliTemp), out var v) ? v : _ollamaConfig.AdvocatusDiaboliTemp);
|
|
public Task<double> GetHookFinderTempAsync() => Task.FromResult(double.TryParse(Get(KeyHookFinderTemp), out var v) ? v : _ollamaConfig.HookFinderTemp);
|
|
public Task<double> GetEli5TempAsync() => Task.FromResult(double.TryParse(Get(KeyEli5Temp), out var v) ? v : _ollamaConfig.Eli5Temp);
|
|
public Task<double> GetCoAuthorTempAsync() => Task.FromResult(double.TryParse(Get(KeyCoAuthorTemp), out var v) ? v : _ollamaConfig.CoAuthorTemp);
|
|
|
|
public Task<string?> GetTechLastenheftPromptAsync() => Task.FromResult(Get(KeyTechLastenheft));
|
|
public Task<string?> GetTechPflichtenheftPromptAsync() => Task.FromResult(Get(KeyTechPflichtenheft));
|
|
public Task<string?> GetTechUseCasePromptAsync() => Task.FromResult(Get(KeyTechUseCase));
|
|
public Task<string?> GetTechStakeholderPromptAsync() => Task.FromResult(Get(KeyTechStakeholder));
|
|
public Task<string?> GetTechGlossarPromptAsync() => Task.FromResult(Get(KeyTechGlossar));
|
|
public Task<string?> GetTechQualitaetPromptAsync() => Task.FromResult(Get(KeyTechQualitaet));
|
|
public Task<string?> GetTechRisikoPromptAsync() => Task.FromResult(Get(KeyTechRisiko));
|
|
public Task<double> GetTechLastenheftTempAsync() => Task.FromResult(double.TryParse(Get(KeyTechLastenheftTemp), out var v) ? v : _ollamaConfig.TechLastenheftTemp);
|
|
public Task<double> GetTechPflichtenheftTempAsync() => Task.FromResult(double.TryParse(Get(KeyTechPflichtenheftTemp), out var v) ? v : _ollamaConfig.TechPflichtenheftTemp);
|
|
public Task<double> GetTechUseCaseTempAsync() => Task.FromResult(double.TryParse(Get(KeyTechUseCaseTemp), out var v) ? v : _ollamaConfig.TechUseCaseTemp);
|
|
public Task<double> GetTechStakeholderTempAsync() => Task.FromResult(double.TryParse(Get(KeyTechStakeholderTemp), out var v) ? v : _ollamaConfig.TechStakeholderTemp);
|
|
public Task<double> GetTechGlossarTempAsync() => Task.FromResult(double.TryParse(Get(KeyTechGlossarTemp), out var v) ? v : _ollamaConfig.TechGlossarTemp);
|
|
public Task<double> GetTechQualitaetTempAsync() => Task.FromResult(double.TryParse(Get(KeyTechQualitaetTemp), out var v) ? v : _ollamaConfig.TechQualitaetTemp);
|
|
public Task<double> GetTechRisikoTempAsync() => Task.FromResult(double.TryParse(Get(KeyTechRisikoTemp), out var v) ? v : _ollamaConfig.TechRisikoTemp);
|
|
public Task<string?> GetThemeAsync() => Task.FromResult(Get(KeyTheme));
|
|
public Task<string?> GetLanguageAsync() => Task.FromResult(Get(KeyLanguage));
|
|
public Task SaveLanguageAsync(string language)
|
|
{
|
|
Set(KeyLanguage, language);
|
|
_ollamaConfig.Language = language;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveOllamaUrlAsync(string url)
|
|
{
|
|
SetGlobal(KeyOllamaUrl, url);
|
|
_ollamaConfig.OllamaUrl = url;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveLlamaCppUrlAsync(string url)
|
|
{
|
|
SetGlobal(KeyLlamaCppUrl, url);
|
|
_ollamaConfig.LlamaCppUrl = url;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveBackendAsync(string backend)
|
|
{
|
|
SetGlobal(KeyBackend, backend);
|
|
_ollamaConfig.Backend = backend;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveRagModelAsync(string model)
|
|
{
|
|
SetGlobal(KeyRagModel, model);
|
|
_ollamaConfig.EmbedModel = model;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveStyleModelAsync(string model)
|
|
{
|
|
SetGlobal(KeyStyleModel, model);
|
|
_ollamaConfig.StyleModel = model;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveLektorSystemPromptAsync(string prompt)
|
|
{
|
|
Set(KeyLektorPrompt, prompt);
|
|
_ollamaConfig.LektorSystemPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveFactCheckTemplateAsync(string prompt)
|
|
{
|
|
Set(KeyFactCheckTemplate, prompt);
|
|
_ollamaConfig.FactCheckTemplate = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveSpellingPromptAsync(string prompt)
|
|
{
|
|
Set(KeySpellingPrompt, prompt);
|
|
_ollamaConfig.SpellingPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveSpellingModelAsync(string model)
|
|
{
|
|
SetGlobal(KeySpellingModel, model);
|
|
_ollamaConfig.SpellingModel = model;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveAdvocatusDiaboliPromptAsync(string prompt)
|
|
{
|
|
Set(KeyAdvocatusDiaboli, prompt);
|
|
_ollamaConfig.AdvocatusDiaboliPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveHookFinderPromptAsync(string prompt)
|
|
{
|
|
Set(KeyHookFinder, prompt);
|
|
_ollamaConfig.HookFinderPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveEli5PromptAsync(string prompt)
|
|
{
|
|
Set(KeyEli5, prompt);
|
|
_ollamaConfig.Eli5Prompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveCoAuthorBrainstormingPromptAsync(string prompt)
|
|
{
|
|
Set(KeyCoAuthor, prompt);
|
|
_ollamaConfig.CoAuthorBrainstormingPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveLektorTempAsync(double temp)
|
|
{
|
|
Set(KeyLektorTemp, temp.ToString("F1"));
|
|
_ollamaConfig.LektorTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveFactCheckTempAsync(double temp)
|
|
{
|
|
Set(KeyFactCheckTemp, temp.ToString("F1"));
|
|
_ollamaConfig.FactCheckTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveSpellingTempAsync(double temp)
|
|
{
|
|
Set(KeySpellingTemp, temp.ToString("F1"));
|
|
_ollamaConfig.SpellingTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveAdvocatusDiaboliTempAsync(double temp)
|
|
{
|
|
Set(KeyAdvocatusDiaboliTemp, temp.ToString("F1"));
|
|
_ollamaConfig.AdvocatusDiaboliTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveHookFinderTempAsync(double temp)
|
|
{
|
|
Set(KeyHookFinderTemp, temp.ToString("F1"));
|
|
_ollamaConfig.HookFinderTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveEli5TempAsync(double temp)
|
|
{
|
|
Set(KeyEli5Temp, temp.ToString("F1"));
|
|
_ollamaConfig.Eli5Temp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveCoAuthorTempAsync(double temp)
|
|
{
|
|
Set(KeyCoAuthorTemp, temp.ToString("F1"));
|
|
_ollamaConfig.CoAuthorTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechLastenheftPromptAsync(string prompt)
|
|
{
|
|
Set(KeyTechLastenheft, prompt);
|
|
_ollamaConfig.TechLastenheftPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechPflichtenheftPromptAsync(string prompt)
|
|
{
|
|
Set(KeyTechPflichtenheft, prompt);
|
|
_ollamaConfig.TechPflichtenheftPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechUseCasePromptAsync(string prompt)
|
|
{
|
|
Set(KeyTechUseCase, prompt);
|
|
_ollamaConfig.TechUseCasePrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechStakeholderPromptAsync(string prompt)
|
|
{
|
|
Set(KeyTechStakeholder, prompt);
|
|
_ollamaConfig.TechStakeholderPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechGlossarPromptAsync(string prompt)
|
|
{
|
|
Set(KeyTechGlossar, prompt);
|
|
_ollamaConfig.TechGlossarPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechQualitaetPromptAsync(string prompt)
|
|
{
|
|
Set(KeyTechQualitaet, prompt);
|
|
_ollamaConfig.TechQualitaetPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechRisikoPromptAsync(string prompt)
|
|
{
|
|
Set(KeyTechRisiko, prompt);
|
|
_ollamaConfig.TechRisikoPrompt = prompt;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechLastenheftTempAsync(double temp)
|
|
{
|
|
Set(KeyTechLastenheftTemp, temp.ToString("F1"));
|
|
_ollamaConfig.TechLastenheftTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechPflichtenheftTempAsync(double temp)
|
|
{
|
|
Set(KeyTechPflichtenheftTemp, temp.ToString("F1"));
|
|
_ollamaConfig.TechPflichtenheftTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechUseCaseTempAsync(double temp)
|
|
{
|
|
Set(KeyTechUseCaseTemp, temp.ToString("F1"));
|
|
_ollamaConfig.TechUseCaseTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechStakeholderTempAsync(double temp)
|
|
{
|
|
Set(KeyTechStakeholderTemp, temp.ToString("F1"));
|
|
_ollamaConfig.TechStakeholderTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechGlossarTempAsync(double temp)
|
|
{
|
|
Set(KeyTechGlossarTemp, temp.ToString("F1"));
|
|
_ollamaConfig.TechGlossarTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechQualitaetTempAsync(double temp)
|
|
{
|
|
Set(KeyTechQualitaetTemp, temp.ToString("F1"));
|
|
_ollamaConfig.TechQualitaetTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveTechRisikoTempAsync(double temp)
|
|
{
|
|
Set(KeyTechRisikoTemp, temp.ToString("F1"));
|
|
_ollamaConfig.TechRisikoTemp = temp;
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task SaveThemeAsync(string theme)
|
|
{
|
|
Set(KeyTheme, theme);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task<List<UserEntity>> GetUsersAsync()
|
|
{
|
|
var col = _db.GetCollection<UserEntity>("users");
|
|
return Task.FromResult(col.FindAll().ToList());
|
|
}
|
|
|
|
public Task<UserEntity> GetCurrentUserAsync()
|
|
{
|
|
var col = _db.GetCollection<UserEntity>("users");
|
|
if (_currentUserId != null)
|
|
{
|
|
var user = col.FindById(_currentUserId.Value);
|
|
if (user != null) return Task.FromResult(user);
|
|
}
|
|
return Task.FromResult(col.FindAll().FirstOrDefault() ?? new UserEntity());
|
|
}
|
|
|
|
public void SetCurrentUser(int userId)
|
|
{
|
|
_currentUserId = userId;
|
|
}
|
|
|
|
public Task<UserEntity> CreateUserAsync(string name)
|
|
{
|
|
var col = _db.GetCollection<UserEntity>("users");
|
|
var hasUsers = col.FindAll().Any();
|
|
var user = new UserEntity
|
|
{
|
|
Name = name,
|
|
Role = hasUsers ? UserRole.Author : UserRole.Administrator
|
|
};
|
|
col.Insert(user);
|
|
return Task.FromResult(user);
|
|
}
|
|
|
|
private void MigrateSchema()
|
|
{
|
|
const string schemaKey = "_schema_version";
|
|
var settings = _db.GetCollection<SettingEntity>("settings");
|
|
var schemaSetting = settings.FindOne(s => s.Key == schemaKey && s.UserId == null && s.ProjectId == null);
|
|
var currentVersion = int.TryParse(schemaSetting?.Value, out var v) ? v : 0;
|
|
|
|
if (currentVersion < 1)
|
|
{
|
|
var users = _db.GetCollection<UserEntity>("users");
|
|
var all = users.FindAll().OrderBy(u => u.Id).ToList();
|
|
if (all.Count > 0)
|
|
{
|
|
all[0].Role = UserRole.Administrator;
|
|
foreach (var u in all)
|
|
{
|
|
u.IsActive = true;
|
|
users.Update(u);
|
|
}
|
|
}
|
|
|
|
var authorExists = all.Any(u => u.Name == "Author");
|
|
if (!authorExists)
|
|
{
|
|
var authorUser = new UserEntity
|
|
{
|
|
Name = "Author",
|
|
PasswordHash = TotpHelper.HashPassword("author123"),
|
|
TwoFactorEnabled = false,
|
|
TwoFactorSecret = string.Empty,
|
|
Role = UserRole.Author,
|
|
IsActive = true
|
|
};
|
|
users.Insert(authorUser);
|
|
}
|
|
|
|
var projects = _db.GetCollection<ProjectEntity>("projects");
|
|
var orphaned = projects.Find(p => p.UserId == 0).ToList();
|
|
if (orphaned.Count > 0)
|
|
{
|
|
var admin = users.FindAll().OrderBy(u => u.Id).FirstOrDefault();
|
|
if (admin != null)
|
|
{
|
|
foreach (var p in orphaned)
|
|
{
|
|
p.UserId = admin.Id;
|
|
projects.Update(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
currentVersion = 1;
|
|
}
|
|
|
|
if (currentVersion < 2)
|
|
{
|
|
var llmKeys = new[] { KeyOllamaUrl, KeyRagModel, KeyStyleModel, KeySpellingModel };
|
|
foreach (var key in llmKeys)
|
|
{
|
|
var perUser = settings.Find(s => s.Key == key && s.UserId != null).ToList();
|
|
foreach (var s in perUser)
|
|
settings.Delete(s.Id);
|
|
|
|
if (settings.FindOne(s => s.Key == key && s.UserId == null && s.ProjectId == null) == null)
|
|
{
|
|
var defaultValue = key switch
|
|
{
|
|
var k when k == KeyOllamaUrl => _ollamaConfig.OllamaUrl,
|
|
var k when k == KeyRagModel => _ollamaConfig.EmbedModel,
|
|
var k when k == KeyStyleModel => _ollamaConfig.StyleModel,
|
|
var k when k == KeySpellingModel => _ollamaConfig.SpellingModel,
|
|
_ => ""
|
|
};
|
|
settings.Insert(new SettingEntity { Key = key, Value = defaultValue, UserId = null, ProjectId = null });
|
|
}
|
|
}
|
|
currentVersion = 2;
|
|
}
|
|
|
|
if (schemaSetting != null)
|
|
{
|
|
schemaSetting.Value = currentVersion.ToString();
|
|
settings.Update(schemaSetting);
|
|
}
|
|
else
|
|
{
|
|
settings.Insert(new SettingEntity { Key = schemaKey, Value = currentVersion.ToString(), UserId = null, ProjectId = null });
|
|
}
|
|
}
|
|
|
|
public Task LoadProjectSettingsAsync()
|
|
{
|
|
var globalKeys = new[] { KeyOllamaUrl, KeyLlamaCppUrl, KeyBackend, KeyRagModel, KeyStyleModel, KeySpellingModel };
|
|
|
|
foreach (var key in globalKeys)
|
|
{
|
|
var val = GetGlobal(key);
|
|
if (val == null) continue;
|
|
switch (key)
|
|
{
|
|
case var k when k == KeyOllamaUrl: _ollamaConfig.OllamaUrl = val; break;
|
|
case var k when k == KeyLlamaCppUrl: _ollamaConfig.LlamaCppUrl = val; break;
|
|
case var k when k == KeyBackend: _ollamaConfig.Backend = val; break;
|
|
case var k when k == KeyRagModel: _ollamaConfig.EmbedModel = val; break;
|
|
case var k when k == KeyStyleModel: _ollamaConfig.StyleModel = val; break;
|
|
case var k when k == KeySpellingModel: _ollamaConfig.SpellingModel = val; break;
|
|
}
|
|
}
|
|
|
|
var tempMap = new (string Key, Action<double> Setter)[]
|
|
{
|
|
(KeyLektorTemp, val => _ollamaConfig.LektorTemp = val),
|
|
(KeyFactCheckTemp, val => _ollamaConfig.FactCheckTemp = val),
|
|
(KeySpellingTemp, val => _ollamaConfig.SpellingTemp = val),
|
|
(KeyAdvocatusDiaboliTemp, val => _ollamaConfig.AdvocatusDiaboliTemp = val),
|
|
(KeyHookFinderTemp, val => _ollamaConfig.HookFinderTemp = val),
|
|
(KeyEli5Temp, val => _ollamaConfig.Eli5Temp = val),
|
|
(KeyCoAuthorTemp, val => _ollamaConfig.CoAuthorTemp = val),
|
|
(KeyTechLastenheftTemp, val => _ollamaConfig.TechLastenheftTemp = val),
|
|
(KeyTechPflichtenheftTemp, val => _ollamaConfig.TechPflichtenheftTemp = val),
|
|
(KeyTechUseCaseTemp, val => _ollamaConfig.TechUseCaseTemp = val),
|
|
(KeyTechStakeholderTemp, val => _ollamaConfig.TechStakeholderTemp = val),
|
|
(KeyTechGlossarTemp, val => _ollamaConfig.TechGlossarTemp = val),
|
|
(KeyTechQualitaetTemp, val => _ollamaConfig.TechQualitaetTemp = val),
|
|
(KeyTechRisikoTemp, val => _ollamaConfig.TechRisikoTemp = val),
|
|
};
|
|
|
|
foreach (var entry in tempMap)
|
|
{
|
|
var val = Get(entry.Key);
|
|
if (val != null && double.TryParse(val, out var d))
|
|
entry.Setter(d);
|
|
}
|
|
|
|
var userEntries = new (string Key, Action<string> Setter)[]
|
|
{
|
|
(KeyTheme, val => _ollamaConfig.Theme = val),
|
|
(KeyLektorPrompt, val => _ollamaConfig.LektorSystemPrompt = val),
|
|
(KeyFactCheckTemplate, val => _ollamaConfig.FactCheckTemplate = val),
|
|
(KeySpellingPrompt, val => _ollamaConfig.SpellingPrompt = val),
|
|
(KeyAdvocatusDiaboli, val => _ollamaConfig.AdvocatusDiaboliPrompt = val),
|
|
(KeyHookFinder, val => _ollamaConfig.HookFinderPrompt = val),
|
|
(KeyEli5, val => _ollamaConfig.Eli5Prompt = val),
|
|
(KeyCoAuthor, val => _ollamaConfig.CoAuthorBrainstormingPrompt = val),
|
|
(KeyTechLastenheft, val => _ollamaConfig.TechLastenheftPrompt = val),
|
|
(KeyTechPflichtenheft, val => _ollamaConfig.TechPflichtenheftPrompt = val),
|
|
(KeyTechUseCase, val => _ollamaConfig.TechUseCasePrompt = val),
|
|
(KeyTechStakeholder, val => _ollamaConfig.TechStakeholderPrompt = val),
|
|
(KeyTechGlossar, val => _ollamaConfig.TechGlossarPrompt = val),
|
|
(KeyTechQualitaet, val => _ollamaConfig.TechQualitaetPrompt = val),
|
|
(KeyTechRisiko, val => _ollamaConfig.TechRisikoPrompt = val),
|
|
(KeyLanguage, val => _ollamaConfig.Language = val),
|
|
};
|
|
|
|
foreach (var entry in userEntries)
|
|
{
|
|
var val = Get(entry.Key);
|
|
if (val != null) entry.Setter(val);
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task InitializeAsync()
|
|
{
|
|
MigrateSchema();
|
|
|
|
var settings = _db.GetCollection<SettingEntity>("settings");
|
|
|
|
var globalEntries = new (string Key, string Default)[]
|
|
{
|
|
(KeyOllamaUrl, _ollamaConfig.OllamaUrl),
|
|
(KeyLlamaCppUrl, _ollamaConfig.LlamaCppUrl),
|
|
(KeyBackend, _ollamaConfig.Backend),
|
|
(KeyRagModel, _ollamaConfig.EmbedModel),
|
|
(KeyStyleModel, _ollamaConfig.StyleModel),
|
|
(KeySpellingModel, _ollamaConfig.SpellingModel),
|
|
};
|
|
|
|
foreach (var entry in globalEntries)
|
|
{
|
|
var existing = settings.FindOne(s =>
|
|
s.Key == entry.Key && s.UserId == null && s.ProjectId == null);
|
|
|
|
if (existing != null)
|
|
{
|
|
var val = existing.Value;
|
|
if (entry.Key == KeyOllamaUrl) _ollamaConfig.OllamaUrl = val;
|
|
else if (entry.Key == KeyLlamaCppUrl) _ollamaConfig.LlamaCppUrl = val;
|
|
else if (entry.Key == KeyBackend) _ollamaConfig.Backend = val;
|
|
else if (entry.Key == KeyRagModel) _ollamaConfig.EmbedModel = val;
|
|
else if (entry.Key == KeyStyleModel) _ollamaConfig.StyleModel = val;
|
|
else if (entry.Key == KeySpellingModel) _ollamaConfig.SpellingModel = val;
|
|
}
|
|
else
|
|
{
|
|
settings.Insert(new SettingEntity
|
|
{
|
|
Key = entry.Key,
|
|
Value = entry.Default,
|
|
UserId = null,
|
|
ProjectId = null
|
|
});
|
|
}
|
|
}
|
|
|
|
if (_currentUserId == null)
|
|
{
|
|
var firstUser = _db.GetCollection<UserEntity>("users").FindAll().FirstOrDefault();
|
|
if (firstUser == null) return Task.CompletedTask;
|
|
_currentUserId = firstUser.Id;
|
|
}
|
|
|
|
var lang = _ollamaConfig.Language;
|
|
|
|
var userEntries = new (string Key, string Default)[]
|
|
{
|
|
(KeyTheme, _ollamaConfig.Theme),
|
|
(KeyLanguage, lang),
|
|
(KeyLektorPrompt, lang == "en" ? _ollamaConfig.LektorSystemPromptEn : _ollamaConfig.LektorSystemPrompt),
|
|
(KeyFactCheckTemplate, lang == "en" ? _ollamaConfig.FactCheckTemplateEn : _ollamaConfig.FactCheckTemplate),
|
|
(KeySpellingPrompt, lang == "en" ? _ollamaConfig.SpellingPromptEn : _ollamaConfig.SpellingPrompt),
|
|
(KeyAdvocatusDiaboli, lang == "en" ? _ollamaConfig.AdvocatusDiaboliPromptEn : _ollamaConfig.AdvocatusDiaboliPrompt),
|
|
(KeyHookFinder, lang == "en" ? _ollamaConfig.HookFinderPromptEn : _ollamaConfig.HookFinderPrompt),
|
|
(KeyEli5, lang == "en" ? _ollamaConfig.Eli5PromptEn : _ollamaConfig.Eli5Prompt),
|
|
(KeyCoAuthor, lang == "en" ? _ollamaConfig.CoAuthorBrainstormingPromptEn : _ollamaConfig.CoAuthorBrainstormingPrompt),
|
|
(KeyTechLastenheft, lang == "en" ? _ollamaConfig.TechLastenheftPromptEn : _ollamaConfig.TechLastenheftPrompt),
|
|
(KeyTechPflichtenheft, lang == "en" ? _ollamaConfig.TechPflichtenheftPromptEn : _ollamaConfig.TechPflichtenheftPrompt),
|
|
(KeyTechUseCase, lang == "en" ? _ollamaConfig.TechUseCasePromptEn : _ollamaConfig.TechUseCasePrompt),
|
|
(KeyTechStakeholder, lang == "en" ? _ollamaConfig.TechStakeholderPromptEn : _ollamaConfig.TechStakeholderPrompt),
|
|
(KeyTechGlossar, lang == "en" ? _ollamaConfig.TechGlossarPromptEn : _ollamaConfig.TechGlossarPrompt),
|
|
(KeyTechQualitaet, lang == "en" ? _ollamaConfig.TechQualitaetPromptEn : _ollamaConfig.TechQualitaetPrompt),
|
|
(KeyTechRisiko, lang == "en" ? _ollamaConfig.TechRisikoPromptEn : _ollamaConfig.TechRisikoPrompt),
|
|
(KeyLektorTemp, _ollamaConfig.LektorTemp.ToString("F1")),
|
|
(KeyFactCheckTemp, _ollamaConfig.FactCheckTemp.ToString("F1")),
|
|
(KeySpellingTemp, _ollamaConfig.SpellingTemp.ToString("F1")),
|
|
(KeyAdvocatusDiaboliTemp, _ollamaConfig.AdvocatusDiaboliTemp.ToString("F1")),
|
|
(KeyHookFinderTemp, _ollamaConfig.HookFinderTemp.ToString("F1")),
|
|
(KeyEli5Temp, _ollamaConfig.Eli5Temp.ToString("F1")),
|
|
(KeyCoAuthorTemp, _ollamaConfig.CoAuthorTemp.ToString("F1")),
|
|
(KeyTechLastenheftTemp, _ollamaConfig.TechLastenheftTemp.ToString("F1")),
|
|
(KeyTechPflichtenheftTemp, _ollamaConfig.TechPflichtenheftTemp.ToString("F1")),
|
|
(KeyTechUseCaseTemp, _ollamaConfig.TechUseCaseTemp.ToString("F1")),
|
|
(KeyTechStakeholderTemp, _ollamaConfig.TechStakeholderTemp.ToString("F1")),
|
|
(KeyTechGlossarTemp, _ollamaConfig.TechGlossarTemp.ToString("F1")),
|
|
(KeyTechQualitaetTemp, _ollamaConfig.TechQualitaetTemp.ToString("F1")),
|
|
(KeyTechRisikoTemp, _ollamaConfig.TechRisikoTemp.ToString("F1")),
|
|
};
|
|
|
|
foreach (var entry in userEntries)
|
|
{
|
|
var existing = settings.FindOne(s =>
|
|
s.Key == entry.Key && s.UserId == _currentUserId && s.ProjectId == _currentProjectId);
|
|
|
|
if (existing != null)
|
|
{
|
|
var val = existing.Value;
|
|
if (entry.Key == KeyTheme) _ollamaConfig.Theme = val;
|
|
else if (entry.Key == KeyLanguage) _ollamaConfig.Language = val;
|
|
else if (entry.Key == KeyLektorPrompt) _ollamaConfig.LektorSystemPrompt = val;
|
|
else if (entry.Key == KeyFactCheckTemplate) _ollamaConfig.FactCheckTemplate = val;
|
|
else if (entry.Key == KeySpellingPrompt) _ollamaConfig.SpellingPrompt = val;
|
|
else if (entry.Key == KeyAdvocatusDiaboli) _ollamaConfig.AdvocatusDiaboliPrompt = val;
|
|
else if (entry.Key == KeyHookFinder) _ollamaConfig.HookFinderPrompt = val;
|
|
else if (entry.Key == KeyEli5) _ollamaConfig.Eli5Prompt = val;
|
|
else if (entry.Key == KeyCoAuthor) _ollamaConfig.CoAuthorBrainstormingPrompt = val;
|
|
else if (entry.Key == KeyLektorTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.LektorTemp = t; }
|
|
else if (entry.Key == KeyFactCheckTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.FactCheckTemp = t; }
|
|
else if (entry.Key == KeySpellingTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.SpellingTemp = t; }
|
|
else if (entry.Key == KeyAdvocatusDiaboliTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.AdvocatusDiaboliTemp = t; }
|
|
else if (entry.Key == KeyHookFinderTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.HookFinderTemp = t; }
|
|
else if (entry.Key == KeyEli5Temp) { if (double.TryParse(val, out var t)) _ollamaConfig.Eli5Temp = t; }
|
|
else if (entry.Key == KeyCoAuthorTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.CoAuthorTemp = t; }
|
|
else if (entry.Key == KeyTechLastenheft) _ollamaConfig.TechLastenheftPrompt = val;
|
|
else if (entry.Key == KeyTechPflichtenheft) _ollamaConfig.TechPflichtenheftPrompt = val;
|
|
else if (entry.Key == KeyTechUseCase) _ollamaConfig.TechUseCasePrompt = val;
|
|
else if (entry.Key == KeyTechStakeholder) _ollamaConfig.TechStakeholderPrompt = val;
|
|
else if (entry.Key == KeyTechGlossar) _ollamaConfig.TechGlossarPrompt = val;
|
|
else if (entry.Key == KeyTechQualitaet) _ollamaConfig.TechQualitaetPrompt = val;
|
|
else if (entry.Key == KeyTechRisiko) _ollamaConfig.TechRisikoPrompt = val;
|
|
else if (entry.Key == KeyTechLastenheftTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.TechLastenheftTemp = t; }
|
|
else if (entry.Key == KeyTechPflichtenheftTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.TechPflichtenheftTemp = t; }
|
|
else if (entry.Key == KeyTechUseCaseTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.TechUseCaseTemp = t; }
|
|
else if (entry.Key == KeyTechStakeholderTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.TechStakeholderTemp = t; }
|
|
else if (entry.Key == KeyTechGlossarTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.TechGlossarTemp = t; }
|
|
else if (entry.Key == KeyTechQualitaetTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.TechQualitaetTemp = t; }
|
|
else if (entry.Key == KeyTechRisikoTemp) { if (double.TryParse(val, out var t)) _ollamaConfig.TechRisikoTemp = t; }
|
|
}
|
|
else
|
|
{
|
|
settings.Insert(new SettingEntity
|
|
{
|
|
Key = entry.Key,
|
|
Value = entry.Default,
|
|
UserId = _currentUserId,
|
|
ProjectId = _currentProjectId
|
|
});
|
|
}
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|