ForcePilot/backend/package/yuxi/channels/contract/plugin/entry.py
Kris 0d067d61d3 chore: 批量更新契约与实现,修复多处细节问题
本次提交包含多类代码优化与修复:
1. 重命名适配器协议类:WebhookTestable→WebhookTestAdapter、AttachmentUploadable→AttachmentUploadAdapter,并同步更新所有引用
2. 为飞书/企业微信插件添加凭证克隆能力开关配置
3. 修复飞书入站适配器URL解析错误,使用hostname替代host属性
4. 新增批量发送消息DTO与已读状态DTO
5. 新增插件目录列表接口与插件能力校验规则
6. 修复权限阶段配置,添加analytics权限映射
7. 优化健康检查、限流模块的环境变量配置支持
8. 修复配对过期扫描器参数名不匹配问题
9. 优化日志调用、文档注释与代码可读性
10. 移除废弃的AuditExportTask聚合根与相关导入
2026-07-02 18:27:06 +08:00

273 lines
9.2 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, ResourceQuota
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:
"""获取配置端口。"""
...
def getLoggerPort(self) -> LoggerPort:
"""获取日志端口。"""
...
def getPersistencePort(self) -> PersistencePort:
"""获取持久化端口。"""
...
def getCachePort(self) -> CachePort:
"""获取缓存端口。"""
...
def getTracerPort(self) -> TracerPort:
"""获取追踪端口。"""
...
def getQueuePort(self) -> QueuePort:
"""获取队列端口。"""
...
def getConversationPort(self) -> ConversationPort:
"""获取会话端口。"""
...
def getAgentRunPort(self) -> AgentRunPort:
"""获取 Agent 运行端口。"""
...
def getIdentityResolverPort(self) -> IdentityResolverPort:
"""获取身份解析端口。"""
...
def getChannelAccountRepositoryPort(self) -> ChannelAccountRepositoryPort:
"""获取渠道账户仓储端口。"""
...
def getChannelSessionRepositoryPort(self) -> ChannelSessionRepositoryPort:
"""获取渠道会话仓储端口。"""
...
def getPairingRepositoryPort(self) -> PairingRepositoryPort:
"""获取配对仓储端口。"""
...
def getAuditLogRepositoryPort(self) -> AuditLogRepositoryPort:
"""获取审计日志仓储端口。"""
...
def getOutboxRepositoryPort(self) -> OutboxRepositoryPort:
"""获取发件箱仓储端口。"""
...
def getUserIdentityRepositoryPort(self) -> UserIdentityRepositoryPort:
"""获取用户身份仓储端口。"""
...
def getIdempotencyRepositoryPort(self) -> IdempotencyRepositoryPort:
"""获取幂等性仓储端口。"""
...
def getPersistenceHealthPort(self) -> PersistenceHealthPort:
"""获取持久化健康端口。"""
...
def registerAdapter(self, adapter_type: str, adapter: PluginAdapter) -> None:
"""注册适配器。
参数:
adapter_type: 适配器类型。
adapter: 适配器实例。
"""
...
def registerStageSlot(self, slot: StageSlot) -> None:
"""注册管道阶段槽位。
参数:
slot: 阶段槽位实例。
"""
...
def registerEventSubscription(self, subscription: EventSubscription) -> None:
"""注册事件订阅。
参数:
subscription: 事件订阅实例。
"""
...
def registerConfigSource(self, source: ConfigSource) -> None:
"""注册配置源。
参数:
source: 配置源实例。
"""
...
def registerCapabilityProver(self, prover: CapabilityProver) -> None:
"""注册能力证明者FR-08 增强)。
注册 ``CapabilityProver`` 实例,供宿主对插件清单声明的静态能力
进行运行时证明。宿主在 ``initialized`` 阶段调用 ``proveCapability``
对每项能力进行证明,证明失败的插件 **不得** 启动FR-32
参数:
prover: 能力证明 Protocol 实例。
"""
...
def registerMatchTier(self, tier: MatchTier) -> None:
"""注册路由匹配层级FR-04
参数:
tier: 匹配层级配置。
"""
...
def registerMatcher(self, name: str, matcher: Matcher) -> None:
"""注册匹配层级的匹配器FR-04
为已注册的层级绑定匹配函数,供 ``RouteResolver`` 在遍历层级时调用
执行匹配逻辑。插件通过本方法注入自定义匹配规则。
参数:
name: 层级名称(必须已通过 ``registerMatchTier`` 注册)。
matcher: 匹配器函数,接收绑定上下文,返回路由绑定或 None。
"""
...
def declareAccessiblePorts(self, ports: tuple[str, ...]) -> None:
"""声明可访问的端口列表。
参数:
ports: 可访问的端口名称元组。
"""
...
def declareInjectablePipelines(self, pipelines: tuple[str, ...]) -> None:
"""声明可注入的管道列表。
参数:
pipelines: 可注入的管道名称元组。
"""
...
def declareResourceQuota(self, quota: ResourceQuota) -> None:
"""声明资源配额。
参数:
quota: 资源配额实例。
"""
...
async def publishEvent(self, event: DomainEvent) -> None:
"""发布领域事件。
宿主负责将事件分发到订阅者。支持的事件类型:
PluginDiscovered/PluginLoaded/PluginStarted/PluginPaused/
PluginResumed/PluginStopped/PluginUnloaded/PluginFailed/
PairingApproved/PairingRevoked/ConfigChanged/ChannelDegraded/ChannelRecovered。
参数:
event: 领域事件。
"""
...
#: 插件入口类型别名。
#:
#: 每个渠道插件 **必须** 通过 ``CHANNEL_ENTRY`` 契约注册,**不得** 隐式全局
#: 注入FR-32。由宿主在 loaded 阶段调用,返回 ``PluginManifest``,包含
#: 元数据、适配器、阶段、事件订阅等。
CHANNEL_ENTRY = Callable[[PluginHost], PluginManifest]