From ddcaf0ead0b4ab1d779bf809989c1fbf29a5f01f Mon Sep 17 00:00:00 2001 From: InfinityPacer Date: Wed, 4 Nov 2026 02:31:32 +0800 Subject: [PATCH] refactor(settings): drop source line numbers from the settings catalog Co-Authored-By: Claude Opus 5.5 --- app/application/settings/contract.py | 4 - .../resources/system_settings_catalog.json | 950 ++++++------------ app/application/settings/service.py | 1 - app/schemas/types.py | 2 +- scripts/generate_system_settings_catalog.py | 18 +- tests/test_system_settings_contract.py | 11 +- 6 files changed, 339 insertions(+), 647 deletions(-) diff --git a/app/application/settings/contract.py b/app/application/settings/contract.py index c68d3d249..680c49fd0 100644 --- a/app/application/settings/contract.py +++ b/app/application/settings/contract.py @@ -138,7 +138,6 @@ class SettingSpec: :param sensitive: 是否包含需要脱敏展示的敏感值 :param systemconfig_key: 数据库配置对应的枚举键;运行配置时为 None :param source_file: 声明该设置的源文件路径,便于追溯 - :param source_line: 设置声明的源码行号;无法定位时为 0 """ key: str @@ -160,7 +159,6 @@ class SettingSpec: sensitive: bool = False systemconfig_key: Optional[SystemConfigKey] = None source_file: str = "" - source_line: int = 0 @dataclass(frozen=True, slots=True) @@ -648,7 +646,6 @@ def build_setting_specs() -> tuple[dict[str, SettingSpec], dict[str, SettingSpec ), sensitive=is_secret_setting_key(key), source_file=str(metadata.get("source_file") or ""), - source_line=int(metadata.get("source_line") or 0), ) system_specs: dict[str, SettingSpec] = {} @@ -686,7 +683,6 @@ def build_setting_specs() -> tuple[dict[str, SettingSpec], dict[str, SettingSpec sensitive=contract.sensitive, systemconfig_key=item, source_file=str(source_metadata.get("source_file") or ""), - source_line=int(source_metadata.get("source_line") or 0), ) return core_specs, system_specs diff --git a/app/application/settings/resources/system_settings_catalog.json b/app/application/settings/resources/system_settings_catalog.json index c2631cc98..b1af8c586 100644 --- a/app/application/settings/resources/system_settings_catalog.json +++ b/app/application/settings/resources/system_settings_catalog.json @@ -4,1888 +4,1574 @@ "ACCESS_TOKEN_EXPIRE_MINUTES": { "description": "TOKEN过期时间", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 206 + "source_file": "app/runtime/config.py" }, "ACOUSTID_API_KEY": { "description": "AcoustID 应用 API Key,用于查询本地音频的 Chromaprint 指纹", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 359 + "source_file": "app/runtime/config.py" }, "AGENT_BACKGROUND_DEFER_SECONDS": { "description": "交互活跃时非关键后台服务最多避让的秒数,0为不避让;不暂停已开始的任务", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 717 + "source_file": "app/runtime/config.py" }, "AGENT_INTERACTIVE_PRIORITY": { "description": "为交互式智能助手隔离执行容量,并让新启动的非关键后台服务有限避让", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 716 + "source_file": "app/runtime/config.py" }, "AGENT_LLM_TIMEOUT": { "description": "Agent单次模型请求的总超时秒数,包含供应商重试;0为不限制", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 718 + "source_file": "app/runtime/config.py" }, "AI_AGENT_ENABLE": { "description": "AI智能体开关", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 715 + "source_file": "app/runtime/config.py" }, "AI_AGENT_GLOBAL": { "description": "合局AI智能体", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 720 + "source_file": "app/runtime/config.py" }, "AI_AGENT_HIDE_ENTRY": { "description": "是否隐藏前端全局智能体入口", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 721 + "source_file": "app/runtime/config.py" }, "AI_AGENT_JOB_INTERVAL": { "description": "AI智能体定时任务检查间隔(小时),0为不启用,默认24小时", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 754 + "source_file": "app/runtime/config.py" }, "AI_AGENT_OUTPUT_LANGUAGE": { "description": "内置智能助手输出语言,默认使用简体中文", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 723 + "source_file": "app/runtime/config.py" }, "AI_AGENT_PET": { "description": "默认助手形象,格式为 插件ID:形象key,留空使用内置机器人;用户个人选择优先", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 722 + "source_file": "app/runtime/config.py" }, "AI_AGENT_RETRY_TRANSFER": { "description": "AI智能体自动重试整理失败记录开关", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 756 + "source_file": "app/runtime/config.py" }, "AI_AGENT_VERBOSE": { "description": "AI智能体啰嗦模式,开启后会回复工具调用过程", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 755 + "source_file": "app/runtime/config.py" }, "AI_RECOMMEND_ENABLED": { "description": "是否启用AI推荐", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 749 + "source_file": "app/runtime/config.py" }, "AI_RECOMMEND_MAX_ITEMS": { "description": "AI推荐条目数量限制", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 752 + "source_file": "app/runtime/config.py" }, "AI_RECOMMEND_USER_PREFERENCE": { "description": "AI推荐用户偏好", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 750 + "source_file": "app/runtime/config.py" }, "ALIPAN_APP_ID": { "description": "阿里云盘开放平台应用标识", "group": "cloud_storage", - "source_file": "app/runtime/config.py", - "source_line": 392 + "source_file": "app/runtime/config.py" }, "ALIPAN_SNAPSHOT_CHECK_FOLDER_MODTIME": { "description": "对阿里云盘进行快照对比时,是否检查文件夹的修改时间(默认关闭,因为阿里云盘目录时间不随子文件变更而更新)", "group": "storage", - "source_file": "app/runtime/config.py", - "source_line": 704 + "source_file": "app/runtime/config.py" }, "ALLOWED_HOSTS": { "description": "允许的跨域来源;为 \"*\" 时浏览器跨域请求不携带凭据,需要跨域带 Cookie 请列出显式来源", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 202 + "source_file": "app/runtime/config.py" }, "AMLL_BASE_URL": { "description": "AMLL TTML 歌词 API 地址,可指向兼容原生接口的自建实例", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 376 + "source_file": "app/runtime/config.py" }, "ANIME_GENREIDS": { "description": "电视剧动漫的分类genre_ids", "group": "media_metadata", - "source_file": "app/runtime/config.py", - "source_line": 334 + "source_file": "app/runtime/config.py" }, "API_DOCS_ENABLE": { "description": "是否开放 API 文档;开放 /docs、/redoc 与 /api/v1/openapi.json,文档首次生成后常驻约 20–30MB 内存,修改后立即生效", "group": "security", - "source_file": "app/runtime/config.py", - "source_line": 693 + "source_file": "app/runtime/config.py" }, "API_TOKEN": { "description": "API密钥,需要更换", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 211 + "source_file": "app/runtime/config.py" }, "API_V1_STR": { "description": "API路径", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 188 + "source_file": "app/runtime/config.py" }, "API_WORKERS": { "description": "API 服务的 worker 进程数。连接池是进程级的,每个 worker 各持一份,数据库连接额度校验按它换算总用量。注意:当前主程序以单进程方式启动(uvicorn.Config 的 workers 仅在多进程 supervisor 路径下生效),调大此项前需先解决调度器会在每个 worker 内重复执行的问题", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 218 + "source_file": "app/runtime/config.py" }, "APP_DOMAIN": { "description": "域名 格式;https://movie-pilot.org", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 187 + "source_file": "app/runtime/config.py" }, "ASYNC_FILE_QUEUE_SIZE": { "description": "异步文件日志队列容量", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 54 + "source_file": "app/runtime/log.py" }, "ASYNC_FILE_WORKERS": { "description": "保留历史配置解析兼容;协程环境文件日志已统一由单一有界队列 writer 执行。", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 55 + "source_file": "app/runtime/log.py" }, "AUDIO_INPUT_API_KEY": { "description": "音频输入 API 密钥", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 761 + "source_file": "app/runtime/config.py" }, "AUDIO_INPUT_BASE_URL": { "description": "音频输入基础URL", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 762 + "source_file": "app/runtime/config.py" }, "AUDIO_INPUT_LANGUAGE": { "description": "音频输入识别语言", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 764 + "source_file": "app/runtime/config.py" }, "AUDIO_INPUT_MODEL": { "description": "音频输入模型", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 763 + "source_file": "app/runtime/config.py" }, "AUDIO_INPUT_PROVIDER": { "description": "音频输入提供商:openai/openai_chat_audio/mimo/minimax", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 760 + "source_file": "app/runtime/config.py" }, "AUDIO_OUTPUT_API_KEY": { "description": "音频输出 API 密钥", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 766 + "source_file": "app/runtime/config.py" }, "AUDIO_OUTPUT_BASE_URL": { "description": "音频输出基础URL", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 767 + "source_file": "app/runtime/config.py" }, "AUDIO_OUTPUT_INCLUDE_TEXT": { "description": "回复语音时是否同时附带文字说明", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 770 + "source_file": "app/runtime/config.py" }, "AUDIO_OUTPUT_MODEL": { "description": "音频输出模型", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 768 + "source_file": "app/runtime/config.py" }, "AUDIO_OUTPUT_PROVIDER": { "description": "音频输出提供商:openai/openai_chat_audio/mimo/minimax", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 765 + "source_file": "app/runtime/config.py" }, "AUDIO_OUTPUT_VOICE": { "description": "音频输出音色/发音人", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 769 + "source_file": "app/runtime/config.py" }, "AUTH_SITE": { "description": "用户认证站点", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 215 + "source_file": "app/runtime/config.py" }, "AUTO_DOWNLOAD_USER": { "description": "交互搜索自动下载用户ID,使用,分割", "group": "downloads", - "source_file": "app/runtime/config.py", - "source_line": 505 + "source_file": "app/runtime/config.py" }, "AUTO_UPDATE_RESOURCE": { "description": "后台检查站点资源包,确认后由启动器在进程拉起前应用", "group": "system_update", - "source_file": "app/runtime/config.py", - "source_line": 406 + "source_file": "app/runtime/config.py" }, "AUXILIARY_AUTH_ENABLE": { "description": "辅助认证,允许通过外部服务进行认证、单点登录以及自动创建用户", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 210 + "source_file": "app/runtime/config.py" }, "BANGUMI_API_DOMAIN": { "description": "Bangumi API代理地址,留空使用官方地址", "group": "bangumi", - "source_file": "app/runtime/config.py", - "source_line": 346 + "source_file": "app/runtime/config.py" }, "BANGUMI_IMAGE_DOMAIN": { "description": "Bangumi图片代理地址,留空时由后端代理端点直接拉取原始图片", "group": "bangumi", - "source_file": "app/runtime/config.py", - "source_line": 347 + "source_file": "app/runtime/config.py" }, "BANGUMI_PROXY_ENABLE": { "description": "是否启用 Bangumi 数据与图片代理", "group": "bangumi", - "source_file": "app/runtime/config.py", - "source_line": 345 + "source_file": "app/runtime/config.py" }, "BATCH_WRITE_SIZE": { "description": "单批文件日志最大写入条数", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 56 + "source_file": "app/runtime/log.py" }, "BIG_MEMORY_MODE": { "description": "大内存模式", "group": "performance", - "source_file": "app/runtime/config.py", - "source_line": 652 + "source_file": "app/runtime/config.py" }, "BROWSER_EMULATION": { "description": "仿真类型:cloakbrowser 或 flaresolverr,其他值按 cloakbrowser 处理", "group": "sites", - "source_file": "app/runtime/config.py", - "source_line": 489 + "source_file": "app/runtime/config.py" }, "BTRFS_FSID_DEDUP": { "description": "是否启用 Btrfs FSID 子卷容量去重(仅 Linux amd64/arm64)", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 196 + "source_file": "app/runtime/config.py" }, "CACHE_BACKEND_TYPE": { "description": "缓存类型,支持 cachetools 和 redis,默认使用 cachetools", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 289 + "source_file": "app/runtime/config.py" }, "CACHE_BACKEND_URL": { "description": "缓存连接字符串,仅外部缓存(如 Redis、Memcached)需要,支持 Redis Unix Socket URL", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 290 + "source_file": "app/runtime/config.py" }, "CACHE_REDIS_MAXMEMORY": { "description": "Redis 缓存最大内存限制,未配置时,如开启大内存模式时为 \"1024mb\",未开启时为 \"256mb\"", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 294 + "source_file": "app/runtime/config.py" }, "CACHE_REDIS_MAX_CONNECTIONS": { "description": "Redis 单个连接池最大连接数;异步连接池按事件循环分别应用该上限", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 298 + "source_file": "app/runtime/config.py" }, "CACHE_REDIS_POOL_TIMEOUT": { "description": "Redis 连接池耗尽时等待可用连接的时间(秒)", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 299 + "source_file": "app/runtime/config.py" }, "CLOAKBROWSER_HUMANIZE": { "description": "CloakBrowser 是否启用拟人化输入", "group": "sites", - "source_file": "app/runtime/config.py", - "source_line": 493 + "source_file": "app/runtime/config.py" }, "CLOAKBROWSER_HUMAN_PRESET": { "description": "CloakBrowser 拟人化输入预设:default 或 careful", "group": "sites", - "source_file": "app/runtime/config.py", - "source_line": 494 + "source_file": "app/runtime/config.py" }, "COMMUNITY_MEDALS_ENABLE": { "description": "社区勋章:关闭后不查询服务端开关、不拉取勋章名单;开启时仍需 MoviePilot 服务端开放该功能", "group": "dependencies", - "source_file": "app/runtime/config.py", - "source_line": 637 + "source_file": "app/runtime/config.py" }, "CONFIG_DIR": { "description": "配置文件目录", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 194 + "source_file": "app/runtime/config.py" }, "COOKIECLOUD_AUTH_HEADER": { "description": "CookieCloud本地上传接口的X-CookieCloud-Auth期望值,留空表示不校验", "group": "cookiecloud", - "source_file": "app/runtime/config.py", - "source_line": 530 + "source_file": "app/runtime/config.py" }, "COOKIECLOUD_BLACKLIST": { "description": "CookieCloud同步黑名单,多个域名,分割", "group": "cookiecloud", - "source_file": "app/runtime/config.py", - "source_line": 535 + "source_file": "app/runtime/config.py" }, "COOKIECLOUD_ENABLE_LOCAL": { "description": "CookieCloud是否启动本地服务", "group": "cookiecloud", - "source_file": "app/runtime/config.py", - "source_line": 526 + "source_file": "app/runtime/config.py" }, "COOKIECLOUD_HOST": { "description": "CookieCloud服务器地址", "group": "cookiecloud", - "source_file": "app/runtime/config.py", - "source_line": 527 + "source_file": "app/runtime/config.py" }, "COOKIECLOUD_INTERVAL": { "description": "CookieCloud同步间隔(分钟)", "group": "cookiecloud", - "source_file": "app/runtime/config.py", - "source_line": 534 + "source_file": "app/runtime/config.py" }, "COOKIECLOUD_KEY": { "description": "CookieCloud用户KEY", "group": "cookiecloud", - "source_file": "app/runtime/config.py", - "source_line": 528 + "source_file": "app/runtime/config.py" }, "COOKIECLOUD_PASSWORD": { "description": "CookieCloud端对端加密密码", "group": "cookiecloud", - "source_file": "app/runtime/config.py", - "source_line": 529 + "source_file": "app/runtime/config.py" }, "CUSTOMIZE_WALLPAPER_API_URL": { "description": "自定义壁纸api地址", "group": "personalization", - "source_file": "app/runtime/config.py", - "source_line": 604 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_AGENT_CHAT_DAYS": { "description": "Agent 会话历史保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 283 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_AGENT_TASK_RUN_DAYS": { "description": "Agent 定时任务运行历史保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 284 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_DOWNLOAD_FAILURE_DAYS": { "description": "下载失败冷却记录保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 281 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_DOWNLOAD_HISTORY_DAYS": { "description": "下载历史表保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 278 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_ENABLE": { "description": "是否启用数据表定时清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 276 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_MESSAGE_DAYS": { "description": "消息表保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 277 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_OUTBOX_COMPLETED_DAYS": { "description": "Outbox 已完成记录保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 285 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_OUTBOX_DEAD_DAYS": { "description": "Outbox 死信记录保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 286 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_SITE_USERDATA_DAYS": { "description": "站点用户数据表保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 279 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_SUBSCRIBE_HISTORY_DAYS": { "description": "订阅完成历史保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 282 + "source_file": "app/runtime/config.py" }, "DATA_CLEANUP_TRANSFER_HISTORY_DAYS": { "description": "整理历史表保留天数,0为不清理", "group": "data_cleanup", - "source_file": "app/runtime/config.py", - "source_line": 280 + "source_file": "app/runtime/config.py" }, "DB_ASYNC_FALLBACK_LIMIT": { "description": "未被池化的事件循环(临时循环)共享的全局并发连接配额。池化路径由连接池自身限流,这里只为 NullPool 兜底路径补上背压,防止临时循环上的突发并发再次无界增长。实测常驻的 feishu/discord 循环不访问数据库,走此路径的只有插件与调度器兜底分支的零星调用,因此取值不必大——它直接计入连接总额度", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 253 + "source_file": "app/runtime/config.py" }, "DB_ASYNC_MAX_OVERFLOW": { "description": "异步连接池溢出数量(每个被池化的事件循环)", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 252 + "source_file": "app/runtime/config.py" }, "DB_ASYNC_POOL_SIZE": { "description": "异步连接池大小(每个被池化的事件循环)", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 251 + "source_file": "app/runtime/config.py" }, "DB_ASYNC_POOL_TYPE": { "description": "异步连接池类型:QueuePool / NullPool。NullPool 下每个异步会话独占一条物理连接、零复用且无上限,突发并发会直接顶穿PostgreSQL 的 max_connections(表现为 TooManyConnectionsError),在 SQLite 上则表现为 WAL 写争用导致的长时间卡顿。默认 QueuePool:仅对常驻主事件循环池化,其余事件循环自动回退 NullPool,避免跨循环复用连接。遇到兼容问题可设为 NullPool回到旧行为。", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 243 + "source_file": "app/runtime/config.py" }, "DB_BACKUP_CRON": { "description": "定时备份的 Cron 表达式,留空时不注册定时任务", "group": "database_backup", - "source_file": "app/runtime/config.py", - "source_line": 270 + "source_file": "app/runtime/config.py" }, "DB_BACKUP_ENABLE": { "description": "是否启用主程序数据库自动备份", "group": "database_backup", - "source_file": "app/runtime/config.py", - "source_line": 269 + "source_file": "app/runtime/config.py" }, "DB_BACKUP_MAX_COUNT": { "description": "本地备份的最大保留份数,0 表示不按数量清理", "group": "database_backup", - "source_file": "app/runtime/config.py", - "source_line": 274 + "source_file": "app/runtime/config.py" }, "DB_BACKUP_ON_UPGRADE": { "description": "检测到现有数据库需要迁移时,在结构变更前创建恢复点", "group": "database_backup", - "source_file": "app/runtime/config.py", - "source_line": 271 + "source_file": "app/runtime/config.py" }, "DB_BACKUP_PATH": { "description": "备份根目录;未配置时使用 CONFIG_PATH/database_backup", "group": "database_backup", - "source_file": "app/runtime/config.py", - "source_line": 272 + "source_file": "app/runtime/config.py" }, "DB_BACKUP_RETENTION_DAYS": { "description": "本地备份的保留天数,0 表示不按时间清理", "group": "database_backup", - "source_file": "app/runtime/config.py", - "source_line": 273 + "source_file": "app/runtime/config.py" }, "DB_CONNECT_ARGS": { "description": "驱动级连接参数,透传给 create_engine/create_async_engine 的 connect_args。例如经 PgBouncer 事务模式接入时 asyncpg 需要 {\"statement_cache_size\": 0}", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 260 + "source_file": "app/runtime/config.py" }, "DB_ECHO": { "description": "是否在控制台输出 SQL 语句,默认关闭", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 227 + "source_file": "app/runtime/config.py" }, "DB_POOL_PRE_PING": { "description": "是否在获取连接时进行预先 ping 操作", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 231 + "source_file": "app/runtime/config.py" }, "DB_POOL_RECYCLE": { "description": "数据库连接的回收时间(秒)", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 232 + "source_file": "app/runtime/config.py" }, "DB_POOL_TIMEOUT": { "description": "数据库连接池获取连接的超时时间(秒)", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 233 + "source_file": "app/runtime/config.py" }, "DB_POOL_TYPE": { "description": "数据库连接池类型,QueuePool, NullPool", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 230 + "source_file": "app/runtime/config.py" }, "DB_POSTGRESQL_DATABASE": { "description": "PostgreSQL 数据库名", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 238 + "source_file": "app/runtime/config.py" }, "DB_POSTGRESQL_HOST": { "description": "PostgreSQL 主机地址", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 236 + "source_file": "app/runtime/config.py" }, "DB_POSTGRESQL_MAX_OVERFLOW": { "description": "PostgreSQL 连接池溢出数量", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 242 + "source_file": "app/runtime/config.py" }, "DB_POSTGRESQL_PASSWORD": { "description": "PostgreSQL 密码", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 240 + "source_file": "app/runtime/config.py" }, "DB_POSTGRESQL_POOL_SIZE": { "description": "PostgreSQL 连接池大小", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 241 + "source_file": "app/runtime/config.py" }, "DB_POSTGRESQL_PORT": { "description": "PostgreSQL 端口;使用 Unix Socket 时可留空", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 237 + "source_file": "app/runtime/config.py" }, "DB_POSTGRESQL_USERNAME": { "description": "PostgreSQL 用户名", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 239 + "source_file": "app/runtime/config.py" }, "DB_SQLITE_MAX_OVERFLOW": { "description": "SQLite 连接池溢出数量", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 235 + "source_file": "app/runtime/config.py" }, "DB_SQLITE_POOL_SIZE": { "description": "SQLite 连接池大小", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 234 + "source_file": "app/runtime/config.py" }, "DB_TIMEOUT": { "description": "数据库连接超时时间(秒),默认为 60 秒", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 228 + "source_file": "app/runtime/config.py" }, "DB_TYPE": { "description": "数据库类型,支持 sqlite 和 postgresql,默认使用 sqlite", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 226 + "source_file": "app/runtime/config.py" }, "DB_WAL_ENABLE": { "description": "是否启用 WAL 模式,仅适用于SQLite,默认开启", "group": "database", - "source_file": "app/runtime/config.py", - "source_line": 229 + "source_file": "app/runtime/config.py" }, "DEBUG": { "description": "是否调试模式", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 197 + "source_file": "app/runtime/config.py" }, "DEFAULT_SUB": { "description": "为指定默认字幕添加.default后缀", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 585 + "source_file": "app/runtime/config.py" }, "DEPRECATION_ENABLED": { "description": "临时放行的废弃标识,多个用,分隔;仅对已进入停用阶段的接口有效,用于观察真实依赖方", "group": "plugins", - "source_file": "app/runtime/config.py", - "source_line": 614 + "source_file": "app/runtime/config.py" }, "DEV": { "description": "是否开发模式", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 198 + "source_file": "app/runtime/config.py" }, "DOH_DOMAINS": { "description": "使用 DOH 解析的域名列表", "group": "network", - "source_file": "app/runtime/config.py", - "source_line": 310 + "source_file": "app/runtime/config.py" }, "DOH_ENABLE": { "description": "是否启用DOH解析域名", "group": "network", - "source_file": "app/runtime/config.py", - "source_line": 309 + "source_file": "app/runtime/config.py" }, "DOH_RESOLVERS": { "description": "DOH 解析服务器列表", "group": "network", - "source_file": "app/runtime/config.py", - "source_line": 318 + "source_file": "app/runtime/config.py" }, "DOWNLOAD_SUBTITLE": { "description": "下载站点字幕", "group": "downloads", - "source_file": "app/runtime/config.py", - "source_line": 504 + "source_file": "app/runtime/config.py" }, "DOWNLOAD_TMPEXT": { "description": "下载器临时文件后缀", "group": "downloads", - "source_file": "app/runtime/config.py", - "source_line": 506 + "source_file": "app/runtime/config.py" }, "EMPTY_RESULT_CACHE_TTL": { "description": "TMDB空结果缓存独立过期时间(秒),故障期间产生的空响应快速过期,故障自愈后可自然恢复", "group": "tmdb", - "source_file": "app/runtime/config.py", - "source_line": 340 + "source_file": "app/runtime/config.py" }, "ENCODING_DETECTION_MIN_CONFIDENCE": { "description": "编码探测的最低置信度阈值", "group": "performance", - "source_file": "app/runtime/config.py", - "source_line": 658 + "source_file": "app/runtime/config.py" }, "ENCODING_DETECTION_PERFORMANCE_MODE": { "description": "是否启用编码探测的性能模式", "group": "performance", - "source_file": "app/runtime/config.py", - "source_line": 657 + "source_file": "app/runtime/config.py" }, "FANART_API_KEY": { "description": "Fanart 接口访问密钥", "group": "fanart", - "source_file": "app/runtime/config.py", - "source_line": 387 + "source_file": "app/runtime/config.py" }, "FANART_ENABLE": { "description": "Fanart开关", "group": "fanart", - "source_file": "app/runtime/config.py", - "source_line": 385 + "source_file": "app/runtime/config.py" }, "FANART_LANG": { "description": "Fanart语言", "group": "fanart", - "source_file": "app/runtime/config.py", - "source_line": 386 + "source_file": "app/runtime/config.py" }, "FEISHU_ADMINS": { "description": "飞书管理员 Open ID 列表,多个使用 , 分隔", "group": "feishu", - "source_file": "app/runtime/config.py", - "source_line": 647 + "source_file": "app/runtime/config.py" }, "FEISHU_APP_ID": { "description": "飞书应用 App ID", "group": "feishu", - "source_file": "app/runtime/config.py", - "source_line": 643 + "source_file": "app/runtime/config.py" }, "FEISHU_APP_SECRET": { "description": "飞书应用 App Secret", "group": "feishu", - "source_file": "app/runtime/config.py", - "source_line": 644 + "source_file": "app/runtime/config.py" }, "FEISHU_CHAT_ID": { "description": "飞书默认接收群聊 Chat ID", "group": "feishu", - "source_file": "app/runtime/config.py", - "source_line": 646 + "source_file": "app/runtime/config.py" }, "FEISHU_ENCRYPT_KEY": { "description": "飞书事件加密 Key", "group": "feishu", - "source_file": "app/runtime/config.py", - "source_line": 649 + "source_file": "app/runtime/config.py" }, "FEISHU_OPEN_ID": { "description": "飞书默认接收用户 Open ID", "group": "feishu", - "source_file": "app/runtime/config.py", - "source_line": 645 + "source_file": "app/runtime/config.py" }, "FEISHU_VERIFICATION_TOKEN": { "description": "飞书事件校验 Token", "group": "feishu", - "source_file": "app/runtime/config.py", - "source_line": 648 + "source_file": "app/runtime/config.py" }, "FLARESOLVERR_URL": { "description": "FlareSolverr 服务地址,例如 http://127.0.0.1:8191", "group": "sites", - "source_file": "app/runtime/config.py", - "source_line": 495 + "source_file": "app/runtime/config.py" }, "FRONTEND_PATH": { "description": "前端资源路径", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 189 + "source_file": "app/runtime/config.py" }, "FS_PROXY_ENABLED": { "description": "本地文件操作是否走可强杀的子进程代理。FUSE/网络挂载进入「请求永不返回」状态时,stat/listdir 这类调用会永久悬挂,而 Python 既不能中断已发出的系统调用、也不能强杀线程,阻塞其上的线程无法回收。走子进程后超时可以 SIGKILL 真正回收,block 型故障被转换成各层已能处理的crash 型故障(OSError)。出现兼容问题时可关闭回到直接调用。", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 543 + "source_file": "app/runtime/config.py" }, "FS_PROXY_STALL_TIMEOUT": { "description": "复制大文件时两次进度上报之间的最长间隔秒数。代理每秒上报一次进度作为心跳,因此这个阈值判定的是「传输完全没有推进」而不是「传输很慢」,复制几小时的大文件也不会被误杀", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 552 + "source_file": "app/runtime/config.py" }, "FS_PROXY_TIMEOUT": { "description": "单次本地快操作(stat/listdir/删除/重命名)的超时秒数,超时即判定挂载无响应并回收代理进程", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 551 + "source_file": "app/runtime/config.py" }, "GITHUB_PROXY": { "description": "Github代理服务器,格式:https://mirror.ghproxy.com/", "group": "dependencies", - "source_file": "app/runtime/config.py", - "source_line": 628 + "source_file": "app/runtime/config.py" }, "GITHUB_TOKEN": { "description": "GitHub Token 供 Agent 提交 Issue/PR 和访问 API;原文只保留在服务端运行配置中", "group": "dependencies", - "source_file": "app/runtime/config.py", - "source_line": 624 + "source_file": "app/runtime/config.py" }, "GLOBAL_IMAGE_CACHE": { "description": "全局图片缓存,将媒体图片缓存到本地", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 300 + "source_file": "app/runtime/config.py" }, "GLOBAL_IMAGE_CACHE_DAYS": { "description": "全局图片缓存保留天数", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 301 + "source_file": "app/runtime/config.py" }, "HOST": { "description": "API监听地址", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 191 + "source_file": "app/runtime/config.py" }, "IMAGE_PROXY_ALLOWED_PRIVATE_RANGES": { "description": "图片代理允许访问的非公网 IP/CIDR,默认不放行任何非公网解析结果", "group": "security", - "source_file": "app/runtime/config.py", - "source_line": 689 + "source_file": "app/runtime/config.py" }, "LLM_API_KEY": { "description": "LLM API密钥", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 738 + "source_file": "app/runtime/config.py" }, "LLM_API_PROTOCOL": { "description": "OpenAI兼容接口API协议:auto(自动)/ chat_completions / responses", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 730 + "source_file": "app/runtime/config.py" }, "LLM_BASE_URL": { "description": "LLM基础URL(用于自定义API端点)", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 739 + "source_file": "app/runtime/config.py" }, "LLM_BASE_URL_PRESET": { "description": "LLM Base URL 预设标识,用于区分同一 Base URL 下的不同模型目录", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 741 + "source_file": "app/runtime/config.py" }, "LLM_MAX_CONTEXT_TOKENS": { "description": "LLM最大上下文Token数量(K),用于目录缺失回退和未匹配兼容端点的用户上限", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 742 + "source_file": "app/runtime/config.py" }, "LLM_MAX_ITERATIONS": { "description": "LLM最大迭代次数", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 745 + "source_file": "app/runtime/config.py" }, "LLM_MAX_TOOLS": { "description": "LLM工具选择中间件最大工具数量,0为不启用工具选择中间件", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 753 + "source_file": "app/runtime/config.py" }, "LLM_MEMORY_RETENTION_DAYS": { "description": "内存记忆保留天数", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 748 + "source_file": "app/runtime/config.py" }, "LLM_MODEL": { "description": "LLM模型名称", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 725 + "source_file": "app/runtime/config.py" }, "LLM_PROVIDER": { "description": "LLM提供商(支持内置 provider,以及从 models.dev 动态补充的平台)", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 724 + "source_file": "app/runtime/config.py" }, "LLM_SUPPORT_AUDIO_INPUT": { "description": "是否启用音频输入,开启后用户语音会先转写为文本再进入 Agent", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 736 + "source_file": "app/runtime/config.py" }, "LLM_SUPPORT_AUDIO_OUTPUT": { "description": "是否启用音频输出,开启后 Agent 可在支持渠道发送语音回复", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 737 + "source_file": "app/runtime/config.py" }, "LLM_SUPPORT_IMAGE_INPUT": { "description": "LLM是否支持图片输入,开启后消息图片会按多模态输入发送给模型", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 735 + "source_file": "app/runtime/config.py" }, "LLM_TEMPERATURE": { "description": "LLM温度参数,留空时不覆盖提供商默认值", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 744 + "source_file": "app/runtime/config.py" }, "LLM_THINKING_LEVEL": { "description": "思考模式/深度配置:off/auto/minimal/low/medium/high/max/xhigh;OpenAI兼容接口保留max/xhigh,仅按已知模型能力降级", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 726 + "source_file": "app/runtime/config.py" }, "LLM_TOOL_TIMEOUT": { "description": "LLM工具调用超时时间(秒)", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 746 + "source_file": "app/runtime/config.py" }, "LLM_USER_AGENT": { "description": "LLM OpenAI兼容接口请求User-Agent", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 743 + "source_file": "app/runtime/config.py" }, "LLM_USE_PROXY": { "description": "LLM调用是否使用系统代理", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 740 + "source_file": "app/runtime/config.py" }, "LLM_VERBOSE": { "description": "是否启用详细日志", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 747 + "source_file": "app/runtime/config.py" }, "LLM_WEB_SEARCH_MODE": { "description": "联网搜索模式:local(本地)/ builtin(模型服务端)/ auto(自动)/ disabled(关闭)", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 731 + "source_file": "app/runtime/config.py" }, "LOCAL_EXISTS_SEARCH": { "description": "检查本地媒体库是否存在资源开关", "group": "subscriptions", - "source_file": "app/runtime/config.py", - "source_line": 482 + "source_file": "app/runtime/config.py" }, "LOG_BACKUP_COUNT": { "description": "每类日志保留的滚动备份文件数量", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 45 + "source_file": "app/runtime/log.py" }, "LOG_CONSOLE_FORMAT": { "description": "控制台日志格式", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 46 + "source_file": "app/runtime/log.py" }, "LOG_FILE_FORMAT": { "description": "文件日志格式", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 50 + "source_file": "app/runtime/log.py" }, "LOG_LEVEL": { "description": "全局日志等级", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 43 + "source_file": "app/runtime/log.py" }, "LOG_MAX_FILE_SIZE": { "description": "单个日志文件最大大小,单位 MB", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 44 + "source_file": "app/runtime/log.py" }, "LRCLIB_BASE_URL": { "description": "LRCLIB 服务地址,可指向兼容官方 API 的自建实例", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 375 + "source_file": "app/runtime/config.py" }, "LYRICS_BATCH_TIMEOUT": { "description": "单次音乐刮削批次用于在线歌词查询的总预算(秒)", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 377 + "source_file": "app/runtime/config.py" }, "LYRICS_PROVIDER_RETRY_MAX_WAIT": { "description": "供应商要求的重试等待超过该值时进入冷却,不阻塞整个批次", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 378 + "source_file": "app/runtime/config.py" }, "MAX_SEARCH_NAME_LIMIT": { "description": "最大搜索名称数量", "group": "search", - "source_file": "app/runtime/config.py", - "source_line": 499 + "source_file": "app/runtime/config.py" }, "MEDIASERVER_SYNC_INTERVAL": { "description": "媒体服务器同步间隔(小时)", "group": "media_servers", - "source_file": "app/runtime/config.py", - "source_line": 474 + "source_file": "app/runtime/config.py" }, "MEDIA_RECOGNIZE_SHARE": { "description": "共享使用媒体识别数据", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 588 + "source_file": "app/runtime/config.py" }, "MEDIA_RECOGNIZE_SHARE_API": { "description": "共享媒体识别API地址,留空时默认拼接为 MP_SERVER_HOST + /recognize/share", "group": "services", - "source_file": "app/runtime/config.py", - "source_line": 595 + "source_file": "app/runtime/config.py" }, "MEMORY_GC_INTERVAL": { "description": "主动内存回收时间间隔(分钟),0为不启用", "group": "performance", - "source_file": "app/runtime/config.py", - "source_line": 659 + "source_file": "app/runtime/config.py" }, "META_CACHE_EXPIRE": { "description": "单条元数据识别缓存有效期(小时),0为自动", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 305 + "source_file": "app/runtime/config.py" }, "MODULE_ENABLE": { "description": "无独立配置项的内置模块开关;未列出的模块默认开启。", "group": "media_metadata", - "source_file": "app/runtime/config.py", - "source_line": 321 + "source_file": "app/runtime/config.py" }, "MONITOR_NETWORK_FAST_MODE": { "description": "允许网络文件系统使用快速模式(inotify)。部分 FUSE 实现(如 CloudDrive2)会正常下发内核通知,快速模式可用,且比每 N 秒 stat 全部目录的轮询对挂载后端的压力小得多,由用户确认后开启", "group": "directory_monitor", - "source_file": "app/runtime/config.py", - "source_line": 509 + "source_file": "app/runtime/config.py" }, "MONITOR_POLL_DELAY_NETWORK": { "description": "网络文件系统的轮询扫描间隔(毫秒),0 表示使用内置默认值", "group": "directory_monitor", - "source_file": "app/runtime/config.py", - "source_line": 516 + "source_file": "app/runtime/config.py" }, "MONITOR_RESCAN_DELAYS": { "description": "新增目录延迟重扫的轮次延迟秒数,多个使用,分隔,如 \"30,120,600,1800\"。FUSE 挂载(如 CloudDrive2)上超大目录树呈现完整内容可能超过分钟级,默认值在常见的 30/120 秒窗口后追加两轮成本极低的长延迟轮次兜底;解析失败(如格式非法、包含非正整数)时回退默认值并记录 warn 日志", "group": "directory_monitor", - "source_file": "app/runtime/config.py", - "source_line": 517 + "source_file": "app/runtime/config.py" }, "MOVIEPILOT_AUTO_UPDATE": { "description": "自动检查稳定版本并提示升级,不自动下载或安装。", "group": "system_update", - "source_file": "app/runtime/config.py", - "source_line": 395 + "source_file": "app/runtime/config.py" }, "MOVIEPILOT_SAFE_MODE": { "description": "安全模式,仅保留核心 API,跳过插件、调度器、监控、命令和工作流等扩展启动项", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 195 + "source_file": "app/runtime/config.py" }, "MOVIEPILOT_UPDATE_DEV": { "description": "Docker 启动时跟踪开发分支;本地 CLI 仅在手动 update 时默认使用 DEV 模式。", "group": "system_update", - "source_file": "app/runtime/config.py", - "source_line": 403 + "source_file": "app/runtime/config.py" }, "MOVIE_RENAME_FORMAT": { "description": "电影重命名格式", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 565 + "source_file": "app/runtime/config.py" }, "MP_SERVER_HOST": { "description": "服务器地址,对应 https://github.com/jxxghp/MoviePilot-Server 项目", "group": "services", - "source_file": "app/runtime/config.py", - "source_line": 591 + "source_file": "app/runtime/config.py" }, "MUSIC_COVER_FILE_PATTERNS": { "description": "同目录音乐封面匹配规则,按顺序选择,逗号分隔、大小写不敏感;留空禁用本地封面", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 355 + "source_file": "app/runtime/config.py" }, "MUSIC_COVER_PROXY": { "description": "音乐封面代理地址(用于解决 coverartarchive.org 无法访问导致的封面不显示问题,留空则使用官方地址)", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 350 + "source_file": "app/runtime/config.py" }, "MUSIC_CUE_ENABLE": { "description": "是否读取关联 CUE;已分轨音频可关闭以忽略错误索引,整轨专辑应保持开启", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 365 + "source_file": "app/runtime/config.py" }, "MUSIC_LOCAL_COVER_ENABLE": { "description": "是否同步整理同目录音乐封面,并在在线封面不可用时用于内嵌回退", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 354 + "source_file": "app/runtime/config.py" }, "MUSIC_LYRICS_TO_SIMPLIFIED": { "description": "是否将写入 LRC/TXT 的歌词正文转为简体中文;保留时间轴、LRC 标签和来源 Lyricsfile", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 361 + "source_file": "app/runtime/config.py" }, "MUSIC_METADATA_TO_SIMPLIFIED": { "description": "是否将识别到的音乐标题、艺术家、专辑等标准元数据转换为简体中文", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 360 + "source_file": "app/runtime/config.py" }, "MUSIC_RELEASE_REGION_PRIORITY": { "description": "MusicBrainz 发行地区优先级,按 ISO 3166-1 两位代码从高到低排列", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 366 + "source_file": "app/runtime/config.py" }, "MUSIC_RELEASE_SCRIPT_PRIORITY": { "description": "MusicBrainz 发行文字字形优先级,按 ISO 15924 四位代码从高到低排列", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 370 + "source_file": "app/runtime/config.py" }, "MUSIC_RENAME_FORMAT": { "description": "音乐重命名格式", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 580 + "source_file": "app/runtime/config.py" }, "NGINX_PORT": { "description": "前端监听端口", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 193 + "source_file": "app/runtime/config.py" }, "NO_CACHE_SITE_KEY": { "description": "不缓存站点资源的域名关键字,多个使用,分隔;留空时所有站点使用缓存", "group": "sites", - "source_file": "app/runtime/config.py", - "source_line": 487 + "source_file": "app/runtime/config.py" }, "OCR_HOST": { "description": "OCR服务器地址,用于识别站点验证码", "group": "sites", - "source_file": "app/runtime/config.py", - "source_line": 488 + "source_file": "app/runtime/config.py" }, "OPENLIST_SNAPSHOT_CHECK_FOLDER_MODTIME": { "description": "对OpenList进行快照对比时,是否检查文件夹的修改时间", "group": "storage", - "source_file": "app/runtime/config.py", - "source_line": 703 + "source_file": "app/runtime/config.py" }, "PACKAGE_CACHE_DAYS": { "description": "pip/uv 包下载缓存保留天数", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 303 + "source_file": "app/runtime/config.py" }, "PACKAGE_CACHE_ROOT": { "description": "pip/uv 包下载缓存根目录,留空时使用配置目录下的 .cache", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 304 + "source_file": "app/runtime/config.py" }, "PASSKEY_REQUIRE_UV": { "description": "PassKey 是否强制用户验证(生物识别等)", "group": "security", - "source_file": "app/runtime/config.py", - "source_line": 692 + "source_file": "app/runtime/config.py" }, "PIP_PROXY": { "description": "pip镜像站点,格式:https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple", "group": "dependencies", - "source_file": "app/runtime/config.py", - "source_line": 629 + "source_file": "app/runtime/config.py" }, "PLAYWRIGHT_BROWSER_TYPE": { "description": "Playwright浏览器类型,供智能体浏览器工具和插件直接使用 Playwright 时读取", "group": "storage", - "source_file": "app/runtime/config.py", - "source_line": 709 + "source_file": "app/runtime/config.py" }, "PLUGIN_AUTO_RELOAD": { "description": "是否开启插件热加载", "group": "plugins", - "source_file": "app/runtime/config.py", - "source_line": 613 + "source_file": "app/runtime/config.py" }, "PLUGIN_INSTALL_FROM_RELEASE": { "description": "插件默认优先安装 Release 资产;false 直接安装当前索引文件,显式选择版本不受影响", "group": "plugins", - "source_file": "app/runtime/config.py", - "source_line": 633 + "source_file": "app/runtime/config.py" }, "PLUGIN_LOCAL_REPO_PATHS": { "description": "本地插件仓库目录,多个地址使用,分隔", "group": "plugins", - "source_file": "app/runtime/config.py", - "source_line": 615 + "source_file": "app/runtime/config.py" }, "PLUGIN_MARKET": { "description": "插件市场仓库地址,多个地址使用,分隔,地址以/结尾", "group": "plugins", - "source_file": "app/runtime/config.py", - "source_line": 607 + "source_file": "app/runtime/config.py" }, "PLUGIN_RELEASE_TIMEOUT": { "description": "插件 Release 元数据和资产各出口的请求超时秒数,默认 30,范围 1 至 300", "group": "plugins", - "source_file": "app/runtime/config.py", - "source_line": 637 + "source_file": "app/runtime/config.py" }, "PLUGIN_STATISTIC_SHARE": { "description": "插件安装数据共享", "group": "plugins", - "source_file": "app/runtime/config.py", - "source_line": 611 + "source_file": "app/runtime/config.py" }, "PORT": { "description": "API监听端口", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 192 + "source_file": "app/runtime/config.py" }, "PROJECT_NAME": { "description": "项目名称", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 186 + "source_file": "app/runtime/config.py" }, "PROXY_HOST": { "description": "网络代理服务器地址", "group": "network", - "source_file": "app/runtime/config.py", - "source_line": 308 + "source_file": "app/runtime/config.py" }, "RCLONE_SNAPSHOT_CHECK_FOLDER_MODTIME": { "description": "对rclone进行快照对比时,是否检查文件夹的修改时间", "group": "storage", - "source_file": "app/runtime/config.py", - "source_line": 702 + "source_file": "app/runtime/config.py" }, "RECOGNIZE_PLUGIN_FIRST": { "description": "优先使用辅助识别", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 587 + "source_file": "app/runtime/config.py" }, "RECOGNIZE_SOURCE": { "description": "媒体识别来源 themoviedb/douban/bangumi/anilist/imdb/musicbrainz/theaudiodb/doubanmusic", "group": "media_metadata", - "source_file": "app/runtime/config.py", - "source_line": 326 + "source_file": "app/runtime/config.py" }, "RENAME_FORMAT_S0_NAMES": { "description": "重命名时支持的S0别名", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 584 + "source_file": "app/runtime/config.py" }, "REPO_GITHUB_TOKEN": { "description": "指定的仓库Github token,多个仓库使用,分隔,格式:{user1}/{repo1}:ghp_****,{user2}/{repo2}:github_pat_****", "group": "dependencies", - "source_file": "app/runtime/config.py", - "source_line": 633 + "source_file": "app/runtime/config.py" }, "RESOURCE_ACCESS_TOKEN_EXPIRE_SECONDS": { "description": "RESOURCE_TOKEN过期时间", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 207 + "source_file": "app/runtime/config.py" }, "RESOURCE_SECRET_KEY": { "description": "RESOURCE密钥", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 201 + "source_file": "app/runtime/config.py" }, "RMT_AUDIOEXT": { "description": "支持的音轨文件后缀格式", "group": "media_formats", - "source_file": "app/runtime/config.py", - "source_line": 431 + "source_file": "app/runtime/config.py" }, "RMT_MEDIAEXT": { "description": "支持的视频文件后缀格式", "group": "media_formats", - "source_file": "app/runtime/config.py", - "source_line": 409 + "source_file": "app/runtime/config.py" }, "RMT_SUBEXT": { "description": "支持的字幕文件后缀格式", "group": "media_formats", - "source_file": "app/runtime/config.py", - "source_line": 430 + "source_file": "app/runtime/config.py" }, "RUST_ACCEL": { "description": "Rust 加速总开关,free-threaded 运行时固定启用", "group": "performance", - "source_file": "app/runtime/config.py", - "source_line": 653 + "source_file": "app/runtime/config.py" }, "SCHEDULER_JOB_TIMEOUT": { "description": "协程调度任务默认执行超时秒数,0为不限制;不强行终止同步线程", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 719 + "source_file": "app/runtime/config.py" }, "SCRAP_4K_BACKGROUND": { "description": "是否获取 Fanart 的 show4kbackground 和 movie4kbackground 图片", "group": "media_metadata", - "source_file": "app/runtime/config.py", - "source_line": 349 + "source_file": "app/runtime/config.py" }, "SCRAP_FOLLOW_TMDB": { "description": "新增已入库媒体是否跟随TMDB信息变化", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 586 + "source_file": "app/runtime/config.py" }, "SCRAP_IMAGE_ALIAS": { "description": "是否为背景图和缩略图写入兼容别名文件;关闭后每张图片只写入来源名称", "group": "media_metadata", - "source_file": "app/runtime/config.py", - "source_line": 345 + "source_file": "app/runtime/config.py" }, "SCRAP_SEASON_IMAGE_TO_ROOT": { "description": "季图片是否同时写入剧集根目录;关闭后仅写季目录,不清理已有图片", "group": "media_metadata", - "source_file": "app/runtime/config.py", - "source_line": 334 + "source_file": "app/runtime/config.py" }, "SCRAP_SOURCE": { "description": "刮削来源 themoviedb/douban/bangumi/anilist/imdb/musicbrainz/theaudiodb/doubanmusic", "group": "media_metadata", - "source_file": "app/runtime/config.py", - "source_line": 330 + "source_file": "app/runtime/config.py" }, "SEARCH_MULTIPLE_NAME": { "description": "搜索多个名称", "group": "search", - "source_file": "app/runtime/config.py", - "source_line": 498 + "source_file": "app/runtime/config.py" }, "SEARCH_RESOURCE_PAGES": { "description": "搜索资源获取页数", "group": "search", - "source_file": "app/runtime/config.py", - "source_line": 500 + "source_file": "app/runtime/config.py" }, "SEARCH_SOURCE": { "description": "媒体搜索来源 themoviedb/douban/bangumi/anilist/imdb/musicbrainz/theaudiodb/doubanmusic,多个用,分隔", "group": "media_metadata", - "source_file": "app/runtime/config.py", - "source_line": 322 + "source_file": "app/runtime/config.py" }, "SECRET_KEY": { "description": "密钥", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 200 + "source_file": "app/runtime/config.py" }, "SECURITY_IMAGE_DOMAINS": { "description": "允许的图片缓存域名", "group": "security", - "source_file": "app/runtime/config.py", - "source_line": 662 + "source_file": "app/runtime/config.py" }, "SECURITY_IMAGE_SUFFIXES": { "description": "允许的图片文件后缀格式", "group": "security", - "source_file": "app/runtime/config.py", - "source_line": 690 + "source_file": "app/runtime/config.py" }, "SITEDATA_REFRESH_INTERVAL": { "description": "站点数据刷新间隔(小时)", "group": "sites", - "source_file": "app/runtime/config.py", - "source_line": 485 + "source_file": "app/runtime/config.py" }, "SITE_MESSAGE": { "description": "读取和发送站点消息", "group": "sites", - "source_file": "app/runtime/config.py", - "source_line": 486 + "source_file": "app/runtime/config.py" }, "SKILL_MARKET": { "description": "技能市场仓库地址,多个地址使用,分隔", "group": "skills", - "source_file": "app/runtime/config.py", - "source_line": 618 + "source_file": "app/runtime/config.py" }, "SUBSCRIBE_MODE": { "description": "订阅模式", "group": "subscriptions", - "source_file": "app/runtime/config.py", - "source_line": 477 + "source_file": "app/runtime/config.py" }, "SUBSCRIBE_RSS_INTERVAL": { "description": "RSS订阅模式刷新时间间隔(分钟)", "group": "subscriptions", - "source_file": "app/runtime/config.py", - "source_line": 478 + "source_file": "app/runtime/config.py" }, "SUBSCRIBE_SEARCH": { "description": "订阅搜索开关", "group": "subscriptions", - "source_file": "app/runtime/config.py", - "source_line": 480 + "source_file": "app/runtime/config.py" }, "SUBSCRIBE_SEARCH_INTERVAL": { "description": "订阅搜索时间间隔(小时)", "group": "subscriptions", - "source_file": "app/runtime/config.py", - "source_line": 481 + "source_file": "app/runtime/config.py" }, "SUBSCRIBE_STATISTIC_SHARE": { "description": "订阅数据共享", "group": "subscriptions", - "source_file": "app/runtime/config.py", - "source_line": 479 + "source_file": "app/runtime/config.py" }, "SUPERUSER": { "description": "超级管理员用户名;V3 首次启动时为空,由初始化页面设置", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 208 + "source_file": "app/runtime/config.py" }, "SUPERUSER_PASSWORD": { "description": "超级管理员密码不再通过部署配置初始化,始终由数据库存储哈希", "group": "authentication", - "source_file": "app/runtime/config.py", - "source_line": 209 + "source_file": "app/runtime/config.py" }, "TEMP_FILE_DAYS": { "description": "临时文件保留天数", "group": "cache", - "source_file": "app/runtime/config.py", - "source_line": 302 + "source_file": "app/runtime/config.py" }, "THEAUDIODB_API_KEY": { "description": "TheAudioDB API Key,默认使用官方公开的免费 V1 Key,可通过环境变量覆盖", "group": "music", - "source_file": "app/runtime/config.py", - "source_line": 374 + "source_file": "app/runtime/config.py" }, "TMDB_API_DOMAIN": { "description": "TMDB API地址", "group": "tmdb", - "source_file": "app/runtime/config.py", - "source_line": 338 + "source_file": "app/runtime/config.py" }, "TMDB_API_KEY": { "description": "TMDB 接口访问密钥", "group": "tmdb", - "source_file": "app/runtime/config.py", - "source_line": 342 + "source_file": "app/runtime/config.py" }, "TMDB_IMAGE_DOMAIN": { "description": "TMDB图片地址", "group": "tmdb", - "source_file": "app/runtime/config.py", - "source_line": 337 + "source_file": "app/runtime/config.py" }, "TMDB_LOCALE": { "description": "TMDB元数据语言", "group": "tmdb", - "source_file": "app/runtime/config.py", - "source_line": 339 + "source_file": "app/runtime/config.py" }, "TMDB_SCRAP_ORIGINAL_IMAGE": { "description": "刮削使用TMDB原始语种图片", "group": "tmdb", - "source_file": "app/runtime/config.py", - "source_line": 341 + "source_file": "app/runtime/config.py" }, "TORRENT_TAG": { "description": "种子标签", "group": "downloads", - "source_file": "app/runtime/config.py", - "source_line": 503 + "source_file": "app/runtime/config.py" }, "TRANSFER_COPY_TRY_REFLINK": { "description": "本地文件复制时,在同一磁盘且支持写时复制时优先尝试引用链接 (reflink / 克隆)。若明确知晓底层文件系统不支持 CoW,可关闭此选项跳过探测直接进行全量复制以提升性能。", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 539 + "source_file": "app/runtime/config.py" }, "TRANSFER_FAILURE_NOTIFICATION_AGGREGATION": { "description": "是否按媒体聚合整理失败通知,关闭时保持逐条发送", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 757 + "source_file": "app/runtime/config.py" }, "TRANSFER_MAX_FAILED_RETRIES": { "description": "自动整理(目录监控、下载器轮询)遇到失败整理记录时,同一源路径允许自动重试的最大次数。一次瞬时故障(网络抖动、TMDB 瞬断、移动失败)不该让文件永久漏整理,因此必须重试;但永远识别不出的文件重试再多也不会成功,只会重复推送失败通知,批量导入时更会刷屏,因此必须有界。取值区间 1-10,越界或非法值会被钳制到边界并记录 warn:既不支持关闭重试,也不支持无限重试。整理成功或删除整理记录时计数清零。与本项无关的是同路径新版本:已成功整理的文件源大小变化时一律放行,由整理链的 overwrite_mode 决断是否覆盖", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 556 + "source_file": "app/runtime/config.py" }, "TRANSFER_SUCCESS_NOTIFICATION_AGGREGATION": { "description": "是否按批次聚合电影、电视剧和音乐的整理成功通知", "group": "ai_agent", - "source_file": "app/runtime/config.py", - "source_line": 758 + "source_file": "app/runtime/config.py" }, "TRANSFER_TASK_TIMEOUT": { "description": "外部接管的运行中整理任务无状态心跳超时(分钟),0 表示禁用", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 564 + "source_file": "app/runtime/config.py" }, "TRANSFER_THREADS": { "description": "文件整理线程数", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 538 + "source_file": "app/runtime/config.py" }, "TVDB_V4_API_KEY": { "description": "TVDB 接口访问密钥", "group": "tvdb", - "source_file": "app/runtime/config.py", - "source_line": 381 + "source_file": "app/runtime/config.py" }, "TVDB_V4_API_PIN": { "description": "TVDB V4 订阅 PIN", "group": "tvdb", - "source_file": "app/runtime/config.py", - "source_line": 382 + "source_file": "app/runtime/config.py" }, "TV_RENAME_FORMAT": { "description": "电视剧重命名格式", "group": "transfer", - "source_file": "app/runtime/config.py", - "source_line": 572 + "source_file": "app/runtime/config.py" }, "TZ": { "description": "时区", "group": "application", - "source_file": "app/runtime/config.py", - "source_line": 190 + "source_file": "app/runtime/config.py" }, "U115_APP_ID": { "description": "115 云盘开放平台应用标识", "group": "cloud_storage", - "source_file": "app/runtime/config.py", - "source_line": 390 + "source_file": "app/runtime/config.py" }, "U115_AUTH_SERVER": { "description": "115 OAuth2 Server 地址", "group": "cloud_storage", - "source_file": "app/runtime/config.py", - "source_line": 391 + "source_file": "app/runtime/config.py" }, "USAGE_STATISTIC_SHARE": { "description": "安装版本统计上报", "group": "plugins", - "source_file": "app/runtime/config.py", - "source_line": 612 + "source_file": "app/runtime/config.py" }, "WALLPAPER": { "description": "登录页面壁纸来源:空字符串表示无壁纸,另支持 tmdb/bing/mediaserver/customize/static", "group": "personalization", - "source_file": "app/runtime/config.py", - "source_line": 601 + "source_file": "app/runtime/config.py" }, "WALLPAPER_IMAGE_URL": { "description": "静态壁纸地址,可使用前端可访问的本地路径或 URL", "group": "personalization", - "source_file": "app/runtime/config.py", - "source_line": 603 + "source_file": "app/runtime/config.py" }, "WALLPAPER_ROTATION_INTERVAL": { "description": "壁纸轮换间隔(秒),0 表示不轮换", "group": "personalization", - "source_file": "app/runtime/config.py", - "source_line": 602 + "source_file": "app/runtime/config.py" }, "WORKFLOW_STATISTIC_SHARE": { "description": "工作流数据共享", "group": "workflow", - "source_file": "app/runtime/config.py", - "source_line": 699 + "source_file": "app/runtime/config.py" }, "WRITE_TIMEOUT": { "description": "日志写入等待超时时间,单位秒", "group": "logging", - "source_file": "app/runtime/log.py", - "source_line": 57 + "source_file": "app/runtime/log.py" } }, "systemconfig": { - "AppPushCredentials": { - "description": "App 中心推送自动接入的内部凭据状态;按服务地址隔离,不通过通知渠道配置下发", - "enum_name": "AppPushCredentials", - "source_file": "app/schemas/types.py", - "source_line": 430 - }, "AIAgentConfig": { "description": "AI智能体配置", "enum_name": "AIAgentConfig", - "source_file": "app/schemas/types.py", - "source_line": 493 + "source_file": "app/schemas/types.py" }, "AIAgentMcpServers": { "description": "AI智能体外部MCP服务器配置", "enum_name": "AIAgentMcpServers", - "source_file": "app/schemas/types.py", - "source_line": 497 + "source_file": "app/schemas/types.py" + }, + "AppPushCredentials": { + "description": "App 中心推送自动接入的内部凭据状态;按服务地址隔离,不通过通知渠道配置下发", + "enum_name": "AppPushCredentials", + "source_file": "app/schemas/types.py" }, "BestVersionFilterRuleGroups": { "description": "洗版默认过滤规则组", "enum_name": "BestVersionFilterRuleGroups", - "source_file": "app/schemas/types.py", - "source_line": 466 + "source_file": "app/schemas/types.py" }, "CustomFilterRules": { "description": "用户自定义规则", "enum_name": "CustomFilterRules", - "source_file": "app/schemas/types.py", - "source_line": 454 + "source_file": "app/schemas/types.py" }, "CustomIdentifiers": { "description": "自定义识别词", "enum_name": "CustomIdentifiers", - "source_file": "app/schemas/types.py", - "source_line": 446 + "source_file": "app/schemas/types.py" }, "CustomReleaseGroups": { "description": "自定义制作组/字幕组", "enum_name": "CustomReleaseGroups", - "source_file": "app/schemas/types.py", - "source_line": 442 + "source_file": "app/schemas/types.py" }, "Customization": { "description": "自定义占位符", "enum_name": "Customization", - "source_file": "app/schemas/types.py", - "source_line": 444 + "source_file": "app/schemas/types.py" }, "DefaultMovieSubscribeConfig": { "description": "默认电影订阅规则", "enum_name": "DefaultMovieSubscribeConfig", - "source_file": "app/schemas/types.py", - "source_line": 481 + "source_file": "app/schemas/types.py" }, "DefaultMusicSubscribeConfig": { "description": "默认音乐订阅规则", "enum_name": "DefaultMusicSubscribeConfig", - "source_file": "app/schemas/types.py", - "source_line": 485 + "source_file": "app/schemas/types.py" }, "DefaultTvSubscribeConfig": { "description": "默认电视剧订阅规则", "enum_name": "DefaultTvSubscribeConfig", - "source_file": "app/schemas/types.py", - "source_line": 483 + "source_file": "app/schemas/types.py" }, "Directories": { "description": "目录配置", "enum_name": "Directories", - "source_file": "app/schemas/types.py", - "source_line": 432 + "source_file": "app/schemas/types.py" }, "Downloaders": { "description": "下载器配置", "enum_name": "Downloaders", - "source_file": "app/schemas/types.py", - "source_line": 424 + "source_file": "app/schemas/types.py" }, "EpisodeFormatRuleTable": { "description": "集数定位规则词表", "enum_name": "EpisodeFormatRuleTable", - "source_file": "app/schemas/types.py", - "source_line": 448 + "source_file": "app/schemas/types.py" }, "FollowSubscribers": { "description": "Follow订阅分享者", "enum_name": "FollowSubscribers", - "source_file": "app/schemas/types.py", - "source_line": 489 + "source_file": "app/schemas/types.py" }, "GithubAuth": { "description": "GitHub OAuth 设备授权元数据", "enum_name": "GithubAuth", - "source_file": "app/schemas/types.py", - "source_line": 495 + "source_file": "app/schemas/types.py" }, "IndexerSites": { "description": "搜索站点范围", "enum_name": "IndexerSites", - "source_file": "app/schemas/types.py", - "source_line": 438 + "source_file": "app/schemas/types.py" }, "MediaClassificationPolicy": { "description": "多媒体自动分类策略及其有界历史", "enum_name": "MediaClassificationPolicy", - "source_file": "app/schemas/types.py", - "source_line": 511 + "source_file": "app/schemas/types.py" }, "MediaRecognizeShareCount": { "description": "共享媒体识别成功次数", "enum_name": "MediaRecognizeShareCount", - "source_file": "app/schemas/types.py", - "source_line": 509 + "source_file": "app/schemas/types.py" }, "MediaServers": { "description": "媒体服务器配置", "enum_name": "MediaServers", - "source_file": "app/schemas/types.py", - "source_line": 426 + "source_file": "app/schemas/types.py" }, "MountedLocalDiskDeleteEmptyDirs": { "description": "挂载型本地盘是否删除空目录", "enum_name": "MountedLocalDiskDeleteEmptyDirs", - "source_file": "app/schemas/types.py", - "source_line": 434 + "source_file": "app/schemas/types.py" }, "NotificationClearBefore": { "description": "通知中心清理时间", "enum_name": "NotificationClearBefore", - "source_file": "app/schemas/types.py", - "source_line": 501 + "source_file": "app/schemas/types.py" }, "NotificationSendTime": { "description": "通知发送时间", "enum_name": "NotificationSendTime", - "source_file": "app/schemas/types.py", - "source_line": 491 + "source_file": "app/schemas/types.py" }, "NotificationSwitchs": { "description": "通知场景开关设置", "enum_name": "NotificationSwitchs", - "source_file": "app/schemas/types.py", - "source_line": 430 + "source_file": "app/schemas/types.py" }, "NotificationTemplates": { "description": "通知消息格式模板", "enum_name": "NotificationTemplates", - "source_file": "app/schemas/types.py", - "source_line": 499 + "source_file": "app/schemas/types.py" }, "Notifications": { "description": "消息通知配置", "enum_name": "Notifications", - "source_file": "app/schemas/types.py", - "source_line": 428 + "source_file": "app/schemas/types.py" }, "PluginFolders": { "description": "插件文件夹分组配置", "enum_name": "PluginFolders", - "source_file": "app/schemas/types.py", - "source_line": 479 + "source_file": "app/schemas/types.py" }, "PluginInstallReport": { "description": "插件安装统计", "enum_name": "PluginInstallReport", - "source_file": "app/schemas/types.py", - "source_line": 505 + "source_file": "app/schemas/types.py" }, "PluginInstances": { "description": "共享源码插件的虚拟运行实例(已迁移到独立表,本键保留作回滚依据)", "enum_name": "PluginInstances", - "source_file": "app/schemas/types.py", - "source_line": 474 + "source_file": "app/schemas/types.py" }, "PluginInstancesImported": { "description": "上面那个旧键各条目导入独立表时的内容指纹 {实例ID: 摘要},据此识别回滚到旧版本 后新增或改写过的条目,同时避免把用户删掉的分身重新导回", "enum_name": "PluginInstancesImported", - "source_file": "app/schemas/types.py", - "source_line": 477 + "source_file": "app/schemas/types.py" }, "RssSites": { "description": "订阅站点范围", "enum_name": "RssSites", - "source_file": "app/schemas/types.py", - "source_line": 440 + "source_file": "app/schemas/types.py" }, "ScrapingSwitchs": { "description": "刮削开关设置", "enum_name": "ScrapingSwitchs", - "source_file": "app/schemas/types.py", - "source_line": 503 + "source_file": "app/schemas/types.py" }, "SearchFilterRuleGroups": { "description": "搜索默认过滤规则组", "enum_name": "SearchFilterRuleGroups", - "source_file": "app/schemas/types.py", - "source_line": 458 + "source_file": "app/schemas/types.py" }, "Storages": { "description": "存储配置", "enum_name": "Storages", - "source_file": "app/schemas/types.py", - "source_line": 436 + "source_file": "app/schemas/types.py" }, "SubscribeDefaultParams": { "description": "订阅默认参数", "enum_name": "SubscribeDefaultParams", - "source_file": "app/schemas/types.py", - "source_line": 464 + "source_file": "app/schemas/types.py" }, "SubscribeFilterRuleGroups": { "description": "订阅默认过滤规则组", "enum_name": "SubscribeFilterRuleGroups", - "source_file": "app/schemas/types.py", - "source_line": 460 + "source_file": "app/schemas/types.py" }, "SubscribeReport": { "description": "订阅统计", "enum_name": "SubscribeReport", - "source_file": "app/schemas/types.py", - "source_line": 468 + "source_file": "app/schemas/types.py" }, "SubscribeSearchStrategy": { "description": "补全搜索策略:smart 默认、full 全量、single_page 仅第一页;洗版始终全量", "enum_name": "SubscribeSearchStrategy", - "source_file": "app/schemas/types.py", - "source_line": 462 + "source_file": "app/schemas/types.py" }, "TorrentsPriority": { "description": "种子优先级规则", "enum_name": "TorrentsPriority", - "source_file": "app/schemas/types.py", - "source_line": 452 + "source_file": "app/schemas/types.py" }, "TransferExcludeWords": { "description": "转移屏蔽词", "enum_name": "TransferExcludeWords", - "source_file": "app/schemas/types.py", - "source_line": 450 + "source_file": "app/schemas/types.py" }, "UgreenSessionCache": { "description": "绿联影视登录会话缓存", "enum_name": "UgreenSessionCache", - "source_file": "app/schemas/types.py", - "source_line": 507 + "source_file": "app/schemas/types.py" }, "UserCustomCSS": { "description": "用户自定义CSS", "enum_name": "UserCustomCSS", - "source_file": "app/schemas/types.py", - "source_line": 470 + "source_file": "app/schemas/types.py" }, "UserFilterRuleGroups": { "description": "用户规则组", "enum_name": "UserFilterRuleGroups", - "source_file": "app/schemas/types.py", - "source_line": 456 + "source_file": "app/schemas/types.py" }, "UserInstalledPlugins": { "description": "用户已安装的插件", "enum_name": "UserInstalledPlugins", - "source_file": "app/schemas/types.py", - "source_line": 472 + "source_file": "app/schemas/types.py" }, "UserSiteAuthParams": { "description": "用户站点认证参数", "enum_name": "UserSiteAuthParams", - "source_file": "app/schemas/types.py", - "source_line": 487 + "source_file": "app/schemas/types.py" } } } diff --git a/app/application/settings/service.py b/app/application/settings/service.py index 36a2f032c..6953f2ed0 100644 --- a/app/application/settings/service.py +++ b/app/application/settings/service.py @@ -391,7 +391,6 @@ class SystemSettingsService: ), "source": { "file": spec.source_file, - "line": spec.source_line, }, } if include_schema: diff --git a/app/schemas/types.py b/app/schemas/types.py index c950e5dc8..8b7f153d3 100644 --- a/app/schemas/types.py +++ b/app/schemas/types.py @@ -426,7 +426,7 @@ class SystemConfigKey(Enum): MediaServers = "MediaServers" # 消息通知配置 Notifications = "Notifications" - # App 中心推送自动接入凭据,业务内部维护且不进入通知渠道配置 + # App 中心推送自动接入的内部凭据状态;按服务地址隔离,不通过通知渠道配置下发 AppPushCredentials = "AppPushCredentials" # 通知场景开关设置 NotificationSwitchs = "NotificationSwitchs" diff --git a/scripts/generate_system_settings_catalog.py b/scripts/generate_system_settings_catalog.py index d983c86a0..c059db30a 100644 --- a/scripts/generate_system_settings_catalog.py +++ b/scripts/generate_system_settings_catalog.py @@ -162,7 +162,7 @@ def _extract_model_fields( default_group: str | None = None, ) -> dict[str, dict[str, Any]]: """ - 提取 Pydantic 配置模型字段的说明、分类和源码位置。 + 提取 Pydantic 配置模型字段的说明、分类和源文件。 """ module, lines = _load_module(path) class_node = _find_class(module, class_name) @@ -186,14 +186,13 @@ def _extract_model_fields( "description": description, "group": group, "source_file": str(path.relative_to(PROJECT_ROOT)), - "source_line": node.lineno, } return results def _extract_systemconfig_fields(path: Path) -> dict[str, dict[str, Any]]: """ - 提取 SystemConfigKey 枚举值的业务说明和源码位置。 + 提取 SystemConfigKey 枚举值的业务说明和源文件。 """ module, lines = _load_module(path) class_node = _find_class(module, "SystemConfigKey") @@ -207,7 +206,6 @@ def _extract_systemconfig_fields(path: Path) -> dict[str, dict[str, Any]]: "enum_name": field_name, "description": " ".join(_preceding_comments(lines, node.lineno, exclude_sections=False)).strip(), "source_file": str(path.relative_to(PROJECT_ROOT)), - "source_line": node.lineno, } return results @@ -272,15 +270,19 @@ def generate_catalog() -> dict[str, Any]: } +def render_catalog() -> str: + """ + 按稳定的键序和缩进序列化来源目录,生成与一致性测试共用同一输出格式。 + """ + return json.dumps(generate_catalog(), ensure_ascii=False, indent=2, sort_keys=True) + "\n" + + def main() -> int: """ 写入格式稳定的系统设置来源目录。 """ OUTPUT_PATH.parent.mkdir(parents=True, exist_ok=True) - OUTPUT_PATH.write_text( - json.dumps(generate_catalog(), ensure_ascii=False, indent=2, sort_keys=True) + "\n", - encoding="utf-8", - ) + OUTPUT_PATH.write_text(render_catalog(), encoding="utf-8") print(f"generated {OUTPUT_PATH.relative_to(PROJECT_ROOT)}") return 0 diff --git a/tests/test_system_settings_contract.py b/tests/test_system_settings_contract.py index 49b9b076f..089de2977 100644 --- a/tests/test_system_settings_contract.py +++ b/tests/test_system_settings_contract.py @@ -20,6 +20,7 @@ from app.application.settings.contract import ( ) from app.runtime.config import Settings from app.schemas.types import SystemConfigKey +from scripts import generate_system_settings_catalog as catalog_generator def test_subscription_search_strategy_contract_declares_three_choices() -> None: @@ -51,7 +52,6 @@ def test_settings_contract_covers_every_declared_source() -> None: assert spec.description assert spec.group assert spec.source_file - assert spec.source_line > 0 schema = build_value_schema(spec) assert schema.get("description") == spec.description assert isinstance(schema, dict) @@ -227,3 +227,12 @@ def test_system_setting_operations_expose_the_three_stage_contract() -> None: update_body_ref = branches["config.system.update"]["properties"]["body"]["$ref"] update_body = schema["$defs"][update_body_ref.rsplit("/", 1)[-1]] assert "expected_revision" in update_body["properties"] + + +def test_system_settings_catalog_matches_source_declarations() -> None: + """ + 来源目录必须由生成脚本从源码注释产出;手工修改目录或改注释后未重新生成都会在这里失败。 + """ + assert catalog_generator.OUTPUT_PATH.read_text(encoding="utf-8") == catalog_generator.render_catalog(), ( + "请运行 python scripts/generate_system_settings_catalog.py 重新生成系统设置来源目录" + )