feat: enhance global config handling and component resolution in plugin runtime
This commit is contained in:
@@ -1146,8 +1146,8 @@ class PluginRunnerSupervisor:
|
|||||||
Returns:
|
Returns:
|
||||||
Dict[str, str]: 传递给 Runner 进程的环境变量映射。
|
Dict[str, str]: 传递给 Runner 进程的环境变量映射。
|
||||||
"""
|
"""
|
||||||
global_config_snapshot = config_manager.get_global_config().model_dump()
|
global_config_snapshot = config_manager.get_global_config().model_dump(mode="json")
|
||||||
global_config_snapshot["model"] = config_manager.get_model_config().model_dump()
|
global_config_snapshot["model"] = config_manager.get_model_config().model_dump(mode="json")
|
||||||
return {
|
return {
|
||||||
ENV_EXTERNAL_PLUGIN_IDS: json.dumps(self._external_available_plugins, ensure_ascii=False),
|
ENV_EXTERNAL_PLUGIN_IDS: json.dumps(self._external_available_plugins, ensure_ascii=False),
|
||||||
ENV_GLOBAL_CONFIG_SNAPSHOT: json.dumps(global_config_snapshot, ensure_ascii=False),
|
ENV_GLOBAL_CONFIG_SNAPSHOT: json.dumps(global_config_snapshot, ensure_ascii=False),
|
||||||
|
|||||||
@@ -543,9 +543,9 @@ class PluginRuntimeManager(
|
|||||||
|
|
||||||
normalized_scopes = self._normalize_config_reload_scopes(changed_scopes)
|
normalized_scopes = self._normalize_config_reload_scopes(changed_scopes)
|
||||||
if "bot" in normalized_scopes:
|
if "bot" in normalized_scopes:
|
||||||
await self._broadcast_config_reload("bot", config_manager.get_global_config().model_dump())
|
await self._broadcast_config_reload("bot", config_manager.get_global_config().model_dump(mode="json"))
|
||||||
if "model" in normalized_scopes:
|
if "model" in normalized_scopes:
|
||||||
await self._broadcast_config_reload("model", config_manager.get_model_config().model_dump())
|
await self._broadcast_config_reload("model", config_manager.get_model_config().model_dump(mode="json"))
|
||||||
|
|
||||||
# ─── 事件桥接 ──────────────────────────────────────────────
|
# ─── 事件桥接 ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ class PluginMeta:
|
|||||||
self.version = manifest.version
|
self.version = manifest.version
|
||||||
self.capabilities_required = list(manifest.capabilities)
|
self.capabilities_required = list(manifest.capabilities)
|
||||||
self.dependencies: List[str] = list(manifest.plugin_dependency_ids)
|
self.dependencies: List[str] = list(manifest.plugin_dependency_ids)
|
||||||
|
self.component_handlers: Dict[str, str] = {}
|
||||||
|
|
||||||
|
|
||||||
class PluginLoader:
|
class PluginLoader:
|
||||||
@@ -421,7 +422,11 @@ class PluginLoader:
|
|||||||
|
|
||||||
# 动态导入插件模块
|
# 动态导入插件模块
|
||||||
module_name = self._build_safe_module_name(plugin_id)
|
module_name = self._build_safe_module_name(plugin_id)
|
||||||
spec = importlib.util.spec_from_file_location(module_name, str(plugin_path))
|
spec = importlib.util.spec_from_file_location(
|
||||||
|
module_name,
|
||||||
|
str(plugin_path),
|
||||||
|
submodule_search_locations=[str(plugin_dir)],
|
||||||
|
)
|
||||||
if spec is None or spec.loader is None:
|
if spec is None or spec.loader is None:
|
||||||
logger.error(f"无法创建模块 spec: {plugin_path}")
|
logger.error(f"无法创建模块 spec: {plugin_path}")
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -335,6 +335,45 @@ class PluginRunner:
|
|||||||
self._rpc_client.register_method("plugin.config_updated", self._handle_config_updated)
|
self._rpc_client.register_method("plugin.config_updated", self._handle_config_updated)
|
||||||
self._rpc_client.register_method("plugin.reload", self._handle_reload_plugin)
|
self._rpc_client.register_method("plugin.reload", self._handle_reload_plugin)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _resolve_component_handler_name(meta: PluginMeta, component_name: str) -> str:
|
||||||
|
"""解析组件名对应的真实处理函数名。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
meta: 已加载插件的元数据。
|
||||||
|
component_name: Host 侧请求中的组件声明名。
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 实际应在插件实例上查找的方法名。
|
||||||
|
"""
|
||||||
|
return str(meta.component_handlers.get(component_name, component_name) or component_name)
|
||||||
|
|
||||||
|
def _resolve_component_handler(self, meta: PluginMeta, component_name: str) -> Any:
|
||||||
|
"""根据组件声明名解析插件实例上的可调用处理函数。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
meta: 已加载插件的元数据。
|
||||||
|
component_name: Host 侧请求中的组件声明名。
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Any: 解析到的可调用对象;未找到时返回 ``None``。
|
||||||
|
"""
|
||||||
|
instance = meta.instance
|
||||||
|
handler_name = self._resolve_component_handler_name(meta, component_name)
|
||||||
|
handler_method = getattr(instance, handler_name, None)
|
||||||
|
if handler_method is not None:
|
||||||
|
return handler_method
|
||||||
|
|
||||||
|
if handler_name != component_name:
|
||||||
|
legacy_style_handler = getattr(instance, f"handle_{component_name}", None)
|
||||||
|
if legacy_style_handler is not None:
|
||||||
|
return legacy_style_handler
|
||||||
|
|
||||||
|
prefixed_handler = getattr(instance, f"handle_{component_name}", None)
|
||||||
|
if prefixed_handler is not None:
|
||||||
|
return prefixed_handler
|
||||||
|
return getattr(instance, component_name, None)
|
||||||
|
|
||||||
async def _bootstrap_plugin(self, meta: PluginMeta, capabilities_required: Optional[List[str]] = None) -> bool:
|
async def _bootstrap_plugin(self, meta: PluginMeta, capabilities_required: Optional[List[str]] = None) -> bool:
|
||||||
"""向 Host 同步插件 bootstrap 能力令牌。"""
|
"""向 Host 同步插件 bootstrap 能力令牌。"""
|
||||||
payload = BootstrapPluginPayload(
|
payload = BootstrapPluginPayload(
|
||||||
@@ -379,15 +418,27 @@ class PluginRunner:
|
|||||||
|
|
||||||
# 从插件实例获取组件声明(SDK 插件须实现 get_components 方法)
|
# 从插件实例获取组件声明(SDK 插件须实现 get_components 方法)
|
||||||
if hasattr(instance, "get_components"):
|
if hasattr(instance, "get_components"):
|
||||||
components.extend(
|
meta.component_handlers.clear()
|
||||||
ComponentDeclaration(
|
for comp_info in instance.get_components():
|
||||||
name=comp_info.get("name", ""),
|
if not isinstance(comp_info, dict):
|
||||||
component_type=comp_info.get("type", ""),
|
continue
|
||||||
plugin_id=meta.plugin_id,
|
|
||||||
metadata=comp_info.get("metadata", {}),
|
component_name = str(comp_info.get("name", "") or "").strip()
|
||||||
|
raw_metadata = comp_info.get("metadata", {})
|
||||||
|
component_metadata = raw_metadata if isinstance(raw_metadata, dict) else {}
|
||||||
|
handler_name = str(component_metadata.get("handler_name", component_name) or component_name).strip()
|
||||||
|
|
||||||
|
if component_name:
|
||||||
|
meta.component_handlers[component_name] = handler_name or component_name
|
||||||
|
|
||||||
|
components.append(
|
||||||
|
ComponentDeclaration(
|
||||||
|
name=component_name,
|
||||||
|
component_type=str(comp_info.get("type", "") or "").strip(),
|
||||||
|
plugin_id=meta.plugin_id,
|
||||||
|
metadata=component_metadata,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
for comp_info in instance.get_components()
|
|
||||||
)
|
|
||||||
if hasattr(instance, "get_config_reload_subscriptions"):
|
if hasattr(instance, "get_config_reload_subscriptions"):
|
||||||
config_reload_subscriptions = list(instance.get_config_reload_subscriptions())
|
config_reload_subscriptions = list(instance.get_config_reload_subscriptions())
|
||||||
|
|
||||||
@@ -812,19 +863,13 @@ class PluginRunner:
|
|||||||
f"插件 {plugin_id} 未加载",
|
f"插件 {plugin_id} 未加载",
|
||||||
)
|
)
|
||||||
|
|
||||||
# 调用插件实例的组件方法
|
|
||||||
instance = meta.instance
|
|
||||||
component_name = invoke.component_name
|
component_name = invoke.component_name
|
||||||
|
handler_method = self._resolve_component_handler(meta, component_name)
|
||||||
# 优先查找 handle_<name> 或直接 <name> 方法(新版 SDK 插件)
|
|
||||||
handler_method = getattr(instance, f"handle_{component_name}", None)
|
|
||||||
if handler_method is None:
|
|
||||||
handler_method = getattr(instance, component_name, None)
|
|
||||||
|
|
||||||
# 回退: 旧版 LegacyPluginAdapter 通过 invoke_component 统一桥接
|
# 回退: 旧版 LegacyPluginAdapter 通过 invoke_component 统一桥接
|
||||||
if (handler_method is None or not callable(handler_method)) and hasattr(instance, "invoke_component"):
|
if (handler_method is None or not callable(handler_method)) and hasattr(meta.instance, "invoke_component"):
|
||||||
try:
|
try:
|
||||||
result = await instance.invoke_component(component_name, **invoke.args)
|
result = await meta.instance.invoke_component(component_name, **invoke.args)
|
||||||
resp_payload = InvokeResultPayload(success=True, result=result)
|
resp_payload = InvokeResultPayload(success=True, result=result)
|
||||||
return envelope.make_response(payload=resp_payload.model_dump())
|
return envelope.make_response(payload=resp_payload.model_dump())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -871,11 +916,8 @@ class PluginRunner:
|
|||||||
f"插件 {plugin_id} 未加载",
|
f"插件 {plugin_id} 未加载",
|
||||||
)
|
)
|
||||||
|
|
||||||
instance = meta.instance
|
|
||||||
component_name = invoke.component_name
|
component_name = invoke.component_name
|
||||||
handler_method = getattr(instance, f"handle_{component_name}", None)
|
handler_method = self._resolve_component_handler(meta, component_name)
|
||||||
if handler_method is None:
|
|
||||||
handler_method = getattr(instance, component_name, None)
|
|
||||||
|
|
||||||
if handler_method is None or not callable(handler_method):
|
if handler_method is None or not callable(handler_method):
|
||||||
return envelope.make_error_response(
|
return envelope.make_error_response(
|
||||||
@@ -933,9 +975,8 @@ class PluginRunner:
|
|||||||
f"插件 {plugin_id} 未加载",
|
f"插件 {plugin_id} 未加载",
|
||||||
)
|
)
|
||||||
|
|
||||||
instance = meta.instance
|
|
||||||
component_name = invoke.component_name
|
component_name = invoke.component_name
|
||||||
handler_method = getattr(instance, f"handle_{component_name}", None) or getattr(instance, component_name, None)
|
handler_method = self._resolve_component_handler(meta, component_name)
|
||||||
if handler_method is None or not callable(handler_method):
|
if handler_method is None or not callable(handler_method):
|
||||||
return envelope.make_error_response(
|
return envelope.make_error_response(
|
||||||
ErrorCode.E_METHOD_NOT_ALLOWED.value,
|
ErrorCode.E_METHOD_NOT_ALLOWED.value,
|
||||||
@@ -985,9 +1026,8 @@ class PluginRunner:
|
|||||||
f"插件 {plugin_id} 未加载",
|
f"插件 {plugin_id} 未加载",
|
||||||
)
|
)
|
||||||
|
|
||||||
instance = meta.instance
|
|
||||||
component_name = invoke.component_name
|
component_name = invoke.component_name
|
||||||
handler_method = getattr(instance, f"handle_{component_name}", None) or getattr(instance, component_name, None)
|
handler_method = self._resolve_component_handler(meta, component_name)
|
||||||
|
|
||||||
if handler_method is None or not callable(handler_method):
|
if handler_method is None or not callable(handler_method):
|
||||||
return envelope.make_error_response(
|
return envelope.make_error_response(
|
||||||
|
|||||||
Reference in New Issue
Block a user