refactor: use explicit runtime facade getters

This commit is contained in:
jxxghp
2026-08-24 03:56:54 +08:00
parent 9f76fc9dec
commit 4dd2d7fed2
25 changed files with 154 additions and 98 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ from sqlalchemy.orm import Session
from app.adapters.external.server import MoviePilotServerHelper
from app.api.context import get_async_session, get_host_runtime, get_sync_session
from app.application.scheduling import Scheduler
from app.application.scheduling import get_scheduler
from app.application.workflow import (
WorkflowCachePort,
WorkflowDefinitionCommand,
@@ -25,7 +25,7 @@ def get_workflow_mutation_command(
runtime: HostRuntime = Depends(get_host_runtime),
) -> WorkflowMutationCommand:
"""组装请求级工作流写用例和提交后的调度副作用。"""
scheduler = Scheduler()
scheduler = get_scheduler()
workflow_manager = get_workflow_manager()
system_config = cast(WorkflowCachePort, runtime.workflow.system_config())
return WorkflowMutationCommand(
+2 -2
View File
@@ -7,7 +7,7 @@ from app.schemas.token import Token as _SchemaToken
from app.schemas.user import AuthProviderInfo as _SchemaAuthProviderInfo
from app.api.response import RAW_RESPONSE_OPENAPI_KEY, ResponseAPIRouter
from app.application.security.auth import AuthService, consume_plugin_auth_ticket
from app.application.plugin.runtime import get_plugin_manager as PluginManager
from app.application.plugin.runtime import get_plugin_manager
from app.api.dependencies.auth import get_auth_service
router = ResponseAPIRouter()
@@ -52,7 +52,7 @@ def auth_providers(service: AuthService = Depends(get_auth_service)) -> list[dic
:return: 认证提供方摘要列表
"""
providers = _system_auth_providers(service)
providers.extend(PluginManager().get_plugin_auth_providers())
providers.extend(get_plugin_manager().get_plugin_auth_providers())
return [provider for provider in providers if provider.get("enabled", True)]
+5 -5
View File
@@ -24,7 +24,7 @@ from app.api.dependencies.history import get_dashboard_query_service
from app.application.dashboard import DashboardQueryService
from app.schemas.types import StorageAction
from app.application.directory import DirectoryHelper
from app.application.scheduling import Scheduler
from app.application.scheduling import get_scheduler
from app.adapters.system.host import SystemUtils
router = ResponseAPIRouter()
@@ -180,7 +180,7 @@ async def schedule(_: Any = Depends(get_current_active_superuser)) -> Any:
查询后台服务信息
"""
# 同步 list() 内含同步进度读取,放到线程池执行避免阻塞事件循环
return await run_in_threadpool(Scheduler().list)
return await run_in_threadpool(get_scheduler().list)
@router.get(
@@ -195,7 +195,7 @@ async def schedule_progress(
查询指定后台服务的执行进度。
"""
# 异步进度后端读取,避免同步 Redis 调用阻塞事件循环
progress = await Scheduler().aget_progress(job_id)
progress = await get_scheduler().aget_progress(job_id)
if not progress:
return _SchemaResponse(success=False, message="后台服务不存在")
return _SchemaResponse(success=True, data=progress.model_dump())
@@ -211,7 +211,7 @@ async def schedule2(_: Annotated[str, Depends(verify_apitoken)]) -> Any:
查询下载器信息 API_TOKEN认证(?token=xxx
"""
# 同步 list() 内含同步进度读取,放到线程池执行避免阻塞事件循环
return await run_in_threadpool(Scheduler().list)
return await run_in_threadpool(get_scheduler().list)
@router.get(
@@ -226,7 +226,7 @@ async def schedule_progress2(
查询指定后台服务的执行进度 API_TOKEN认证(?token=xxx
"""
# 异步进度后端读取,避免同步 Redis 调用阻塞事件循环
progress = await Scheduler().aget_progress(job_id)
progress = await get_scheduler().aget_progress(job_id)
if not progress:
return _SchemaResponse(success=False, message="后台服务不存在")
return _SchemaResponse(success=True, data=progress.model_dump())
+27 -25
View File
@@ -35,7 +35,7 @@ from app.application.commands import init_commands
from app.application.scheduling import remove_plugin_job, update_plugin_job
from app.runtime.cache import async_fresh
from app.application.configuration import get_api_runtime_config_snapshot
from app.application.plugin.runtime import get_plugin_manager as PluginManager
from app.application.plugin.runtime import PluginRuntime, get_plugin_manager
from app.runtime.extensions.plugin.contracts import (
PluginDashboardError,
PluginNotFoundError,
@@ -71,7 +71,7 @@ _plugin_release_refresh_tasks: set[asyncio.Task] = set()
async def _get_market_plugin_from_repo(
plugin_manager: PluginManager,
plugin_manager: PluginRuntime,
plugin_id: str,
repo_url: str,
force: bool,
@@ -175,7 +175,7 @@ def _is_plugin_auth_remote_file(plugin_id: str, filepath: str) -> bool:
"""
path = filepath.lstrip("/")
normalized_plugin_id = plugin_id.lower()
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
for provider in plugin_manager.get_plugin_auth_providers():
remote = provider.get("remote") or {}
if str(remote.get("id") or "").lower() != normalized_plugin_id:
@@ -214,7 +214,7 @@ async def _get_plugin_history_detail(
"""
按需获取插件远端元数据,避免插件列表加载时批量访问网络。
"""
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
installed_plugin = next(
(
plugin
@@ -266,7 +266,7 @@ async def all_plugins(
查询所有插件清单,包括本地插件和在线插件,插件状态:installed, market, all
"""
# 本地插件
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
local_plugins = plugin_manager.get_local_plugins()
# 已安装插件
installed_plugins = [plugin for plugin in local_plugins if plugin.installed]
@@ -332,7 +332,7 @@ async def runtime_status(
_: ApiPrincipal = Depends(get_current_active_superuser_async),
) -> _SchemaPluginRuntimeSummary:
"""返回插件页轮询所需的轻量状态摘要。"""
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
statuses = plugin_manager.get_plugin_runtime_statuses()
pending = {
_SchemaPluginRuntimeStatus.SOURCE_MISSING,
@@ -394,7 +394,7 @@ async def plugin_releases(
"items": [],
}
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
market_plugin = await _get_market_plugin_from_repo(
plugin_manager, plugin_id, repo_url, force
)
@@ -523,7 +523,7 @@ def reload_plugin(
"""
重新加载插件
"""
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
try:
with plugin_manager.mutation(f"重载插件 {plugin_id}"):
# 重新加载插件
@@ -557,7 +557,7 @@ async def install(
"""
plugin_helper = PluginHelper()
package_manager = PluginPackageManager(plugin_helper)
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
async def save_installed_plugins(plugin_ids: List[str]) -> object:
"""保存安装用例确认后的插件列表。"""
@@ -582,7 +582,9 @@ async def install(
async def reload_runtime(target_id: str) -> object:
"""在线程池中重建源插件及其全部虚拟实例。"""
return await run_in_threadpool(PluginManager().reload_plugin_tree, target_id)
return await run_in_threadpool(
get_plugin_manager().reload_plugin_tree, target_id
)
async def refresh_registrations(target_id: str) -> object:
"""在线程池中刷新源插件及其虚拟实例的全部宿主注册。"""
@@ -594,7 +596,7 @@ async def install(
SystemConfigKey.UserInstalledPlugins
) or [],
installed_plugins_writer=save_installed_plugins,
plugin_ids_provider=lambda: PluginManager().get_plugin_ids(),
plugin_ids_provider=lambda: get_plugin_manager().get_plugin_ids(),
compatibility_checker=plugin_helper.async_get_plugin_system_version_check_message,
package_installer=install_package,
package_checkpointer=package_manager.async_checkpoint,
@@ -633,7 +635,7 @@ async def remotes(token: str) -> Any:
"""
if token != "moviepilot":
raise HTTPException(status_code=403, detail="Forbidden")
return PluginManager().get_plugin_remotes()
return get_plugin_manager().get_plugin_remotes()
@router.get(
@@ -645,7 +647,7 @@ def plugin_sidebar_nav(_: _SchemaTokenPayload = Depends(verify_token)) -> Any:
"""
聚合已启用 Vue 插件声明的侧栏入口(get_sidebar_nav),供前端主界面侧栏展示。
"""
return PluginManager().get_plugin_sidebar_nav()
return get_plugin_manager().get_plugin_sidebar_nav()
@router.get(
@@ -659,7 +661,7 @@ def plugin_form(
"""
根据插件ID获取插件配置表单或Vue组件URL
"""
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
plugin_instance = plugin_manager.running_plugins.get(plugin_id)
if not plugin_instance:
raise HTTPException(
@@ -695,7 +697,7 @@ def plugin_page(
"""
根据插件ID获取插件数据页面
"""
plugin_instance = PluginManager().running_plugins.get(plugin_id)
plugin_instance = get_plugin_manager().running_plugins.get(plugin_id)
if not plugin_instance:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
@@ -723,7 +725,7 @@ def plugin_dashboard_meta(
"""
获取所有插件仪表板元信息
"""
return PluginManager().get_plugin_dashboard_meta()
return get_plugin_manager().get_plugin_dashboard_meta()
@router.get("/dashboard/{plugin_id}/{key}", summary="获取插件仪表板配置")
@@ -737,7 +739,7 @@ def plugin_dashboard_by_key(
根据插件ID获取插件仪表板
"""
try:
return PluginManager().get_plugin_dashboard(plugin_id, key, user_agent)
return get_plugin_manager().get_plugin_dashboard(plugin_id, key, user_agent)
except PluginNotFoundError as error:
raise HTTPException(status_code=404, detail=str(error)) from error
except PluginDashboardError as error:
@@ -804,7 +806,7 @@ async def plugin_static_file(
)
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Forbidden")
source_plugin_id = PluginManager().get_plugin_source_id(plugin_id)
source_plugin_id = get_plugin_manager().get_plugin_source_id(plugin_id)
plugin_base_dir = (
AsyncPath(get_api_runtime_config_snapshot().root_path)
/ "app"
@@ -897,7 +899,7 @@ async def save_plugin_folders(
保存插件文件夹分组配置
"""
try:
with PluginManager().mutation("保存插件文件夹配置"):
with get_plugin_manager().mutation("保存插件文件夹配置"):
await get_configured_system_config().async_set(
SystemConfigKey.PluginFolders,
folders,
@@ -920,7 +922,7 @@ async def create_plugin_folder(
创建新的插件文件夹
"""
try:
with PluginManager().mutation(f"创建插件文件夹 {folder_name}"):
with get_plugin_manager().mutation(f"创建插件文件夹 {folder_name}"):
folders = (
get_configured_system_config().get(SystemConfigKey.PluginFolders) or {}
)
@@ -951,7 +953,7 @@ async def delete_plugin_folder(
删除插件文件夹
"""
try:
with PluginManager().mutation(f"删除插件文件夹 {folder_name}"):
with get_plugin_manager().mutation(f"删除插件文件夹 {folder_name}"):
folders = (
get_configured_system_config().get(SystemConfigKey.PluginFolders) or {}
)
@@ -986,7 +988,7 @@ async def update_folder_plugins(
更新指定文件夹中的插件列表
"""
try:
with PluginManager().mutation(f"更新插件文件夹 {folder_name}"):
with get_plugin_manager().mutation(f"更新插件文件夹 {folder_name}"):
folders = (
get_configured_system_config().get(SystemConfigKey.PluginFolders) or {}
)
@@ -1014,7 +1016,7 @@ def clone_plugin(
"""
创建插件分身
"""
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
try:
with plugin_manager.mutation(f"创建插件 {plugin_id} 分身"):
success, message = plugin_manager.clone_plugin(
@@ -1049,7 +1051,7 @@ async def plugin_config(
"""
根据插件ID获取插件配置信息
"""
return PluginManager().get_plugin_config(plugin_id)
return get_plugin_manager().get_plugin_config(plugin_id)
@router.put("/{plugin_id}", summary="更新插件配置", response_model=_SchemaResponse[None])
@@ -1073,7 +1075,7 @@ def uninstall_plugin(
"""
卸载插件
"""
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
try:
with plugin_manager.mutation(f"卸载插件 {plugin_id}"):
virtual_instance = plugin_manager.get_plugin_instance(plugin_id)
+6 -6
View File
@@ -22,7 +22,7 @@ from app.api.endpoints.plugin import register_plugin_api
from app.chain.site import SiteChain
from app.chain.torrents import TorrentsChain
from app.application.commands import init_commands
from app.application.plugin.runtime import get_plugin_manager as PluginManager
from app.application.plugin.runtime import get_plugin_manager
from app.adapters.web.security.access import verify_token
from app.api.principal import ApiPrincipal
from app.application.configuration import get_configured_system_config
@@ -39,7 +39,7 @@ from app.api.dependencies.site import (
)
from app.application.site.sites import SitesHelper # pylint: disable=import-error,no-name-in-module
from app.runtime.log import logger
from app.application.scheduling import Scheduler
from app.application.scheduling import get_scheduler
from app.schemas.types import SystemConfigKey, MediaType
from app.domain import site as site_rules
from app.api.context import get_background_task_registry, resolve_background_task_registry
@@ -178,7 +178,7 @@ async def cookie_cloud_sync(
运行CookieCloud同步站点信息
"""
resolve_background_task_registry(task_registry).create_sync(
Scheduler().start, job_id="cookiecloud", owner="api.site.cookiecloud_sync"
get_scheduler().start, job_id="cookiecloud", owner="api.site.cookiecloud_sync"
)
return _SchemaResponse(success=True, message="CookieCloud同步任务已启动!")
@@ -196,7 +196,7 @@ async def reset(
await get_configured_system_config().async_set(SystemConfigKey.IndexerSites, [])
await get_configured_system_config().async_set(SystemConfigKey.RssSites, [])
resolve_background_task_registry(task_registry).create_sync(
Scheduler().start,
get_scheduler().start,
job_id="cookiecloud",
owner="api.site.reset",
manual=True,
@@ -567,8 +567,8 @@ def auth_site(
status, msg = SitesHelper().check_user(auth_info.site, auth_info.params)
get_configured_system_config().set(SystemConfigKey.UserSiteAuthParams, auth_info.model_dump())
# 认证成功后,重新初始化插件
PluginManager().init_config()
Scheduler().init_plugin_jobs()
get_plugin_manager().init_config()
get_scheduler().init_plugin_jobs()
init_commands()
register_plugin_api()
return _SchemaResponse(success=status, message=msg)
+3 -3
View File
@@ -55,7 +55,7 @@ from app.api.dependencies.subscription import (
get_subscription_sync_mutation_service,
)
from app.adapters.external.server import MoviePilotServerHelper
from app.application.scheduling import Scheduler
from app.application.scheduling import get_scheduler
from app.runtime.tasks import TaskRegistry
from app.schemas.event import SubscribeModifiedEventData
from app.schemas.types import (
@@ -376,7 +376,7 @@ def refresh_subscribes(
"""
if not current_user.is_superuser:
return _SchemaResponse(success=False, message="订阅不存在")
Scheduler().start("subscribe_refresh")
get_scheduler().start("subscribe_refresh")
return _SchemaResponse(success=True)
@@ -418,7 +418,7 @@ def check_subscribes(
"""
if not current_user.is_superuser:
return _SchemaResponse(success=False, message="订阅不存在")
Scheduler().start("subscribe_tmdb")
get_scheduler().start("subscribe_tmdb")
return _SchemaResponse(success=True)
+8 -8
View File
@@ -38,7 +38,7 @@ from app.chain.system import SystemChain
from app.runtime.config import global_vars
from app.runtime.events import eventmanager
from app.domain.metainfo import MetaInfo
from app.application.module import ModuleManager
from app.application.module import get_module_manager
from app.adapters.web.security.access import verify_apitoken, verify_resource_token, verify_token
from app.api.principal import ApiPrincipal
from app.application.configuration import (
@@ -66,7 +66,7 @@ from app.application.rules import RuleHelper
from app.adapters.external.server import MoviePilotServerHelper
from app.runtime.state import SystemHelper
from app.runtime.log import logger
from app.application.scheduling import Scheduler
from app.application.scheduling import get_scheduler
from app.schemas.event import ConfigChangeEventData
from app.schemas.exception import PluginMutationRejectedError
from app.schemas.types import SystemConfigKey, EventType
@@ -1449,7 +1449,7 @@ def modulelist(_: _SchemaTokenPayload = Depends(verify_token)):
查询已加载的模块ID列表
"""
modules = []
for spec in ModuleManager().list_specs():
for spec in get_module_manager().list_specs():
module_id = spec.id
name = str(spec.metadata["name"])
modules.append(
@@ -1473,7 +1473,7 @@ def moduletest(moduleid: str, _: _SchemaTokenPayload = Depends(verify_token)):
"""
模块可用性测试接口
"""
state, errmsg = ModuleManager().test(moduleid)
state, errmsg = get_module_manager().test(moduleid)
return _SchemaResponse(success=state, message=errmsg)
@@ -1514,9 +1514,9 @@ def run_scheduler(jobid: str, _: ApiPrincipal = Depends(get_current_active_super
if not jobid:
return _SchemaResponse(success=False, message="命令不能为空!")
if jobid in {"recommend_refresh", "cookiecloud"}:
Scheduler().start(jobid, manual=True)
get_scheduler().start(jobid, manual=True)
else:
Scheduler().start(jobid)
get_scheduler().start(jobid)
return _SchemaResponse(success=True)
@@ -1531,7 +1531,7 @@ def run_scheduler2(jobid: str, _: Annotated[str, Depends(verify_apitoken)]):
return _SchemaResponse(success=False, message="命令不能为空!")
if jobid in {"recommend_refresh", "cookiecloud"}:
Scheduler().start(jobid, manual=True)
get_scheduler().start(jobid, manual=True)
else:
Scheduler().start(jobid)
get_scheduler().start(jobid)
return _SchemaResponse(success=True)
+2 -2
View File
@@ -16,7 +16,7 @@ from app.application.workflow import (
get_workflow_manager,
)
from app.chain.workflow import WorkflowChain
from app.application.plugin.runtime import get_plugin_manager as PluginManager
from app.application.plugin.runtime import get_plugin_manager
from app.api.dependencies.auth import (
get_current_active_manage_user,
get_current_active_manage_user_async,
@@ -66,7 +66,7 @@ def list_plugin_actions(
"""
获取所有动作
"""
return PluginManager().get_plugin_actions(plugin_id)
return get_plugin_manager().get_plugin_actions(plugin_id)
@router.get(
+4 -4
View File
@@ -12,10 +12,10 @@ from app.chain.subscribe import SubscribeChain
from app.chain.system import SystemChain
from app.chain.transfer import TransferChain
from app.runtime.events import Event as ManagerEvent, eventmanager, Event
from app.application.plugin.runtime import get_plugin_manager as PluginManager
from app.application.plugin.runtime import get_plugin_manager
from app.application.messaging.message import MessageHelper
from app.application.messaging.skill import SkillInteractionHandler
from app.application.scheduling import Scheduler
from app.application.scheduling import get_scheduler
from app.runtime.thread import ThreadHelper
from app.runtime.log import logger
from app.schemas.message import Message
@@ -147,9 +147,9 @@ class Command(metaclass=Singleton):
# 初始化锁
self._rlock = threading.RLock()
# 插件管理
self.pluginmanager = PluginManager()
self.pluginmanager = get_plugin_manager()
# 定时服务管理
self.scheduler = Scheduler()
self.scheduler = get_scheduler()
# 消息管理器
self.messagehelper = MessageHelper()
# 初始化命令
+3 -3
View File
@@ -14,7 +14,7 @@ from app.adapters.observability.otel import build_observation_port
from app.adapters.web.plugin.routes import FastAPIDynamicRouteRegistry
from app.adapters.web.health import install_health_routes
from app.application.plugin.routes import configure_plugin_routes
from app.application.plugin.runtime import get_plugin_manager as PluginManager
from app.application.plugin.runtime import get_plugin_manager
from app.schemas.exception import (
PersistenceUnavailableError,
)
@@ -381,8 +381,8 @@ def create_app() -> FastAPI:
# 统一经服务完成,避免 api.endpoints 反向依赖本模块。
configure_plugin_routes(FastAPIDynamicRouteRegistry(
app=_app,
plugin_ids=lambda: PluginManager().get_running_plugin_ids(),
plugin_apis=lambda plugin_id: PluginManager().get_plugin_apis(plugin_id),
plugin_ids=lambda: get_plugin_manager().get_running_plugin_ids(),
plugin_apis=lambda plugin_id: get_plugin_manager().get_plugin_apis(plugin_id),
verify_token=verify_token,
verify_apikey=verify_apikey,
prefix=f"{settings.API_V1_STR}/plugin",
+6 -6
View File
@@ -31,7 +31,7 @@ from app.runtime.events import Event, eventmanager
from app.db.oper.agenttask import AgentTaskOper
from app.application.database import get_database_governance
from app.application.outbox import dispatch_pending_outbox
from app.application.plugin.runtime import get_plugin_manager as PluginManager
from app.application.plugin.runtime import get_plugin_manager
from app.application.configuration import (
SchedulerRuntimeConfig,
get_configured_system_config,
@@ -551,7 +551,7 @@ class Scheduler(ConfigReloadMixin, metaclass=SingletonClass):
JobSpec("random_wallpager", "壁纸缓存", WallpaperHelper().get_wallpapers, "image"),
JobSpec("sitedata_refresh", "站点数据刷新", SiteChain().refresh_userdatas, "site"),
JobSpec("recommend_refresh", "推荐缓存", RecommendChain().refresh_recommend, "recommend"),
JobSpec("plugin_market_refresh", "插件市场缓存", PluginManager().async_get_online_plugins, "plugin", kwargs={"force": True}),
JobSpec("plugin_market_refresh", "插件市场缓存", get_plugin_manager().async_get_online_plugins, "plugin", kwargs={"force": True}),
JobSpec("subscribe_calendar_cache", "订阅日历缓存", SubscribeChain().cache_calendar, "subscription"),
JobSpec("full_gc", "主动内存回收", self.full_gc, "runtime"),
JobSpec("agent_heartbeat", "智能体定时任务", self.agent_heartbeat, "agent"),
@@ -1608,7 +1608,7 @@ class Scheduler(ConfigReloadMixin, metaclass=SingletonClass):
"""
初始化插件定时服务
"""
for pid in PluginManager().get_running_plugin_ids():
for pid in get_plugin_manager().get_running_plugin_ids():
self.update_plugin_job(pid)
@eventmanager.register(EventType.PluginReload)
@@ -1684,7 +1684,7 @@ class Scheduler(ConfigReloadMixin, metaclass=SingletonClass):
self._jobs.pop(job_id, None)
if not jobs_to_remove:
return
plugin_name = PluginManager().get_plugin_attr(pid, "plugin_name")
plugin_name = get_plugin_manager().get_plugin_attr(pid, "plugin_name")
# 遍历移除任务
for job_id, service in jobs_to_remove:
try:
@@ -1758,7 +1758,7 @@ class Scheduler(ConfigReloadMixin, metaclass=SingletonClass):
self.remove_plugin_job(pid)
# 获取插件服务列表
with self._lock:
plugin_manager = PluginManager()
plugin_manager = get_plugin_manager()
try:
plugin_services = plugin_manager.get_plugin_services(pid=pid)
except Exception as e:
@@ -2047,7 +2047,7 @@ class Scheduler(ConfigReloadMixin, metaclass=SingletonClass):
)
)
# 认证通过后重新初始化插件
PluginManager().init_config()
get_plugin_manager().init_config()
self.init_plugin_jobs()
else:
+2 -2
View File
@@ -1,7 +1,7 @@
from pydantic import Field
from app.workflow.actions import BaseAction
from app.application.plugin.runtime import get_plugin_manager as PluginManager
from app.application.plugin.runtime import get_plugin_manager
from app.runtime.log import logger
from app.schemas.workflow import ActionParams
from app.schemas.workflow import ActionContext
@@ -43,7 +43,7 @@ class InvokePluginAction(BaseAction):
if not params.plugin_id or not params.action_id:
return context
try:
plugin_actions = PluginManager().get_plugin_actions(params.plugin_id)
plugin_actions = get_plugin_manager().get_plugin_actions(params.plugin_id)
if not plugin_actions:
logger.error(f"插件不存在: {params.plugin_id}")
return context