diff --git a/FlowVision/FlowVision.csproj b/FlowVision/FlowVision.csproj
index 7888030..a7b5355 100644
--- a/FlowVision/FlowVision.csproj
+++ b/FlowVision/FlowVision.csproj
@@ -183,6 +183,8 @@
Form1.cs
+
+
diff --git a/FlowVision/Form1.cs b/FlowVision/Form1.cs
index 6fb827d..4a64b3d 100644
--- a/FlowVision/Form1.cs
+++ b/FlowVision/Form1.cs
@@ -11,6 +11,7 @@
using Microsoft.SemanticKernel.ChatCompletion;
// Add System.Speech namespace
using System.Speech.Recognition;
+using FlowVision.lib.UI;
namespace FlowVision
{
@@ -24,6 +25,7 @@ public partial class Form1 : Form
// Speech recognition components
private SpeechRecognitionService speechRecognition;
private bool isListening = false;
+ private ThemeManager _themeManager; // Add ThemeManager field declaration
// Add a delegate for handling plugin output messages
public delegate void PluginOutputHandler(string message);
@@ -49,6 +51,60 @@ private void azureOpenAIToolStripMenuItem_Click(object sender, EventArgs e)
}
}
+ private void ApplyTheme(string themeName = null) // Fix ApplyTheme method to handle parameter
+ {
+ // Initialize ThemeManager if it doesn't exist yet
+ if (_themeManager == null)
+ {
+ _themeManager = new ThemeManager();
+ }
+
+ // Use provided theme name or current theme from ThemeManager
+ string theme = themeName ?? _themeManager.CurrentTheme;
+
+ if (theme == "Dark")
+ {
+ ApplyDarkTheme();
+ }
+ else
+ {
+ ApplyLightTheme();
+ }
+ }
+
+ private void ApplyLightTheme()
+ {
+ // Let ThemeManager handle applying the light theme to all controls
+ _themeManager.ApplyThemeToControls(this);
+
+ // Update status indicator
+ UpdateStatusIndicators();
+ }
+
+ private void ApplyDarkTheme()
+ {
+ // Let ThemeManager handle applying the dark theme to all controls
+ _themeManager.ApplyThemeToControls(this);
+
+ // Apply specific overrides for any controls that need special handling
+
+ // Update status indicator
+ UpdateStatusIndicators();
+ }
+
+ private void UpdateStatusIndicators() // Add missing UpdateStatusIndicators method
+ {
+ // Update any status indicators based on current state
+ // This can be extended later if more indicators are added
+
+ // Update microphone button appearance based on isListening state
+ if (microphoneButton != null)
+ {
+ microphoneButton.Text = isListening ? "βΉοΈ" : "π€";
+ microphoneButton.BackColor = isListening ? Color.Red : SystemColors.Control;
+ }
+ }
+
private void Form1_Load(object sender, EventArgs e)
{
// Check if tools are configured, if not, create default configuration
@@ -59,7 +115,9 @@ private void Form1_Load(object sender, EventArgs e)
var defaultConfig = new ToolConfig();
defaultConfig.SaveConfig(toolConfigName);
}
-
+ // Add this call after initializing UI components
+ ApplyTheme();
+
// Create messages panel as a FlowLayoutPanel with auto-scroll
messagesPanel = new FlowLayoutPanel
{
@@ -114,7 +172,7 @@ private void Form1_Load(object sender, EventArgs e)
// Initialize speech recognition service
InitializeSpeechRecognition();
-
+
// Handle window resize to adjust message widths
this.Resize += (s, args) =>
{
@@ -147,17 +205,18 @@ private void InitializeSpeechRecognition()
try
{
var toolConfig = ToolConfig.LoadConfig("toolsconfig");
-
+
// Only initialize if speech recognition is enabled in config
if (toolConfig.EnableSpeechRecognition)
{
speechRecognition = new SpeechRecognitionService();
- speechRecognition.SpeechRecognized += (sender, result) =>
+ speechRecognition.SpeechRecognized += (sender, result) =>
{
// Use Invoke to update UI from a different thread
if (this.InvokeRequired)
{
- this.Invoke(new Action((text) => {
+ this.Invoke(new Action((text) =>
+ {
userInputTextBox.Text = text;
}), result);
}
@@ -166,7 +225,7 @@ private void InitializeSpeechRecognition()
userInputTextBox.Text = result;
}
};
-
+
// Add handler for voice commands
if (toolConfig.EnableVoiceCommands)
{
@@ -174,7 +233,8 @@ private void InitializeSpeechRecognition()
{
if (this.InvokeRequired)
{
- this.Invoke(new Action(() => {
+ this.Invoke(new Action(() =>
+ {
if (!string.IsNullOrWhiteSpace(userInputTextBox.Text))
{
AddMessage("System", $"Voice command recognized: \"{command}\"", true);
@@ -191,7 +251,7 @@ private void InitializeSpeechRecognition()
}
}
};
-
+
// Start continuous listening if voice commands are enabled
if (toolConfig.EnableVoiceCommands)
{
@@ -234,21 +294,21 @@ private void StartListening()
try
{
var toolConfig = ToolConfig.LoadConfig("toolsconfig");
-
+
// Clear existing text before starting to listen
userInputTextBox.Text = "";
-
+
// Change button appearance to indicate recording
microphoneButton.Text = "βΉοΈ";
microphoneButton.BackColor = Color.Red;
isListening = true;
-
+
// Start listening
speechRecognition.StartListening();
-
+
// Add temporary message to indicate we're listening
- AddMessage("System", "Listening... Speak now." +
- (toolConfig.EnableVoiceCommands ?
+ AddMessage("System", "Listening... Speak now." +
+ (toolConfig.EnableVoiceCommands ?
$" Say \"{toolConfig.VoiceCommandPhrase}\" to send your message." : ""), true);
}
catch (Exception ex)
@@ -266,13 +326,13 @@ private void StopListening()
microphoneButton.Text = "π€";
microphoneButton.BackColor = SystemColors.Control;
isListening = false;
-
+
// Stop listening
speechRecognition.StopListening();
-
+
// Remove the listening message
RemoveMessagesByAuthor("System");
-
+
// If we have recognized text, send it automatically
if (!string.IsNullOrWhiteSpace(userInputTextBox.Text))
{
@@ -312,7 +372,7 @@ private async void SendButton_Click(object sender, EventArgs e)
{
string aiResponse = await GetAIResponseAsync(userInput);
AddMessage("AI", aiResponse, true);
-
+
// Check if we should retain chat history
var toolConfig = ToolConfig.LoadConfig("toolsconfig");
if (!toolConfig.RetainChatHistory)
@@ -327,7 +387,7 @@ private async void SendButton_Click(object sender, EventArgs e)
catch (Exception ex)
{
MessageBox.Show($"Error communicating with AI: {ex.Message}", "Error");
-
+
allowUserInput(true);
}
@@ -341,46 +401,52 @@ private async Task GetAIResponseAsync(string userInput)
// Get the current config to determine which model to use
var actionerConfig = APIConfig.LoadConfig("actioner");
var githubConfig = APIConfig.LoadConfig("github");
- var toolConfig = ToolConfig.LoadConfig("toolsconfig");
// Create a StringBuilder to collect plugin output
StringBuilder pluginOutput = new StringBuilder();
-
+
// Define a plugin output handler that adds messages to the plugin output
- PluginOutputHandler outputHandler = (message) => {
+ PluginOutputHandler outputHandler = (message) =>
+ {
pluginOutput.AppendLine(message);
};
// Show a pre-execution notification to the user in the UI
AddMessage("System", "Your request is being processed. Please wait...", true);
-
+
string aiResponse = string.Empty;
-
+
// Use TaskNotifier to wrap the action execution with notifications
try
{
await TaskNotifier.RunWithNotificationAsync(
- "Request Processing",
+ "Request Processing",
"Processing your request and preparing tools",
async () =>
{
+ var toolConfig = ToolConfig.LoadConfig("toolsconfig");
+
// Use Actioner model with the notification infrastructure
Actioner actioner = new Actioner(outputHandler);
- if(toolConfig.RetainChatHistory)
+
+ // Set multi-agent mode based on tool configuration
+ actioner.SetMultiAgentMode(toolConfig.EnableMultiAgentMode);
+
+ if (toolConfig.RetainChatHistory)
{
actioner.SetChatHistory(chatHistory);
}
-
+
// Execute the action and get the AI response
aiResponse = await actioner.ExecuteAction(userInput);
});
-
+
// If there's plugin output, prepend it to the AI response
if (pluginOutput.Length > 0)
{
aiResponse = $"{pluginOutput}\n\n{aiResponse}";
}
-
+
// Remove the "processing" message from the UI
RemoveMessageIfSystem();
return aiResponse;
@@ -389,15 +455,31 @@ await TaskNotifier.RunWithNotificationAsync(
{
// Remove the "processing" message from the UI
RemoveMessageIfSystem();
-
+
return $"Error processing request: {ex.Message}";
}
}
- // Helper method to remove system messages
- private void RemoveMessageIfSystem()
+ private void RemoveMessageIfSystem() // Add missing RemoveMessageIfSystem method
{
+ // Find and remove any "System" messages that indicate processing
+ for (int i = messagesPanel.Controls.Count - 1; i >= 0; i--)
+ {
+ Control c = messagesPanel.Controls[i];
+ if (c is Panel bubble)
+ {
+ Label authorLabel = bubble.Controls.OfType