@lobehub/lobehub 2.0.0-next.179 → 2.0.0-next.180

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.
@@ -0,0 +1,341 @@
1
+ name: Desktop Manual Build
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ channel:
7
+ description: 'Release channel for desktop build (affects version suffix and workflow:set-desktop-version)'
8
+ required: true
9
+ default: nightly
10
+ type: choice
11
+ options:
12
+ - nightly
13
+ - beta
14
+ - stable
15
+ build_macos:
16
+ description: 'Build macOS artifacts'
17
+ required: true
18
+ default: true
19
+ type: boolean
20
+ build_windows:
21
+ description: 'Build Windows artifacts'
22
+ required: true
23
+ default: true
24
+ type: boolean
25
+ build_linux:
26
+ description: 'Build Linux artifacts'
27
+ required: true
28
+ default: true
29
+ type: boolean
30
+ version:
31
+ description: 'Override desktop version (e.g. 1.2.3). Leave empty to auto-generate.'
32
+ required: false
33
+ default: ''
34
+
35
+ concurrency:
36
+ group: manual-${{ github.ref }}-${{ github.workflow }}
37
+ cancel-in-progress: true
38
+
39
+ permissions:
40
+ contents: read
41
+
42
+ env:
43
+ NODE_VERSION: 24.11.1
44
+ BUN_VERSION: 1.2.23
45
+
46
+ jobs:
47
+ test:
48
+ name: Code quality check
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - name: Checkout base
52
+ uses: actions/checkout@v5
53
+ with:
54
+ fetch-depth: 0
55
+
56
+ - name: Setup Node & Bun
57
+ uses: ./.github/actions/setup-node-bun
58
+ with:
59
+ node-version: ${{ env.NODE_VERSION }}
60
+ bun-version: ${{ env.BUN_VERSION }}
61
+ package-manager-cache: 'false'
62
+
63
+ - name: Install deps
64
+ run: bun i
65
+ env:
66
+ NODE_OPTIONS: --max-old-space-size=6144
67
+
68
+ - name: Lint
69
+ run: bun run lint
70
+ env:
71
+ NODE_OPTIONS: --max-old-space-size=6144
72
+
73
+ version:
74
+ name: Determine version
75
+ runs-on: ubuntu-latest
76
+ outputs:
77
+ version: ${{ steps.set_version.outputs.version }}
78
+ steps:
79
+ - uses: actions/checkout@v5
80
+ with:
81
+ fetch-depth: 0
82
+
83
+ - name: Setup Node.js
84
+ uses: actions/setup-node@v6
85
+ with:
86
+ node-version: ${{ env.NODE_VERSION }}
87
+ package-manager-cache: false
88
+
89
+ - name: Set version
90
+ id: set_version
91
+ env:
92
+ INPUT_VERSION: ${{ inputs.version }}
93
+ CHANNEL: ${{ inputs.channel }}
94
+ run: |
95
+ base_version=$(node -p "require('./apps/desktop/package.json').version")
96
+
97
+ if [ -n "$INPUT_VERSION" ]; then
98
+ version="$INPUT_VERSION"
99
+ echo "📦 Using provided version: ${version} (base: ${base_version})"
100
+ else
101
+ ci_build_number="${{ github.run_number }}"
102
+ version="0.0.0-${CHANNEL}.manual.${ci_build_number}"
103
+ echo "📦 Generated version: ${version} (base: ${base_version})"
104
+ fi
105
+
106
+ echo "version=${version}" >> $GITHUB_OUTPUT
107
+
108
+ - name: Version Summary
109
+ run: |
110
+ echo "🚦 Release Version: ${{ steps.set_version.outputs.version }}"
111
+
112
+ build-macos:
113
+ needs: [version, test]
114
+ name: Build Desktop App (macOS)
115
+ if: inputs.build_macos
116
+ runs-on: ${{ matrix.os }}
117
+ strategy:
118
+ matrix:
119
+ os: [macos-latest, macos-15-intel]
120
+ steps:
121
+ - uses: actions/checkout@v5
122
+ with:
123
+ fetch-depth: 0
124
+
125
+ - name: Setup Node & pnpm
126
+ uses: ./.github/actions/setup-node-pnpm
127
+ with:
128
+ node-version: ${{ env.NODE_VERSION }}
129
+ package-manager-cache: 'false'
130
+
131
+ # node-linker=hoisted 模式将可以确保 asar 压缩可用
132
+ - name: Install dependencies
133
+ run: pnpm install --node-linker=hoisted
134
+
135
+ - name: Install deps on Desktop
136
+ run: npm run install-isolated --prefix=./apps/desktop
137
+
138
+ - name: Set package version
139
+ run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
140
+
141
+ - name: Build artifact on macOS
142
+ run: npm run desktop:build
143
+ env:
144
+ UPDATE_CHANNEL: ${{ inputs.channel }}
145
+ APP_URL: http://localhost:3015
146
+ DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
147
+ KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
148
+ CSC_LINK: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
149
+ CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
150
+ NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
151
+ NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
152
+ CSC_FOR_PULL_REQUEST: true
153
+ APPLE_ID: ${{ secrets.APPLE_ID }}
154
+ APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
155
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
156
+
157
+ - name: Rename macOS latest-mac.yml for multi-architecture support
158
+ if: runner.os == 'macOS'
159
+ run: |
160
+ cd apps/desktop/release
161
+ if [ -f "latest-mac.yml" ]; then
162
+ SYSTEM_ARCH=$(uname -m)
163
+ if [[ "$SYSTEM_ARCH" == "arm64" ]]; then
164
+ ARCH_SUFFIX="arm64"
165
+ else
166
+ ARCH_SUFFIX="x64"
167
+ fi
168
+
169
+ mv latest-mac.yml "latest-mac-${ARCH_SUFFIX}.yml"
170
+ echo "✅ Renamed latest-mac.yml to latest-mac-${ARCH_SUFFIX}.yml (detected: $SYSTEM_ARCH)"
171
+ ls -la latest-mac-*.yml
172
+ else
173
+ echo "⚠️ latest-mac.yml not found, skipping rename"
174
+ ls -la latest*.yml || echo "No latest*.yml files found"
175
+ fi
176
+
177
+ - name: Upload artifact
178
+ uses: actions/upload-artifact@v5
179
+ with:
180
+ name: release-${{ matrix.os }}
181
+ path: |
182
+ apps/desktop/release/latest*
183
+ apps/desktop/release/*.dmg*
184
+ apps/desktop/release/*.zip*
185
+ apps/desktop/release/*.exe*
186
+ apps/desktop/release/*.AppImage
187
+ apps/desktop/release/*.deb*
188
+ apps/desktop/release/*.snap*
189
+ apps/desktop/release/*.rpm*
190
+ apps/desktop/release/*.tar.gz*
191
+ retention-days: 5
192
+
193
+ build-windows:
194
+ needs: [version, test]
195
+ name: Build Desktop App (Windows)
196
+ if: inputs.build_windows
197
+ runs-on: windows-2025
198
+ steps:
199
+ - uses: actions/checkout@v5
200
+ with:
201
+ fetch-depth: 0
202
+
203
+ - name: Setup Node & pnpm
204
+ uses: ./.github/actions/setup-node-pnpm
205
+ with:
206
+ node-version: ${{ env.NODE_VERSION }}
207
+ package-manager-cache: 'false'
208
+
209
+ - name: Install dependencies
210
+ run: pnpm install --node-linker=hoisted
211
+
212
+ - name: Install deps on Desktop
213
+ run: npm run install-isolated --prefix=./apps/desktop
214
+
215
+ - name: Set package version
216
+ run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
217
+
218
+ - name: Build artifact on Windows
219
+ run: npm run desktop:build
220
+ env:
221
+ UPDATE_CHANNEL: ${{ inputs.channel }}
222
+ APP_URL: http://localhost:3015
223
+ DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
224
+ KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
225
+ NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
226
+ NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
227
+ TEMP: C:\temp
228
+ TMP: C:\temp
229
+
230
+ - name: Upload artifact
231
+ uses: actions/upload-artifact@v5
232
+ with:
233
+ name: release-windows-2025
234
+ path: |
235
+ apps/desktop/release/latest*
236
+ apps/desktop/release/*.dmg*
237
+ apps/desktop/release/*.zip*
238
+ apps/desktop/release/*.exe*
239
+ apps/desktop/release/*.AppImage
240
+ apps/desktop/release/*.deb*
241
+ apps/desktop/release/*.snap*
242
+ apps/desktop/release/*.rpm*
243
+ apps/desktop/release/*.tar.gz*
244
+ retention-days: 5
245
+
246
+ build-linux:
247
+ needs: [version, test]
248
+ name: Build Desktop App (Linux)
249
+ if: inputs.build_linux
250
+ runs-on: ubuntu-latest
251
+ steps:
252
+ - uses: actions/checkout@v5
253
+ with:
254
+ fetch-depth: 0
255
+
256
+ - name: Setup Node & pnpm
257
+ uses: ./.github/actions/setup-node-pnpm
258
+ with:
259
+ node-version: ${{ env.NODE_VERSION }}
260
+ package-manager-cache: 'false'
261
+
262
+ - name: Install dependencies
263
+ run: pnpm install --node-linker=hoisted
264
+
265
+ - name: Install deps on Desktop
266
+ run: npm run install-isolated --prefix=./apps/desktop
267
+
268
+ - name: Set package version
269
+ run: npm run workflow:set-desktop-version ${{ needs.version.outputs.version }} ${{ inputs.channel }}
270
+
271
+ - name: Build artifact on Linux
272
+ run: npm run desktop:build
273
+ env:
274
+ UPDATE_CHANNEL: ${{ inputs.channel }}
275
+ APP_URL: http://localhost:3015
276
+ DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
277
+ KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
278
+ NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_PROJECT_ID || secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
279
+ NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ inputs.channel == 'beta' && secrets.UMAMI_BETA_DESKTOP_BASE_URL || secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
280
+
281
+ - name: Upload artifact
282
+ uses: actions/upload-artifact@v5
283
+ with:
284
+ name: release-ubuntu-latest
285
+ path: |
286
+ apps/desktop/release/latest*
287
+ apps/desktop/release/*.dmg*
288
+ apps/desktop/release/*.zip*
289
+ apps/desktop/release/*.exe*
290
+ apps/desktop/release/*.AppImage
291
+ apps/desktop/release/*.deb*
292
+ apps/desktop/release/*.snap*
293
+ apps/desktop/release/*.rpm*
294
+ apps/desktop/release/*.tar.gz*
295
+ retention-days: 5
296
+
297
+ merge-mac-files:
298
+ needs: [build-macos, version]
299
+ name: Merge macOS Release Files
300
+ runs-on: ubuntu-latest
301
+ permissions:
302
+ contents: read
303
+ if: inputs.build_macos
304
+ steps:
305
+ - name: Checkout repository
306
+ uses: actions/checkout@v5
307
+
308
+ - name: Setup Node & Bun
309
+ uses: ./.github/actions/setup-node-bun
310
+ with:
311
+ node-version: ${{ env.NODE_VERSION }}
312
+ bun-version: ${{ env.BUN_VERSION }}
313
+ package-manager-cache: 'false'
314
+
315
+ - name: Download artifacts
316
+ uses: actions/download-artifact@v6
317
+ with:
318
+ path: release
319
+ pattern: release-*
320
+ merge-multiple: true
321
+
322
+ - name: List downloaded artifacts
323
+ run: ls -R release
324
+
325
+ - name: Install yaml only for merge step
326
+ run: |
327
+ cd scripts/electronWorkflow
328
+ if [ ! -f package.json ]; then
329
+ echo '{"name":"merge-mac-release","private":true}' > package.json
330
+ fi
331
+ bun add --no-save yaml@2.8.1
332
+
333
+ - name: Merge latest-mac.yml files
334
+ run: bun run scripts/electronWorkflow/mergeMacReleaseFiles.js
335
+
336
+ - name: Upload artifacts with merged macOS files
337
+ uses: actions/upload-artifact@v5
338
+ with:
339
+ name: merged-release-manual
340
+ path: release/
341
+ retention-days: 1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.180](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.179...v2.0.0-next.180)
6
+
7
+ <sup>Released on **2025-12-26**</sup>
8
+
9
+ <br/>
10
+
11
+ <details>
12
+ <summary><kbd>Improvements and Fixes</kbd></summary>
13
+
14
+ </details>
15
+
16
+ <div align="right">
17
+
18
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
19
+
20
+ </div>
21
+
5
22
  ## [Version 2.0.0-next.179](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.178...v2.0.0-next.179)
6
23
 
7
24
  <sup>Released on **2025-12-25**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,9 @@
1
1
  [
2
+ {
3
+ "children": {},
4
+ "date": "2025-12-26",
5
+ "version": "2.0.0-next.180"
6
+ },
2
7
  {
3
8
  "children": {},
4
9
  "date": "2025-12-25",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.179",
3
+ "version": "2.0.0-next.180",
4
4
  "description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -17,16 +17,6 @@
17
17
  "@lobechat/const": "workspace:*",
18
18
  "@lobechat/types": "workspace:*",
19
19
  "@lobechat/utils": "workspace:*",
20
- "@lobehub/charts": "^2.1.2",
21
- "@lobehub/chat-plugin-sdk": "^1.32.4",
22
- "@neondatabase/serverless": "^1.0.2",
23
- "@trpc/server": "^11.7.1",
24
- "debug": "^4.4.3",
25
- "drizzle-zod": "^0.5.1",
26
- "lodash-es": "^4.17.21",
27
- "model-bank": "workspace:*",
28
- "next-auth": "5.0.0-beta.30",
29
- "p-map": "^7.0.4",
30
20
  "random-words": "^2.0.1",
31
21
  "ts-md5": "^2.0.1",
32
22
  "type-fest": "^5.2.0",
@@ -29,7 +29,6 @@
29
29
  "mime": "^4.1.0",
30
30
  "model-bank": "workspace:*",
31
31
  "nanoid": "^5.1.6",
32
- "next": "^16.0.1",
33
32
  "numeral": "^2.0.6",
34
33
  "pure-rand": "^7.0.1",
35
34
  "remark": "^15.0.1",
@@ -0,0 +1,100 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+
3
+ import { isCommandPressed } from './keyboard';
4
+ import * as platform from './platform';
5
+
6
+ describe('keyboard', () => {
7
+ describe('isCommandPressed', () => {
8
+ beforeEach(() => {
9
+ vi.restoreAllMocks();
10
+ });
11
+
12
+ it('should return true when metaKey is pressed on macOS', () => {
13
+ vi.spyOn(platform, 'isMacOS').mockReturnValue(true);
14
+
15
+ const event = {
16
+ metaKey: true,
17
+ ctrlKey: false,
18
+ } as KeyboardEvent;
19
+
20
+ expect(isCommandPressed(event)).toBe(true);
21
+ });
22
+
23
+ it('should return false when metaKey is not pressed on macOS', () => {
24
+ vi.spyOn(platform, 'isMacOS').mockReturnValue(true);
25
+
26
+ const event = {
27
+ metaKey: false,
28
+ ctrlKey: false,
29
+ } as KeyboardEvent;
30
+
31
+ expect(isCommandPressed(event)).toBe(false);
32
+ });
33
+
34
+ it('should return true when ctrlKey is pressed on Windows/Linux', () => {
35
+ vi.spyOn(platform, 'isMacOS').mockReturnValue(false);
36
+
37
+ const event = {
38
+ metaKey: false,
39
+ ctrlKey: true,
40
+ } as KeyboardEvent;
41
+
42
+ expect(isCommandPressed(event)).toBe(true);
43
+ });
44
+
45
+ it('should return false when ctrlKey is not pressed on Windows/Linux', () => {
46
+ vi.spyOn(platform, 'isMacOS').mockReturnValue(false);
47
+
48
+ const event = {
49
+ metaKey: false,
50
+ ctrlKey: false,
51
+ } as KeyboardEvent;
52
+
53
+ expect(isCommandPressed(event)).toBe(false);
54
+ });
55
+
56
+ it('should ignore ctrlKey on macOS and only check metaKey', () => {
57
+ vi.spyOn(platform, 'isMacOS').mockReturnValue(true);
58
+
59
+ const event = {
60
+ metaKey: false,
61
+ ctrlKey: true, // ctrlKey should be ignored on macOS
62
+ } as KeyboardEvent;
63
+
64
+ expect(isCommandPressed(event)).toBe(false);
65
+ });
66
+
67
+ it('should ignore metaKey on Windows/Linux and only check ctrlKey', () => {
68
+ vi.spyOn(platform, 'isMacOS').mockReturnValue(false);
69
+
70
+ const event = {
71
+ metaKey: true, // metaKey should be ignored on Windows/Linux
72
+ ctrlKey: false,
73
+ } as KeyboardEvent;
74
+
75
+ expect(isCommandPressed(event)).toBe(false);
76
+ });
77
+
78
+ it('should handle both keys pressed on macOS correctly', () => {
79
+ vi.spyOn(platform, 'isMacOS').mockReturnValue(true);
80
+
81
+ const event = {
82
+ metaKey: true,
83
+ ctrlKey: true, // both pressed, but only metaKey matters on macOS
84
+ } as KeyboardEvent;
85
+
86
+ expect(isCommandPressed(event)).toBe(true);
87
+ });
88
+
89
+ it('should handle both keys pressed on Windows/Linux correctly', () => {
90
+ vi.spyOn(platform, 'isMacOS').mockReturnValue(false);
91
+
92
+ const event = {
93
+ metaKey: true, // both pressed, but only ctrlKey matters on Windows/Linux
94
+ ctrlKey: true,
95
+ } as KeyboardEvent;
96
+
97
+ expect(isCommandPressed(event)).toBe(true);
98
+ });
99
+ });
100
+ });