Files
zn-ai/docs/Launch-At-Startup-Migration-Plan.md
duanshuwen 301f7d33ed feat: implement launch at startup functionality in zn-ai
- Added a new setting for "launch at startup" in the GeneralSettingsPanel.
- Integrated the setting with the existing settings store and IPC mechanisms.
- Implemented platform-specific logic for enabling/disabling startup behavior in the main process.
- Created a new service for managing launch at startup settings, including Linux desktop entry creation.
- Added unit tests for the new functionality and ensured existing tests are updated accordingly.
- Updated i18n messages for the new setting in English, Chinese, and Japanese.
2026-04-20 23:29:10 +08:00

13 KiB
Raw Blame History

开机自动启动功能复制计划

1. 目标与结论

目标是在 zn-ai/src/pages/Setting/components/GeneralSettingsPanel.tsx 中复制 ClawX 的“开机自动启动”能力,并把视觉位置排在“语言设置”后面、“网关设置”前面。

先给结论:

  • ClawX 的“开机自动启动”不是单纯的前端 Switch,而是“设置持久化 + 主进程 OS 级生效 + 启动时回放同步”的完整链路。
  • zn-ai 已经具备可复用的设置基础设施:settingsStoreconfig-serviceSET_CONFIG/GET_CONFIG IPC、/api/settings 本地路由。
  • zn-ai 当前没有 launchAtStartup 配置键,也没有任何 OS 级自启动应用逻辑。
  • 这次复制不需要新增复杂的状态 hook、也不需要新增 preload 专用桥接;最小可行方案是复用现有设置存取链路,只补 launchAtStartup 配置模型和主进程副作用。

2. ClawX 现有实现拆解

2.1 渲染层 UI 结构

ClawX/src/pages/Settings/index.tsx 中,“开机自动启动”位于通用设置区块内,紧跟在语言设置后面,位于 Gateway 区块前:

  • 主题按钮组
  • 语言按钮组
  • launchAtStartup 开关
  • Separator
  • Gateway 区块

对应 UI 代码位置:

  • ClawX/src/pages/Settings/index.tsx:528
  • ClawX/src/pages/Settings/index.tsx:545

交互特征:

  • 左侧是标题和说明文案。
  • 右侧是一个 Switch
  • 没有额外保存按钮,属于“切换即保存”。
  • 没有单独 loading/error 状态,也没有回滚提示。

2.2 渲染层状态链路

ClawX 渲染层把 launchAtStartup 放在 settings store 中统一管理:

  • 字段定义:ClawX/src/stores/settings.ts:19
  • 默认值:ClawX/src/stores/settings.ts:72
  • 初始化从 /api/settings 拉取:ClawX/src/stores/settings.ts:86
  • setter 里直接调用 /api/settings/launchAtStartupClawX/src/stores/settings.ts:132

实现特征:

  • 先本地 set({ launchAtStartup }),再异步请求主进程。
  • 请求失败时静默吞掉,没有回滚。
  • 这和 gatewayAutoStartthemelanguage 是同一类“轻量即改即存”模式。

2.3 i18n 文案

ClawX 使用 settings.appearance 下的两个键:

  • launchAtStartup
  • launchAtStartupDesc

对应位置:

  • 中文:ClawX/src/i18n/locales/zh/settings.json:12
  • 英文:ClawX/src/i18n/locales/en/settings.json:12
  • 日文:ClawX/src/i18n/locales/ja/settings.json:12

2.4 主进程与 Host API 链路

ClawX 的主进程实现分成 4 层:

  1. 持久化配置

    • ClawX/electron/utils/store.ts:24
    • launchAtStartup 被定义为 AppSettings 字段,默认值为 false
  2. 设置路由

    • ClawX/electron/api/routes/settings.ts:27
    • PUT /api/settings
    • PUT /api/settings/launchAtStartup
    • POST /api/settings/reset
    • 只要 patch/key 触达 launchAtStartup,都会执行 syncLaunchAtStartupSettingFromStore()
  3. OS 级应用逻辑

    • ClawX/electron/main/launch-at-startup.ts:1
    • Windows/macOSapp.setLoginItemSettings({ openAtLogin, openAsHidden: false })
    • Linux写入或删除 ~/.config/autostart/clawx.desktop
    • 错误只记录日志,不向上抛出
  4. 启动时同步

    • ClawX/electron/main/index.ts:298
    • 应用启动后会从 store 读取 launchAtStartup,再回放到操作系统

