🐛 fix(desktop): macos26 small icon (#9421)

* 🐛 fix(desktop): macos26 icon small

* Revert "🐛 fix(desktop): macos26 icon small"

This reverts commit 4a4b7b230c.

*  feat(desktop): support Liquid Glass icons for macOS 26

- Add pre-generated Assets.car files for all build variants
- Configure afterPack hook to copy Assets.car during build
- Maintain backward compatibility with .icns fallback for older macOS

Reference: https://github.com/electron-userland/electron-builder/issues/9254

* docs: optimize comments

* fix: update deprecated macos-13 to macos-15-intel

* docs: optimize ai rules
This commit is contained in:
YuTengjing
2025-10-08 23:30:35 +08:00
committed by GitHub
parent d8bfec02ad
commit ca033420b9
11 changed files with 79 additions and 59 deletions

View File

@@ -6,18 +6,16 @@ alwaysApply: true
You are developing an open-source, modern-design AI chat framework: lobehub(previous lobe-chat).
support platforms:
Supported platforms:
- web desktop/mobile
- desktop(electron)
- mobile app(react native). coming soon
- mobile app(react native), coming soon
logo emoji: 🤯
## Project Technologies Stack
read [package.json](mdc:package.json) to know all npm packages you can use.
- Next.js 15
- react 19
- TypeScript
@@ -33,6 +31,6 @@ read [package.json](mdc:package.json) to know all npm packages you can use.
- dayjs for time library
- lodash-es for utility library
- TRPC for type safe backend
- PGLite for client DB and PostgreSQL for backend DB
- PGLite for client DB and Neon PostgreSQL for backend DB
- Drizzle ORM
- Vitest for testing

View File

@@ -5,11 +5,11 @@ alwaysApply: false
# LobeChat Project Structure
note: some not very important files are not shown for simplicity.
## Complete Project Structure
this project use common monorepo structure. The workspace packages name use `@lobechat/` namespace.
This project uses common monorepo structure. The workspace packages name use `@lobechat/` namespace.
**note**: some not very important files are not shown for simplicity.
```plaintext
lobe-chat/
@@ -28,10 +28,12 @@ lobe-chat/
│ │ │ ├── schemas/
│ │ │ └── repositories/
│ ├── model-bank/
│ │ └── src/
│ │ └── aiModels/
│ ├── model-runtime/
│ │ └── src/
│ │ ├── openai/
│ │ └── anthropic/
│ │ ├── core/
│ │ └── providers/
│ ├── types/
│ │ └── src/
│ │ ├── message/
@@ -96,14 +98,14 @@ lobe-chat/
- UI Components: `src/components`, `src/features`
- Global providers: `src/layout`
- Zustand stores: `src/store`
- Client Services: `src/services/`
- Client Services: `src/services/` cross-platform services
- clientDB: `src/services/<domain>/client.ts`
- serverDB: `src/services/<domain>/server.ts`
- API Routers:
- `src/app/(backend)/webapi` (REST)
- `src/server/routers/{edge|lambda|async|desktop|tools}` (tRPC)
- Server:
- Services(can access serverDB): `src/server/services`
- Services(can access serverDB): `src/server/services` server-used-only services
- Modules(can't access db): `src/server/modules` (Server only Third-party Service Module)
- Database:
- Schema (Drizzle): `packages/database/src/schemas`
@@ -113,8 +115,8 @@ lobe-chat/
## Data Flow Architecture
- **Browser/PWA**: React UI → Client Service → Direct Model Access → PGLite (Web WASM)
- **Server**: React UI → Client Service → tRPC Lambda → Server Services → PostgreSQL (Remote)
- **Web with ClientDB**: React UI → Client Service → Direct Model Access → PGLite (Web WASM)
- **Web with ServerDB**: React UI → Client Service → tRPC Lambda → Server Services → PostgreSQL (Remote)
- **Desktop**:
- Cloud sync disabled: Electron UI → Client Service → tRPC Lambda → Local Server Services → PGLite (Node WASM)
- Cloud sync enabled: Electron UI → Client Service → tRPC Lambda → Cloud Server Services → PostgreSQL (Remote)

View File

@@ -29,16 +29,11 @@ alwaysApply: false
## Code Structure and Readability
- Refactor repeated logic into reusable functions.
- Prefer object destructuring when accessing and using properties.
- Use consistent, descriptive naming; avoid obscure abbreviations.
- Use semantically meaningful variable, function, and class names.
- Replace magic numbers or strings with well-named constants.
- Keep meaningful code comments; do not remove them when applying edits. Update comments when behavior changes.
- Ensure JSDoc comments accurately reflect the implementation.
- Look for opportunities to simplify or modernize code with the latest JavaScript/TypeScript features where it improves clarity.
- Defer formatting to tooling; ignore purely formatting-only issues and autofixable lint problems.
- Respect project Prettier settings.
## UI and Theming
@@ -50,15 +45,14 @@ alwaysApply: false
## Performance
- Prefer `for…of` loops to index-based `for` loops when feasible.
- Decide whether callbacks should be debounced or throttled based on UX and performance needs.
- Reuse existing npm packages rather than reinventing the wheel (e.g., `lodash-es/omit`).
- Reuse existing utils inside `packages/utils` or installed npm packages rather than reinventing the wheel.
- Query only the required columns from a database rather than selecting entire rows.
## Time and Consistency
- Instead of calling `Date.now()` multiple times, assign it to a constant once and reuse it to ensure consistency and improve readability.
## Some logging rules
## Logging
- Never log user private information like api key, etc
- Don't use `import { log } from 'debug'` to log messages, because it will directly log the message to the console.

View File

@@ -95,7 +95,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, macos-13, windows-2025, ubuntu-latest]
os: [macos-latest, macos-15-intel, windows-2025, ubuntu-latest]
steps:
- uses: actions/checkout@v5
with:
@@ -129,11 +129,11 @@ jobs:
run: npm run desktop:build
env:
# 设置更新通道PR构建为nightly否则为stable
UPDATE_CHANNEL: 'nightly'
UPDATE_CHANNEL: "nightly"
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
# 默认添加一个加密 SECRET
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
# macOS 签名和公证配置
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
@@ -152,10 +152,10 @@ jobs:
run: npm run desktop:build
env:
# 设置更新通道PR构建为nightly否则为stable
UPDATE_CHANNEL: 'nightly'
UPDATE_CHANNEL: "nightly"
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}
# 将 TEMP 和 TMP 目录设置到 C 盘
@@ -168,10 +168,10 @@ jobs:
run: npm run desktop:build
env:
# 设置更新通道PR构建为nightly否则为stable
UPDATE_CHANNEL: 'nightly'
UPDATE_CHANNEL: "nightly"
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_NIGHTLY_DESKTOP_BASE_URL }}

View File

@@ -82,7 +82,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, macos-13, windows-2025, ubuntu-latest]
os: [macos-latest, macos-15-intel, windows-2025, ubuntu-latest]
steps:
- uses: actions/checkout@v5
with:
@@ -116,9 +116,9 @@ jobs:
run: npm run desktop:build
env:
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
# 默认添加一个加密 SECRET
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
# macOS 签名和公证配置
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
@@ -137,8 +137,8 @@ jobs:
run: npm run desktop:build
env:
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_BETA_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_BETA_DESKTOP_BASE_URL }}
@@ -152,8 +152,8 @@ jobs:
run: npm run desktop:build
env:
APP_URL: http://localhost:3015
DATABASE_URL: 'postgresql://postgres@localhost:5432/postgres'
KEY_VAULTS_SECRET: 'oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE='
DATABASE_URL: "postgresql://postgres@localhost:5432/postgres"
KEY_VAULTS_SECRET: "oLXWIiR/AKF+rWaqy9lHkrYgzpATbW3CtJp3UfkVgpE="
NEXT_PUBLIC_DESKTOP_PROJECT_ID: ${{ secrets.UMAMI_BETA_DESKTOP_PROJECT_ID }}
NEXT_PUBLIC_DESKTOP_UMAMI_BASE_URL: ${{ secrets.UMAMI_BETA_DESKTOP_BASE_URL }}

View File

@@ -31,28 +31,18 @@ This repository adopts a monorepo structure.
see @.cursor/rules/typescript.mdc
### Modify Code Rules
- **Code Language**:
- For files with existing Chinese comments: Continue using Chinese to maintain consistency
- For new files or files without Chinese comments: MUST use American English.
- eg: new react tsx file and new test file
- Conservative for existing code, modern approaches for new features
### Testing
Testing work follows the Rule-Aware Task Execution system above.
- **Required Rule**: `testing-guide/testing-guide.mdc`
- **Required Rule**: read `@.cursor/rules/testing-guide/testing-guide.mdc` before writing tests
- **Command**:
- web: `bunx vitest run --silent='passed-only' '[file-path-pattern]'`
- packages(eg: database): `cd packages/database && bunx vitest run --silent='passed-only' '[file-path-pattern]'`
**Important**:
- wrapped the file path in single quotes to avoid shell expansion
- wrap the file path in single quotes to avoid shell expansion
- Never run `bun run test` etc to run tests, this will run all tests and cost about 10mins
- If try to fix the same test twice, but still failed, stop and ask for help.
- If trying to fix the same test twice, but still failed, stop and ask for help.
### Typecheck
@@ -61,15 +51,9 @@ Testing work follows the Rule-Aware Task Execution system above.
### i18n
- **Keys**: Add to `src/locales/default/namespace.ts`
- **Dev**: Translate `locales/zh-CN/namespace.json` locale file only for preview
- **Dev**: Translate `locales/zh-CN/namespace.json` and `locales/en-US/namespace.json` locales file only for dev preview
- DON'T run `pnpm i18n`, let CI auto handle it
## Rules Index
Some useful rules of this project. Read them when needed.
**IMPORTANT**: All rule files referenced in this document are located in the `.cursor/rules/` directory. Throughout this document, rule files are referenced by their filename only for brevity.
### 📋 Complete Rule Files
Some useful project rules are listed in @.cursor/rules/rules-index.mdc

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,7 @@
const dotenv = require('dotenv');
const fs = require('node:fs/promises');
const os = require('node:os');
const path = require('node:path');
dotenv.config();
@@ -32,11 +34,50 @@ const getProtocolScheme = () => {
const protocolScheme = getProtocolScheme();
// Determine icon file based on version type
const getIconFileName = () => {
if (isNightly) return 'Icon-nightly';
if (isBeta) return 'Icon-beta';
return 'Icon';
};
/**
* @type {import('electron-builder').Configuration}
* @see https://www.electron.build/configuration
*/
const config = {
/**
* AfterPack hook to copy pre-generated Liquid Glass Assets.car for macOS 26+
* @see https://github.com/electron-userland/electron-builder/issues/9254
* @see https://github.com/MultiboxLabs/flow-browser/pull/159
* @see https://github.com/electron/packager/pull/1806
*/
afterPack: async (context) => {
// Only process macOS builds
if (context.electronPlatformName !== 'darwin') {
return;
}
const iconFileName = getIconFileName();
const assetsCarSource = path.join(__dirname, 'build', `${iconFileName}.Assets.car`);
const resourcesPath = path.join(
context.appOutDir,
`${context.packager.appInfo.productFilename}.app`,
'Contents',
'Resources',
);
const assetsCarDest = path.join(resourcesPath, 'Assets.car');
try {
await fs.access(assetsCarSource);
await fs.copyFile(assetsCarSource, assetsCarDest);
console.log(`✅ Copied Liquid Glass icon: ${iconFileName}.Assets.car`);
} catch {
// Non-critical: Assets.car not found or copy failed
// App will use fallback .icns icon on all macOS versions
console.log(`⏭️ Skipping Assets.car (not found or copy failed)`);
}
},
appId: isNightly
? 'com.lobehub.lobehub-desktop-nightly'
: isBeta
@@ -81,6 +122,7 @@ const config = {
compression: 'maximum',
entitlementsInherit: 'build/entitlements.mac.plist',
extendInfo: {
CFBundleIconName: 'AppIcon',
CFBundleURLTypes: [
{
CFBundleURLName: 'LobeHub Protocol',