yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
agent_configuration_panel.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cstdio>
5#include <cstdlib>
6#include <string>
7#include <vector>
8
9#include "absl/strings/str_format.h"
10#include "absl/strings/str_join.h"
11#include "absl/strings/ascii.h"
13#include "app/editor/system/toast_manager.h"
14#include "app/gui/core/icons.h"
15#include "imgui/imgui.h"
16
17#if defined(__EMSCRIPTEN__)
18#include <emscripten/emscripten.h>
19#endif
20
21namespace yaze {
22namespace editor {
23
24namespace {
25
26std::string FormatByteSize(uint64_t bytes) {
27 if (bytes < 1024) return absl::StrFormat("%d B", bytes);
28 if (bytes < 1024 * 1024) return absl::StrFormat("%.1f KB", bytes / 1024.0);
29 if (bytes < 1024 * 1024 * 1024)
30 return absl::StrFormat("%.1f MB", bytes / (1024.0 * 1024.0));
31 return absl::StrFormat("%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0));
32}
33
34std::string FormatRelativeTime(absl::Time timestamp) {
35 if (timestamp == absl::InfinitePast()) return "never";
36 auto delta = absl::Now() - timestamp;
37 if (delta < absl::Seconds(60)) return "just now";
38 if (delta < absl::Minutes(60))
39 return absl::StrFormat("%.0fm ago", absl::ToDoubleMinutes(delta));
40 if (delta < absl::Hours(24))
41 return absl::StrFormat("%.0fh ago", absl::ToDoubleHours(delta));
42 return absl::StrFormat("%.0fd ago", absl::ToDoubleHours(delta) / 24.0);
43}
44
45} // namespace
46
48 const Callbacks& callbacks,
49 ToastManager* toast_manager) {
50 const auto& theme = AgentUI::GetTheme();
51
52 ImGui::PushStyleColor(ImGuiCol_ChildBg, theme.panel_bg_color);
53 ImGui::BeginChild("AgentConfig", ImVec2(0, 190), true);
55 theme.command_text_color);
56
57 if (ImGui::BeginTabBar("AgentConfigTabs",
58 ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
59 if (ImGui::BeginTabItem(ICON_MD_SMART_TOY " Models")) {
60 RenderModelConfigControls(context, callbacks, toast_manager);
61 ImGui::Separator();
62 RenderModelDeck(context, callbacks, toast_manager);
63 ImGui::EndTabItem();
64 }
65 if (ImGui::BeginTabItem(ICON_MD_TUNE " Parameters")) {
67 ImGui::EndTabItem();
68 }
69 if (ImGui::BeginTabItem(ICON_MD_CONSTRUCTION " Tools")) {
70 RenderToolingControls(context->agent_config(), callbacks);
71 ImGui::EndTabItem();
72 }
73 }
74 ImGui::EndTabBar();
75
76 ImGui::Spacing();
77 // Note: persist_agent_config_with_history_ logic was local to AgentChatWidget.
78 // We might want to move it to AgentConfigState if it needs to be persisted.
79 // For now, we'll skip it or add it to AgentConfigState if needed.
80 // Assuming it's not critical for this refactor, or we can add it later.
81
82 if (ImGui::Button(ICON_MD_CLOUD_SYNC " Apply Provider Settings",
83 ImVec2(-1, 0))) {
84 if (callbacks.update_config) {
85 callbacks.update_config(context->agent_config());
86 }
87 }
88
89 ImGui::EndChild();
90 ImGui::PopStyleColor();
91}
92
94 AgentUIContext* context, const Callbacks& callbacks,
95 ToastManager* toast_manager) {
96 const auto& theme = AgentUI::GetTheme();
97 auto& config = context->agent_config();
98 auto& model_cache = context->model_cache();
99
100 // Provider selection buttons using theme colors
101 auto provider_button = [&](const char* label, const char* value,
102 const ImVec4& color) {
103 bool active = config.ai_provider == value;
104 if (active) {
105 ImGui::PushStyleColor(ImGuiCol_Button, color);
106 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
107 ImVec4(color.x * 1.15f, color.y * 1.15f,
108 color.z * 1.15f, color.w));
109 }
110 if (ImGui::Button(label, ImVec2(90, 28))) {
111 config.ai_provider = value;
112 std::snprintf(config.provider_buffer, sizeof(config.provider_buffer),
113 "%s", value);
114 }
115 if (active) {
116 ImGui::PopStyleColor(2);
117 }
118 ImGui::SameLine();
119 };
120
121 provider_button(ICON_MD_SETTINGS " Mock", "mock", theme.provider_mock);
122 provider_button(ICON_MD_CLOUD " Ollama", "ollama", theme.provider_ollama);
123 provider_button(ICON_MD_SMART_TOY " Gemini", "gemini", theme.provider_gemini);
124 provider_button(ICON_MD_AUTO_AWESOME " OpenAI", "openai", theme.provider_openai);
125 ImGui::NewLine();
126 ImGui::NewLine();
127
128 // Provider-specific configuration
129 ImGui::Text("Ollama Host:");
130 ImGui::SameLine();
131 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
132 if (ImGui::InputTextWithHint("##ollama_host", "http://localhost:11434",
133 config.ollama_host_buffer,
134 IM_ARRAYSIZE(config.ollama_host_buffer))) {
135 config.ollama_host = config.ollama_host_buffer;
136 }
137
138 ImGui::Text("Gemini Key:");
139 ImGui::SameLine();
140 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 60.0f);
141 if (ImGui::InputTextWithHint("##gemini_key", "API key...",
142 config.gemini_key_buffer,
143 IM_ARRAYSIZE(config.gemini_key_buffer),
144 ImGuiInputTextFlags_Password)) {
145 config.gemini_api_key = config.gemini_key_buffer;
146 }
147 ImGui::SameLine();
148 if (ImGui::SmallButton(ICON_MD_SYNC " Env##gemini")) {
149 const char* env_key = std::getenv("GEMINI_API_KEY");
150 if (env_key) {
151 std::snprintf(config.gemini_key_buffer, sizeof(config.gemini_key_buffer),
152 "%s", env_key);
153 config.gemini_api_key = env_key;
154 if (toast_manager) {
155 toast_manager->Show("Loaded GEMINI_API_KEY from environment",
156 ToastType::kInfo, 2.0f);
157 }
158 } else if (toast_manager) {
159 toast_manager->Show("GEMINI_API_KEY not set", ToastType::kWarning, 2.0f);
160 }
161 }
162
163 ImGui::Text("OpenAI Key:");
164 ImGui::SameLine();
165 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 60.0f);
166 if (ImGui::InputTextWithHint("##openai_key", "API key...",
167 config.openai_key_buffer,
168 IM_ARRAYSIZE(config.openai_key_buffer),
169 ImGuiInputTextFlags_Password)) {
170 config.openai_api_key = config.openai_key_buffer;
171 }
172 ImGui::SameLine();
173 if (ImGui::SmallButton(ICON_MD_SYNC " Env##openai")) {
174 const char* env_key = std::getenv("OPENAI_API_KEY");
175 if (env_key) {
176 std::snprintf(config.openai_key_buffer, sizeof(config.openai_key_buffer),
177 "%s", env_key);
178 config.openai_api_key = env_key;
179 if (toast_manager) {
180 toast_manager->Show("Loaded OPENAI_API_KEY from environment",
181 ToastType::kInfo, 2.0f);
182 }
183 } else if (toast_manager) {
184 toast_manager->Show("OPENAI_API_KEY not set", ToastType::kWarning, 2.0f);
185 }
186 }
187
188 ImGui::Spacing();
189
190 // Unified Model Selection
191 if (ImGui::InputTextWithHint("##ai_model", "Model name...",
192 config.model_buffer,
193 IM_ARRAYSIZE(config.model_buffer))) {
194 config.ai_model = config.model_buffer;
195 }
196
197 // Provider filter checkbox for unified model list
198 static bool filter_by_provider = false;
199 ImGui::Checkbox("Filter by selected provider", &filter_by_provider);
200 ImGui::SameLine();
202 ImGui::SameLine();
203
204 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 60.0f);
205 ImGui::InputTextWithHint("##model_search", "Search all models...",
206 model_cache.search_buffer,
207 IM_ARRAYSIZE(model_cache.search_buffer));
208 ImGui::SameLine();
209 if (ImGui::Button(model_cache.loading ? ICON_MD_SYNC : ICON_MD_REFRESH)) {
210 if (callbacks.refresh_models) {
211 callbacks.refresh_models(true);
212 }
213 }
214
215 // Use theme color for model list background
216 ImGui::PushStyleColor(ImGuiCol_ChildBg, theme.panel_bg_darker);
217 ImGui::BeginChild("UnifiedModelList", ImVec2(0, 140), true);
218 std::string filter = absl::AsciiStrToLower(model_cache.search_buffer);
219
220 if (model_cache.available_models.empty() && model_cache.model_names.empty()) {
221 ImGui::TextDisabled("No cached models. Refresh to discover.");
222 } else {
223 auto get_provider_color = [&theme](const std::string& provider) -> ImVec4 {
224 if (provider == "ollama") return theme.provider_ollama;
225 if (provider == "gemini") return theme.provider_gemini;
226 if (provider == "openai") return theme.provider_openai;
227 return theme.provider_mock;
228 };
229
230 if (!model_cache.available_models.empty()) {
231 int model_index = 0;
232 for (const auto& info : model_cache.available_models) {
233 std::string lower_name = absl::AsciiStrToLower(info.name);
234 std::string lower_provider = absl::AsciiStrToLower(info.provider);
235
236 if (filter_by_provider && info.provider != config.ai_provider) {
237 continue;
238 }
239
240 if (!filter.empty()) {
241 bool match = lower_name.find(filter) != std::string::npos ||
242 lower_provider.find(filter) != std::string::npos;
243 if (!match && !info.parameter_size.empty()) {
244 match = absl::AsciiStrToLower(info.parameter_size).find(filter) !=
245 std::string::npos;
246 }
247 if (!match && !info.family.empty()) {
248 match = absl::AsciiStrToLower(info.family).find(filter) !=
249 std::string::npos;
250 }
251 if (!match) continue;
252 }
253
254 ImGui::PushID(model_index++);
255
256 bool is_selected = config.ai_model == info.name;
257
258 ImVec4 provider_color = get_provider_color(info.provider);
259 ImGui::PushStyleColor(ImGuiCol_Button, provider_color);
260 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 8.0f);
261 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 2));
262 ImGui::SmallButton(info.provider.c_str());
263 ImGui::PopStyleVar(2);
264 ImGui::PopStyleColor();
265 ImGui::SameLine();
266
267 if (ImGui::Selectable(info.name.c_str(), is_selected,
268 ImGuiSelectableFlags_None,
269 ImVec2(ImGui::GetContentRegionAvail().x - 60, 0))) {
270 config.ai_model = info.name;
271 config.ai_provider = info.provider;
272 std::snprintf(config.model_buffer, sizeof(config.model_buffer), "%s",
273 info.name.c_str());
274 std::snprintf(config.provider_buffer, sizeof(config.provider_buffer),
275 "%s", info.provider.c_str());
276 }
277
278 ImGui::SameLine();
279 bool is_favorite =
280 std::find(config.favorite_models.begin(),
281 config.favorite_models.end(),
282 info.name) != config.favorite_models.end();
283 ImGui::PushStyleColor(ImGuiCol_Text,
284 is_favorite ? theme.status_warning
285 : theme.text_secondary_color);
286 if (ImGui::SmallButton(is_favorite ? ICON_MD_STAR
288 if (is_favorite) {
289 config.favorite_models.erase(
290 std::remove(config.favorite_models.begin(),
291 config.favorite_models.end(), info.name),
292 config.favorite_models.end());
293 config.model_chain.erase(
294 std::remove(config.model_chain.begin(),
295 config.model_chain.end(), info.name),
296 config.model_chain.end());
297 } else {
298 config.favorite_models.push_back(info.name);
299 }
300 }
301 ImGui::PopStyleColor();
302 if (ImGui::IsItemHovered()) {
303 ImGui::SetTooltip(is_favorite ? "Remove from favorites"
304 : "Favorite model");
305 }
306
307 ImGui::SameLine();
308 if (ImGui::SmallButton(ICON_MD_NOTE_ADD)) {
309 ModelPreset preset;
310 preset.name = info.name;
311 preset.model = info.name;
312 preset.provider = info.provider;
313 preset.host =
314 (info.provider == "ollama") ? config.ollama_host : "";
315 preset.tags = {info.provider};
316 preset.last_used = absl::Now();
317 config.model_presets.push_back(std::move(preset));
318 if (toast_manager) {
319 toast_manager->Show("Preset captured", ToastType::kSuccess, 2.0f);
320 }
321 }
322 if (ImGui::IsItemHovered()) {
323 ImGui::SetTooltip("Capture preset from this model");
324 }
325
326 std::string size_label = info.parameter_size.empty()
327 ? FormatByteSize(info.size_bytes)
328 : info.parameter_size;
329 ImGui::TextColored(theme.text_secondary_color, " %s",
330 size_label.c_str());
331 if (!info.quantization.empty()) {
332 ImGui::SameLine();
333 ImGui::TextColored(theme.text_info, " %s", info.quantization.c_str());
334 }
335 if (!info.family.empty()) {
336 ImGui::SameLine();
337 ImGui::TextColored(theme.text_secondary_gray, " Family: %s",
338 info.family.c_str());
339 }
340 if (info.is_local) {
341 ImGui::SameLine();
342 ImGui::TextColored(theme.status_success, " " ICON_MD_COMPUTER);
343 if (ImGui::IsItemHovered()) {
344 ImGui::SetTooltip("Running locally");
345 }
346 }
347 ImGui::Separator();
348 ImGui::PopID();
349 }
350 } else {
351 // Fallback to just names
352 int model_index = 0;
353 for (const auto& model_name : model_cache.model_names) {
354 std::string lower = absl::AsciiStrToLower(model_name);
355 if (!filter.empty() && lower.find(filter) == std::string::npos) {
356 continue;
357 }
358
359 ImGui::PushID(model_index++);
360
361 bool is_selected = config.ai_model == model_name;
362 if (ImGui::Selectable(model_name.c_str(), is_selected)) {
363 config.ai_model = model_name;
364 std::snprintf(config.model_buffer, sizeof(config.model_buffer), "%s",
365 model_name.c_str());
366 }
367
368 ImGui::SameLine();
369 bool is_favorite =
370 std::find(config.favorite_models.begin(),
371 config.favorite_models.end(),
372 model_name) != config.favorite_models.end();
373 ImGui::PushStyleColor(ImGuiCol_Text,
374 is_favorite ? theme.status_warning
375 : theme.text_secondary_color);
376 if (ImGui::SmallButton(is_favorite ? ICON_MD_STAR
378 if (is_favorite) {
379 config.favorite_models.erase(
380 std::remove(config.favorite_models.begin(),
381 config.favorite_models.end(), model_name),
382 config.favorite_models.end());
383 } else {
384 config.favorite_models.push_back(model_name);
385 }
386 }
387 ImGui::PopStyleColor();
388 ImGui::Separator();
389 ImGui::PopID();
390 }
391 }
392 }
393 ImGui::EndChild();
394 ImGui::PopStyleColor();
395
396 if (model_cache.last_refresh != absl::InfinitePast()) {
397 double seconds = absl::ToDoubleSeconds(absl::Now() - model_cache.last_refresh);
398 ImGui::TextDisabled("Last refresh %.0fs ago", seconds);
399 } else {
400 ImGui::TextDisabled("Models not refreshed yet");
401 }
402
403 if (config.ai_provider == "ollama") {
405 }
406
407 if (!config.favorite_models.empty()) {
408 ImGui::Separator();
409 ImGui::TextColored(theme.status_warning, ICON_MD_STAR " Favorites");
410 for (size_t i = 0; i < config.favorite_models.size(); ++i) {
411 auto& favorite = config.favorite_models[i];
412 ImGui::PushID(static_cast<int>(i));
413 bool active = config.ai_model == favorite;
414
415 std::string provider_name;
416 for (const auto& info : model_cache.available_models) {
417 if (info.name == favorite) {
418 provider_name = info.provider;
419 break;
420 }
421 }
422
423 if (!provider_name.empty()) {
424 ImVec4 badge_color = theme.provider_mock;
425 if (provider_name == "ollama") badge_color = theme.provider_ollama;
426 else if (provider_name == "gemini") badge_color = theme.provider_gemini;
427 else if (provider_name == "openai") badge_color = theme.provider_openai;
428 ImGui::PushStyleColor(ImGuiCol_Button, badge_color);
429 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 6.0f);
430 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(3, 1));
431 ImGui::SmallButton(provider_name.c_str());
432 ImGui::PopStyleVar(2);
433 ImGui::PopStyleColor();
434 ImGui::SameLine();
435 }
436
437 if (ImGui::Selectable(favorite.c_str(), active)) {
438 config.ai_model = favorite;
439 std::snprintf(config.model_buffer, sizeof(config.model_buffer), "%s",
440 favorite.c_str());
441 if (!provider_name.empty()) {
442 config.ai_provider = provider_name;
443 std::snprintf(config.provider_buffer, sizeof(config.provider_buffer),
444 "%s", provider_name.c_str());
445 }
446 }
447 ImGui::SameLine();
448 ImGui::PushStyleColor(ImGuiCol_Text, theme.status_error);
449 if (ImGui::SmallButton(ICON_MD_CLOSE)) {
450 config.model_chain.erase(
451 std::remove(config.model_chain.begin(),
452 config.model_chain.end(), favorite),
453 config.model_chain.end());
454 config.favorite_models.erase(config.favorite_models.begin() + i);
455 ImGui::PopStyleColor();
456 ImGui::PopID();
457 break;
458 }
459 ImGui::PopStyleColor();
460 ImGui::PopID();
461 }
462 }
463}
464
466 const Callbacks& callbacks,
467 ToastManager* toast_manager) {
468 const auto& theme = AgentUI::GetTheme();
469 auto& config = context->agent_config();
470 auto& model_cache = context->model_cache();
471
472 ImGui::TextDisabled("Model Deck");
473 if (config.model_presets.empty()) {
474 ImGui::TextWrapped(
475 "Capture a preset to quickly swap between hosts/models with consistent "
476 "tool stacks.");
477 }
478 ImGui::InputTextWithHint("##new_preset_name", "Preset name...",
479 model_cache.new_preset_name,
480 IM_ARRAYSIZE(model_cache.new_preset_name));
481 ImGui::SameLine();
482 if (ImGui::SmallButton(ICON_MD_NOTE_ADD " Capture Current")) {
483 ModelPreset preset;
484 preset.name = model_cache.new_preset_name[0]
485 ? std::string(model_cache.new_preset_name)
486 : config.ai_model;
487 preset.model = config.ai_model;
488 preset.host = config.ollama_host;
489 preset.tags = {config.ai_provider};
490 preset.last_used = absl::Now();
491 config.model_presets.push_back(std::move(preset));
492 model_cache.new_preset_name[0] = '\0';
493 if (toast_manager) {
494 toast_manager->Show("Captured chat preset", ToastType::kSuccess, 2.0f);
495 }
496 }
497
498 ImGui::PushStyleColor(ImGuiCol_ChildBg, theme.panel_bg_darker);
499 ImGui::BeginChild("PresetList", ImVec2(0, 110), true);
500 if (config.model_presets.empty()) {
501 ImGui::TextDisabled("No presets yet");
502 } else {
503 for (int i = 0; i < static_cast<int>(config.model_presets.size()); ++i) {
504 auto& preset = config.model_presets[i];
505 ImGui::PushID(i);
506 bool selected = model_cache.active_preset_index == i;
507 if (ImGui::Selectable(preset.name.c_str(), selected)) {
508 model_cache.active_preset_index = i;
509 if (callbacks.apply_preset) {
510 callbacks.apply_preset(preset);
511 }
512 }
513 ImGui::SameLine();
514 if (ImGui::SmallButton(ICON_MD_PLAY_ARROW "##apply")) {
515 model_cache.active_preset_index = i;
516 if (callbacks.apply_preset) {
517 callbacks.apply_preset(preset);
518 }
519 }
520 ImGui::SameLine();
521 if (ImGui::SmallButton(preset.pinned ? ICON_MD_STAR
523 preset.pinned = !preset.pinned;
524 }
525 ImGui::SameLine();
526 if (ImGui::SmallButton(ICON_MD_DELETE)) {
527 config.model_presets.erase(config.model_presets.begin() + i);
528 if (model_cache.active_preset_index == i) {
529 model_cache.active_preset_index = -1;
530 }
531 ImGui::PopID();
532 break;
533 }
534 if (!preset.host.empty()) {
535 ImGui::TextDisabled("%s", preset.host.c_str());
536 }
537 if (!preset.tags.empty()) {
538 ImGui::TextDisabled("Tags: %s",
539 absl::StrJoin(preset.tags, ", ").c_str());
540 }
541 if (preset.last_used != absl::InfinitePast()) {
542 ImGui::TextDisabled("Last used %s",
543 FormatRelativeTime(preset.last_used).c_str());
544 }
545 ImGui::Separator();
546 ImGui::PopID();
547 }
548 }
549 ImGui::EndChild();
550 ImGui::PopStyleColor();
551}
552
554 ImGui::SliderFloat("Temperature", &config.temperature, 0.0f, 1.5f);
555 ImGui::SliderFloat("Top P", &config.top_p, 0.0f, 1.0f);
556 ImGui::SliderInt("Max Output Tokens", &config.max_output_tokens, 256, 8192);
557 ImGui::SliderInt("Max Tool Iterations", &config.max_tool_iterations, 1, 10);
558 ImGui::SliderInt("Max Retry Attempts", &config.max_retry_attempts, 0, 5);
559 ImGui::Checkbox("Stream responses", &config.stream_responses);
560 ImGui::SameLine();
561 ImGui::Checkbox("Show reasoning", &config.show_reasoning);
562 ImGui::SameLine();
563 ImGui::Checkbox("Verbose logs", &config.verbose);
564}
565
567 const Callbacks& callbacks) {
568 struct ToolToggleEntry {
569 const char* label;
570 bool* flag;
571 const char* hint;
572 } entries[] = {
573 {"Resources", &config.tool_config.resources, "resource-list/search"},
574 {"Dungeon", &config.tool_config.dungeon, "Room + sprite inspection"},
575 {"Overworld", &config.tool_config.overworld, "Map + entrance analysis"},
576 {"Dialogue", &config.tool_config.dialogue, "Dialogue list/search"},
577 {"Messages", &config.tool_config.messages, "Message table + ROM text"},
578 {"GUI Automation", &config.tool_config.gui, "GUI automation tools"},
579 {"Music", &config.tool_config.music, "Music info & tracks"},
580 {"Sprite", &config.tool_config.sprite, "Sprite palette/properties"},
581 {"Emulator", &config.tool_config.emulator, "Emulator controls"}};
582
583 int columns = 2;
584 ImGui::Columns(columns, nullptr, false);
585 for (size_t i = 0; i < std::size(entries); ++i) {
586 if (ImGui::Checkbox(entries[i].label, entries[i].flag)) {
587 if (callbacks.apply_tool_preferences) {
588 callbacks.apply_tool_preferences();
589 }
590 }
591 if (ImGui::IsItemHovered() && entries[i].hint) {
592 ImGui::SetTooltip("%s", entries[i].hint);
593 }
594 ImGui::NextColumn();
595 }
596 ImGui::Columns(1);
597}
598
600 ImGui::Spacing();
601 ImGui::TextDisabled("Chain Mode (Experimental)");
602
603 bool round_robin = config.chain_mode == ChainMode::kRoundRobin;
604 if (ImGui::Checkbox("Round Robin", &round_robin)) {
606 }
607 if (ImGui::IsItemHovered()) {
608 ImGui::SetTooltip("Rotate through favorite models for each response");
609 }
610
611 ImGui::SameLine();
612 bool consensus = config.chain_mode == ChainMode::kConsensus;
613 if (ImGui::Checkbox("Consensus", &consensus)) {
615 }
616 if (ImGui::IsItemHovered()) {
617 ImGui::SetTooltip("Ask multiple models and synthesize a response");
618 }
619}
620
621} // namespace editor
622} // namespace yaze
void RenderChainModeControls(AgentConfigState &config)
void Draw(AgentUIContext *context, const Callbacks &callbacks, ToastManager *toast_manager)
void RenderParameterControls(AgentConfigState &config)
void RenderToolingControls(AgentConfigState &config, const Callbacks &callbacks)
void RenderModelConfigControls(AgentUIContext *context, const Callbacks &callbacks, ToastManager *toast_manager)
void RenderModelDeck(AgentUIContext *context, const Callbacks &callbacks, ToastManager *toast_manager)
Unified context for agent UI components.
AgentConfigState & agent_config()
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
#define ICON_MD_SETTINGS
Definition icons.h:1699
#define ICON_MD_NOTE_ADD
Definition icons.h:1330
#define ICON_MD_CLOUD_SYNC
Definition icons.h:429
#define ICON_MD_STAR
Definition icons.h:1848
#define ICON_MD_PLAY_ARROW
Definition icons.h:1479
#define ICON_MD_CONSTRUCTION
Definition icons.h:458
#define ICON_MD_TUNE
Definition icons.h:2022
#define ICON_MD_REFRESH
Definition icons.h:1572
#define ICON_MD_AUTO_AWESOME
Definition icons.h:214
#define ICON_MD_DELETE
Definition icons.h:530
#define ICON_MD_STAR_BORDER
Definition icons.h:1849
#define ICON_MD_SYNC
Definition icons.h:1919
#define ICON_MD_CLOUD
Definition icons.h:423
#define ICON_MD_COMPUTER
Definition icons.h:452
#define ICON_MD_CLOSE
Definition icons.h:418
#define ICON_MD_SMART_TOY
Definition icons.h:1781
void HorizontalSpacing(float amount)
const AgentUITheme & GetTheme()
void RenderSectionHeader(const char *icon, const char *label, const ImVec4 &color)
Agent configuration state.
std::function< void(const ModelPreset &) apply_preset)
std::function< void(const AgentConfigState &) update_config)
Model preset for quick switching.
std::vector< std::string > tags