mofox-plugin-dev-toolkit 0.3.3__tar.gz → 0.4.1__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.3.3/mofox_plugin_dev_toolkit.egg-info → mofox_plugin_dev_toolkit-0.4.1}/PKG-INFO +1 -1
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1/mofox_plugin_dev_toolkit.egg-info}/PKG-INFO +1 -1
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/SOURCES.txt +3 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/__init__.py +1 -1
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/cli.py +1 -1
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/generate.py +278 -64
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/init.py +310 -133
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/templates/__init__.py +20 -24
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/action_template.py +64 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/adapter_template.py +127 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/chatter_template.py +115 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/collection_template.py +104 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/config_template.py +57 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/event_template.py +101 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/plus_command_template.py +92 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/router_template.py +114 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/service_template.py +105 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/templates/tool_template.py +90 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/code_parser.py +94 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/config_loader.py +11 -11
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/config_manager.py +9 -16
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/file_ops.py +25 -22
- mofox_plugin_dev_toolkit-0.4.1/mpdt/utils/plugin_parser.py +137 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/auto_fix_validator.py +266 -150
- mofox_plugin_dev_toolkit-0.4.1/mpdt/validators/component_validator.py +1026 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/validators/config_validator.py +320 -0
- mofox_plugin_dev_toolkit-0.4.1/mpdt/validators/metadata_validator.py +169 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/structure_validator.py +1 -1
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/pyproject.toml +1 -1
- mofox_plugin_dev_toolkit-0.3.3/mpdt/templates/action_template.py +0 -102
- mofox_plugin_dev_toolkit-0.3.3/mpdt/templates/adapter_template.py +0 -129
- mofox_plugin_dev_toolkit-0.3.3/mpdt/templates/chatter_template.py +0 -103
- mofox_plugin_dev_toolkit-0.3.3/mpdt/templates/event_template.py +0 -116
- mofox_plugin_dev_toolkit-0.3.3/mpdt/templates/plus_command_template.py +0 -150
- mofox_plugin_dev_toolkit-0.3.3/mpdt/templates/router_template.py +0 -175
- mofox_plugin_dev_toolkit-0.3.3/mpdt/templates/tool_template.py +0 -98
- mofox_plugin_dev_toolkit-0.3.3/mpdt/utils/plugin_parser.py +0 -195
- mofox_plugin_dev_toolkit-0.3.3/mpdt/validators/component_validator.py +0 -842
- mofox_plugin_dev_toolkit-0.3.3/mpdt/validators/config_validator.py +0 -119
- mofox_plugin_dev_toolkit-0.3.3/mpdt/validators/metadata_validator.py +0 -107
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/LICENSE +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/MANIFEST.in +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/README.md +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/dependency_links.txt +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/entry_points.txt +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/requires.txt +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/top_level.txt +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/__main__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/check.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/dev.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/cleanup_handler.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/dev_config.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/file_watcher.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/plugin.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/templates/prompt_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/color_printer.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/license_generator.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/template_engine.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/base.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/style_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/type_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.3 → mofox_plugin_dev_toolkit-0.4.1}/setup.cfg +0 -0
|
@@ -25,10 +25,13 @@ mpdt/templates/__init__.py
|
|
|
25
25
|
mpdt/templates/action_template.py
|
|
26
26
|
mpdt/templates/adapter_template.py
|
|
27
27
|
mpdt/templates/chatter_template.py
|
|
28
|
+
mpdt/templates/collection_template.py
|
|
29
|
+
mpdt/templates/config_template.py
|
|
28
30
|
mpdt/templates/event_template.py
|
|
29
31
|
mpdt/templates/plus_command_template.py
|
|
30
32
|
mpdt/templates/prompt_template.py
|
|
31
33
|
mpdt/templates/router_template.py
|
|
34
|
+
mpdt/templates/service_template.py
|
|
32
35
|
mpdt/templates/tool_template.py
|
|
33
36
|
mpdt/utils/__init__.py
|
|
34
37
|
mpdt/utils/code_parser.py
|
|
@@ -67,7 +67,7 @@ def init(ctx: click.Context, plugin_name: str | None, template: str, author: str
|
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
@cli.command()
|
|
70
|
-
@click.argument("component_type", type=click.Choice(["action", "tool", "event", "adapter", "
|
|
70
|
+
@click.argument("component_type", type=click.Choice(["action", "tool", "event", "adapter", "plus-command", "router", "chatter", "service", "config"]), required=False)
|
|
71
71
|
@click.argument("component_name", required=False)
|
|
72
72
|
@click.option("--description", "-d", help="组件描述")
|
|
73
73
|
@click.option("--output", "-o", type=click.Path(), help="输出目录")
|
|
@@ -9,7 +9,6 @@ import libcst as cst
|
|
|
9
9
|
import questionary
|
|
10
10
|
|
|
11
11
|
from mpdt.templates import prepare_component_context
|
|
12
|
-
from mpdt.utils.code_parser import CodeParser
|
|
13
12
|
from mpdt.utils.color_printer import (
|
|
14
13
|
console,
|
|
15
14
|
print_error,
|
|
@@ -24,7 +23,43 @@ from mpdt.utils.file_ops import (
|
|
|
24
23
|
to_snake_case,
|
|
25
24
|
validate_component_name,
|
|
26
25
|
)
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
# =============================================================================
|
|
28
|
+
# 常量定义
|
|
29
|
+
# =============================================================================
|
|
30
|
+
|
|
31
|
+
# 组件类型到目录名的映射(统一管理)
|
|
32
|
+
COMPONENT_DIR_MAP = {
|
|
33
|
+
"action": "actions",
|
|
34
|
+
"tool": "tools",
|
|
35
|
+
"plus_command": "plus_command",
|
|
36
|
+
"event": "events",
|
|
37
|
+
"adapter": "adapters",
|
|
38
|
+
"chatter": "chatters",
|
|
39
|
+
"router": "routers",
|
|
40
|
+
"service": "services",
|
|
41
|
+
"config": "configs",
|
|
42
|
+
"collection": "collections",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# 组件类型到模板 key 的映射
|
|
46
|
+
COMPONENT_TYPE_MAP = {
|
|
47
|
+
"action": "action",
|
|
48
|
+
"tool": "tool",
|
|
49
|
+
"event": "event",
|
|
50
|
+
"adapter": "adapter",
|
|
51
|
+
"plus_command": "plus_command",
|
|
52
|
+
"chatter": "chatter",
|
|
53
|
+
"router": "router",
|
|
54
|
+
"service": "service",
|
|
55
|
+
"config": "config",
|
|
56
|
+
"collection": "collection",
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# =============================================================================
|
|
61
|
+
# 主入口函数
|
|
62
|
+
# =============================================================================
|
|
28
63
|
|
|
29
64
|
|
|
30
65
|
def generate_component(
|
|
@@ -97,7 +132,6 @@ def generate_component(
|
|
|
97
132
|
plugin_name=plugin_name,
|
|
98
133
|
author=git_info.get("name", ""),
|
|
99
134
|
description=description or f"{component_name} 组件",
|
|
100
|
-
is_async=True, # 始终生成异步方法
|
|
101
135
|
)
|
|
102
136
|
|
|
103
137
|
# 生成组件文件
|
|
@@ -136,6 +170,11 @@ def generate_component(
|
|
|
136
170
|
console.print(" 3. 运行 mpdt test 测试功能")
|
|
137
171
|
|
|
138
172
|
|
|
173
|
+
# =============================================================================
|
|
174
|
+
# 交互式界面
|
|
175
|
+
# =============================================================================
|
|
176
|
+
|
|
177
|
+
|
|
139
178
|
def _interactive_generate() -> dict[str, Any]:
|
|
140
179
|
"""交互式生成组件"""
|
|
141
180
|
console.print("\n[bold cyan]🔧 组件生成向导[/bold cyan]\n")
|
|
@@ -146,12 +185,14 @@ def _interactive_generate() -> dict[str, Any]:
|
|
|
146
185
|
choices=[
|
|
147
186
|
questionary.Choice("Action 组件", value="action"),
|
|
148
187
|
questionary.Choice("Tool 组件", value="tool"),
|
|
188
|
+
questionary.Choice("Collection 集合", value="collection"),
|
|
149
189
|
questionary.Choice("Event 事件", value="event"),
|
|
150
190
|
questionary.Choice("Adapter 适配器", value="adapter"),
|
|
151
|
-
questionary.Choice("Prompt 提示词", value="prompt"),
|
|
152
191
|
questionary.Choice("Plus Command 命令", value="plus-command"),
|
|
153
192
|
questionary.Choice("Chatter 聊天组件", value="chatter"),
|
|
154
193
|
questionary.Choice("Router 路由组件", value="router"),
|
|
194
|
+
questionary.Choice("Service 服务", value="service"),
|
|
195
|
+
questionary.Choice("Config 配置", value="config"),
|
|
155
196
|
],
|
|
156
197
|
),
|
|
157
198
|
component_name=questionary.text(
|
|
@@ -178,6 +219,11 @@ def _interactive_generate() -> dict[str, Any]:
|
|
|
178
219
|
return answers
|
|
179
220
|
|
|
180
221
|
|
|
222
|
+
# =============================================================================
|
|
223
|
+
# 插件检测
|
|
224
|
+
# =============================================================================
|
|
225
|
+
|
|
226
|
+
|
|
181
227
|
def _detect_plugin_name(work_dir: Path) -> str | None:
|
|
182
228
|
"""
|
|
183
229
|
检测插件名称
|
|
@@ -201,6 +247,11 @@ def _detect_plugin_name(work_dir: Path) -> str | None:
|
|
|
201
247
|
return work_dir.name
|
|
202
248
|
|
|
203
249
|
|
|
250
|
+
# =============================================================================
|
|
251
|
+
# 组件文件生成
|
|
252
|
+
# =============================================================================
|
|
253
|
+
|
|
254
|
+
|
|
204
255
|
def _generate_component_file(
|
|
205
256
|
work_dir: Path,
|
|
206
257
|
component_type: str,
|
|
@@ -227,13 +278,14 @@ def _generate_component_file(
|
|
|
227
278
|
"""
|
|
228
279
|
# 确定组件目录
|
|
229
280
|
if use_components_folder:
|
|
230
|
-
|
|
281
|
+
dir_name = COMPONENT_DIR_MAP.get(component_type, f"{component_type}s")
|
|
282
|
+
component_dir = work_dir / "components" / dir_name
|
|
231
283
|
ensure_dir(component_dir)
|
|
232
284
|
|
|
233
285
|
# 确保 __init__.py 存在
|
|
234
286
|
init_file = component_dir / "__init__.py"
|
|
235
287
|
if not init_file.exists():
|
|
236
|
-
safe_write_file(init_file, f'"""\n{
|
|
288
|
+
safe_write_file(init_file, f'"""\n{dir_name.title()} 组件\n"""\n')
|
|
237
289
|
else:
|
|
238
290
|
# 在插件根目录生成
|
|
239
291
|
component_dir = work_dir
|
|
@@ -241,24 +293,14 @@ def _generate_component_file(
|
|
|
241
293
|
# 生成组件文件
|
|
242
294
|
component_file = component_dir / f"{component_name}.py"
|
|
243
295
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
type_map = {
|
|
247
|
-
"action": "action",
|
|
248
|
-
"tool": "tool",
|
|
249
|
-
"event": "event",
|
|
250
|
-
"adapter": "adapter",
|
|
251
|
-
"prompt": "prompt",
|
|
252
|
-
"plus_command": "plus_command",
|
|
253
|
-
"chatter":"chatter",
|
|
254
|
-
"router":"router"
|
|
255
|
-
}
|
|
256
|
-
template_key = type_map.get(component_type)
|
|
296
|
+
# 获取模板 key
|
|
297
|
+
template_key = COMPONENT_TYPE_MAP.get(component_type)
|
|
257
298
|
if not template_key:
|
|
258
299
|
print_error(f"不支持的组件类型: {component_type}")
|
|
259
300
|
return None
|
|
260
301
|
|
|
261
302
|
from mpdt.templates import get_component_template
|
|
303
|
+
|
|
262
304
|
template = get_component_template(template_key)
|
|
263
305
|
content = template.format(**context)
|
|
264
306
|
|
|
@@ -276,7 +318,70 @@ def _generate_component_file(
|
|
|
276
318
|
return None
|
|
277
319
|
|
|
278
320
|
|
|
279
|
-
|
|
321
|
+
# =============================================================================
|
|
322
|
+
# 插件注册更新
|
|
323
|
+
# =============================================================================
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def _update_manifest_json(
|
|
327
|
+
work_dir: Path,
|
|
328
|
+
component_type: str,
|
|
329
|
+
component_name: str,
|
|
330
|
+
verbose: bool,
|
|
331
|
+
) -> bool:
|
|
332
|
+
"""
|
|
333
|
+
更新 manifest.json 文件,添加新组件
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
work_dir: 工作目录
|
|
337
|
+
component_type: 组件类型
|
|
338
|
+
component_name: 组件名称
|
|
339
|
+
verbose: 详细输出
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
是否更新成功
|
|
343
|
+
"""
|
|
344
|
+
import json
|
|
345
|
+
|
|
346
|
+
manifest_file = work_dir / "manifest.json"
|
|
347
|
+
if not manifest_file.exists():
|
|
348
|
+
if verbose:
|
|
349
|
+
console.print("[dim yellow]⚠ 未找到 manifest.json 文件[/dim yellow]")
|
|
350
|
+
return False
|
|
351
|
+
|
|
352
|
+
try:
|
|
353
|
+
# 读取现有 manifest
|
|
354
|
+
with open(manifest_file, encoding="utf-8") as f:
|
|
355
|
+
manifest = json.load(f)
|
|
356
|
+
|
|
357
|
+
# 检查组件是否已存在
|
|
358
|
+
include_list = manifest.get("include", [])
|
|
359
|
+
for item in include_list:
|
|
360
|
+
if item.get("component_name") == component_name and item.get("component_type") == component_type:
|
|
361
|
+
if verbose:
|
|
362
|
+
console.print(f"[dim]组件 {component_name} 已在 manifest.json 中[/dim]")
|
|
363
|
+
return True
|
|
364
|
+
|
|
365
|
+
# 添加新组件
|
|
366
|
+
new_component = {"component_type": component_type, "component_name": component_name, "dependencies": []}
|
|
367
|
+
include_list.append(new_component)
|
|
368
|
+
manifest["include"] = include_list
|
|
369
|
+
|
|
370
|
+
# 写回文件
|
|
371
|
+
with open(manifest_file, "w", encoding="utf-8") as f:
|
|
372
|
+
json.dump(manifest, f, ensure_ascii=False, indent=4)
|
|
373
|
+
|
|
374
|
+
if verbose:
|
|
375
|
+
console.print("[dim]✓ 已更新 manifest.json[/dim]")
|
|
376
|
+
return True
|
|
377
|
+
|
|
378
|
+
except Exception as e:
|
|
379
|
+
if verbose:
|
|
380
|
+
console.print(f"[dim red]更新 manifest.json 失败: {e}[/dim red]")
|
|
381
|
+
return False
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def _update_plugin_py_components(
|
|
280
385
|
work_dir: Path,
|
|
281
386
|
component_type: str,
|
|
282
387
|
component_name: str,
|
|
@@ -285,7 +390,7 @@ def _update_plugin_registration(
|
|
|
285
390
|
use_components_folder: bool = True,
|
|
286
391
|
) -> bool:
|
|
287
392
|
"""
|
|
288
|
-
|
|
393
|
+
更新 plugin.py 中的 get_components() 方法,添加组件导入和类引用
|
|
289
394
|
|
|
290
395
|
Args:
|
|
291
396
|
work_dir: 工作目录
|
|
@@ -303,6 +408,8 @@ def _update_plugin_registration(
|
|
|
303
408
|
return False
|
|
304
409
|
|
|
305
410
|
try:
|
|
411
|
+
from mpdt.utils.plugin_parser import extract_plugin_name
|
|
412
|
+
|
|
306
413
|
# 使用 plugin_parser 验证插件名称
|
|
307
414
|
parsed_plugin_name = extract_plugin_name(work_dir)
|
|
308
415
|
if not parsed_plugin_name:
|
|
@@ -310,10 +417,12 @@ def _update_plugin_registration(
|
|
|
310
417
|
parsed_plugin_name = work_dir.name
|
|
311
418
|
|
|
312
419
|
# 使用 CodeParser 读取和解析源代码
|
|
420
|
+
from mpdt.utils.code_parser import CodeParser
|
|
421
|
+
|
|
313
422
|
parser = CodeParser.from_file(plugin_file)
|
|
314
423
|
|
|
315
424
|
# 创建转换器
|
|
316
|
-
transformer =
|
|
425
|
+
transformer = ComponentImportTransformer(
|
|
317
426
|
plugin_name=parsed_plugin_name,
|
|
318
427
|
component_type=component_type,
|
|
319
428
|
component_name=component_name,
|
|
@@ -327,14 +436,67 @@ def _update_plugin_registration(
|
|
|
327
436
|
# 写回文件
|
|
328
437
|
plugin_file.write_text(modified_tree.code, encoding="utf-8")
|
|
329
438
|
|
|
330
|
-
|
|
439
|
+
if verbose:
|
|
440
|
+
console.print("[dim]✓ 已更新 plugin.py[/dim]")
|
|
441
|
+
|
|
442
|
+
return transformer.import_added or transformer.component_added
|
|
331
443
|
|
|
332
|
-
except Exception:
|
|
444
|
+
except Exception as e:
|
|
445
|
+
if verbose:
|
|
446
|
+
console.print(f"[dim red]更新 plugin.py 失败: {e}[/dim red]")
|
|
333
447
|
return False
|
|
334
448
|
|
|
335
449
|
|
|
336
|
-
|
|
337
|
-
|
|
450
|
+
def _update_plugin_registration(
|
|
451
|
+
work_dir: Path,
|
|
452
|
+
component_type: str,
|
|
453
|
+
component_name: str,
|
|
454
|
+
context: dict,
|
|
455
|
+
verbose: bool,
|
|
456
|
+
use_components_folder: bool = True,
|
|
457
|
+
) -> bool:
|
|
458
|
+
"""
|
|
459
|
+
更新插件注册代码(Neo-MoFox 架构)
|
|
460
|
+
|
|
461
|
+
更新两个文件:
|
|
462
|
+
1. manifest.json - 添加组件声明
|
|
463
|
+
2. plugin.py - 添加组件导入和 get_components() 返回列表
|
|
464
|
+
|
|
465
|
+
Args:
|
|
466
|
+
work_dir: 工作目录
|
|
467
|
+
component_type: 组件类型
|
|
468
|
+
component_name: 组件名称
|
|
469
|
+
context: 模板上下文
|
|
470
|
+
verbose: 详细输出
|
|
471
|
+
use_components_folder: 是否使用 components 文件夹
|
|
472
|
+
|
|
473
|
+
Returns:
|
|
474
|
+
是否更新成功
|
|
475
|
+
"""
|
|
476
|
+
# 更新 manifest.json
|
|
477
|
+
manifest_updated = _update_manifest_json(work_dir, component_type, component_name, verbose)
|
|
478
|
+
|
|
479
|
+
# 更新 plugin.py
|
|
480
|
+
plugin_updated = _update_plugin_py_components(
|
|
481
|
+
work_dir, component_type, component_name, context, verbose, use_components_folder
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
return manifest_updated or plugin_updated
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
# =============================================================================
|
|
488
|
+
# CST 代码转换器
|
|
489
|
+
# =============================================================================
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
class ComponentImportTransformer(cst.CSTTransformer):
|
|
493
|
+
"""用于添加组件导入和更新插件类的 CST 转换器(Neo-MoFox 架构)
|
|
494
|
+
|
|
495
|
+
功能:
|
|
496
|
+
1. 添加组件导入语句
|
|
497
|
+
2. 对于 config 组件:更新 configs 类属性
|
|
498
|
+
3. 对于其他组件:更新 get_components() 方法返回列表
|
|
499
|
+
"""
|
|
338
500
|
|
|
339
501
|
def __init__(
|
|
340
502
|
self,
|
|
@@ -350,7 +512,8 @@ class PluginRegistrationTransformer(cst.CSTTransformer):
|
|
|
350
512
|
self.class_name = class_name
|
|
351
513
|
self.use_components_folder = use_components_folder
|
|
352
514
|
self.import_added = False
|
|
353
|
-
self.
|
|
515
|
+
self.component_added = False
|
|
516
|
+
self.is_config = component_type == "config"
|
|
354
517
|
|
|
355
518
|
def leave_Module( # noqa: N802
|
|
356
519
|
self, original_node: cst.Module, updated_node: cst.Module
|
|
@@ -361,13 +524,12 @@ class PluginRegistrationTransformer(cst.CSTTransformer):
|
|
|
361
524
|
|
|
362
525
|
# 根据存放位置构建导入语句
|
|
363
526
|
if self.use_components_folder:
|
|
364
|
-
|
|
527
|
+
dir_name = COMPONENT_DIR_MAP.get(self.component_type, f"{self.component_type}s")
|
|
528
|
+
import_path = f"{self.plugin_name}.components.{dir_name}.{self.component_name}"
|
|
365
529
|
else:
|
|
366
530
|
import_path = f"{self.plugin_name}.{self.component_name}"
|
|
367
531
|
|
|
368
|
-
import_statement = cst.parse_statement(
|
|
369
|
-
f"from {import_path} import {self.class_name}"
|
|
370
|
-
)
|
|
532
|
+
import_statement = cst.parse_statement(f"from {import_path} import {self.class_name}")
|
|
371
533
|
|
|
372
534
|
# 检查是否已存在相同的导入
|
|
373
535
|
for stmt in updated_node.body:
|
|
@@ -396,52 +558,104 @@ class PluginRegistrationTransformer(cst.CSTTransformer):
|
|
|
396
558
|
|
|
397
559
|
return updated_node
|
|
398
560
|
|
|
561
|
+
def leave_ClassDef( # noqa: N802
|
|
562
|
+
self, original_node: cst.ClassDef, updated_node: cst.ClassDef
|
|
563
|
+
) -> cst.ClassDef:
|
|
564
|
+
"""更新插件类的 config 类属性(仅用于 config 组件)"""
|
|
565
|
+
# 只有 config 组件才需要更新 config 类属性
|
|
566
|
+
if not self.is_config:
|
|
567
|
+
return updated_node
|
|
568
|
+
|
|
569
|
+
if self.component_added:
|
|
570
|
+
return updated_node
|
|
571
|
+
|
|
572
|
+
# 检查是否已存在 config 属性
|
|
573
|
+
new_body = []
|
|
574
|
+
config_found = False
|
|
575
|
+
|
|
576
|
+
for stmt in updated_node.body.body:
|
|
577
|
+
# 查找 config 类属性定义
|
|
578
|
+
if isinstance(stmt, cst.SimpleStatementLine):
|
|
579
|
+
for assign in stmt.body:
|
|
580
|
+
if isinstance(assign, cst.AnnAssign) and isinstance(assign.target, cst.Name):
|
|
581
|
+
if assign.target.value == "config":
|
|
582
|
+
config_found = True
|
|
583
|
+
# 检查是否已包含当前配置类
|
|
584
|
+
if assign.value and isinstance(assign.value, cst.List):
|
|
585
|
+
existing_elements = list(assign.value.elements)
|
|
586
|
+
# 检查是否已存在
|
|
587
|
+
has_class = any(
|
|
588
|
+
isinstance(elem.value, cst.Name) and elem.value.value == self.class_name
|
|
589
|
+
for elem in existing_elements
|
|
590
|
+
)
|
|
591
|
+
if not has_class:
|
|
592
|
+
# 添加新配置类
|
|
593
|
+
new_element = cst.Element(value=cst.Name(self.class_name))
|
|
594
|
+
existing_elements.append(new_element)
|
|
595
|
+
new_list = assign.value.with_changes(elements=existing_elements)
|
|
596
|
+
new_assign = assign.with_changes(value=new_list)
|
|
597
|
+
new_stmt_body = [new_assign if s is assign else s for s in stmt.body]
|
|
598
|
+
stmt = stmt.with_changes(body=new_stmt_body)
|
|
599
|
+
self.component_added = True
|
|
600
|
+
else:
|
|
601
|
+
# 已存在,标记为已添加
|
|
602
|
+
self.component_added = True
|
|
603
|
+
new_body.append(stmt)
|
|
604
|
+
|
|
605
|
+
# 如果找到 config 属性(无论是否更新)
|
|
606
|
+
if config_found:
|
|
607
|
+
if self.component_added:
|
|
608
|
+
return updated_node.with_changes(body=updated_node.body.with_changes(body=new_body))
|
|
609
|
+
else:
|
|
610
|
+
# 找到了 config 但没有更新,说明已存在
|
|
611
|
+
self.component_added = True
|
|
612
|
+
|
|
613
|
+
return updated_node
|
|
614
|
+
|
|
399
615
|
def leave_FunctionDef( # noqa: N802
|
|
400
616
|
self, original_node: cst.FunctionDef, updated_node: cst.FunctionDef
|
|
401
617
|
) -> cst.FunctionDef:
|
|
402
|
-
"""在
|
|
403
|
-
|
|
618
|
+
"""在 get_components 函数中添加组件类引用(不包括 config 组件)"""
|
|
619
|
+
# config 组件在 configs 类属性中处理,不需要在 get_components 中添加
|
|
620
|
+
if self.is_config:
|
|
404
621
|
return updated_node
|
|
405
|
-
|
|
406
|
-
if self.registration_added:
|
|
622
|
+
if updated_node.name.value != "get_components":
|
|
407
623
|
return updated_node
|
|
408
624
|
|
|
409
|
-
|
|
410
|
-
info_method_map = {
|
|
411
|
-
"action": "get_action_info",
|
|
412
|
-
"tool": "get_tool_info",
|
|
413
|
-
"event": "get_event_handler_info",
|
|
414
|
-
"adapter": "get_adapter_info",
|
|
415
|
-
"prompt": "get_prompt_info",
|
|
416
|
-
"plus_command": "get_command_info",
|
|
417
|
-
"chatter": "get_chatter_info",
|
|
418
|
-
"router": "get_router_info",
|
|
419
|
-
}
|
|
420
|
-
info_method = info_method_map.get(self.component_type, "get_component_info")
|
|
421
|
-
|
|
422
|
-
# 构建注册代码(带注释的语句)
|
|
423
|
-
registration_stmt = f"components.append(({self.class_name}.{info_method}(), {self.class_name})) # 注册 {self.class_name}"
|
|
424
|
-
|
|
425
|
-
# 检查是否已存在注册代码
|
|
426
|
-
function_code = cst.Module([]).code_for_node(updated_node)
|
|
427
|
-
if self.class_name in function_code and info_method in function_code:
|
|
428
|
-
self.registration_added = True
|
|
625
|
+
if self.component_added:
|
|
429
626
|
return updated_node
|
|
430
627
|
|
|
431
|
-
# 找到 return
|
|
628
|
+
# 找到 return 语句并修改其返回列表
|
|
432
629
|
new_body = []
|
|
433
630
|
for stmt in updated_node.body.body:
|
|
434
|
-
# 如果是 return 语句,在前面插入注册代码
|
|
435
631
|
if isinstance(stmt, cst.SimpleStatementLine):
|
|
436
|
-
for s in stmt.body:
|
|
437
|
-
if isinstance(s, cst.Return):
|
|
438
|
-
#
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
632
|
+
for i, s in enumerate(stmt.body):
|
|
633
|
+
if isinstance(s, cst.Return) and s.value:
|
|
634
|
+
# 尝试解析返回值
|
|
635
|
+
if isinstance(s.value, cst.List):
|
|
636
|
+
# 检查是否已存在该组件
|
|
637
|
+
existing_elements = list(s.value.elements)
|
|
638
|
+
has_component = any(
|
|
639
|
+
isinstance(elem.value, cst.Name) and elem.value.value == self.class_name
|
|
640
|
+
for elem in existing_elements
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
if has_component:
|
|
644
|
+
self.component_added = True
|
|
645
|
+
return updated_node
|
|
646
|
+
|
|
647
|
+
# 如果是列表,添加新组件
|
|
648
|
+
new_element = cst.Element(value=cst.Name(self.class_name))
|
|
649
|
+
existing_elements.append(new_element)
|
|
650
|
+
new_list = s.value.with_changes(elements=existing_elements)
|
|
651
|
+
new_return = s.with_changes(value=new_list)
|
|
652
|
+
new_stmt_body = list(stmt.body)
|
|
653
|
+
new_stmt_body[i] = new_return
|
|
654
|
+
stmt = stmt.with_changes(body=new_stmt_body)
|
|
655
|
+
self.component_added = True
|
|
442
656
|
new_body.append(stmt)
|
|
443
657
|
|
|
444
|
-
if self.
|
|
658
|
+
if self.component_added:
|
|
445
659
|
new_function_body = updated_node.body.with_changes(body=new_body)
|
|
446
660
|
return updated_node.with_changes(body=new_function_body)
|
|
447
661
|
|