# Config System ## Design Goal 配置系统不是辅助功能,而是新系统的控制面基础设施。 目标: - 所有运行参数有统一来源 - 配置可被严格校验 - 配置可被 UI、CLI、文件三种方式修改 - 配置变更可审计 - 无效配置不得直接污染运行态 ## Design Principles 借鉴 OpenClaw 的做法,配置系统采用 `schema-first` 设计。 核心原则: - 所有配置项必须先声明在 schema 中 - 所有模块只能通过配置服务读取配置 - UI 表单由 schema 驱动渲染 - 保存前必须校验 - 校验失败不允许生效 - 配置有版本和变更记录 ## Config Sources ### 1. Default Config 系统默认值,由代码内置或默认配置文件提供。 ### 2. Active Config 当前生效的正式配置。 建议位置: - `biliup-next/config/settings.json` ### 3. Staged Config 用户在 UI 或 CLI 中提交、但尚未生效的待校验配置。 建议位置: - `biliup-next/config/settings.staged.json` ### 4. Schema 定义配置结构、类型、默认值、枚举范围、校验规则和 UI 元信息。 建议位置: - `biliup-next/config/settings.schema.json` ## Config Flow ```text User edits config -> Write staged config -> Validate against schema -> Run dependency checks -> If valid: promote to active -> If invalid: keep current active config ``` ## Validation Layers ### 1. Schema Validation 检查: - 类型 - 必填字段 - 枚举值 - 数值范围 - 字段格式 ### 2. Semantic Validation 检查: - 路径是否存在 - 可执行文件是否可用 - season id 是否合法 - 依赖组合是否冲突 ### 3. Runtime Validation 检查: - provider 是否可初始化 - 凭证是否存在 - 外部连接是否可用 ## Suggested Config Groups ### runtime - `workspace_dir` - `database_path` - `log_level` - `scan_interval_seconds` ### paths - `stage_dir` - `backup_dir` - `session_dir` - `cookies_file` - `upload_config_file` ### ingest - `provider` - `min_duration_seconds` - `ffprobe_bin` - `yt_dlp_cmd` - `allowed_extensions` ### transcribe - `provider` - `groq_api_key` - `max_file_size_mb` - `ffmpeg_bin` ### song_detect - `provider` - `codex_cmd` - `qwen_cmd` - `poll_interval_seconds` ### split - `ffmpeg_bin` - `poll_interval_seconds` ### publish - `provider` - `biliup_path` - `cookie_file` - `retry_count` - `retry_schedule_minutes` - `retry_backoff_seconds` ### comment - `enabled` - `max_retries` - `base_delay_seconds` - `poll_interval_seconds` ## Upload And Comment Templates `paths.upload_config_file` 指向 `runtime/upload_config.json`。这个文件不只控制 `biliup upload` 的标题、简介、动态和标签,也控制 B 站置顶评论格式。 投稿字段在 `template` 中: ```json { "template": { "title": "【{streamer} (歌曲纯享版)】 {date} 共{song_count}首歌", "description": "{streamer} {date} 歌曲纯享版。\n\n完整歌单与时间轴见置顶评论。\n直播完整版:{current_full_video_link}\n上次直播:{previous_full_video_link}", "tag": "可爱,王海颖,唱歌,音乐", "dynamic": "{streamer} {date} 歌曲纯享版已发布。\n直播完整版:{current_full_video_link}" } } ``` 评论字段在 `comment_template` 中: ```json { "comment_template": { "split_header": "当前视频:歌曲纯享版:只保留本场直播中的歌曲片段,歌单见下方。\n直播完整版:{current_full_video_link} (完整录播,含聊天/互动/完整流程)\n上次纯享:{previous_pure_video_link} (上一场歌曲纯享版)", "full_header": "当前视频:直播完整版:保留本场完整录播内容,歌曲时间轴见下方。\n歌曲纯享版:{current_pure_video_link} (只听歌曲看这里)\n上次完整版:{previous_full_video_link} (上一场完整录播)", "split_part_header": "P{part_index}:", "full_part_header": "P{part_index}:", "split_song_line": "{song_index}. {title}{artist_suffix}", "split_text_song_line": "{song_index}. {song_text}", "full_timeline_line": "{song_index}. {line_text}" } } ``` 可用变量: - `streamer`:主播名。 - `date`:从文件名解析出来的日期和时间。 - `song_count`:识别到的歌曲数量。 - `songs_list`:`songs.txt` 原始歌单内容。 - `daily_quote` / `quote_author`:随机引用文本。 - `current_full_video_bvid` / `current_full_video_link`:本场直播完整版 BV 和链接。 - `current_pure_video_bvid` / `current_pure_video_link`:本场歌曲纯享版 BV 和链接。 - `previous_full_video_bvid` / `previous_full_video_link`:上一场直播完整版 BV 和链接。 - `previous_pure_video_bvid` / `previous_pure_video_link`:上一场歌曲纯享版 BV 和链接。 - `part_index`:评论中的 `P1/P2/P3` 分段序号。 - `song_index`:全局歌曲序号。 - `title` / `artist` / `artist_suffix`:从 `songs.json` 生成纯享歌单时使用。 - `song_text`:从 `songs.txt` 兜底生成纯享歌单时使用,通常不含时间戳。 - `line_text`:完整版时间轴的原始行,通常包含时间戳。 评论头部模板有一条额外规则:如果某一行包含空链接变量,例如 `{previous_full_video_link}` 为空,这一整行会自动跳过,避免发出空链接提示。 Docker 部署时 `./runtime` 是宿主机挂载目录。镜像更新不会覆盖已有 `runtime/upload_config.json`,因此调整文案或评论格式时应修改宿主机上的这个文件,然后重启容器。 ### collection - `enabled` - `season_id_a` - `season_id_b` - `allow_fuzzy_full_video_match` - `append_collection_a_new_to_end` - `append_collection_b_new_to_end` ## UI Strategy 管理台不手写业务表单,而是由 schema 驱动生成配置界面。 每个配置项除了类型信息,还应有: - `title` - `description` - `group` - `ui:widget` - `ui:secret` - `ui:order` 这样可以让配置页面和底层配置保持同源。 ## Audit Trail 每次配置变更都应记录: - 修改人 - 修改时间 - 修改前值 - 修改后值 - 校验结果 - 是否已生效 ## Non-Goals - 不追求兼容任意格式的配置文件 - 不允许模块私自定义一份独立配置入口 - 不允许 UI 和代码维护两套不同的字段定义