|
8 | 8 | | |
9 | 9 | +-- WorkerSession (插件 A) -- StdioTransport -- PluginWorkerRuntime (子进程) |
10 | 10 | | |
11 | | - +-- WorkerSession (插件 B) -- StdioTransport -- PluginWorkerRuntime (子进程) |
| 11 | + +-- WorkerSession (插件 B, 插件 C) -- StdioTransport -- GroupWorkerRuntime (子进程) |
12 | 12 | | |
13 | | - +-- WorkerSession (插件 C) -- StdioTransport -- PluginWorkerRuntime (子进程) |
| 13 | + +-- WorkerSession (插件 D) -- StdioTransport -- PluginWorkerRuntime (子进程) |
14 | 14 |
|
15 | 15 | 核心类: |
16 | 16 | SupervisorRuntime: 监管者运行时 |
17 | 17 | - 发现并加载所有插件 |
18 | | - - 为每个插件启动 Worker 进程 |
| 18 | + - 为单个插件或兼容插件组启动 Worker 进程 |
19 | 19 | - 聚合所有 handler 并向 Core 注册 |
20 | 20 | - 路由 Core 的调用请求到对应 Worker |
21 | 21 | - 处理 Worker 进程崩溃和重连 |
|
45 | 45 |
|
46 | 46 | from loguru import logger |
47 | 47 |
|
| 48 | +from .._internal.plugin_ids import ( |
| 49 | + capability_belongs_to_plugin, |
| 50 | + plugin_capability_prefix, |
| 51 | +) |
48 | 52 | from ..errors import AstrBotError |
49 | 53 | from ..protocol.descriptors import CapabilityDescriptor |
50 | 54 | from ..protocol.messages import EventMessage, InitializeOutput, PeerInfo |
@@ -533,60 +537,25 @@ def _register_plugin_capability( |
533 | 537 | session: WorkerSession, |
534 | 538 | plugin_name: str, |
535 | 539 | ) -> None: |
536 | | - """注册插件 capability,处理命名冲突。 |
537 | | -
|
538 | | - 当 capability 名称冲突时: |
539 | | - - 如果是保留命名空间(handler/system/internal),跳过并警告 |
540 | | - - 否则,使用插件名作为前缀重新命名,例如: |
541 | | - - 插件 'my_plugin' 注册 'demo.echo' 冲突 |
542 | | - - 自动重命名为 'my_plugin.demo.echo' |
543 | | - """ |
| 540 | + """注册插件 capability。""" |
544 | 541 | capability_name = descriptor.name |
545 | | - |
546 | | - if not self.capability_router.contains(capability_name): |
547 | | - # 无冲突,直接注册 |
548 | | - self._do_register_capability( |
549 | | - descriptor, session, capability_name, plugin_name |
550 | | - ) |
551 | | - return |
552 | | - |
553 | | - # 检查是否在保留命名空间内 |
554 | | - if capability_name.startswith(("handler.", "system.", "internal.")): |
555 | | - logger.warning( |
556 | | - "Capability '{}' 在保留命名空间内,跳过插件 '{}' 的注册。" |
557 | | - "保留命名空间不允许插件覆盖。", |
558 | | - capability_name, |
559 | | - plugin_name, |
| 542 | + if not capability_belongs_to_plugin(capability_name, plugin_name): |
| 543 | + expected_prefix = plugin_capability_prefix(plugin_name) |
| 544 | + raise ValueError( |
| 545 | + "插件导出的 capability 必须使用 plugin_id 作为公开命名空间前缀:" |
| 546 | + f" plugin={plugin_name!r}, capability={capability_name!r}, " |
| 547 | + f"expected_prefix={expected_prefix!r}" |
560 | 548 | ) |
561 | | - return |
562 | | - |
563 | | - # 尝试添加插件前缀解决冲突 |
564 | | - prefixed_name = f"{plugin_name}.{capability_name}" |
565 | | - if self.capability_router.contains(prefixed_name): |
566 | | - logger.warning( |
567 | | - "Capability '{}' 和 '{}.{}' 均已存在," |
568 | | - "跳过插件 '{}' 的注册。请考虑使用更唯一的命名。", |
569 | | - capability_name, |
570 | | - plugin_name, |
571 | | - capability_name, |
572 | | - plugin_name, |
| 549 | + # Worker 侧 loader 已经做过命名空间校验;这里若还能撞名,说明协议数据 |
| 550 | + # 与本地路由状态不一致,继续静默改名只会掩盖问题。 |
| 551 | + if self.capability_router.contains(capability_name): |
| 552 | + existing_plugin = self._capability_sources.get(capability_name, "<unknown>") |
| 553 | + raise RuntimeError( |
| 554 | + "duplicate capability registration detected after worker load validation: " |
| 555 | + f"{capability_name!r} already registered by {existing_plugin!r}, " |
| 556 | + f"cannot register again for {plugin_name!r}" |
573 | 557 | ) |
574 | | - return |
575 | | - |
576 | | - # 使用前缀名称注册 |
577 | | - prefixed_descriptor = descriptor.model_copy(deep=True) |
578 | | - prefixed_descriptor.name = prefixed_name |
579 | | - logger.info( |
580 | | - "Capability '{}' 与已注册能力冲突,自动重命名为 '{}' (插件: {})。", |
581 | | - capability_name, |
582 | | - prefixed_name, |
583 | | - plugin_name, |
584 | | - ) |
585 | | - self._do_register_capability( |
586 | | - prefixed_descriptor, session, prefixed_name, plugin_name |
587 | | - ) |
588 | | - # 记录原始名称到前缀名称的映射,便于调试 |
589 | | - self._capability_sources[f"_original:{prefixed_name}"] = capability_name |
| 558 | + self._do_register_capability(descriptor, session, capability_name, plugin_name) |
590 | 559 |
|
591 | 560 | def _do_register_capability( |
592 | 561 | self, |
|
0 commit comments