Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .cursor/rules/project-introduce.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
20 changes: 11 additions & 9 deletions .cursor/rules/project-structure.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand All @@ -28,10 +28,12 @@ lobe-chat/
│ │ │ ├── schemas/
│ │ │ └── repositories/
│ ├── model-bank/
│ │ └── src/
│ │ └── aiModels/
│ ├── model-runtime/
│ │ └── src/
│ │ ├── openai/
│ │ └── anthropic/
│ │ ├── core/
│ │ └── providers/
│ ├── types/
│ │ └── src/
│ │ ├── message/
Expand Down Expand Up @@ -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`
Expand All @@ -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)
10 changes: 2 additions & 8 deletions .cursor/rules/typescript.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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.
20 changes: 10 additions & 10 deletions .github/workflows/desktop-pr-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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 }}
Expand All @@ -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 盘
Expand All @@ -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 }}

Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/release-desktop-beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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 }}
Expand All @@ -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 }}

Expand All @@ -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 }}

Expand Down
24 changes: 4 additions & 20 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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 added apps/desktop/build/Icon-beta.Assets.car
Binary file not shown.
Binary file added apps/desktop/build/Icon-dev.Assets.car
Binary file not shown.
Binary file added apps/desktop/build/Icon-nightly.Assets.car
Binary file not shown.
Binary file added apps/desktop/build/Icon.Assets.car
Binary file not shown.
42 changes: 42 additions & 0 deletions apps/desktop/electron-builder.js
Original file line number Diff line number Diff line change
@@ -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();

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -81,6 +122,7 @@ const config = {
compression: 'maximum',
entitlementsInherit: 'build/entitlements.mac.plist',
extendInfo: {
CFBundleIconName: 'AppIcon',
CFBundleURLTypes: [
{
CFBundleURLName: 'LobeHub Protocol',
Expand Down
Loading