mofox-plugin-dev-toolkit 0.3.5__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.5/mofox_plugin_dev_toolkit.egg-info → mofox_plugin_dev_toolkit-0.4.1}/PKG-INFO +1 -1
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1/mofox_plugin_dev_toolkit.egg-info}/PKG-INFO +1 -1
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/SOURCES.txt +3 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/__init__.py +1 -1
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/cli.py +1 -1
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/generate.py +278 -63
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/init.py +310 -132
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/templates/__init__.py +18 -21
- 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.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/code_parser.py +94 -0
- {mofox_plugin_dev_toolkit-0.3.5 → 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.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/structure_validator.py +1 -1
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/pyproject.toml +1 -1
- mofox_plugin_dev_toolkit-0.3.5/mpdt/templates/action_template.py +0 -102
- mofox_plugin_dev_toolkit-0.3.5/mpdt/templates/adapter_template.py +0 -129
- mofox_plugin_dev_toolkit-0.3.5/mpdt/templates/chatter_template.py +0 -103
- mofox_plugin_dev_toolkit-0.3.5/mpdt/templates/event_template.py +0 -116
- mofox_plugin_dev_toolkit-0.3.5/mpdt/templates/plus_command_template.py +0 -150
- mofox_plugin_dev_toolkit-0.3.5/mpdt/templates/router_template.py +0 -175
- mofox_plugin_dev_toolkit-0.3.5/mpdt/templates/tool_template.py +0 -98
- mofox_plugin_dev_toolkit-0.3.5/mpdt/validators/component_validator.py +0 -842
- mofox_plugin_dev_toolkit-0.3.5/mpdt/validators/config_validator.py +0 -119
- mofox_plugin_dev_toolkit-0.3.5/mpdt/validators/metadata_validator.py +0 -107
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/LICENSE +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/MANIFEST.in +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/README.md +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/dependency_links.txt +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/entry_points.txt +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/requires.txt +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mofox_plugin_dev_toolkit.egg-info/top_level.txt +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/__main__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/check.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/commands/dev.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/cleanup_handler.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/dev_config.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/file_watcher.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/dev/bridge_plugin/plugin.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/templates/prompt_template.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/color_printer.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/config_loader.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/config_manager.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/file_ops.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/license_generator.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/plugin_parser.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/utils/template_engine.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/__init__.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/base.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/style_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → mofox_plugin_dev_toolkit-0.4.1}/mpdt/validators/type_validator.py +0 -0
- {mofox_plugin_dev_toolkit-0.3.5 → 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(
|
|
@@ -135,6 +170,11 @@ def generate_component(
|
|
|
135
170
|
console.print(" 3. 运行 mpdt test 测试功能")
|
|
136
171
|
|
|
137
172
|
|
|
173
|
+
# =============================================================================
|
|
174
|
+
# 交互式界面
|
|
175
|
+
# =============================================================================
|
|
176
|
+
|
|
177
|
+
|
|
138
178
|
def _interactive_generate() -> dict[str, Any]:
|
|
139
179
|
"""交互式生成组件"""
|
|
140
180
|
console.print("\n[bold cyan]🔧 组件生成向导[/bold cyan]\n")
|
|
@@ -145,12 +185,14 @@ def _interactive_generate() -> dict[str, Any]:
|
|
|
145
185
|
choices=[
|
|
146
186
|
questionary.Choice("Action 组件", value="action"),
|
|
147
187
|
questionary.Choice("Tool 组件", value="tool"),
|
|
188
|
+
questionary.Choice("Collection 集合", value="collection"),
|
|
148
189
|
questionary.Choice("Event 事件", value="event"),
|
|
149
190
|
questionary.Choice("Adapter 适配器", value="adapter"),
|
|
150
|
-
questionary.Choice("Prompt 提示词", value="prompt"),
|
|
151
191
|
questionary.Choice("Plus Command 命令", value="plus-command"),
|
|
152
192
|
questionary.Choice("Chatter 聊天组件", value="chatter"),
|
|
153
193
|
questionary.Choice("Router 路由组件", value="router"),
|
|
194
|
+
questionary.Choice("Service 服务", value="service"),
|
|
195
|
+
questionary.Choice("Config 配置", value="config"),
|
|
154
196
|
],
|
|
155
197
|
),
|
|
156
198
|
component_name=questionary.text(
|
|
@@ -177,6 +219,11 @@ def _interactive_generate() -> dict[str, Any]:
|
|
|
177
219
|
return answers
|
|
178
220
|
|
|
179
221
|
|
|
222
|
+
# =============================================================================
|
|
223
|
+
# 插件检测
|
|
224
|
+
# =============================================================================
|
|
225
|
+
|
|
226
|
+
|
|
180
227
|
def _detect_plugin_name(work_dir: Path) -> str | None:
|
|
181
228
|
"""
|
|
182
229
|
检测插件名称
|
|
@@ -200,6 +247,11 @@ def _detect_plugin_name(work_dir: Path) -> str | None:
|
|
|
200
247
|
return work_dir.name
|
|
201
248
|
|
|
202
249
|
|
|
250
|
+
# =============================================================================
|
|
251
|
+
# 组件文件生成
|
|
252
|
+
# =============================================================================
|
|
253
|
+
|
|
254
|
+
|
|
203
255
|
def _generate_component_file(
|
|
204
256
|
work_dir: Path,
|
|
205
257
|
component_type: str,
|
|
@@ -226,13 +278,14 @@ def _generate_component_file(
|
|
|
226
278
|
"""
|
|
227
279
|
# 确定组件目录
|
|
228
280
|
if use_components_folder:
|
|
229
|
-
|
|
281
|
+
dir_name = COMPONENT_DIR_MAP.get(component_type, f"{component_type}s")
|
|
282
|
+
component_dir = work_dir / "components" / dir_name
|
|
230
283
|
ensure_dir(component_dir)
|
|
231
284
|
|
|
232
285
|
# 确保 __init__.py 存在
|
|
233
286
|
init_file = component_dir / "__init__.py"
|
|
234
287
|
if not init_file.exists():
|
|
235
|
-
safe_write_file(init_file, f'"""\n{
|
|
288
|
+
safe_write_file(init_file, f'"""\n{dir_name.title()} 组件\n"""\n')
|
|
236
289
|
else:
|
|
237
290
|
# 在插件根目录生成
|
|
238
291
|
component_dir = work_dir
|
|
@@ -240,24 +293,14 @@ def _generate_component_file(
|
|
|
240
293
|
# 生成组件文件
|
|
241
294
|
component_file = component_dir / f"{component_name}.py"
|
|
242
295
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
type_map = {
|
|
246
|
-
"action": "action",
|
|
247
|
-
"tool": "tool",
|
|
248
|
-
"event": "event",
|
|
249
|
-
"adapter": "adapter",
|
|
250
|
-
"prompt": "prompt",
|
|
251
|
-
"plus_command": "plus_command",
|
|
252
|
-
"chatter":"chatter",
|
|
253
|
-
"router":"router"
|
|
254
|
-
}
|
|
255
|
-
template_key = type_map.get(component_type)
|
|
296
|
+
# 获取模板 key
|
|
297
|
+
template_key = COMPONENT_TYPE_MAP.get(component_type)
|
|
256
298
|
if not template_key:
|
|
257
299
|
print_error(f"不支持的组件类型: {component_type}")
|
|
258
300
|
return None
|
|
259
301
|
|
|
260
302
|
from mpdt.templates import get_component_template
|
|
303
|
+
|
|
261
304
|
template = get_component_template(template_key)
|
|
262
305
|
content = template.format(**context)
|
|
263
306
|
|
|
@@ -275,7 +318,70 @@ def _generate_component_file(
|
|
|
275
318
|
return None
|
|
276
319
|
|
|
277
320
|
|
|
278
|
-
|
|
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(
|
|
279
385
|
work_dir: Path,
|
|
280
386
|
component_type: str,
|
|
281
387
|
component_name: str,
|
|
@@ -284,7 +390,7 @@ def _update_plugin_registration(
|
|
|
284
390
|
use_components_folder: bool = True,
|
|
285
391
|
) -> bool:
|
|
286
392
|
"""
|
|
287
|
-
|
|
393
|
+
更新 plugin.py 中的 get_components() 方法,添加组件导入和类引用
|
|
288
394
|
|
|
289
395
|
Args:
|
|
290
396
|
work_dir: 工作目录
|
|
@@ -302,6 +408,8 @@ def _update_plugin_registration(
|
|
|
302
408
|
return False
|
|
303
409
|
|
|
304
410
|
try:
|
|
411
|
+
from mpdt.utils.plugin_parser import extract_plugin_name
|
|
412
|
+
|
|
305
413
|
# 使用 plugin_parser 验证插件名称
|
|
306
414
|
parsed_plugin_name = extract_plugin_name(work_dir)
|
|
307
415
|
if not parsed_plugin_name:
|
|
@@ -309,10 +417,12 @@ def _update_plugin_registration(
|
|
|
309
417
|
parsed_plugin_name = work_dir.name
|
|
310
418
|
|
|
311
419
|
# 使用 CodeParser 读取和解析源代码
|
|
420
|
+
from mpdt.utils.code_parser import CodeParser
|
|
421
|
+
|
|
312
422
|
parser = CodeParser.from_file(plugin_file)
|
|
313
423
|
|
|
314
424
|
# 创建转换器
|
|
315
|
-
transformer =
|
|
425
|
+
transformer = ComponentImportTransformer(
|
|
316
426
|
plugin_name=parsed_plugin_name,
|
|
317
427
|
component_type=component_type,
|
|
318
428
|
component_name=component_name,
|
|
@@ -326,14 +436,67 @@ def _update_plugin_registration(
|
|
|
326
436
|
# 写回文件
|
|
327
437
|
plugin_file.write_text(modified_tree.code, encoding="utf-8")
|
|
328
438
|
|
|
329
|
-
|
|
439
|
+
if verbose:
|
|
440
|
+
console.print("[dim]✓ 已更新 plugin.py[/dim]")
|
|
441
|
+
|
|
442
|
+
return transformer.import_added or transformer.component_added
|
|
330
443
|
|
|
331
|
-
except Exception:
|
|
444
|
+
except Exception as e:
|
|
445
|
+
if verbose:
|
|
446
|
+
console.print(f"[dim red]更新 plugin.py 失败: {e}[/dim red]")
|
|
332
447
|
return False
|
|
333
448
|
|
|
334
449
|
|
|
335
|
-
|
|
336
|
-
|
|
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
|
+
"""
|
|
337
500
|
|
|
338
501
|
def __init__(
|
|
339
502
|
self,
|
|
@@ -349,7 +512,8 @@ class PluginRegistrationTransformer(cst.CSTTransformer):
|
|
|
349
512
|
self.class_name = class_name
|
|
350
513
|
self.use_components_folder = use_components_folder
|
|
351
514
|
self.import_added = False
|
|
352
|
-
self.
|
|
515
|
+
self.component_added = False
|
|
516
|
+
self.is_config = component_type == "config"
|
|
353
517
|
|
|
354
518
|
def leave_Module( # noqa: N802
|
|
355
519
|
self, original_node: cst.Module, updated_node: cst.Module
|
|
@@ -360,13 +524,12 @@ class PluginRegistrationTransformer(cst.CSTTransformer):
|
|
|
360
524
|
|
|
361
525
|
# 根据存放位置构建导入语句
|
|
362
526
|
if self.use_components_folder:
|
|
363
|
-
|
|
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}"
|
|
364
529
|
else:
|
|
365
530
|
import_path = f"{self.plugin_name}.{self.component_name}"
|
|
366
531
|
|
|
367
|
-
import_statement = cst.parse_statement(
|
|
368
|
-
f"from {import_path} import {self.class_name}"
|
|
369
|
-
)
|
|
532
|
+
import_statement = cst.parse_statement(f"from {import_path} import {self.class_name}")
|
|
370
533
|
|
|
371
534
|
# 检查是否已存在相同的导入
|
|
372
535
|
for stmt in updated_node.body:
|
|
@@ -395,52 +558,104 @@ class PluginRegistrationTransformer(cst.CSTTransformer):
|
|
|
395
558
|
|
|
396
559
|
return updated_node
|
|
397
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
|
+
|
|
398
615
|
def leave_FunctionDef( # noqa: N802
|
|
399
616
|
self, original_node: cst.FunctionDef, updated_node: cst.FunctionDef
|
|
400
617
|
) -> cst.FunctionDef:
|
|
401
|
-
"""在
|
|
402
|
-
|
|
618
|
+
"""在 get_components 函数中添加组件类引用(不包括 config 组件)"""
|
|
619
|
+
# config 组件在 configs 类属性中处理,不需要在 get_components 中添加
|
|
620
|
+
if self.is_config:
|
|
403
621
|
return updated_node
|
|
404
|
-
|
|
405
|
-
if self.registration_added:
|
|
622
|
+
if updated_node.name.value != "get_components":
|
|
406
623
|
return updated_node
|
|
407
624
|
|
|
408
|
-
|
|
409
|
-
info_method_map = {
|
|
410
|
-
"action": "get_action_info",
|
|
411
|
-
"tool": "get_tool_info",
|
|
412
|
-
"event": "get_event_handler_info",
|
|
413
|
-
"adapter": "get_adapter_info",
|
|
414
|
-
"prompt": "get_prompt_info",
|
|
415
|
-
"plus_command": "get_command_info",
|
|
416
|
-
"chatter": "get_chatter_info",
|
|
417
|
-
"router": "get_router_info",
|
|
418
|
-
}
|
|
419
|
-
info_method = info_method_map.get(self.component_type, "get_component_info")
|
|
420
|
-
|
|
421
|
-
# 构建注册代码(带注释的语句)
|
|
422
|
-
registration_stmt = f"components.append(({self.class_name}.{info_method}(), {self.class_name})) # 注册 {self.class_name}"
|
|
423
|
-
|
|
424
|
-
# 检查是否已存在注册代码
|
|
425
|
-
function_code = cst.Module([]).code_for_node(updated_node)
|
|
426
|
-
if self.class_name in function_code and info_method in function_code:
|
|
427
|
-
self.registration_added = True
|
|
625
|
+
if self.component_added:
|
|
428
626
|
return updated_node
|
|
429
627
|
|
|
430
|
-
# 找到 return
|
|
628
|
+
# 找到 return 语句并修改其返回列表
|
|
431
629
|
new_body = []
|
|
432
630
|
for stmt in updated_node.body.body:
|
|
433
|
-
# 如果是 return 语句,在前面插入注册代码
|
|
434
631
|
if isinstance(stmt, cst.SimpleStatementLine):
|
|
435
|
-
for s in stmt.body:
|
|
436
|
-
if isinstance(s, cst.Return):
|
|
437
|
-
#
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
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
|
|
441
656
|
new_body.append(stmt)
|
|
442
657
|
|
|
443
|
-
if self.
|
|
658
|
+
if self.component_added:
|
|
444
659
|
new_function_body = updated_node.body.with_changes(body=new_body)
|
|
445
660
|
return updated_node.with_changes(body=new_function_body)
|
|
446
661
|
|