#pragma once // Step 159: Agent registry for marketplace #include #include #include #include #include #include using json = nlohmann::json; struct AgentDescriptor { std::string name; std::string description; std::string endpoint; std::vector capabilities; std::vector requiredPermissions; bool installed = false; }; class AgentRegistry { public: const std::vector& list() const { return agents_; } AgentDescriptor* find(const std::string& name) { for (auto& a : agents_) { if (a.name == name) return &a; } return nullptr; } void upsert(const AgentDescriptor& agent) { if (auto* existing = find(agent.name)) { *existing = agent; } else { agents_.push_back(agent); } } void remove(const std::string& name) { agents_.erase(std::remove_if(agents_.begin(), agents_.end(), [&](const AgentDescriptor& a) { return a.name == name; }), agents_.end()); } void clear() { agents_.clear(); } void setRegistryUrl(const std::string& url) { registryUrl_ = url; } const std::string& getRegistryUrl() const { return registryUrl_; } bool loadFromFile(const std::string& path, std::string& error) { std::ifstream in(path); if (!in.is_open()) { error = "Could not open file: " + path; return false; } std::ostringstream ss; ss << in.rdbuf(); return loadFromJsonString(ss.str(), error); } bool saveToFile(const std::string& path, std::string& error) const { std::ofstream out(path); if (!out.is_open()) { error = "Could not write file: " + path; return false; } out << toJson().dump(2); return true; } bool loadFromJsonString(const std::string& text, std::string& error) { try { json j = json::parse(text); return loadFromJson(j, error); } catch (const std::exception& e) { error = std::string("JSON parse error: ") + e.what(); return false; } } bool loadFromJson(const json& j, std::string& error) { if (!j.is_object()) { error = "Invalid registry format"; return false; } registryUrl_ = j.value("registryUrl", registryUrl_); if (!j.contains("agents") || !j["agents"].is_array()) { error = "Missing agents list"; return false; } agents_.clear(); for (const auto& item : j["agents"]) { AgentDescriptor desc; desc.name = item.value("name", ""); desc.description = item.value("description", ""); desc.endpoint = item.value("endpoint", ""); desc.installed = item.value("installed", false); if (item.contains("capabilities")) { for (const auto& cap : item["capabilities"]) { desc.capabilities.push_back(cap.get()); } } if (item.contains("requiredPermissions")) { for (const auto& perm : item["requiredPermissions"]) { desc.requiredPermissions.push_back(perm.get()); } } if (!desc.name.empty()) agents_.push_back(std::move(desc)); } return true; } json toJson() const { json out; out["registryUrl"] = registryUrl_; json arr = json::array(); for (const auto& agent : agents_) { arr.push_back({ {"name", agent.name}, {"description", agent.description}, {"endpoint", agent.endpoint}, {"capabilities", agent.capabilities}, {"requiredPermissions", agent.requiredPermissions}, {"installed", agent.installed} }); } out["agents"] = arr; return out; } private: std::string registryUrl_; std::vector agents_; };