journal/Journal.Core/Services/Config/JournalConfigService.cs
stan44 069b38071c Added Web WebGateway
Added connector so gateway works.
scripts are much more polished and functional.
2026-02-27 11:03:53 -06:00

109 lines
5.1 KiB
C#

using Journal.Core.Models;
namespace Journal.Core.Services.Config;
public sealed class JournalConfigService : IJournalConfigService
{
public JournalConfig Current => BuildConfig();
private static JournalConfig BuildConfig()
{
var projectRoot = ResolveProjectRoot();
var appDirectory = ResolvePath("JOURNAL_APP_DIR", Path.Combine(projectRoot, "journal"));
var dataDirectory = ResolvePath("JOURNAL_DATA_DIR", Path.Combine(appDirectory, "data"));
var vaultDirectory = ResolvePath("JOURNAL_VAULT_DIR", Path.Combine(appDirectory, "vault"));
var logDirectory = ResolvePath("JOURNAL_LOG_DIR", Path.Combine(projectRoot, "logs"));
var pidFile = ResolvePath("JOURNAL_PID_FILE", Path.Combine(logDirectory, "nicegui_server.pid"));
var serverControlFile = ResolvePath("JOURNAL_SERVER_CONTROL_FILE", Path.Combine(logDirectory, "server_control.action"));
var nlpBackend = (Environment.GetEnvironmentVariable("JOURNAL_NLP_BACKEND") ?? "auto").Trim().ToLowerInvariant();
if (nlpBackend is not ("auto" or "spacy" or "fallback"))
nlpBackend = "auto";
var aiProvider = (Environment.GetEnvironmentVariable("JOURNAL_AI_PROVIDER") ?? "none").Trim().ToLowerInvariant();
if (aiProvider is not ("none" or "python-sidecar"))
aiProvider = "none";
var pythonExecutable = Environment.GetEnvironmentVariable("JOURNAL_PYTHON_EXE");
if (string.IsNullOrWhiteSpace(pythonExecutable))
pythonExecutable = "python";
var defaultAiSidecarPath = Path.Combine(projectRoot, "journal", "ai", "sidecar.py");
var pythonAiSidecarPath = ResolvePath("JOURNAL_AI_SIDECAR_PATH", defaultAiSidecarPath);
var aiSidecarTimeoutMs = ParseInt("JOURNAL_AI_TIMEOUT_MS", 45000);
return new JournalConfig(
ProjectRoot: projectRoot,
AppDirectory: appDirectory,
DataDirectory: dataDirectory,
VaultDirectory: vaultDirectory,
LogDirectory: logDirectory,
PidFile: pidFile,
ServerControlFile: serverControlFile,
DatabaseFilename: Environment.GetEnvironmentVariable("JOURNAL_DATABASE_FILENAME") ?? "journal_cache.db",
MonthlyVaultFormat: Environment.GetEnvironmentVariable("JOURNAL_MONTHLY_VAULT_FORMAT") ?? "%Y-%m.vault",
CloudAiApiKey: Environment.GetEnvironmentVariable("CLOUDAI_API_KEY") ?? "",
CloudAiApiUrl: Environment.GetEnvironmentVariable("CLOUDAI_API_URL") ?? "",
LlamaCppUrl: Environment.GetEnvironmentVariable("LLAMA_CPP_URL") ?? "http://127.0.0.1:8085/v1/completions",
LlamaCppModel: Environment.GetEnvironmentVariable("LLAMA_CPP_MODEL") ?? "qwen/qwen3-4b",
LlamaCppTimeout: ParseInt("LLAMA_CPP_TIMEOUT", 6000),
EmbeddingApiUrl: Environment.GetEnvironmentVariable("EMBEDDING_API_URL") ?? "http://127.0.0.1:8086/v1/embeddings",
EmbeddingModelName: Environment.GetEnvironmentVariable("EMBEDDING_MODEL_NAME") ?? "text-embedding-nomic-embed-text-v2-moe",
ModelContextTokens: ParseInt("MODEL_CONTEXT_TOKENS", 131072),
ChunkTokenBudget: ParseInt("CHUNK_TOKEN_BUDGET", 120000),
MicrophoneDeviceIndex: ParseNullableInt("MICROPHONE_DEVICE_INDEX"),
SpeechRecognitionEngine: Environment.GetEnvironmentVariable("SPEECH_RECOGNITION_ENGINE") ?? "whisper",
WhisperModelSize: Environment.GetEnvironmentVariable("WHISPER_MODEL_SIZE") ?? "base",
NlpBackend: nlpBackend,
AiProvider: aiProvider,
PythonExecutable: pythonExecutable,
PythonAiSidecarPath: pythonAiSidecarPath,
AiSidecarTimeoutMs: aiSidecarTimeoutMs);
}
private static string ResolveProjectRoot()
{
var envRoot = Environment.GetEnvironmentVariable("JOURNAL_PROJECT_ROOT");
if (!string.IsNullOrWhiteSpace(envRoot))
return Path.GetFullPath(envRoot);
var cwd = Directory.GetCurrentDirectory();
if (Directory.Exists(Path.Combine(cwd, "journal")))
return Path.GetFullPath(cwd);
var upOne = Path.GetFullPath(Path.Combine(cwd, ".."));
if (Directory.Exists(Path.Combine(upOne, "journal")))
return upOne;
var upTwo = Path.GetFullPath(Path.Combine(cwd, "..", ".."));
if (Directory.Exists(Path.Combine(upTwo, "journal")))
return upTwo;
return Path.GetFullPath(cwd);
}
private static string ResolvePath(string envVar, string defaultPath)
{
var value = Environment.GetEnvironmentVariable(envVar);
var raw = string.IsNullOrWhiteSpace(value) ? defaultPath : value;
return Path.GetFullPath(raw);
}
private static int ParseInt(string envVar, int defaultValue)
{
var value = Environment.GetEnvironmentVariable(envVar);
return int.TryParse(value, out var parsed) ? parsed : defaultValue;
}
private static int? ParseNullableInt(string envVar)
{
var value = Environment.GetEnvironmentVariable(envVar);
if (string.IsNullOrWhiteSpace(value))
return null;
return int.TryParse(value, out var parsed) ? parsed : null;
}
}