yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
agent_automation_panel.cc
Go to the documentation of this file.
2
3#include <cmath>
4#include <string>
5#include <vector>
6
7#include "absl/strings/str_format.h"
8#include "absl/time/clock.h"
9#include "absl/time/time.h"
11#include "app/gui/core/icons.h"
12#include "imgui/imgui.h"
13
14namespace yaze {
15namespace editor {
16
18 const AutomationCallbacks& callbacks) {
19 const auto& theme = AgentUI::GetTheme();
20 auto& state = context->automation_state();
21
22 ImGui::PushID("AutomationPanel");
23
24 // Auto-poll for status updates
25 if (callbacks.poll_status) {
26 callbacks.poll_status();
27 }
28
29 // Animate pulse and scanlines for retro effect
30 state.pulse_animation += ImGui::GetIO().DeltaTime * 2.0f;
31 state.scanline_offset += ImGui::GetIO().DeltaTime * 0.5f;
32 if (state.scanline_offset > 1.0f) {
33 state.scanline_offset -= 1.0f;
34 }
35
37 if (ImGui::BeginChild("Automation_Panel", ImVec2(0, 240), true)) {
38 // === HEADER WITH RETRO GLITCH EFFECT ===
39 float pulse = 0.5f + 0.5f * std::sin(state.pulse_animation);
40 ImVec4 header_glow = ImVec4(theme.provider_ollama.x + 0.3f * pulse,
41 theme.provider_ollama.y + 0.2f * pulse,
42 theme.provider_ollama.z + 0.4f * pulse, 1.0f);
43
44 ImGui::PushStyleColor(ImGuiCol_Text, header_glow);
45 ImGui::TextWrapped("%s %s", ICON_MD_SMART_TOY, "GUI AUTOMATION");
46 ImGui::PopStyleColor();
47
48 ImGui::SameLine();
49 ImGui::TextDisabled("[v0.5.x]");
50
51 // === CONNECTION STATUS WITH VISUAL EFFECTS ===
52 bool connected = state.harness_connected;
53 ImVec4 status_color;
54 const char* status_text;
55 const char* status_icon;
56
57 if (connected) {
58 // Pulsing green for connected
59 float green_pulse = 0.7f + 0.3f * std::sin(state.pulse_animation * 0.5f);
60 status_color = ImVec4(0.1f, green_pulse, 0.3f, 1.0f);
61 status_text = "ONLINE";
62 status_icon = ICON_MD_CHECK_CIRCLE;
63 } else {
64 // Pulsing red for disconnected
65 float red_pulse = 0.6f + 0.4f * std::sin(state.pulse_animation * 1.5f);
66 status_color = ImVec4(red_pulse, 0.2f, 0.2f, 1.0f);
67 status_text = "OFFLINE";
68 status_icon = ICON_MD_ERROR;
69 }
70
71 ImGui::Separator();
72 ImGui::TextColored(status_color, "%s %s", status_icon, status_text);
73 ImGui::SameLine();
74 ImGui::TextDisabled("| %s", state.grpc_server_address.c_str());
75
76 // === CONTROL BAR ===
77 ImGui::Spacing();
78
79 // Refresh button with pulse effect when auto-refresh is on
80 bool auto_ref_pulse =
81 state.auto_refresh_enabled &&
82 (static_cast<int>(state.pulse_animation * 2.0f) % 2 == 0);
83 if (auto_ref_pulse) {
84 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.5f, 0.7f, 0.8f));
85 }
86
87 if (ImGui::SmallButton(ICON_MD_REFRESH " Refresh")) {
88 if (callbacks.poll_status) {
89 callbacks.poll_status();
90 }
91 if (callbacks.show_active_tests) {
92 callbacks.show_active_tests();
93 }
94 }
95
96 if (auto_ref_pulse) {
97 ImGui::PopStyleColor();
98 }
99
100 if (ImGui::IsItemHovered()) {
101 ImGui::SetTooltip("Refresh automation status\nAuto-refresh: %s (%.1fs)",
102 state.auto_refresh_enabled ? "ON" : "OFF",
103 state.refresh_interval_seconds);
104 }
105
106 // Auto-refresh toggle
107 ImGui::SameLine();
108 ImGui::Checkbox("##auto_refresh", &state.auto_refresh_enabled);
109 if (ImGui::IsItemHovered()) {
110 ImGui::SetTooltip("Auto-refresh connection status");
111 }
112
113 // Quick action buttons
114 ImGui::SameLine();
115 if (ImGui::SmallButton(ICON_MD_DASHBOARD " Dashboard")) {
116 if (callbacks.open_harness_dashboard) {
117 callbacks.open_harness_dashboard();
118 }
119 }
120 if (ImGui::IsItemHovered()) {
121 ImGui::SetTooltip("Open automation dashboard");
122 }
123
124 ImGui::SameLine();
125 if (ImGui::SmallButton(ICON_MD_REPLAY " Replay")) {
126 if (callbacks.replay_last_plan) {
127 callbacks.replay_last_plan();
128 }
129 }
130 if (ImGui::IsItemHovered()) {
131 ImGui::SetTooltip("Replay last automation plan");
132 }
133
134 // === SETTINGS ROW ===
135 ImGui::Spacing();
136 ImGui::SetNextItemWidth(80.0f);
137 ImGui::SliderFloat("##refresh_interval", &state.refresh_interval_seconds,
138 0.5f, 10.0f, "%.1fs");
139 if (ImGui::IsItemHovered()) {
140 ImGui::SetTooltip("Auto-refresh interval");
141 }
142
143 ImGui::Spacing();
144 ImGui::Separator();
145 ImGui::TextDisabled("Automation Hooks");
146 ImGui::Checkbox("Auto-run harness plan", &state.auto_run_plan);
147 ImGui::Checkbox("Auto-sync ROM context", &state.auto_sync_rom);
148 ImGui::Checkbox("Auto-focus proposal drawer", &state.auto_focus_proposals);
149
150 // === RECENT AUTOMATION ACTIONS WITH SCROLLING ===
151 ImGui::Spacing();
152 ImGui::Separator();
153
154 // Header with retro styling
155 ImGui::TextColored(ImVec4(0.4f, 0.8f, 1.0f, 1.0f), "%s RECENT ACTIONS",
157 ImGui::SameLine();
158 ImGui::TextDisabled("[%zu]", state.recent_tests.size());
159
160 if (state.recent_tests.empty()) {
161 ImGui::Spacing();
162 ImGui::TextDisabled(" > No recent actions");
163 ImGui::TextDisabled(" > Waiting for automation tasks...");
164
165 // Add animated dots
166 int dots = static_cast<int>(state.pulse_animation) % 4;
167 std::string dot_string(dots, '.');
168 ImGui::TextDisabled(" > %s", dot_string.c_str());
169 } else {
170 // Scrollable action list with retro styling
171 ImGui::BeginChild("ActionQueue", ImVec2(0, 100), true,
172 ImGuiWindowFlags_AlwaysVerticalScrollbar);
173
174 // Add scanline effect (visual only)
175 ImDrawList* draw_list = ImGui::GetWindowDrawList();
176 ImVec2 win_pos = ImGui::GetWindowPos();
177 ImVec2 win_size = ImGui::GetWindowSize();
178
179 // Draw scanlines
180 for (float y = 0; y < win_size.y; y += 4.0f) {
181 float offset_y = y + state.scanline_offset * 4.0f;
182 if (offset_y < win_size.y) {
183 draw_list->AddLine(
184 ImVec2(win_pos.x, win_pos.y + offset_y),
185 ImVec2(win_pos.x + win_size.x, win_pos.y + offset_y),
186 IM_COL32(0, 0, 0, 20));
187 }
188 }
189
190 for (const auto& test : state.recent_tests) {
191 ImGui::PushID(test.test_id.c_str());
192
193 // Status icon with animation for running tests
194 ImVec4 action_color;
195 const char* status_icon;
196
197 if (test.status == "success" || test.status == "completed" ||
198 test.status == "passed") {
199 action_color = theme.status_success;
200 status_icon = ICON_MD_CHECK_CIRCLE;
201 } else if (test.status == "running" || test.status == "in_progress") {
202 float running_pulse =
203 0.5f + 0.5f * std::sin(state.pulse_animation * 3.0f);
204 action_color =
205 ImVec4(theme.provider_ollama.x * running_pulse,
206 theme.provider_ollama.y * (0.8f + 0.2f * running_pulse),
207 theme.provider_ollama.z * running_pulse, 1.0f);
208 status_icon = ICON_MD_PENDING;
209 } else if (test.status == "failed" || test.status == "error") {
210 action_color = theme.status_error;
211 status_icon = ICON_MD_ERROR;
212 } else {
213 action_color = theme.text_secondary_color;
214 status_icon = ICON_MD_HELP;
215 }
216
217 // Icon with pulse
218 ImGui::TextColored(action_color, "%s", status_icon);
219 ImGui::SameLine();
220
221 // Action name with monospace font
222 ImGui::Text("> %s", test.name.c_str());
223
224 // Timestamp
225 if (test.updated_at != absl::InfinitePast()) {
226 ImGui::SameLine();
227 auto elapsed = absl::Now() - test.updated_at;
228 if (elapsed < absl::Seconds(60)) {
229 ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "[%ds]",
230 static_cast<int>(absl::ToInt64Seconds(elapsed)));
231 } else if (elapsed < absl::Minutes(60)) {
232 ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "[%dm]",
233 static_cast<int>(absl::ToInt64Minutes(elapsed)));
234 } else {
235 ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "[%dh]",
236 static_cast<int>(absl::ToInt64Hours(elapsed)));
237 }
238 }
239
240 // Message (if any) with indentation
241 if (!test.message.empty()) {
242 ImGui::Indent(20.0f);
243 ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.7f, 0.7f, 0.7f, 1.0f));
244 ImGui::TextWrapped(" %s %s", ICON_MD_MESSAGE, test.message.c_str());
245 ImGui::PopStyleColor();
246 ImGui::Unindent(20.0f);
247 }
248
249 ImGui::PopID();
250 }
251
252 ImGui::EndChild();
253 }
254 }
255 ImGui::EndChild();
257 ImGui::PopID();
258}
259
260} // namespace editor
261} // namespace yaze
void Draw(AgentUIContext *context, const AutomationCallbacks &callbacks)
Unified context for agent UI components.
AutomationState & automation_state()
#define ICON_MD_REFRESH
Definition icons.h:1572
#define ICON_MD_MESSAGE
Definition icons.h:1201
#define ICON_MD_REPLAY
Definition icons.h:1588
#define ICON_MD_ERROR
Definition icons.h:686
#define ICON_MD_LIST
Definition icons.h:1094
#define ICON_MD_PENDING
Definition icons.h:1398
#define ICON_MD_CHECK_CIRCLE
Definition icons.h:400
#define ICON_MD_DASHBOARD
Definition icons.h:517
#define ICON_MD_HELP
Definition icons.h:933
#define ICON_MD_SMART_TOY
Definition icons.h:1781
const AgentUITheme & GetTheme()
Callbacks for automation operations.
std::function< void()> show_active_tests
std::function< void()> open_harness_dashboard
std::function< void()> replay_last_plan
std::function< void()> poll_status