修复通知渠道 schema 导出清单 (#6512)

* fix(schema): hide uuid factory from exports

* chore(architecture): refresh notification dependency baseline

* docs(architecture): sync dependency metrics

* fix(notification): type configuration schema

* chore(architecture): refresh schema dependency snapshot

* chore(architecture): sync notification type baselines

* chore(architecture): sync coverage snapshot

* fix(notification): preserve channel switch schema

* chore(schema): refresh export manifest
This commit is contained in:
InfinityPacer
2026-08-31 10:20:38 +08:00
committed by GitHub
parent e71a124f08
commit 35a19e622a
9 changed files with 31 additions and 22 deletions

View File

@@ -470,7 +470,6 @@ SCHEMA_EXPORTS = {
'json': ('app.schemas.subscribe', 'json'),
'model_validator': ('app.schemas.transfer', 'model_validator'),
're': ('app.schemas.file', 're'),
'uuid4': ('app.schemas.system', 'uuid4'),
}
SCHEMA_CONFLICTS = {

View File

@@ -1,7 +1,7 @@
from dataclasses import dataclass
from datetime import datetime as _DateTime
from typing import Optional, Any, Literal
from uuid import uuid4
from typing import Any, Literal, Optional
from uuid import uuid4 as _uuid4
from pydantic import BaseModel, Field, field_validator
@@ -91,15 +91,15 @@ class NotificationConf(BaseModel):
"""
# 稳定渠道身份;名称变化时保持不变,用于运行态凭据和跨页面引用。
id: str = Field(default_factory=lambda: str(uuid4()))
id: str = Field(default_factory=lambda: str(_uuid4()))
# 名称
name: Optional[str] = None
# 类型 telegram/wechat/feishu/vocechat/synologychat/slack/webpush/qqbot
type: Optional[str] = None
# 配置
config: Optional[dict] = Field(default_factory=dict)
# 场景开关
switchs: Optional[list] = Field(default_factory=list)
config: Optional[dict[str, Any]] = Field(default_factory=dict)
# 场景开关名称列表NotificationSwitchConf 属于全局通知范围配置,不是渠道字段。
switchs: Optional[list[str]] = Field(default_factory=list)
# 是否启用
enabled: Optional[bool] = False

View File

@@ -101,8 +101,8 @@ ARCH-201 至 ARCH-204 均达到实现、验证、提交、推送和远端门禁
| Event Contract | 53 | 均已有 payload model但当前全部是 diagnostic enforcement |
| Python 源码量 | 305,884 行 | 排除 `app/plugins/**`61 个文件超过 1,000 行11 个超过 2,000 行 |
| 长方法 | 290 个超过 80 行 | AST 统计排除 `app/plugins/**`65 个超过 150 行21 个超过 250 行 |
| 全量 mypy 历史债务 | 9,982 / 591 文件 | canonical `SearchChain` Facade 已补齐显式类型转发strict frontier 当前覆盖 41 个文件,低水位只允许继续下降 |
| Ruff 历史诊断 | 631 | 低水位门禁通过,但规则集只覆盖 `E4/E7/E9/F/I` |
| 全量 mypy 历史债务 | 9,986 / 591 文件 | canonical `SearchChain` Facade 已补齐显式类型转发strict frontier 当前覆盖 41 个文件,低水位只允许继续下降 |
| Ruff 历史诊断 | 630 | 低水位门禁通过,但规则集只覆盖 `E4/E7/E9/F/I` |
| 覆盖率低水位 | Application 81.80%Domain 81.03% | Chain、Runtime、Agent、Adapter、Startup 未进入包级覆盖率门禁 |
### 3.3 热点文件

View File

@@ -1,8 +1,8 @@
{
"application": {
"covered_lines": 12966,
"covered_lines": 12969,
"percent": 81.8,
"statements": 15851
"statements": 15854
},
"domain": {
"covered_lines": 3686,

View File

@@ -897,8 +897,8 @@
"type-arg": 3
},
"app/api/endpoints/notification.py": {
"misc": 1,
"no-untyped-def": 1
"misc": 2,
"no-untyped-def": 2
},
"app/api/endpoints/openai.py": {
"attr-defined": 1,
@@ -1803,7 +1803,7 @@
},
"app/modules/__init__.py": {
"assignment": 1,
"attr-defined": 3,
"attr-defined": 4,
"empty-body": 4,
"misc": 3,
"no-any-return": 1,
@@ -2856,17 +2856,17 @@
"empty-body": 1,
"no-any-return": 1,
"no-untyped-call": 1,
"no-untyped-def": 3,
"no-untyped-def": 4,
"type-arg": 2,
"union-attr": 1
},
"app/modules/wechatclawbot/wechatclawbot.py": {
"arg-type": 2,
"assignment": 1,
"assignment": 2,
"comparison-overlap": 3,
"no-any-return": 3,
"no-untyped-def": 4,
"type-arg": 1,
"type-arg": 2,
"union-attr": 1
},
"app/modules/zspace/__init__.py": {
@@ -3197,7 +3197,7 @@
"app/schemas/system.py": {
"assignment": 1,
"misc": 15,
"type-arg": 6
"type-arg": 4
},
"app/schemas/tmdb.py": {
"misc": 5

View File

@@ -717,9 +717,6 @@
"app/schemas/subscribe.py": {
"I001": 1
},
"app/schemas/system.py": {
"I001": 1
},
"app/schemas/types.py": {
"I001": 1
},

View File

@@ -4,7 +4,7 @@ from types import SimpleNamespace
from unittest.mock import MagicMock, patch
from app.agent.tools.impl.query_download_tasks import QueryDownloadTasksTool
from app.schemas.transfer import DownloadTaskMedia, DownloaderTorrent
from app.schemas.transfer import DownloaderTorrent, DownloadTaskMedia
from app.schemas.types import MediaSource

View File

@@ -766,6 +766,8 @@ def test_openapi_success_models_have_no_implicit_empty_nested_schemas():
"Response_Dict_str__Any__",
# LLM 提供商管理响应的 data 目录查询为列表、其余动作为映射。
"Response_Union_List_Dict_str__Any____Dict_str__Any___",
# 通知渠道配置由各渠道模块定义,保留动态键值以承载渠道特有选项。
"NotificationConf",
}
allowed_empty_components = {"McpJsonRpcEmptyResult"}
violations = []

View File

@@ -20,6 +20,17 @@ def test_notification_config_normalizes_names_and_rejects_duplicates():
)
def test_notification_channel_switches_keep_string_list_contract():
"""渠道场景开关仍按消息类型名称列表存储并参与匹配。"""
config = NotificationConf(
name="Alpha",
type="telegram",
switchs=["资源下载"],
)
assert config.switchs == ["资源下载"]
def test_reconcile_cached_states_migrates_renamed_identity_and_cleans_removed(monkeypatch):
values = {}