Commit c6ebeedf authored by AI-甘富林's avatar AI-甘富林

docs: add dmg packaging plan

parent 91f42aa0
# macOS .dmg 独立分支改造方案(不做双平台共存)
## Summary
目标改为:基于当前仓库事实,复制出一个新的独立分支,只为 macOS arm64 开发 .dmg 包与对应运行时,不考虑和现有 Windows 打包共存,也不要求保留 Windows 打包链路。
这会把方案明显简化:
- 不做双平台 builder 配置兼容
- 不保留 NSIS / .exe / Windows branding / installer smoke
- 不做跨平台 materialize 主入口
- 直接把当前仓库里的 Windows 假设替换为 mac 假设
- 目标产物就是单一 macOS arm64 .dmg
当前需要改的核心仍是 4 块:
- electron-builder 只支持 Windows,见 /D:/qjclaw/apps/desktop/electron-builder.yml:24
- runtime 路径写死 node.exe / python.exe,见 /D:/qjclaw/packages/runtime-manager/src/index.ts:653
- runtime materialize 是 PowerShell 且产出 Windows 物料,见 /D:/qjclaw/build/scripts/materialize-runtime-payload.ps1:52
- workspace 执行器含 PowerShell fallback 和 python\Scripts 假设,见 /D:/qjclaw/apps/desktop/src/main/services/project-workspace-executor.ts:271
## Goal
### 目标
在新的 mac 专用分支上,做出一个只面向 darwin-arm64 的桌面包架构。
### 成功标准
- pnpm package:mac 能产出 .dmg
- .app 内包含可工作的 mac bundled runtime
- 应用能启动并进入主界面
- RuntimeManager 在 mac 下可识别 runtime ready
- workspace execution 主链路可跑通
- 不保留任何 Windows 打包要求
## Phase 1: 建立 mac 专用分支的边界
### 目标
先明确这个分支里哪些内容可以直接删掉或废弃,避免继续为 Windows 兼容付出成本。
### 步骤
1. 明确此分支唯一目标平台
- 只支持 darwin-arm64
- 不支持 Windows
- 不支持 Intel mac
- 不做 universal
2. 明确此分支保留的能力
- Electron 主程序
- UI 渲染层
- bundled runtime
- workspace execution
- mac 打包和 smoke
3. 明确此分支不再保留的能力
- NSIS 安装器
- installer.nsh
- Windows afterPack branding patch
- .ico 图标链路
- node.exe / python.exe 路径假设
- taskkill
- PowerShell installer smoke
- 与 Windows 相关的打包命令和验证命令
4. 明确目录策略
- 继续沿用现有 repo 结构
- 但 vendor/openclaw-runtime 直接改成 mac 专用目录内容,不再做多平台子目录
- 因为这个分支只做 mac,没必要保留 win32-x64 物料布局
### 输出
- 一个明确的“mac-only 分支边界”
- 后续实现过程中默认允许直接删除 Windows 打包逻辑
## Phase 2: Electron 打包链路改成 mac-only
### 目标
把现在的 Windows electron-builder 配置,直接改造成只生成 mac .dmg 的配置。
### 步骤
1. 重写 /D:/qjclaw/apps/desktop/electron-builder.yml:1
- 保留:
- appId
- productName
- compression
- asar
- asarUnpack
- files
- 删除:
- artifactName: ${productName}-Setup-${version}.${ext}
- afterPack: build/hooks/after-pack-branding.cjs
- extraResources 里的 .ico
- win
- nsis
2. 新增 mac-only 配置
- 增加:
- mac.target: dmg
- mac.arch: arm64
- mac.icon: build/icons/brand-icon.icns
- mac.category: public.app-category.productivity
- artifactName 改为适合 mac 的命名
- 增加 dmg 布局配置
- 输出目录可改为 dist/dmg 或 dist/release
3. 清理 Windows afterPack
- 不再使用 /D:/qjclaw/apps/desktop/build/hooks/after-pack-branding.cjs:100
- 该文件在 mac-only 分支可直接废弃
- 若后续需要 mac 的资源整理,再新写独立 hook
4. 图标资产替换
- 删除 .ico 在打包链路中的依赖
- 补齐 .icns
- 主程序窗口图标解析改为 mac 逻辑
5. 调整 package scripts
- 根 package.json 中:
- package 可直接改成 mac 打包命令,或新增 package:mac
- apps/desktop/package.json 中:
- package 也改成 mac-only 打包命令
### 输出
- 一个只生成 .dmg 的打包链路
- 不再有任何 NSIS / Setup / .exe 语义
## Phase 3: runtime-manager 全量切到 mac 路径
### 目标
把运行时管理从 Windows 文件结构直接改成 mac 文件结构。
### 步骤
1. 重写 resolveBundledPaths()
- 当前 /D:/qjclaw/packages/runtime-manager/src/index.ts:653 写死:
- node/node.exe
- python/python.exe
- mac-only 分支直接改成:
- node/bin/node
- python/bin/python3
- 或你最终选定的 mac runtime 目录结构
2. 简化平台判断
- 删除大部分 process.platform === "win32" 特判
- 代码默认认为当前平台是 mac
- 保留极少量 darwin 生命周期逻辑即可
3. 改 readiness 逻辑
- readiness 检查目标文件全部切为 mac 文件
- 关键存在性检查改成:
- Node 可执行文件
- Python 可执行文件
- OpenClaw 入口
- Config
- Playwright browsers
- README
- runtime manifest
4. 改 PATH 注入
- 当前把 python\Scripts 写入 PATH
- 改成 mac 对应的 python/bin
- 所有 child process 都依赖这个新路径
5. 改 stop/restart
- 删除 taskkill.exe 路径逻辑
- stop() 统一使用:
- SIGTERM
- 超时后 SIGKILL
- 不再维护 Windows 停止分支
6. 删除 PowerShell EPERM fallback
- execPythonInlineScript 中 PowerShell 回退可删
- runtime 启动的 PowerShell wrapper 可删
- 失败就直接报 mac 实际错误,不做 Windows 兼容补丁
### 输出
- 一个纯 mac 的 runtime-manager
- 路径、进程控制、PATH 注入都不再有 Windows 残留
## Phase 4: bundled runtime 物料生成改成 mac-only
### 目标
用 mac 物料重建 vendor/openclaw-runtime,不再兼容 Windows payload。
### 步骤
1. 废弃现有 PowerShell materialize 主入口
- /D:/qjclaw/build/scripts/materialize-runtime-payload.ps1:52 是 Windows-only 设计
- 在 mac-only 分支中,不建议继续修它
- 直接新建 mac materialize 脚本作为唯一正式入口
2. 重新定义 runtime 目录结构
- vendor/openclaw-runtime/
- node/
- python/
- openclaw/
- config/
- playwright-browsers/
- runtime-manifest.json
- README.md
3. 生成 Node runtime
- 从 mac 环境收集 Node 可执行文件
- 放入 node/bin/node
- manifest 记录真实相对路径
4. 生成 Python runtime
- 收集或封装 mac 可分发 Python runtime
- 放入 python/bin/python3
- 安装锁定依赖
- 生成 python-manifest.json
- 验证可执行性
5. 复制 OpenClaw package
- 保持现有 OpenClaw 包内容复制逻辑
- 保留模板文档依赖,例如 AGENTS.md 所在模板路径
6. 复制默认 config
- 继续产出 config/openclaw.json
7. 复制 Playwright browsers
- 用 mac 平台的 browsers 目录
- 不能复用 Windows 浏览器缓存
8. 生成 runtime manifest
- 记录:
- platform: darwin
- arch: arm64
- nodeExecutable
- pythonExecutable
- pythonBinDir
- openClawEntry
- playwrightBrowsersPath
- materializationKey
9. 建立 materialize:runtime:mac
- 根 package.json 增加 mac 专用命令
- 所有打包与 smoke 都依赖这个命令
### 输出
- vendor/openclaw-runtime 变成 mac 可运行 payload
- materialize 链路不再依赖 PowerShell
## Phase 5: workspace execution 改成 mac-only
### 目标
保证 Python automation 和 Node runner 都能在 mac bundled runtime 下运行。
### 步骤
1. 简化 /D:/qjclaw/apps/desktop/src/main/services/project-workspace-executor.ts:271
- 删除 getWindowsPowerShellPath()
- 删除 escapePowerShellSingleQuoted() 若仅用于 PowerShell
- 删除 EPERM -> PowerShell wrapper fallback
2. 保留主执行路径
- 统一直接 spawn(executable, args, spawnOptions)
- executable 来自 runtime-manager 的 mac 路径
- 不通过 shell 包裹
3. 调整 PATH 注入
- 把 python\Scripts 改成 python/bin
- 保留:
- OPENCLAW_HOME
- OPENCLAW_STATE_DIR
- OPENCLAW_CONFIG_PATH
- PLAYWRIGHT_BROWSERS_PATH
- 其余运行时环境变量
4. 保留 Python automation 协议
- workspaceAutomation.runtime = "python" 不变
- scriptPath 模板解析逻辑不变
- 只是 pythonExecutable 改用 mac 路径
5. 保留 Node runner 协议
- project-workspace-agent-runner.js 继续保留
- 运行入口改为 mac Node 可执行文件
### 输出
- workspace execution 链路变成纯 mac 执行模型
- 不再有 PowerShell / Windows shell 假设
## Phase 6: Electron 主进程适配 mac 行为
### 目标
让应用在 mac 上以合理方式启动和交互。
### 步骤
1. 改造窗口图标
- /D:/qjclaw/apps/desktop/src/main/create-window.ts:23 当前只处理 .ico
- 改成只处理 mac 资源,或直接依赖应用 bundle 图标
- 删除 .ico 路径引用
2. 调整窗口框架
- 当前:
- frame: false
- titleBarStyle: "hidden"
- mac 下先以“可用优先”
- 推荐默认方案:
- 恢复较标准的 mac 窗口框架
- 不把 Windows 的无边框方案强搬过去
- 如果后续再做 mac 自定义标题栏,再单独优化
3. 菜单策略
- 当前 Menu.setApplicationMenu(null) 在 mac 上不理想
- mac-only 分支应至少提供基础应用菜单
- 不必一开始做复杂菜单,但不能完全无菜单
4. 生命周期
- window-all-closed 与 activate 的 mac 逻辑保留
- 验证 dock 点击恢复窗口行为
### 输出
- mac 启动和窗口行为稳定
- 不受 Windows UI 壳策略影响
## Phase 7: 清理 Windows 打包与 smoke 残留
### 目标
把这个分支里不再需要的 Windows 打包逻辑彻底下线,避免维护噪音。
### 步骤
1. package scripts 清理
- 删除或废弃:
- smoke:installer
- smoke:installer:path-change
- smoke:installer:target-residue
- 其他明确依赖 .exe/NSIS 的命令
2. build scripts 清理
- 标记或移除:
- installer-smoke.ps1
- installer-path-change-smoke.ps1
- installer-target-residue-smoke.ps1
- installer.nsh
- 如果暂时不删,也应明确不再被任何命令引用
3. README/文档清理
- /D:/qjclaw/build/scripts/README.md:1 中与 installer、NSIS、.exe 相关说明改为 mac 版本说明
- 移除误导性的 Windows 打包说明
4. 资源清理
- 移除 builder 中的 .ico
- 不再把 Windows runtime 物料带入包中
### 输出
- 分支内只保留 mac 需要的打包与验证路径
- 不再混杂 Windows 发布概念
## Phase 8: 建立 mac smoke 验证链路
### 目标
替代现有 Windows installer smoke,建立 mac 发布前回归链路。
### 步骤
1. smoke:mac:package
- 校验 .dmg 与 .app 是否产出
- 校验 .app/Contents/Resources 关键资源存在
2. smoke:mac:runtime
- 校验 bundled runtime 是否 ready
- 校验 manifest 路径可解析
- 校验 Node / Python 可执行
3. smoke:mac:python-imports
- 校验关键 Python 依赖导入:
- openpyxl
- pandas
- requests
- bs4
- lxml
- pypdf
- docx
- yaml
- PIL
- dotenv
- greenlet
- playwright
- edge_tts
4. smoke:mac:workspace-entry
- 启动应用
- 走 bundled runtime
- 执行 workspace entry
- 验证 event stream / reply 回传
5. smoke:mac:playwright
- 验证 bundled browsers 可被运行时访问
6. smoke:mac:launch
- 做一次最小人工/自动启动验证
- 确保应用首次进入主窗口而不是闪退
- 一组完整的 mac smoke 命令
## Phase 9: 交付顺序
### 推荐一步步实施顺序
1. 建立 mac-only 分支并确认“不保留 Windows 打包”
2. 重写 electron-builder.yml 为 mac-only
3. 新增 .icns 资源
4. 修改 create-window.ts 的图标、frame、menu 策略
5. 修改 runtime-manager,把 .exe / taskkill / PowerShell 全部切掉
6. 修改 project-workspace-executor.ts,移除 PowerShell fallback
7. 新建 mac runtime materialize 脚本
8. 重建 vendor/openclaw-runtime 为 mac payload
9. 接入 package:mac
10. 编写 smoke:mac:package
11. 编写 smoke:mac:runtime
12. 编写 smoke:mac:workspace-entry
13. 更新文档,清理 Windows installer 说明
## Deliverables
- mac-only 的 /D:/qjclaw/apps/desktop/electron-builder.yml:1
- mac 专用 .icns 图标资源
- mac-only 的 runtime-manager
- mac-only 的 project-workspace-executor
- 新的 mac runtime materialize 脚本
- 重建后的 vendor/openclaw-runtime
- package:mac
- smoke:mac:package
- smoke:mac:runtime
- smoke:mac:workspace-entry
- 一份 mac 打包与验证文档
## Test Plan
- pnpm typecheck
- pnpm materialize:runtime:mac
- pnpm package:mac
- pnpm smoke:mac:package
- pnpm smoke:mac:runtime
- pnpm smoke:mac:workspace-entry
- 人工确认:
- .dmg 可打开
- .app 可启动
- 主窗口正常
- bundled runtime 正常
- workspace automation 正常
## Assumptions
- 这是一个新的 mac 专用开发分支,不需要为 Windows 打包兼容负责。
- vendor/openclaw-runtime 在该分支里可以直接变成 mac-only 内容。
- 签名、公证、staple 当前不纳入实施。
- 若 mac 无边框窗口适配成本高,优先恢复标准 mac 窗口行为。
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment