Size: 7.1 KB Modified: 4/07/2026 3:29 AM
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using KaiChat.Models;

namespace KaiChat.Pages;

public class SettingsModel : PageModel
{
    private readonly IConfiguration _config;
    private readonly KaiChatConfig _kaiChatConfig;

    public SettingsModel(IConfiguration config, KaiChatConfig kaiChatConfig)
    {
        _config = config;
        _kaiChatConfig = kaiChatConfig;
    }

    [BindProperty]
    public string ApiEndpoint { get; set; } = "";
    [BindProperty]
    public string ApiKey { get; set; } = "";
    [BindProperty]
    public string Model { get; set; } = "";
    [BindProperty]
    public int ModelInputTokens { get; set; } = 1_000_000;
    [BindProperty]
    public int ModelOutputTokens { get; set; } = 384_000;
    [BindProperty]
    public bool TestMode { get; set; } = false;
    [BindProperty]
    public bool NightscoutEnabled { get; set; } = false;
    [BindProperty]
    public string NightscoutBaseUrl { get; set; } = "";
    [BindProperty]
    public string NightscoutApiSecret { get; set; } = "";
    [BindProperty]
    public string NightscoutDisplayUnits { get; set; } = "mmol/L";
    [BindProperty]
    public bool NightscoutAttachLocalReadings { get; set; } = true;
    [BindProperty]
    public string NightscoutBridgeHost { get; set; } = "127.0.0.1";
    [BindProperty]
    public int NightscoutBridgePort { get; set; } = 30283;
    [BindProperty]
    public int NightscoutBridgeReadingCount { get; set; } = 10;
    [BindProperty]
    public int NightscoutBridgeTimeoutMs { get; set; } = 2500;
    public string BaseFolder { get; set; } = "";
    public List<string> SystemPromptFiles { get; set; } = new();
    public bool Saved { get; set; }

    public void OnGet()
    {
        LoadSettings();
    }

    public IActionResult OnPost()
    {
        var apiEndpoint = Clean(ApiEndpoint);
        var apiKey = Clean(ApiKey);
        var model = Clean(Model);
        var nightscoutBaseUrl = Clean(NightscoutBaseUrl);
        var nightscoutApiSecret = Clean(NightscoutApiSecret);
        var nightscoutDisplayUnits = Clean(NightscoutDisplayUnits, "mmol/L");
        var nightscoutBridgeHost = Clean(NightscoutBridgeHost, "127.0.0.1");
        // Persist to user config file for next startup
        var userConfigPath = Path.Combine(
            _config.GetValue<string>("KaiChat:BaseFolder") ?? ".",
            ".kaichatconfig.json");

        var userConfig = new Dictionary<string, string>
        {
            ["KaiChat:ApiEndpoint"] = apiEndpoint,
            ["KaiChat:ApiKey"] = apiKey,
            ["KaiChat:Model"] = model,
            ["KaiChat:ModelLimits:InputTokens"] = Math.Max(1, ModelInputTokens).ToString(),
            ["KaiChat:ModelLimits:OutputTokens"] = Math.Max(1, ModelOutputTokens).ToString(),
            ["KaiChat:TestMode"] = TestMode.ToString().ToLowerInvariant(),
            ["KaiChat:Nightscout:Enabled"] = NightscoutEnabled.ToString().ToLowerInvariant(),
            ["KaiChat:Nightscout:BaseUrl"] = nightscoutBaseUrl,
            ["KaiChat:Nightscout:ApiSecret"] = nightscoutApiSecret,
            ["KaiChat:Nightscout:DisplayUnits"] = nightscoutDisplayUnits,
            ["KaiChat:Nightscout:AttachLocalReadingsToMessages"] = NightscoutAttachLocalReadings.ToString().ToLowerInvariant(),
            ["KaiChat:Nightscout:BridgeHost"] = nightscoutBridgeHost,
            ["KaiChat:Nightscout:BridgePort"] = Math.Clamp(NightscoutBridgePort <= 0 ? 30283 : NightscoutBridgePort, 1, 65535).ToString(),
            ["KaiChat:Nightscout:BridgeReadingCount"] = Math.Clamp(NightscoutBridgeReadingCount <= 0 ? 10 : NightscoutBridgeReadingCount, 1, 50).ToString(),
            ["KaiChat:Nightscout:BridgeTimeoutMs"] = Math.Clamp(NightscoutBridgeTimeoutMs <= 0 ? 2500 : NightscoutBridgeTimeoutMs, 500, 15000).ToString()
        };

        System.IO.File.WriteAllText(userConfigPath,
            System.Text.Json.JsonSerializer.Serialize(userConfig, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }));

