飞行雪绒 DOCS

鸣潮·爱弥斯纪念桌宠 · LTS1.0.6beta8

使用与维护 · M1

维护手册

最完整的一份运维文档:目录职责、配置体系、用户数据边界与常见故障排查。

源文件 doc/维护手册.md 更新 2026-07-31 17.4 KB 在 GitHub 查看

飞行雪绒维护手册#

更新时间:2026-07-31

本手册面向维护者和代码代理,说明当前工程边界、常见变更路径和验收方式。开始工作前先读 doc/AI协作规范.md,再按任务阅读专项文档。

1. 事实源与优先级#

发生冲突时按以下顺序判断:

  1. 可执行源码与测试。
  2. 本手册和 doc/README.md
  3. 事件、游戏包等专项协议文档。
  4. 根目录 README、贡献和发布说明。
  5. 历史计划、整改清单和更新日志。
内容 权威位置
应用版本 config/version_info.py
默认配置 config/config_*.py
用户稀疏覆盖 config/user_settings.py
用户目录布局 config/user_storage_paths.py
事件类型与派发 lib/core/event/center.py
工作台页面元数据 lib/script/workbench/page_registry.pysettings/schema.py
音乐公开接口 lib/script/music/
游戏包契约 doc/游戏包格式.mdgame_packages.py
依赖集合 requirements*.txt
发行文件边界 scripts/package_*.pyrelease_common.py

2. 启动与退出#

启动链路#

启动程序.bat / 调试模式.bat
  -> lib/core/qt_desktop_pet.py
  -> lib/script/main.py::main
  -> ApplicationState
  -> APP_PRE_START / APP_INIT_READY / APP_START / APP_MAIN

ApplicationState 负责单实例、Qt 应用、主窗口、管理器、托盘、预加载和最终清理。长生命周期组件不得绕过它自行结束应用。

主界面就绪后,AnnouncementController 从固定 Gitee RESC 发布槽异步下载桌宠公告。公告文件使用按出现顺序解析的 titlesubtitletext 引号块,可重复出现多个 subtitletext;正文窗口保持紧凑并独立滚动。用户可仅抑制当日自动显示或永久抑制自动显示,状态写入 <用户根>/user/state/announcement.json,最近一次成功内容缓存到 <用户根>/cache/announcement.txt。“界面与动画”页的“不显示公告”复选框读取并修改同一份永久抑制状态,取消勾选不会清除当日抑制。托盘“桌宠公告”入口不受自动显示偏好限制;每次手动打开都先进入加载态并发起独立的无缓存请求,只接受最后一次请求的结果,网络失败时才回退到本地缓存。

退出链路#

正常退出由 ApplicationState.request_exit() 发起,依次停止主窗口、清理运行时服务、清理视觉组件并退出 Qt 事件循环。APP_EXIT 广播退出阶段,APP_QUIT 请求主编排器开始退出。

最后一个退出阶段使用带退出码的 QApplication.exit(),处理 DeferredDelete 后等待 aboutToQuit 确认;未确认时会关闭残留顶层窗口并再次请求正常退出。事件循环返回后还要短暂等待非守护线程结束。15 秒进程级 watchdog 只作为整个退出链路卡死时的最终兜底,正常收尾确认后必须取消。

需要重启时向 APP_QUIT 传入 restart: true。主编排器必须先成功拉起脱离当前进程树的重启 helper,再走完整退出流程并释放单实例锁;helper 等待旧 PID 真正退出后启动新实例。helper 创建失败时不得退出当前实例。重启 helper 不属于本地托管服务,服务清理不得结束它;界面组件也不得自行拉起副本。启动阶段诊断写入 logs/restart.log

分发包更新使用独立的更新 helper:主进程只并发检测固定 GitHub/Gitee 发布槽、下载并校验 ZIP,成功创建 helper 后通过普通 APP_QUIT 优雅退出,不再由主进程覆盖文件,也不再创建普通重启 helper。更新 helper 必须确认旧 PID 已退出,随后保护 logs/resc/user/resc/models/py.ini,覆盖程序文件、写入更新状态并启动新实例。等待超时或覆盖失败时不得启动半更新实例,诊断写入 logs/update.log

维护约束:

  • 新增长生命周期对象必须提供幂等 cleanup()
  • 事件订阅必须有对称 unsubscribe()
  • 网络流设置有限连接/读取超时,并在 cleanup 时关闭活动响应。
  • 子进程保存句柄;先正常终止,超时后结束进程树。
  • 后台任务统一使用 lib/core/compute_hub.py,不得新建无所有者线程池。
  • 用户点击后必须立即开始的长耗时 I/O 使用 ComputeHub.submit_interactive_io() 的保留执行槽,不能排在登录、音乐下载等共享后台队列之后。
  • os._exit() 只能作为最终超时兜底。

3. 模块边界#

核心层 lib/core#

核心层包含事件、绘制、层级、输入、物理、调度、日志和主宠窗口。业务模块可以依赖核心层,核心层不得反向依赖具体 provider 或工作台页面。

  • 绘制排序:render_core.pyrender_layer.py
  • 业务绘制入口:draw_core.pyunified_draw.py
  • 窗口层级:layer_manager.py
  • 事件中心:event/center.py
  • 后台执行:compute_hub.py

core/objectcore/render 包和 topmost_manager.py 已删除,不得恢复兼容壳。

业务层 lib/script#

  • AI/聊天:chat/
  • 音乐搜索门面:music/
  • 音乐播放内部实现:cloudmusic/
  • 本地子进程服务:yuanbao_free_api/local_hosted_service.py
  • ONNX 语音推理与安装:gsvmove/
  • 桌面对象:obj-*
  • 游戏系统:gemes/MAIN/
  • UI:ui/
  • 工作台元数据与组件:workbench/

新增跨模块调用时优先使用明确服务接口;事件只用于需要解耦、广播或跨线程切换的场景。

4. 工作台#

工作台采用两级懒加载:启动预加载器不创建工作台;打开总览只创建工作台壳;进入设置页或工具页时才调用页面工厂。

工作台顶栏搜索框左侧的粉青色明暗主题开关保存到 UI.workbench_light_theme,默认关闭为当前暗色主题;开启后使用白色/粉色表面和深灰蓝文字,并通过 CONFIG_UPDATED 热重载工作台样式。“界面与动画”设置页不再提供重复入口。

工作台及其动态创建的控件统一使用 config.font_config.get_ui_font() 注册的 HarmonyOS Sans SC 字体族;控件树刷新时只替换字体族,不覆盖字号、粗细和自定义绘制字体。

相关位置:

  • 窗口与宿主:lib/script/ui/workbench_window.py
  • 页面注册:lib/script/workbench/page_registry.py
  • 设置 schema:lib/script/workbench/settings/schema.py
  • 设置布局:lib/script/workbench/settings/page_layout.py
  • AI 设置控制器:lib/script/ui/ai_settings_panel.py

约束:

  • 页面元数据使用 dataclass,不转回 legacy dict。
  • 新工具页提供无参数 factory,首次访问时创建。
  • 页面嵌入后不得保留独立窗口旗标或重复层级注册。
  • 页面关闭时释放信号、定时器和后台任务。
  • 不把新功能继续堆入 ai_settings_panel.py,新页面放入 workbench/ 或专属模块。
  • AI 回复模式是单一路由:福利 API、手动 API、本地 Ollama、规则回复和元宝之间不做失败回退。模式专属配置只在对应模式下显示。
  • 福利 API 配置由 lib/script/chat/welfare_api_config.py 从 GitHub/Gitee 发布源并发测速获取密钥与地址。模型使用程序内置的固定标识,不依赖服务端实现 /models:默认模型为 agnes-2.0-flash,“智力提升”开启后使用 agnes-2.5-flash;配置下载超时固定 10 秒,首次失败后最多重试 3 次。
  • 手动 API 的模型探测只辅助选择该路由的模型:设置面板以当前未保存的地址和密钥异步请求 OpenAI 兼容 /models,失败时保留用户当前输入。模型字段始终允许手工输入;无协议的公网地址按 HTTPS、本机地址按 HTTP 规范化后保存。
  • 语音设置在 ONNX 包有效时显示;检测到旧 start_gsvmove.bat、缺失包或损坏包时,面板顶部显示“安装最新语音包”。有效包和损坏包同时提供带确认的后台删除入口,删除后立即刷新为可重新安装状态。安装窗口中的“后台安装”只隐藏界面、不取消任务;再次点击安装入口可恢复进度,后台仅在关键阶段以桌宠气泡提醒。面板开放当前 v2Pro 实际消费的采样温度、Top-K、Top-P、重复惩罚、语速、分句、片段停顿、随机种子和最大解码步数;批处理、流式及 v3/v4 专属兼容字段不显示为有效设置。安装与包管理 UI 位于独立的 voice_package_installer.py,不得继续堆入设置面板。

5. 配置与用户数据#

config/config_*.py 只存程序默认值,运行时禁止改写 Python 源文件。普通设置通过 config.user_settings 保存为版本化稀疏 JSON;密钥和登录态使用独立 secrets/state 路径。

默认值: config/config_*.py
用户覆盖: <用户根>/user/settings.json
状态: <用户根>/user/state/
密钥: <用户根>/user/secrets/
缓存: <用户根>/cache/

旧路径只允许一次性迁移读取。迁移必须有唯一 migration id、可重复执行、不覆盖新值,成功后只读写新位置,并提供迁移与幂等测试。

AI 密钥保存到 <用户根>/user/secrets/ai.json。设置面板每次打开都重新读取该文件,不能只使用模块首次导入时的内存值,以保证跨进程写入和重启后的配置一致。

通用配置保存使用 config.general_user_settings.save_general_values();不要在业务模块中自行解析或正则修改配置源码。

6. 事件、调度与绘制#

事件类型只能定义在 EventType。payload 使用字典,新增字段应允许旧订阅者忽略。后台线程发布事件时,由 Qt pump 切回事件中心线程。

修改事件时同步 事件系统使用说明.txt已注册的事件.txt 以及生产者和消费者测试。

帧、tick、GIF 帧和延迟任务由 TimingManager 负责。不要用散落的永久 QTimer 替代共享调度,除非计时器天然属于控件生命周期。

绘制请求统一使用 DrawCore/RenderCore,窗口置顶统一使用 LayerManager。新增窗口必须选择明确 Layer,并在销毁时 unregister。

7. 音乐与本地服务#

外部音乐调用只使用 lib.script.music.get_music_service()MusicProvider 负责搜索结果标准化,MusicPlaybackBackend 定义播放运行时契约,cloudmusic 是内部实现。

禁止业务模块访问 backend 私有字段、provider 反向导入 MusicService、恢复 cloudmusic 单例兼容入口或运行时改写 config_music.py

本地子进程服务复用 local_hosted_service.py。健康检查、端口切换、启动和清理必须可重复调用。

元宝服务源码位于 services/yuanbao-free-api/。发行时 release_common.py 根据当前源码生成 services/bundles/yuanbao-free-api-main.zip,仓库中的旧 zip 不是发行权威源。

元宝本地中转端口被占用时,YuanbaoFreeApiService 会切换到随机本地端口;OpenAI 兼容请求在发送前必须读取 get_yuanbao_local_base_url() 的运行时地址,不能继续使用管理器初始化期缓存的端口。

设置面板的元宝登录区只显示当前可执行操作:未登录时显示“微信登录元宝”,已登录时显示“退出元宝登录”。面板读取已有服务状态必须使用无副作用的 peek_service_status(),不得为检查状态启动服务、切换端口或触发浏览器登录。

GSV 兼容门面不再启动端口 9880 的 HTTP 服务,而是在原语音工作线程中复用单个 ONNX 引擎。格式版本 2 保留 GPT-SoVITS API v2 参数命名;同一格式内影响正确性的模型或推理升级使用独立 runtime_revision,客户端必须拒绝低于当前最低修订的旧包并显示更新入口。语速必须使用 VITS 图内 speed_factor,禁止恢复改变音高的最终波形重采样。当前 revision 3 包内置中文 RoBERTa,RoBERTa 加载失败必须报错,不能退回零特征;参考 HuBERT 提示语义必须保留原生链路的尾静音。安装器提供完全包、默认中等包和节约包三档,优先 ModelScope、回退 Hugging Face;每档为单个 RAR5 solid archive,使用 64 MiB 字典,大小与空间检查以 VoicePackageProfile 的真实发布值为准。语音包格式、单文件下载、安装、用户确认删除、旧运行时清理和随包 UnRAR 边界以 doc/语音包协议.md 为准。安装前不得为定位旧运行时递归扫描用户目录;安装成功后只清理路径记录明确指向的旧外部 GSVmove。包删除必须由服务在推理锁内释放引擎后执行,并限定在固定磁盘的受管理目录;仓库内 lib/script/gsvmove/ 不属于删除目标。

8. 游戏包兼容边界#

游戏包 manifest、目录布局、加载语义和官方包隔离属于稳定契约。内部实现可以收敛,但不得未经迁移修改包格式。

改动前阅读 doc/游戏包格式.md,并运行:

py -3 -m unittest tests.test_game_package_service
py -3 -m unittest tests.test_game_runtime_geometry tests.test_game_runtime_hash_commands

官方源码包位于 lib/script/gemes/packages/official/,发布时生成 zip,不直接把源码目录作为安装包分发。

9. 依赖与发布#

