@lobehub/lobehub 2.0.0-next.291 → 2.0.0-next.293

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/.conductor/setup.sh +107 -0
  2. package/.cursor/rules/linear.mdc +53 -0
  3. package/.github/actions/desktop-build-setup/action.yml +29 -0
  4. package/.github/actions/desktop-upload-artifacts/action.yml +46 -0
  5. package/.github/workflows/release-desktop-beta.yml +76 -115
  6. package/.github/workflows/release-desktop-stable.yml +472 -0
  7. package/CHANGELOG.md +58 -0
  8. package/CLAUDE.md +2 -48
  9. package/apps/desktop/dev-app-update.yml +10 -0
  10. package/apps/desktop/electron-builder.mjs +40 -10
  11. package/apps/desktop/electron.vite.config.ts +3 -2
  12. package/apps/desktop/package.json +2 -1
  13. package/apps/desktop/scripts/update-test/README.md +222 -0
  14. package/apps/desktop/scripts/update-test/dev-app-update.local.yml +18 -0
  15. package/apps/desktop/scripts/update-test/generate-manifest.sh +277 -0
  16. package/apps/desktop/scripts/update-test/run-test.sh +105 -0
  17. package/apps/desktop/scripts/update-test/setup.sh +111 -0
  18. package/apps/desktop/scripts/update-test/start-server.sh +70 -0
  19. package/apps/desktop/scripts/update-test/stop-server.sh +33 -0
  20. package/apps/desktop/src/main/core/infrastructure/UpdaterManager.ts +120 -9
  21. package/apps/desktop/src/main/core/infrastructure/__tests__/UpdaterManager.test.ts +17 -1
  22. package/apps/desktop/src/main/env.ts +19 -11
  23. package/apps/desktop/src/main/modules/updater/configs.ts +14 -1
  24. package/changelog/v1.json +14 -0
  25. package/conductor.json +5 -0
  26. package/locales/en-US/subscription.json +2 -2
  27. package/locales/zh-CN/subscription.json +2 -2
  28. package/package.json +1 -1
  29. package/packages/builtin-tool-notebook/src/client/Render/CreateDocument/DocumentCard.tsx +16 -14
  30. package/packages/const/src/cacheControl.ts +1 -0
  31. package/packages/electron-client-ipc/src/useWatchBroadcast.ts +10 -4
  32. package/packages/model-bank/src/aiModels/qiniu.ts +6 -6
  33. package/packages/observability-otel/src/node.ts +39 -37
  34. package/scripts/electronWorkflow/mergeMacReleaseFiles.js +22 -8
  35. package/src/app/(backend)/api/desktop/latest/route.ts +115 -0
  36. package/src/app/(backend)/api/version/route.ts +13 -0
  37. package/src/app/(backend)/middleware/validate/createValidator.test.ts +61 -0
  38. package/src/app/(backend)/middleware/validate/createValidator.ts +79 -0
  39. package/src/app/(backend)/middleware/validate/index.ts +3 -0
  40. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +2 -1
  41. package/src/app/[variants]/(main)/_layout/index.tsx +2 -1
  42. package/src/app/[variants]/(main)/agent/cron/[cronId]/features/CronJobScheduleConfig.tsx +0 -1
  43. package/src/app/[variants]/(main)/agent/cron/[cronId]/index.tsx +5 -5
  44. package/src/app/[variants]/(main)/agent/features/Conversation/ThreadHydration.tsx +3 -1
  45. package/src/app/[variants]/(main)/group/features/Conversation/ThreadHydration.tsx +3 -1
  46. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/Checker.tsx +3 -3
  47. package/src/app/[variants]/(mobile)/router/mobileRouter.config.tsx +1 -4
  48. package/src/app/[variants]/router/desktopRouter.config.tsx +1 -4
  49. package/src/components/HtmlPreview/PreviewDrawer.tsx +1 -1
  50. package/src/features/Conversation/Messages/AssistantGroup/components/GroupItem.tsx +12 -2
  51. package/src/features/Conversation/Messages/Tool/Tool/index.tsx +10 -1
  52. package/src/features/{ElectronTitlebar/hooks → Electron/navigation}/useNavigationHistory.ts +1 -1
  53. package/src/features/{ElectronTitlebar/NavigationBar/index.tsx → Electron/titlebar/NavigationBar.tsx} +1 -1
  54. package/src/features/{ElectronTitlebar/NavigationBar → Electron/titlebar}/RecentlyViewed.tsx +1 -1
  55. package/src/features/{ElectronTitlebar/index.tsx → Electron/titlebar/TitleBar.tsx} +19 -9
  56. package/src/features/Electron/titlebar/WinControl.tsx +5 -0
  57. package/src/features/Electron/updater/UpdateModal.tsx +299 -0
  58. package/src/features/LibraryModal/AddFilesToKnowledgeBase/index.test.tsx +24 -0
  59. package/src/features/LibraryModal/AddFilesToKnowledgeBase/index.tsx +21 -24
  60. package/src/features/LibraryModal/CreateNew/index.tsx +18 -22
  61. package/src/features/PluginDevModal/index.tsx +1 -1
  62. package/src/layout/GlobalProvider/AppTheme.tsx +1 -1
  63. package/src/libs/swr/index.ts +26 -30
  64. package/src/server/services/desktopRelease/index.test.ts +65 -0
  65. package/src/server/services/desktopRelease/index.ts +208 -0
  66. package/src/store/aiInfra/slices/aiProvider/action.ts +16 -17
  67. package/src/store/chat/slices/portal/action.test.ts +0 -2
  68. package/src/store/chat/slices/portal/action.ts +17 -44
  69. package/src/store/chat/slices/thread/action.test.ts +4 -1
  70. package/src/store/chat/slices/thread/action.ts +6 -1
  71. package/src/components/FunctionModal/createModalHooks.ts +0 -48
  72. package/src/components/FunctionModal/index.ts +0 -1
  73. package/src/components/FunctionModal/style.tsx +0 -44
  74. package/src/features/ElectronTitlebar/UpdateModal.tsx +0 -274
  75. package/src/features/ElectronTitlebar/WinControl/index.tsx +0 -90
  76. /package/src/features/{ElectronTitlebar/Connection/index.tsx → Electron/connection/Connection.tsx} +0 -0
  77. /package/src/features/{ElectronTitlebar/Connection → Electron/connection}/ConnectionMode.tsx +0 -0
  78. /package/src/features/{ElectronTitlebar/Connection → Electron/connection}/Option.tsx +0 -0
  79. /package/src/features/{ElectronTitlebar/Connection → Electron/connection}/RemoteStatus.tsx +0 -0
  80. /package/src/features/{ElectronTitlebar/Connection → Electron/connection}/Waiting.tsx +0 -0
  81. /package/src/features/{ElectronTitlebar/Connection → Electron/connection}/WaitingAnim.tsx +0 -0
  82. /package/src/features/{ElectronTitlebar/helpers → Electron/navigation}/routeMetadata.ts +0 -0
  83. /package/src/features/{ElectronTitlebar/hooks → Electron/system}/useWatchThemeUpdate.ts +0 -0
  84. /package/src/features/{ElectronTitlebar → Electron/titlebar}/SimpleTitleBar.tsx +0 -0
  85. /package/src/features/{ElectronTitlebar → Electron/updater}/UpdateNotification.tsx +0 -0
@@ -21,11 +21,12 @@ export default defineConfig({
21
21
  },
22
22
  sourcemap: isDev ? 'inline' : false,
23
23
  },
24
- // 这里是关键:在构建时进行文本替换
24
+
25
25
  define: {
26
26
  'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
27
- 'process.env.OFFICIAL_CLOUD_SERVER': JSON.stringify(process.env.OFFICIAL_CLOUD_SERVER),
28
27
  'process.env.UPDATE_CHANNEL': JSON.stringify(process.env.UPDATE_CHANNEL),
28
+
29
+ 'process.env.UPDATE_SERVER_URL': JSON.stringify(process.env.UPDATE_SERVER_URL),
29
30
  },
30
31
 
31
32
  resolve: {
@@ -36,7 +36,8 @@
36
36
  "stylelint": "stylelint \"src/**/*.{js,jsx,ts,tsx}\" --fix",
37
37
  "test": "vitest --run",
38
38
  "type-check": "tsgo --noEmit -p tsconfig.json",
39
- "typecheck": "tsgo --noEmit -p tsconfig.json"
39
+ "typecheck": "tsgo --noEmit -p tsconfig.json",
40
+ "update-server": "sh scripts/update-test/run-test.sh"
40
41
  },
41
42
  "dependencies": {
42
43
  "electron-updater": "^6.6.2",
@@ -0,0 +1,222 @@
1
+ # 本地更新测试指南
2
+
3
+ 本目录包含用于在本地测试 Desktop 应用更新功能的工具和脚本。
4
+
5
+ ## 目录结构
6
+
7
+ ```
8
+ scripts/update-test/
9
+ ├── README.md # 本文档
10
+ ├── setup.sh # 一键设置脚本
11
+ ├── start-server.sh # 启动本地更新服务器
12
+ ├── stop-server.sh # 停止本地更新服务器
13
+ ├── generate-manifest.sh # 生成 manifest 和目录结构
14
+ ├── dev-app-update.local.yml # 本地测试用的更新配置模板
15
+ └── server/ # 本地服务器文件目录 (自动生成)
16
+ ├── stable/ # stable 渠道
17
+ │ ├── latest-mac.yml
18
+ │ └── {version}/
19
+ │ ├── xxx.dmg
20
+ │ └── xxx.zip
21
+ ├── beta/ # beta 渠道
22
+ │ └── ...
23
+ └── nightly/ # nightly 渠道
24
+ └── ...
25
+ ```
26
+
27
+ ## 快速开始
28
+
29
+ ### 1. 首次设置
30
+
31
+ ```bash
32
+ cd apps/desktop/scripts/update-test
33
+ chmod +x *.sh
34
+ ./setup.sh
35
+ ```
36
+
37
+ ### 2. 构建测试包
38
+
39
+ ```bash
40
+ # 回到 desktop 目录
41
+ cd ../..
42
+
43
+ # 构建未签名的本地测试包
44
+ bun run build
45
+ bun run build-local
46
+ ```
47
+
48
+ ### 3. 生成更新文件
49
+
50
+ ```bash
51
+ cd scripts/update-test
52
+
53
+ # 从 release 目录自动检测并生成 (默认 stable 渠道)
54
+ ./generate-manifest.sh --from-release
55
+
56
+ # 指定版本号 (用于模拟更新)
57
+ ./generate-manifest.sh --from-release -v 0.0.1
58
+
59
+ # 指定渠道
60
+ ./generate-manifest.sh --from-release -c beta -v 2.1.0-beta.1
61
+ ```
62
+
63
+ ### 4. 启动本地服务器
64
+
65
+ ```bash
66
+ ./start-server.sh
67
+ # 服务器默认在 http://localhost:8787 启动
68
+ ```
69
+
70
+ ### 5. 配置应用使用本地服务器
71
+
72
+ ```bash
73
+ # 复制本地测试配置到 desktop 根目录
74
+ cp dev-app-update.local.yml ../../dev-app-update.yml
75
+
76
+ # 或者直接编辑 dev-app-update.yml,确保 URL 指向正确的渠道:
77
+ # url: http://localhost:8787/stable
78
+ ```
79
+
80
+ ### 6. 运行应用测试
81
+
82
+ ```bash
83
+ cd ../..
84
+ bun run dev
85
+ ```
86
+
87
+ ### 7. 测试完成后
88
+
89
+ ```bash
90
+ cd scripts/update-test
91
+ ./stop-server.sh
92
+
93
+ # 恢复默认的 dev-app-update.yml(可选)
94
+ cd ../..
95
+ git checkout dev-app-update.yml
96
+ ```
97
+
98
+ ---
99
+
100
+ ## generate-manifest.sh 用法
101
+
102
+ ```bash
103
+ 用法: ./generate-manifest.sh [选项]
104
+
105
+ 选项:
106
+ -v, --version VERSION 指定版本号 (例如: 2.0.1)
107
+ -c, --channel CHANNEL 指定渠道 (stable|beta|nightly, 默认: stable)
108
+ -d, --dmg FILE 指定 DMG 文件名
109
+ -z, --zip FILE 指定 ZIP 文件名
110
+ -n, --notes TEXT 指定 release notes
111
+ -f, --from-release 从 release 目录自动复制文件
112
+ -h, --help 显示帮助信息
113
+
114
+ 示例:
115
+ ./generate-manifest.sh --from-release
116
+ ./generate-manifest.sh -v 2.0.1 -c stable --from-release
117
+ ./generate-manifest.sh -v 2.1.0-beta.1 -c beta --from-release
118
+ ```
119
+
120
+ ---
121
+
122
+ ## 详细说明
123
+
124
+ ### 关于 macOS 签名验证
125
+
126
+ 本地测试的包未经签名和公证,macOS 会阻止运行。解决方法:
127
+
128
+ #### 方法 1:临时禁用 Gatekeeper(推荐)
129
+
130
+ ```bash
131
+ # 禁用
132
+ sudo spctl --master-disable
133
+
134
+ # 测试完成后务必重新启用!
135
+ sudo spctl --master-enable
136
+ ```
137
+
138
+ #### 方法 2:手动移除隔离属性
139
+
140
+ ```bash
141
+ # 对下载的 DMG 或解压后的 .app 执行
142
+ xattr -cr /path/to/YourApp.app
143
+ ```
144
+
145
+ #### 方法 3:系统偏好设置
146
+
147
+ 1. 打开「系统偏好设置」→「安全性与隐私」→「通用」
148
+ 2. 点击「仍要打开」允许未签名的应用
149
+
150
+ ### 自定义 Release Notes
151
+
152
+ 编辑 `server/{channel}/latest-mac.yml` 中的 `releaseNotes` 字段:
153
+
154
+ ```yaml
155
+ releaseNotes: |
156
+ ## 🎉 v2.0.1 测试版本
157
+
158
+ ### ✨ 新功能
159
+ - 功能 A
160
+ - 功能 B
161
+
162
+ ### 🐛 修复
163
+ - 修复问题 X
164
+ ```
165
+
166
+ ### 测试不同场景
167
+
168
+ | 场景 | 操作 |
169
+ | ------------ | ----------------------------------------------------- |
170
+ | 有新版本可用 | 设置 manifest 中的 `version` 大于当前应用版本 (0.0.0) |
171
+ | 无新版本 | 设置 `version` 小于或等于当前版本 |
172
+ | 下载失败 | 删除 server/{channel}/{version}/ 中的 DMG 文件 |
173
+ | 网络错误 | 停止本地服务器 |
174
+ | 测试不同渠道 | 修改 dev-app-update.yml 中的 URL 指向不同渠道 |
175
+
176
+ ### 环境变量
177
+
178
+ 也可以通过环境变量指定更新服务器:
179
+
180
+ ```bash
181
+ UPDATE_SERVER_URL=http://localhost:8787/stable bun run dev
182
+ ```
183
+
184
+ ---
185
+
186
+ ## 故障排除
187
+
188
+ ### 1. 服务器启动失败
189
+
190
+ ```bash
191
+ # 检查端口是否被占用
192
+ lsof -i :8787
193
+
194
+ # 使用其他端口
195
+ PORT=9000 ./start-server.sh
196
+ ```
197
+
198
+ ### 2. 更新检测不到
199
+
200
+ - 确认 `dev-app-update.yml` 中的 URL 包含渠道路径 (如 `/stable`)
201
+ - 确认 manifest 中的版本号大于当前版本 (0.0.0)
202
+ - 查看日志:`tail -f ~/Library/Logs/lobehub-desktop-dev/main.log`
203
+
204
+ ### 3. 请求了错误的 yml 文件
205
+
206
+ - 如果请求的是 `stable-mac.yml` 而不是 `latest-mac.yml`,说明代码中设置了 channel
207
+ - 确保在 dev 模式下运行,代码不会设置 `autoUpdater.channel`
208
+
209
+ ### 4. 下载后无法安装
210
+
211
+ - 确认已禁用 Gatekeeper 或移除隔离属性
212
+ - 确认 DMG 文件完整
213
+
214
+ ---
215
+
216
+ ## 注意事项
217
+
218
+ ⚠️ **安全提醒**:
219
+
220
+ 1. 测试完成后务必重新启用 Gatekeeper
221
+ 2. 这些脚本仅用于本地开发测试
222
+ 3. 不要将未签名的包分发给其他用户
@@ -0,0 +1,18 @@
1
+ # 本地更新测试配置
2
+ # 将此文件复制到 apps/desktop/dev-app-update.yml 以使用本地服务器测试
3
+ #
4
+ # 使用方法:
5
+ # cp scripts/update-test/dev-app-update.local.yml dev-app-update.yml
6
+ #
7
+ # 恢复默认配置:
8
+ # git checkout dev-app-update.yml
9
+
10
+ provider: generic
11
+ # URL 格式: http://localhost:8787/{channel}
12
+ # 可选渠道: stable, beta, nightly
13
+ url: http://localhost:8787/stable
14
+ updaterCacheDirName: lobehub-desktop-local-test
15
+
16
+ # 设置 channel 为 stable 以匹配生产环境行为
17
+ # stable channel 会找 stable-mac.yml
18
+ channel: stable
@@ -0,0 +1,277 @@
1
+ #!/bin/bash
2
+
3
+ # ============================================
4
+ # 生成更新 manifest 文件 ({channel}-mac.yml)
5
+ #
6
+ # 目录结构:
7
+ # server/
8
+ # {channel}/
9
+ # {channel}-mac.yml (e.g., stable-mac.yml)
10
+ # {version}/
11
+ # xxx.dmg
12
+ # xxx.zip
13
+ # ============================================
14
+
15
+ set -e
16
+
17
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
18
+ SERVER_DIR="$SCRIPT_DIR/server"
19
+ DESKTOP_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
20
+ RELEASE_DIR="$DESKTOP_DIR/release"
21
+
22
+ # 默认值
23
+ VERSION=""
24
+ CHANNEL="stable"
25
+ DMG_FILE=""
26
+ ZIP_FILE=""
27
+ RELEASE_NOTES=""
28
+ FROM_RELEASE=false
29
+
30
+ # 帮助信息
31
+ show_help() {
32
+ echo "用法: $0 [选项]"
33
+ echo ""
34
+ echo "选项:"
35
+ echo " -v, --version VERSION 指定版本号 (例如: 2.0.1)"
36
+ echo " -c, --channel CHANNEL 指定渠道 (stable|beta|nightly, 默认: stable)"
37
+ echo " -d, --dmg FILE 指定 DMG 文件名"
38
+ echo " -z, --zip FILE 指定 ZIP 文件名"
39
+ echo " -n, --notes TEXT 指定 release notes"
40
+ echo " -f, --from-release 从 release 目录自动复制文件"
41
+ echo " -h, --help 显示帮助信息"
42
+ echo ""
43
+ echo "示例:"
44
+ echo " $0 --from-release"
45
+ echo " $0 -v 2.0.1 -c stable -d LobeHub-2.0.1-arm64.dmg"
46
+ echo " $0 -v 2.1.0-beta.1 -c beta --from-release"
47
+ echo ""
48
+ echo "生成的目录结构:"
49
+ echo " server/"
50
+ echo " {channel}/"
51
+ echo " {channel}-mac.yml (e.g., stable-mac.yml)"
52
+ echo " {version}/"
53
+ echo " xxx.dmg"
54
+ echo " xxx.zip"
55
+ echo ""
56
+ }
57
+
58
+ # 计算 SHA512
59
+ calc_sha512() {
60
+ local file="$1"
61
+ if [ -f "$file" ]; then
62
+ shasum -a 512 "$file" | awk '{print $1}' | xxd -r -p | base64
63
+ else
64
+ echo "placeholder-sha512-file-not-found"
65
+ fi
66
+ }
67
+
68
+ # 获取文件大小
69
+ get_file_size() {
70
+ local file="$1"
71
+ if [ -f "$file" ]; then
72
+ stat -f%z "$file" 2>/dev/null || stat --printf="%s" "$file" 2>/dev/null || echo "0"
73
+ else
74
+ echo "0"
75
+ fi
76
+ }
77
+
78
+ # 解析参数
79
+ FROM_RELEASE=false
80
+ while [[ $# -gt 0 ]]; do
81
+ case $1 in
82
+ -v|--version)
83
+ VERSION="$2"
84
+ shift 2
85
+ ;;
86
+ -c|--channel)
87
+ CHANNEL="$2"
88
+ shift 2
89
+ ;;
90
+ -d|--dmg)
91
+ DMG_FILE="$2"
92
+ shift 2
93
+ ;;
94
+ -z|--zip)
95
+ ZIP_FILE="$2"
96
+ shift 2
97
+ ;;
98
+ -n|--notes)
99
+ RELEASE_NOTES="$2"
100
+ shift 2
101
+ ;;
102
+ -f|--from-release)
103
+ FROM_RELEASE=true
104
+ shift
105
+ ;;
106
+ -h|--help)
107
+ show_help
108
+ exit 0
109
+ ;;
110
+ *)
111
+ echo "未知参数: $1"
112
+ show_help
113
+ exit 1
114
+ ;;
115
+ esac
116
+ done
117
+
118
+ echo "🔧 生成更新 manifest 文件..."
119
+ echo " 渠道: $CHANNEL"
120
+ echo ""
121
+
122
+ # 渠道目录
123
+ CHANNEL_DIR="$SERVER_DIR/$CHANNEL"
124
+
125
+ # 自动从 release 目录检测和复制
126
+ if [ "$FROM_RELEASE" = true ]; then
127
+ echo "📂 从 release 目录检测文件..."
128
+
129
+ if [ ! -d "$RELEASE_DIR" ]; then
130
+ echo "❌ release 目录不存在: $RELEASE_DIR"
131
+ echo " 请先运行构建命令"
132
+ exit 1
133
+ fi
134
+
135
+ # 查找 DMG 文件
136
+ DMG_PATH=$(find "$RELEASE_DIR" -maxdepth 1 -name "*.dmg" -type f | head -1)
137
+ if [ -n "$DMG_PATH" ]; then
138
+ DMG_FILE=$(basename "$DMG_PATH")
139
+ echo " 找到 DMG: $DMG_FILE"
140
+ fi
141
+
142
+ # 查找 ZIP 文件
143
+ ZIP_PATH=$(find "$RELEASE_DIR" -maxdepth 1 -name "*-mac.zip" -type f | head -1)
144
+ if [ -n "$ZIP_PATH" ]; then
145
+ ZIP_FILE=$(basename "$ZIP_PATH")
146
+ echo " 找到 ZIP: $ZIP_FILE"
147
+ fi
148
+
149
+ # 从文件名提取版本号
150
+ # 文件名格式: lobehub-desktop-dev-0.0.0-arm64.dmg
151
+ # 版本号格式: x.y.z 或 x.y.z-beta.1 等
152
+ if [ -z "$VERSION" ] && [ -n "$DMG_FILE" ]; then
153
+ # 先尝试匹配带预发布标签的版本 (如 2.0.0-beta.1)
154
+ VERSION=$(echo "$DMG_FILE" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+-(alpha|beta|rc|nightly)\.[0-9]+' | head -1)
155
+ # 如果没有预发布标签,只匹配基本版本号 (如 2.0.0)
156
+ if [ -z "$VERSION" ]; then
157
+ VERSION=$(echo "$DMG_FILE" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
158
+ fi
159
+ fi
160
+ fi
161
+
162
+ # 设置默认版本号
163
+ if [ -z "$VERSION" ]; then
164
+ VERSION="0.0.1"
165
+ echo "⚠️ 未指定版本号,使用默认值: $VERSION"
166
+ fi
167
+
168
+ # 版本目录
169
+ VERSION_DIR="$CHANNEL_DIR/$VERSION"
170
+
171
+ # 创建目录结构
172
+ echo ""
173
+ echo "📁 创建目录结构..."
174
+ mkdir -p "$VERSION_DIR"
175
+ echo " $CHANNEL_DIR/"
176
+ echo " $VERSION/"
177
+
178
+ # 复制文件到版本目录
179
+ if [ "$FROM_RELEASE" = true ]; then
180
+ if [ -n "$DMG_PATH" ] && [ -f "$DMG_PATH" ]; then
181
+ echo " 复制 $DMG_FILE -> $VERSION/"
182
+ cp "$DMG_PATH" "$VERSION_DIR/"
183
+ fi
184
+
185
+ if [ -n "$ZIP_PATH" ] && [ -f "$ZIP_PATH" ]; then
186
+ echo " 复制 $ZIP_FILE -> $VERSION/"
187
+ cp "$ZIP_PATH" "$VERSION_DIR/"
188
+ fi
189
+ fi
190
+
191
+ # 设置默认 release notes
192
+ if [ -z "$RELEASE_NOTES" ]; then
193
+ RELEASE_NOTES="## 🎉 v$VERSION 本地测试版本
194
+
195
+ 这是一个用于本地测试更新功能的模拟版本。
196
+
197
+ ### ✨ 新功能
198
+ - 测试自动更新功能
199
+ - 验证更新流程
200
+
201
+ ### 🐛 修复
202
+ - 本地测试环境配置"
203
+ fi
204
+
205
+ # 生成 {channel}-mac.yml (e.g., stable-mac.yml)
206
+ MANIFEST_FILE="$CHANNEL-mac.yml"
207
+ echo ""
208
+ echo "📝 生成 $CHANNEL/$MANIFEST_FILE..."
209
+
210
+ DMG_SHA512=""
211
+ DMG_SIZE="0"
212
+ ZIP_SHA512=""
213
+ ZIP_SIZE="0"
214
+
215
+ if [ -n "$DMG_FILE" ] && [ -f "$VERSION_DIR/$DMG_FILE" ]; then
216
+ echo " 计算 DMG SHA512..."
217
+ DMG_SHA512=$(calc_sha512 "$VERSION_DIR/$DMG_FILE")
218
+ DMG_SIZE=$(get_file_size "$VERSION_DIR/$DMG_FILE")
219
+ fi
220
+
221
+ if [ -n "$ZIP_FILE" ] && [ -f "$VERSION_DIR/$ZIP_FILE" ]; then
222
+ echo " 计算 ZIP SHA512..."
223
+ ZIP_SHA512=$(calc_sha512 "$VERSION_DIR/$ZIP_FILE")
224
+ ZIP_SIZE=$(get_file_size "$VERSION_DIR/$ZIP_FILE")
225
+ fi
226
+
227
+ # 写入 manifest 文件 (放在渠道目录下)
228
+ cat > "$CHANNEL_DIR/$MANIFEST_FILE" << EOF
229
+ version: $VERSION
230
+ files:
231
+ EOF
232
+
233
+ if [ -n "$DMG_FILE" ]; then
234
+ cat >> "$CHANNEL_DIR/$MANIFEST_FILE" << EOF
235
+ - url: $VERSION/$DMG_FILE
236
+ sha512: ${DMG_SHA512:-placeholder}
237
+ size: $DMG_SIZE
238
+ EOF
239
+ fi
240
+
241
+ if [ -n "$ZIP_FILE" ]; then
242
+ cat >> "$CHANNEL_DIR/$MANIFEST_FILE" << EOF
243
+ - url: $VERSION/$ZIP_FILE
244
+ sha512: ${ZIP_SHA512:-placeholder}
245
+ size: $ZIP_SIZE
246
+ EOF
247
+ fi
248
+
249
+ cat >> "$CHANNEL_DIR/$MANIFEST_FILE" << EOF
250
+ path: $VERSION/${DMG_FILE:-LobeHub-$VERSION-arm64.dmg}
251
+ sha512: ${DMG_SHA512:-placeholder}
252
+ releaseDate: '$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")'
253
+ releaseNotes: |
254
+ $(echo "$RELEASE_NOTES" | sed 's/^/ /')
255
+ EOF
256
+
257
+ echo "✅ 已生成 $CHANNEL_DIR/$MANIFEST_FILE"
258
+
259
+ # 显示生成的文件内容
260
+ echo ""
261
+ echo "📋 文件内容:"
262
+ echo "----------------------------------------"
263
+ cat "$CHANNEL_DIR/$MANIFEST_FILE"
264
+ echo "----------------------------------------"
265
+
266
+ # 显示目录结构
267
+ echo ""
268
+ echo "📁 目录结构:"
269
+ find "$CHANNEL_DIR" -type f | sed "s|$SERVER_DIR/||" | sort
270
+
271
+ echo ""
272
+ echo "✅ 完成!"
273
+ echo ""
274
+ echo "下一步:"
275
+ echo " 1. 启动服务器: ./start-server.sh"
276
+ echo " 2. 确认 dev-app-update.yml 的 URL 为: http://localhost:8787/$CHANNEL"
277
+ echo " 3. 运行应用: cd ../.. && bun run dev"
@@ -0,0 +1,105 @@
1
+ #!/bin/bash
2
+
3
+ # ============================================
4
+ # 一键启动本地更新测试
5
+ # ============================================
6
+ #
7
+ # 此脚本会:
8
+ # 1. 设置测试环境
9
+ # 2. 从 release 目录复制文件
10
+ # 3. 生成 manifest
11
+ # 4. 启动本地服务器
12
+ # 5. 配置应用使用本地服务器
13
+ # 6. 启动应用
14
+ #
15
+
16
+ set -e
17
+
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ DESKTOP_DIR="$(dirname "$(dirname "$SCRIPT_DIR")")"
20
+
21
+ echo "============================================"
22
+ echo "🧪 本地更新测试 - 一键启动"
23
+ echo "============================================"
24
+ echo ""
25
+
26
+ # 检查 macOS Gatekeeper 状态
27
+ check_gatekeeper() {
28
+ if command -v spctl &> /dev/null; then
29
+ STATUS=$(spctl --status 2>&1 || true)
30
+ if [[ "$STATUS" == *"enabled"* ]]; then
31
+ echo "⚠️ 警告: macOS Gatekeeper 已启用"
32
+ echo ""
33
+ echo " 未签名的应用可能无法安装。你可以:"
34
+ echo " 1. 临时禁用: sudo spctl --master-disable"
35
+ echo " 2. 或者在安装后手动允许应用"
36
+ echo ""
37
+ read -p "是否继续?[y/N] " -n 1 -r
38
+ echo ""
39
+ if [[ ! $REPLY =~ ^[Yy]$ ]]; then
40
+ exit 1
41
+ fi
42
+ else
43
+ echo "✅ Gatekeeper 已禁用,可以安装未签名应用"
44
+ fi
45
+ fi
46
+ }
47
+
48
+ # 步骤 1: 设置
49
+ echo "📦 步骤 1/5: 设置测试环境..."
50
+ cd "$SCRIPT_DIR"
51
+ chmod +x *.sh
52
+ mkdir -p server
53
+
54
+ # 步骤 2: 检查 release 目录
55
+ echo ""
56
+ echo "📂 步骤 2/5: 检查构建产物..."
57
+ if [ ! -d "$DESKTOP_DIR/release" ] || [ -z "$(ls -A "$DESKTOP_DIR/release"/*.dmg 2>/dev/null)" ]; then
58
+ echo "❌ 未找到构建产物"
59
+ echo ""
60
+ echo "请先构建应用:"
61
+ echo " cd $DESKTOP_DIR"
62
+ echo " npm run build-local"
63
+ echo ""
64
+ exit 1
65
+ fi
66
+
67
+ # 步骤 3: 生成 manifest
68
+ echo ""
69
+ echo "📝 步骤 3/5: 生成 manifest 文件..."
70
+ ./generate-manifest.sh --from-release
71
+
72
+ # 步骤 4: 启动服务器
73
+ echo ""
74
+ echo "🚀 步骤 4/5: 启动本地服务器..."
75
+ ./start-server.sh
76
+
77
+ # 步骤 5: 配置并启动应用
78
+ echo ""
79
+ echo "⚙️ 步骤 5/5: 配置应用..."
80
+ cp "$SCRIPT_DIR/dev-app-update.local.yml" "$DESKTOP_DIR/dev-app-update.yml"
81
+ echo "✅ 已更新 dev-app-update.yml"
82
+
83
+ # 检查 Gatekeeper
84
+ echo ""
85
+ check_gatekeeper
86
+
87
+ echo ""
88
+ echo "============================================"
89
+ echo "✅ 准备完成!"
90
+ echo "============================================"
91
+ echo ""
92
+ echo "现在可以运行应用进行测试:"
93
+ echo ""
94
+ echo " cd $DESKTOP_DIR"
95
+ echo " npm run dev"
96
+ echo ""
97
+ echo "或者直接运行:"
98
+ read -p "是否现在启动应用?[Y/n] " -n 1 -r
99
+ echo ""
100
+ if [[ ! $REPLY =~ ^[Nn]$ ]]; then
101
+ echo ""
102
+ echo "🚀 启动应用..."
103
+ cd "$DESKTOP_DIR"
104
+ npm run dev
105
+ fi