2.5 测试覆盖

ClawX 已经对 OS 级逻辑做了单元测试:

  • ClawX/tests/unit/launch-at-startup.test.ts

覆盖点:

  • Windows setLoginItemSettings
  • macOS setLoginItemSettings
  • Linux .desktop 文件创建/删除
  • 非支持平台不抛异常

3. zn-ai 当前现状

3.1 已有可复用能力

zn-ai 已经具备以下基础:

  • 通用设置 UIzn-ai/src/pages/Setting/components/GeneralSettingsPanel.tsx
  • 设置页容器:zn-ai/src/pages/Setting/index.tsx
  • 自定义开关组件:zn-ai/src/pages/Setting/components/ToggleSwitch.tsx
  • 全局设置 storezn-ai/src/stores/settings.ts
  • 配置持久化:zn-ai/electron/service/config-service/index.ts
  • 通用设置本地路由:zn-ai/electron/api/routes/settings.ts
  • 主进程初始化入口:zn-ai/electron/main.ts

3.2 关键差异

ClawX 相比,zn-ai 当前的关键差异有 5 个:

  1. launchAtStartup 不在 ConfigValueMap

    • zn-ai/src/types/runtime.ts
    • zn-ai/runtime-shared/lib/constants.ts
    • zn-ai/runtime-shared/lib/types.ts
  2. settingsStore 只管理 gatewayAutoStart,没有 launchAtStartup

    • zn-ai/src/stores/settings.ts
  3. config-service 默认配置里没有 launchAtStartup

    • zn-ai/electron/service/config-service/index.ts
  4. 主进程没有 OS 级开机自启动服务

    • zn-ai/electron 下目前不存在 launch-at-startup 模块
  5. zn-ai 的设置主写路径不是 Host API而是 SET_CONFIG IPC

    • zn-ai/src/stores/settings.ts
    • zn-ai/electron/service/config-service/index.ts

这意味着:

  • 不能只在 /api/settings 路由里补副作用。
  • 必须覆盖到 SET_CONFIG 这条实际写入通路,否则 UI 开关会“写进配置但不生效到系统”。

4. 复制范围与非目标

4.1 本次复制范围

只复制 ClawX 的这一项能力:

  • “开机自动启动”开关
  • 配套说明文案
  • 配置持久化
  • 主进程 OS 级应用
  • 应用启动时回放同步

4.2 明确不做的内容

这次不要把以下内容一起带进来:

  • startMinimized
  • minimizeToTray
  • Gateway 自动启动
  • 代理设置
  • 日志目录打开
  • 开发者模式
  • Telemetry

原因:

  • 这些不是 ClawX“开机自动启动”功能的必要组成。
  • 一起迁移会把范围从“复制单一功能”扩大成“重新设计通用设置”。

5. zn-ai 的最小复制方案

5.1 UI 方案

zn-ai/src/pages/Setting/components/GeneralSettingsPanel.tsx 中,把新行插在语言设置后面:

  • 保持和现有设置页一致的 border-b 行布局
  • 左侧:标题 + 描述
  • 右侧:复用 ToggleSwitch

建议结构:

  1. 主题设置
  2. 语言设置
  3. 开机自动启动
  4. Gateway
  5. 更新

说明:

  • 不需要新建卡片。
  • 不需要新建 section header。
  • 不需要新建独立 hook。
  • 这项功能足够简单,沿用 themeMode/language 的 props 传递模式即可。

5.2 状态与设置层方案

推荐在 zn-ai/src/stores/settings.ts 中新增:

  • launchAtStartup: boolean
  • updateLaunchAtStartup(launchAtStartup: boolean, persist = true)

