feat: Enhance Agent Editor and Chat Widget for Improved Configuration and Collaboration
- Introduced a comprehensive AI Agent configuration dashboard, allowing users to select providers, models, and adjust settings. - Updated the AgentChatWidget to include a reactive UI for collaboration status and improved connection management. - Enhanced the EditorManager to initialize the agent editor with dependencies and streamline the editor selection process. - Added functionality to clear recent editors upon loading a new ROM, ensuring a fresh start for user sessions. - Improved the menu structure to include new options for the AI Agent, enhancing user interaction and accessibility.
This commit is contained in:
@@ -490,32 +490,15 @@ void AgentChatWidget::Draw() {
|
|||||||
ImGui::SetNextWindowSize(ImVec2(1200, 800), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(1200, 800), ImGuiCond_FirstUseEver);
|
||||||
ImGui::Begin(title_.c_str(), &active_, ImGuiWindowFlags_MenuBar);
|
ImGui::Begin(title_.c_str(), &active_, ImGuiWindowFlags_MenuBar);
|
||||||
|
|
||||||
// Modern menu bar
|
// Simplified menu bar
|
||||||
if (ImGui::BeginMenuBar()) {
|
if (ImGui::BeginMenuBar()) {
|
||||||
if (ImGui::BeginMenu("File")) {
|
if (ImGui::BeginMenu(ICON_MD_MENU " Actions")) {
|
||||||
if (ImGui::MenuItem(ICON_MD_SAVE " Export History")) {
|
|
||||||
// TODO: Implement export
|
|
||||||
}
|
|
||||||
if (ImGui::MenuItem(ICON_MD_FOLDER_OPEN " Import History")) {
|
|
||||||
// TODO: Implement import
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
|
||||||
if (ImGui::MenuItem(ICON_MD_DELETE_FOREVER " Clear History")) {
|
if (ImGui::MenuItem(ICON_MD_DELETE_FOREVER " Clear History")) {
|
||||||
agent_service_.ResetConversation();
|
agent_service_.ResetConversation();
|
||||||
if (toast_manager_) {
|
if (toast_manager_) {
|
||||||
toast_manager_->Show("Chat history cleared", ToastType::kInfo, 2.5f);
|
toast_manager_->Show("Chat history cleared", ToastType::kInfo, 2.5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Agent")) {
|
|
||||||
if (ImGui::MenuItem(ICON_MD_SETTINGS " Configure", nullptr, show_agent_config_)) {
|
|
||||||
show_agent_config_ = !show_agent_config_;
|
|
||||||
}
|
|
||||||
if (ImGui::MenuItem(ICON_MD_TERMINAL " Commands", nullptr, show_z3ed_commands_)) {
|
|
||||||
show_z3ed_commands_ = !show_z3ed_commands_;
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::MenuItem(ICON_MD_REFRESH " Reset Conversation")) {
|
if (ImGui::MenuItem(ICON_MD_REFRESH " Reset Conversation")) {
|
||||||
agent_service_.ResetConversation();
|
agent_service_.ResetConversation();
|
||||||
@@ -526,290 +509,182 @@ void AgentChatWidget::Draw() {
|
|||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Collaboration")) {
|
if (ImGui::BeginMenu(ICON_MD_VIEW_SIDEBAR " Panels")) {
|
||||||
if (ImGui::MenuItem(ICON_MD_SYNC " ROM Sync", nullptr, show_rom_sync_)) {
|
ImGui::MenuItem(ICON_MD_SETTINGS " Configuration", nullptr, &show_agent_config_);
|
||||||
show_rom_sync_ = !show_rom_sync_;
|
ImGui::MenuItem(ICON_MD_TERMINAL " Commands", nullptr, &show_z3ed_commands_);
|
||||||
}
|
ImGui::MenuItem(ICON_MD_SYNC " ROM Sync", nullptr, &show_rom_sync_);
|
||||||
if (ImGui::MenuItem(ICON_MD_PHOTO_CAMERA " Snapshot Preview", nullptr, show_snapshot_preview_)) {
|
ImGui::MenuItem(ICON_MD_PHOTO_CAMERA " Snapshots", nullptr, &show_snapshot_preview_);
|
||||||
show_snapshot_preview_ = !show_snapshot_preview_;
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Help")) {
|
|
||||||
if (ImGui::MenuItem(ICON_MD_HELP " Documentation")) {
|
|
||||||
// TODO: Open docs
|
|
||||||
}
|
|
||||||
if (ImGui::MenuItem(ICON_MD_INFO " About")) {
|
|
||||||
// TODO: Show about dialog
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndMenuBar();
|
ImGui::EndMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modern tabbed interface
|
// Update reactive status color
|
||||||
if (ImGui::BeginTabBar("AgentChatTabs", ImGuiTabBarFlags_None)) {
|
collaboration_status_color_ = collaboration_state_.active ?
|
||||||
// Main Chat Tab - with integrated controls
|
ImVec4(0.133f, 0.545f, 0.133f, 1.0f) : ImVec4(0.6f, 0.6f, 0.6f, 1.0f);
|
||||||
if (ImGui::BeginTabItem(ICON_MD_CHAT " Chat")) {
|
|
||||||
// Stylish connection status bar with gradient
|
|
||||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
|
||||||
ImVec2 bar_start = ImGui::GetCursorScreenPos();
|
|
||||||
ImVec2 bar_size(ImGui::GetContentRegionAvail().x, 85);
|
|
||||||
|
|
||||||
// Gradient background
|
// Connection status bar at top
|
||||||
ImU32 color_top = ImGui::GetColorU32(ImVec4(0.18f, 0.22f, 0.28f, 1.0f));
|
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||||
ImU32 color_bottom = ImGui::GetColorU32(ImVec4(0.12f, 0.16f, 0.22f, 1.0f));
|
ImVec2 bar_start = ImGui::GetCursorScreenPos();
|
||||||
draw_list->AddRectFilledMultiColor(bar_start,
|
ImVec2 bar_size(ImGui::GetContentRegionAvail().x, 75);
|
||||||
ImVec2(bar_start.x + bar_size.x, bar_start.y + bar_size.y),
|
|
||||||
color_top, color_top, color_bottom, color_bottom);
|
|
||||||
|
|
||||||
// Colored accent bar based on provider
|
// Gradient background
|
||||||
ImVec4 accent_color = (agent_config_.ai_provider == "ollama") ? ImVec4(0.2f, 0.8f, 0.4f, 1.0f) :
|
ImU32 color_top = ImGui::GetColorU32(ImVec4(0.18f, 0.22f, 0.28f, 1.0f));
|
||||||
(agent_config_.ai_provider == "gemini") ? ImVec4(0.196f, 0.6f, 0.8f, 1.0f) :
|
ImU32 color_bottom = ImGui::GetColorU32(ImVec4(0.12f, 0.16f, 0.22f, 1.0f));
|
||||||
ImVec4(0.6f, 0.6f, 0.6f, 1.0f);
|
draw_list->AddRectFilledMultiColor(bar_start,
|
||||||
draw_list->AddRectFilled(bar_start, ImVec2(bar_start.x + bar_size.x, bar_start.y + 3),
|
ImVec2(bar_start.x + bar_size.x, bar_start.y + bar_size.y),
|
||||||
ImGui::GetColorU32(accent_color));
|
color_top, color_top, color_bottom, color_bottom);
|
||||||
|
|
||||||
ImGui::BeginChild("ConnectionStatusBar", bar_size, false, ImGuiWindowFlags_NoScrollbar);
|
// Colored accent bar based on provider
|
||||||
{
|
ImVec4 accent_color = (agent_config_.ai_provider == "ollama") ? ImVec4(0.2f, 0.8f, 0.4f, 1.0f) :
|
||||||
ImGui::Spacing();
|
(agent_config_.ai_provider == "gemini") ? ImVec4(0.196f, 0.6f, 0.8f, 1.0f) :
|
||||||
|
ImVec4(0.6f, 0.6f, 0.6f, 1.0f);
|
||||||
|
draw_list->AddRectFilled(bar_start, ImVec2(bar_start.x + bar_size.x, bar_start.y + 3),
|
||||||
|
ImGui::GetColorU32(accent_color));
|
||||||
|
|
||||||
// Provider selection and connection status in one row
|
ImGui::BeginChild("AgentChat_ConnectionBar", bar_size, false, ImGuiWindowFlags_NoScrollbar);
|
||||||
ImGui::TextColored(accent_color, ICON_MD_SMART_TOY " AI Provider:");
|
ImGui::PushID("ConnectionBar");
|
||||||
ImGui::SameLine();
|
{
|
||||||
ImGui::SetNextItemWidth(120);
|
ImGui::Spacing();
|
||||||
const char* providers[] = { "Mock", "Ollama", "Gemini" };
|
|
||||||
int current_provider = (agent_config_.ai_provider == "mock") ? 0 :
|
|
||||||
(agent_config_.ai_provider == "ollama") ? 1 : 2;
|
|
||||||
if (ImGui::Combo("##chat_provider_combo", ¤t_provider, providers, 3)) {
|
|
||||||
agent_config_.ai_provider = (current_provider == 0) ? "mock" :
|
|
||||||
(current_provider == 1) ? "ollama" : "gemini";
|
|
||||||
strncpy(agent_config_.provider_buffer, agent_config_.ai_provider.c_str(),
|
|
||||||
sizeof(agent_config_.provider_buffer) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
// Provider selection
|
||||||
if (agent_config_.ai_provider == "ollama") {
|
ImGui::TextColored(accent_color, ICON_MD_SMART_TOY " Provider:");
|
||||||
ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.4f, 1.0f), ICON_MD_LINK " Host:");
|
ImGui::SameLine();
|
||||||
ImGui::SameLine();
|
ImGui::SetNextItemWidth(110);
|
||||||
ImGui::SetNextItemWidth(200);
|
const char* providers[] = { "Mock", "Ollama", "Gemini" };
|
||||||
if (ImGui::InputText("##chat_ollama_host", agent_config_.ollama_host_buffer,
|
int current_provider = (agent_config_.ai_provider == "mock") ? 0 :
|
||||||
sizeof(agent_config_.ollama_host_buffer))) {
|
(agent_config_.ai_provider == "ollama") ? 1 : 2;
|
||||||
agent_config_.ollama_host = agent_config_.ollama_host_buffer;
|
if (ImGui::Combo("##main_provider", ¤t_provider, providers, 3)) {
|
||||||
}
|
agent_config_.ai_provider = (current_provider == 0) ? "mock" :
|
||||||
ImGui::SameLine();
|
(current_provider == 1) ? "ollama" : "gemini";
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.15f, 0.6f, 0.3f, 0.8f));
|
}
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.2f, 0.8f, 0.4f, 1.0f));
|
|
||||||
if (ImGui::Button(ICON_MD_REFRESH " Test##test_ollama_conn")) {
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show("Testing Ollama connection...", ToastType::kInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::PopStyleColor(2);
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Test connection to Ollama server");
|
|
||||||
}
|
|
||||||
} else if (agent_config_.ai_provider == "gemini") {
|
|
||||||
ImGui::TextColored(ImVec4(0.196f, 0.6f, 0.8f, 1.0f), ICON_MD_KEY " API Key:");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(250);
|
|
||||||
if (ImGui::InputText("##chat_gemini_key", agent_config_.gemini_key_buffer,
|
|
||||||
sizeof(agent_config_.gemini_key_buffer),
|
|
||||||
ImGuiInputTextFlags_Password)) {
|
|
||||||
agent_config_.gemini_api_key = agent_config_.gemini_key_buffer;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.15f, 0.5f, 0.7f, 0.8f));
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.196f, 0.6f, 0.8f, 1.0f));
|
|
||||||
if (ImGui::Button(ICON_MD_CHECK " Verify##verify_gemini_key")) {
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show("Verifying Gemini API key...", ToastType::kInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::PopStyleColor(2);
|
|
||||||
} else {
|
|
||||||
ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
|
|
||||||
ICON_MD_INFO " Mock mode - no external connection needed");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second row: Model selection and quick settings
|
ImGui::SameLine();
|
||||||
ImGui::TextColored(accent_color, ICON_MD_PSYCHOLOGY " Model:");
|
if (agent_config_.ai_provider != "mock") {
|
||||||
ImGui::SameLine();
|
ImGui::TextColored(accent_color, ICON_MD_PSYCHOLOGY " Model:");
|
||||||
ImGui::SetNextItemWidth(200);
|
ImGui::SameLine();
|
||||||
ImGui::InputText("##chat_model_input", agent_config_.model_buffer, sizeof(agent_config_.model_buffer));
|
ImGui::SetNextItemWidth(180);
|
||||||
|
ImGui::InputText("##main_model", agent_config_.model_buffer, sizeof(agent_config_.model_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox(ICON_MD_VISIBILITY " Reasoning", &agent_config_.show_reasoning);
|
ImGui::Checkbox(ICON_MD_VISIBILITY " Reasoning", &agent_config_.show_reasoning);
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Show agent's reasoning process in responses");
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
// Connection status indicator
|
||||||
ImGui::TextColored(accent_color, ICON_MD_LOOP);
|
ImGui::SameLine(ImGui::GetContentRegionAvail().x - 100);
|
||||||
ImGui::SameLine();
|
if (collaboration_state_.active) {
|
||||||
ImGui::SetNextItemWidth(80);
|
ImGui::TextColored(collaboration_status_color_, ICON_MD_CHECK_CIRCLE " Session Active");
|
||||||
ImGui::InputInt("##chat_max_iter", &agent_config_.max_tool_iterations);
|
} else {
|
||||||
if (ImGui::IsItemHovered()) {
|
ImGui::TextDisabled(ICON_MD_CANCEL " No Session");
|
||||||
ImGui::SetTooltip("Maximum tool call iterations per request");
|
}
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// Main layout: Chat area (left, 70%) + Control panels (right, 30%)
|
||||||
|
if (ImGui::BeginTable("AgentChat_MainLayout", 2,
|
||||||
|
ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInnerV)) {
|
||||||
|
ImGui::TableSetupColumn("Chat", ImGuiTableColumnFlags_WidthStretch, 0.7f);
|
||||||
|
ImGui::TableSetupColumn("Controls", ImGuiTableColumnFlags_WidthStretch, 0.3f);
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
// LEFT: Chat area (emphasized)
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::PushID("ChatColumn");
|
||||||
|
RenderHistory();
|
||||||
|
RenderInputBox();
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
// RIGHT: Control panels (collapsible sections)
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::PushID("ControlsColumn");
|
||||||
|
ImGui::BeginChild("AgentChat_ControlPanels", ImVec2(0, 0), false);
|
||||||
|
|
||||||
|
// Quick Actions
|
||||||
|
if (ImGui::CollapsingHeader(ICON_MD_BOLT " Quick Actions", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
ImGui::PushID("QuickActions");
|
||||||
|
if (ImGui::Button(ICON_MD_REFRESH " Reset Chat", ImVec2(-1, 0))) {
|
||||||
|
agent_service_.ResetConversation();
|
||||||
|
if (toast_manager_) {
|
||||||
|
toast_manager_->Show("Conversation reset", ToastType::kInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::PopID();
|
||||||
|
|
||||||
ImGui::Spacing();
|
|
||||||
|
|
||||||
// Main chat area
|
|
||||||
RenderHistory();
|
|
||||||
RenderInputBox();
|
|
||||||
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commands Tab - Z3ED and Multimodal
|
// Collapsible panels
|
||||||
if (ImGui::BeginTabItem(ICON_MD_TERMINAL " Commands")) {
|
if (show_agent_config_) {
|
||||||
RenderZ3EDCommandPanel();
|
|
||||||
ImGui::Separator();
|
|
||||||
RenderMultimodalPanel();
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collaboration Tab
|
|
||||||
if (ImGui::BeginTabItem(ICON_MD_PEOPLE " Collaboration")) {
|
|
||||||
RenderCollaborationPanel();
|
|
||||||
ImGui::Separator();
|
|
||||||
RenderRomSyncPanel();
|
|
||||||
if (show_snapshot_preview_) {
|
|
||||||
ImGui::Separator();
|
|
||||||
RenderSnapshotPreviewPanel();
|
|
||||||
}
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advanced Settings Tab
|
|
||||||
if (ImGui::BeginTabItem(ICON_MD_SETTINGS " Advanced")) {
|
|
||||||
RenderAgentConfigPanel();
|
RenderAgentConfigPanel();
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proposals Tab
|
if (show_z3ed_commands_) {
|
||||||
if (ImGui::BeginTabItem(ICON_MD_PREVIEW " Proposals")) {
|
RenderZ3EDCommandPanel();
|
||||||
RenderProposalManagerPanel();
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metrics Tab
|
RenderCollaborationPanel();
|
||||||
if (ImGui::BeginTabItem(ICON_MD_ANALYTICS " Metrics")) {
|
RenderMultimodalPanel();
|
||||||
auto metrics = agent_service_.GetMetrics();
|
|
||||||
ImGui::Text("Session Statistics");
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
if (ImGui::BeginTable("MetricsTable", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
if (show_rom_sync_) {
|
||||||
ImGui::TableSetupColumn("Metric", ImGuiTableColumnFlags_WidthFixed, 200.0f);
|
RenderRomSyncPanel();
|
||||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
|
|
||||||
ImGui::TableHeadersRow();
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Total Messages");
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%d user, %d agent", metrics.total_user_messages, metrics.total_agent_messages);
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Tool Calls");
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%d", metrics.total_tool_calls);
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Commands Executed");
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%d", metrics.total_commands);
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Proposals Created");
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%d", metrics.total_proposals);
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Average Latency");
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%.2f seconds", metrics.average_latency_seconds);
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Total Session Time");
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%.1f seconds", metrics.total_elapsed_seconds);
|
|
||||||
|
|
||||||
ImGui::EndTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// File Editor Tabs
|
RenderProposalManagerPanel();
|
||||||
if (ImGui::BeginTabItem(ICON_MD_EDIT_NOTE " Files")) {
|
|
||||||
RenderFileEditorTabs();
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
// System Prompt Editor Tab
|
ImGui::EndChild();
|
||||||
if (ImGui::BeginTabItem(ICON_MD_SETTINGS_SUGGEST " System Prompt")) {
|
ImGui::PopID();
|
||||||
RenderSystemPromptEditor();
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndTabBar();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AgentChatWidget::RenderCollaborationPanel() {
|
void AgentChatWidget::RenderCollaborationPanel() {
|
||||||
if (!ImGui::CollapsingHeader("Collaborative Session",
|
ImGui::PushID("CollabPanel");
|
||||||
ImGuiTreeNodeFlags_DefaultOpen)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode selector
|
// Update reactive status color based on connection state
|
||||||
ImGui::Text("Mode:");
|
const bool connected = collaboration_state_.active;
|
||||||
ImGui::SameLine();
|
collaboration_status_color_ = connected ? ImVec4(0.133f, 0.545f, 0.133f, 1.0f) : ImVec4(0.6f, 0.6f, 0.6f, 1.0f);
|
||||||
int mode = static_cast<int>(collaboration_state_.mode);
|
|
||||||
if (ImGui::RadioButton("Local", &mode, 0)) {
|
|
||||||
collaboration_state_.mode = CollaborationMode::kLocal;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::RadioButton("Network", &mode, 1)) {
|
|
||||||
collaboration_state_.mode = CollaborationMode::kNetwork;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
// Top section: Mode selector in a styled box
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.15f, 0.18f, 0.22f, 0.8f));
|
||||||
|
ImGui::BeginChild("Collab_ModeSelector", ImVec2(0, 45), true, ImGuiWindowFlags_NoScrollbar);
|
||||||
|
{
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_SETTINGS_ETHERNET " Collaboration Mode:");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(ICON_MD_FOLDER " Local##collab_mode_local",
|
||||||
|
reinterpret_cast<int*>(&collaboration_state_.mode),
|
||||||
|
static_cast<int>(CollaborationMode::kLocal));
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(ICON_MD_WIFI " Network##collab_mode_network",
|
||||||
|
reinterpret_cast<int*>(&collaboration_state_.mode),
|
||||||
|
static_cast<int>(CollaborationMode::kNetwork));
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
// Table layout: Left side = Session Details, Right side = Controls
|
ImGui::Spacing();
|
||||||
if (ImGui::BeginTable(
|
|
||||||
"collab_table", 2,
|
// Main content in table layout
|
||||||
ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingFixedFit)) {
|
if (ImGui::BeginTable("Collab_MainTable", 2, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_Resizable)) {
|
||||||
ImGui::TableSetupColumn("Session Details", ImGuiTableColumnFlags_WidthFixed,
|
ImGui::TableSetupColumn("Status", ImGuiTableColumnFlags_WidthFixed, 320);
|
||||||
250.0f);
|
|
||||||
ImGui::TableSetupColumn("Controls", ImGuiTableColumnFlags_WidthStretch);
|
ImGui::TableSetupColumn("Controls", ImGuiTableColumnFlags_WidthStretch);
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
// LEFT COLUMN: Session Details with gradient background
|
// LEFT COLUMN: Session Details
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.15f, 0.2f, 0.18f, 0.4f));
|
ImGui::BeginGroup();
|
||||||
ImGui::BeginChild("session_details", ImVec2(0, 180), true);
|
ImGui::PushID("StatusColumn");
|
||||||
ImVec4 status_color = ImVec4(1.0f, 0.843f, 0.0f, 1.0f);
|
|
||||||
|
|
||||||
const bool connected = collaboration_state_.active;
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.15f, 0.2f, 0.18f, 0.4f));
|
||||||
|
ImGui::BeginChild("Collab_SessionDetails", ImVec2(0, 180), true);
|
||||||
ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_INFO " Session Status:");
|
ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_INFO " Session Status:");
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
if (connected) {
|
if (connected) {
|
||||||
ImGui::TextColored(status_color, ICON_MD_CHECK_CIRCLE " Connected");
|
ImGui::TextColored(collaboration_status_color_, ICON_MD_CHECK_CIRCLE " Connected");
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextDisabled(ICON_MD_CANCEL " Not connected");
|
ImGui::TextDisabled(ICON_MD_CANCEL " Not connected");
|
||||||
}
|
}
|
||||||
@@ -822,13 +697,13 @@ void AgentChatWidget::RenderCollaborationPanel() {
|
|||||||
|
|
||||||
if (!collaboration_state_.session_name.empty()) {
|
if (!collaboration_state_.session_name.empty()) {
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::TextColored(status_color, ICON_MD_LABEL " Session:");
|
ImGui::TextColored(collaboration_status_color_, ICON_MD_LABEL " Session:");
|
||||||
ImGui::TextWrapped("%s", collaboration_state_.session_name.c_str());
|
ImGui::TextWrapped("%s", collaboration_state_.session_name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!collaboration_state_.session_id.empty()) {
|
if (!collaboration_state_.session_id.empty()) {
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::TextColored(status_color, ICON_MD_KEY " Session Code:");
|
ImGui::TextColored(collaboration_status_color_, ICON_MD_KEY " Session Code:");
|
||||||
ImGui::TextWrapped("%s", collaboration_state_.session_id.c_str());
|
ImGui::TextWrapped("%s", collaboration_state_.session_id.c_str());
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.4f, 0.4f, 0.6f, 0.6f));
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.4f, 0.4f, 0.6f, 0.6f));
|
||||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.416f, 0.353f, 0.804f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.416f, 0.353f, 0.804f, 1.0f));
|
||||||
@@ -848,31 +723,41 @@ void AgentChatWidget::RenderCollaborationPanel() {
|
|||||||
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f),
|
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f),
|
||||||
"%s", absl::FormatTime("%H:%M:%S", collaboration_state_.last_synced,
|
"%s", absl::FormatTime("%H:%M:%S", collaboration_state_.last_synced,
|
||||||
absl::LocalTimeZone())
|
absl::LocalTimeZone())
|
||||||
.c_str());
|
.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
// Show participants list below session details
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// Participants list below session details
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.12f, 0.16f, 0.14f, 0.4f));
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.12f, 0.16f, 0.14f, 0.4f));
|
||||||
ImGui::BeginChild("participants", ImVec2(0, 0), true);
|
ImGui::BeginChild("Collab_ParticipantsList", ImVec2(0, 0), true);
|
||||||
if (collaboration_state_.participants.empty()) {
|
{
|
||||||
ImGui::TextDisabled(ICON_MD_PEOPLE " No participants yet");
|
if (collaboration_state_.participants.empty()) {
|
||||||
} else {
|
ImGui::TextDisabled(ICON_MD_PEOPLE " No participants yet");
|
||||||
ImGui::TextColored(status_color, ICON_MD_PEOPLE " Participants (%zu):",
|
} else {
|
||||||
collaboration_state_.participants.size());
|
ImGui::TextColored(collaboration_status_color_, ICON_MD_PEOPLE " Participants (%zu):",
|
||||||
ImGui::Separator();
|
collaboration_state_.participants.size());
|
||||||
for (const auto& participant : collaboration_state_.participants) {
|
ImGui::Separator();
|
||||||
ImGui::BulletText(ICON_MD_PERSON " %s", participant.c_str());
|
for (size_t i = 0; i < collaboration_state_.participants.size(); ++i) {
|
||||||
|
ImGui::PushID(static_cast<int>(i));
|
||||||
|
ImGui::BulletText(ICON_MD_PERSON " %s", collaboration_state_.participants[i].c_str());
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
ImGui::PopID(); // StatusColumn
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
// RIGHT COLUMN: Controls
|
// RIGHT COLUMN: Controls
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::BeginChild("controls", ImVec2(0, 0), false);
|
ImGui::BeginGroup();
|
||||||
|
ImGui::PushID("ControlsColumn");
|
||||||
|
ImGui::BeginChild("Collab_Controls", ImVec2(0, 0), false);
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
@@ -1004,7 +889,7 @@ void AgentChatWidget::RenderCollaborationPanel() {
|
|||||||
ImGui::SetTooltip("Join an existing collaboration session");
|
ImGui::SetTooltip("Join an existing collaboration session");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connected) {
|
if (collaboration_state_.active) {
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
@@ -1030,11 +915,10 @@ void AgentChatWidget::RenderCollaborationPanel() {
|
|||||||
ToastType::kError, 5.0f);
|
ToastType::kError, 5.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
if (!can_leave)
|
if (!can_leave)
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
}
|
|
||||||
|
|
||||||
if (connected) {
|
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (!can_refresh)
|
if (!can_refresh)
|
||||||
@@ -1052,48 +936,63 @@ void AgentChatWidget::RenderCollaborationPanel() {
|
|||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
} else {
|
} else {
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::TextDisabled("Start or join a session to collaborate.");
|
ImGui::TextDisabled(ICON_MD_INFO " Start or join a session to collaborate.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndChild(); // controls
|
ImGui::EndChild(); // Collab_Controls
|
||||||
|
ImGui::PopID(); // ControlsColumn
|
||||||
|
ImGui::EndGroup();
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::PopID(); // CollabPanel
|
||||||
}
|
}
|
||||||
|
|
||||||
void AgentChatWidget::RenderMultimodalPanel() {
|
void AgentChatWidget::RenderMultimodalPanel() {
|
||||||
|
ImGui::PushID("MultimodalPanel");
|
||||||
ImVec4 gemini_color = ImVec4(0.196f, 0.6f, 0.8f, 1.0f);
|
ImVec4 gemini_color = ImVec4(0.196f, 0.6f, 0.8f, 1.0f);
|
||||||
|
|
||||||
if (!ImGui::CollapsingHeader(ICON_MD_CAMERA " Gemini Multimodal Vision",
|
if (!ImGui::CollapsingHeader(ICON_MD_CAMERA " Gemini Multimodal Vision",
|
||||||
ImGuiTreeNodeFlags_DefaultOpen)) {
|
ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
ImGui::PopID();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_capture = static_cast<bool>(multimodal_callbacks_.capture_snapshot);
|
bool can_capture = static_cast<bool>(multimodal_callbacks_.capture_snapshot);
|
||||||
bool can_send = static_cast<bool>(multimodal_callbacks_.send_to_gemini);
|
bool can_send = static_cast<bool>(multimodal_callbacks_.send_to_gemini);
|
||||||
|
|
||||||
// Capture mode selection with icons
|
// Organize in table layout
|
||||||
ImGui::TextColored(gemini_color, ICON_MD_SCREENSHOT " Capture Mode:");
|
if (ImGui::BeginTable("Multimodal_Layout", 1, ImGuiTableFlags_None)) {
|
||||||
ImGui::RadioButton(ICON_MD_FULLSCREEN " Full Window##mm_radio_full",
|
ImGui::TableSetupColumn("Content", ImGuiTableColumnFlags_WidthStretch);
|
||||||
reinterpret_cast<int*>(&multimodal_state_.capture_mode),
|
ImGui::TableNextRow();
|
||||||
static_cast<int>(CaptureMode::kFullWindow));
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton(ICON_MD_DASHBOARD " Active Editor##mm_radio_active",
|
|
||||||
reinterpret_cast<int*>(&multimodal_state_.capture_mode),
|
|
||||||
static_cast<int>(CaptureMode::kActiveEditor));
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::RadioButton(ICON_MD_WINDOW " Specific##mm_radio_specific",
|
|
||||||
reinterpret_cast<int*>(&multimodal_state_.capture_mode),
|
|
||||||
static_cast<int>(CaptureMode::kSpecificWindow));
|
|
||||||
|
|
||||||
// If specific window mode, show input for window name
|
ImGui::BeginGroup();
|
||||||
if (multimodal_state_.capture_mode == CaptureMode::kSpecificWindow) {
|
|
||||||
ImGui::SetNextItemWidth(-1);
|
|
||||||
ImGui::InputTextWithHint("##mm_window_name_input", "Window name (e.g., Overworld Editor)...",
|
|
||||||
multimodal_state_.specific_window_buffer,
|
|
||||||
IM_ARRAYSIZE(multimodal_state_.specific_window_buffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
// Capture mode selection with icons
|
||||||
|
ImGui::TextColored(gemini_color, ICON_MD_SCREENSHOT " Capture Mode:");
|
||||||
|
ImGui::RadioButton(ICON_MD_FULLSCREEN " Full Window##mm_radio_full",
|
||||||
|
reinterpret_cast<int*>(&multimodal_state_.capture_mode),
|
||||||
|
static_cast<int>(CaptureMode::kFullWindow));
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(ICON_MD_DASHBOARD " Active Editor##mm_radio_active",
|
||||||
|
reinterpret_cast<int*>(&multimodal_state_.capture_mode),
|
||||||
|
static_cast<int>(CaptureMode::kActiveEditor));
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::RadioButton(ICON_MD_WINDOW " Specific##mm_radio_specific",
|
||||||
|
reinterpret_cast<int*>(&multimodal_state_.capture_mode),
|
||||||
|
static_cast<int>(CaptureMode::kSpecificWindow));
|
||||||
|
|
||||||
|
// If specific window mode, show input for window name
|
||||||
|
if (multimodal_state_.capture_mode == CaptureMode::kSpecificWindow) {
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
ImGui::InputTextWithHint("##mm_window_name_input", "Window name (e.g., Overworld Editor)...",
|
||||||
|
multimodal_state_.specific_window_buffer,
|
||||||
|
IM_ARRAYSIZE(multimodal_state_.specific_window_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndGroup();
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
if (!can_capture)
|
if (!can_capture)
|
||||||
ImGui::BeginDisabled();
|
ImGui::BeginDisabled();
|
||||||
@@ -1205,6 +1104,11 @@ void AgentChatWidget::RenderMultimodalPanel() {
|
|||||||
.c_str());
|
.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID(); // MultimodalPanel
|
||||||
}
|
}
|
||||||
|
|
||||||
void AgentChatWidget::RefreshCollaboration() {
|
void AgentChatWidget::RefreshCollaboration() {
|
||||||
@@ -1427,24 +1331,32 @@ void AgentChatWidget::RenderAgentConfigPanel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AgentChatWidget::RenderZ3EDCommandPanel() {
|
void AgentChatWidget::RenderZ3EDCommandPanel() {
|
||||||
|
ImGui::PushID("Z3EDCmdPanel");
|
||||||
|
ImVec4 command_color = ImVec4(1.0f, 0.647f, 0.0f, 1.0f);
|
||||||
|
|
||||||
if (!ImGui::CollapsingHeader(ICON_MD_TERMINAL " Z3ED Commands",
|
if (!ImGui::CollapsingHeader(ICON_MD_TERMINAL " Z3ED Commands",
|
||||||
ImGuiTreeNodeFlags_DefaultOpen)) {
|
ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
ImGui::PopID();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.14f, 0.12f, 0.18f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.14f, 0.12f, 0.18f, 1.0f));
|
||||||
ImGui::BeginChild("Z3EDCommands", ImVec2(0, 300), true);
|
ImGui::BeginChild("Z3ED_CommandsChild", ImVec2(0, 300), true);
|
||||||
|
|
||||||
ImGui::Text(ICON_MD_CODE " Command Palette");
|
ImGui::TextColored(command_color, ICON_MD_CODE " Command Palette");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
ImGui::InputTextWithHint("##z3ed_command", "Enter z3ed command or prompt...",
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
ImGui::InputTextWithHint("##z3ed_cmd_input_field", "Enter z3ed command or prompt...",
|
||||||
z3ed_command_state_.command_input_buffer,
|
z3ed_command_state_.command_input_buffer,
|
||||||
IM_ARRAYSIZE(z3ed_command_state_.command_input_buffer));
|
IM_ARRAYSIZE(z3ed_command_state_.command_input_buffer));
|
||||||
|
|
||||||
ImGui::BeginDisabled(z3ed_command_state_.command_running);
|
ImGui::BeginDisabled(z3ed_command_state_.command_running);
|
||||||
|
|
||||||
if (ImGui::Button(ICON_MD_PLAY_ARROW " Run Task", ImVec2(-1, 0)) ||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.6f, 0.4f, 0.0f, 0.8f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, command_color);
|
||||||
|
if (ImGui::Button(ICON_MD_PLAY_ARROW " Run Task##z3ed_run_task_btn", ImVec2(-1, 0)) ||
|
||||||
(ImGui::IsItemFocused() && ImGui::IsKeyPressed(ImGuiKey_Enter))) {
|
(ImGui::IsItemFocused() && ImGui::IsKeyPressed(ImGuiKey_Enter))) {
|
||||||
if (z3ed_callbacks_.run_agent_task) {
|
if (z3ed_callbacks_.run_agent_task) {
|
||||||
std::string command = z3ed_command_state_.command_input_buffer;
|
std::string command = z3ed_command_state_.command_input_buffer;
|
||||||
@@ -1463,15 +1375,19 @@ void AgentChatWidget::RenderZ3EDCommandPanel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::Text(ICON_MD_LIST " Quick Actions");
|
ImGui::TextColored(command_color, ICON_MD_LIST " Quick Actions");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
if (ImGui::BeginTable("Z3EDQuickActions", 2, ImGuiTableFlags_SizingStretchProp)) {
|
if (ImGui::BeginTable("Z3ED_QuickActionsTable", 2, ImGuiTableFlags_SizingStretchProp)) {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_PREVIEW " List Proposals", ImVec2(-1, 0))) {
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.4f, 0.35f, 0.6f, 0.8f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.502f, 0.0f, 0.502f, 1.0f));
|
||||||
|
if (ImGui::Button(ICON_MD_PREVIEW " List##z3ed_list_btn", ImVec2(-1, 0))) {
|
||||||
if (z3ed_callbacks_.list_proposals) {
|
if (z3ed_callbacks_.list_proposals) {
|
||||||
auto result = z3ed_callbacks_.list_proposals();
|
auto result = z3ed_callbacks_.list_proposals();
|
||||||
if (result.ok()) {
|
if (result.ok()) {
|
||||||
@@ -1485,9 +1401,12 @@ void AgentChatWidget::RenderZ3EDCommandPanel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_DIFFERENCE " View Diff", ImVec2(-1, 0))) {
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.15f, 0.5f, 0.7f, 0.8f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.196f, 0.6f, 0.8f, 1.0f));
|
||||||
|
if (ImGui::Button(ICON_MD_DIFFERENCE " Diff##z3ed_diff_btn", ImVec2(-1, 0))) {
|
||||||
if (z3ed_callbacks_.diff_proposal) {
|
if (z3ed_callbacks_.diff_proposal) {
|
||||||
auto result = z3ed_callbacks_.diff_proposal("");
|
auto result = z3ed_callbacks_.diff_proposal("");
|
||||||
if (result.ok()) {
|
if (result.ok()) {
|
||||||
@@ -1495,18 +1414,24 @@ void AgentChatWidget::RenderZ3EDCommandPanel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_CHECK " Accept", ImVec2(-1, 0))) {
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.1f, 0.5f, 0.1f, 0.8f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.133f, 0.545f, 0.133f, 1.0f));
|
||||||
|
if (ImGui::Button(ICON_MD_CHECK " Accept##z3ed_accept_btn", ImVec2(-1, 0))) {
|
||||||
if (z3ed_callbacks_.accept_proposal && proposal_drawer_) {
|
if (z3ed_callbacks_.accept_proposal && proposal_drawer_) {
|
||||||
// TODO: Get selected proposal ID from drawer
|
// TODO: Get selected proposal ID from drawer
|
||||||
auto status = z3ed_callbacks_.accept_proposal("");
|
auto status = z3ed_callbacks_.accept_proposal("");
|
||||||
(void)status; // Acknowledge result
|
(void)status; // Acknowledge result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_CLOSE " Reject", ImVec2(-1, 0))) {
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.7f, 0.2f, 0.2f, 0.8f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.863f, 0.078f, 0.235f, 1.0f));
|
||||||
|
if (ImGui::Button(ICON_MD_CLOSE " Reject##z3ed_reject_btn", ImVec2(-1, 0))) {
|
||||||
if (z3ed_callbacks_.reject_proposal && proposal_drawer_) {
|
if (z3ed_callbacks_.reject_proposal && proposal_drawer_) {
|
||||||
// TODO: Get selected proposal ID from drawer
|
// TODO: Get selected proposal ID from drawer
|
||||||
auto status = z3ed_callbacks_.reject_proposal("");
|
auto status = z3ed_callbacks_.reject_proposal("");
|
||||||
|
|||||||
@@ -278,6 +278,9 @@ public:
|
|||||||
bool show_snapshot_preview_ = false;
|
bool show_snapshot_preview_ = false;
|
||||||
std::vector<uint8_t> snapshot_preview_data_;
|
std::vector<uint8_t> snapshot_preview_data_;
|
||||||
|
|
||||||
|
// Reactive UI colors
|
||||||
|
ImVec4 collaboration_status_color_ = ImVec4(0.6f, 0.6f, 0.6f, 1.0f);
|
||||||
|
|
||||||
// File editing state
|
// File editing state
|
||||||
struct FileEditorTab {
|
struct FileEditorTab {
|
||||||
std::string filepath;
|
std::string filepath;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "app/editor/system/proposal_drawer.h"
|
#include "app/editor/system/proposal_drawer.h"
|
||||||
#include "app/editor/system/toast_manager.h"
|
#include "app/editor/system/toast_manager.h"
|
||||||
#include "app/rom.h"
|
#include "app/rom.h"
|
||||||
|
#include "app/gui/icons.h"
|
||||||
|
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
#include "app/editor/agent/network_collaboration_coordinator.h"
|
#include "app/editor/agent/network_collaboration_coordinator.h"
|
||||||
@@ -18,19 +19,59 @@ namespace yaze {
|
|||||||
namespace editor {
|
namespace editor {
|
||||||
|
|
||||||
AgentEditor::AgentEditor() {
|
AgentEditor::AgentEditor() {
|
||||||
|
type_ = EditorType::kAgent;
|
||||||
chat_widget_ = std::make_unique<AgentChatWidget>();
|
chat_widget_ = std::make_unique<AgentChatWidget>();
|
||||||
local_coordinator_ = std::make_unique<AgentCollaborationCoordinator>();
|
local_coordinator_ = std::make_unique<AgentCollaborationCoordinator>();
|
||||||
|
|
||||||
|
// Initialize default configuration
|
||||||
|
current_config_.provider = "mock";
|
||||||
|
current_config_.show_reasoning = true;
|
||||||
|
current_config_.max_tool_iterations = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
AgentEditor::~AgentEditor() = default;
|
AgentEditor::~AgentEditor() = default;
|
||||||
|
|
||||||
void AgentEditor::Initialize(ToastManager* toast_manager,
|
void AgentEditor::Initialize() {
|
||||||
ProposalDrawer* proposal_drawer) {
|
// Base initialization
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status AgentEditor::Load() {
|
||||||
|
// Load agent configuration from project/settings
|
||||||
|
// TODO: Load from config file
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status AgentEditor::Save() {
|
||||||
|
// Save agent configuration
|
||||||
|
// TODO: Save to config file
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status AgentEditor::Update() {
|
||||||
|
if (!active_) return absl::OkStatus();
|
||||||
|
|
||||||
|
// Draw configuration dashboard
|
||||||
|
DrawDashboard();
|
||||||
|
|
||||||
|
// Chat widget is drawn separately (not here)
|
||||||
|
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AgentEditor::InitializeWithDependencies(ToastManager* toast_manager,
|
||||||
|
ProposalDrawer* proposal_drawer,
|
||||||
|
Rom* rom) {
|
||||||
toast_manager_ = toast_manager;
|
toast_manager_ = toast_manager;
|
||||||
proposal_drawer_ = proposal_drawer;
|
proposal_drawer_ = proposal_drawer;
|
||||||
|
rom_ = rom;
|
||||||
|
|
||||||
chat_widget_->SetToastManager(toast_manager_);
|
if (chat_widget_) {
|
||||||
chat_widget_->SetProposalDrawer(proposal_drawer_);
|
chat_widget_->SetToastManager(toast_manager);
|
||||||
|
chat_widget_->SetProposalDrawer(proposal_drawer);
|
||||||
|
if (rom) {
|
||||||
|
chat_widget_->SetRomContext(rom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetupChatWidgetCallbacks();
|
SetupChatWidgetCallbacks();
|
||||||
SetupMultimodalCallbacks();
|
SetupMultimodalCallbacks();
|
||||||
@@ -43,9 +84,194 @@ void AgentEditor::SetRomContext(Rom* rom) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AgentEditor::Draw() {
|
void AgentEditor::DrawDashboard() {
|
||||||
|
if (!active_) return;
|
||||||
|
|
||||||
|
ImGui::Begin(ICON_MD_SMART_TOY " AI Agent Configuration", &active_, ImGuiWindowFlags_MenuBar);
|
||||||
|
|
||||||
|
// Menu bar
|
||||||
|
if (ImGui::BeginMenuBar()) {
|
||||||
|
if (ImGui::BeginMenu(ICON_MD_MENU " Actions")) {
|
||||||
|
if (ImGui::MenuItem(ICON_MD_CHAT " Open Chat Window", "Ctrl+Shift+A")) {
|
||||||
|
OpenChatWindow();
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGui::MenuItem(ICON_MD_SAVE " Save Configuration")) {
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem(ICON_MD_REFRESH " Reset to Defaults")) {
|
||||||
|
current_config_ = AgentConfig{};
|
||||||
|
current_config_.show_reasoning = true;
|
||||||
|
current_config_.max_tool_iterations = 4;
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
ImGui::EndMenuBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dashboard content in organized sections
|
||||||
|
if (ImGui::BeginTable("AgentDashboard_Layout", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInnerV)) {
|
||||||
|
ImGui::TableSetupColumn("Configuration", ImGuiTableColumnFlags_WidthStretch, 0.6f);
|
||||||
|
ImGui::TableSetupColumn("Info", ImGuiTableColumnFlags_WidthStretch, 0.4f);
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
// LEFT: Configuration
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::PushID("ConfigColumn");
|
||||||
|
DrawConfigurationPanel();
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
// RIGHT: Status & Info
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::PushID("InfoColumn");
|
||||||
|
DrawStatusPanel();
|
||||||
|
DrawMetricsPanel();
|
||||||
|
ImGui::PopID();
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AgentEditor::DrawConfigurationPanel() {
|
||||||
|
// AI Provider Configuration
|
||||||
|
if (ImGui::CollapsingHeader(ICON_MD_SETTINGS " AI Provider", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_SMART_TOY " Provider Selection");
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// Provider buttons (large, visual)
|
||||||
|
ImVec2 button_size(ImGui::GetContentRegionAvail().x / 3 - 8, 60);
|
||||||
|
|
||||||
|
bool is_mock = (current_config_.provider == "mock");
|
||||||
|
bool is_ollama = (current_config_.provider == "ollama");
|
||||||
|
bool is_gemini = (current_config_.provider == "gemini");
|
||||||
|
|
||||||
|
if (is_mock) ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.6f, 0.6f, 0.6f, 0.8f));
|
||||||
|
if (ImGui::Button(ICON_MD_SETTINGS " Mock", button_size)) {
|
||||||
|
current_config_.provider = "mock";
|
||||||
|
}
|
||||||
|
if (is_mock) ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (is_ollama) ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.8f, 0.4f, 0.8f));
|
||||||
|
if (ImGui::Button(ICON_MD_CLOUD " Ollama", button_size)) {
|
||||||
|
current_config_.provider = "ollama";
|
||||||
|
}
|
||||||
|
if (is_ollama) ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (is_gemini) ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.196f, 0.6f, 0.8f, 0.8f));
|
||||||
|
if (ImGui::Button(ICON_MD_SMART_TOY " Gemini", button_size)) {
|
||||||
|
current_config_.provider = "gemini";
|
||||||
|
}
|
||||||
|
if (is_gemini) ImGui::PopStyleColor();
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// Provider-specific settings
|
||||||
|
if (current_config_.provider == "ollama") {
|
||||||
|
ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.4f, 1.0f), ICON_MD_SETTINGS " Ollama Settings");
|
||||||
|
ImGui::Text("Model:");
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
static char model_buf[128] = "qwen2.5-coder:7b";
|
||||||
|
ImGui::InputTextWithHint("##ollama_model", "e.g., qwen2.5-coder:7b, llama3.2", model_buf, sizeof(model_buf));
|
||||||
|
current_config_.model = model_buf;
|
||||||
|
|
||||||
|
ImGui::Text("Host URL:");
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
static char host_buf[256] = "http://localhost:11434";
|
||||||
|
ImGui::InputText("##ollama_host", host_buf, sizeof(host_buf));
|
||||||
|
current_config_.ollama_host = host_buf;
|
||||||
|
} else if (current_config_.provider == "gemini") {
|
||||||
|
ImGui::TextColored(ImVec4(0.196f, 0.6f, 0.8f, 1.0f), ICON_MD_SMART_TOY " Gemini Settings");
|
||||||
|
ImGui::Text("Model:");
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
static char model_buf[128] = "gemini-1.5-flash";
|
||||||
|
ImGui::InputTextWithHint("##gemini_model", "e.g., gemini-1.5-flash", model_buf, sizeof(model_buf));
|
||||||
|
current_config_.model = model_buf;
|
||||||
|
|
||||||
|
ImGui::Text("API Key:");
|
||||||
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
static char key_buf[256] = "";
|
||||||
|
ImGui::InputText("##gemini_key", key_buf, sizeof(key_buf), ImGuiInputTextFlags_Password);
|
||||||
|
current_config_.gemini_api_key = key_buf;
|
||||||
|
} else {
|
||||||
|
ImGui::TextDisabled(ICON_MD_INFO " Mock mode - no configuration needed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Behavior Settings
|
||||||
|
if (ImGui::CollapsingHeader(ICON_MD_TUNE " Behavior", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
ImGui::Checkbox(ICON_MD_VISIBILITY " Show Reasoning", ¤t_config_.show_reasoning);
|
||||||
|
ImGui::Checkbox(ICON_MD_ANALYTICS " Verbose Output", ¤t_config_.verbose);
|
||||||
|
ImGui::SliderInt(ICON_MD_LOOP " Max Iterations", ¤t_config_.max_tool_iterations, 1, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply button
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.133f, 0.545f, 0.133f, 0.8f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.133f, 0.545f, 0.133f, 1.0f));
|
||||||
|
if (ImGui::Button(ICON_MD_CHECK " Apply Configuration", ImVec2(-1, 40))) {
|
||||||
|
ApplyConfig(current_config_);
|
||||||
|
if (toast_manager_) {
|
||||||
|
toast_manager_->Show("Agent configuration applied", ToastType::kSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AgentEditor::DrawStatusPanel() {
|
||||||
|
// Chat Status
|
||||||
|
if (ImGui::CollapsingHeader(ICON_MD_CHAT " Chat Status", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
|
if (chat_widget_ && chat_widget_->is_active()) {
|
||||||
|
ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f), ICON_MD_CHECK_CIRCLE " Chat Active");
|
||||||
|
} else {
|
||||||
|
ImGui::TextDisabled(ICON_MD_CANCEL " Chat Inactive");
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
if (ImGui::Button(ICON_MD_OPEN_IN_NEW " Open Chat", ImVec2(-1, 0))) {
|
||||||
|
OpenChatWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collaboration Status
|
||||||
|
if (ImGui::CollapsingHeader(ICON_MD_PEOPLE " Collaboration")) {
|
||||||
|
ImGui::TextDisabled("Mode: %s", current_mode_ == CollaborationMode::kLocal ? "Local" : "Network");
|
||||||
|
ImGui::TextDisabled(ICON_MD_INFO " Configure in chat window");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AgentEditor::DrawMetricsPanel() {
|
||||||
|
if (ImGui::CollapsingHeader(ICON_MD_ANALYTICS " Session Metrics")) {
|
||||||
|
if (chat_widget_) {
|
||||||
|
ImGui::TextDisabled("View metrics in chat window");
|
||||||
|
} else {
|
||||||
|
ImGui::TextDisabled("No metrics available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AgentEditor::AgentConfig AgentEditor::GetCurrentConfig() const {
|
||||||
|
return current_config_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AgentEditor::ApplyConfig(const AgentConfig& config) {
|
||||||
|
current_config_ = config;
|
||||||
|
|
||||||
|
// Apply to chat widget if available
|
||||||
if (chat_widget_) {
|
if (chat_widget_) {
|
||||||
chat_widget_->Draw();
|
AgentChatWidget::AgentConfigState chat_config;
|
||||||
|
chat_config.ai_provider = config.provider;
|
||||||
|
chat_config.ai_model = config.model;
|
||||||
|
chat_config.ollama_host = config.ollama_host;
|
||||||
|
chat_config.gemini_api_key = config.gemini_api_key;
|
||||||
|
chat_config.verbose = config.verbose;
|
||||||
|
chat_config.show_reasoning = config.show_reasoning;
|
||||||
|
chat_config.max_tool_iterations = config.max_tool_iterations;
|
||||||
|
chat_widget_->UpdateAgentConfig(chat_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +289,12 @@ void AgentEditor::ToggleChat() {
|
|||||||
SetChatActive(!IsChatActive());
|
SetChatActive(!IsChatActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AgentEditor::OpenChatWindow() {
|
||||||
|
if (chat_widget_) {
|
||||||
|
chat_widget_->set_active(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
absl::StatusOr<AgentEditor::SessionInfo> AgentEditor::HostSession(
|
absl::StatusOr<AgentEditor::SessionInfo> AgentEditor::HostSession(
|
||||||
const std::string& session_name, CollaborationMode mode) {
|
const std::string& session_name, CollaborationMode mode) {
|
||||||
current_mode_ = mode;
|
current_mode_ = mode;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
|
#include "app/editor/editor.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
|
|
||||||
@@ -26,33 +27,68 @@ class NetworkCollaborationCoordinator;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @class AgentEditor
|
* @class AgentEditor
|
||||||
* @brief Manages all agent-related functionality including chat, collaboration,
|
* @brief AI Agent Configuration Dashboard (separate from chat)
|
||||||
* and network coordination for the Z3ED editor.
|
|
||||||
*
|
*
|
||||||
* This class serves as a high-level manager for:
|
* A comprehensive configuration editor for the AI agent:
|
||||||
* - Agent chat widget and conversations
|
* - Agent provider configuration (Ollama, Gemini, Mock)
|
||||||
* - Local filesystem-based collaboration
|
* - Model selection and parameters
|
||||||
* - Network-based (WebSocket) collaboration
|
* - Collaboration settings (Local/Network)
|
||||||
* - Coordination between multiple collaboration modes
|
* - Z3ED command automation presets
|
||||||
|
* - Multimodal/vision configuration
|
||||||
|
* - Session metrics and monitoring
|
||||||
|
* - System prompt customization
|
||||||
|
*
|
||||||
|
* The chat widget is separate and managed by EditorManager.
|
||||||
*/
|
*/
|
||||||
class AgentEditor {
|
class AgentEditor : public Editor {
|
||||||
public:
|
public:
|
||||||
AgentEditor();
|
AgentEditor();
|
||||||
~AgentEditor();
|
~AgentEditor() override;
|
||||||
|
|
||||||
// Initialization
|
// Editor interface implementation
|
||||||
void Initialize(ToastManager* toast_manager, ProposalDrawer* proposal_drawer);
|
void Initialize() override;
|
||||||
|
absl::Status Load() override;
|
||||||
|
absl::Status Save() override;
|
||||||
|
absl::Status Update() override;
|
||||||
|
absl::Status Cut() override { return absl::UnimplementedError("Not applicable"); }
|
||||||
|
absl::Status Copy() override { return absl::UnimplementedError("Not applicable"); }
|
||||||
|
absl::Status Paste() override { return absl::UnimplementedError("Not applicable"); }
|
||||||
|
absl::Status Undo() override { return absl::UnimplementedError("Not applicable"); }
|
||||||
|
absl::Status Redo() override { return absl::UnimplementedError("Not applicable"); }
|
||||||
|
absl::Status Find() override { return absl::UnimplementedError("Not applicable"); }
|
||||||
|
|
||||||
|
// Initialization with dependencies
|
||||||
|
void InitializeWithDependencies(ToastManager* toast_manager,
|
||||||
|
ProposalDrawer* proposal_drawer,
|
||||||
|
Rom* rom);
|
||||||
void SetRomContext(Rom* rom);
|
void SetRomContext(Rom* rom);
|
||||||
|
|
||||||
// Main rendering
|
|
||||||
void Draw();
|
|
||||||
|
|
||||||
// Chat widget access
|
// Main rendering (called by Update())
|
||||||
|
void DrawDashboard();
|
||||||
|
|
||||||
|
// Get current agent configuration (for chat to use)
|
||||||
|
struct AgentConfig {
|
||||||
|
std::string provider = "mock";
|
||||||
|
std::string model;
|
||||||
|
std::string ollama_host = "http://localhost:11434";
|
||||||
|
std::string gemini_api_key;
|
||||||
|
bool verbose = false;
|
||||||
|
bool show_reasoning = true;
|
||||||
|
int max_tool_iterations = 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
AgentConfig GetCurrentConfig() const;
|
||||||
|
void ApplyConfig(const AgentConfig& config);
|
||||||
|
|
||||||
|
// Chat widget access (for EditorManager)
|
||||||
|
AgentChatWidget* GetChatWidget() { return chat_widget_.get(); }
|
||||||
bool IsChatActive() const;
|
bool IsChatActive() const;
|
||||||
void SetChatActive(bool active);
|
void SetChatActive(bool active);
|
||||||
void ToggleChat();
|
void ToggleChat();
|
||||||
|
void OpenChatWindow();
|
||||||
|
|
||||||
// Collaboration management
|
// Collaboration and session management
|
||||||
enum class CollaborationMode {
|
enum class CollaborationMode {
|
||||||
kLocal, // Filesystem-based collaboration
|
kLocal, // Filesystem-based collaboration
|
||||||
kNetwork // WebSocket-based collaboration
|
kNetwork // WebSocket-based collaboration
|
||||||
@@ -64,21 +100,13 @@ class AgentEditor {
|
|||||||
std::vector<std::string> participants;
|
std::vector<std::string> participants;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Host a new collaboration session
|
|
||||||
absl::StatusOr<SessionInfo> HostSession(const std::string& session_name,
|
absl::StatusOr<SessionInfo> HostSession(const std::string& session_name,
|
||||||
CollaborationMode mode = CollaborationMode::kLocal);
|
CollaborationMode mode = CollaborationMode::kLocal);
|
||||||
|
|
||||||
// Join an existing collaboration session
|
|
||||||
absl::StatusOr<SessionInfo> JoinSession(const std::string& session_code,
|
absl::StatusOr<SessionInfo> JoinSession(const std::string& session_code,
|
||||||
CollaborationMode mode = CollaborationMode::kLocal);
|
CollaborationMode mode = CollaborationMode::kLocal);
|
||||||
|
|
||||||
// Leave the current collaboration session
|
|
||||||
absl::Status LeaveSession();
|
absl::Status LeaveSession();
|
||||||
|
|
||||||
// Refresh session information
|
|
||||||
absl::StatusOr<SessionInfo> RefreshSession();
|
absl::StatusOr<SessionInfo> RefreshSession();
|
||||||
|
|
||||||
// Multimodal (vision/screenshot) support
|
|
||||||
struct CaptureConfig {
|
struct CaptureConfig {
|
||||||
enum class CaptureMode {
|
enum class CaptureMode {
|
||||||
kFullWindow,
|
kFullWindow,
|
||||||
@@ -94,32 +122,34 @@ class AgentEditor {
|
|||||||
absl::Status SendToGemini(const std::filesystem::path& image_path,
|
absl::Status SendToGemini(const std::filesystem::path& image_path,
|
||||||
const std::string& prompt);
|
const std::string& prompt);
|
||||||
|
|
||||||
// Server management for network mode
|
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
absl::Status ConnectToServer(const std::string& server_url);
|
absl::Status ConnectToServer(const std::string& server_url);
|
||||||
void DisconnectFromServer();
|
void DisconnectFromServer();
|
||||||
bool IsConnectedToServer() const;
|
bool IsConnectedToServer() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// State queries
|
|
||||||
bool IsInSession() const;
|
bool IsInSession() const;
|
||||||
CollaborationMode GetCurrentMode() const;
|
CollaborationMode GetCurrentMode() const;
|
||||||
std::optional<SessionInfo> GetCurrentSession() const;
|
std::optional<SessionInfo> GetCurrentSession() const;
|
||||||
|
|
||||||
// Access to underlying components (for advanced use)
|
// Access to underlying components
|
||||||
AgentChatWidget* GetChatWidget() { return chat_widget_.get(); }
|
|
||||||
AgentCollaborationCoordinator* GetLocalCoordinator() { return local_coordinator_.get(); }
|
AgentCollaborationCoordinator* GetLocalCoordinator() { return local_coordinator_.get(); }
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
NetworkCollaborationCoordinator* GetNetworkCoordinator() { return network_coordinator_.get(); }
|
NetworkCollaborationCoordinator* GetNetworkCoordinator() { return network_coordinator_.get(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Setup callbacks for the chat widget
|
// Dashboard panel rendering
|
||||||
|
void DrawConfigurationPanel();
|
||||||
|
void DrawStatusPanel();
|
||||||
|
void DrawMetricsPanel();
|
||||||
|
|
||||||
|
// Setup callbacks
|
||||||
void SetupChatWidgetCallbacks();
|
void SetupChatWidgetCallbacks();
|
||||||
void SetupMultimodalCallbacks();
|
void SetupMultimodalCallbacks();
|
||||||
|
|
||||||
// Internal state
|
// Internal state
|
||||||
std::unique_ptr<AgentChatWidget> chat_widget_;
|
std::unique_ptr<AgentChatWidget> chat_widget_; // Owned by AgentEditor
|
||||||
std::unique_ptr<AgentCollaborationCoordinator> local_coordinator_;
|
std::unique_ptr<AgentCollaborationCoordinator> local_coordinator_;
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
std::unique_ptr<NetworkCollaborationCoordinator> network_coordinator_;
|
std::unique_ptr<NetworkCollaborationCoordinator> network_coordinator_;
|
||||||
@@ -129,11 +159,16 @@ class AgentEditor {
|
|||||||
ProposalDrawer* proposal_drawer_ = nullptr;
|
ProposalDrawer* proposal_drawer_ = nullptr;
|
||||||
Rom* rom_ = nullptr;
|
Rom* rom_ = nullptr;
|
||||||
|
|
||||||
|
// Configuration state
|
||||||
|
AgentConfig current_config_;
|
||||||
CollaborationMode current_mode_ = CollaborationMode::kLocal;
|
CollaborationMode current_mode_ = CollaborationMode::kLocal;
|
||||||
bool in_session_ = false;
|
bool in_session_ = false;
|
||||||
std::string current_session_id_;
|
std::string current_session_id_;
|
||||||
std::string current_session_name_;
|
std::string current_session_name_;
|
||||||
std::vector<std::string> current_participants_;
|
std::vector<std::string> current_participants_;
|
||||||
|
|
||||||
|
// UI state
|
||||||
|
bool show_advanced_settings_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace editor
|
||||||
|
|||||||
@@ -61,12 +61,13 @@ enum class EditorType {
|
|||||||
kSprite,
|
kSprite,
|
||||||
kMessage,
|
kMessage,
|
||||||
kHex,
|
kHex,
|
||||||
|
kAgent,
|
||||||
kSettings,
|
kSettings,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::array<const char*, 11> kEditorNames = {
|
constexpr std::array<const char*, 12> kEditorNames = {
|
||||||
"Assembly", "Dungeon", "Graphics", "Music", "Overworld",
|
"Assembly", "Dungeon", "Graphics", "Music", "Overworld",
|
||||||
"Palette", "Screen", "Sprite", "Message", "Hex", "Settings",
|
"Palette", "Screen", "Sprite", "Message", "Hex", "Agent", "Settings",
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -237,8 +237,10 @@ void EditorManager::Initialize(const std::string& filename) {
|
|||||||
project_file_editor_.SetToastManager(&toast_manager_);
|
project_file_editor_.SetToastManager(&toast_manager_);
|
||||||
|
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
// Initialize the agent editor
|
// Initialize the agent editor as a proper Editor (configuration dashboard)
|
||||||
agent_editor_.Initialize(&toast_manager_, &proposal_drawer_);
|
agent_editor_.set_context(&context_);
|
||||||
|
agent_editor_.Initialize();
|
||||||
|
agent_editor_.InitializeWithDependencies(&toast_manager_, &proposal_drawer_, nullptr);
|
||||||
|
|
||||||
// Set up multimodal (vision) callbacks for Gemini
|
// Set up multimodal (vision) callbacks for Gemini
|
||||||
AgentChatWidget::MultimodalCallbacks multimodal_callbacks;
|
AgentChatWidget::MultimodalCallbacks multimodal_callbacks;
|
||||||
@@ -550,7 +552,7 @@ absl::Status EditorManager::Update() {
|
|||||||
|
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
// Draw agent editor (includes chat widget and collaboration UI)
|
// Draw agent editor (includes chat widget and collaboration UI)
|
||||||
agent_editor_.Draw();
|
agent_editor_.Update();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Draw background grid effects for the entire viewport
|
// Draw background grid effects for the entire viewport
|
||||||
@@ -711,11 +713,10 @@ absl::Status EditorManager::Update() {
|
|||||||
proposal_drawer_.Draw();
|
proposal_drawer_.Draw();
|
||||||
}
|
}
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
Rom* rom_context =
|
// Update ROM context for agent editor
|
||||||
(current_rom_ != nullptr && current_rom_->is_loaded()) ? current_rom_
|
if (current_rom_ && current_rom_->is_loaded()) {
|
||||||
: nullptr;
|
agent_editor_.SetRomContext(current_rom_);
|
||||||
agent_editor_.SetRomContext(rom_context);
|
}
|
||||||
agent_editor_.Draw();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
@@ -858,6 +859,10 @@ void EditorManager::BuildModernMenu() {
|
|||||||
[this]() { current_editor_set_->screen_editor_.set_active(true); }, "Ctrl+8")
|
[this]() { current_editor_set_->screen_editor_.set_active(true); }, "Ctrl+8")
|
||||||
.Item("Hex Editor", ICON_MD_DATA_ARRAY,
|
.Item("Hex Editor", ICON_MD_DATA_ARRAY,
|
||||||
[this]() { show_memory_editor_ = true; }, "Ctrl+0")
|
[this]() { show_memory_editor_ = true; }, "Ctrl+0")
|
||||||
|
#ifdef YAZE_WITH_GRPC
|
||||||
|
.Item("AI Agent", ICON_MD_SMART_TOY,
|
||||||
|
[this]() { agent_editor_.set_active(true); }, "Ctrl+Shift+A")
|
||||||
|
#endif
|
||||||
.Separator()
|
.Separator()
|
||||||
.Item("Welcome Screen", ICON_MD_HOME,
|
.Item("Welcome Screen", ICON_MD_HOME,
|
||||||
[this]() { show_welcome_screen_ = true; })
|
[this]() { show_welcome_screen_ = true; })
|
||||||
@@ -1856,7 +1861,8 @@ absl::Status EditorManager::LoadRom() {
|
|||||||
// Hide welcome screen when ROM is successfully loaded - don't reset manual close state
|
// Hide welcome screen when ROM is successfully loaded - don't reset manual close state
|
||||||
show_welcome_screen_ = false;
|
show_welcome_screen_ = false;
|
||||||
|
|
||||||
// Show editor selection dialog after ROM loads
|
// Clear recent editors for fresh start with new ROM and show editor selection dialog
|
||||||
|
editor_selection_dialog_.ClearRecentEditors();
|
||||||
show_editor_selection_ = true;
|
show_editor_selection_ = true;
|
||||||
|
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
@@ -1982,6 +1988,7 @@ absl::Status EditorManager::OpenRomOrProject(const std::string& filename) {
|
|||||||
|
|
||||||
// Hide welcome screen and show editor selection when ROM is loaded
|
// Hide welcome screen and show editor selection when ROM is loaded
|
||||||
show_welcome_screen_ = false;
|
show_welcome_screen_ = false;
|
||||||
|
editor_selection_dialog_.ClearRecentEditors();
|
||||||
show_editor_selection_ = true;
|
show_editor_selection_ = true;
|
||||||
}
|
}
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
@@ -2061,6 +2068,7 @@ absl::Status EditorManager::OpenProject() {
|
|||||||
|
|
||||||
// Hide welcome screen and show editor selection when project ROM is loaded
|
// Hide welcome screen and show editor selection when project ROM is loaded
|
||||||
show_welcome_screen_ = false;
|
show_welcome_screen_ = false;
|
||||||
|
editor_selection_dialog_.ClearRecentEditors();
|
||||||
show_editor_selection_ = true;
|
show_editor_selection_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ EditorSelectionDialog::EditorSelectionDialog() {
|
|||||||
"Direct ROM memory editing and comparison", "Ctrl+0", false, true,
|
"Direct ROM memory editing and comparison", "Ctrl+0", false, true,
|
||||||
ImVec4(0.2f, 0.8f, 0.4f, 1.0f)}, // Matrix green
|
ImVec4(0.2f, 0.8f, 0.4f, 1.0f)}, // Matrix green
|
||||||
|
|
||||||
|
{EditorType::kAgent, "AI Agent", ICON_MD_SMART_TOY,
|
||||||
|
"Configure AI agent, collaboration, and automation", "Ctrl+Shift+A", false, false,
|
||||||
|
ImVec4(0.8f, 0.4f, 1.0f, 1.0f)}, // Purple/magenta
|
||||||
|
|
||||||
{EditorType::kSettings, "Settings", ICON_MD_SETTINGS,
|
{EditorType::kSettings, "Settings", ICON_MD_SETTINGS,
|
||||||
"Configure ROM and project settings", "", false, true,
|
"Configure ROM and project settings", "", false, true,
|
||||||
ImVec4(0.6f, 0.6f, 0.6f, 1.0f)}, // Gray
|
ImVec4(0.6f, 0.6f, 0.6f, 1.0f)}, // Gray
|
||||||
|
|||||||
@@ -85,6 +85,14 @@ class EditorSelectionDialog {
|
|||||||
*/
|
*/
|
||||||
void SaveRecentEditors();
|
void SaveRecentEditors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear recent editors (for new ROM sessions)
|
||||||
|
*/
|
||||||
|
void ClearRecentEditors() {
|
||||||
|
recent_editors_.clear();
|
||||||
|
SaveRecentEditors();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DrawEditorCard(const EditorInfo& info, int index);
|
void DrawEditorCard(const EditorInfo& info, int index);
|
||||||
void DrawWelcomeHeader();
|
void DrawWelcomeHeader();
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ void WelcomeScreen::DrawRecentProjects() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Grid layout for project cards (compact)
|
// Grid layout for project cards (compact)
|
||||||
float card_width = 200.0f; // Reduced for compactness
|
float card_width = 220.0f; // Reduced for compactness
|
||||||
float card_height = 95.0f; // Reduced for less scrolling
|
float card_height = 95.0f; // Reduced for less scrolling
|
||||||
int columns = std::max(1, (int)(ImGui::GetContentRegionAvail().x / (card_width + 12)));
|
int columns = std::max(1, (int)(ImGui::GetContentRegionAvail().x / (card_width + 12)));
|
||||||
|
|
||||||
@@ -650,8 +650,8 @@ void WelcomeScreen::DrawProjectCard(const RecentProject& project, int index) {
|
|||||||
ImGui::SetCursorScreenPos(ImVec2(content_pos.x + 4, content_pos.y + 58));
|
ImGui::SetCursorScreenPos(ImVec2(content_pos.x + 4, content_pos.y + 58));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.4f, 0.4f, 0.4f, 1.0f));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.4f, 0.4f, 0.4f, 1.0f));
|
||||||
std::string short_path = project.filepath;
|
std::string short_path = project.filepath;
|
||||||
if (short_path.length() > 28) {
|
if (short_path.length() > 26) {
|
||||||
short_path = "..." + short_path.substr(short_path.length() - 25);
|
short_path = "..." + short_path.substr(short_path.length() - 23);
|
||||||
}
|
}
|
||||||
ImGui::Text(ICON_MD_FOLDER " %s", short_path.c_str());
|
ImGui::Text(ICON_MD_FOLDER " %s", short_path.c_str());
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|||||||
Reference in New Issue
Block a user