1. 移除所有适配器文件中多余的空导入行 2. 调整ValidationError继承,移除不必要的ValueError继承 3. 修正多处ChannelType使用方式,从.value改为直接使用枚举实例 4. 优化飞书插件部分硬编码渠道类型为枚举实例 5. 更新wechat_ilink插件清单与适配器配置 6. 新增飞书目录适配器缓存清理支持判断与iLink生命周期适配器凭据轮换支持判断 7. 优化配置处理器历史查询逻辑,区分键不存在与无历史记录场景
153 lines
12 KiB
Python
153 lines
12 KiB
Python
"""配置 schema 元数据契约层定义。
|
||
|
||
定义配置字段的完整 schema 元数据(``CONFIG_SCHEMA``),包括键、类型、
|
||
是否必填、默认值、是否可热更新与约束,作为配置 schema 的唯一真相源
|
||
(§13.1 配置分层 / §6.1 契约层职责)。适配器(如 ``RedisConfigAdapter``)
|
||
与应用层(如 ``ConfigManager``)共享引用本模块,消除 schema 元数据
|
||
下沉至适配器层的 DRY 违反。
|
||
|
||
``HOT_RELOADABLE_KEYS`` / ``NON_HOT_RELOADABLE_KEYS`` 从 ``CONFIG_SCHEMA``
|
||
派生,供 ``ConfigManager`` 做热更新策略校验(ADP-030)。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from yuxi.channels.contract.dtos.config import ConfigField
|
||
|
||
# 配置 schema:全部配置字段的完整元数据(FR-37 配置热更新)。
|
||
# 40 个可热更新字段 + 13 个不可热更新字段,共 53 个。
|
||
# 字段顺序:先可热更新(hot_reloadable=True),后不可热更新(hot_reloadable=False)。
|
||
CONFIG_SCHEMA: tuple[ConfigField, ...] = (
|
||
# === 可热更新字段(hot_reloadable=True)===
|
||
ConfigField(key="dm_policy", type="json", required=False, default=None, hot_reloadable=True),
|
||
ConfigField(key="allow_from", type="json", required=False, default=None, hot_reloadable=True),
|
||
ConfigField(key="rate_limit", type="json", required=False, default=None, hot_reloadable=True),
|
||
ConfigField(key="bot_loop_budget", type="int", required=False, default=0, hot_reloadable=True),
|
||
# FR-08~14 功能开关(Task 30)
|
||
ConfigField(key="rich_message_enabled", type="bool", required=False, default=False, hot_reloadable=True),
|
||
ConfigField(key="status_writeback_enabled", type="bool", required=False, default=False, hot_reloadable=True),
|
||
ConfigField(key="agent_prompt_enabled", type="bool", required=False, default=False, hot_reloadable=True),
|
||
ConfigField(key="channel_tools_enabled", type="bool", required=False, default=False, hot_reloadable=True),
|
||
# AC-22: 消息操作开关默认"开"(FR-12)
|
||
ConfigField(key="message_ops_enabled", type="bool", required=False, default=True, hot_reloadable=True),
|
||
ConfigField(key="streaming_enabled", type="bool", required=False, default=False, hot_reloadable=True),
|
||
ConfigField(key="enable_typing", type="bool", required=False, default=True, hot_reloadable=True),
|
||
ConfigField(key="directory_enabled", type="bool", required=False, default=False, hot_reloadable=True),
|
||
ConfigField(key="command_enabled", type="bool", required=False, default=True, hot_reloadable=True),
|
||
# FR-12 消息操作细粒度开关(PRD §FR-12 配置项)。
|
||
# AC-22 默认行为:表情反应"开"、置顶"关"、卡片更新"关"。
|
||
ConfigField(key="enable_reaction", type="bool", required=False, default=True, hot_reloadable=True),
|
||
ConfigField(key="enable_pin", type="bool", required=False, default=False, hot_reloadable=True),
|
||
ConfigField(key="enable_card_update", type="bool", required=False, default=False, hot_reloadable=True),
|
||
# FR-15 管理员命令权限白名单(账户级,JSON 数组,存放允许执行 ADMIN 权限命令的 peer_id)
|
||
ConfigField(key="admin_users", type="json", required=False, default=None, hot_reloadable=True),
|
||
# FR-29 入站提及策略(账户级,JSON,含 allowed_implicit_kinds 列表,
|
||
# 控制哪些隐式提及类型被视为"已提及",未配置时默认空策略)
|
||
ConfigField(key="mention_policy", type="json", required=False, default=None, hot_reloadable=True),
|
||
# FR-07 会话合并策略开关(默认禁用)
|
||
ConfigField(key="merge_strategy_enabled", type="bool", required=False, default=False, hot_reloadable=True),
|
||
# FR-06 跨渠道身份策略(默认隔离,可选 association 开启跨渠道关联)
|
||
ConfigField(
|
||
key="cross_channel_identity_strategy", type="str", required=False, default="isolation", hot_reloadable=True
|
||
),
|
||
# 可配置值(Task 30)
|
||
ConfigField(key="command_prefix", type="str", required=False, default="/", hot_reloadable=True),
|
||
ConfigField(key="fence_ttl_seconds", type="int", required=False, default=120, hot_reloadable=True),
|
||
ConfigField(key="streaming_min_chunk_interval_ms", type="int", required=False, default=200, hot_reloadable=True),
|
||
ConfigField(key="streaming_ttl_seconds", type="int", required=False, default=60, hot_reloadable=True),
|
||
ConfigField(key="typing_ttl_ms", type="int", required=False, default=10000, hot_reloadable=True),
|
||
ConfigField(key="durability_policy_default", type="str", required=False, default="required", hot_reloadable=True),
|
||
# FR-24 分阶段 ACK 策略(PRD §FR-24)。
|
||
# 四阶段策略:after_record / after_agent_dispatch / after_persist / manual,
|
||
# 默认 after_agent_dispatch(平衡可靠性与响应速度)。
|
||
ConfigField(key="ack_policy", type="str", required=False, default="after_agent_dispatch", hot_reloadable=True),
|
||
# 手动策略下插件忘记 ACK 时核心兜底超时(默认 60s)自动 ACK。
|
||
ConfigField(key="ack_fallback_timeout_seconds", type="int", required=False, default=60, hot_reloadable=True),
|
||
# 传输引擎配置
|
||
ConfigField(key="transport.stall_timeout_ms", type="int", required=False, default=120000, hot_reloadable=True),
|
||
ConfigField(
|
||
key="transport.backoff_schedule", type="str", required=False, default="1,2,5,10,30", hot_reloadable=True
|
||
),
|
||
ConfigField(key="transport.backoff_jitter", type="float", required=False, default=0.2, hot_reloadable=True),
|
||
# FR-22 Outbox 重试策略(OBX-POLICY-UPDATE),JSON 格式:
|
||
# {"max_retry": int, "ttl_seconds": int, "retry_backoff_schedule": [int, ...]}
|
||
# 由 OutboxHandler.updateRetryPolicy 双写到 ConfigPort(Redis),
|
||
# 支持跨请求 / 跨进程最终一致性。
|
||
ConfigField(key="outbox_retry_policy", type="json", required=False, default=None, hot_reloadable=True),
|
||
# === 渠道用户与 Agent 交互链路优化(Task 6/7/8)===
|
||
# 身份解析置信度阈值(账户级,scope=ACCOUNT),低于此阈值的解析结果视为
|
||
# 未命中,进入 channel_guest 身份生成路径。缺口补齐:原 _getThreshold
|
||
# 使用硬编码默认值,现统一收敛至 CONFIG_SCHEMA。
|
||
ConfigField(key="identity_confidence_threshold", type="float", required=False, default=0.5, hot_reloadable=True),
|
||
# 新建 Agent 的默认渠道访问级别(全局级,scope=GLOBAL),取值如
|
||
# "none" / "read" / "write" 等,由 Agent 创建流程读取。
|
||
ConfigField(key="channel_access_default_level", type="str", required=False, default="none", hot_reloadable=True),
|
||
# 渠道访客身份置信度(全局级,scope=GLOBAL),channel_guest 身份生成时
|
||
# 使用此置信度,低于 identity_confidence_threshold 以避免被误判为
|
||
# 已解析身份。
|
||
ConfigField(key="channel_guest_confidence", type="float", required=False, default=0.3, hot_reloadable=True),
|
||
# 是否启用管理员手动绑定功能(全局级,scope=GLOBAL),控制渠道用户与
|
||
# 统一身份的手动绑定入口是否可用。
|
||
ConfigField(key="enable_channel_user_binding", type="bool", required=False, default=True, hot_reloadable=True),
|
||
# === 渠道账号运营流程优化(Task 14:契约层 CONFIG_SCHEMA 健康检查配置键)===
|
||
# 以下 2 个键均为渠道级(scope=CHANNEL),归属 ConfigPort(Redis 热重载,
|
||
# CHANNEL 业务策略体系),不得声明在 app_config。
|
||
# 凭证失效计数阈值。健康检查探活返回 401/403 时计入凭证失效计数,
|
||
# 达阈值后调聚合根 markFailed。窗口外(credential_failure_window_seconds)
|
||
# 重置计数。
|
||
ConfigField(key="credential_failure_threshold", type="int", required=False, default=3, hot_reloadable=True),
|
||
# 凭证失效计数窗口(秒)。窗口外的失效计数被重置,避免历史故障永久影响账号状态。
|
||
ConfigField(key="credential_failure_window_seconds", type="int", required=False, default=300, hot_reloadable=True),
|
||
# 审计日志保留策略(全局级,scope=GLOBAL)。JSON 格式:
|
||
# {"retention_days": int, "cleanup_interval_hours": int}
|
||
# 控制审计日志的保留天数与清理周期,由审计清理任务读取。
|
||
ConfigField(
|
||
key="audit_retention_policy",
|
||
type="json",
|
||
required=False,
|
||
default={"retention_days": 90, "cleanup_interval_hours": 24},
|
||
hot_reloadable=True,
|
||
),
|
||
# 扫码登录重定向 URI(全局级,scope=GLOBAL)。扫码登录成功后的前端跳转地址,
|
||
# 为空时使用默认跳转行为。
|
||
ConfigField(key="qr_login_redirect_uri", type="str", required=False, default="", hot_reloadable=True),
|
||
# === 不可热更新字段(hot_reloadable=False)===
|
||
ConfigField(key="webhook_port", type="int", required=False, default=None, hot_reloadable=False),
|
||
ConfigField(key="webhook_secret", type="str", required=False, default=None, hot_reloadable=False),
|
||
ConfigField(key="tls_cert", type="str", required=False, default=None, hot_reloadable=False),
|
||
ConfigField(key="tls_key", type="str", required=False, default=None, hot_reloadable=False),
|
||
ConfigField(key="plugin_entry", type="str", required=False, default=None, hot_reloadable=False),
|
||
ConfigField(key="database_url", type="str", required=False, default=None, hot_reloadable=False),
|
||
ConfigField(key="redis_url", type="str", required=False, default=None, hot_reloadable=False),
|
||
ConfigField(key="transport.max_restart_attempts", type="int", required=False, default=None, hot_reloadable=False),
|
||
ConfigField(
|
||
key="transport.graceful_shutdown_timeout_s", type="float", required=False, default=10.0, hot_reloadable=False
|
||
),
|
||
# === 渠道账号运营流程优化(Task 3:契约层 CONFIG_SCHEMA 凭证配置键)===
|
||
# 以下 3 个键均为账户级(scope=ACCOUNT),归属 ConfigPort(Redis 热重载,
|
||
# CHANNEL 业务策略/toggles/TTLs 体系),不得声明在 app_config。
|
||
# 凭证包,敏感字段加密存储。由 CredentialService 唯一写入入口维护,
|
||
# 包含 bot_token/app_secret/user_access_token 等渠道认证凭证。
|
||
ConfigField(key="credentials", type="dict", required=False, default=None, hot_reloadable=False),
|
||
# 登录态:unlogged/logging_in/logged_in/logout_failed。由 QrLoginService
|
||
# 通过 ConfigPort 维护,区分扫码会话状态与最终凭证落库状态。
|
||
ConfigField(key="login_status", type="str", required=False, default="unlogged", hot_reloadable=False),
|
||
# 凭证版本号,每次 rotateCredentials 自增。用于乐观锁控制与缓存失效判定。
|
||
ConfigField(key="credential_version", type="int", required=False, default=0, hot_reloadable=False),
|
||
# FR17-P0-3 已应用迁移列表(ACCOUNT 作用域,target=channel_type 或
|
||
# {channel_type}:{account_id})。由 PluginLifecycleManager 在插件 onStart
|
||
# 成功后追加 manifest.version 标记配置已加载,DoctorService 只读不写。
|
||
# hot_reloadable=False:非业务策略,启动期写入,无需热更新。
|
||
# default=[] 让首次加载时 ConfigPort.get 返回空列表而非 NotFoundError,
|
||
# 避免 PluginLifecycleManager 与 DoctorService 的 catch 块接不到异常。
|
||
ConfigField(key="applied_migrations", type="json", required=False, default=[], hot_reloadable=False),
|
||
)
|
||
|
||
# 可热更新的配置项键集合(FR-37),从 CONFIG_SCHEMA 派生。
|
||
HOT_RELOADABLE_KEYS = frozenset(f.key for f in CONFIG_SCHEMA if f.hot_reloadable)
|
||
|
||
# 不可热更新的配置项键集合(FR-37),从 CONFIG_SCHEMA 派生。
|
||
NON_HOT_RELOADABLE_KEYS = frozenset(f.key for f in CONFIG_SCHEMA if not f.hot_reloadable)
|
||
|
||
__all__ = ["CONFIG_SCHEMA", "HOT_RELOADABLE_KEYS", "NON_HOT_RELOADABLE_KEYS"]
|