feat: Enhance AgentChatWidget with system prompt management and project settings

- Updated system prompt loading functionality to support both version 1 and version 2 prompts, allowing users to load built-in prompts directly.
- Implemented custom system prompt loading and saving capabilities, enabling users to manage their prompts more effectively.
- Added methods to load and save agent settings from/to project files, including AI provider configurations and custom prompts.
- Improved user feedback with toast notifications for successful and failed operations related to system prompts and settings.
This commit is contained in:
scawful
2025-10-04 21:37:56 -04:00
parent dec8314a55
commit 9b51cd09f6
8 changed files with 227 additions and 53 deletions

View File

@@ -8,6 +8,7 @@
#include <string>
#include <utility>
#include <vector>
#include <fstream>
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
@@ -18,6 +19,7 @@
#include "app/editor/system/proposal_drawer.h"
#include "app/editor/system/toast_manager.h"
#include "app/gui/icons.h"
#include "app/core/project.h"
#include "imgui/imgui.h"
#include "imgui/misc/cpp/imgui_stdlib.h"
@@ -1644,19 +1646,17 @@ void AgentChatWidget::RenderSystemPromptEditor() {
ImGui::BeginChild("SystemPromptEditor", ImVec2(0, 0), false);
// Toolbar
if (ImGui::Button(ICON_MD_FOLDER_OPEN " Load Default")) {
// Load system_prompt_v2.txt
std::string prompt_path = core::GetConfigDirectory() + "/../assets/agent/system_prompt_v2.txt";
std::ifstream file(prompt_path);
if (file.is_open()) {
if (ImGui::Button(ICON_MD_FOLDER_OPEN " Load V1")) {
// Load embedded system_prompt.txt (v1)
std::string prompt_v1 = core::LoadFile("assets/agent/system_prompt.txt");
if (!prompt_v1.empty()) {
// Find or create system prompt tab
bool found = false;
for (auto& tab : open_files_) {
if (tab.is_system_prompt) {
std::stringstream buffer;
buffer << file.rdbuf();
tab.editor.SetText(buffer.str());
tab.filepath = prompt_path;
tab.editor.SetText(prompt_v1);
tab.filepath = ""; // Not saved to disk
tab.filename = "system_prompt_v1.txt (built-in)";
found = true;
break;
}
@@ -1664,39 +1664,80 @@ void AgentChatWidget::RenderSystemPromptEditor() {
if (!found) {
FileEditorTab tab;
tab.filename = "system_prompt_v2.txt";
tab.filepath = prompt_path;
tab.filename = "system_prompt_v1.txt (built-in)";
tab.filepath = "";
tab.is_system_prompt = true;
tab.editor.SetLanguageDefinition(TextEditor::LanguageDefinition::CPlusPlus());
std::stringstream buffer;
buffer << file.rdbuf();
tab.editor.SetText(buffer.str());
tab.editor.SetText(prompt_v1);
open_files_.push_back(std::move(tab));
active_file_tab_ = static_cast<int>(open_files_.size()) - 1;
}
if (toast_manager_) {
toast_manager_->Show("System prompt loaded", ToastType::kSuccess);
toast_manager_->Show("System prompt V1 loaded", ToastType::kSuccess);
}
} else if (toast_manager_) {
toast_manager_->Show("Could not load system prompt file", ToastType::kError);
toast_manager_->Show("Could not load system prompt V1", ToastType::kError);
}
}
ImGui::SameLine();
if (ImGui::Button(ICON_MD_SAVE " Save")) {
// Save the current system prompt
if (ImGui::Button(ICON_MD_FOLDER_OPEN " Load V2")) {
// Load embedded system_prompt_v2.txt
std::string prompt_v2 = core::LoadFile("assets/agent/system_prompt_v2.txt");
if (!prompt_v2.empty()) {
// Find or create system prompt tab
bool found = false;
for (auto& tab : open_files_) {
if (tab.is_system_prompt) {
tab.editor.SetText(prompt_v2);
tab.filepath = ""; // Not saved to disk
tab.filename = "system_prompt_v2.txt (built-in)";
found = true;
break;
}
}
if (!found) {
FileEditorTab tab;
tab.filename = "system_prompt_v2.txt (built-in)";
tab.filepath = "";
tab.is_system_prompt = true;
tab.editor.SetLanguageDefinition(TextEditor::LanguageDefinition::CPlusPlus());
tab.editor.SetText(prompt_v2);
open_files_.push_back(std::move(tab));
active_file_tab_ = static_cast<int>(open_files_.size()) - 1;
}
if (toast_manager_) {
toast_manager_->Show("System prompt V2 loaded", ToastType::kSuccess);
}
} else if (toast_manager_) {
toast_manager_->Show("Could not load system prompt V2", ToastType::kError);
}
}
ImGui::SameLine();
if (ImGui::Button(ICON_MD_SAVE " Save to Project")) {
// Save the current system prompt to project directory
for (auto& tab : open_files_) {
if (tab.is_system_prompt && !tab.filepath.empty()) {
std::ofstream file(tab.filepath);
if (file.is_open()) {
file << tab.editor.GetText();
tab.modified = false;
if (toast_manager_) {
toast_manager_->Show("System prompt saved", ToastType::kSuccess);
if (tab.is_system_prompt) {
auto save_path = core::FileDialogWrapper::ShowSaveFileDialog(
"custom_system_prompt", "txt");
if (!save_path.empty()) {
std::ofstream file(save_path);
if (file.is_open()) {
file << tab.editor.GetText();
tab.filepath = save_path;
tab.filename = core::GetFileName(save_path);
tab.modified = false;
if (toast_manager_) {
toast_manager_->Show(absl::StrFormat("System prompt saved to %s", save_path),
ToastType::kSuccess);
}
} else if (toast_manager_) {
toast_manager_->Show("Failed to save system prompt", ToastType::kError);
}
} else if (toast_manager_) {
toast_manager_->Show("Failed to save system prompt", ToastType::kError);
}
break;
}
@@ -1705,10 +1746,56 @@ void AgentChatWidget::RenderSystemPromptEditor() {
ImGui::SameLine();
if (ImGui::Button(ICON_MD_NOTE_ADD " Create New")) {
CreateNewFileInEditor("system_prompt_custom.txt");
if (!open_files_.empty()) {
open_files_.back().is_system_prompt = true;
open_files_.back().editor.SetText("# Custom System Prompt\n\nEnter your custom system prompt here...\n");
FileEditorTab tab;
tab.filename = "custom_system_prompt.txt (unsaved)";
tab.filepath = "";
tab.is_system_prompt = true;
tab.modified = true;
tab.editor.SetLanguageDefinition(TextEditor::LanguageDefinition::CPlusPlus());
tab.editor.SetText("# Custom System Prompt\n\nEnter your custom system prompt here...\n");
open_files_.push_back(std::move(tab));
active_file_tab_ = static_cast<int>(open_files_.size()) - 1;
}
ImGui::SameLine();
if (ImGui::Button(ICON_MD_FOLDER_OPEN " Load Custom")) {
auto filepath = core::FileDialogWrapper::ShowOpenFileDialog();
if (!filepath.empty()) {
std::ifstream file(filepath);
if (file.is_open()) {
bool found = false;
for (auto& tab : open_files_) {
if (tab.is_system_prompt) {
std::stringstream buffer;
buffer << file.rdbuf();
tab.editor.SetText(buffer.str());
tab.filepath = filepath;
tab.filename = core::GetFileName(filepath);
tab.modified = false;
found = true;
break;
}
}
if (!found) {
FileEditorTab tab;
tab.filename = core::GetFileName(filepath);
tab.filepath = filepath;
tab.is_system_prompt = true;
tab.editor.SetLanguageDefinition(TextEditor::LanguageDefinition::CPlusPlus());
std::stringstream buffer;
buffer << file.rdbuf();
tab.editor.SetText(buffer.str());
open_files_.push_back(std::move(tab));
active_file_tab_ = static_cast<int>(open_files_.size()) - 1;
}
if (toast_manager_) {
toast_manager_->Show("Custom system prompt loaded", ToastType::kSuccess);
}
} else if (toast_manager_) {
toast_manager_->Show("Could not load file", ToastType::kError);
}
}
}
@@ -1919,5 +2006,83 @@ void AgentChatWidget::CreateNewFileInEditor(const std::string& filename) {
active_file_tab_ = static_cast<int>(open_files_.size()) - 1;
}
void AgentChatWidget::LoadAgentSettingsFromProject(const core::YazeProject& project) {
// Load AI provider settings from project
agent_config_.ai_provider = project.agent_settings.ai_provider;
agent_config_.ai_model = project.agent_settings.ai_model;
agent_config_.ollama_host = project.agent_settings.ollama_host;
agent_config_.gemini_api_key = project.agent_settings.gemini_api_key;
agent_config_.show_reasoning = project.agent_settings.show_reasoning;
agent_config_.verbose = project.agent_settings.verbose;
agent_config_.max_tool_iterations = project.agent_settings.max_tool_iterations;
agent_config_.max_retry_attempts = project.agent_settings.max_retry_attempts;
// Copy to buffer for ImGui
strncpy(agent_config_.provider_buffer, agent_config_.ai_provider.c_str(),
sizeof(agent_config_.provider_buffer) - 1);
strncpy(agent_config_.model_buffer, agent_config_.ai_model.c_str(),
sizeof(agent_config_.model_buffer) - 1);
strncpy(agent_config_.ollama_host_buffer, agent_config_.ollama_host.c_str(),
sizeof(agent_config_.ollama_host_buffer) - 1);
strncpy(agent_config_.gemini_key_buffer, agent_config_.gemini_api_key.c_str(),
sizeof(agent_config_.gemini_key_buffer) - 1);
// Load custom system prompt if specified
if (project.agent_settings.use_custom_prompt &&
!project.agent_settings.custom_system_prompt.empty()) {
std::string prompt_path = project.GetAbsolutePath(project.agent_settings.custom_system_prompt);
std::ifstream file(prompt_path);
if (file.is_open()) {
// Load into system prompt tab
bool found = false;
for (auto& tab : open_files_) {
if (tab.is_system_prompt) {
std::stringstream buffer;
buffer << file.rdbuf();
tab.editor.SetText(buffer.str());
tab.filepath = prompt_path;
tab.filename = core::GetFileName(prompt_path);
found = true;
break;
}
}
if (!found) {
FileEditorTab tab;
tab.filename = core::GetFileName(prompt_path);
tab.filepath = prompt_path;
tab.is_system_prompt = true;
tab.editor.SetLanguageDefinition(TextEditor::LanguageDefinition::CPlusPlus());
std::stringstream buffer;
buffer << file.rdbuf();
tab.editor.SetText(buffer.str());
open_files_.push_back(std::move(tab));
}
}
}
}
void AgentChatWidget::SaveAgentSettingsToProject(core::YazeProject& project) {
// Save AI provider settings to project
project.agent_settings.ai_provider = agent_config_.ai_provider;
project.agent_settings.ai_model = agent_config_.ai_model;
project.agent_settings.ollama_host = agent_config_.ollama_host;
project.agent_settings.gemini_api_key = agent_config_.gemini_api_key;
project.agent_settings.show_reasoning = agent_config_.show_reasoning;
project.agent_settings.verbose = agent_config_.verbose;
project.agent_settings.max_tool_iterations = agent_config_.max_tool_iterations;
project.agent_settings.max_retry_attempts = agent_config_.max_retry_attempts;
// Check if a custom system prompt is loaded
for (const auto& tab : open_files_) {
if (tab.is_system_prompt && !tab.filepath.empty()) {
project.agent_settings.custom_system_prompt =
project.GetRelativePath(tab.filepath);
project.agent_settings.use_custom_prompt = true;
break;
}
}
}
} // namespace editor
} // namespace yaze

View File

@@ -12,6 +12,7 @@
#include "absl/time/time.h"
#include "app/gui/modules/text_editor.h"
#include "cli/service/agent/conversational_agent_service.h"
#include "core/project.h"
namespace yaze {
@@ -176,6 +177,10 @@ public:
// Agent configuration accessors
const AgentConfigState& GetAgentConfig() const { return agent_config_; }
void UpdateAgentConfig(const AgentConfigState& config);
// Load agent settings from project
void LoadAgentSettingsFromProject(const core::YazeProject& project);
void SaveAgentSettingsToProject(core::YazeProject& project);
// Collaboration history management (public so EditorManager can call them)
void SwitchToSharedHistory(const std::string& session_id);

View File

@@ -514,7 +514,7 @@ void EditorManager::Initialize(const std::string& filename) {
context_.shortcut_manager.GetKeys("Open"),
context_.shortcut_manager.GetCallback("Open")},
{absl::StrCat(ICON_MD_HISTORY, " Open Recent"), "", []() {},
[]() { return !manager.GetRecentFiles().empty(); }, recent_files},
[&manager]() { return !manager.GetRecentFiles().empty(); }, recent_files},
{absl::StrCat(ICON_MD_FILE_DOWNLOAD, " Save"),
context_.shortcut_manager.GetKeys("Save"),
context_.shortcut_manager.GetCallback("Save")},

View File

@@ -1,6 +1,7 @@
#include "app/emu/emulator.h"
#include <cstdint>
#include <fstream>
#include <vector>
#include "app/core/platform/file_dialog.h"