更改项目名为NebulaShell

This commit is contained in:
Falck
2026-05-02 08:30:31 +08:00
parent d16e28ab17
commit 2c2ec60a2b
233 changed files with 298 additions and 276 deletions

View File

@@ -0,0 +1,172 @@
# PL 注入机制使用说明
## 概述
PL 注入机制允许插件通过 `PL/` 文件夹向插件加载器注册自定义功能。插件加载器在启动时会自动扫描所有插件,检查其 `manifest.json` 中是否声明了 `pl_injection` 配置项。
## 使用步骤
### 1. 在 manifest.json 中声明 pl_injection
在插件的 `manifest.json``config.args` 中添加 `"pl_injection": true`
```json
{
"metadata": {
"name": "my-plugin",
"version": "1.0.0",
"author": "MyName",
"description": "我的插件",
"type": "utility"
},
"config": {
"enabled": true,
"args": {
"pl_injection": true
}
},
"dependencies": [],
"permissions": []
}
```
### 2. 创建 PL/ 文件夹和 PL/main.py
在插件目录下创建 `PL/` 文件夹,并在其中创建 `main.py`
```
store/@{MyName}/my-plugin/
├── manifest.json # 声明 pl_injection: true
├── main.py # 插件主逻辑
├── PL/ # PL 注入文件夹
│ └── main.py # 注入逻辑(必须包含 register() 函数)
└── README.md
```
### 3. 实现 PL/main.py
`PL/main.py` 必须导出一个 `register(injector)` 函数,接收一个 `PLInjector` 实例:
```python
# PL/main.py
"""PL 注入 - 向插件加载器注册功能"""
def register(injector):
"""向插件加载器注册功能
Args:
injector: PLInjector 实例,提供以下注册方法:
- register_function(name, func, description="")
- register_route(method, path, handler)
- register_event_handler(event_name, handler)
"""
# 示例 1: 注册一个普通功能
def my_helper():
print("这是从 PL 注入的功能")
injector.register_function("my_helper", my_helper, "一个辅助功能")
# 示例 2: 注册 HTTP 路由
def hello_handler(request):
return {"message": "Hello from PL injection!"}
injector.register_route("GET", "/pl/hello", hello_handler)
# 示例 3: 注册事件处理器
def on_plugin_started(plugin_name):
print(f"插件 {plugin_name} 已启动")
injector.register_event_handler("plugin.started", on_plugin_started)
```
### 4. 引用其他文件
`PL/main.py` 可以引用 `PL/` 文件夹下的其他 Python 文件:
```
store/@{MyName}/my-plugin/PL/
├── main.py # 入口,包含 register() 函数
├── helpers.py # 辅助函数(被 main.py 引用)
└── routes.py # 路由定义(被 main.py 引用)
```
```python
# PL/main.py
from .helpers import format_response
from .routes import register_routes
def register(injector):
def my_handler():
return format_response("Hello")
injector.register_function("my_handler", my_handler)
register_routes(injector)
```
## 行为说明
| 场景 | 结果 |
|------|------|
| manifest.json 中 `pl_injection: true` + 存在 `PL/main.py` | ✅ 正常加载,执行注入 |
| manifest.json 中 `pl_injection: true` + 缺少 `PL/` 文件夹 | ❌ 警告并拒绝加载该插件 |
| manifest.json 中 `pl_injection: true` + 存在 `PL/` 但缺少 `main.py` | ❌ 警告并拒绝加载该插件 |
| manifest.json 中未声明 `pl_injection` | ✅ 正常加载,跳过 PL 检查 |
| manifest.json 中 `pl_injection: false` | ✅ 正常加载,跳过 PL 检查 |
## 安全限制
PL 注入机制实施了多层安全限制,防止恶意代码注入:
### 1. 文件类型限制
- PL 文件夹中禁止包含 `.sh``.bat``.exe``.dll``.so``.dylib``.bin` 等可执行/二进制文件
- 违反则拒绝加载该插件
### 2. 静态源码安全检查
PL/main.py 源码在编译前会进行静态扫描,禁止以下操作:
- 导入系统级模块(`os``sys``subprocess``shutil``socket``ctypes``cffi``multiprocessing``threading`
- 使用 `__import__``exec``eval``compile`
- 直接操作文件(`open`
- 访问 `__builtins__`
### 3. 沙箱执行环境
PL/main.py 在受限的沙箱中执行,仅提供安全的 builtins
- 基础类型:`dict``list``str``int``float``bool``tuple``set`
- 安全函数:`len``range``enumerate``zip``map``filter``sorted`
- 异常类型:`Exception``ValueError``TypeError``KeyError``IndexError`
### 4. 参数校验
| 校验项 | 限制 |
|--------|------|
| 功能名称 | 仅允许字母、数字、下划线、冒号、斜杠、连字符、点,最长 128 字符 |
| 路由路径 | 必须以 `/` 开头,禁止 `..``//``/\.``~``%`,最长 256 字符 |
| HTTP 方法 | 仅允许 GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS |
| 事件名称 | 字母开头,仅允许字母、数字、点、下划线,最长 128 字符 |
| 功能描述 | 最长 256 字符 |
### 5. 数量限制
| 限制项 | 上限 |
|--------|------|
| 每个插件最多注册的功能数 | 50 |
| 每个功能名称最多被注册次数 | 10 |
### 6. 异常安全
- 所有注册的函数会被自动包装,执行时抛出异常不会影响主流程
- 异常会被记录到日志,函数返回 `None`
### 7. 调用者溯源
- 通过栈帧回溯自动识别调用者插件名
- 防止其他插件冒充注册
## 注入器 API
`PLInjector` 实例提供以下方法供 `PL/main.py` 调用:
| 方法 | 说明 |
|------|------|
| `register_function(name, func, description="")` | 注册一个注入功能 |
| `register_route(method, path, handler)` | 注册 HTTP 路由 |
| `register_event_handler(event_name, handler)` | 注册事件处理器 |
| `get_injected_functions(name=None)` | 获取已注册的注入功能 |
| `get_injection_info(plugin_name=None)` | 获取注入信息 |
| `has_injection(plugin_name)` | 检查插件是否有 PL 注入 |
| `get_registry_info()` | 获取注册表完整信息(用于监控) |