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