mofox-plugin-dev-toolkit 0.2.2__tar.gz → 0.2.7__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.2.2/mofox_plugin_dev_toolkit.egg-info → mofox_plugin_dev_toolkit-0.2.7}/PKG-INFO +2 -1
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7/mofox_plugin_dev_toolkit.egg-info}/PKG-INFO +2 -1
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mofox_plugin_dev_toolkit.egg-info/SOURCES.txt +1 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mofox_plugin_dev_toolkit.egg-info/requires.txt +1 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/__init__.py +1 -1
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/cli.py +1 -1
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/check.py +91 -13
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/generate.py +134 -71
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/init.py +20 -13
- mofox_plugin_dev_toolkit-0.2.7/mpdt/utils/code_parser.py +402 -0
- mofox_plugin_dev_toolkit-0.2.7/mpdt/validators/auto_fix_validator.py +996 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/base.py +8 -0
- mofox_plugin_dev_toolkit-0.2.7/mpdt/validators/component_validator.py +840 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/config_validator.py +18 -72
- mofox_plugin_dev_toolkit-0.2.7/mpdt/validators/metadata_validator.py +110 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/type_validator.py +0 -2
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/pyproject.toml +2 -1
- mofox_plugin_dev_toolkit-0.2.2/mpdt/validators/auto_fix_validator.py +0 -182
- mofox_plugin_dev_toolkit-0.2.2/mpdt/validators/component_validator.py +0 -494
- mofox_plugin_dev_toolkit-0.2.2/mpdt/validators/metadata_validator.py +0 -125
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/LICENSE +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/MANIFEST.in +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/README.md +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mofox_plugin_dev_toolkit.egg-info/dependency_links.txt +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mofox_plugin_dev_toolkit.egg-info/entry_points.txt +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mofox_plugin_dev_toolkit.egg-info/top_level.txt +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/__main__.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/dev.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/dev/bridge_plugin/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/dev/bridge_plugin/discovery_server.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/dev/bridge_plugin/plugin.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/action_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/adapter_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/chatter_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/event_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/plus_command_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/prompt_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/router_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/tool_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/color_printer.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/config_loader.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/config_manager.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/file_ops.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/license_generator.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/plugin_parser.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/template_engine.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/structure_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/style_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mofox-plugin-dev-toolkit
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: 开发工具集,用于快速创建、开发和测试 MoFox-Bot 插件
|
|
5
5
|
Author-email: MoFox-Studio <mofox.studio@example.com>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -28,6 +28,7 @@ Requires-Dist: tomli-w>=1.0.0
|
|
|
28
28
|
Requires-Dist: pydantic>=2.5.0
|
|
29
29
|
Requires-Dist: watchdog>=3.0.0
|
|
30
30
|
Requires-Dist: websockets>=12.0
|
|
31
|
+
Requires-Dist: libcst>=1.8.6
|
|
31
32
|
Requires-Dist: aiohttp>=3.9.0
|
|
32
33
|
Requires-Dist: uvicorn>=0.24.0
|
|
33
34
|
Requires-Dist: fastapi>=0.104.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mofox-plugin-dev-toolkit
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: 开发工具集,用于快速创建、开发和测试 MoFox-Bot 插件
|
|
5
5
|
Author-email: MoFox-Studio <mofox.studio@example.com>
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -28,6 +28,7 @@ Requires-Dist: tomli-w>=1.0.0
|
|
|
28
28
|
Requires-Dist: pydantic>=2.5.0
|
|
29
29
|
Requires-Dist: watchdog>=3.0.0
|
|
30
30
|
Requires-Dist: websockets>=12.0
|
|
31
|
+
Requires-Dist: libcst>=1.8.6
|
|
31
32
|
Requires-Dist: aiohttp>=3.9.0
|
|
32
33
|
Requires-Dist: uvicorn>=0.24.0
|
|
33
34
|
Requires-Dist: fastapi>=0.104.0
|
|
@@ -209,7 +209,7 @@ def config_show() -> None:
|
|
|
209
209
|
table.add_column("值", style="green")
|
|
210
210
|
|
|
211
211
|
table.add_row("配置文件", str(config.config_path))
|
|
212
|
-
table.add_row("
|
|
212
|
+
table.add_row("MoFox-Bot 路径", str(config.mmc_path) if config.mmc_path else "[red]未配置[/red]")
|
|
213
213
|
table.add_row("虚拟环境类型", config.venv_type)
|
|
214
214
|
table.add_row("虚拟环境路径", str(config.venv_path) if config.venv_path else "[dim]无[/dim]")
|
|
215
215
|
table.add_row("自动重载", "是" if config.auto_reload else "否")
|
|
@@ -114,19 +114,41 @@ def check_plugin(
|
|
|
114
114
|
_print_validation_summary(result, verbose)
|
|
115
115
|
|
|
116
116
|
# 自动修复(如果启用)
|
|
117
|
+
auto_fixer = None
|
|
117
118
|
if auto_fix:
|
|
118
119
|
print_info("正在应用自动修复...")
|
|
119
120
|
auto_fixer = AutoFixValidator(path)
|
|
120
|
-
fix_result = auto_fixer.
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
fix_result = auto_fixer.fix_issues(all_results)
|
|
122
|
+
|
|
123
|
+
# 从原始结果中移除已修复的问题(使用对象 id 比较)
|
|
124
|
+
fixed_issue_ids = {id(issue) for issue in auto_fixer.fixed_issues}
|
|
125
|
+
for result in all_results:
|
|
126
|
+
result.issues = [issue for issue in result.issues if id(issue) not in fixed_issue_ids]
|
|
127
|
+
# 更新计数
|
|
128
|
+
result._update_counts()
|
|
129
|
+
|
|
130
|
+
# 显示修复摘要
|
|
131
|
+
if auto_fixer.fixes_applied:
|
|
132
|
+
print_success(f" ✓ 成功修复 {len(auto_fixer.fixes_applied)} 个问题")
|
|
133
|
+
if verbose:
|
|
134
|
+
for fix in auto_fixer.fixes_applied:
|
|
135
|
+
console.print(f" [green]✓[/green] {fix}")
|
|
136
|
+
|
|
137
|
+
if auto_fixer.fixes_failed:
|
|
138
|
+
print_warning(f" ⚠ {len(auto_fixer.fixes_failed)} 个问题修复失败")
|
|
139
|
+
if verbose:
|
|
140
|
+
for fail in auto_fixer.fixes_failed:
|
|
141
|
+
console.print(f" [yellow]✗[/yellow] {fail}")
|
|
142
|
+
|
|
143
|
+
if not auto_fixer.fixes_applied and not auto_fixer.fixes_failed:
|
|
144
|
+
print_info(" ℹ 未发现可自动修复的问题")
|
|
123
145
|
|
|
124
146
|
# 生成总体报告
|
|
125
|
-
_print_overall_report(all_results, level)
|
|
147
|
+
_print_overall_report(all_results, level, auto_fixer)
|
|
126
148
|
|
|
127
149
|
# 保存报告(如果需要)
|
|
128
150
|
if output_path:
|
|
129
|
-
_save_report(all_results, output_path, report_format)
|
|
151
|
+
_save_report(all_results, output_path, report_format, auto_fixer)
|
|
130
152
|
|
|
131
153
|
|
|
132
154
|
def _print_validation_summary(result: ValidationResult, verbose: bool = False) -> None:
|
|
@@ -181,12 +203,13 @@ def _print_issue(issue) -> None:
|
|
|
181
203
|
console.print(f" [dim]💡 {issue.suggestion}[/dim]")
|
|
182
204
|
|
|
183
205
|
|
|
184
|
-
def _print_overall_report(results: list[ValidationResult], level: str) -> None:
|
|
206
|
+
def _print_overall_report(results: list[ValidationResult], level: str, auto_fixer: AutoFixValidator | None = None) -> None:
|
|
185
207
|
"""打印总体报告
|
|
186
208
|
|
|
187
209
|
Args:
|
|
188
210
|
results: 所有验证结果
|
|
189
211
|
level: 显示级别
|
|
212
|
+
auto_fixer: 自动修复器对象(如果启用了自动修复)
|
|
190
213
|
"""
|
|
191
214
|
console.print()
|
|
192
215
|
console.print("=" * 60)
|
|
@@ -236,44 +259,85 @@ def _print_overall_report(results: list[ValidationResult], level: str) -> None:
|
|
|
236
259
|
|
|
237
260
|
# 总结
|
|
238
261
|
console.print()
|
|
262
|
+
if auto_fixer:
|
|
263
|
+
console.print("[bold cyan]═══ 修复统计 ═══[/bold cyan]")
|
|
264
|
+
console.print()
|
|
265
|
+
|
|
266
|
+
if auto_fixer.fixes_applied:
|
|
267
|
+
console.print(f"[green]✓ 成功修复: {len(auto_fixer.fixes_applied)} 个[/green]")
|
|
268
|
+
for fix in auto_fixer.fixes_applied:
|
|
269
|
+
console.print(f" [green]•[/green] {fix}")
|
|
270
|
+
console.print()
|
|
271
|
+
|
|
272
|
+
if auto_fixer.fixes_failed:
|
|
273
|
+
console.print(f"[yellow]✗ 修复失败: {len(auto_fixer.fixes_failed)} 个[/yellow]")
|
|
274
|
+
for fail in auto_fixer.fixes_failed:
|
|
275
|
+
console.print(f" [yellow]•[/yellow] {fail}")
|
|
276
|
+
console.print()
|
|
277
|
+
|
|
278
|
+
if not auto_fixer.fixes_applied and not auto_fixer.fixes_failed:
|
|
279
|
+
console.print("[blue]ℹ 未发现可自动修复的问题[/blue]")
|
|
280
|
+
console.print()
|
|
281
|
+
|
|
282
|
+
console.print("[bold cyan]═══ 最终结果 ═══[/bold cyan]")
|
|
283
|
+
console.print()
|
|
239
284
|
if total_errors > 0:
|
|
240
|
-
print_error(f"
|
|
285
|
+
print_error(f"剩余 {total_errors} 个错误,{total_warnings} 个警告")
|
|
241
286
|
elif total_warnings > 0:
|
|
242
|
-
print_warning(f"
|
|
287
|
+
print_warning(f"剩余 {total_warnings} 个警告")
|
|
243
288
|
else:
|
|
244
289
|
print_success("所有检查通过!")
|
|
245
290
|
|
|
246
291
|
|
|
247
|
-
def _save_report(results: list[ValidationResult], output_path: str, report_format: str) -> None:
|
|
292
|
+
def _save_report(results: list[ValidationResult], output_path: str, report_format: str, auto_fixer: AutoFixValidator | None = None) -> None:
|
|
248
293
|
"""保存检查报告
|
|
249
294
|
|
|
250
295
|
Args:
|
|
251
296
|
results: 验证结果列表
|
|
252
297
|
output_path: 输出路径
|
|
253
298
|
report_format: 报告格式
|
|
299
|
+
auto_fixer: 自动修复器对象(如果启用了自动修复)
|
|
254
300
|
"""
|
|
255
301
|
if report_format == "markdown":
|
|
256
|
-
_save_markdown_report(results, output_path)
|
|
302
|
+
_save_markdown_report(results, output_path, auto_fixer)
|
|
257
303
|
else:
|
|
258
304
|
print_warning(f"不支持的报告格式: {report_format}")
|
|
259
305
|
|
|
260
306
|
|
|
261
|
-
def _save_markdown_report(results: list[ValidationResult], output_path: str) -> None:
|
|
307
|
+
def _save_markdown_report(results: list[ValidationResult], output_path: str, auto_fixer: AutoFixValidator | None = None) -> None:
|
|
262
308
|
"""保存 Markdown 格式的报告
|
|
263
309
|
|
|
264
310
|
Args:
|
|
265
311
|
results: 验证结果列表
|
|
266
312
|
output_path: 输出路径
|
|
313
|
+
auto_fixer: 自动修复器对象(如果启用了自动修复)
|
|
267
314
|
"""
|
|
268
|
-
lines = ["# 插件检查报告\n"]
|
|
315
|
+
lines = ["# 插件检查报告\n\n"]
|
|
269
316
|
|
|
270
317
|
# 统计
|
|
271
318
|
total_errors = sum(r.error_count for r in results)
|
|
272
319
|
total_warnings = sum(r.warning_count for r in results)
|
|
320
|
+
total_info = sum(r.info_count for r in results)
|
|
273
321
|
|
|
274
|
-
lines.append("## 摘要\n")
|
|
322
|
+
lines.append("## 摘要\n\n")
|
|
275
323
|
lines.append(f"- 错误: {total_errors}\n")
|
|
276
324
|
lines.append(f"- 警告: {total_warnings}\n")
|
|
325
|
+
lines.append(f"- 信息: {total_info}\n")
|
|
326
|
+
|
|
327
|
+
# 修复统计
|
|
328
|
+
if auto_fixer:
|
|
329
|
+
lines.append("\n### 自动修复统计\n\n")
|
|
330
|
+
if auto_fixer.fixes_applied:
|
|
331
|
+
lines.append(f"- ✅ 成功修复: {len(auto_fixer.fixes_applied)} 个\n")
|
|
332
|
+
for fix in auto_fixer.fixes_applied:
|
|
333
|
+
lines.append(f" - {fix}\n")
|
|
334
|
+
if auto_fixer.fixes_failed:
|
|
335
|
+
lines.append(f"- ❌ 修复失败: {len(auto_fixer.fixes_failed)} 个\n")
|
|
336
|
+
for fail in auto_fixer.fixes_failed:
|
|
337
|
+
lines.append(f" - {fail}\n")
|
|
338
|
+
if not auto_fixer.fixes_applied and not auto_fixer.fixes_failed:
|
|
339
|
+
lines.append("- ℹ️ 未发现可自动修复的问题\n")
|
|
340
|
+
|
|
277
341
|
lines.append("\n")
|
|
278
342
|
|
|
279
343
|
# 详细结果
|
|
@@ -307,6 +371,20 @@ def _save_markdown_report(results: list[ValidationResult], output_path: str) ->
|
|
|
307
371
|
|
|
308
372
|
lines.append("\n")
|
|
309
373
|
|
|
374
|
+
# 总结
|
|
375
|
+
lines.append("## 总结\n\n")
|
|
376
|
+
if auto_fixer and auto_fixer.fixes_applied:
|
|
377
|
+
lines.append(f"✅ 成功修复 {len(auto_fixer.fixes_applied)} 个问题\n\n")
|
|
378
|
+
if auto_fixer.fixes_failed:
|
|
379
|
+
lines.append(f"⚠️ {len(auto_fixer.fixes_failed)} 个问题修复失败\n\n")
|
|
380
|
+
|
|
381
|
+
if total_errors > 0:
|
|
382
|
+
lines.append(f"❌ 剩余 {total_errors} 个错误,{total_warnings} 个警告\n")
|
|
383
|
+
elif total_warnings > 0:
|
|
384
|
+
lines.append(f"⚠️ 剩余 {total_warnings} 个警告\n")
|
|
385
|
+
else:
|
|
386
|
+
lines.append("✅ 所有检查通过!\n")
|
|
387
|
+
|
|
310
388
|
# 写入文件
|
|
311
389
|
try:
|
|
312
390
|
with open(output_path, "w", encoding="utf-8") as f:
|
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any
|
|
7
7
|
|
|
8
|
+
import libcst as cst
|
|
8
9
|
import questionary
|
|
9
10
|
|
|
10
11
|
from mpdt.templates import prepare_component_context
|
|
12
|
+
from mpdt.utils.plugin_parser import extract_plugin_name
|
|
11
13
|
from mpdt.utils.color_printer import (
|
|
12
14
|
console,
|
|
13
15
|
print_error,
|
|
@@ -264,7 +266,7 @@ def _update_plugin_registration(
|
|
|
264
266
|
verbose: bool,
|
|
265
267
|
) -> bool:
|
|
266
268
|
"""
|
|
267
|
-
更新插件注册代码
|
|
269
|
+
更新插件注册代码 (使用 AST 解析)
|
|
268
270
|
|
|
269
271
|
Args:
|
|
270
272
|
work_dir: 工作目录
|
|
@@ -281,45 +283,30 @@ def _update_plugin_registration(
|
|
|
281
283
|
return False
|
|
282
284
|
|
|
283
285
|
try:
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
lines.insert(import_insert_index, import_line.rstrip())
|
|
309
|
-
content = "\n".join(lines)
|
|
310
|
-
|
|
311
|
-
# 在 get_plugin_components 中添加组件注册
|
|
312
|
-
# 根据组件类型生成正确的注册代码
|
|
313
|
-
registration_code = _generate_registration_code(component_type, context)
|
|
314
|
-
|
|
315
|
-
if "get_plugin_components" in content and registration_code not in content:
|
|
316
|
-
# 找到 return components 前插入注册代码
|
|
317
|
-
content = content.replace(
|
|
318
|
-
"return components",
|
|
319
|
-
f"{registration_code}\n return components"
|
|
320
|
-
)
|
|
321
|
-
|
|
322
|
-
plugin_file.write_text(content, encoding="utf-8")
|
|
286
|
+
# 使用 plugin_parser 验证插件名称
|
|
287
|
+
parsed_plugin_name = extract_plugin_name(work_dir)
|
|
288
|
+
if not parsed_plugin_name:
|
|
289
|
+
if verbose:
|
|
290
|
+
console.print("[dim]⚠ 无法解析插件名称[/dim]")
|
|
291
|
+
return False
|
|
292
|
+
|
|
293
|
+
# 读取源代码
|
|
294
|
+
source_code = plugin_file.read_text(encoding="utf-8")
|
|
295
|
+
source_tree = cst.parse_module(source_code)
|
|
296
|
+
|
|
297
|
+
# 创建转换器
|
|
298
|
+
transformer = PluginRegistrationTransformer(
|
|
299
|
+
plugin_name=parsed_plugin_name,
|
|
300
|
+
component_type=component_type,
|
|
301
|
+
component_name=component_name,
|
|
302
|
+
class_name=context["class_name"],
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
# 应用转换
|
|
306
|
+
modified_tree = source_tree.visit(transformer)
|
|
307
|
+
|
|
308
|
+
# 写回文件
|
|
309
|
+
plugin_file.write_text(modified_tree.code, encoding="utf-8")
|
|
323
310
|
|
|
324
311
|
if verbose:
|
|
325
312
|
console.print(f"[dim]✓ 更新插件注册: {plugin_file}[/dim]")
|
|
@@ -332,35 +319,111 @@ def _update_plugin_registration(
|
|
|
332
319
|
return False
|
|
333
320
|
|
|
334
321
|
|
|
335
|
-
|
|
336
|
-
"""
|
|
337
|
-
根据组件类型生成正确的注册代码
|
|
338
|
-
|
|
339
|
-
Args:
|
|
340
|
-
component_type: 组件类型
|
|
341
|
-
context: 模板上下文
|
|
342
|
-
|
|
343
|
-
Returns:
|
|
344
|
-
注册代码字符串
|
|
345
|
-
"""
|
|
346
|
-
class_name = context['class_name']
|
|
347
|
-
|
|
348
|
-
# 根据组件类型生成对应的 get_xxx_info() 方法调用
|
|
349
|
-
info_method_map = {
|
|
350
|
-
"action": "get_action_info",
|
|
351
|
-
"tool": "get_tool_info",
|
|
352
|
-
"event": "get_event_handler_info",
|
|
353
|
-
"adapter": "get_adapter_info",
|
|
354
|
-
"prompt": "get_prompt_info",
|
|
355
|
-
"plus_command": "get_command_info",
|
|
356
|
-
"chatter": "get_chatter_info",
|
|
357
|
-
"router": "get_router_info",
|
|
358
|
-
}
|
|
322
|
+
class PluginRegistrationTransformer(cst.CSTTransformer):
|
|
323
|
+
"""用于添加组件导入和注册的 CST 转换器"""
|
|
359
324
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
325
|
+
def __init__(
|
|
326
|
+
self,
|
|
327
|
+
plugin_name: str,
|
|
328
|
+
component_type: str,
|
|
329
|
+
component_name: str,
|
|
330
|
+
class_name: str,
|
|
331
|
+
):
|
|
332
|
+
self.plugin_name = plugin_name
|
|
333
|
+
self.component_type = component_type
|
|
334
|
+
self.component_name = component_name
|
|
335
|
+
self.class_name = class_name
|
|
336
|
+
self.import_added = False
|
|
337
|
+
self.registration_added = False
|
|
338
|
+
|
|
339
|
+
def leave_Module(self, original_node: cst.Module, updated_node: cst.Module) -> cst.Module:
|
|
340
|
+
"""在模块级别添加导入语句"""
|
|
341
|
+
if self.import_added:
|
|
342
|
+
return updated_node
|
|
343
|
+
|
|
344
|
+
# 构建导入语句
|
|
345
|
+
import_statement = cst.parse_statement(
|
|
346
|
+
f"from {self.plugin_name}.components.{self.component_type}s.{self.component_name} import {self.class_name}"
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
# 检查是否已存在相同的导入
|
|
350
|
+
for stmt in updated_node.body:
|
|
351
|
+
if isinstance(stmt, cst.SimpleStatementLine):
|
|
352
|
+
for s in stmt.body:
|
|
353
|
+
if isinstance(s, cst.ImportFrom) and s.module:
|
|
354
|
+
module_str = cst.Module([]).code_for_node(s.module)
|
|
355
|
+
target_module = f"{self.plugin_name}.components.{self.component_type}s.{self.component_name}"
|
|
356
|
+
if module_str == target_module:
|
|
357
|
+
self.import_added = True
|
|
358
|
+
return updated_node
|
|
359
|
+
|
|
360
|
+
# 找到最后一个导入语句的位置
|
|
361
|
+
last_import_idx = -1
|
|
362
|
+
for idx, stmt in enumerate(updated_node.body):
|
|
363
|
+
if isinstance(stmt, cst.SimpleStatementLine):
|
|
364
|
+
for s in stmt.body:
|
|
365
|
+
if isinstance(s, (cst.Import, cst.ImportFrom)):
|
|
366
|
+
last_import_idx = idx
|
|
367
|
+
|
|
368
|
+
# 在最后一个导入后添加新导入
|
|
369
|
+
if last_import_idx >= 0:
|
|
370
|
+
new_body = list(updated_node.body)
|
|
371
|
+
new_body.insert(last_import_idx + 1, import_statement)
|
|
372
|
+
self.import_added = True
|
|
373
|
+
return updated_node.with_changes(body=new_body)
|
|
374
|
+
|
|
375
|
+
return updated_node
|
|
376
|
+
|
|
377
|
+
def leave_FunctionDef(
|
|
378
|
+
self, original_node: cst.FunctionDef, updated_node: cst.FunctionDef
|
|
379
|
+
) -> cst.FunctionDef:
|
|
380
|
+
"""在 get_plugin_components 函数中添加注册代码"""
|
|
381
|
+
if updated_node.name.value != "get_plugin_components":
|
|
382
|
+
return updated_node
|
|
383
|
+
|
|
384
|
+
if self.registration_added:
|
|
385
|
+
return updated_node
|
|
386
|
+
|
|
387
|
+
# 根据组件类型生成对应的 get_xxx_info() 方法调用
|
|
388
|
+
info_method_map = {
|
|
389
|
+
"action": "get_action_info",
|
|
390
|
+
"tool": "get_tool_info",
|
|
391
|
+
"event": "get_event_handler_info",
|
|
392
|
+
"adapter": "get_adapter_info",
|
|
393
|
+
"prompt": "get_prompt_info",
|
|
394
|
+
"plus_command": "get_command_info",
|
|
395
|
+
"chatter": "get_chatter_info",
|
|
396
|
+
"router": "get_router_info",
|
|
397
|
+
}
|
|
398
|
+
info_method = info_method_map.get(self.component_type, "get_component_info")
|
|
399
|
+
|
|
400
|
+
# 构建注册代码
|
|
401
|
+
registration_code = f"""# 注册 {self.class_name}
|
|
402
|
+
components.append(({self.class_name}.{info_method}(), {self.class_name}))"""
|
|
403
|
+
|
|
404
|
+
# 检查是否已存在注册代码
|
|
405
|
+
function_code = cst.Module([]).code_for_node(updated_node)
|
|
406
|
+
if self.class_name in function_code and info_method in function_code:
|
|
407
|
+
self.registration_added = True
|
|
408
|
+
return updated_node
|
|
409
|
+
|
|
410
|
+
# 找到 return 语句并在其前面插入注册代码
|
|
411
|
+
new_body = []
|
|
412
|
+
for stmt in updated_node.body.body:
|
|
413
|
+
# 如果是 return 语句,在前面插入注册代码
|
|
414
|
+
if isinstance(stmt, cst.SimpleStatementLine):
|
|
415
|
+
for s in stmt.body:
|
|
416
|
+
if isinstance(s, cst.Return):
|
|
417
|
+
# 插入注册代码
|
|
418
|
+
for line in registration_code.split("\n"):
|
|
419
|
+
if line.strip():
|
|
420
|
+
new_body.append(cst.parse_statement(line))
|
|
421
|
+
self.registration_added = True
|
|
422
|
+
|
|
423
|
+
new_body.append(stmt)
|
|
424
|
+
|
|
425
|
+
if self.registration_added:
|
|
426
|
+
new_function_body = updated_node.body.with_changes(body=new_body)
|
|
427
|
+
return updated_node.with_changes(body=new_function_body)
|
|
428
|
+
|
|
429
|
+
return updated_node
|
|
@@ -106,12 +106,14 @@ def init_plugin(
|
|
|
106
106
|
print_tree(
|
|
107
107
|
plugin_name,
|
|
108
108
|
{
|
|
109
|
-
".gitignore":None,
|
|
109
|
+
".gitignore": None,
|
|
110
110
|
"__init__.py": None,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
plugin_name: {
|
|
112
|
+
"__init__.py": None,
|
|
113
|
+
"plugin.py": None,
|
|
114
|
+
"components": ["actions", "plus_command", "tools", "events"],
|
|
115
|
+
"utils": ["__init__.py"],
|
|
116
|
+
},
|
|
115
117
|
"docs": ["README.md"] if with_docs else [],
|
|
116
118
|
"pyproject.toml": None,
|
|
117
119
|
"requirements.txt": None,
|
|
@@ -198,17 +200,22 @@ def _create_plugin_structure(
|
|
|
198
200
|
# 创建主目录
|
|
199
201
|
ensure_dir(plugin_dir)
|
|
200
202
|
|
|
201
|
-
#
|
|
202
|
-
|
|
203
|
-
safe_write_file(plugin_dir / "__init__.py",
|
|
203
|
+
# 创建根目录下的 __init__.py (给 MoFox-Plugin-Repo读取)
|
|
204
|
+
root_init_content = _generate_init_file(plugin_name, author, license_type)
|
|
205
|
+
safe_write_file(plugin_dir / "__init__.py", root_init_content)
|
|
206
|
+
|
|
207
|
+
# 创建插件代码子目录
|
|
208
|
+
plugin_code_dir = ensure_dir(plugin_dir / plugin_name)
|
|
209
|
+
|
|
210
|
+
# 创建插件代码目录下的 __init__.py (给插件系统读取,内容与根目录的相同)
|
|
211
|
+
safe_write_file(plugin_code_dir / "__init__.py", root_init_content)
|
|
204
212
|
|
|
205
213
|
# 创建 plugin.py
|
|
206
214
|
plugin_content = _generate_plugin_file(plugin_name, template)
|
|
207
|
-
safe_write_file(
|
|
208
|
-
|
|
215
|
+
safe_write_file(plugin_code_dir / "plugin.py", plugin_content)
|
|
209
216
|
|
|
210
217
|
# 创建 components 目录
|
|
211
|
-
components_dir = ensure_dir(
|
|
218
|
+
components_dir = ensure_dir(plugin_code_dir / "components")
|
|
212
219
|
safe_write_file(components_dir / "__init__.py", '"""\n组件模块\n"""\n')
|
|
213
220
|
|
|
214
221
|
for comp_type in ["actions", "plus_command", "tools", "events"]:
|
|
@@ -216,7 +223,7 @@ def _create_plugin_structure(
|
|
|
216
223
|
safe_write_file(comp_dir / "__init__.py", f'"""\n{comp_type.title()} 组件\n"""\n')
|
|
217
224
|
|
|
218
225
|
# 创建 utils 目录
|
|
219
|
-
utils_dir = ensure_dir(
|
|
226
|
+
utils_dir = ensure_dir(plugin_code_dir / "utils")
|
|
220
227
|
safe_write_file(utils_dir / "__init__.py", '"""\n工具函数\n"""\n')
|
|
221
228
|
|
|
222
229
|
# 创建文档目录
|
|
@@ -357,7 +364,7 @@ MoFox-Bot 插件
|
|
|
357
364
|
|
|
358
365
|
## 安装
|
|
359
366
|
|
|
360
|
-
|
|
367
|
+
将{plugin_name}文件夹放入 `plugins/` 目录中。
|
|
361
368
|
|
|
362
369
|
## 配置
|
|
363
370
|
|