mofox-plugin-dev-toolkit 0.3.3__py3-none-any.whl

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 (46) hide show
  1. mofox_plugin_dev_toolkit-0.3.3.dist-info/METADATA +730 -0
  2. mofox_plugin_dev_toolkit-0.3.3.dist-info/RECORD +46 -0
  3. mofox_plugin_dev_toolkit-0.3.3.dist-info/WHEEL +5 -0
  4. mofox_plugin_dev_toolkit-0.3.3.dist-info/entry_points.txt +2 -0
  5. mofox_plugin_dev_toolkit-0.3.3.dist-info/licenses/LICENSE +674 -0
  6. mofox_plugin_dev_toolkit-0.3.3.dist-info/top_level.txt +1 -0
  7. mpdt/__init__.py +15 -0
  8. mpdt/__main__.py +8 -0
  9. mpdt/cli.py +316 -0
  10. mpdt/commands/__init__.py +9 -0
  11. mpdt/commands/check.py +498 -0
  12. mpdt/commands/dev.py +318 -0
  13. mpdt/commands/generate.py +448 -0
  14. mpdt/commands/init.py +686 -0
  15. mpdt/dev/bridge_plugin/__init__.py +17 -0
  16. mpdt/dev/bridge_plugin/cleanup_handler.py +65 -0
  17. mpdt/dev/bridge_plugin/dev_config.py +24 -0
  18. mpdt/dev/bridge_plugin/file_watcher.py +169 -0
  19. mpdt/dev/bridge_plugin/plugin.py +219 -0
  20. mpdt/templates/__init__.py +165 -0
  21. mpdt/templates/action_template.py +102 -0
  22. mpdt/templates/adapter_template.py +129 -0
  23. mpdt/templates/chatter_template.py +103 -0
  24. mpdt/templates/event_template.py +116 -0
  25. mpdt/templates/plus_command_template.py +150 -0
  26. mpdt/templates/prompt_template.py +92 -0
  27. mpdt/templates/router_template.py +175 -0
  28. mpdt/templates/tool_template.py +98 -0
  29. mpdt/utils/__init__.py +10 -0
  30. mpdt/utils/code_parser.py +401 -0
  31. mpdt/utils/color_printer.py +99 -0
  32. mpdt/utils/config_loader.py +171 -0
  33. mpdt/utils/config_manager.py +297 -0
  34. mpdt/utils/file_ops.py +207 -0
  35. mpdt/utils/license_generator.py +980 -0
  36. mpdt/utils/plugin_parser.py +195 -0
  37. mpdt/utils/template_engine.py +112 -0
  38. mpdt/validators/__init__.py +26 -0
  39. mpdt/validators/auto_fix_validator.py +990 -0
  40. mpdt/validators/base.py +129 -0
  41. mpdt/validators/component_validator.py +842 -0
  42. mpdt/validators/config_validator.py +119 -0
  43. mpdt/validators/metadata_validator.py +107 -0
  44. mpdt/validators/structure_validator.py +72 -0
  45. mpdt/validators/style_validator.py +117 -0
  46. mpdt/validators/type_validator.py +206 -0
