29 ImGuiIO& io = ImGui::GetIO();
30 ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x -
drawer_width_, 0),
32 ImGui::SetNextWindowSize(ImVec2(
drawer_width_, io.DisplaySize.y),
35 ImGuiWindowFlags flags = ImGuiWindowFlags_NoMove |
36 ImGuiWindowFlags_NoResize |
37 ImGuiWindowFlags_NoCollapse;
39 if (ImGui::Begin(
"Agent Proposals", &
visible_, flags)) {
58 float list_height = ImGui::GetContentRegionAvail().y * 0.4f;
60 ImGui::BeginChild(
"ProposalList", ImVec2(0, list_height),
true);
66 ImGui::BeginChild(
"ProposalDetail", ImVec2(0, 0),
true);
75 ImGui::OpenPopup(
"Confirm Action");
79 if (ImGui::BeginPopupModal(
"Confirm Action",
nullptr,
80 ImGuiWindowFlags_AlwaysAutoResize)) {
81 ImGui::Text(
"Are you sure you want to %s this proposal?",
85 if (ImGui::Button(
"Yes", ImVec2(120, 0))) {
93 ImGui::CloseCurrentPopup();
97 if (ImGui::Button(
"No", ImVec2(120, 0))) {
98 ImGui::CloseCurrentPopup();
103#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
106 ImGui::OpenPopup(
"Override Policy");
110 if (ImGui::BeginPopupModal(
"Override Policy",
nullptr,
111 ImGuiWindowFlags_AlwaysAutoResize)) {
112 ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f),
115 ImGui::TextWrapped(
"This proposal has policy warnings.");
116 ImGui::TextWrapped(
"Do you want to override and accept anyway?");
118 ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
119 "Note: This action will be logged.");
122 if (ImGui::Button(
"Override and Accept", ImVec2(150, 0))) {
125 ImGui::CloseCurrentPopup();
128 if (ImGui::Button(
"Cancel", ImVec2(150, 0))) {
129 ImGui::CloseCurrentPopup();
139 ImGui::TextWrapped(
"No proposals found.");
140 ImGui::TextWrapped(
"Run CLI command: z3ed agent run --prompt \"...\"");
144 ImGuiTableFlags flags = ImGuiTableFlags_Borders |
145 ImGuiTableFlags_RowBg |
146 ImGuiTableFlags_ScrollY;
148 if (ImGui::BeginTable(
"ProposalsTable", 3, flags)) {
149 ImGui::TableSetupColumn(
"ID", ImGuiTableColumnFlags_WidthFixed, 60.0f);
150 ImGui::TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 80.0f);
151 ImGui::TableSetupColumn(
"Prompt", ImGuiTableColumnFlags_WidthStretch);
152 ImGui::TableSetupScrollFreeze(0, 1);
153 ImGui::TableHeadersRow();
156 ImGui::TableNextRow();
159 ImGui::TableSetColumnIndex(0);
161 if (ImGui::Selectable(proposal.id.c_str(), is_selected,
162 ImGuiSelectableFlags_SpanAllColumns)) {
167 ImGui::TableSetColumnIndex(1);
168 switch (proposal.status) {
170 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f),
"Pending");
173 ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"Accepted");
176 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
"Rejected");
181 ImGui::TableSetColumnIndex(2);
182 std::string truncated = proposal.prompt;
183 if (truncated.length() > 30) {
184 truncated = truncated.substr(0, 27) +
"...";
186 ImGui::TextWrapped(
"%s", truncated.c_str());
199 if (ImGui::CollapsingHeader(
"Metadata", ImGuiTreeNodeFlags_DefaultOpen)) {
200 ImGui::Text(
"ID: %s", p.id.c_str());
201 ImGui::Text(
"Sandbox: %s", p.sandbox_id.c_str());
202 ImGui::Text(
"Created: %s", absl::FormatTime(p.created_at).c_str());
203 if (p.reviewed_at.has_value()) {
204 ImGui::Text(
"Reviewed: %s", absl::FormatTime(*p.reviewed_at).c_str());
206 ImGui::Text(
"Commands: %d", p.commands_executed);
207 ImGui::Text(
"Bytes Changed: %d", p.bytes_changed);
209 ImGui::TextWrapped(
"Prompt: %s", p.prompt.c_str());
210 ImGui::TextWrapped(
"Description: %s", p.description.c_str());
214 if (ImGui::CollapsingHeader(
"Diff", ImGuiTreeNodeFlags_DefaultOpen)) {
215 if (
diff_content_.empty() && std::filesystem::exists(p.diff_path)) {
216 std::ifstream diff_file(p.diff_path);
217 if (diff_file.is_open()) {
218 std::stringstream buffer;
219 buffer << diff_file.rdbuf();
225 ImGui::BeginChild(
"DiffContent", ImVec2(0, 150),
true,
226 ImGuiWindowFlags_HorizontalScrollbar);
230 ImGui::TextWrapped(
"No diff available");
235 if (ImGui::CollapsingHeader(
"Execution Log")) {
236 if (
log_content_.empty() && std::filesystem::exists(p.log_path)) {
237 std::ifstream log_file(p.log_path);
238 if (log_file.is_open()) {
239 std::stringstream buffer;
243 buffer << line <<
"\n";
247 buffer <<
"... (truncated, see " << p.log_path.string() <<
")\n";
254 ImGui::BeginChild(
"LogContent", ImVec2(0, 150),
true,
255 ImGuiWindowFlags_HorizontalScrollbar);
259 ImGui::TextWrapped(
"No log available");
264#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
285#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
295 if (ImGui::CollapsingHeader(
"Policy Status", ImGuiTreeNodeFlags_DefaultOpen)) {
298 if (!policy_eval.IsEnabled()) {
299 ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f),
301 ImGui::TextWrapped(
"Create .yaze/policies/agent.yaml to enable policy evaluation");
306 auto policy_result = policy_eval.EvaluateProposal(p.id);
308 if (!policy_result.ok()) {
309 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
311 ImGui::TextWrapped(
"%s", policy_result.status().message().data());
315 const auto& result = policy_result.value();
318 if (result.is_clean()) {
319 ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
321 }
else if (result.passed) {
322 ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f),
325 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
332 if (!result.critical_violations.empty()) {
333 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
335 for (
const auto& violation : result.critical_violations) {
337 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
338 violation.message.c_str());
339 if (!violation.details.empty()) {
341 ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
"%s",
342 violation.details.c_str());
350 if (!result.warnings.empty()) {
351 ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f),
353 for (
const auto& violation : result.warnings) {
355 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
356 violation.message.c_str());
357 if (!violation.details.empty()) {
359 ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
"%s",
360 violation.details.c_str());
368 if (!result.info.empty()) {
369 ImGui::TextColored(ImVec4(0.5f, 0.5f, 1.0f, 1.0f),
371 for (
const auto& violation : result.info) {
373 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
374 violation.message.c_str());
512 auto proposal_or = registry.GetProposal(proposal_id);
513 if (!proposal_or.ok()) {
514 return proposal_or.status();
517 const auto& proposal = *proposal_or;
521 return absl::FailedPreconditionError(
522 "No ROM loaded. Cannot merge proposal changes.");
527 auto sandboxes = sandbox_mgr.ListSandboxes();
529 std::filesystem::path sandbox_rom_path;
530 for (
const auto& sandbox : sandboxes) {
531 if (sandbox.id == proposal.sandbox_id) {
532 sandbox_rom_path = sandbox.rom_path;
537 if (sandbox_rom_path.empty()) {
538 return absl::NotFoundError(
539 absl::StrFormat(
"Sandbox ROM not found for proposal %s (sandbox: %s)",
540 proposal_id, proposal.sandbox_id));
545 if (!std::filesystem::exists(sandbox_rom_path, ec)) {
546 return absl::NotFoundError(
547 absl::StrFormat(
"Sandbox ROM file does not exist: %s",
548 sandbox_rom_path.string()));
553 auto load_status = sandbox_rom.
LoadFromFile(sandbox_rom_path.string());
554 if (!load_status.ok()) {
555 return absl::InternalError(
556 absl::StrFormat(
"Failed to load sandbox ROM: %s",
557 load_status.message()));
562 const auto& sandbox_data = sandbox_rom.
vector();
564 if (!merge_status.ok()) {
565 return absl::InternalError(
566 absl::StrFormat(
"Failed to merge sandbox ROM data: %s",
567 merge_status.message()));
571 auto status = registry.UpdateStatus(