Files
NebulaShell/oss/plugin/loader.py
qwen.ai[bot] 97ced1b5e6 Title: Implement minimal core framework with PL injection and update build config
Key features implemented:
- Updated package metadata and dependencies in PKG-INFO, setup files
- Added main.py entry point for backward compatibility with README launch method
- Enhanced CLI with config options, system info command, and proper signal handling
- Implemented minimal PluginManager loading only plugin-loader core plugin
- Refactored PluginLoader to follow minimal core design, removed sandbox/isolation complexity
- Updated auto-dependency plugin with safer PL injection mechanism and disabled pl_injection
- Removed legacy plugin files (firewall, frp_proxy, ftp_server, multi_lang_deploy, ops_toolbox, security_gateway) as functionality moved to core plugin system
- Improved gitignore with comprehensive ignore patterns

The changes implement a minimal core framework design where only the plugin-loader is directly loaded by the core, with all other plugins managed through the PL injection mechanism, significantly simplifying the architecture.
2026-04-25 10:47:26 +00:00

106 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""插件加载器 - 专门用于加载核心插件
遵循「最小化核心框架」设计哲学:
- 只负责加载可信的核心插件(来自 store/@{FutureOSS}/
- 所有插件都使用统一的加载机制
- 不再区分沙箱模式和非沙箱模式
"""
import sys
import importlib.util
from pathlib import Path
from typing import Any, Optional, Dict
from oss.config import get_config
class PluginLoader:
"""插件加载器 - 专门用于加载核心插件
遵循「最小化核心框架」设计哲学:
- 只负责加载可信的核心插件(来自 store/@{FutureOSS}/
- 所有插件都使用统一的加载机制
- 不再区分沙箱模式和非沙箱模式
"""
def __init__(self):
self.loaded: dict[str, Any] = {}
self._config = get_config()
def load_core_plugin(self, plugin_name: str, store_dir: Optional[str] = None) -> Optional[dict[str, Any]]:
"""加载核心插件(来自 store/@{FutureOSS}/
Args:
plugin_name: 插件名称(如 "plugin-loader"
store_dir: 插件仓库目录,默认使用配置中的 STORE_DIR
Returns:
插件信息字典,包含 instance、module、path、name
"""
if store_dir is None:
store_dir = str(self._config.store_dir)
plugin_dir = Path(store_dir) / "@{FutureOSS}" / plugin_name
return self._load_plugin(plugin_name, plugin_dir)
def _load_plugin(self, plugin_name: str, plugin_dir: Path) -> Optional[dict[str, Any]]:
"""加载插件(内部方法)
Args:
plugin_name: 插件名称
plugin_dir: 插件目录路径
Returns:
插件信息字典,如果加载失败则返回 None
"""
if not (plugin_dir / "main.py").exists():
print(f"[PluginLoader] 插件不存在:{plugin_dir}")
return None
# 清理插件名(去掉 } 等)
clean_name = plugin_name.rstrip("}")
module_name = f"plugin.{clean_name}"
spec = importlib.util.spec_from_file_location(module_name, str(plugin_dir / "main.py"))
module = importlib.util.module_from_spec(spec)
module.__package__ = module_name
module.__path__ = [str(plugin_dir)] # 启用相对导入子模块
sys.modules[spec.name] = module
# 执行模块(核心插件是可信的,不需要沙箱)
try:
spec.loader.exec_module(module)
except SyntaxError as e:
print(f"[PluginLoader] 插件 {clean_name} 语法错误:{e}")
import traceback
traceback.print_exc()
return None
except ImportError as e:
print(f"[PluginLoader] 插件 {clean_name} 导入错误:{e}")
import traceback
traceback.print_exc()
return None
except Exception as e:
print(f"[PluginLoader] 加载插件 {clean_name} 失败:{type(e).__name__}: {e}")
import traceback
traceback.print_exc()
return None
if not hasattr(module, "New"):
print(f"[PluginLoader] 插件 {clean_name} 缺少 New() 函数")
return None
try:
instance = module.New()
except TypeError as e:
print(f"[PluginLoader] 创建插件 {clean_name} 实例失败:参数错误 - {e}")
return None
except Exception as e:
print(f"[PluginLoader] 创建插件 {clean_name} 实例失败:{type(e).__name__}: {e}")
return None
self.loaded[clean_name] = {
"instance": instance,
"module": module,
"path": str(plugin_dir),
"name": clean_name,
}
return self.loaded[clean_name]