diff --git a/README.md b/README.md index 9c78f36..5eba2f3 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,6 @@ A Windows desktop friend application inspired by BonziBUDDY and CyberBuddy, usin - **SAPI4 Text-to-Speech**: Full SAPI4 voice support with configurable Speed, Pitch, and Volume - **Customizable Lines**: Edit welcome, idle, moved, exit, clicked, jokes, and thoughts lines - **Ollama AI Integration**: Connect to Ollama for dynamic AI-powered conversations with personality prompting - - **Token Usage Tracking**: Monitor prompt, completion, and total token usage for all interactions - - **API Key Support**: Optional authentication for secured Ollama deployments - - **Web Search**: AI can search the web using DuckDuckGo (requires compatible model) - - **URL Reading**: AI can read and process content from URLs (requires compatible model) - - **Tool/Function Calling**: Extensible tool system for enhanced AI capabilities - **Random Dialog**: Configurable random dialog feature (1 in 9000 chance per second by default) that sends custom prompts to Ollama - **User-Friendly GUI**: System tray application with comprehensive settings panel @@ -58,25 +53,10 @@ Access via tray menu: **View Log...** ### Ollama AI Settings - **Ollama URL**: Default is `http://localhost:11434` - **Model**: Select from available Ollama models -- **API Key**: Optional API key for authentication (if your Ollama deployment requires it) - **Personality Prompt**: Customize the AI's personality - **Enable Chat**: Toggle AI chat functionality - **Random Dialog**: Enable random AI-generated dialog - **Random Chance**: Set the chance of random dialog (1 in N per second) -- **Web Search**: Enable web searching capabilities (requires compatible model with tool support) -- **URL Reading**: Enable reading content from URLs (requires compatible model with tool support) - -#### Token Usage Tracking -The Ollama client now tracks token usage for all interactions: -- **Prompt Tokens**: Number of tokens in the input -- **Completion Tokens**: Number of tokens in the response -- **Total Tokens**: Sum of prompt and completion tokens -- Session tracking maintains cumulative token counts - -#### Advanced Features -- **Tool/Function Calling**: When enabled, the AI can use tools like web search and URL reading -- **DuckDuckGo Search**: No API key required for web search functionality -- **URL Content Reading**: Fetches and processes content from web pages ### Pipeline Settings - **Protocol**: Choose between Named Pipe (local) or TCP Socket (network) diff --git a/src/AI/OllamaClient.cs b/src/AI/OllamaClient.cs index acf4edc..1510e21 100644 --- a/src/AI/OllamaClient.cs +++ b/src/AI/OllamaClient.cs @@ -24,81 +24,10 @@ public class OllamaClient : IDisposable public int MaxTokens { get; set; } = 150; public double Temperature { get; set; } = 0.8; - private string _apiKey = ""; - public string ApiKey - { - get => _apiKey; - set - { - _apiKey = value; - UpdateHttpClientHeaders(); - } - } - - public bool EnableWebSearch { get; set; } = false; - public bool EnableUrlReading { get; set; } = false; - // Available animations for AI to use public List AvailableAnimations { get; set; } = new List(); private List _conversationHistory = new List(); - - // Token usage tracking - public int LastPromptTokens { get; private set; } - public int LastCompletionTokens { get; private set; } - public int LastTotalTokens { get; private set; } - public int TotalPromptTokens { get; private set; } - public int TotalCompletionTokens { get; private set; } - public int TotalTokensUsed { get; private set; } - - // Tool definitions for Ollama - private static readonly object[] _tools = new object[] - { - new - { - type = "function", - function = new - { - name = "web_search", - description = "Search the web for current information. Use this when you need up-to-date information or facts that you don't have in your training data.", - parameters = new - { - type = "object", - properties = new - { - query = new - { - type = "string", - description = "The search query to look up" - } - }, - required = new[] { "query" } - } - } - }, - new - { - type = "function", - function = new - { - name = "read_url", - description = "Read the content from a specific URL. Use this when you need to get information from a specific webpage.", - parameters = new - { - type = "object", - properties = new - { - url = new - { - type = "string", - description = "The URL to read content from" - } - }, - required = new[] { "url" } - } - } - } - }; // Enforced system prompt additions private const string ENFORCED_RULES = @" @@ -109,9 +38,6 @@ 1. NEVER use em dashes (—), asterisks (*), or emojis in your responses. 4. Keep responses short and conversational (1-3 sentences). 5. Speak naturally as a desktop companion character. "; - - // URL content reading limit (characters) - private const int MAX_URL_CONTENT_LENGTH = 2000; public OllamaClient() { @@ -120,26 +46,6 @@ public OllamaClient() Timeout = TimeSpan.FromSeconds(120) }; } - - /// - /// Sets the API key for authentication - /// - public void SetApiKey(string apiKey) - { - ApiKey = apiKey; - } - - /// - /// Updates HttpClient headers with API key if set - /// - private void UpdateHttpClientHeaders() - { - _httpClient.DefaultRequestHeaders.Remove("Authorization"); - if (!string.IsNullOrEmpty(ApiKey)) - { - _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {ApiKey}"); - } - } /// /// Tests the connection to Ollama @@ -290,66 +196,17 @@ public async Task ChatAsync(string message, CancellationToken cancellati // Add the new user message messages.Add(new { role = "user", content = message }); - // Build request object - object request; - if (EnableWebSearch || EnableUrlReading) + var request = new { - // Filter tools based on enabled features - var enabledTools = new List(); - if (EnableWebSearch && _tools.Length > 0) - { - enabledTools.Add(_tools[0]); // web_search - } - if (EnableUrlReading && _tools.Length > 1) - { - enabledTools.Add(_tools[1]); // read_url - } - - // Include only enabled tools in the request - if (enabledTools.Count > 0) + model = Model, + messages = messages, + stream = false, + options = new { - request = new - { - model = Model, - messages = messages, - stream = false, - tools = enabledTools.ToArray(), - options = new - { - num_predict = MaxTokens, - temperature = Temperature - } - }; + num_predict = MaxTokens, + temperature = Temperature } - else - { - request = new - { - model = Model, - messages = messages, - stream = false, - options = new - { - num_predict = MaxTokens, - temperature = Temperature - } - }; - } - } - else - { - request = new - { - model = Model, - messages = messages, - stream = false, - options = new - { - num_predict = MaxTokens, - temperature = Temperature - } - }; - } + }; var json = JsonConvert.SerializeObject(request); var content = new StringContent(json, Encoding.UTF8, "application/json"); @@ -361,82 +218,7 @@ public async Task ChatAsync(string message, CancellationToken cancellati var responseContent = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject(responseContent); - // Track token usage - LastPromptTokens = result.PromptEvalCount; - LastCompletionTokens = result.EvalCount; - LastTotalTokens = LastPromptTokens + LastCompletionTokens; - TotalPromptTokens += LastPromptTokens; - TotalCompletionTokens += LastCompletionTokens; - TotalTokensUsed += LastTotalTokens; - - // Check if the model wants to use tools - if (result?.Message?.ToolCalls != null && result.Message.ToolCalls.Count > 0) - { - // Execute tool calls - foreach (var toolCall in result.Message.ToolCalls) - { - if (toolCall?.Function != null) - { - var toolResult = await ExecuteToolAsync( - toolCall.Function.Name, - toolCall.Function.Arguments ?? new Dictionary() - ); - - // Add tool result to messages - messages.Add(new - { - role = "tool", - content = toolResult - }); - } - } - - // Make another request with tool results - var followUpRequest = new - { - model = Model, - messages = messages, - stream = false, - options = new - { - num_predict = MaxTokens, - temperature = Temperature - } - }; - - var followUpJson = JsonConvert.SerializeObject(followUpRequest); - var followUpContent = new StringContent(followUpJson, Encoding.UTF8, "application/json"); - var followUpResponse = await _httpClient.PostAsync($"{BaseUrl}/api/chat", followUpContent, cancellationToken); - - if (followUpResponse.IsSuccessStatusCode) - { - var followUpResponseContent = await followUpResponse.Content.ReadAsStringAsync(); - var followUpResult = JsonConvert.DeserializeObject(followUpResponseContent); - - if (followUpResult?.Message?.Content != null) - { - string cleanedResponse = CleanResponse(followUpResult.Message.Content); - - // Update token usage with follow-up request - // Add follow-up tokens to the cumulative totals - TotalPromptTokens += followUpResult.PromptEvalCount; - TotalCompletionTokens += followUpResult.EvalCount; - TotalTokensUsed += followUpResult.PromptEvalCount + followUpResult.EvalCount; - - // Update last request to include both initial and follow-up tokens - LastPromptTokens += followUpResult.PromptEvalCount; - LastCompletionTokens += followUpResult.EvalCount; - LastTotalTokens += followUpResult.PromptEvalCount + followUpResult.EvalCount; - - // Add to conversation history - _conversationHistory.Add(new ChatMessage { Role = "user", Content = message }); - _conversationHistory.Add(new ChatMessage { Role = "assistant", Content = cleanedResponse }); - - return cleanedResponse; - } - } - } - else if (result?.Message?.Content != null) + if (result?.Message?.Content != null) { string cleanedResponse = CleanResponse(result.Message.Content); @@ -525,147 +307,6 @@ public void ClearHistory() { _conversationHistory.Clear(); } - - /// - /// Resets token usage counters - /// - public void ResetTokenCounters() - { - LastPromptTokens = 0; - LastCompletionTokens = 0; - LastTotalTokens = 0; - TotalPromptTokens = 0; - TotalCompletionTokens = 0; - TotalTokensUsed = 0; - } - - /// - /// Gets a summary of token usage - /// - public string GetTokenUsageSummary() - { - return $"Last Request: {LastPromptTokens} prompt + {LastCompletionTokens} completion = {LastTotalTokens} total\n" + - $"Total Session: {TotalPromptTokens} prompt + {TotalCompletionTokens} completion = {TotalTokensUsed} total"; - } - - /// - /// Performs a web search using DuckDuckGo - /// - private async Task WebSearchAsync(string query) - { - try - { - // Use DuckDuckGo's instant answer API (no API key required) - var searchUrl = $"https://api.duckduckgo.com/?q={Uri.EscapeDataString(query)}&format=json&no_html=1&skip_disambig=1"; - var response = await _httpClient.GetAsync(searchUrl); - - if (response.IsSuccessStatusCode) - { - var content = await response.Content.ReadAsStringAsync(); - var result = JsonConvert.DeserializeObject(content); - - if (!string.IsNullOrEmpty(result?.AbstractText)) - { - return result.AbstractText; - } - - if (!string.IsNullOrEmpty(result?.Abstract)) - { - return result.Abstract; - } - - // If we have related topics, return the first one - if (result?.RelatedTopics?.Count > 0) - { - var topic = result.RelatedTopics[0]; - if (topic.Text != null) - { - return topic.Text; - } - } - - return "No relevant information found for this query."; - } - - return "Web search failed."; - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine($"Web search error: {ex.Message}"); - return $"Error performing web search: {ex.Message}"; - } - } - - /// - /// Reads content from a URL - /// - private async Task ReadUrlAsync(string url) - { - try - { - // Validate URL - if (!Uri.TryCreate(url, UriKind.Absolute, out var uri) || - (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)) - { - return "Invalid URL format. Only HTTP and HTTPS URLs are supported."; - } - - var response = await _httpClient.GetAsync(url); - - if (response.IsSuccessStatusCode) - { - var content = await response.Content.ReadAsStringAsync(); - - // Basic HTML stripping (simple approach) - content = Regex.Replace(content, @"]*>[\s\S]*?", "", RegexOptions.IgnoreCase); - content = Regex.Replace(content, @"]*>[\s\S]*?", "", RegexOptions.IgnoreCase); - content = Regex.Replace(content, @"<[^>]+>", " "); - content = Regex.Replace(content, @"\s+", " "); - content = System.Net.WebUtility.HtmlDecode(content).Trim(); - - // Limit content length to avoid excessive token usage - if (content.Length > MAX_URL_CONTENT_LENGTH) - { - content = content.Substring(0, MAX_URL_CONTENT_LENGTH) + "... (truncated)"; - } - - return content; - } - - return $"Failed to read URL. Status: {response.StatusCode}"; - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine($"URL reading error: {ex.Message}"); - return $"Error reading URL: {ex.Message}"; - } - } - - /// - /// Executes a tool call - /// - private async Task ExecuteToolAsync(string toolName, Dictionary arguments) - { - switch (toolName) - { - case "web_search": - if (arguments.ContainsKey("query")) - { - return await WebSearchAsync(arguments["query"].ToString()); - } - return "Missing 'query' parameter for web_search"; - - case "read_url": - if (arguments.ContainsKey("url")) - { - return await ReadUrlAsync(arguments["url"].ToString()); - } - return "Missing 'url' parameter for read_url"; - - default: - return $"Unknown tool: {toolName}"; - } - } public void Dispose() { @@ -693,48 +334,12 @@ private class OllamaChatResponse { [JsonProperty("message")] public OllamaChatMessage Message { get; set; } - - [JsonProperty("prompt_eval_count")] - public int PromptEvalCount { get; set; } - - [JsonProperty("eval_count")] - public int EvalCount { get; set; } - - [JsonProperty("total_duration")] - public long TotalDuration { get; set; } - - [JsonProperty("load_duration")] - public long LoadDuration { get; set; } - - [JsonProperty("prompt_eval_duration")] - public long PromptEvalDuration { get; set; } - - [JsonProperty("eval_duration")] - public long EvalDuration { get; set; } } private class OllamaChatMessage { [JsonProperty("content")] public string Content { get; set; } - - [JsonProperty("tool_calls")] - public List ToolCalls { get; set; } - } - - private class OllamaToolCall - { - [JsonProperty("function")] - public OllamaToolFunction Function { get; set; } - } - - private class OllamaToolFunction - { - [JsonProperty("name")] - public string Name { get; set; } - - [JsonProperty("arguments")] - public Dictionary Arguments { get; set; } } private class ChatMessage @@ -742,24 +347,5 @@ private class ChatMessage public string Role { get; set; } public string Content { get; set; } } - - // DuckDuckGo API response classes - private class DuckDuckGoResponse - { - [JsonProperty("AbstractText")] - public string AbstractText { get; set; } - - [JsonProperty("Abstract")] - public string Abstract { get; set; } - - [JsonProperty("RelatedTopics")] - public List RelatedTopics { get; set; } - } - - private class DuckDuckGoTopic - { - [JsonProperty("Text")] - public string Text { get; set; } - } } } diff --git a/src/Config/AppSettings.cs b/src/Config/AppSettings.cs index bf0e0db..28c741e 100644 --- a/src/Config/AppSettings.cs +++ b/src/Config/AppSettings.cs @@ -36,11 +36,8 @@ public class AppSettings // Ollama AI settings public string OllamaUrl { get; set; } = "http://localhost:11434"; public string OllamaModel { get; set; } = "llama2"; - public string OllamaApiKey { get; set; } = ""; public string PersonalityPrompt { get; set; } = "You are a helpful and friendly desktop companion. Keep responses short and conversational."; public bool EnableOllamaChat { get; set; } = false; - public bool EnableWebSearch { get; set; } = false; - public bool EnableUrlReading { get; set; } = false; // Pipeline settings public string PipelineProtocol { get; set; } = "NamedPipe"; // "NamedPipe" or "TCP" diff --git a/src/UI/MainForm.cs b/src/UI/MainForm.cs index 974b0a8..aadde23 100644 --- a/src/UI/MainForm.cs +++ b/src/UI/MainForm.cs @@ -135,10 +135,7 @@ private void InitializeManagers() { BaseUrl = _settings.OllamaUrl, Model = _settings.OllamaModel, - PersonalityPrompt = _settings.PersonalityPrompt, - ApiKey = _settings.OllamaApiKey, - EnableWebSearch = _settings.EnableWebSearch, - EnableUrlReading = _settings.EnableUrlReading + PersonalityPrompt = _settings.PersonalityPrompt }; _cancellationTokenSource = new CancellationTokenSource(); @@ -851,9 +848,6 @@ private void ApplySettings() _ollamaClient.BaseUrl = _settings.OllamaUrl; _ollamaClient.Model = _settings.OllamaModel; _ollamaClient.PersonalityPrompt = _settings.PersonalityPrompt; - _ollamaClient.ApiKey = _settings.OllamaApiKey; - _ollamaClient.EnableWebSearch = _settings.EnableWebSearch; - _ollamaClient.EnableUrlReading = _settings.EnableUrlReading; // Update available animations for AI to use if (_agentManager?.IsLoaded == true) diff --git a/src/UI/SettingsForm.cs b/src/UI/SettingsForm.cs index b6edae5..69020d3 100644 --- a/src/UI/SettingsForm.cs +++ b/src/UI/SettingsForm.cs @@ -81,9 +81,6 @@ public class SettingsForm : Form private NumericUpDown _randomChanceNumeric; private CheckBox _enablePrewrittenIdleCheckBox; private NumericUpDown _prewrittenIdleChanceNumeric; - private TextBox _apiKeyTextBox; - private CheckBox _enableWebSearchCheckBox; - private CheckBox _enableUrlReadingCheckBox; // Theme controls private ComboBox _themeComboBox; @@ -181,18 +178,15 @@ private void InitializeComponent() this.Text = "MSAgent AI Settings"; this.Size = new Size(650, 550); this.StartPosition = FormStartPosition.CenterScreen; - this.FormBorderStyle = FormBorderStyle.Sizable; - this.MaximizeBox = true; - this.MinimizeBox = true; - this.MinimumSize = new Size(650, 550); - this.AutoScroll = true; + this.FormBorderStyle = FormBorderStyle.FixedDialog; + this.MaximizeBox = false; + this.MinimizeBox = false; // Create main tab control _tabControl = new TabControl { Location = new Point(10, 10), - Size = new Size(615, 450), - Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right + Size = new Size(615, 450) }; // Create tabs @@ -211,8 +205,7 @@ private void InitializeComponent() Text = "OK", Location = new Point(365, 470), Size = new Size(80, 30), - DialogResult = DialogResult.OK, - Anchor = AnchorStyles.Bottom | AnchorStyles.Right + DialogResult = DialogResult.OK }; _okButton.Click += OnOkClick; @@ -221,16 +214,14 @@ private void InitializeComponent() Text = "Cancel", Location = new Point(455, 470), Size = new Size(80, 30), - DialogResult = DialogResult.Cancel, - Anchor = AnchorStyles.Bottom | AnchorStyles.Right + DialogResult = DialogResult.Cancel }; _applyButton = new Button { Text = "Apply", Location = new Point(545, 470), - Size = new Size(80, 30), - Anchor = AnchorStyles.Bottom | AnchorStyles.Right + Size = new Size(80, 30) }; _applyButton.Click += OnApplyClick; @@ -883,34 +874,17 @@ private void CreateOllamaTab() Size = new Size(60, 25) }; _refreshModelsButton.Click += OnRefreshModelsClick; - - var apiKeyLabel = new Label - { - Text = "API Key (optional):", - Location = new Point(15, 90), - Size = new Size(100, 20) - }; - - // API key text box with password masking - // Note: Uses PasswordChar for visual masking only. For production deployments - // requiring higher security, consider using SecureString or encrypted storage. - _apiKeyTextBox = new TextBox - { - Location = new Point(120, 87), - Size = new Size(300, 23), - PasswordChar = '*' - }; var presetLabel = new Label { Text = "Preset:", - Location = new Point(15, 125), + Location = new Point(15, 90), Size = new Size(100, 20) }; _personalityPresetComboBox = new ComboBox { - Location = new Point(120, 122), + Location = new Point(120, 87), Size = new Size(200, 23), DropDownStyle = ComboBoxStyle.DropDownList }; @@ -930,7 +904,7 @@ private void CreateOllamaTab() _applyPresetButton = new Button { Text = "Apply", - Location = new Point(330, 121), + Location = new Point(330, 86), Size = new Size(60, 25) }; _applyPresetButton.Click += OnApplyPresetClick; @@ -938,7 +912,7 @@ private void CreateOllamaTab() _savePresetButton = new Button { Text = "Save As...", - Location = new Point(395, 121), + Location = new Point(395, 86), Size = new Size(70, 25) }; _savePresetButton.Click += OnSavePresetClick; @@ -946,13 +920,13 @@ private void CreateOllamaTab() var themeLabel = new Label { Text = "UI Theme:", - Location = new Point(475, 125), + Location = new Point(475, 90), Size = new Size(60, 20) }; _themeComboBox = new ComboBox { - Location = new Point(535, 122), + Location = new Point(535, 87), Size = new Size(55, 23), DropDownStyle = ComboBoxStyle.DropDownList }; @@ -962,13 +936,13 @@ private void CreateOllamaTab() var personalityLabel = new Label { Text = "Personality Prompt:", - Location = new Point(15, 155), + Location = new Point(15, 120), Size = new Size(200, 20) }; _personalityTextBox = new TextBox { - Location = new Point(15, 175), + Location = new Point(15, 140), Size = new Size(580, 100), Multiline = true, ScrollBars = ScrollBars.Vertical @@ -977,27 +951,27 @@ private void CreateOllamaTab() _enableChatCheckBox = new CheckBox { Text = "Enable Ollama Chat", - Location = new Point(15, 285), + Location = new Point(15, 250), Size = new Size(200, 25) }; _enableRandomDialogCheckBox = new CheckBox { Text = "Enable Random Dialog (uses Ollama)", - Location = new Point(15, 315), + Location = new Point(15, 280), Size = new Size(250, 25) }; var chanceLabel = new Label { Text = "Random Chance (1 in N per second):", - Location = new Point(15, 350), + Location = new Point(15, 315), Size = new Size(220, 20) }; _randomChanceNumeric = new NumericUpDown { - Location = new Point(240, 347), + Location = new Point(240, 312), Size = new Size(100, 23), Minimum = 100, Maximum = 100000, @@ -1007,44 +981,30 @@ private void CreateOllamaTab() _enablePrewrittenIdleCheckBox = new CheckBox { Text = "Enable Pre-written Idle Lines", - Location = new Point(15, 380), + Location = new Point(15, 345), Size = new Size(220, 25) }; var prewrittenChanceLabel = new Label { Text = "Idle Chance (1 in N):", - Location = new Point(240, 383), + Location = new Point(240, 348), Size = new Size(130, 20) }; _prewrittenIdleChanceNumeric = new NumericUpDown { - Location = new Point(370, 380), + Location = new Point(370, 345), Size = new Size(80, 23), Minimum = 1, Maximum = 1000, Value = 30 }; - - _enableWebSearchCheckBox = new CheckBox - { - Text = "Enable Web Search (requires compatible model)", - Location = new Point(15, 415), - Size = new Size(300, 25) - }; - - _enableUrlReadingCheckBox = new CheckBox - { - Text = "Enable URL Reading (requires compatible model)", - Location = new Point(15, 445), - Size = new Size(300, 25) - }; var promptsLabel = new Label { Text = "Edit random dialog prompts in the 'Lines' tab. AI uses /emp/ for emphasis and &&Animation for animations.", - Location = new Point(15, 480), + Location = new Point(15, 380), Size = new Size(580, 20), ForeColor = Color.Gray }; @@ -1053,14 +1013,12 @@ private void CreateOllamaTab() { urlLabel, _ollamaUrlTextBox, _testConnectionButton, modelLabel, _ollamaModelComboBox, _refreshModelsButton, - apiKeyLabel, _apiKeyTextBox, presetLabel, _personalityPresetComboBox, _applyPresetButton, _savePresetButton, themeLabel, _themeComboBox, personalityLabel, _personalityTextBox, _enableChatCheckBox, _enableRandomDialogCheckBox, chanceLabel, _randomChanceNumeric, _enablePrewrittenIdleCheckBox, prewrittenChanceLabel, _prewrittenIdleChanceNumeric, - _enableWebSearchCheckBox, _enableUrlReadingCheckBox, promptsLabel }); } @@ -1289,7 +1247,6 @@ private void LoadSettings() // Ollama settings _ollamaUrlTextBox.Text = _settings.OllamaUrl; _ollamaModelComboBox.Text = _settings.OllamaModel; - _apiKeyTextBox.Text = _settings.OllamaApiKey; _personalityTextBox.Text = _settings.PersonalityPrompt; _enableChatCheckBox.Checked = _settings.EnableOllamaChat; _enableRandomDialogCheckBox.Checked = _settings.EnableRandomDialog; @@ -1298,8 +1255,6 @@ private void LoadSettings() _enablePrewrittenIdleCheckBox.Checked = _settings.EnablePrewrittenIdle; _prewrittenIdleChanceNumeric.Value = Math.Max(_prewrittenIdleChanceNumeric.Minimum, Math.Min(_prewrittenIdleChanceNumeric.Maximum, _settings.PrewrittenIdleChance)); - _enableWebSearchCheckBox.Checked = _settings.EnableWebSearch; - _enableUrlReadingCheckBox.Checked = _settings.EnableUrlReading; // Theme int themeIndex = _themeComboBox.Items.IndexOf(_settings.UITheme); @@ -1370,15 +1325,12 @@ private void SaveSettings() // Ollama settings _settings.OllamaUrl = _ollamaUrlTextBox.Text; _settings.OllamaModel = _ollamaModelComboBox.Text; - _settings.OllamaApiKey = _apiKeyTextBox.Text; _settings.PersonalityPrompt = _personalityTextBox.Text; _settings.EnableOllamaChat = _enableChatCheckBox.Checked; _settings.EnableRandomDialog = _enableRandomDialogCheckBox.Checked; _settings.RandomDialogChance = (int)_randomChanceNumeric.Value; _settings.EnablePrewrittenIdle = _enablePrewrittenIdleCheckBox.Checked; _settings.PrewrittenIdleChance = (int)_prewrittenIdleChanceNumeric.Value; - _settings.EnableWebSearch = _enableWebSearchCheckBox.Checked; - _settings.EnableUrlReading = _enableUrlReadingCheckBox.Checked; // Theme _settings.UITheme = _themeComboBox.SelectedItem?.ToString() ?? "Default";