Files
whetstone_DSL/editor/src/AgentMarketplace.h
2026-02-09 21:26:10 -07:00

137 lines
5.5 KiB
C++

#pragma once
// Step 159: Agent marketplace UI
#include "imgui.h"
#include "AgentRegistry.h"
#include "NotificationSystem.h"
#include <string>
#include <algorithm>
struct AgentMarketplaceState {
char filterBuf[128] = {};
char registryPathBuf[260] = {};
char registryUrlBuf[260] = {};
std::string selectedAgent;
};
static bool agentMatchesFilter(const AgentDescriptor& agent,
const std::string& filter) {
if (filter.empty()) return true;
std::string name = agent.name;
std::string desc = agent.description;
std::string f = filter;
std::transform(name.begin(), name.end(), name.begin(),
[](unsigned char c) { return (char)std::tolower(c); });
std::transform(desc.begin(), desc.end(), desc.begin(),
[](unsigned char c) { return (char)std::tolower(c); });
std::transform(f.begin(), f.end(), f.begin(),
[](unsigned char c) { return (char)std::tolower(c); });
return name.find(f) != std::string::npos || desc.find(f) != std::string::npos;
}
static void renderAgentMarketplace(AgentMarketplaceState& state,
AgentRegistry& registry,
NotificationSystem& notifications,
const std::string& workspaceRoot) {
if (state.registryPathBuf[0] == '\0') {
std::string path = workspaceRoot.empty() ? "agents.json"
: (workspaceRoot + "\\agents.json");
std::snprintf(state.registryPathBuf, sizeof(state.registryPathBuf), "%s", path.c_str());
}
if (state.registryUrlBuf[0] == '\0' && !registry.getRegistryUrl().empty()) {
std::snprintf(state.registryUrlBuf, sizeof(state.registryUrlBuf), "%s",
registry.getRegistryUrl().c_str());
}
ImGui::InputText("Filter", state.filterBuf, sizeof(state.filterBuf));
ImGui::InputText("Registry URL", state.registryUrlBuf, sizeof(state.registryUrlBuf));
if (ImGui::Button("Set URL")) {
registry.setRegistryUrl(state.registryUrlBuf);
notifications.notify(NotificationLevel::Info, "[agents] Registry URL set.");
}
ImGui::SameLine();
if (ImGui::Button("Refresh")) {
notifications.notify(NotificationLevel::Info,
"[agents] STUB: refresh registry from " +
std::string(state.registryUrlBuf));
}
ImGui::InputText("Registry File", state.registryPathBuf, sizeof(state.registryPathBuf));
if (ImGui::Button("Load")) {
std::string error;
if (!registry.loadFromFile(state.registryPathBuf, error)) {
notifications.notify(NotificationLevel::Error,
"[agents] Load failed: " + error);
} else {
notifications.notify(NotificationLevel::Success,
"[agents] Loaded registry.");
}
}
ImGui::SameLine();
if (ImGui::Button("Save")) {
std::string error;
if (!registry.saveToFile(state.registryPathBuf, error)) {
notifications.notify(NotificationLevel::Error,
"[agents] Save failed: " + error);
} else {
notifications.notify(NotificationLevel::Success,
"[agents] Saved registry.");
}
}
ImGui::Separator();
ImGui::TextUnformatted("Available Agents");
std::string filter = state.filterBuf;
const auto& agents = registry.list();
if (agents.empty()) {
ImGui::TextDisabled("(no agents)");
} else {
for (const auto& agent : agents) {
if (!agentMatchesFilter(agent, filter)) continue;
std::string label = agent.name;
if (agent.installed) label += " [installed]";
bool selected = state.selectedAgent == agent.name;
if (ImGui::Selectable(label.c_str(), selected)) {
state.selectedAgent = agent.name;
}
}
}
ImGui::Separator();
if (!state.selectedAgent.empty()) {
AgentDescriptor* selected = registry.find(state.selectedAgent);
if (selected) {
ImGui::Text("Name: %s", selected->name.c_str());
ImGui::TextWrapped("%s", selected->description.c_str());
ImGui::Text("Endpoint: %s", selected->endpoint.c_str());
if (!selected->capabilities.empty()) {
ImGui::Text("Capabilities:");
for (const auto& cap : selected->capabilities) {
ImGui::BulletText("%s", cap.c_str());
}
}
if (!selected->requiredPermissions.empty()) {
ImGui::Text("Permissions:");
for (const auto& perm : selected->requiredPermissions) {
ImGui::BulletText("%s", perm.c_str());
}
}
if (!selected->installed) {
if (ImGui::Button("Install Agent")) {
selected->installed = true;
notifications.notify(NotificationLevel::Success,
"[agents] Installed " + selected->name +
" (" + selected->endpoint + ")");
}
} else {
if (ImGui::Button("Uninstall Agent")) {
selected->installed = false;
notifications.notify(NotificationLevel::Success,
"[agents] Uninstalled " + selected->name);
}
}
}
}
}