mpdt/commands/dev.py ADDED
@@ -0,0 +1,318 @@
1
+ """
2
+ mpdt dev 命令实现
3
+ 启动开发模式:注入开发插件到主程序,由开发插件负责文件监控和热重载
4
+ """
5
+
6
+ import shutil
7
+ import subprocess
8
+ from pathlib import Path
9
+
10
+ from rich.console import Console
11
+ from rich.panel import Panel
12
+
13
+ from mpdt.utils.config_manager import MPDTConfig, interactive_config
14
+ from mpdt.utils.plugin_parser import extract_plugin_name
15
+
16
+ console = Console()
17
+
18
+
19
+ class DevServer:
20
+ """开发服务器 - 注入开发插件并启动主程序"""
21
+
22
+ def __init__(self, plugin_path: Path, config: MPDTConfig, mofox_path: Path | None = None):
23
+ self.plugin_path = plugin_path.absolute()
24
+ self.config = config
25
+
26
+ resolved_path = mofox_path or config.mofox_path
27
+ if not resolved_path:
28
+ raise ValueError("未配置 mofox 主程序路径")
29
+ self.mofox_path: Path = resolved_path
30
+
31
+ self.plugin_name: str | None = None
32
+ self.process: subprocess.Popen[str] | None = None
33
+
34
+ def start(self):
35
+ """启动开发模式(同步方法)"""
36
+ try:
37
+ # 1. 解析插件名称
38
+ self._parse_plugin_info()
39
+
40
+ # 2. 注入目标开发插件
41
+ self._inject_target_plugin()
42
+
43
+ # 4. 注入 DevBridge 插件(包含配置)
44
+ self._inject_bridge_plugin()
45
+
46
+ # 5. 启动主程序
47
+ self._start_main_process()
48
+
49
+ console.print("\n[bold green]✨ 开发模式已启动![/bold green]")
50
+ console.print("[dim]主程序窗口中会显示文件监控和重载信息[/dim]")
51
+ console.print("[dim]DevBridge 插件会在主程序退出时自动清理[/dim]\n")
52
+
53
+ # 启动完成,直接退出,让插件自己管理生命周期
54
+ console.print("[green]✓ 开发服务器启动完成,此窗口将关闭[/green]")
55
+
56
+ except Exception as e:
57
+ console.print(f"[red]错误: {e}[/red]")
58
+ import traceback
59
+ traceback.print_exc()
60
+
61
+
62
+
63
+ def _parse_plugin_info(self):
64
+ """解析插件信息"""
65
+ console.print(
66
+ Panel.fit(
67
+ f"[bold cyan]🚀 MoFox Plugin Dev Server[/bold cyan]\n\n"
68
+ f"📂 目录: {self.plugin_path.name}\n"
69
+ f"📍 路径: {self.plugin_path}"
70
+ )
71
+ )
72
+
73
+ # 提取插件名称
74
+ self.plugin_name = extract_plugin_name(self.plugin_path)
75
+
76
+ if not self.plugin_name:
77
+ console.print("[red]❌ 无法读取插件名称[/red]")
78
+ console.print("\n请确保 plugin.py 中有:")
79
+ console.print("```python")
80
+ console.print("class YourPlugin(BasePlugin):")
81
+ console.print(' plugin_name = "your_plugin"')
82
+ console.print("```")
83
+ raise ValueError("无法解析插件名称")
84
+
85
+ console.print(f"[green]✓ 插件名: {self.plugin_name}[/green]")
86
+
87
+ def _inject_target_plugin(self):
88
+ """将目标插件复制到 mofox 的 plugins 目录"""
89
+ assert self.plugin_name is not None, "plugin_name 未初始化"
90
+ plugins_dir = self.mofox_path / "plugins"
91
+ target_dir = plugins_dir / self.plugin_name
92
+
93
+ # 检查插件是否已经在 plugins 目录下
94
+ if self.plugin_path.parent.resolve() == plugins_dir.resolve():
95
+ console.print("[dim]📦 插件已在 plugins 目录下,跳过复制[/dim]")
96
+ return
97
+
98
+ console.print("[cyan]📦 注入目标插件...[/cyan]")
99
+
100
+ # 如果已存在,先删除
101
+ if target_dir.exists():
102
+ shutil.rmtree(target_dir)
103
+
104
+ # 复制插件
105
+ shutil.copytree(self.plugin_path, target_dir)
106
+
107
+ console.print(f"[green]✓ 目标插件已注入: {target_dir}[/green]")
108
+
109
+ def _inject_bridge_plugin(self):
110
+ """注入 DevBridge 插件到主程序,并修改配置常量"""
111
+ console.print("[cyan]🔗 注入开发模式插件...[/cyan]")
112
+
113
+ # DevBridge 插件源路径
114
+ bridge_source = Path(__file__).parent.parent / "dev" / "bridge_plugin"
115
+
116
+ if not bridge_source.exists():
117
+ raise FileNotFoundError(f"DevBridge 插件源不存在: {bridge_source}")
118
+
119
+ # 目标路径
120
+ bridge_target = self.mofox_path / "plugins" / "dev_bridge"
121
+
122
+ # 如果已存在,先删除
123
+ if bridge_target.exists():
124
+ shutil.rmtree(bridge_target)
125
+
126
+ # 复制插件
127
+ shutil.copytree(bridge_source, bridge_target)
128
+
129
+ # 动态修改 dev_config.py 中的常量
130
+ self._update_dev_config(bridge_target)
131
+
132
+ console.print(f"[green]✓ DevBridge 插件已注入: {bridge_target}[/green]")
133
+ console.print(f"[dim] 目标插件: {self.plugin_name}[/dim]")
134
+ console.print(f"[dim] 监控路径: {self.plugin_path}[/dim]")
135
+
136
+ def _update_dev_config(self, bridge_target: Path):
137
+ """更新开发插件的配置文件"""
138
+ config_file = bridge_target / "dev_config.py"
139
+
140
+ # 生成新的配置内容
141
+ config_content = f'''"""
142
+ 开发模式配置文件
143
+ 此文件由 mpdt dev 自动生成,请勿手动修改
144
+ """
145
+
146
+ # ==================== 开发目标插件配置 ====================
147
+
148
+ # 目标插件的绝对路径
149
+ TARGET_PLUGIN_PATH: str = r"{self.plugin_path}"
150
+
151
+ # 目标插件名称
152
+ TARGET_PLUGIN_NAME: str = "{self.plugin_name}"
153
+
154
+ # 是否启用文件监控
155
+ ENABLE_FILE_WATCHER: bool = True
156
+
157
+ # 文件监控防抖延迟(秒)
158
+ DEBOUNCE_DELAY: float = 0.3
159
+
160
+ # ==================== 其他配置 ====================
161
+
162
+ # 发现服务器端口(保留,暂未使用)
163
+ DISCOVERY_PORT: int = 12318
164
+ '''
165
+
166
+ with open(config_file, "w", encoding="utf-8") as f:
167
+ f.write(config_content)
168
+
169
+ console.print("[dim] 配置已写入 dev_config.py[/dim]")
170
+
171
+
172
+
173
+ def _start_main_process(self):
174
+ """启动主程序"""
175
+ console.print(f"[cyan]🚀 启动主程序: {self.mofox_path / 'bot.py'}[/cyan]")
176
+
177
+ # 获取 Python 命令
178
+ venv_type = self.config.venv_type
179
+ venv_path = self.config.venv_path
180
+
181
+ try:
182
+ import os
183
+ import sys
184
+
185
+ # Windows 下打开新窗口
186
+ if os.name == "nt":
187
+ if venv_type in ["venv", "uv"] and venv_path:
188
+ activate_script = venv_path / "Scripts" / "activate.bat"
189
+ if activate_script.exists():
190
+ cmd = [
191
+ "cmd",
192
+ "/c",
193
+ f"chcp 65001 && cd /d {self.mofox_path} && {activate_script} && python bot.py",
194
+ ]
195
+ console.print(f"[dim]命令: 激活 {venv_type} 环境并启动[/dim]")
196
+ else:
197
+ python_cmd = self.config.get_python_command()
198
+ cmd = ["cmd", "/c", f"chcp 65001 && cd /d {self.mofox_path} && {python_cmd[0]} bot.py"]
199
+ console.print("[yellow]警告: 未找到激活脚本,使用直接启动[/yellow]")
200
+ elif venv_type == "conda" and venv_path:
201
+ cmd = [
202
+ "cmd",
203
+ "/c",
204
+ f"chcp 65001 && cd /d {self.mofox_path} && conda activate {venv_path} && python bot.py",
205
+ ]
206
+ console.print("[dim]命令: 激活 conda 环境并启动[/dim]")
207
+ elif venv_type == "poetry":
208
+ cmd = ["cmd", "/c", f"chcp 65001 && cd /d {self.mofox_path} && poetry run python bot.py"]
209
+ console.print("[dim]命令: 使用 poetry run 启动[/dim]")
210
+ else:
211
+ cmd = ["cmd", "/c", f"chcp 65001 && cd /d {self.mofox_path} && python bot.py"]
212
+ console.print("[dim]命令: 使用系统 Python 启动[/dim]")
213
+
214
+ self.process = subprocess.Popen(
215
+ cmd, creationflags=subprocess.CREATE_NEW_CONSOLE, encoding="utf-8", errors="ignore"
216
+ )
217
+ else:
218
+ # Linux/Mac
219
+ if venv_type in ["venv", "uv"] and venv_path:
220
+ activate_script = venv_path / "bin" / "activate"
221
+ if activate_script.exists():
222
+ shell_cmd = f"cd {self.mofox_path} && source {activate_script} && python bot.py"
223
+ else:
224
+ python_cmd = self.config.get_python_command()
225
+ shell_cmd = f"cd {self.mofox_path} && {python_cmd[0]} bot.py"
226
+ console.print("[yellow]警告: 未找到激活脚本,使用直接启动[/yellow]")
227
+ console.print(f"[dim]命令: 激活 {venv_type} 环境并启动[/dim]")
228
+ elif venv_type == "conda" and venv_path:
229
+ shell_cmd = f"cd {self.mofox_path} && conda activate {venv_path} && python bot.py"
230
+ console.print("[dim]命令: 激活 conda 环境并启动[/dim]")
231
+ elif venv_type == "poetry":
232
+ shell_cmd = f"cd {self.mofox_path} && poetry run python bot.py"
233
+ console.print("[dim]命令: 使用 poetry run 启动[/dim]")
234
+ else:
235
+ shell_cmd = f"cd {self.mofox_path} && python bot.py"
236
+ console.print("[dim]命令: 使用系统 Python 启动[/dim]")
237
+
238
+ if sys.platform == "darwin":
239
+ cmd = ["osascript", "-e", f'tell application "Terminal" to do script "{shell_cmd}"']
240
+ else:
241
+ terminals = [
242
+ ("gnome-terminal", ["gnome-terminal", "--", "bash", "-c", shell_cmd]),
243
+ ("konsole", ["konsole", "-e", "bash", "-c", shell_cmd]),
244
+ ("xfce4-terminal", ["xfce4-terminal", "-e", f"bash -c '{shell_cmd}'"]),
245
+ ("xterm", ["xterm", "-e", f"bash -c '{shell_cmd}'"]),
246
+ ]
247
+
248
+ cmd = None
249
+ for term_name, term_cmd in terminals:
250
+ if (
251
+ subprocess.run(
252
+ ["which", term_name], capture_output=True, encoding="utf-8", errors="ignore"
253
+ ).returncode
254
+ == 0
255
+ ):
256
+ cmd = term_cmd
257
+ break
258
+
259
+ if cmd is None:
260
+ console.print("[yellow]警告: 未找到支持的终端模拟器,使用后台启动[/yellow]")
261
+ cmd = ["bash", "-c", shell_cmd]
262
+ self.process = subprocess.Popen(
263
+ cmd,
264
+ stdout=subprocess.PIPE,
265
+ stderr=subprocess.PIPE,
266
+ text=True,
267
+ encoding="utf-8",
268
+ errors="ignore",
269
+ )
270
+ console.print("[green]✓ 主程序已启动(后台)[/green]")
271
+ return
272
+
273
+ self.process = subprocess.Popen(cmd, encoding="utf-8", errors="ignore")
274
+ console.print("[green]✓ 主程序已启动(新窗口)[/green]")
275
+ except Exception as e:
276
+ raise RuntimeError(f"启动主程序失败: {e}")
277
+
278
+
279
+
280
+
281
+ def dev_command(
282
+ plugin_path: Path | None = None,
283
+ mofox_path: Path | None = None,
284
+ ):
285
+ """启动开发模式
286
+
287
+ Args:
288
+ plugin_path: 插件路径,默认为当前目录
289
+ mofox_path: mmc 主程序路径,默认从配置读取
290
+ """
291
+ # 确定插件路径
292
+ if plugin_path is None:
293
+ plugin_path = Path.cwd()
294
+
295
+ # 加载配置
296
+ config = MPDTConfig()
297
+
298
+ # 如果未配置,运行配置向导
299
+ if not config.is_configured() and mofox_path is None:
300
+ console.print("[yellow]未找到配置,启动配置向导...[/yellow]\n")
301
+ config = interactive_config()
302
+
303
+ # 如果提供了 mofox_path,使用它
304
+ if mofox_path:
305
+ config.mofox_path = mofox_path
306
+
307
+ # 验证配置
308
+ valid, errors = config.validate()
309
+ if not valid:
310
+ console.print("[red]配置验证失败:[/red]")
311
+ for error in errors:
312
+ console.print(f" - {error}")
313
+ console.print("\n请运行 [cyan]mpdt config init[/cyan] 重新配置")
314
+ return
315
+
316
+ # 创建并启动开发服务器(同步方法)
317
+ server = DevServer(plugin_path, config, mofox_path)
318
+ server.start()