        // Apply in-memory immediately — no restart needed
        _kaiChatConfig.TestMode = TestMode;
        _kaiChatConfig.ApiEndpoint = apiEndpoint;
        _kaiChatConfig.ApiKey = apiKey;
        _kaiChatConfig.Model = model;
        _kaiChatConfig.ModelLimits ??= new ModelLimitsConfig();
        _kaiChatConfig.ModelLimits.InputTokens = Math.Max(1, ModelInputTokens);
        _kaiChatConfig.ModelLimits.OutputTokens = Math.Max(1, ModelOutputTokens);
        _kaiChatConfig.Nightscout ??= new NightscoutConfig();
        _kaiChatConfig.Nightscout.Enabled = NightscoutEnabled;
        _kaiChatConfig.Nightscout.BaseUrl = nightscoutBaseUrl;
        _kaiChatConfig.Nightscout.ApiSecret = nightscoutApiSecret;
        _kaiChatConfig.Nightscout.DisplayUnits = nightscoutDisplayUnits;
        _kaiChatConfig.Nightscout.AttachLocalReadingsToMessages = NightscoutAttachLocalReadings;
        _kaiChatConfig.Nightscout.BridgeHost = nightscoutBridgeHost;
        _kaiChatConfig.Nightscout.BridgePort = Math.Clamp(NightscoutBridgePort <= 0 ? 30283 : NightscoutBridgePort, 1, 65535);
        _kaiChatConfig.Nightscout.BridgeReadingCount = Math.Clamp(NightscoutBridgeReadingCount <= 0 ? 10 : NightscoutBridgeReadingCount, 1, 50);
        _kaiChatConfig.Nightscout.BridgeTimeoutMs = Math.Clamp(NightscoutBridgeTimeoutMs <= 0 ? 2500 : NightscoutBridgeTimeoutMs, 500, 15000);

        Saved = true;
        LoadSettings();
        return Page();
    }

    private void LoadSettings()
    {
        var kc = _config.GetSection("KaiChat");
        ApiEndpoint = _kaiChatConfig.ApiEndpoint;
        ApiKey = _kaiChatConfig.ApiKey;
        Model = _kaiChatConfig.Model;
        ModelInputTokens = _kaiChatConfig.GetModelInputTokenLimit();
        ModelOutputTokens = _kaiChatConfig.GetModelOutputTokenLimit();
        TestMode = _kaiChatConfig.TestMode;
        NightscoutEnabled = _kaiChatConfig.Nightscout.Enabled;
        NightscoutBaseUrl = _kaiChatConfig.Nightscout.BaseUrl;
        NightscoutApiSecret = _kaiChatConfig.Nightscout.ApiSecret;
        NightscoutDisplayUnits = string.IsNullOrWhiteSpace(_kaiChatConfig.Nightscout.DisplayUnits)
            ? "mmol/L"
            : _kaiChatConfig.Nightscout.DisplayUnits;
        NightscoutAttachLocalReadings = _kaiChatConfig.Nightscout.AttachLocalReadingsToMessages;
        NightscoutBridgeHost = string.IsNullOrWhiteSpace(_kaiChatConfig.Nightscout.BridgeHost)
            ? "127.0.0.1"
            : _kaiChatConfig.Nightscout.BridgeHost;
        NightscoutBridgePort = _kaiChatConfig.Nightscout.BridgePort > 0 ? _kaiChatConfig.Nightscout.BridgePort : 30283;
        NightscoutBridgeReadingCount = _kaiChatConfig.Nightscout.BridgeReadingCount > 0 ? _kaiChatConfig.Nightscout.BridgeReadingCount : 10;
        NightscoutBridgeTimeoutMs = _kaiChatConfig.Nightscout.BridgeTimeoutMs > 0 ? _kaiChatConfig.Nightscout.BridgeTimeoutMs : 2500;
        BaseFolder = kc["BaseFolder"] ?? "";
        SystemPromptFiles = kc.GetSection("SystemPromptFiles").Get<List<string>>() ?? new();
    }

    private static string Clean(string? value, string fallback = "")
    {
        return string.IsNullOrWhiteSpace(value) ? fallback : value.Trim();
    }
}
Offline