# macOS App 与本地服务 App、Web 服务、Vue 界面和 Runner 同仓维护。正式 App 在每个构建首次启动时,将较旧的本机 Web 同步为配套构建;已有更新的 Web 保留。Web 由独立 LaunchAgent 运行,App 连接它。源码开发模式仍使用包内子进程。默认数据目录为 `~/.hermes-yaoyao`,默认 Web 端口为 15300。Hermes 是独立基础运行时,由本地服务检测并按既有托管逻辑启动;隔离电脑另需本机 Docker 或 Podman。 ## 生命周期与权限 - App 单实例;服务和 Runner 各自对实际数据目录持有 SQLite 独占锁。 - 使用私有随机凭据核对服务实例、PID、数据目录、协议及版本。App 自己启动的服务必须匹配内置版本。连接旧版本外部服务时使用其界面和能力声明。 - 老 CLI 服务没有描述文件时,只有确认它同时持有目标 SQLite 文件和监听端口才连接。 - 关闭窗口保留任务;菜单栏和 Dock 可恢复。正式 App 退出时停止自己托管的 Runner,独立 Web 服务继续运行。源码开发 App 仍清理自己的服务子进程。停止无法确认时显示实际清理错误。 - 服务崩溃有界重启,睡眠恢复后重新核对连接;错误页面提供重试和日志。 - Runner 配置由原生文件选择器导入。新配置用 AES-GCM 加密,密钥按数据目录保存在系统钥匙串中;加密助手仅允许所属、同签名团队的 App 调用,明文通过私有进程管道传递。旧 safeStorage 格式仍可在系统授权后读取。Web 页面没有配置解密或桌面启动权限,外部页面不能调用原生桥。 ## 登录启动 “夭夭 → 登录 macOS 时启动”使用系统登录项,默认不开启。用户可另选“登录启动时仅驻留菜单栏”;这个偏好只影响登录启动,手动打开 App 仍显示窗口。正常安装不会改写系统登录项。 源码开发 App 不提供登录项开关;安装包中的开关由系统管理。实际开机/重新登录验收尚未执行,当前验证的是偏好持久化和手动重新打开行为。 ## 更新与回退 App 新增“检查 App 更新…”窗口,直接从官方 GitHub 检查稳定版本、下载并校验 DMG,由用户手动安装。它不依赖 Web 或 9119 在线,详见 [GitHub 版本升级](github-updates.md)。 正式 App 的同步在安装/更新后的**首次启动**执行;复制 App 文件本身不执行服务操作。详见 [App 与 Web 版本同步](app-web-sync.md)。 - 同步仅针对当前用户、相同数据目录和端口的本机 LaunchAgent;保留已有服务的地址、TLS、上游及通知配置。 - 使用版本、提交关系和完整服务包校验值识别构建。同版本不同提交可以向上同步;不同分支且无法确认先后时保留现有服务并提示原因。 - App 携带独立 Node 运行时及预编译 Web 服务,首次同步不依赖联网、npm 或源码构建。Node 的许可证随服务包交付。 - 同步成功按 App 服务包校验值记账;同一构建再次打开不会反复覆盖 Web。Web 可以继续通过原有更新入口升级。 - 新版服务空闲时短暂暂停请求,停止后备份数据、切换版本,验证实际构建、健康及关键接口后开放请求。失败恢复程序与数据;进程中断由下一次同步或更新恢复。 - 原有旧版服务缺少协作暂停接口时,需要确认无未完成任务及本机服务进程的客户端连接。忙碌时 App 先连接已验证的原 Web,在菜单提示同步待完成并提供重试,不强行中断聊天。不能验证身份、TLS 或数据归属的服务不接管,启动页显示错误及恢复操作。 - 回退单独通过 Web 的回滚入口处理。只在数据库结构兼容时切回程序并保留现有数据;结构已变化或缺少兼容性记录时拒绝直接降级,不能用旧备份覆盖升级后的新消息。 正式后台服务的程序位于 `~/.local/share/hermes-yaoyao/releases`,`current` 指向启用的构建;数据仍在 `~/.hermes-yaoyao`。App 签名资源不被 Web 更新器改写。开发模式的包内服务仍随开发 App 管理,不提供服务内更新。 ## 构建与验收 ```sh npm run desktop:build npm run desktop:test npm run desktop:pack codesign --verify --deep --strict desktop-release/mac-arm64/夭夭.app hdiutil verify desktop-release/Yaoyao-0.4.1-arm64.dmg ``` 开发 App 的 6 项测试通过:真实内置服务启动、账号与 Runner 连接、关闭窗口保持运行、服务崩溃恢复、外部客户端不误停服务、退出清理、加密配置再次启动、偏好保存及手动重新打开、版本不符拒绝、钥匙串失败保护。另有更新器 14 项定向测试通过,包含 App 禁用源码更新及回退。 最终分支包位于 `desktop-release/agent-platform`;旧的顶层包保留为历史快照。新包通过严格签名、DMG 完整性及实际 App 生命周期验证。使用 Apple Development 开发签名,未公证、未安装或发布,详见 `agent-platform-implementation.md`。 ### 原生加密核对 Electron 初始化时设置其钥匙串项目名称([v43.4.0 源码](https://github.com/electron/electron/blob/v43.4.0/shell/browser/electron_browser_main_parts.cc#L524))。首次签名包验收在旧项目的系统授权上等待,未修改其权限。新配置改用 Runner 专属、按数据目录区分的原生项目;旧配置保持兼容读取,不强制迁移。 助手使用 CryptoKit AES-GCM、Security.framework 和私有 stdin/stdout,不把密钥放进环境变量、参数或日志。分发版本验证调用 App 路径、签名和团队,拒绝外部 shell 调用;仅用于源码开发的测试助手不会进入安装包。钥匙串调用有 30 秒上限,失败保留原配置。 原生钥匙串加密往返、密文篡改拒绝、跨数据目录拒绝、外部直接调用拒绝,以及完整 Runner 导入/退出/恢复等 8 项桌面测试通过。 最终实际签名 App 的完整 Runner 导入、加密保存、服务崩溃恢复、窗口关闭保持连接、退出清理和再次打开自动连接均已通过;另有独立的核心服务生命周期测试通过。新加密助手在实际签名 App 中验证所属路径和签名团队。安装包经挂载检查,开发专用助手没有进入分发包。 v0.4.1 同时发布 Web 与 macOS Apple Silicon DMG,见 [发布说明](releases/v0.4.1.md)。正式 App 首次启动按上文同步规则升级较旧的本机 Web;已有更新版本保留。独立预览应指定独立 `HERMES_YAOYAO_HOME` 和 `HERMES_YAOYAO_DESKTOP_PORT`。