文件 用途
requirements.txt 桌宠核心运行依赖
requirements-service.txt 核心依赖 + 可选本地服务
requirements-dev.txt 服务依赖 + 测试/开发工具
services/yuanbao-free-api/requirements.txt 服务独立运行环境

普通版和绿色版共享清单、敏感配置清洗、官方游戏包及服务 bundle 生成逻辑。绿色版额外处理 Vosk、动画和 Chromium 归档。

两类发行包都必须携带 lib/script/gsvmove/bin/UnRAR.exeLICENSE-UnRAR.txt,但不携带七卷 ONNX 角色模型。解压器固定校验,不允许安装时联网补取。

依赖安装脚本在摘要前以单行动态展示“正在检查依赖”的当前包、检查数、百分比和进度条;随后只保留已有/未安装依赖摘要和两条固定安装进度行。支持 ANSI 的终端使用 pip 风格的青色当前依赖、粉色整体进度与暗色未完成轨道,不支持颜色的终端显示等宽单色回退。进度刷新不得逐包追加日志。

pip 安装调用必须兼容 Python 3.11.6 随附的 pip 23.2.1;单个依赖失败后继续安装后续依赖,并在最终摘要中显示对应 pip 错误原因,不能只列失败包名。genie-tts 依赖的 jieba-fast 0.53 在 PyPI 没有 Python 3.11 Windows wheel,安装器必须先从 resc.net.txt 的 Gitee/GitHub 镜像下载固定的 cp311-win_amd64 wheel,校验内置 SHA-256 后本地安装,再安装 genie-tts,不得回退到用户机器上的 C++ 源码编译。

依赖可用性默认同时检查 pip 元数据和实际导入。genie-tts 的顶层导入会访问外部 GenieData 并产生输出,因此使用 spec:genie_tts 做无副作用的模块规格检查;不得因资源目录尚未安装而反复重装同一个 Python 包。

发布脚本只允许白名单顶层路径。新增发行文件时必须检查两个入口。--dry-run 不下载资源、不写发行包。

桌宠更新器只探测两个固定程序发布槽:GitHub MARK42IRPC/FlyingSnowVelvet-AemeathPACK release,以及 Gitee Mark42IRPC/Aemeath-AIdeskpet 的“最新包” release。两个源应指向同一份已验收程序快照;更新器并发读取结构化 release API,优先选择发布时间较新的源,时间相同时选择响应更快的源。检查阶段不下载 ZIP;用户确认更新后才开始下载。同 revision 的首选镜像下载失败时可自动切换备用镜像,revision 不同则禁止混用。更新器不扫描 release 列表,因此 RESC 安装依赖仓库不会进入程序更新候选。

固定发布槽当前允许不上传附件:这种情况下使用 tag 自动生成的源码 ZIP,供测试版更新。后续上传真实打包 ZIP 后优先使用 release 附件,并继续保留源码 ZIP 回退能力。

固定发布槽的 tag 名不是应用版本号。更新状态同时记录 release 时间、源和 revision;只有远端发布时间较新,或时间相同但 revision 改变时才提示更新。下载后的覆盖安装由 lib/script/app/update_installer.py 在主进程退出后执行。

10. 验证矩阵#

所有代码任务至少运行:

py -3 -m compileall -q config lib scripts install_deps.py
py -3 -m unittest discover -s tests -p "test_*.py" -q
py -3 scripts/package_release.py --dry-run --version VERIFY

修改绿色版、资源或安装器时追加:

py -3 scripts/package_green_release.py --dry-run --version VERIFY

修改文档时追加:

py -3 scripts/generate_doc_portal.py

验收记录必须写明实际命令、结果和未执行项,不能只写“测试通过”。

11. 常见变更检查表#

新增长生命周期服务#

  • 明确所有者和创建入口。
  • 提供幂等 cleanup。
  • 处理活动响应、线程和子进程。
  • 接入主退出链路。
  • 增加启动、重复清理和运行中退出测试。

新增工作台页面#

  • 注册页面元数据与 factory。
  • 保持首次访问前不构造。
  • 实现嵌入模式和关闭释放。
  • 添加路由、懒加载和布局测试。

新增配置#

  • 在默认配置中定义类型和默认值。
  • 接入稀疏用户设置。
  • 必要时提供一次性迁移。
  • 测试默认值、覆盖、错误类型和迁移幂等性。

新增音乐 provider#

  • 实现 MusicProvider 并返回标准 MusicTrack
  • 接入路由、标签和能力声明。
  • 测试失败回退、去重和编码边界。