并在 SettingsStatecreateInitialState()hydrate() 中补齐:

  • 读取 CONFIG_KEYS.LAUNCH_AT_STARTUP
  • 默认值 false

GeneralSettingsPanel 通过 props 收到:

  • launchAtStartup
  • onLaunchAtStartupChange

Setting/index.tsx 负责从 useSettingsStore 取值并透传。

5.3 配置模型方案

需要同时修改以下位置,保证 key 一致:

  • zn-ai/runtime-shared/lib/constants.ts
  • zn-ai/runtime-shared/lib/types.ts
  • zn-ai/src/types/runtime.ts
  • zn-ai/electron/service/config-service/index.ts

建议新增 key

  • launchAtStartup

默认值建议:

  • false

原因:

  • ClawX 保持一致。
  • 对桌面应用更保守,避免首次启动时直接注册系统自启动。

5.4 主进程方案

建议新增模块:

  • zn-ai/electron/service/launch-at-startup/index.ts

职责直接对齐 ClawX,但把应用标识替换为 zn-ai 当前产品信息:

  • Windows/macOS
    • app.setLoginItemSettings({ openAtLogin: enabled, openAsHidden: false })
  • Linux
    • 写入或删除 ~/.config/autostart/*.desktop
    • 不能直接照搬 clawx.desktop
    • NameComment、桌面文件名需要改成 zn-ai 当前产品名

建议暴露两个函数:

  • applyLaunchAtStartupSetting(enabled: boolean)
  • syncLaunchAtStartupSettingFromStore()

5.5 副作用挂载位置

这是本次复制里最关键的实现点。

因为 zn-ai 当前 renderer 主要通过 SET_CONFIG IPC 写设置,所以副作用至少要覆盖两条路径:

  1. SET_CONFIG / UPDATE_CONFIG

    • 位置:zn-ai/electron/service/config-service/index.ts
    • 当 key 或 patch 触达 launchAtStartup 时,调用 applyLaunchAtStartupSetting(...)
  2. 应用启动回放

    • 位置:zn-ai/electron/main.ts
    • await configManager.init() 之后调用 syncLaunchAtStartupSettingFromStore()

一致性建议:

  • zn-ai/electron/api/routes/settings.ts 也补齐同样的副作用。
  • 虽然当前 UI 主通路不是走这个 route但本地 Host API 应该与 IPC 行为一致。

6. 文件级改动清单

6.1 渲染层

  • zn-ai/src/pages/Setting/components/GeneralSettingsPanel.tsx
  • zn-ai/src/pages/Setting/index.tsx
  • zn-ai/src/stores/settings.ts
  • zn-ai/src/i18n/messages.ts
  • zn-ai/src/types/runtime.ts

6.2 共享常量与类型

  • zn-ai/runtime-shared/lib/constants.ts
  • zn-ai/runtime-shared/lib/types.ts

6.3 主进程

  • zn-ai/electron/service/config-service/index.ts
  • zn-ai/electron/service/launch-at-startup/index.ts(新增)
  • zn-ai/electron/api/routes/settings.ts
  • zn-ai/electron/main.ts

6.4 测试

  • zn-ai/tests/launch-at-startup.test.ts(建议新增)

7. 关键风险与处理建议

7.1 双写路径风险

风险:

  • SET_CONFIG IPC 和 /api/settings route 都能改配置。
  • 如果只给其中一条路径挂副作用,会出现“配置值正确但系统登录项没同步”的假成功。

处理:

  • 两条路径都挂同一个 helper。

7.2 Linux 桌面文件元数据风险

风险:

  • 直接复制 ClawXclawx.desktopName=ClawX 会导致 Linux 桌面环境识别错误。

处理:

  • 使用 zn-ai 当前产品名、可执行路径和桌面文件名。
  • 优先通过 app.getName() / process.execPath 生成,而不是写死 ClawX 文案。

7.3 产品名文案不一致风险

风险:

  • package.jsonproductNameNIANXX,但前端文案里大量使用 ZN-AI

处理:

  • 本次设置说明文案优先使用“应用”或“系统登录后自动启动”这种泛化表达。
  • 不在这次迁移里额外引入品牌命名统一改造。

7.4 静默失败体验风险

风险:

  • ClawX 的写法对失败是静默吞掉,用户可能看不出 OS 级注册失败。

处理:

  • 第一版可以保持与 ClawX 相同的轻量体验。
  • 如果后续需要提高可观测性,再补 toast 或错误文案,但这不属于这次最小复制范围。

8. 推荐实施顺序

Phase 1主进程能力补齐

  1. 新增 launchAtStartup config key
  2. 新增 launch-at-startup 服务
  3. config-service/api/settings 中挂副作用
  4. electron/main.ts 启动时回放同步

Phase 2渲染层接入

  1. settingsStore 增加 launchAtStartup
  2. Setting/index.tsx 透传 prop
  3. GeneralSettingsPanel.tsx 在语言设置后插入 UI
  4. messages.ts 补三语文案

Phase 3验证

  1. typecheck
  2. launch-at-startup 单元测试
  3. 手动验证设置页切换
  4. 手动验证 Windows/macOS/Linux 的系统登录项行为

9. 最小测试集合

建议至少覆盖以下 4 类验证:

  1. 单元测试

    • Windows/macOS 调用 app.setLoginItemSettings
    • Linux .desktop 创建/删除
  2. 配置链路测试

    • 改写 launchAtStartup 后,configManager 中值已更新
  3. 渲染层回归

    • 设置页中开关显示在语言设置后面
    • 开关值能和 store 状态联动
  4. 启动同步验证

    • 应用启动后能读取持久化值并重新应用 OS 级自启动

10. sub-agent 估算与分工

10.1 推荐数量

推荐 3 个 sub-agent。

理由:

  • 这次复制的改动面天然分成“渲染层”“配置/状态链路”“主进程 OS 级服务”三块。
  • 三块之间耦合度低,适合并行推进。
  • 再往上拆会让协同成本高于收益。

10.2 分工建议

Worker 1渲染层与 i18n

负责文件:

  • zn-ai/src/pages/Setting/components/GeneralSettingsPanel.tsx
  • zn-ai/src/pages/Setting/index.tsx
  • zn-ai/src/i18n/messages.ts

职责:

  • 在语言设置后插入 UI
  • 接入 launchAtStartup prop
  • 补齐中英日文案
  • 确保视觉风格与现有设置页一致

Worker 2设置模型与配置链路

负责文件:

  • zn-ai/src/stores/settings.ts
  • zn-ai/src/types/runtime.ts
  • zn-ai/runtime-shared/lib/constants.ts
  • zn-ai/runtime-shared/lib/types.ts

职责:

  • 新增 launchAtStartup 配置键和类型
  • 在 store 中完成读取、更新、对外导出
  • 保证 renderer 能通过现有设置链路读写该值

Worker 3主进程自启动服务与测试

负责文件:

  • zn-ai/electron/service/launch-at-startup/index.ts
  • zn-ai/electron/service/config-service/index.ts
  • zn-ai/electron/api/routes/settings.ts
  • zn-ai/electron/main.ts
  • zn-ai/tests/launch-at-startup.test.ts

职责:

  • 实现跨平台 OS 级自启动逻辑
  • 把副作用挂到配置写入与启动同步节点
  • 补齐最小单元测试

11. 最终建议

这次复制应严格控制在“ClawX 的 launchAtStartup 单功能迁移”范围内推进。

建议落地原则:

  • UI 只加一行,不做新的设置分组。
  • 状态层只加一个布尔配置,不新建复杂 hook。
  • 主进程只加一个独立服务,不顺手扩散到别的系统设置功能。
  • 测试优先覆盖 OS 级副作用,而不是先写大量 UI 测试。

按这个方案推进,能以最小代价把 ClawX 的成熟能力复制到 zn-ai,同时避免出现“只做了开关外观、没有真正接到系统登录项”的伪完成状态。