mofox-plugin-dev-toolkit 0.4.1__tar.gz → 0.4.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mofox_plugin_dev_toolkit-0.4.1/mofox_plugin_dev_toolkit.egg-info → mofox_plugin_dev_toolkit-0.4.3}/PKG-INFO +1 -1
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3/mofox_plugin_dev_toolkit.egg-info}/PKG-INFO +1 -1
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mofox_plugin_dev_toolkit.egg-info/SOURCES.txt +2 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/__init__.py +1 -1
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/cli.py +21 -4
- mofox_plugin_dev_toolkit-0.4.3/mpdt/commands/__init__.py +3 -0
- mofox_plugin_dev_toolkit-0.4.3/mpdt/commands/build.py +300 -0
- mofox_plugin_dev_toolkit-0.4.3/mpdt/dev/bridge_plugin/__init__.py +7 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/dev/bridge_plugin/cleanup_handler.py +6 -7
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/dev/bridge_plugin/file_watcher.py +1 -1
- mofox_plugin_dev_toolkit-0.4.3/mpdt/dev/bridge_plugin/manifest.json +16 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/dev/bridge_plugin/plugin.py +29 -59
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/pyproject.toml +1 -1
- mofox_plugin_dev_toolkit-0.4.1/mpdt/commands/__init__.py +0 -9
- mofox_plugin_dev_toolkit-0.4.1/mpdt/dev/bridge_plugin/__init__.py +0 -17
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/LICENSE +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/MANIFEST.in +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/README.md +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mofox_plugin_dev_toolkit.egg-info/dependency_links.txt +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mofox_plugin_dev_toolkit.egg-info/entry_points.txt +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mofox_plugin_dev_toolkit.egg-info/requires.txt +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mofox_plugin_dev_toolkit.egg-info/top_level.txt +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/__main__.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/commands/check.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/commands/dev.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/commands/generate.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/commands/init.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/dev/bridge_plugin/dev_config.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/action_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/adapter_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/chatter_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/collection_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/config_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/event_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/plus_command_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/prompt_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/router_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/service_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/tool_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/code_parser.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/color_printer.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/config_loader.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/config_manager.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/file_ops.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/license_generator.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/plugin_parser.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/template_engine.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/auto_fix_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/base.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/component_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/config_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/metadata_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/structure_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/style_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/type_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/setup.cfg +0 -0
|
@@ -12,6 +12,7 @@ mpdt/__init__.py
|
|
|
12
12
|
mpdt/__main__.py
|
|
13
13
|
mpdt/cli.py
|
|
14
14
|
mpdt/commands/__init__.py
|
|
15
|
+
mpdt/commands/build.py
|
|
15
16
|
mpdt/commands/check.py
|
|
16
17
|
mpdt/commands/dev.py
|
|
17
18
|
mpdt/commands/generate.py
|
|
@@ -20,6 +21,7 @@ mpdt/dev/bridge_plugin/__init__.py
|
|
|
20
21
|
mpdt/dev/bridge_plugin/cleanup_handler.py
|
|
21
22
|
mpdt/dev/bridge_plugin/dev_config.py
|
|
22
23
|
mpdt/dev/bridge_plugin/file_watcher.py
|
|
24
|
+
mpdt/dev/bridge_plugin/manifest.json
|
|
23
25
|
mpdt/dev/bridge_plugin/plugin.py
|
|
24
26
|
mpdt/templates/__init__.py
|
|
25
27
|
mpdt/templates/action_template.py
|
|
@@ -135,14 +135,31 @@ def check(ctx: click.Context, path: str, level: str, fix: bool, report: str, out
|
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
@cli.command()
|
|
138
|
+
@click.argument("plugin_path", type=click.Path(), required=False, default=".")
|
|
138
139
|
@click.option("--output", "-o", type=click.Path(), default="dist", help="输出目录")
|
|
139
140
|
@click.option("--with-docs", is_flag=True, help="包含文档")
|
|
140
|
-
@click.option("--format", type=click.Choice(["
|
|
141
|
+
@click.option("--format", "fmt", type=click.Choice(["mfp", "zip"]), default="mfp", help="构建格式(mfp 为推荐格式)")
|
|
141
142
|
@click.option("--bump", type=click.Choice(["major", "minor", "patch"]), help="自动升级版本号")
|
|
142
143
|
@click.pass_context
|
|
143
|
-
def build(ctx: click.Context, output: str, with_docs: bool,
|
|
144
|
-
"""
|
|
145
|
-
|
|
144
|
+
def build(ctx: click.Context, plugin_path: str, output: str, with_docs: bool, fmt: str, bump: str | None) -> None:
|
|
145
|
+
"""构建并打包插件为 .mfp 文件
|
|
146
|
+
|
|
147
|
+
PLUGIN_PATH 为插件根目录(含 manifest.json),默认为当前目录。
|
|
148
|
+
"""
|
|
149
|
+
from mpdt.commands.build import build_plugin
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
build_plugin(
|
|
153
|
+
plugin_path=plugin_path,
|
|
154
|
+
output_dir=output,
|
|
155
|
+
with_docs=with_docs,
|
|
156
|
+
fmt=fmt,
|
|
157
|
+
bump=bump,
|
|
158
|
+
verbose=ctx.obj["verbose"],
|
|
159
|
+
)
|
|
160
|
+
except Exception as e:
|
|
161
|
+
console.print(f"[bold red]❌ 构建失败: {e}[/bold red]")
|
|
162
|
+
raise click.Abort()
|
|
146
163
|
|
|
147
164
|
|
|
148
165
|
@cli.command()
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""
|
|
2
|
+
构建命令实现
|
|
3
|
+
|
|
4
|
+
将插件目录打包为 .mfp 文件(本质为 ZIP 压缩包)。
|
|
5
|
+
loader.py 支持从 .mfp 直接加载插件,与文件夹加载行为一致。
|
|
6
|
+
|
|
7
|
+
流程:
|
|
8
|
+
1. 验证插件目录及 manifest.json
|
|
9
|
+
2. 可选地自动升级版本号(major / minor / patch)
|
|
10
|
+
3. 收集需打包的文件(排除缓存、版本控制等)
|
|
11
|
+
4. 写入 .mfp(ZIP)或 .zip 文件
|
|
12
|
+
5. 打印构建摘要
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
import re
|
|
19
|
+
import zipfile
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
from rich.panel import Panel
|
|
23
|
+
from rich.table import Table
|
|
24
|
+
|
|
25
|
+
from mpdt.utils.color_printer import (
|
|
26
|
+
console,
|
|
27
|
+
print_error,
|
|
28
|
+
print_step,
|
|
29
|
+
print_success,
|
|
30
|
+
print_warning,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# 构建时默认排除的文件/目录名称(精确匹配)
|
|
34
|
+
_EXCLUDE_NAMES: set[str] = {
|
|
35
|
+
"__pycache__",
|
|
36
|
+
".git",
|
|
37
|
+
".gitignore",
|
|
38
|
+
".gitattributes",
|
|
39
|
+
".github",
|
|
40
|
+
".mypy_cache",
|
|
41
|
+
".ruff_cache",
|
|
42
|
+
".pytest_cache",
|
|
43
|
+
".venv",
|
|
44
|
+
"venv",
|
|
45
|
+
".env",
|
|
46
|
+
"node_modules",
|
|
47
|
+
"dist",
|
|
48
|
+
".DS_Store",
|
|
49
|
+
"Thumbs.db",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# 排除的文件扩展名
|
|
53
|
+
_EXCLUDE_EXTS: set[str] = {
|
|
54
|
+
".pyc",
|
|
55
|
+
".pyo",
|
|
56
|
+
".pyd",
|
|
57
|
+
".egg-info",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# 文档相关目录/文件名
|
|
61
|
+
_DOC_NAMES: set[str] = {
|
|
62
|
+
"docs",
|
|
63
|
+
"doc",
|
|
64
|
+
"README.md",
|
|
65
|
+
"README.rst",
|
|
66
|
+
"CHANGELOG.md",
|
|
67
|
+
"CHANGELOG.rst",
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _is_excluded(path: Path, with_docs: bool) -> bool:
|
|
72
|
+
"""判断路径是否应被排除。"""
|
|
73
|
+
name = path.name
|
|
74
|
+
if name in _EXCLUDE_NAMES:
|
|
75
|
+
return True
|
|
76
|
+
if path.suffix in _EXCLUDE_EXTS:
|
|
77
|
+
return True
|
|
78
|
+
# 以 . 开头的隐藏文件/目录
|
|
79
|
+
if name.startswith("."):
|
|
80
|
+
return True
|
|
81
|
+
# 文档文件(若不包含文档)
|
|
82
|
+
if not with_docs and name in _DOC_NAMES:
|
|
83
|
+
return True
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _collect_files(plugin_dir: Path, with_docs: bool) -> list[Path]:
|
|
88
|
+
"""递归收集插件目录中需要打包的文件列表(相对路径)。"""
|
|
89
|
+
files: list[Path] = []
|
|
90
|
+
|
|
91
|
+
for item in sorted(plugin_dir.rglob("*")):
|
|
92
|
+
# 检查路径上的每个部分是否被排除
|
|
93
|
+
relative = item.relative_to(plugin_dir)
|
|
94
|
+
parts = relative.parts
|
|
95
|
+
|
|
96
|
+
excluded = False
|
|
97
|
+
for part in parts:
|
|
98
|
+
part_path = Path(part)
|
|
99
|
+
if _is_excluded(part_path, with_docs):
|
|
100
|
+
excluded = True
|
|
101
|
+
break
|
|
102
|
+
|
|
103
|
+
if excluded:
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
if item.is_file():
|
|
107
|
+
files.append(item)
|
|
108
|
+
|
|
109
|
+
return files
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _bump_version(version: str, bump: str) -> str:
|
|
113
|
+
"""按规则升级版本号(语义化版本 major.minor.patch)。
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
version: 当前版本字符串,例如 "1.2.3"
|
|
117
|
+
bump: 升级类型,"major" / "minor" / "patch"
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
升级后的版本字符串
|
|
121
|
+
|
|
122
|
+
Raises:
|
|
123
|
+
ValueError: 版本格式不合法
|
|
124
|
+
"""
|
|
125
|
+
match = re.fullmatch(r"(\d+)\.(\d+)\.(\d+)(.*)", version.strip())
|
|
126
|
+
if not match:
|
|
127
|
+
raise ValueError(f"版本号格式不合法: '{version}',应为 major.minor.patch")
|
|
128
|
+
|
|
129
|
+
major, minor, patch, suffix = int(match.group(1)), int(match.group(2)), int(match.group(3)), match.group(4)
|
|
130
|
+
|
|
131
|
+
if bump == "major":
|
|
132
|
+
major += 1
|
|
133
|
+
minor = 0
|
|
134
|
+
patch = 0
|
|
135
|
+
elif bump == "minor":
|
|
136
|
+
minor += 1
|
|
137
|
+
patch = 0
|
|
138
|
+
elif bump == "patch":
|
|
139
|
+
patch += 1
|
|
140
|
+
|
|
141
|
+
return f"{major}.{minor}.{patch}{suffix}"
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _load_manifest(plugin_dir: Path) -> dict | None:
|
|
145
|
+
"""读取并解析 manifest.json,返回字典;失败返回 None。"""
|
|
146
|
+
manifest_path = plugin_dir / "manifest.json"
|
|
147
|
+
if not manifest_path.exists():
|
|
148
|
+
print_error(f"manifest.json 不存在: {manifest_path}")
|
|
149
|
+
return None
|
|
150
|
+
try:
|
|
151
|
+
with open(manifest_path, encoding="utf-8") as f:
|
|
152
|
+
return json.load(f)
|
|
153
|
+
except json.JSONDecodeError as e:
|
|
154
|
+
print_error(f"manifest.json 解析失败: {e}")
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _save_manifest(plugin_dir: Path, manifest: dict) -> None:
|
|
159
|
+
"""将 manifest 字典写回 manifest.json。"""
|
|
160
|
+
manifest_path = plugin_dir / "manifest.json"
|
|
161
|
+
with open(manifest_path, "w", encoding="utf-8") as f:
|
|
162
|
+
json.dump(manifest, f, ensure_ascii=False, indent=4)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def build_plugin(
|
|
166
|
+
plugin_path: str = ".",
|
|
167
|
+
output_dir: str = "dist",
|
|
168
|
+
with_docs: bool = False,
|
|
169
|
+
fmt: str = "mfp",
|
|
170
|
+
bump: str | None = None,
|
|
171
|
+
verbose: bool = False,
|
|
172
|
+
) -> None:
|
|
173
|
+
"""构建并打包插件为 .mfp / .zip 文件。
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
plugin_path: 插件根目录(包含 manifest.json)
|
|
177
|
+
output_dir: 输出目录,默认 dist/
|
|
178
|
+
with_docs: 是否将文档文件打入包中
|
|
179
|
+
fmt: 输出格式,"mfp"(推荐) 或 "zip"
|
|
180
|
+
bump: 自动升级版本,"major" / "minor" / "patch" / None
|
|
181
|
+
verbose: 是否显示详细信息
|
|
182
|
+
"""
|
|
183
|
+
plugin_dir = Path(plugin_path).resolve()
|
|
184
|
+
|
|
185
|
+
# ── 1. 基本验证 ──────────────────────────────────────────────────────────
|
|
186
|
+
if not plugin_dir.exists():
|
|
187
|
+
print_error(f"插件路径不存在: {plugin_dir}")
|
|
188
|
+
return
|
|
189
|
+
if not plugin_dir.is_dir():
|
|
190
|
+
print_error(f"插件路径不是目录: {plugin_dir}")
|
|
191
|
+
return
|
|
192
|
+
|
|
193
|
+
console.print(Panel.fit(f"📦 构建插件: [cyan]{plugin_dir.name}[/cyan]", border_style="blue"))
|
|
194
|
+
|
|
195
|
+
manifest = _load_manifest(plugin_dir)
|
|
196
|
+
if manifest is None:
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
required = ["name", "version", "description", "author", "entry_point"]
|
|
200
|
+
for field in required:
|
|
201
|
+
if field not in manifest:
|
|
202
|
+
print_error(f"manifest.json 缺少必需字段: '{field}'")
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
plugin_name: str = manifest["name"]
|
|
206
|
+
plugin_version: str = manifest["version"]
|
|
207
|
+
|
|
208
|
+
# ── 2. 版本升级 ──────────────────────────────────────────────────────────
|
|
209
|
+
if bump:
|
|
210
|
+
try:
|
|
211
|
+
new_version = _bump_version(plugin_version, bump)
|
|
212
|
+
except ValueError as e:
|
|
213
|
+
print_error(str(e))
|
|
214
|
+
return
|
|
215
|
+
print_step(f"版本升级: [yellow]{plugin_version}[/yellow] → [green]{new_version}[/green]")
|
|
216
|
+
manifest["version"] = new_version
|
|
217
|
+
_save_manifest(plugin_dir, manifest)
|
|
218
|
+
plugin_version = new_version
|
|
219
|
+
|
|
220
|
+
# ── 3. 验证入口文件 ───────────────────────────────────────────────────────
|
|
221
|
+
entry_point = manifest.get("entry_point", "plugin.py")
|
|
222
|
+
entry_file = plugin_dir / entry_point
|
|
223
|
+
if not entry_file.exists():
|
|
224
|
+
print_warning(f"入口文件不存在: {entry_point}(仍将继续构建)")
|
|
225
|
+
|
|
226
|
+
# ── 4. 收集文件 ───────────────────────────────────────────────────────────
|
|
227
|
+
print_step("收集文件...")
|
|
228
|
+
files = _collect_files(plugin_dir, with_docs)
|
|
229
|
+
|
|
230
|
+
if not files:
|
|
231
|
+
print_warning("未找到任何需要打包的文件")
|
|
232
|
+
return
|
|
233
|
+
|
|
234
|
+
if verbose:
|
|
235
|
+
for f in files:
|
|
236
|
+
rel = f.relative_to(plugin_dir)
|
|
237
|
+
console.print(f" [dim]+ {rel}[/dim]")
|
|
238
|
+
|
|
239
|
+
# ── 5. 确定输出路径 ───────────────────────────────────────────────────────
|
|
240
|
+
# output_dir 可以是绝对路径或相对于插件目录
|
|
241
|
+
out_path = Path(output_dir)
|
|
242
|
+
if not out_path.is_absolute():
|
|
243
|
+
out_path = plugin_dir / output_dir
|
|
244
|
+
|
|
245
|
+
out_path.mkdir(parents=True, exist_ok=True)
|
|
246
|
+
|
|
247
|
+
suffix = ".mfp" if fmt == "mfp" else ".zip"
|
|
248
|
+
archive_name = f"{plugin_name}-{plugin_version}{suffix}"
|
|
249
|
+
archive_path = out_path / archive_name
|
|
250
|
+
|
|
251
|
+
if archive_path.exists():
|
|
252
|
+
print_warning(f"目标文件已存在,将覆盖: {archive_path}")
|
|
253
|
+
|
|
254
|
+
# ── 6. 压缩打包 ───────────────────────────────────────────────────────────
|
|
255
|
+
print_step(f"正在写入 {suffix} 包...")
|
|
256
|
+
total_bytes = 0
|
|
257
|
+
|
|
258
|
+
try:
|
|
259
|
+
with zipfile.ZipFile(archive_path, "w", compression=zipfile.ZIP_DEFLATED) as zf:
|
|
260
|
+
for file_path in files:
|
|
261
|
+
arcname = file_path.relative_to(plugin_dir)
|
|
262
|
+
zf.write(file_path, arcname)
|
|
263
|
+
total_bytes += file_path.stat().st_size
|
|
264
|
+
if verbose:
|
|
265
|
+
console.print(f" [dim] → {arcname}[/dim]")
|
|
266
|
+
except Exception as e:
|
|
267
|
+
print_error(f"打包失败: {e}")
|
|
268
|
+
# 清理不完整的文件
|
|
269
|
+
if archive_path.exists():
|
|
270
|
+
archive_path.unlink()
|
|
271
|
+
return
|
|
272
|
+
|
|
273
|
+
# ── 7. 摘要 ──────────────────────────────────────────────────────────────
|
|
274
|
+
archive_size = archive_path.stat().st_size
|
|
275
|
+
|
|
276
|
+
table = Table(show_header=False, box=None, padding=(0, 2))
|
|
277
|
+
table.add_column(style="cyan")
|
|
278
|
+
table.add_column(style="white")
|
|
279
|
+
table.add_row("插件名称", plugin_name)
|
|
280
|
+
table.add_row("版本", plugin_version)
|
|
281
|
+
table.add_row("作者", manifest.get("author", "-"))
|
|
282
|
+
table.add_row("入口文件", entry_point)
|
|
283
|
+
table.add_row("打包文件数", str(len(files)))
|
|
284
|
+
table.add_row("原始大小", _format_size(total_bytes))
|
|
285
|
+
table.add_row("包大小", _format_size(archive_size))
|
|
286
|
+
table.add_row("输出路径", str(archive_path))
|
|
287
|
+
|
|
288
|
+
console.print()
|
|
289
|
+
console.print(table)
|
|
290
|
+
console.print()
|
|
291
|
+
print_success(f"构建完成: {archive_path.name}")
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _format_size(size: int) -> str:
|
|
295
|
+
"""将字节数格式化为人类可读字符串。"""
|
|
296
|
+
for unit in ("B", "KB", "MB", "GB"):
|
|
297
|
+
if size < 1024:
|
|
298
|
+
return f"{size:.1f} {unit}"
|
|
299
|
+
size //= 1024
|
|
300
|
+
return f"{size:.1f} TB"
|
|
@@ -5,11 +5,10 @@ DevBridge 清理事件处理器
|
|
|
5
5
|
|
|
6
6
|
import shutil
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import ClassVar
|
|
9
8
|
|
|
10
|
-
from src.
|
|
11
|
-
from src.
|
|
12
|
-
from src.
|
|
9
|
+
from src.core.components.base.event_handler import BaseEventHandler
|
|
10
|
+
from src.core.components.types import EventType
|
|
11
|
+
from src.kernel.logger import get_logger
|
|
13
12
|
|
|
14
13
|
from .dev_config import TARGET_PLUGIN_NAME, TARGET_PLUGIN_PATH
|
|
15
14
|
|
|
@@ -22,10 +21,10 @@ class CleanupHandler(BaseEventHandler):
|
|
|
22
21
|
handler_name = "dev_bridge_cleanup"
|
|
23
22
|
handler_description = "DevBridge 清理处理器"
|
|
24
23
|
weight = -100 # 负权重,确保最后执行
|
|
25
|
-
init_subscribe:
|
|
24
|
+
init_subscribe: list[EventType | str] = [EventType.ON_STOP]
|
|
26
25
|
|
|
27
|
-
def __init__(self):
|
|
28
|
-
super().__init__()
|
|
26
|
+
def __init__(self, plugin=None):
|
|
27
|
+
super().__init__(plugin)
|
|
29
28
|
self._target_plugin_name = TARGET_PLUGIN_NAME
|
|
30
29
|
self._target_plugin_path = TARGET_PLUGIN_PATH
|
|
31
30
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dev_bridge",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "开发模式桥接插件,提供文件监控和热重载功能",
|
|
5
|
+
"author": "MoFox Team",
|
|
6
|
+
"license": "GPL-3.0",
|
|
7
|
+
"min_core_version": "0.1.0",
|
|
8
|
+
"entry_point": "plugin.py",
|
|
9
|
+
"keywords": ["dev", "watcher", "reload", "bridge"],
|
|
10
|
+
"categories": ["utility"],
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"plugins": [],
|
|
13
|
+
"components": []
|
|
14
|
+
},
|
|
15
|
+
"include": []
|
|
16
|
+
}
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/dev/bridge_plugin/plugin.py
RENAMED
|
@@ -2,17 +2,16 @@
|
|
|
2
2
|
DevBridge 插件 - 完整的开发模式插件
|
|
3
3
|
负责文件监控、插件重载等所有开发操作
|
|
4
4
|
配置通过 dev_config.py 中的常量传递(mpdt dev 注入时动态修改)
|
|
5
|
+
|
|
6
|
+
Neo-MoFox 版本:适配新版插件系统 API。
|
|
5
7
|
"""
|
|
6
8
|
|
|
7
9
|
import asyncio
|
|
8
10
|
from pathlib import Path
|
|
9
|
-
from typing import ClassVar
|
|
10
11
|
|
|
11
|
-
from src.
|
|
12
|
-
from src.
|
|
13
|
-
|
|
14
|
-
register_plugin,
|
|
15
|
-
)
|
|
12
|
+
from src.core.components.base.plugin import BasePlugin
|
|
13
|
+
from src.core.components.loader import register_plugin
|
|
14
|
+
from src.kernel.logger import get_logger
|
|
16
15
|
|
|
17
16
|
# 导入配置(由 mpdt dev 注入时修改)
|
|
18
17
|
from .dev_config import (
|
|
@@ -37,22 +36,23 @@ class DevBridgePlugin(BasePlugin):
|
|
|
37
36
|
"""
|
|
38
37
|
|
|
39
38
|
plugin_name = "dev_bridge"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
dependencies: ClassVar = []
|
|
43
|
-
python_dependencies: ClassVar = []
|
|
39
|
+
plugin_description = "开发模式桥接插件,提供文件监控和热重载功能"
|
|
40
|
+
plugin_version = "1.0.0"
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
configs: list = []
|
|
43
|
+
dependent_components: list[str] = []
|
|
44
|
+
|
|
45
|
+
def __init__(self, config=None):
|
|
46
|
+
super().__init__(config)
|
|
47
47
|
self._file_watcher = None
|
|
48
48
|
self._target_plugin_name = TARGET_PLUGIN_NAME
|
|
49
49
|
self._target_plugin_path = TARGET_PLUGIN_PATH
|
|
50
50
|
|
|
51
|
-
def
|
|
51
|
+
def get_components(self) -> list[type]:
|
|
52
52
|
"""注册清理事件处理器"""
|
|
53
53
|
from .cleanup_handler import CleanupHandler
|
|
54
54
|
|
|
55
|
-
return [
|
|
55
|
+
return [CleanupHandler]
|
|
56
56
|
|
|
57
57
|
async def on_plugin_loaded(self):
|
|
58
58
|
"""插件加载完成后启动文件监控"""
|
|
@@ -92,30 +92,20 @@ class DevBridgePlugin(BasePlugin):
|
|
|
92
92
|
return
|
|
93
93
|
|
|
94
94
|
try:
|
|
95
|
-
from src.
|
|
95
|
+
from src.core.managers.plugin_manager import get_plugin_manager
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
plugin_manager = get_plugin_manager()
|
|
98
|
+
is_loaded = plugin_manager.is_plugin_loaded(self._target_plugin_name)
|
|
99
99
|
|
|
100
100
|
if not is_loaded:
|
|
101
101
|
logger.error("=" * 60)
|
|
102
102
|
logger.error(f"❌ 目标插件 {self._target_plugin_name} 未加载!")
|
|
103
103
|
logger.error("")
|
|
104
|
-
|
|
105
|
-
logger.error("📋 原因: 插件已被禁用")
|
|
106
|
-
logger.error("")
|
|
107
|
-
logger.error("🔧 解决方案:")
|
|
108
|
-
logger.error(" 1. 检查插件的 config.toml 中 [plugin] enabled = true")
|
|
109
|
-
logger.error(" 2. 或在 plugin.py 中设置 enable_plugin = True")
|
|
110
|
-
logger.error(" 3. 或直接删除 enable_plugin 行(默认启用)")
|
|
111
|
-
else:
|
|
112
|
-
logger.error("📋 原因: 插件加载失败,请检查插件代码是否有错误")
|
|
104
|
+
logger.error("📋 原因: 插件加载失败,请检查插件代码是否有错误")
|
|
113
105
|
logger.error("=" * 60)
|
|
114
106
|
else:
|
|
115
107
|
logger.info(f"✅ 目标插件 {self._target_plugin_name} 已成功加载")
|
|
116
108
|
|
|
117
|
-
except ValueError:
|
|
118
|
-
logger.error(f"❌ 目标插件 {self._target_plugin_name} 未注册")
|
|
119
109
|
except Exception as e:
|
|
120
110
|
logger.error(f"❌ 检查目标插件状态时出错: {e}")
|
|
121
111
|
|
|
@@ -136,49 +126,29 @@ class DevBridgePlugin(BasePlugin):
|
|
|
136
126
|
return
|
|
137
127
|
|
|
138
128
|
try:
|
|
139
|
-
from src.
|
|
129
|
+
from src.core.managers.plugin_manager import get_plugin_manager
|
|
140
130
|
|
|
131
|
+
plugin_manager = get_plugin_manager()
|
|
141
132
|
plugin_name = self._target_plugin_name
|
|
142
|
-
is_loaded =
|
|
143
|
-
is_enabled = plugin_manage_api.is_plugin_enabled(plugin_name)
|
|
133
|
+
is_loaded = plugin_manager.is_plugin_loaded(plugin_name)
|
|
144
134
|
|
|
145
135
|
if is_loaded:
|
|
146
|
-
#
|
|
147
|
-
if not is_enabled:
|
|
148
|
-
logger.info(f"🔓 插件 {plugin_name} 已禁用,正在启用...")
|
|
149
|
-
await plugin_manage_api.enable_plugin(plugin_name)
|
|
150
|
-
|
|
151
|
-
# 重载插件
|
|
136
|
+
# 插件已加载,直接重载
|
|
152
137
|
logger.info(f"🔄 正在重载插件: {plugin_name}...")
|
|
153
|
-
success = await
|
|
138
|
+
success = await plugin_manager.reload_plugin(plugin_name)
|
|
154
139
|
if success:
|
|
155
140
|
logger.info(f"✅ 插件 {plugin_name} 重载成功")
|
|
156
141
|
else:
|
|
157
142
|
logger.error(f"❌ 插件 {plugin_name} 重载失败")
|
|
158
143
|
else:
|
|
159
|
-
#
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
success = await plugin_manage_api.enable_plugin(plugin_name)
|
|
144
|
+
# 插件未加载,通过路径直接加载
|
|
145
|
+
logger.info(f"📦 插件 {plugin_name} 未加载,正在从路径加载...")
|
|
146
|
+
success = await plugin_manager.load_plugin(self._target_plugin_path)
|
|
163
147
|
if success:
|
|
164
|
-
logger.info(f"✅ 插件 {plugin_name}
|
|
165
|
-
else:
|
|
166
|
-
logger.error(f"❌ 插件 {plugin_name} 启用/加载失败")
|
|
167
|
-
|
|
168
|
-
except ValueError as e:
|
|
169
|
-
# 插件未注册,尝试扫描并加载
|
|
170
|
-
logger.warning(f"⚠️ 插件未注册: {e}")
|
|
171
|
-
logger.info("🔍 正在扫描插件目录...")
|
|
172
|
-
try:
|
|
173
|
-
from src.plugin_system.apis import plugin_manage_api
|
|
174
|
-
|
|
175
|
-
plugin_manage_api.rescan_and_register_plugins(load_after_register=True)
|
|
176
|
-
if plugin_manage_api.is_plugin_loaded(self._target_plugin_name):
|
|
177
|
-
logger.info(f"✅ 插件 {self._target_plugin_name} 扫描并加载成功")
|
|
148
|
+
logger.info(f"✅ 插件 {plugin_name} 加载成功")
|
|
178
149
|
else:
|
|
179
|
-
logger.error(f"❌ 插件 {
|
|
180
|
-
|
|
181
|
-
logger.error(f"❌ 扫描插件目录失败: {scan_e}")
|
|
150
|
+
logger.error(f"❌ 插件 {plugin_name} 加载失败")
|
|
151
|
+
|
|
182
152
|
except Exception as e:
|
|
183
153
|
logger.error(f"❌ 操作插件时出错: {e}")
|
|
184
154
|
import traceback
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"""开发模式桥接插件
|
|
2
|
-
|
|
3
|
-
这是一个特殊的插件,在开发模式下临时注入到主程序。
|
|
4
|
-
负责文件监控和插件热重载,配置由 mpdt dev 在注入时写入 dev_config.py。
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from src.plugin_system.base.plugin_metadata import PluginMetadata
|
|
8
|
-
|
|
9
|
-
__plugin_meta__ = PluginMetadata(
|
|
10
|
-
name="dev_bridge",
|
|
11
|
-
description="开发模式桥接插件,提供文件监控和热重载功能",
|
|
12
|
-
usage="在开发模式下临时注入,监控目标插件文件变化并自动重载。",
|
|
13
|
-
version="1.0.0",
|
|
14
|
-
author="MoFox Team",
|
|
15
|
-
dependencies=[],
|
|
16
|
-
python_dependencies=["watchdog"],
|
|
17
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/__init__.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/action_template.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/adapter_template.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/chatter_template.py
RENAMED
|
File without changes
|
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/config_template.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/event_template.py
RENAMED
|
File without changes
|
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/prompt_template.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/router_template.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/service_template.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/templates/tool_template.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/color_printer.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/config_loader.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/config_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/license_generator.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/plugin_parser.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/utils/template_engine.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/style_validator.py
RENAMED
|
File without changes
|
{mofox_plugin_dev_toolkit-0.4.1 → mofox_plugin_dev_toolkit-0.4.3}/mpdt/validators/type_validator.py
RENAMED
|
File without changes
|
|
File without changes
|