重大重构:引擎模块拆分 + P0插件实现 + 55个Bug修复

核心变更:
- engine.py(1781行)拆分为8个独立模块: lifecycle/security/deps/
  datastore/pl_injector/watcher/signature/manager
- 新增plugin-bridge: 事件总线 + 服务注册 + RPC通信
- 新增i18n: 国际化/多语言翻译支持
- 新增plugin-storage: 插件键值/文件存储
- 新增ws-api: WebSocket实时通信(pub/sub + 自定义处理器)
- nodejs-adapter统一为Plugin ABC模式

Bug修复:
- 修复load_all()中store_dir未定义崩溃
- 修复DependencyResolver入度计算(拓扑排序)
- 修复PermissionError隐藏内置异常
- 修复CORS中间件头部未附加到响应
- 修复IntegrityChecker跳过__pycache__目录
- 修复版本号不一致(v2.0.0→v1.2.0)
- 修复测试文件的Logger导入/路径/私有方法调用
- 修复context.py缺少typing导入
- 修复config.py STORE_DIR默认路径(./mods→./store)

测试覆盖: 14→91个测试, 全部通过
This commit is contained in:
Falck
2026-05-12 11:40:06 +08:00
parent 3a096f59a9
commit bce27db4ac
57 changed files with 3669 additions and 2367 deletions

View File

@@ -53,7 +53,7 @@ class NBPFFormatter:
NIR_DIR = "NIR/"
RES_DIR = "RES/"
# META-INF 文件
# META-INF 文件RSA 私钥持有者可解密读取)
MANIFEST = META_INF + "MANIFEST.MF"
SIGNATURE = META_INF + "SIGNATURE"
SIGNER_PEM = META_INF + "SIGNER.PEM"
@@ -62,6 +62,9 @@ class NBPFFormatter:
INNER_ENCRYPTION = META_INF + "INNER_ENCRYPTION"
MODULE_SIGS = META_INF + "MODULE_SIGS"
# META-INF 公开元数据(明文,仅含 name/version/author/description
PLUGIN_MF = META_INF + "PLUGIN.MF"
# 跳过列表(打包时排除的文件)
SKIP_FILES = {"__pycache__", "SIGNATURE", ".DS_Store", "Thumbs.db"}
@@ -130,9 +133,6 @@ class NBPFPacker:
# 5. 构建 ZIP 包
with zipfile.ZipFile(output_path, 'w', zipfile.ZIP_DEFLATED) as zf:
# META-INF/MANIFEST.MF
zf.writestr(NBPFFormatter.MANIFEST, json.dumps(manifest, indent=2))
# META-INF/SIGNATURE
zf.writestr(NBPFFormatter.SIGNATURE, package_info["outer_signature"])
@@ -166,10 +166,20 @@ class NBPFPacker:
nir_path = NBPFFormatter.NIR_DIR + mod_name
zf.writestr(nir_path, json.dumps(enc_info))
# RES/ 目录
# RES/ 目录(资源文件不加密)
for res_path, res_data in res_files.items():
zf.writestr(NBPFFormatter.RES_DIR + res_path, res_data)
# META-INF/PLUGIN.MF仅公开元数据明文存储便于发现
meta = manifest.get("metadata", {})
plugin_mf = {
"name": meta.get("name", plugin_dir.name),
"version": meta.get("version", "1.0.0"),
"author": meta.get("author", "unknown"),
"description": meta.get("description", ""),
}
zf.writestr(NBPFFormatter.PLUGIN_MF, json.dumps(plugin_mf, indent=2))
Log.ok("NBPF", f"打包完成: {output_path}")
return output_path
@@ -276,11 +286,17 @@ class NBPFUnpacker:
return output_dir
def extract_manifest(self, nbpf_path: Path) -> dict:
"""提取 manifest.json不解密"""
"""提取公开元数据(不解密,读取 PLUGIN.MF
包含 name / version / author / description 公开字段,
完整 manifest含依赖和权限声明仅在加密的 META-INF 中。
Raises:
NBPFFormatError: 如果 .nbpf 文件中缺少 PLUGIN.MF
"""
with zipfile.ZipFile(nbpf_path, 'r') as zf:
if NBPFFormatter.MANIFEST not in zf.namelist():
raise NBPFFormatError(".nbpf 文件中缺少 MANIFEST.MF")
return json.loads(zf.read(NBPFFormatter.MANIFEST).decode("utf-8"))
if NBPFFormatter.PLUGIN_MF not in zf.namelist():
raise NBPFFormatError(".nbpf 文件中缺少 PLUGIN.MF")
return json.loads(zf.read(NBPFFormatter.PLUGIN_MF).decode("utf-8"))
def verify_signature(
self,