50 const float avail_y = std::max(0.0f, ImGui::GetContentRegionAvail().y);
51 const float detail_reserve =
53 const float list_budget = std::max(0.0f, avail_y - detail_reserve);
54 const float preferred_list = std::clamp(avail_y * 0.45f, 180.0f, 320.0f);
55 const float list_height = std::min(preferred_list, list_budget);
57 ImGui::BeginChild(
"ProposalListEmbed", ImVec2(0, list_height),
true);
63 ImGui::BeginChild(
"ProposalDetailEmbed", ImVec2(0, 0),
true);
74 ImGuiIO& io = ImGui::GetIO();
75 ImGui::SetNextWindowPos(ImVec2(io.DisplaySize.x -
drawer_width_, 0),
77 ImGui::SetNextWindowSize(ImVec2(
drawer_width_, io.DisplaySize.y),
80 ImGuiWindowFlags flags = ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize |
81 ImGuiWindowFlags_NoCollapse;
83 if (ImGui::Begin(
"Agent Proposals", &
visible_, flags)) {
102 float list_height = ImGui::GetContentRegionAvail().y * 0.4f;
104 ImGui::BeginChild(
"ProposalList", ImVec2(0, list_height),
true);
110 ImGui::BeginChild(
"ProposalDetail", ImVec2(0, 0),
true);
119 ImGui::OpenPopup(
"Confirm Action");
123 if (ImGui::BeginPopupModal(
"Confirm Action",
nullptr,
124 ImGuiWindowFlags_AlwaysAutoResize)) {
125 ImGui::Text(tr(
"Are you sure you want to %s this proposal?"),
129 if (ImGui::Button(tr(
"Yes"), ImVec2(120, 0))) {
137 ImGui::CloseCurrentPopup();
141 if (ImGui::Button(tr(
"No"), ImVec2(120, 0))) {
142 ImGui::CloseCurrentPopup();
147#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
150 ImGui::OpenPopup(
"Override Policy");
154 if (ImGui::BeginPopupModal(
"Override Policy",
nullptr,
155 ImGuiWindowFlags_AlwaysAutoResize)) {
159 ImGui::TextWrapped(tr(
"This proposal has policy warnings."));
160 ImGui::TextWrapped(tr(
"Do you want to override and accept anyway?"));
163 tr(
"Note: This action will be logged."));
166 if (ImGui::Button(tr(
"Override and Accept"), ImVec2(150, 0))) {
169 ImGui::CloseCurrentPopup();
172 if (ImGui::Button(tr(
"Cancel"), ImVec2(150, 0))) {
173 ImGui::CloseCurrentPopup();
182 ImGui::TextWrapped(tr(
"No proposals found."));
183 ImGui::TextWrapped(tr(
"Run CLI command: z3ed agent run --prompt \"...\""));
187 ImGuiTableFlags flags =
188 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY;
190 if (ImGui::BeginTable(
"ProposalsTable", 3, flags)) {
191 ImGui::TableSetupColumn(
"ID", ImGuiTableColumnFlags_WidthFixed, 60.0f);
192 ImGui::TableSetupColumn(
"Status", ImGuiTableColumnFlags_WidthFixed, 80.0f);
193 ImGui::TableSetupColumn(
"Prompt", ImGuiTableColumnFlags_WidthStretch);
194 ImGui::TableSetupScrollFreeze(0, 1);
195 ImGui::TableHeadersRow();
198 ImGui::TableNextRow();
201 ImGui::TableSetColumnIndex(0);
203 if (ImGui::Selectable(proposal.id.c_str(), is_selected,
204 ImGuiSelectableFlags_SpanAllColumns)) {
209 ImGui::TableSetColumnIndex(1);
210 switch (proposal.status) {
225 ImGui::TableSetColumnIndex(2);
226 std::string truncated = proposal.prompt;
227 if (truncated.length() > 30) {
228 truncated = truncated.substr(0, 27) +
"...";
230 ImGui::TextWrapped(
"%s", truncated.c_str());
244 if (ImGui::CollapsingHeader(tr(
"Metadata"), ImGuiTreeNodeFlags_DefaultOpen)) {
245 ImGui::Text(tr(
"ID: %s"), p.id.c_str());
246 ImGui::Text(tr(
"Sandbox: %s"), p.sandbox_id.c_str());
247 ImGui::Text(tr(
"Created: %s"), absl::FormatTime(p.created_at).c_str());
248 if (p.reviewed_at.has_value()) {
249 ImGui::Text(tr(
"Reviewed: %s"), absl::FormatTime(*p.reviewed_at).c_str());
251 ImGui::Text(tr(
"Commands: %d"), p.commands_executed);
252 ImGui::Text(tr(
"Bytes Changed: %d"), p.bytes_changed);
254 ImGui::TextWrapped(tr(
"Prompt: %s"), p.prompt.c_str());
255 ImGui::TextWrapped(tr(
"Description: %s"), p.description.c_str());
259 if (ImGui::CollapsingHeader(tr(
"Diff"), ImGuiTreeNodeFlags_DefaultOpen)) {
260 if (
diff_content_.empty() && std::filesystem::exists(p.diff_path)) {
261 std::ifstream diff_file(p.diff_path);
262 if (diff_file.is_open()) {
263 std::stringstream buffer;
264 buffer << diff_file.rdbuf();
270 ImGui::BeginChild(
"DiffContent", ImVec2(0, 150),
true,
271 ImGuiWindowFlags_HorizontalScrollbar);
275 ImGui::TextWrapped(tr(
"No diff available"));
280 if (ImGui::CollapsingHeader(tr(
"Execution Log"))) {
281 if (
log_content_.empty() && std::filesystem::exists(p.log_path)) {
282 std::ifstream log_file(p.log_path);
283 if (log_file.is_open()) {
284 std::stringstream buffer;
287 while (std::getline(log_file, line) &&
289 buffer << line <<
"\n";
293 buffer <<
"... (truncated, see " << p.log_path.string() <<
")\n";
300 ImGui::BeginChild(
"LogContent", ImVec2(0, 150),
true,
301 ImGuiWindowFlags_HorizontalScrollbar);
305 ImGui::TextWrapped(tr(
"No log available"));
310#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
331#ifdef YAZE_ENABLE_POLICY_FRAMEWORK
342 if (ImGui::CollapsingHeader(tr(
"Policy Status"),
343 ImGuiTreeNodeFlags_DefaultOpen)) {
346 if (!policy_eval.IsEnabled()) {
350 tr(
"Create .yaze/policies/agent.yaml to enable policy evaluation"));
355 auto policy_result = policy_eval.EvaluateProposal(p.id);
357 if (!policy_result.ok()) {
360 ImGui::TextWrapped(
"%s", policy_result.status().message().data());
364 const auto& result = policy_result.value();
367 if (result.is_clean()) {
370 }
else if (result.passed) {
381 if (!result.critical_violations.empty()) {
384 for (
const auto& violation : result.critical_violations) {
386 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
387 violation.message.c_str());
388 if (!violation.details.empty()) {
391 violation.details.c_str());
399 if (!result.warnings.empty()) {
401 for (
const auto& violation : result.warnings) {
403 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
404 violation.message.c_str());
405 if (!violation.details.empty()) {
408 violation.details.c_str());
416 if (!result.info.empty()) {
418 for (
const auto& violation : result.info) {
420 ImGui::TextWrapped(
"%s: %s", violation.policy_name.c_str(),
421 violation.message.c_str());
562 auto proposal_or = registry.GetProposal(proposal_id);
563 if (!proposal_or.ok()) {
564 return proposal_or.status();
567 const auto& proposal = *proposal_or;
571 return absl::FailedPreconditionError(
572 "No ROM loaded. Cannot merge proposal changes.");
577 auto sandboxes = sandbox_mgr.ListSandboxes();
579 std::filesystem::path sandbox_rom_path;
580 for (
const auto& sandbox : sandboxes) {
581 if (sandbox.id == proposal.sandbox_id) {
582 sandbox_rom_path = sandbox.rom_path;
587 if (sandbox_rom_path.empty()) {
588 return absl::NotFoundError(
589 absl::StrFormat(
"Sandbox ROM not found for proposal %s (sandbox: %s)",
590 proposal_id, proposal.sandbox_id));
595 if (!std::filesystem::exists(sandbox_rom_path, ec)) {
596 return absl::NotFoundError(absl::StrFormat(
597 "Sandbox ROM file does not exist: %s", sandbox_rom_path.string()));
602 auto load_status = sandbox_rom.
LoadFromFile(sandbox_rom_path.string());
603 if (!load_status.ok()) {
604 return absl::InternalError(absl::StrFormat(
"Failed to load sandbox ROM: %s",
605 load_status.message()));
610 const auto& sandbox_data = sandbox_rom.
vector();
612 if (!merge_status.ok()) {
613 return absl::InternalError(absl::StrFormat(
614 "Failed to merge sandbox ROM data: %s", merge_status.message()));
618 auto status = registry.UpdateStatus(
630 return absl::UnimplementedError(
"AI features disabled");