ForcePilot/backend/package/yuxi/channels/plugins/wecom/entry.py
Kris a484844ea1 chore: 汇总完成多模块功能迭代与缺陷修复
此提交包含了大量跨模块的优化与修复:
1.  配置与依赖调整:调整账号列表分页默认值、重试上限、内容审核长度限制,新增出站文件支持
2.  代码结构优化:重构白名单缓存逻辑、移除冗余日志依赖、清理过时TODO注释
3.  功能增强:添加死信计数接口、会话绑定审计、SSE订阅限流、凭据验证服务
4.  契约更新:修正DTO字段命名、完善类型定义、更新审计操作类型
5.  错误处理:优化限流清理逻辑、添加异常捕获与告警
6.  文档与校验:补充字段校验规则、完善注释与文档说明
2026-07-11 21:37:16 +08:00

201 lines
8.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.

"""企业微信渠道插件入口。
实现 ``CHANNEL_ENTRY`` 契约,注册 16 个适配器与生命周期钩子,返回
``PluginManifest``。由宿主在 loaded 阶段通过 ``importlib`` 导入并调用。
调用顺序(严格):
1. ``getXxxPort`` 获取被驱动端口实例(宿主已从 manifest.accessible_ports
加载权限,无需运行时 declareXxx
2. 实例化 ``WecomLifecycleHandler`` 与 ``WecomClient``。
3. 实例化并注册 16 个适配器15 个列表追加 + 1 个 identity_resolver 单实例)。
4. ``registerLifecycleHandler`` 注册生命周期钩子(鸭子类型调用)。
5. 返回 ``PluginManifest``。
F-03 单真相源:本入口仅承接 discover 阶段解析的 ``ChannelManifest``
不再重复构造声明性字段capabilities / config_schema / accessible_ports /
injectable_pipelines / resource_quota / env_vars / credential_strategy 等),
所有声明性字段以 ``manifest.json`` 为唯一真相源。本函数仅负责适配器实例化、
client 实例化、LifecycleHandler 构造与 ``registerAdapter`` 调用。
per-account 适配器处理:``WizardAdapter`` 的 ``__init__`` 需
``account_id``,但 ``CHANNEL_ENTRY`` 在插件加载时不知具体账户,传入空字符串
占位(``_PLACEHOLDER_ACCOUNT_ID``)。``WhitelistAdapter`` 由协议方法传入
``account_id``,无需构造时绑定。``WizardAdapter`` 实际 account_id 由
``LifecycleAdapter.afterAccountConfigWritten`` 在账户配置写入后按账户重建
对应适配器,或由调用方通过 ``ConfigPort`` 动态读取。
回调接收管理:企业微信自建应用回调由宿主 Webhook 服务统一承载(决策 3
单模事件接收),``LifecycleAdapter`` 与 ``LifecycleHandler`` 不自管理连接。
v1 不注册 ``puller`` / ``stream_connector`` 适配器§2.5.3)。
依赖方向:仅 import ``yuxi.channels.contract.*`` + 标准库 + 同插件内部模块,
不污染框架层。
"""
from __future__ import annotations
from yuxi.channels.contract.plugin.entry import PluginHost
from yuxi.channels.contract.plugin.manifest import (
ChannelManifest,
PluginManifest,
)
from .adapters.command_adapter import WecomCommandAdapter
from .adapters.directory_adapter import WecomDirectoryAdapter
from .adapters.doctor_adapter import WecomDoctorAdapter
from .adapters.identity_resolver_adapter import WecomIdentityResolverAdapter
from .adapters.inbound_adapter import WecomInboundAdapter
from .adapters.lifecycle_adapter import WecomLifecycleAdapter
from .adapters.login_adapter import WecomLoginAdapter
from .adapters.message_ops_adapter import WecomMessageOpsAdapter
from .adapters.outbound_adapter import WecomOutboundAdapter
from .adapters.probeable_adapter import WecomProbeableAdapter
from .adapters.rich_message_adapter import WecomRichMessageAdapter
from .adapters.session_adapter import WecomSessionAdapter
from .adapters.status_adapter import WecomStatusAdapter
from .adapters.streaming_adapter import WecomStreamingAdapter
from .adapters.whitelist_adapter import WecomWhitelistAdapter
from .adapters.wizard_adapter import WecomWizardAdapter
from .lifecycle import WecomLifecycleHandler
from .wecom_client import WecomClient
# per-account 适配器占位 account_idCHANNEL_ENTRY 在插件加载时不知具体账户,
# WizardAdapter 传入空字符串占位。WhitelistAdapter 由协议方法传入 account_id
# 无需构造时绑定。
# WizardAdapter 实际 account_id 由 LifecycleAdapter 在账户配置写入后按账户重建
# 适配器实例,或由适配器在方法调用时通过 ConfigPort 动态读取。
_PLACEHOLDER_ACCOUNT_ID = ""
# 已注册适配器类型列表(与 registerAdapter 调用顺序一致)。
# 此处为运行时适配器清单,非声明性字段,需与下方 registerAdapter 调用保持一致。
# 企业微信 v1 不注册 mentionmanifest 声明 false与 stream_connector
# §2.5.3,回调由宿主 Webhook 服务承载)。
_ADAPTER_TYPES: tuple[str, ...] = (
"inbound",
"outbound",
"session",
"status",
"rich_message",
"streaming",
"message_ops",
"directory",
"command",
"whitelist",
"wizard",
"doctor",
"lifecycle",
"probeable",
"login",
"identity_resolver",
)
def channel_entry(host: PluginHost, manifest: ChannelManifest) -> PluginManifest:
"""企业微信渠道插件入口。
由宿主在 loaded 阶段调用,完成适配器注册、生命周期钩子注册,
返回 ``PluginManifest``。
能力边界accessible_ports / injectable_pipelines / resource_quota /
config_schema / env_vars / credential_strategy 等)由 discover 阶段
解析的 ``manifest`` 静态字段承载,宿主在加载期通过
``PluginCapabilityChecker.check`` 校验,运行时通过
``PluginHostImpl._checkPortAccess`` 从 manifest 读取并强制约束。本函数
不重复构造声明性字段F-03 单真相源)。
参数:
host: 插件宿主,提供端口获取与扩展点注册 API。
manifest: 渠道清单,由 discover 阶段从 ``manifest.json`` 解析得到,
承载所有声明性字段。本函数复用其 ``config_schema`` 注入
``LifecycleHandler``,并直接作为返回 ``PluginManifest.manifest``。
"""
# 1. 获取端口实例(宿主已从 manifest.accessible_ports 加载权限)
config_port = host.getConfigPort()
logger_port = host.getLoggerPort()
cache_port = host.getCachePort()
persistence_port = host.getPersistencePort()
# 2. 实例化 WecomClient 与 LifecycleHandler
# 依赖关系为单向handler 在 onInit 调 client.attach_http_client 注入
# 连接池client 不引用 handler。先创建 client再创建 handler 并通过
# 构造器注入。config_schema 取自 manifestF-03 单真相源)。
client = WecomClient(config_port, cache_port, logger_port)
handler = WecomLifecycleHandler(
config_port,
logger_port,
cache_port,
manifest.config_schema,
client,
)
# 3. 实例化并注册 16 个适配器
# 15 个列表追加 + 1 个 identity_resolver 单实例赋值
host.registerAdapter(
"inbound",
WecomInboundAdapter(client, config_port, logger_port, cache_port),
)
host.registerAdapter(
"outbound",
WecomOutboundAdapter(client, logger_port, cache_port),
)
host.registerAdapter("session", WecomSessionAdapter())
host.registerAdapter("status", WecomStatusAdapter(logger_port))
host.registerAdapter("rich_message", WecomRichMessageAdapter(logger_port))
host.registerAdapter(
"streaming",
WecomStreamingAdapter(client, logger_port, cache_port),
)
host.registerAdapter(
"message_ops",
WecomMessageOpsAdapter(client, logger_port, cache_port),
)
host.registerAdapter(
"directory",
WecomDirectoryAdapter(client, cache_port, config_port),
)
host.registerAdapter("command", WecomCommandAdapter(config_port))
host.registerAdapter(
"whitelist",
WecomWhitelistAdapter(
persistence_port,
logger_port,
),
)
host.registerAdapter(
"wizard",
WecomWizardAdapter(config_port, client, _PLACEHOLDER_ACCOUNT_ID),
)
host.registerAdapter("doctor", WecomDoctorAdapter(client, config_port))
host.registerAdapter(
"lifecycle",
WecomLifecycleAdapter(client, cache_port, logger_port),
)
host.registerAdapter(
"probeable",
WecomProbeableAdapter(client, config_port, persistence_port),
)
host.registerAdapter(
"login",
WecomLoginAdapter(client, config_port, logger_port),
)
# identity_resolver 为单实例注册(非列表追加)
host.registerAdapter(
"identity_resolver",
WecomIdentityResolverAdapter(client, cache_port),
)
# 4. 注册生命周期钩子
# PluginHost Protocol 未声明 registerLifecycleHandler但 PluginHostImpl
# 已实现,运行时通过鸭子类型调用。
host.registerLifecycleHandler(handler)
# 5. 返回 PluginManifestmanifest 直接复用入参adapters 为运行时清单)
return PluginManifest(
manifest=manifest,
adapters=_ADAPTER_TYPES,
)
CHANNEL_ENTRY = channel_entry