7#include "absl/strings/match.h"
8#include "absl/strings/str_format.h"
9#include "absl/time/clock.h"
24#if defined(YAZE_WITH_JSON)
25#include "nlohmann/json.hpp"
78 if (std::filesystem::exists(profiles_dir)) {
79 for (
const auto& entry :
80 std::filesystem::directory_iterator(profiles_dir)) {
81 if (entry.path().extension() ==
".json") {
82 std::ifstream file(entry.path());
84 std::string json_content((std::istreambuf_iterator<char>(file)),
85 std::istreambuf_iterator<char>());
87 if (profile_or.ok()) {
94 return absl::OkStatus();
104 return absl::OkStatus();
111 return absl::OkStatus();
145 ImGuiIO& io = ImGui::GetIO();
154 ImGui::PushStyleColor(ImGuiCol_TitleBgActive, ImVec4(
156 0.2f + 0.15f * pulse,
161 ImGui::SetNextWindowSize(ImVec2(1200, 800), ImGuiCond_FirstUseEver);
163 ImGuiWindowFlags_MenuBar);
166 if (ImGui::BeginMenuBar()) {
192 if (ImGui::MenuItem(
ICON_MD_CHAT " Open Chat Window",
"Ctrl+Shift+A")) {
196 ImGui::MenuItem(
ICON_MD_EDIT " Show Prompt Editor",
nullptr,
211 if (ImGui::BeginTabBar(
"AgentEditorTabs", ImGuiTabBarFlags_None)) {
217 ImGuiTableFlags table_flags = ImGuiTableFlags_Resizable |
218 ImGuiTableFlags_BordersInnerV |
219 ImGuiTableFlags_SizingStretchProp;
221 if (ImGui::BeginTable(
"BotStudioLayout", 3, table_flags)) {
222 ImGui::TableSetupColumn(
"Settings", ImGuiTableColumnFlags_WidthFixed,
224 ImGui::TableSetupColumn(
"Editors", ImGuiTableColumnFlags_WidthStretch);
225 ImGui::TableSetupColumn(
"Profiles", ImGuiTableColumnFlags_WidthFixed,
227 ImGui::TableNextRow();
230 ImGui::TableNextColumn();
231 ImGui::PushID(
"SettingsColumn");
243 ImGui::TableNextColumn();
244 ImGui::PushID(
"EditorsColumn");
246 if (ImGui::BeginTabBar(
"EditorTabs", ImGuiTabBarFlags_None)) {
247 if (ImGui::BeginTabItem(
ICON_MD_EDIT " System Prompt")) {
257 if (ImGui::BeginTabItem(
ICON_MD_ADD " New Prompt")) {
268 ImGui::TableNextColumn();
269 ImGui::PushID(
"ProfilesColumn");
284 if (ImGui::BeginTable(
286 ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInnerV)) {
287 ImGui::TableSetupColumn(
"History", ImGuiTableColumnFlags_WidthStretch,
289 ImGui::TableSetupColumn(
"Metrics", ImGuiTableColumnFlags_WidthStretch,
291 ImGui::TableNextRow();
294 ImGui::TableSetColumnIndex(0);
298 ImGui::TableSetColumnIndex(1);
313 ImGui::PopStyleColor();
320 ImGuiTreeNodeFlags_DefaultOpen)) {
321 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
326 ImVec2 button_size(ImGui::GetContentRegionAvail().x / 3 - 8, 60);
333 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.6f, 0.6f, 0.6f, 0.8f));
338 ImGui::PopStyleColor();
342 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.8f, 0.4f, 0.8f));
347 ImGui::PopStyleColor();
351 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.196f, 0.6f, 0.8f, 0.8f));
356 ImGui::PopStyleColor();
363 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.4f, 1.0f),
365 ImGui::Text(
"Model:");
366 ImGui::SetNextItemWidth(-1);
367 static char model_buf[128] =
"qwen2.5-coder:7b";
370 sizeof(model_buf) - 1);
372 if (ImGui::InputTextWithHint(
"##ollama_model",
373 "e.g., qwen2.5-coder:7b, llama3.2",
374 model_buf,
sizeof(model_buf))) {
378 ImGui::Text(
"Host URL:");
379 ImGui::SetNextItemWidth(-1);
380 static char host_buf[256] =
"http://localhost:11434";
382 sizeof(host_buf) - 1);
383 if (ImGui::InputText(
"##ollama_host", host_buf,
sizeof(host_buf))) {
387 ImGui::TextColored(ImVec4(0.196f, 0.6f, 0.8f, 1.0f),
392 const char* gemini_key = std::getenv(
"GEMINI_API_KEY");
409 ImGui::Text(
"Model:");
410 ImGui::SetNextItemWidth(-1);
411 static char model_buf[128] =
"gemini-1.5-flash";
414 sizeof(model_buf) - 1);
416 if (ImGui::InputTextWithHint(
"##gemini_model",
"e.g., gemini-1.5-flash",
417 model_buf,
sizeof(model_buf))) {
421 ImGui::Text(
"API Key:");
422 ImGui::SetNextItemWidth(-1);
423 static char key_buf[256] =
"";
426 sizeof(key_buf) - 1);
428 if (ImGui::InputText(
"##gemini_key", key_buf,
sizeof(key_buf),
429 ImGuiInputTextFlags_Password)) {
433 ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f),
437 ImGui::TextDisabled(
ICON_MD_INFO " Mock mode - no configuration needed");
443 ImGuiTreeNodeFlags_DefaultOpen)) {
455 if (ImGui::CollapsingHeader(
ICON_MD_INFO " Profile Info")) {
456 ImGui::Text(
"Name:");
457 static char name_buf[128];
459 if (ImGui::InputText(
"##profile_name", name_buf,
sizeof(name_buf))) {
463 ImGui::Text(
"Description:");
464 static char desc_buf[256];
466 sizeof(desc_buf) - 1);
467 if (ImGui::InputTextMultiline(
"##profile_desc", desc_buf,
sizeof(desc_buf),
472 ImGui::Text(
"Tags (comma-separated):");
473 static char tags_buf[256];
475 std::string tags_str;
481 strncpy(tags_buf, tags_str.c_str(),
sizeof(tags_buf) - 1);
483 if (ImGui::InputText(
"##profile_tags", tags_buf,
sizeof(tags_buf))) {
486 std::string tags_str(tags_buf);
488 while ((pos = tags_str.find(
',')) != std::string::npos) {
489 std::string tag = tags_str.substr(0, pos);
491 tag.erase(0, tag.find_first_not_of(
" \t"));
492 tag.erase(tag.find_last_not_of(
" \t") + 1);
496 tags_str.erase(0, pos + 1);
498 if (!tags_str.empty()) {
499 tags_str.erase(0, tags_str.find_first_not_of(
" \t"));
500 tags_str.erase(tags_str.find_last_not_of(
" \t") + 1);
501 if (!tags_str.empty()) {
510 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.133f, 0.545f, 0.133f, 0.8f));
511 ImGui::PushStyleColor(ImGuiCol_ButtonHovered,
512 ImVec4(0.133f, 0.545f, 0.133f, 1.0f));
513 if (ImGui::Button(
ICON_MD_CHECK " Apply & Save Configuration",
532 ImGui::PopStyleColor(2);
541 ImGui::BeginChild(
"ChatStatusCard", ImVec2(0, 100),
true);
542 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
ICON_MD_CHAT " Chat");
546 ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f),
561 ImGui::BeginChild(
"RomStatusCard", ImVec2(0, 100),
true);
562 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
ICON_MD_GAMEPAD " ROM");
566 ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f),
568 ImGui::TextDisabled(
"Title: %s",
rom_->
title().c_str());
569 ImGui::TextDisabled(
"Tools: Ready");
571 ImGui::TextColored(ImVec4(0.8f, 0.2f, 0.2f, 1.0f),
573 ImGui::TextDisabled(
"Load ROM for AI tools");
580 ImGui::BeginChild(
"QuickTipsCard", ImVec2(0, 150),
true);
581 ImGui::TextColored(ImVec4(0.196f, 0.6f, 0.8f, 1.0f),
586 ImGui::BulletText(
"Ctrl+H: Toggle chat popup");
587 ImGui::BulletText(
"Ctrl+P: View proposals");
588 ImGui::BulletText(
"Edit prompts in center");
589 ImGui::BulletText(
"Create custom bots");
590 ImGui::BulletText(
"Save/load chat sessions");
599 ImGui::TextDisabled(
"View detailed metrics in the Metrics tab");
601 ImGui::TextDisabled(
"No metrics available");
607 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
613 ImGui::Text(
"File:");
614 ImGui::SetNextItemWidth(-45);
616 if (ImGui::Selectable(
"system_prompt.txt",
621 if (ImGui::Selectable(
"system_prompt_v2.txt",
626 if (ImGui::Selectable(
"system_prompt_v3.txt",
638 if (ImGui::IsItemHovered()) {
639 ImGui::SetTooltip(
"Reload from disk");
647 if (content_result.ok()) {
660 std::cerr <<
" Error: " << content_result.status().message() <<
"\n";
663 std::string placeholder = absl::StrFormat(
664 "# System prompt file not found: %s\n"
666 "# Please ensure the file exists in:\n"
667 "# - assets/agent/%s\n"
668 "# - Or Contents/Resources/agent/%s (macOS bundle)\n\n"
669 "# You can create a custom prompt here and save it to your bot "
683 ImVec2 editor_size = ImVec2(ImGui::GetContentRegionAvail().x,
684 ImGui::GetContentRegionAvail().y - 50);
689 if (ImGui::Button(
ICON_MD_SAVE " Save Prompt to Profile", ImVec2(-1, 0))) {
700 "Edit the system prompt that guides the AI agent's behavior. Changes are "
701 "saved to the current bot profile.");
705 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
711 ImGui::BeginChild(
"CurrentProfile", ImVec2(0, 150),
true);
712 ImGui::TextColored(ImVec4(0.196f, 0.6f, 0.8f, 1.0f),
720 ImGui::TextWrapped(
"Description: %s",
729 if (ImGui::Button(
ICON_MD_ADD " Create New Profile", ImVec2(-1, 0))) {
732 new_profile.
name =
"New Profile";
745 ImGui::TextColored(ImVec4(0.196f, 0.6f, 0.8f, 1.0f),
749 ImGui::BeginChild(
"ProfilesList", ImVec2(0, 0),
true);
753 "No saved profiles. Create and save a profile to see it here.");
757 ImGui::PushID(
static_cast<int>(i));
761 ImGui::PushStyleColor(ImGuiCol_Button,
762 ImVec4(0.196f, 0.6f, 0.8f, 0.6f));
765 if (ImGui::Button(profile.name.c_str(),
766 ImVec2(ImGui::GetContentRegionAvail().x - 80, 0))) {
770 absl::StrFormat(
"Loaded profile: %s", profile.name),
776 ImGui::PopStyleColor();
780 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.2f, 0.2f, 0.6f));
785 absl::StrFormat(
"Deleted profile: %s", profile.name),
789 ImGui::PopStyleColor();
791 ImGui::TextDisabled(
" %s | %s", profile.provider.c_str(),
792 profile.description.empty()
794 : profile.description.c_str());
805 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
834 ImGui::BeginChild(
"HistoryList", ImVec2(0, 0),
true);
838 "No chat history. Start a conversation in the chat window.");
842 ImVec4 color = from_user ? ImVec4(0.6f, 0.8f, 1.0f, 1.0f)
843 : ImVec4(0.4f, 0.8f, 0.4f, 1.0f);
845 ImGui::PushStyleColor(ImGuiCol_Text, color);
846 ImGui::Text(
"%s:", from_user ?
"User" :
"Agent");
847 ImGui::PopStyleColor();
850 ImGui::TextDisabled(
"%s", absl::FormatTime(
"%H:%M:%S", msg.timestamp,
851 absl::LocalTimeZone())
854 ImGui::TextWrapped(
"%s", msg.message.c_str());
864 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
872 if (ImGui::BeginTable(
"MetricsTable", 2,
873 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
874 ImGui::TableSetupColumn(
"Metric", ImGuiTableColumnFlags_WidthFixed,
876 ImGui::TableSetupColumn(
"Value", ImGuiTableColumnFlags_WidthStretch);
877 ImGui::TableHeadersRow();
879 ImGui::TableNextRow();
880 ImGui::TableSetColumnIndex(0);
882 ImGui::TableSetColumnIndex(1);
883 ImGui::TextDisabled(
"Available in chat session");
885 ImGui::TableNextRow();
886 ImGui::TableSetColumnIndex(0);
888 ImGui::TableSetColumnIndex(1);
889 ImGui::TextDisabled(
"Available in chat session");
891 ImGui::TableNextRow();
892 ImGui::TableSetColumnIndex(0);
894 ImGui::TableSetColumnIndex(1);
895 ImGui::TextDisabled(
"Available in chat session");
897 ImGui::TableNextRow();
898 ImGui::TableSetColumnIndex(0);
900 ImGui::TableSetColumnIndex(1);
901 ImGui::TextDisabled(
"Available in chat session");
908 "Detailed session metrics are available during active chat sessions. "
909 "Open the chat window to see live statistics.");
912 "No metrics available. Initialize the chat system first.");
917 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
923 "Customize the tile reference file that AI uses for tile placement. "
924 "Organize tiles by category and provide hex IDs with descriptions.");
942 if (ImGui::Button(
ICON_MD_SAVE " Save", ImVec2(100, 0))) {
946 " Save to project directory (coming soon)",
955 if (ImGui::IsItemHovered()) {
956 ImGui::SetTooltip(
"Reload from disk");
966 std::string default_tiles =
967 "# Common Tile16 Reference\n"
968 "# Format: 0xHEX = Description\n\n"
970 "0x020 = Grass (standard)\n\n"
972 "0x02E = Tree (oak)\n"
975 "0x14C = Water (top edge)\n"
976 "0x14D = Water (middle)\n";
987 ImVec2 editor_size(ImGui::GetContentRegionAvail().x,
988 ImGui::GetContentRegionAvail().y);
994 ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
1000 "Create a custom system prompt from scratch or use a template.");
1006 ImGui::Text(
"Prompt Name:");
1007 ImGui::SetNextItemWidth(-1);
1008 ImGui::InputTextWithHint(
"##new_prompt_name",
"e.g., custom_prompt.txt",
1014 ImGui::Text(
"Start from template:");
1050 std::string blank_template =
1051 "# Custom System Prompt\n\n"
1052 "You are an AI assistant for ROM hacking.\n\n"
1054 "- Help users understand ROM data\n"
1055 "- Provide accurate information\n"
1056 "- Use tools when needed\n\n"
1057 "## Available Tools\n"
1058 "- resource-list: List resources by type\n"
1059 "- dungeon-describe-room: Get room details\n"
1060 "- overworld-find-tile: Find tile locations\n"
1061 "- ... (see function schemas for complete list)\n\n"
1063 "1. Always provide text_response after tool calls\n"
1064 "2. Be helpful and accurate\n"
1065 "3. Explain your reasoning\n";
1078 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.133f, 0.545f, 0.133f, 0.8f));
1079 if (ImGui::Button(
ICON_MD_SAVE " Save New Prompt", ImVec2(-1, 40))) {
1083 if (!absl::EndsWith(filename,
".txt")) {
1090 absl::StrFormat(
ICON_MD_SAVE " Prompt saved as %s", filename),
1101 ImGui::PopStyleColor();
1105 "Note: New prompts are saved to your project. Use 'System Prompt' tab to "
1106 "edit existing prompts.");
1111#if defined(YAZE_WITH_JSON)
1114 std::filesystem::path profile_path =
1116 std::ofstream file(profile_path);
1117 if (!file.is_open()) {
1118 return absl::InternalError(
"Failed to open profile file for writing");
1127 return absl::OkStatus();
1129 return absl::UnimplementedError(
1130 "JSON support required for profile management");
1135#if defined(YAZE_WITH_JSON)
1136 std::filesystem::path profile_path =
1138 if (!std::filesystem::exists(profile_path)) {
1139 return absl::NotFoundError(absl::StrFormat(
"Profile '%s' not found", name));
1142 std::ifstream file(profile_path);
1143 if (!file.is_open()) {
1144 return absl::InternalError(
"Failed to open profile file");
1147 std::string json_content((std::istreambuf_iterator<char>(file)),
1148 std::istreambuf_iterator<char>());
1165 return absl::OkStatus();
1167 return absl::UnimplementedError(
1168 "JSON support required for profile management");
1173 std::filesystem::path profile_path =
1175 if (!std::filesystem::exists(profile_path)) {
1176 return absl::NotFoundError(absl::StrFormat(
"Profile '%s' not found", name));
1179 std::filesystem::remove(profile_path);
1184 return absl::OkStatus();
1205 const std::filesystem::path& path) {
1206#if defined(YAZE_WITH_JSON)
1207 std::ofstream file(path);
1208 if (!file.is_open()) {
1209 return absl::InternalError(
"Failed to open export file");
1215 return absl::OkStatus();
1217 return absl::UnimplementedError(
"JSON support required");
1222#if defined(YAZE_WITH_JSON)
1223 if (!std::filesystem::exists(path)) {
1224 return absl::NotFoundError(
"Import file not found");
1227 std::ifstream file(path);
1228 if (!file.is_open()) {
1229 return absl::InternalError(
"Failed to open import file");
1232 std::string json_content((std::istreambuf_iterator<char>(file)),
1233 std::istreambuf_iterator<char>());
1240 return absl::UnimplementedError(
"JSON support required");
1246 if (!config_dir.ok()) {
1248 return std::filesystem::current_path() /
".yaze" /
"agent" /
"profiles";
1250 return *config_dir /
"agent" /
"profiles";
1256 std::filesystem::create_directories(dir, ec);
1258 return absl::InternalError(absl::StrFormat(
1259 "Failed to create profiles directory: %s", ec.message()));
1261 return absl::OkStatus();
1265#if defined(YAZE_WITH_JSON)
1266 nlohmann::json json;
1267 json[
"name"] = profile.
name;
1269 json[
"provider"] = profile.
provider;
1270 json[
"model"] = profile.
model;
1274 json[
"verbose"] = profile.
verbose;
1278 json[
"tags"] = profile.
tags;
1279 json[
"created_at"] = absl::FormatTime(absl::RFC3339_full, profile.
created_at,
1280 absl::UTCTimeZone());
1281 json[
"modified_at"] = absl::FormatTime(
1282 absl::RFC3339_full, profile.
modified_at, absl::UTCTimeZone());
1284 return json.dump(2);
1291 const std::string& json_str)
const {
1292#if defined(YAZE_WITH_JSON)
1294 nlohmann::json json = nlohmann::json::parse(json_str);
1297 profile.
name = json.value(
"name",
"Unnamed Profile");
1298 profile.
description = json.value(
"description",
"");
1299 profile.
provider = json.value(
"provider",
"mock");
1300 profile.
model = json.value(
"model",
"");
1301 profile.
ollama_host = json.value(
"ollama_host",
"http://localhost:11434");
1304 profile.
verbose = json.value(
"verbose",
false);
1309 if (json.contains(
"tags") && json[
"tags"].is_array()) {
1310 for (
const auto& tag : json[
"tags"]) {
1311 profile.
tags.push_back(tag.get<std::string>());
1315 if (json.contains(
"created_at")) {
1317 if (absl::ParseTime(absl::RFC3339_full,
1318 json[
"created_at"].get<std::string>(), &created,
1324 if (json.contains(
"modified_at")) {
1325 absl::Time modified;
1326 if (absl::ParseTime(absl::RFC3339_full,
1327 json[
"modified_at"].get<std::string>(), &modified,
1334 }
catch (
const std::exception& e) {
1335 return absl::InternalError(
1336 absl::StrFormat(
"Failed to parse profile JSON: %s", e.what()));
1339 return absl::UnimplementedError(
"JSON support required");
1410 absl::StrFormat(
"Hosting local session: %s", session_name),
1417#ifdef YAZE_WITH_GRPC
1419 if (!network_coordinator_) {
1420 return absl::FailedPreconditionError(
1421 "Network coordinator not initialized. Connect to a server first.");
1424 const char* username = std::getenv(
"USER");
1426 username = std::getenv(
"USERNAME");
1429 username =
"unknown";
1433 network_coordinator_->HostSession(session_name, username));
1447 absl::StrFormat(
"Hosting network session: %s", session_name),
1455 return absl::InvalidArgumentError(
"Unsupported collaboration mode");
1483 absl::StrFormat(
"Joined local session: %s", session_code),
1490#ifdef YAZE_WITH_GRPC
1492 if (!network_coordinator_) {
1493 return absl::FailedPreconditionError(
1494 "Network coordinator not initialized. Connect to a server first.");
1497 const char* username = std::getenv(
"USER");
1499 username = std::getenv(
"USERNAME");
1502 username =
"unknown";
1506 network_coordinator_->JoinSession(session_code, username));
1520 absl::StrFormat(
"Joined network session: %s", session_code),
1528 return absl::InvalidArgumentError(
"Unsupported collaboration mode");
1533 return absl::FailedPreconditionError(
"Not in a session");
1539#ifdef YAZE_WITH_GRPC
1541 if (network_coordinator_) {
1561 return absl::OkStatus();
1566 return absl::FailedPreconditionError(
"Not in a session");
1591 [[maybe_unused]] std::filesystem::path* output_path,
1593 return absl::UnimplementedError(
1594 "CaptureSnapshot should be called through the chat widget UI");
1598 [[maybe_unused]]
const std::filesystem::path& image_path,
1599 [[maybe_unused]]
const std::string& prompt) {
1600 return absl::UnimplementedError(
1601 "SendToGemini should be called through the chat widget UI");
1604#ifdef YAZE_WITH_GRPC
1605absl::Status AgentEditor::ConnectToServer(
const std::string& server_url) {
1607 network_coordinator_ =
1608 std::make_unique<NetworkCollaborationCoordinator>(server_url);
1612 absl::StrFormat(
"Connected to server: %s", server_url),
1616 return absl::OkStatus();
1617 }
catch (
const std::exception& e) {
1618 return absl::InternalError(
1619 absl::StrFormat(
"Failed to connect to server: %s", e.what()));
1623void AgentEditor::DisconnectFromServer() {
1627 network_coordinator_.reset();
1634bool AgentEditor::IsConnectedToServer()
const {
1635 return network_coordinator_ && network_coordinator_->IsConnected();
1649 return std::nullopt;
1666 collab_callbacks.
host_session = [
this](
const std::string& session_name)
1679 collab_callbacks.
join_session = [
this](
const std::string& session_code)
1697 [
this]() -> absl::StatusOr<
1708 chat_widget_->SetCollaborationCallbacks(collab_callbacks);
static absl::StatusOr< std::string > LoadTextFile(const std::string &relative_path)
The Rom class is used to load, save, and modify Rom data.
std::unique_ptr< AgentChatWidget > chat_widget_
std::string current_session_id_
void SetCurrentProfile(const BotProfile &profile)
void ApplyConfig(const AgentConfig &config)
void InitializeWithDependencies(ToastManager *toast_manager, ProposalDrawer *proposal_drawer, Rom *rom)
void DrawAdvancedMetricsPanel()
absl::StatusOr< SessionInfo > JoinSession(const std::string &session_code, CollaborationMode mode=CollaborationMode::kLocal)
void SetRomContext(Rom *rom)
void SetChatActive(bool active)
absl::StatusOr< BotProfile > JsonToProfile(const std::string &json) const
absl::StatusOr< SessionInfo > RefreshSession()
absl::Status ImportProfile(const std::filesystem::path &path)
bool IsChatActive() const
void SetupMultimodalCallbacks()
bool prompt_editor_initialized_
void Initialize() override
ProposalDrawer * proposal_drawer_
bool show_metrics_dashboard_
std::vector< cli::agent::ChatMessage > cached_history_
AgentConfig current_config_
absl::Status Save() override
bool common_tiles_initialized_
std::string current_session_name_
CollaborationMode GetCurrentMode() const
void DrawPromptEditorPanel()
absl::Status SendToGemini(const std::filesystem::path &image_path, const std::string &prompt)
absl::Status EnsureProfilesDirectory()
bool history_needs_refresh_
absl::Status ExportProfile(const BotProfile &profile, const std::filesystem::path &path)
void DrawNewPromptCreator()
CollaborationMode current_mode_
absl::Status SaveBotProfile(const BotProfile &profile)
std::string active_prompt_file_
absl::Status DeleteBotProfile(const std::string &name)
std::filesystem::path GetProfilesDirectory() const
ToastManager * toast_manager_
AgentConfig GetCurrentConfig() const
std::unique_ptr< TextEditor > common_tiles_editor_
absl::StatusOr< SessionInfo > HostSession(const std::string &session_name, CollaborationMode mode=CollaborationMode::kLocal)
void DrawCommonTilesEditor()
char new_prompt_name_[128]
std::string ProfileToJson(const BotProfile &profile) const
absl::Status LeaveSession()
std::unique_ptr< TextEditor > prompt_editor_
std::unique_ptr< AgentCollaborationCoordinator > local_coordinator_
absl::Status CaptureSnapshot(std::filesystem::path *output_path, const CaptureConfig &config)
absl::Status Load() override
BotProfile current_profile_
absl::Status LoadBotProfile(const std::string &name)
std::vector< BotProfile > GetAllProfiles() const
void DrawChatHistoryViewer()
std::vector< std::string > current_participants_
void DrawBotProfilesPanel()
absl::Status Update() override
void DrawConfigurationPanel()
std::vector< BotProfile > loaded_profiles_
std::optional< SessionInfo > GetCurrentSession() const
void SetupChatWidgetCallbacks()
ImGui drawer for displaying and managing agent proposals.
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_VIEW_LIST
#define ICON_MD_FILE_DOWNLOAD
#define ICON_MD_VISIBILITY
#define ICON_MD_TIPS_AND_UPDATES
#define ICON_MD_FILE_UPLOAD
#define ICON_MD_FILE_COPY
#define ICON_MD_CHECK_CIRCLE
#define ICON_MD_OPEN_IN_NEW
#define ICON_MD_ANALYTICS
#define ICON_MD_SMART_TOY
#define RETURN_IF_ERROR(expression)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
Main namespace for the application.
static const LanguageDefinition & CPlusPlus()
std::vector< std::string > participants
std::string gemini_api_key
std::vector< std::string > tags
std::string gemini_api_key
std::string system_prompt
std::vector< std::string > participants