mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-04 08:42:10 +00:00
Merge branch 'main' into feature/bambu_printer_housekeeping
# Conflicts: # tests/slic3rutils/CMakeLists.txt
This commit is contained in:
@@ -48,6 +48,8 @@ enum class FilamentSyncMode {
|
||||
*
|
||||
* Implementations:
|
||||
* - OrcaPrinterAgent: Stub implementation (printer ops not yet supported)
|
||||
* - PrinterAgentPluginCapability: Python printer-agent plugin capability that
|
||||
* implements IPrinterAgent directly and is handed out as the live agent
|
||||
* - BBLPrinterAgent: Wrapper around Bambu Lab's proprietary DLL
|
||||
*
|
||||
* Token Access:
|
||||
|
||||
@@ -115,15 +115,11 @@ void NetworkAgent::add_cloud_agent(const std::string& provider, std::shared_ptr<
|
||||
|
||||
void NetworkAgent::set_printer_agent(std::shared_ptr<IPrinterAgent> printer_agent)
|
||||
{
|
||||
if (!printer_agent) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disconnect all callbacks from the old agent
|
||||
auto old_printer_agent = m_printer_agent;
|
||||
|
||||
m_printer_agent = std::move(printer_agent);
|
||||
m_printer_agent_id = m_printer_agent->get_agent_info().id;
|
||||
m_printer_agent_id = m_printer_agent ? m_printer_agent->get_agent_info().id : "";
|
||||
|
||||
// Disconnect the old agent's connections/threads.
|
||||
if (old_printer_agent && old_printer_agent != m_printer_agent) {
|
||||
@@ -131,6 +127,9 @@ void NetworkAgent::set_printer_agent(std::shared_ptr<IPrinterAgent> printer_agen
|
||||
apply_printer_callbacks(old_printer_agent, {});
|
||||
}
|
||||
|
||||
if (!m_printer_agent)
|
||||
return;
|
||||
|
||||
apply_printer_callbacks(m_printer_agent, m_printer_callbacks);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,16 +6,29 @@
|
||||
#include "QidiPrinterAgent.hpp"
|
||||
#include "SnapmakerPrinterAgent.hpp"
|
||||
#include "MoonrakerPrinterAgent.hpp"
|
||||
#include "slic3r/plugin/PluginManager.hpp"
|
||||
#include "slic3r/plugin/pluginTypes/printerAgent/PrinterAgentPluginCapability.hpp"
|
||||
#include "CrealityPrintAgent.hpp"
|
||||
#include <algorithm>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
#include <slic3r/GUI/GUI_App.hpp>
|
||||
#include <slic3r/plugin/PluginDescriptor.hpp>
|
||||
#include <slic3r/plugin/PythonPluginInterface.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace {
|
||||
|
||||
static std::mutex s_registry_mutex;
|
||||
|
||||
struct PythonPrinterAgentRegistrationToken {};
|
||||
|
||||
static std::map<std::pair<std::string, std::string>, std::shared_ptr<PythonPrinterAgentRegistrationToken>>
|
||||
s_python_printer_agent_registration_tokens;
|
||||
|
||||
std::map<std::string, PrinterAgentInfo>& get_printer_agents()
|
||||
{
|
||||
static std::map<std::string, PrinterAgentInfo> agents;
|
||||
@@ -28,22 +41,32 @@ std::map<std::string, std::shared_ptr<IPrinterAgent>>& get_printer_agent_cache()
|
||||
return cache;
|
||||
}
|
||||
|
||||
std::map<std::pair<std::string, std::string>, std::string>& get_python_printer_agent_ids()
|
||||
{
|
||||
static std::map<std::pair<std::string, std::string>, std::string> capability_to_agent_id;
|
||||
return capability_to_agent_id;
|
||||
}
|
||||
|
||||
std::string plugin_printer_agent_full_ref(const PluginDescriptor& descriptor, const std::string& capability_name)
|
||||
{
|
||||
const std::string identity = descriptor.is_cloud_plugin() ? descriptor.name : descriptor.plugin_key;
|
||||
return identity + ';' + descriptor.cloud_uuid() + ';' + capability_name;
|
||||
}
|
||||
|
||||
// Helper to register a printer agent type with the standard factory pattern.
|
||||
// AgentTypes that take a log_dir constructor arg use the default; BBLPrinterAgent
|
||||
// (no log_dir) is registered separately.
|
||||
template<typename T>
|
||||
void register_agent()
|
||||
template<typename T> void register_agent()
|
||||
{
|
||||
auto info = T::get_agent_info_static();
|
||||
NetworkAgentFactory::register_printer_agent(
|
||||
info.id, info.name,
|
||||
[](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir) -> std::shared_ptr<IPrinterAgent> {
|
||||
auto agent = std::make_shared<T>(log_dir);
|
||||
if (cloud_agent)
|
||||
agent->set_cloud_agent(cloud_agent);
|
||||
return agent;
|
||||
});
|
||||
NetworkAgentFactory::register_printer_agent(info.id, info.name,
|
||||
[](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir) -> std::shared_ptr<IPrinterAgent> {
|
||||
auto agent = std::make_shared<T>(log_dir);
|
||||
if (cloud_agent)
|
||||
agent->set_cloud_agent(cloud_agent);
|
||||
return agent;
|
||||
});
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
@@ -51,48 +74,62 @@ void register_agent()
|
||||
bool NetworkAgentFactory::register_printer_agent(const std::string& id, const std::string& display_name, PrinterAgentFactory factory)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
auto& agents = get_printer_agents();
|
||||
return agents.emplace(id, PrinterAgentInfo(id, display_name, std::move(factory))).second;
|
||||
}
|
||||
|
||||
bool NetworkAgentFactory::is_printer_agent_registered(const std::string& id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
auto& agents = get_printer_agents();
|
||||
return agents.find(id) != agents.end();
|
||||
}
|
||||
|
||||
const PrinterAgentInfo* NetworkAgentFactory::get_printer_agent_info(const std::string& id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
auto it = agents.find(id);
|
||||
auto& agents = get_printer_agents();
|
||||
auto it = agents.find(id);
|
||||
return (it != agents.end()) ? &it->second : nullptr;
|
||||
}
|
||||
|
||||
std::string NetworkAgentFactory::get_printer_agent_plugin_identifier(const std::string& id)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
auto it = agents.find(id);
|
||||
return (it != agents.end() && it->second.is_plugin()) ? it->second.plugin_identifier : std::string();
|
||||
}
|
||||
|
||||
std::vector<PrinterAgentInfo> NetworkAgentFactory::get_registered_printer_agents()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& agents = get_printer_agents();
|
||||
std::vector<PrinterAgentInfo> result;
|
||||
result.reserve(agents.size());
|
||||
|
||||
for (const auto& pair : agents) {
|
||||
result.push_back(pair.second);
|
||||
if (!pair.second.is_plugin())
|
||||
result.push_back(pair.second);
|
||||
}
|
||||
|
||||
for (const auto& pair : agents) {
|
||||
if (pair.second.is_plugin())
|
||||
result.push_back(pair.second);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<IPrinterAgent> NetworkAgentFactory::create_printer_agent_by_id(const std::string& id,
|
||||
std::shared_ptr<IPrinterAgent> NetworkAgentFactory::create_printer_agent_by_id(const std::string& id,
|
||||
std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& log_dir)
|
||||
const std::string& log_dir)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
|
||||
// Check cache first
|
||||
auto& cache = get_printer_agent_cache();
|
||||
auto cache_it = cache.find(id);
|
||||
auto& cache = get_printer_agent_cache();
|
||||
auto cache_it = cache.find(id);
|
||||
if (cache_it != cache.end()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Reusing cached printer agent: " << id;
|
||||
if (cloud_agent)
|
||||
@@ -102,7 +139,7 @@ std::shared_ptr<IPrinterAgent> NetworkAgentFactory::create_printer_agent_by_id(c
|
||||
|
||||
// Not cached — create via factory
|
||||
auto& agents = get_printer_agents();
|
||||
auto it = agents.find(id);
|
||||
auto it = agents.find(id);
|
||||
|
||||
if (it == agents.end()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Unknown printer agent ID: " << id;
|
||||
@@ -120,7 +157,7 @@ std::shared_ptr<IPrinterAgent> NetworkAgentFactory::create_printer_agent_by_id(c
|
||||
void NetworkAgentFactory::clear_printer_agent_cache()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto& cache = get_printer_agent_cache();
|
||||
auto& cache = get_printer_agent_cache();
|
||||
for (auto& pair : cache) {
|
||||
if (pair.second)
|
||||
pair.second->disconnect_printer();
|
||||
@@ -139,7 +176,8 @@ void NetworkAgentFactory::register_all_agents()
|
||||
// for K-series boards with CFS support.
|
||||
register_agent<MoonrakerPrinterAgent>();
|
||||
|
||||
// BBLPrinterAgent takes no constructor args, so register manually
|
||||
// Keep BBL as a built-in option. Python printer-agent plugins with the
|
||||
// same AgentInfo ID are listed separately under the plugin registry key.
|
||||
{
|
||||
auto info = BBLPrinterAgent::get_agent_info_static();
|
||||
register_printer_agent(info.id, info.name,
|
||||
@@ -189,4 +227,263 @@ std::unique_ptr<NetworkAgent> create_agent_from_config(const std::string& log_di
|
||||
return agent;
|
||||
}
|
||||
|
||||
void NetworkAgentFactory::register_python_plugin(const std::string& plugin_key)
|
||||
{
|
||||
for (const auto& capability : PluginManager::instance().get_plugin_capabilities(plugin_key, PluginCapabilityType::PrinterConnection,
|
||||
/*only_enabled=*/true))
|
||||
register_python_printer_agent(plugin_key, capability->name());
|
||||
}
|
||||
|
||||
void NetworkAgentFactory::register_python_printer_agent(const std::string& plugin_key, const std::string& capability_name)
|
||||
{
|
||||
PluginManager& plugin_manager = PluginManager::instance();
|
||||
|
||||
auto cap = plugin_manager.get_plugin_capability({PluginCapabilityType::PrinterConnection, capability_name, plugin_key},
|
||||
/*only_enabled=*/false);
|
||||
if (!cap) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer-agent capability '" << capability_name << "' not found for plugin '" << plugin_key << "'";
|
||||
return;
|
||||
}
|
||||
|
||||
PluginDescriptor descriptor;
|
||||
if (!plugin_manager.try_get_plugin_descriptor(plugin_key, descriptor)) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Could not find descriptor for plugin key: '" << plugin_key;
|
||||
return;
|
||||
}
|
||||
if (!cap->is_enabled()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer-agent capability '" << capability_name << "' is disabled for plugin '" << plugin_key << "'";
|
||||
return;
|
||||
}
|
||||
|
||||
auto plugin = std::dynamic_pointer_cast<PrinterAgentPluginCapability>(cap);
|
||||
|
||||
if (!plugin) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Loaded plugin capability '" << capability_name << "' is not a printer-agent plugin";
|
||||
return;
|
||||
}
|
||||
|
||||
auto info = plugin->get_agent_info();
|
||||
|
||||
if (info.id.empty()) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer-agent plugin '" << capability_name << "' returned an empty agent ID";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto capability_key = std::make_pair(plugin_key, capability_name);
|
||||
std::shared_ptr<PythonPrinterAgentRegistrationToken> registration_token;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
auto token_it = std::find_if(s_python_printer_agent_registration_tokens.begin(), s_python_printer_agent_registration_tokens.end(),
|
||||
[&plugin_key, &capability_name](const auto& entry) {
|
||||
return entry.first.first == plugin_key && entry.first.second == capability_name;
|
||||
});
|
||||
if (token_it == s_python_printer_agent_registration_tokens.end()) {
|
||||
registration_token = std::make_shared<PythonPrinterAgentRegistrationToken>();
|
||||
s_python_printer_agent_registration_tokens.emplace(capability_key, registration_token);
|
||||
} else {
|
||||
registration_token = token_it->second;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string plugin_full_ref = plugin_printer_agent_full_ref(descriptor, capability_name);
|
||||
|
||||
std::weak_ptr<PrinterAgentPluginCapability> weak_plugin = plugin;
|
||||
PrinterAgentFactory factory = [weak_plugin](std::shared_ptr<ICloudServiceAgent> cloud_agent,
|
||||
const std::string& /*log_dir*/) -> std::shared_ptr<IPrinterAgent> {
|
||||
// The capability implements IPrinterAgent directly, so it is handed out as the
|
||||
// live agent (no adapter); the Python plugin services the calls.
|
||||
auto plugin = weak_plugin.lock();
|
||||
if (!plugin)
|
||||
return nullptr;
|
||||
|
||||
if (cloud_agent)
|
||||
plugin->set_cloud_agent(cloud_agent);
|
||||
return plugin;
|
||||
};
|
||||
|
||||
// Python work above may allow disable/unload/reload to replace this capability.
|
||||
// Re-resolve without holding the registry mutex to avoid lock inversion and reentrancy.
|
||||
// only_enabled defaults to true here, so a capability that changed identity (reload) or was
|
||||
// merely disabled both surface the same way: current_cap no longer equals cap.
|
||||
auto current_cap = plugin_manager.get_plugin_capability({PluginCapabilityType::PrinterConnection, capability_name, plugin_key});
|
||||
if (current_cap != cap) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Printer-agent capability '" << capability_name << "' from plugin '" << plugin_key
|
||||
<< "' changed or was disabled during registration";
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<IPrinterAgent> cached_agent;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
|
||||
auto token_it = std::find_if(s_python_printer_agent_registration_tokens.begin(), s_python_printer_agent_registration_tokens.end(),
|
||||
[&plugin_key, &capability_name](const auto& entry) {
|
||||
return entry.first.first == plugin_key && entry.first.second == capability_name;
|
||||
});
|
||||
const bool cap_still_enabled = cap->is_enabled();
|
||||
if (token_it == s_python_printer_agent_registration_tokens.end() || token_it->second != registration_token ||
|
||||
!cap_still_enabled) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Printer-agent capability '" << capability_name << "' from plugin '" << plugin_key
|
||||
<< "' was disabled before registry commit";
|
||||
return;
|
||||
}
|
||||
|
||||
auto& python_agent_ids = get_python_printer_agent_ids();
|
||||
for (const auto& pair : python_agent_ids) {
|
||||
if (pair.first != capability_key && pair.second == info.id) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer-agent plugin '" << capability_name << "' uses duplicate agent ID '" << info.id
|
||||
<< "' already registered by capability '" << pair.first.second << "' from plugin '"
|
||||
<< pair.first.first << "'";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto plugin_it = python_agent_ids.find(capability_key);
|
||||
if (plugin_it != python_agent_ids.end() && plugin_it->second != info.id) {
|
||||
const std::string old_agent_id = plugin_it->second;
|
||||
get_printer_agents().erase(old_agent_id);
|
||||
|
||||
auto& cache = get_printer_agent_cache();
|
||||
auto cache_it = cache.find(old_agent_id);
|
||||
if (cache_it != cache.end()) {
|
||||
cached_agent = std::move(cache_it->second);
|
||||
cache.erase(cache_it);
|
||||
}
|
||||
}
|
||||
|
||||
auto& agents = get_printer_agents();
|
||||
auto agent_it = agents.find(info.id);
|
||||
if (agent_it != agents.end() && agent_it->second.plugin_identifier != plugin_full_ref) {
|
||||
BOOST_LOG_TRIVIAL(warning) << "Printer-agent plugin '" << capability_name << "' uses agent ID '" << info.id
|
||||
<< "' already registered by '" << agent_it->second.display_name << "'";
|
||||
return;
|
||||
}
|
||||
|
||||
agents.insert_or_assign(info.id, PrinterAgentInfo(info.id, info.name, plugin_full_ref, std::move(factory)));
|
||||
python_agent_ids[capability_key] = info.id;
|
||||
|
||||
auto& cache = get_printer_agent_cache();
|
||||
auto cache_it = cache.find(info.id);
|
||||
if (cache_it != cache.end()) {
|
||||
cached_agent = std::move(cache_it->second);
|
||||
cache.erase(cache_it);
|
||||
}
|
||||
}
|
||||
|
||||
if (cached_agent)
|
||||
cached_agent->disconnect_printer();
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Registered printer-agent plugin '" << capability_name << "' with agent ID '" << info.id
|
||||
<< "' and plugin ref '" << plugin_full_ref << "'";
|
||||
}
|
||||
|
||||
void NetworkAgentFactory::deregister_python_plugin(const std::string& plugin_key)
|
||||
{
|
||||
std::vector<std::string> capability_names;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
for (const auto& [capability_key, token] : s_python_printer_agent_registration_tokens) {
|
||||
(void) token;
|
||||
if (capability_key.first == plugin_key)
|
||||
capability_names.push_back(capability_key.second);
|
||||
}
|
||||
for (const auto& [capability_key, agent_id] : get_python_printer_agent_ids()) {
|
||||
(void) agent_id;
|
||||
if (capability_key.first == plugin_key &&
|
||||
std::find(capability_names.begin(), capability_names.end(), capability_key.second) == capability_names.end())
|
||||
capability_names.push_back(capability_key.second);
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::string& capability_name : capability_names)
|
||||
deregister_python_printer_agent(plugin_key, capability_name);
|
||||
|
||||
if (capability_names.empty())
|
||||
BOOST_LOG_TRIVIAL(debug) << "Python printer-agent plugin '" << plugin_key << "' has no registered capabilities";
|
||||
}
|
||||
|
||||
void NetworkAgentFactory::deregister_python_printer_agent(const std::string& plugin_key, const std::string& capability_name)
|
||||
{
|
||||
std::string agent_id;
|
||||
std::shared_ptr<IPrinterAgent> cached_agent;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_registry_mutex);
|
||||
|
||||
auto token_it = std::find_if(s_python_printer_agent_registration_tokens.begin(),
|
||||
s_python_printer_agent_registration_tokens.end(),
|
||||
[&plugin_key, &capability_name](const auto& entry) {
|
||||
return entry.first.first == plugin_key &&
|
||||
entry.first.second == capability_name;
|
||||
});
|
||||
if (token_it != s_python_printer_agent_registration_tokens.end())
|
||||
s_python_printer_agent_registration_tokens.erase(token_it);
|
||||
|
||||
auto& python_agent_ids = get_python_printer_agent_ids();
|
||||
auto id_it = std::find_if(python_agent_ids.begin(), python_agent_ids.end(),
|
||||
[&plugin_key, &capability_name](const auto& entry) {
|
||||
return entry.first.first == plugin_key &&
|
||||
entry.first.second == capability_name;
|
||||
});
|
||||
if (id_it == python_agent_ids.end()) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Python printer-agent capability '" << capability_name << "' from plugin '"
|
||||
<< plugin_key << "' is not registered";
|
||||
return;
|
||||
}
|
||||
|
||||
agent_id = id_it->second;
|
||||
python_agent_ids.erase(id_it);
|
||||
|
||||
auto& cache = get_printer_agent_cache();
|
||||
auto cache_it = cache.find(agent_id);
|
||||
if (cache_it != cache.end()) {
|
||||
cached_agent = std::move(cache_it->second);
|
||||
cache.erase(cache_it);
|
||||
}
|
||||
|
||||
get_printer_agents().erase(agent_id);
|
||||
}
|
||||
|
||||
if (cached_agent)
|
||||
cached_agent->disconnect_printer();
|
||||
|
||||
// The GUI may still own the active capability separately from the factory cache. Clear that
|
||||
// handle before the plugin module is torn down, otherwise NetworkAgent can retain a Python
|
||||
// object whose implementation is about to be unloaded.
|
||||
if (!agent_id.empty() && wxTheApp) {
|
||||
NetworkAgent* network_agent = GUI::wxGetApp().getAgent();
|
||||
if (network_agent) {
|
||||
const auto active_agent = network_agent->get_printer_agent();
|
||||
if (active_agent && active_agent->get_agent_info().id == agent_id)
|
||||
network_agent->set_printer_agent(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Deregistered Python printer-agent capability '" << capability_name << "' from plugin '"
|
||||
<< plugin_key << "' with agent ID '" << agent_id << "'";
|
||||
}
|
||||
|
||||
bool NetworkAgentFactory::is_current_printer_agent_plugin()
|
||||
{
|
||||
auto* preset_bundle = GUI::wxGetApp().preset_bundle;
|
||||
if (!preset_bundle)
|
||||
return false;
|
||||
|
||||
std::string agent_key = ORCA_PRINTER_AGENT_ID;
|
||||
if (preset_bundle->is_bbl_vendor())
|
||||
agent_key = BBL_PRINTER_AGENT_ID;
|
||||
|
||||
const auto& cfg = preset_bundle->printers.get_edited_preset().config;
|
||||
if (cfg.has("printer_agent")) {
|
||||
const std::string& value = cfg.option<ConfigOptionString>("printer_agent")->value;
|
||||
if (!value.empty())
|
||||
agent_key = value;
|
||||
}
|
||||
|
||||
const PrinterAgentInfo* info = get_printer_agent_info(agent_key);
|
||||
return info && info->is_plugin();
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -24,13 +24,19 @@ using PrinterAgentFactory =
|
||||
// Information about a registered printer agent
|
||||
struct PrinterAgentInfo
|
||||
{
|
||||
std::string id; // e.g., "orca", "bbl"
|
||||
std::string id; // Registry/config key, e.g. "orca" or a plugin AgentInfo::id
|
||||
std::string display_name; // e.g., "Orca Native", "Bambu Lab"
|
||||
std::string plugin_identifier; // Empty for built-ins, otherwise <plugin_key>;<uuid>;<capability_name>
|
||||
PrinterAgentFactory factory; // Function to create the agent
|
||||
|
||||
bool is_plugin() const { return !plugin_identifier.empty(); }
|
||||
PrinterAgentInfo(const std::string& id_, const std::string& display_name_, PrinterAgentFactory factory_)
|
||||
: id(id_), display_name(display_name_), factory(std::move(factory_))
|
||||
{}
|
||||
|
||||
PrinterAgentInfo(const std::string& id_, const std::string& display_name_, const std::string& plugin_identifier, PrinterAgentFactory factory_)
|
||||
: id(id_), display_name(display_name_), plugin_identifier(plugin_identifier), factory(std::move(factory_))
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -80,27 +86,32 @@ public:
|
||||
static bool register_printer_agent(const std::string& id, const std::string& display_name, PrinterAgentFactory factory);
|
||||
|
||||
/**
|
||||
* Check if an agent ID is registered
|
||||
* Check if an agent registry/config key is registered
|
||||
*/
|
||||
static bool is_printer_agent_registered(const std::string& id);
|
||||
|
||||
/**
|
||||
* Get info about a registered agent
|
||||
* Get info about a registered agent by registry/config key
|
||||
*/
|
||||
static const PrinterAgentInfo* get_printer_agent_info(const std::string& id);
|
||||
|
||||
/**
|
||||
* Return the full plugin reference for a plugin-backed printer agent ID, or empty for built-ins.
|
||||
*/
|
||||
static std::string get_printer_agent_plugin_identifier(const std::string& id);
|
||||
|
||||
/**
|
||||
* Get all registered printer agents (for UI population)
|
||||
*/
|
||||
static std::vector<PrinterAgentInfo> get_registered_printer_agents();
|
||||
|
||||
/**
|
||||
* Create a printer agent by ID (using registry)
|
||||
* Create a printer agent by registry/config key
|
||||
*
|
||||
* Returns a cached instance if one exists for the given ID, otherwise
|
||||
* Returns a cached instance if one exists for the given key, otherwise
|
||||
* creates a new agent via the registered factory and caches it.
|
||||
*
|
||||
* @param id Agent ID to create
|
||||
* @param id Agent registry/config key to create
|
||||
* @param cloud_agent Cloud agent for token access
|
||||
* @param log_dir Directory for log files
|
||||
* @return Shared pointer to IPrinterAgent, or nullptr if ID not found
|
||||
@@ -148,6 +159,15 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Plugin printer agents
|
||||
static void register_python_plugin(const std::string& plugin_key);
|
||||
static void deregister_python_plugin(const std::string& plugin_key);
|
||||
|
||||
static void register_python_printer_agent(const std::string& plugin_key, const std::string& capability_name);
|
||||
static void deregister_python_printer_agent(const std::string& plugin_key, const std::string& capability_name);
|
||||
|
||||
static bool is_current_printer_agent_plugin();
|
||||
|
||||
private:
|
||||
// Factory is not instantiable
|
||||
NetworkAgentFactory() = delete;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,14 +2,17 @@
|
||||
#define __ORCA_CLOUD_SERVICE_AGENT_HPP__
|
||||
|
||||
#include "ICloudServiceAgent.hpp"
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
class wxSecretStore;
|
||||
@@ -19,6 +22,22 @@ namespace Slic3r {
|
||||
// Forward declarations
|
||||
class AppConfig;
|
||||
struct BundleMetadata;
|
||||
struct PluginDescriptor;
|
||||
struct PluginChangelog;
|
||||
|
||||
struct PluginDownloadData
|
||||
{
|
||||
std::string plugin_id;
|
||||
std::string download_link;
|
||||
std::string requested_os;
|
||||
std::string returned_os;
|
||||
};
|
||||
|
||||
struct PluginDownloadNotFound
|
||||
{
|
||||
std::string id;
|
||||
std::string reason;
|
||||
};
|
||||
|
||||
// Outcome of a token-refresh attempt: decides whether a 401 should log the user
|
||||
// out (AuthRejected) or be treated as a recoverable condition (Transient).
|
||||
@@ -36,6 +55,15 @@ namespace auth_constants {
|
||||
constexpr const char* LOGOUT_PATH = "/auth/v1/logout";
|
||||
} // namespace auth_constants
|
||||
|
||||
// Names of the on-disk credential files inside the config dir.
|
||||
namespace secret_constants {
|
||||
// Encrypted refresh-token fallback file, written when wxSecretStore is unavailable.
|
||||
// Also seeded into PluginAuditManager's denied-filename registry (install_hook), which
|
||||
// additionally covers the ".tmp" staging file the token is written to before its atomic
|
||||
// rename, so plugins can read neither.
|
||||
constexpr const char* USER_SECRET_FILENAME = "orca_refresh_token.sec";
|
||||
} // namespace secret_constants
|
||||
|
||||
// ============================================================================
|
||||
// Sync Protocol Data Structures (per Orca Cloud Sync Protocol Specification)
|
||||
// ============================================================================
|
||||
@@ -270,6 +298,22 @@ public:
|
||||
int get_subscribed_bundles(std::vector<std::pair<std::string, std::string>>* bundles,std::vector<std::string>& notfound, std::vector<std::string>& unauthorized);
|
||||
int get_shared_bundle(const std::string& bundle_id, std::map<std::string, std::map<std::string, std::string>>* presets, BundleMetadata* bundle_metadata);
|
||||
|
||||
// ========================================================================
|
||||
// Plugins API
|
||||
// ========================================================================
|
||||
int fetch_subscribed_manifests_into_descriptors(std::vector<PluginDescriptor>& descriptors, std::vector<std::string>& not_found, std::vector<std::string>& unauthorized);
|
||||
int fetch_mine_manifests_into_descriptors(std::vector<PluginDescriptor>& descriptors);
|
||||
int get_plugin_download_url(const std::string& uuid,
|
||||
const std::string& requested_version,
|
||||
std::vector<PluginDownloadData>& data,
|
||||
std::vector<PluginDownloadNotFound>& not_found,
|
||||
std::vector<std::string>& unauthorized);
|
||||
std::string get_plugin_url(const std::string& sharing_token) const;
|
||||
int subscribe_plugin(const std::string& plugin_uuid);
|
||||
int unsubscribe_plugins(const std::vector<std::string>& plugin_uuids);
|
||||
int delete_my_plugin(const std::string& plugin_uuid);
|
||||
int fetch_plugin_changelogs(const std::vector<std::string>& uuids, std::unordered_map<std::string, std::vector<PluginChangelog>>& changelog);
|
||||
|
||||
// ========================================================================
|
||||
// Additional Public Methods - Auth
|
||||
// ========================================================================
|
||||
|
||||
Reference in New Issue
Block a user