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.
Files changed (53) hide show
  1. {mofox_plugin_dev_toolkit-0.2.2/mofox_plugin_dev_toolkit.egg-info → mofox_plugin_dev_toolkit-0.2.7}/PKG-INFO +2 -1
  2. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7/mofox_plugin_dev_toolkit.egg-info}/PKG-INFO +2 -1
  3. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mofox_plugin_dev_toolkit.egg-info/SOURCES.txt +1 -0
  4. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mofox_plugin_dev_toolkit.egg-info/requires.txt +1 -0
  5. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/__init__.py +1 -1
  6. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/cli.py +1 -1
  7. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/check.py +91 -13
  8. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/generate.py +134 -71
  9. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/init.py +20 -13
  10. mofox_plugin_dev_toolkit-0.2.7/mpdt/utils/code_parser.py +402 -0
  11. mofox_plugin_dev_toolkit-0.2.7/mpdt/validators/auto_fix_validator.py +996 -0
  12. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/base.py +8 -0
  13. mofox_plugin_dev_toolkit-0.2.7/mpdt/validators/component_validator.py +840 -0
  14. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/config_validator.py +18 -72
  15. mofox_plugin_dev_toolkit-0.2.7/mpdt/validators/metadata_validator.py +110 -0
  16. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/type_validator.py +0 -2
  17. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/pyproject.toml +2 -1
  18. mofox_plugin_dev_toolkit-0.2.2/mpdt/validators/auto_fix_validator.py +0 -182
  19. mofox_plugin_dev_toolkit-0.2.2/mpdt/validators/component_validator.py +0 -494
  20. mofox_plugin_dev_toolkit-0.2.2/mpdt/validators/metadata_validator.py +0 -125
  21. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/LICENSE +0 -0
  22. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/MANIFEST.in +0 -0
  23. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/README.md +0 -0
  24. {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
  25. {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
  26. {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
  27. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/__main__.py +0 -0
  28. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/__init__.py +0 -0
  29. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/commands/dev.py +0 -0
  30. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/dev/bridge_plugin/__init__.py +0 -0
  31. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/dev/bridge_plugin/discovery_server.py +0 -0
  32. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/dev/bridge_plugin/plugin.py +0 -0
  33. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/__init__.py +0 -0
  34. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/action_template.py +0 -0
  35. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/adapter_template.py +0 -0
  36. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/chatter_template.py +0 -0
  37. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/event_template.py +0 -0
  38. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/plus_command_template.py +0 -0
  39. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/prompt_template.py +0 -0
  40. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/router_template.py +0 -0
  41. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/templates/tool_template.py +0 -0
  42. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/__init__.py +0 -0
  43. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/color_printer.py +0 -0
  44. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/config_loader.py +0 -0
  45. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/config_manager.py +0 -0
  46. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/file_ops.py +0 -0
  47. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/license_generator.py +0 -0
  48. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/plugin_parser.py +0 -0
  49. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/utils/template_engine.py +0 -0
  50. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/__init__.py +0 -0
  51. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/structure_validator.py +0 -0
  52. {mofox_plugin_dev_toolkit-0.2.2 → mofox_plugin_dev_toolkit-0.2.7}/mpdt/validators/style_validator.py +0 -0
  53. {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.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.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
@@ -29,6 +29,7 @@ mpdt/templates/prompt_template.py
29
29
  mpdt/templates/router_template.py
30
30
  mpdt/templates/tool_template.py
31
31
  mpdt/utils/__init__.py
32
+ mpdt/utils/code_parser.py
32
33
  mpdt/utils/color_printer.py
33
34
  mpdt/utils/config_loader.py
34
35
  mpdt/utils/config_manager.py
@@ -8,6 +8,7 @@ tomli-w>=1.0.0
8
8
  pydantic>=2.5.0
9
9
  watchdog>=3.0.0
10
10
  websockets>=12.0
11
+ libcst>=1.8.6
11
12
  aiohttp>=3.9.0
12
13
  uvicorn>=0.24.0
13
14
  fastapi>=0.104.0
@@ -4,7 +4,7 @@ MoFox Plugin Dev Toolkit
4
4
  一个用于 MoFox-Bot 插件开发的工具集
5
5
  """
6
6
 
7
- __version__ = "0.1.7"
7
+ __version__ = "0.2.7"
8
8
  __author__ = "MoFox-Studio"
9
9
  __license__ = "GPL-3.0-or-later"
10
10
 
@@ -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("mmc 路径", str(config.mmc_path) if config.mmc_path else "[red]未配置[/red]")
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.validate()
121
- all_results.append(fix_result)
122
- _print_validation_summary(fix_result, verbose)
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"发现 {total_errors} 个错误,{total_warnings} 个警告")
285
+ print_error(f"剩余 {total_errors} 个错误,{total_warnings} 个警告")
241
286
  elif total_warnings > 0:
242
- print_warning(f"发现 {total_warnings} 个警告")
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
- content = plugin_file.read_text(encoding="utf-8")
285
-
286
- # 添加 import 语句
287
- import_line = f"from {context['plugin_name']}.components.{component_type}s.{component_name} import {context['class_name']}\n"
288
-
289
- # 检查是否已导入
290
- if import_line.strip() not in content:
291
- # 找到合适的位置插入 import (在最后一个 import 之后,class 定义之前)
292
- lines = content.split("\n")
293
- import_insert_index = -1
294
- last_import_index = -1
295
-
296
- for i, line in enumerate(lines):
297
- if line.startswith("from") or line.startswith("import"):
298
- last_import_index = i
299
- elif line.startswith("class") or line.startswith("@"):
300
- # 在 class 或装饰器之前插入
301
- import_insert_index = last_import_index + 1 if last_import_index >= 0 else i
302
- break
303
-
304
- if import_insert_index > 0:
305
- # 确保插入位置后有空行
306
- if import_insert_index < len(lines) and lines[import_insert_index].strip():
307
- lines.insert(import_insert_index, "")
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
- def _generate_registration_code(component_type: str, context: dict) -> str:
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
- info_method = info_method_map.get(component_type, "get_component_info")
361
-
362
- registration = f"""
363
- # 注册 {class_name}
364
- components.append(({class_name}.{info_method}(), {class_name}))"""
365
-
366
- return registration
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
- "plugin.py": None,
112
- "config": ["config.toml"],
113
- "components": ["actions", "commands", "tools", "events"],
114
- "utils": ["__init__.py"],
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
- # 创建 __init__.py
202
- init_content = _generate_init_file(plugin_name, author, license_type)
203
- safe_write_file(plugin_dir / "__init__.py", init_content)
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(plugin_dir / "plugin.py", plugin_content)
208
-
215
+ safe_write_file(plugin_code_dir / "plugin.py", plugin_content)
209
216
 
210
217
  # 创建 components 目录
211
- components_dir = ensure_dir(plugin_dir / "components")
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(plugin_dir / "utils")
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
- 将插件目录放入 `plugins/` 目录中。
367
+ 将{plugin_name}文件夹放入 `plugins/` 目录中。
361
368
 
362
369
  ## 配置
363
370