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