ForcePilot/backend/package/yuxi/channels/contract/plugin/entry.py
Kris 00092c818e chore: 批量代码优化与规范完善
本次提交包含多项代码优化与规范修正:
1. 文档与注释优化:修正注释术语、补充注解与FR编号
2. 代码格式调整:统一空格、换行与缩进规范
3. 类型与接口完善:补充__all__导出、修正返回类型注解
4. 错误处理增强:新增领域错误类与校验逻辑
5. 依赖与导入调整:修复路径引用、统一时区导入
6. 协议与契约更新:完善接口文档与一致性注解
2026-07-03 19:18:13 +08:00

324 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""插件入口契约。
定义插件宿主 Protocol``PluginHost``)与插件入口类型别名
``CHANNEL_ENTRY``)。插件通过 ``CHANNEL_ENTRY`` 函数注册,由宿主在
loaded 阶段调用,返回 ``PluginManifest``。
"""
from __future__ import annotations
from collections.abc import Callable
from typing import Any, Protocol, runtime_checkable
from yuxi.channels.contract.dtos.plugin import DomainEvent
from yuxi.channels.contract.dtos.route import MatchTier
from yuxi.channels.contract.plugin.capability import CapabilityProver
from yuxi.channels.contract.plugin.extension_point import (
ConfigSource,
EventSubscription,
StageSlot,
)
from yuxi.channels.contract.plugin.manifest import PluginManifest
from yuxi.channels.contract.ports.driven import (
AgentRunPort,
AuditLogRepositoryPort,
CachePort,
ChannelAccountRepositoryPort,
ChannelSessionRepositoryPort,
ConfigPort,
ConversationPort,
IdempotencyRepositoryPort,
IdentityResolverPort,
LoggerPort,
OutboxRepositoryPort,
PairingRepositoryPort,
PersistenceHealthPort,
PersistencePort,
QueuePort,
TracerPort,
UserIdentityRepositoryPort,
)
class PluginAdapter(Protocol):
"""插件适配器标记 Protocol。
标识 ``PluginHost.registerAdapter`` 接受的适配器实例类型。渠道插件
可注册的适配器包括 ``contract.plugin.adapters`` 中定义的 23 类适配器
协议InboundAdapter / OutboundAdapter / SessionAdapter / RichMessageAdapter
/ StreamingAdapter / DirectoryAdapter / CommandAdapter / WizardAdapter
/ DoctorAdapter / WhitelistAdapter / ToolsAdapter / MessageOpsAdapter
/ StatusAdapter / MentionAdapter / IdentityResolverAdapter / LifecycleAdapter
/ LoginAdapter / ProbeableAdapter / ContentModerationAdapter / PullerAdapter
/ StreamConnectorAdapter / AttachmentUploadAdapter / WebhookTestAdapter
渠道上下文提供者端口ChannelContextProviderPort它们各自定义独立
的处理方法,无公共方法基类,故本 Protocol 作为类型边界用于静态检查
与文档化,不含公共方法声明。
"""
...
#: 路由匹配器类型别名。
#:
#: 接收绑定上下文,返回匹配的路由绑定或 ``None``。插件通过
#: ``registerMatcher`` 注入自定义匹配函数,供 ``RouteResolver`` 遍历
#: 层级时调用执行匹配逻辑。使用 ``Any`` 避免运行时解析
#: ``BindingContext``TYPE_CHECKING 导入,见 ``TierMatcher``)。
Matcher = Callable[..., Any]
@runtime_checkable
class PluginHost(Protocol):
"""插件宿主 Protocol。
由宿主实现,向插件提供被驱动端口获取、扩展点注册、能力边界声明与
事件发布能力。使用 ``@runtime_checkable`` 装饰以支持 ``isinstance``
检查。
资源访问约束INV-I7 / FF-ADAPTER-01 / FR-32
- 插件 **不得** 直接访问宿主的 ``settings``、``logger``、数据库连接池、
Redis 客户端,**必须** 通过 ``PluginHost`` 提供的端口获取方法获取依赖。
- 插件 **不得** 修改宿主的中间件链、路由表、事件订阅器,**只能** 通过
扩展点注册方法注入自身逻辑。
- 插件能力声明 **必须** 通过 ``CapabilityProver`` 验证,验证失败 **不得**
启动插件。
插件必须通过 ``PluginHost`` 完成以下三类操作:
1. 端口获取:通过 ``getXxxPort()`` 方法获取被驱动端口,访问配置、日志、
持久化、缓存、追踪、队列、会话、Agent 运行与身份解析能力。
2. 扩展点注册:通过 ``registerXxx()`` 方法注册适配器、阶段槽位、事件订阅、
配置源与能力证明者,向宿主注入自身逻辑。
3. 能力边界声明:通过 ``declareXxx()`` 方法声明可访问端口、可注入管道与
资源配额,由宿主强制约束。
"""
def getConfigPort(self) -> ConfigPort:
"""获取配置端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getLoggerPort(self) -> LoggerPort:
"""获取日志端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getPersistencePort(self) -> PersistencePort:
"""获取持久化端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getCachePort(self) -> CachePort:
"""获取缓存端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getTracerPort(self) -> TracerPort:
"""获取追踪端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getQueuePort(self) -> QueuePort:
"""获取队列端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getConversationPort(self) -> ConversationPort:
"""获取会话端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getAgentRunPort(self) -> AgentRunPort:
"""获取 Agent 运行端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getIdentityResolverPort(self) -> IdentityResolverPort:
"""获取身份解析端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getChannelAccountRepositoryPort(self) -> ChannelAccountRepositoryPort:
"""获取渠道账户仓储端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getChannelSessionRepositoryPort(self) -> ChannelSessionRepositoryPort:
"""获取渠道会话仓储端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getPairingRepositoryPort(self) -> PairingRepositoryPort:
"""获取配对仓储端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getAuditLogRepositoryPort(self) -> AuditLogRepositoryPort:
"""获取审计日志仓储端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getOutboxRepositoryPort(self) -> OutboxRepositoryPort:
"""获取发件箱仓储端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getUserIdentityRepositoryPort(self) -> UserIdentityRepositoryPort:
"""获取用户身份仓储端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getIdempotencyRepositoryPort(self) -> IdempotencyRepositoryPort:
"""获取幂等性仓储端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def getPersistenceHealthPort(self) -> PersistenceHealthPort:
"""获取持久化健康端口。
@consistency: 无状态stateless返回注入的端口实例。
"""
...
def registerAdapter(self, adapter_type: str, adapter: PluginAdapter) -> None:
"""注册适配器。
参数:
adapter_type: 适配器类型。
adapter: 适配器实例。
@consistency: 无状态stateless仅写入注册表。
@idempotent: False — 重复注册相同 adapter_type 会覆盖前一次的实例.
"""
...
def registerStageSlot(self, slot: StageSlot) -> None:
"""注册管道阶段槽位。
参数:
slot: 阶段槽位实例。
@consistency: 无状态stateless仅写入注册表。
@idempotent: False — 重复注册相同锚点 + 优先级的 slot 会触发冲突策略.
"""
...
def registerEventSubscription(self, subscription: EventSubscription) -> None:
"""注册事件订阅。
参数:
subscription: 事件订阅实例。
@consistency: 无状态stateless仅写入注册表。
@idempotent: False — 重复注册会创建多个订阅,同一事件被多次处理.
"""
...
def registerConfigSource(self, source: ConfigSource) -> None:
"""注册配置源。
参数:
source: 配置源实例。
@consistency: 无状态stateless仅写入注册表。
@idempotent: False — 重复注册相同 key 会覆盖前一次的源.
"""
...
def registerCapabilityProver(self, prover: CapabilityProver) -> None:
"""注册能力证明者FR-08 增强)。
注册 ``CapabilityProver`` 实例,供宿主对插件清单声明的静态能力
进行运行时证明。宿主在 ``initialized`` 阶段调用 ``proveCapability``
对每项能力进行证明,证明失败的插件 **不得** 启动FR-32
参数:
prover: 能力证明 Protocol 实例。
@consistency: 无状态stateless仅写入注册表。
@idempotent: False — 重复注册会覆盖前一次的 prover 实例.
"""
...
def registerMatchTier(self, tier: MatchTier) -> None:
"""注册路由匹配层级FR-04
参数:
tier: 匹配层级配置。
@consistency: 无状态stateless仅写入注册表。
@idempotent: False — 重复注册相同层级名会覆盖前一次的配置.
"""
...
def registerMatcher(self, name: str, matcher: Matcher) -> None:
"""注册匹配层级的匹配器FR-04
为已注册的层级绑定匹配函数,供 ``RouteResolver`` 在遍历层级时调用
执行匹配逻辑。插件通过本方法注入自定义匹配规则。
参数:
name: 层级名称(必须已通过 ``registerMatchTier`` 注册)。
matcher: 匹配器函数,接收绑定上下文,返回路由绑定或 None。
@consistency: 无状态stateless仅写入注册表。
@idempotent: False — 重复注册相同 name 会覆盖前一次的 matcher.
"""
...
async def publishEvent(self, event: DomainEvent) -> None:
"""发布领域事件。
宿主负责将事件分发到订阅者。支持的事件类型:
PluginDiscovered/PluginLoaded/PluginStarted/PluginPaused/
PluginResumed/PluginStopped/PluginUnloaded/PluginFailed/
PairingApproved/PairingRevoked/ConfigChanged/ChannelDegraded/ChannelRecovered。
参数:
event: 领域事件。
@consistency: 最终一致eventual订阅者按各自策略处理。
@idempotent: True — 重复发布相同事件产生等价结果(订阅者需自行幂等).
"""
...
#: 插件入口类型别名。
#:
#: 每个渠道插件 **必须** 通过 ``CHANNEL_ENTRY`` 契约注册,**不得** 隐式全局
#: 注入FR-32。由宿主在 loaded 阶段调用,返回 ``PluginManifest``,包含
#: 元数据、适配器、阶段、事件订阅等。
CHANNEL_ENTRY = Callable[[PluginHost], PluginManifest]