66 ImGuiIO& io = ImGui::GetIO();
67 ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x -
drawer_width_, 0),
69 ImGui::SetNextWindowSize(ImVec2(
drawer_width_, io.DisplaySize.y),
72 ImGuiWindowFlags flags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize |
73 ImGuiWindowFlags_NoCollapse;
75 if (ImGui::Begin(
"Agent Proposals", &
visible_, flags)) {
94 float list_height = ImGui::GetContentRegionAvail().y * 0.4f;
96 ImGui::BeginChild(
"ProposalList", ImVec2(0, list_height),
true);
102 ImGui::BeginChild(
"ProposalDetail", ImVec2(0, 0),
true);
111 ImGui::OpenPopup(
"Confirm Action");
115 if (ImGui::BeginPopupModal(
"Confirm Action",
nullptr,
116 ImGuiWindowFlags_AlwaysAutoResize)) {
117 ImGui::Text(
"Are you sure you want to %s this proposal?",
121 if (ImGui::Button(
"Yes", ImVec2(120, 0))) {
129 ImGui::CloseCurrentPopup();
133 if (ImGui::Button(
"No", ImVec2(120, 0))) {
134 ImGui::CloseCurrentPopup();
139#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
142 ImGui::OpenPopup(
"Override Policy");
146 if (ImGui::BeginPopupModal(
"Override Policy",
nullptr,
147 ImGuiWindowFlags_AlwaysAutoResize)) {
148 ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f),
151 ImGui::TextWrapped(
"This proposal has policy warnings.");
152 ImGui::TextWrapped(
"Do you want to override and accept anyway?");
154 ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
155 "Note: This action will be logged.");
158 if (ImGui::Button(
"Override and Accept", ImVec2(150, 0))) {
161 ImGui::CloseCurrentPopup();
164 if (ImGui::Button(
"Cancel", ImVec2(150, 0))) {
165 ImGui::CloseCurrentPopup();
174 ImGui::TextWrapped(
"No proposals found.");
175 ImGui::TextWrapped(
"Run CLI command: z3ed agent run --prompt \"...\"");
179 ImGuiTableFlags flags =
180 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY;
182 if (ImGui::BeginTable(
"ProposalsTable", 3, flags)) {
183 ImGui::TableSetupColumn(
"ID", ImGuiTableColumnFlags_WidthFixed, 60.0f);
184 ImGui::TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 80.0f);
185 ImGui::TableSetupColumn(
"Prompt", ImGuiTableColumnFlags_WidthStretch);
186 ImGui::TableSetupScrollFreeze(0, 1);
187 ImGui::TableHeadersRow();
190 ImGui::TableNextRow();
193 ImGui::TableSetColumnIndex(0);
195 if (ImGui::Selectable(proposal.id.c_str(), is_selected,
196 ImGuiSelectableFlags_SpanAllColumns)) {
201 ImGui::TableSetColumnIndex(1);
202 switch (proposal.status) {
204 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f),
"Pending");
207 ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
"Accepted");
210 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
"Rejected");
215 ImGui::TableSetColumnIndex(2);
216 std::string truncated = proposal.prompt;
217 if (truncated.length() > 30) {
218 truncated = truncated.substr(0, 27) +
"...";
220 ImGui::TextWrapped(
"%s", truncated.c_str());
234 if (ImGui::CollapsingHeader(
"Metadata", ImGuiTreeNodeFlags_DefaultOpen)) {
235 ImGui::Text(
"ID: %s", p.id.c_str());
236 ImGui::Text(
"Sandbox: %s", p.sandbox_id.c_str());
237 ImGui::Text(
"Created: %s", absl::FormatTime(p.created_at).c_str());
238 if (p.reviewed_at.has_value()) {
239 ImGui::Text(
"Reviewed: %s", absl::FormatTime(*p.reviewed_at).c_str());
241 ImGui::Text(
"Commands: %d", p.commands_executed);
242 ImGui::Text(
"Bytes Changed: %d", p.bytes_changed);
244 ImGui::TextWrapped(
"Prompt: %s", p.prompt.c_str());
245 ImGui::TextWrapped(
"Description: %s", p.description.c_str());
249 if (ImGui::CollapsingHeader(
"Diff", ImGuiTreeNodeFlags_DefaultOpen)) {
250 if (
diff_content_.empty() && std::filesystem::exists(p.diff_path)) {
251 std::ifstream diff_file(p.diff_path);
252 if (diff_file.is_open()) {
253 std::stringstream buffer;
254 buffer << diff_file.rdbuf();
260 ImGui::BeginChild(
"DiffContent", ImVec2(0, 150),
true,
261 ImGuiWindowFlags_HorizontalScrollbar);
265 ImGui::TextWrapped(
"No diff available");
270 if (ImGui::CollapsingHeader(
"Execution Log")) {
271 if (
log_content_.empty() && std::filesystem::exists(p.log_path)) {
272 std::ifstream log_file(p.log_path);
273 if (log_file.is_open()) {
274 std::stringstream buffer;
277 while (std::getline(log_file, line) &&
279 buffer << line <<
"\n";
283 buffer <<
"... (truncated, see " << p.log_path.string() <<
")\n";
290 ImGui::BeginChild(
"LogContent", ImVec2(0, 150),
true,
291 ImGuiWindowFlags_HorizontalScrollbar);
295 ImGui::TextWrapped(
"No log available");
300#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
321#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
332 if (ImGui::CollapsingHeader(
"Policy Status",
333 ImGuiTreeNodeFlags_DefaultOpen)) {
336 if (!policy_eval.IsEnabled()) {
337 ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f),
340 "Create .yaze/policies/agent.yaml to enable policy evaluation");
345 auto policy_result = policy_eval.EvaluateProposal(p.id);
347 if (!policy_result.ok()) {
348 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
350 ImGui::TextWrapped(
"%s", policy_result.status().message().data());
354 const auto& result = policy_result.value();
357 if (result.is_clean()) {
358 ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
360 }
else if (result.passed) {
361 ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f),
364 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
371 if (!result.critical_violations.empty()) {
372 ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f),
374 for (
const auto& violation : result.critical_violations) {
376 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
377 violation.message.c_str());
378 if (!violation.details.empty()) {
380 ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
"%s",
381 violation.details.c_str());
389 if (!result.warnings.empty()) {
390 ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f),
392 for (
const auto& violation : result.warnings) {
394 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
395 violation.message.c_str());
396 if (!violation.details.empty()) {
398 ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f),
"%s",
399 violation.details.c_str());
407 if (!result.info.empty()) {
408 ImGui::TextColored(ImVec4(0.5f, 0.5f, 1.0f, 1.0f),
410 for (
const auto& violation : result.info) {
412 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
413 violation.message.c_str());
554 auto proposal_or = registry.GetProposal(proposal_id);
555 if (!proposal_or.ok()) {
556 return proposal_or.status();
559 const auto& proposal = *proposal_or;
563 return absl::FailedPreconditionError(
564 "No ROM loaded. Cannot merge proposal changes.");
569 auto sandboxes = sandbox_mgr.ListSandboxes();
571 std::filesystem::path sandbox_rom_path;
572 for (
const auto& sandbox : sandboxes) {
573 if (sandbox.id == proposal.sandbox_id) {
574 sandbox_rom_path = sandbox.rom_path;
579 if (sandbox_rom_path.empty()) {
580 return absl::NotFoundError(
581 absl::StrFormat(
"Sandbox ROM not found for proposal %s (sandbox: %s)",
582 proposal_id, proposal.sandbox_id));
587 if (!std::filesystem::exists(sandbox_rom_path, ec)) {
588 return absl::NotFoundError(absl::StrFormat(
589 "Sandbox ROM file does not exist: %s", sandbox_rom_path.string()));
594 auto load_status = sandbox_rom.
LoadFromFile(sandbox_rom_path.string());
595 if (!load_status.ok()) {
596 return absl::InternalError(absl::StrFormat(
"Failed to load sandbox ROM: %s",
597 load_status.message()));
602 const auto& sandbox_data = sandbox_rom.
vector();
604 if (!merge_status.ok()) {
605 return absl::InternalError(absl::StrFormat(
606 "Failed to merge sandbox ROM data: %s", merge_status.message()));
610 auto status = registry.UpdateStatus(
622 return absl::UnimplementedError(
"AI features disabled");