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